跳至内容
liuzhen932 的小窝
返回

为博客集成 Twtxt:快速接入去中心化社交,兼容 Yarn 社交平台

0x00 前情提要

什么是 Twtxt?

Twtxt 是一种极简的纯文本微型博客服务,灵感来源于 Twitter,但完全由用户自主掌控数据,没有中心化的服务器或公司控制。它的设计哲学是简单、隐私优先和去中心化,适合喜欢技术自主性和对隐私敏感的用户。

Twtxt 通过简单的文本文件(称为「Feeds」)运行,每个文件包含一个用户的状态更新。这些文件通常由 Web 服务器提供,并通过 URL 访问。

尽管该项目标榜为网络服务,但实际使用时需要用户自行将程序部署到服务器环境中。名为 twtxt 的工具主要具备两大功能:其一,能够将用户的推文内容写入指定的 twtxt.txt 文本文件;其二,支持从互联网上的其他 twtxt.txt 文件(即其他用户的动态源)进行内容获取与阅读操作。

Twtxt 出现多久了?

Twtxt 最先由 @buckket 于 ~2016 年设计和开发,目前主流版本是 Twtxt v2,由社区驱动开发拓展。

Twtxt 的文件格式是怎么样的?

一个 Twtxt 源包含每行一个状态更新。每行以一个 RFC3339 日期时间字符串开头,后跟一个制表符(\t)将其与实际文本分开(建议将新的状态追加到文件末尾)。

该文件必须使用 UTF-8 编码,并使用 LF(\n)作为行分隔符。一个源通常以元数据开头,可能包括用户的昵称、头像和可选的描述。建议用空行将元数据与状态分开。

给个示例看看?

你可以在我 博客的 Twtxt Feed 找到一个合法的示例,也欢迎在你的 Twtxt 客户端订阅我的博客~

# nick        = example
# url         = https://example.com/twtxt.txt
# avatar      = https://example.com/avatar.png
# description = An example feed

2024-09-29T13:30:00Z   Hello World!
2024-09-29T13:40:00Z   (#ohmmloa) Is anyone alive? 🤔

0x01 为博客添加一个 Twtxt

请注意:本部分内容因框架升级已过时,仅供参考,请以最新信息为准。

我的博客使用 Astro 构建,所以我需要在 /src/pages 下创建一个 twtxt.txt.ts 文件,在里面使用标准 API 构建我们的 Twtxt:

import { getCollection } from "astro:content";
import getSortedPosts from "@utils/getSortedPosts";
import { SITE } from "@config";

export async function GET() {
  const posts = await getCollection("blog");
  const sortedPosts = getSortedPosts(posts);

  const twtxt = sortedPosts
    .map(
      ({ data, slug }) =>
        `${new Date(data.modDatetime ?? data.pubDatetime).toISOString()}\t${data.title} ${SITE.website}post/${slug}`
    )
    .join("\n");

  return new Response(twtxt, {
    headers: {
      "Content-Type": "text/plain",
    },
  });
}

这是我的第一版代码,这会输出一个基本可用的框架(不过还没有任何的元数据,我们接下来会添加),接下来讲讲怎么在 Yarn 里订阅。

0x02 在 Yarn.social 里订阅博客

刷新博客缓存后,我们便可以在 Yarn.social 实例里订阅了,这里以 XMSL TwT 为例:

XMSL TwT

导航到 /feeds,在 Follow 框上输入我们的 Twtxt 地址:

输入地址,然后 Follow

随后回到主页,我们便可以查看到来自博客的文章了:

可以在时间线查看来自博客的文章

很棒,我们来为文章加点元数据吧:

0x03 优化我们的 Twtxt

废话不多说,我们直接上代码:

import { getCollection } from "astro:content";
import getSortedPosts from "@utils/getSortedPosts";
import { SITE } from "@config";

export async function GET() {
  const posts = await getCollection("blog");
  const sortedPosts = getSortedPosts(posts);

  // 构建注释部分(以 # 开头)
  const comments = [
    "# Twtxt is an open, distributed microblogging platform that",
    "# uses human-readable text files, common transport protocols,",
    "# and free software.",
    "#",
    "# Learn more about twtxt at this links:",
    "# * https://twtxt.readthedocs.io/en/stable/",
    "# * https://twtxt.net",
    "# * https://twtxt.dev",
    "#",
    `# nick = liuzhen932_blog`,
    `# url = ${SITE.website}twtxt.txt`,
    `# link = Website ${SITE.website}`,
    `# avatar = ${SITE.website}favicon.png`,
    `# description = ${SITE.desc}`,
    `# type = rss`,
    `# follow = liuzhen932 https://twt.xmsl.im/user/liuzhen932/twtxt.txt`,
    "",
  ];

  // 构建帖子内容部分
  const postsContent = sortedPosts.map(({ data, slug }) => {
    return `${new Date(data.modDatetime ?? data.pubDatetime).toISOString()}\t**${data.title}** ${data.description} ⌘ [Read more](${SITE.website}post/${slug})`;
  });

  // 合并注释和帖子内容
  const twtxt = [...comments, ...postsContent].join("\n");

  return new Response(twtxt, {
    headers: {
      "Content-Type": "text/plain",
    },
  });
}

这段代码通过 Astro Content API 动态生成符合 Twtxt 标准的文本文件(.txt),将博客文章以 Twtxt 格式输出。

元数据部分:定义 Twtxt 的身份与配置

const comments = [
  "# nick = liuzhen932_blog",
  `# url = ${SITE.website}twtxt.txt`,
  `# avatar = ${SITE.website}favicon.png`,
  `# description = ${SITE.desc}`,
  `# follow = https://twt.xmsl.im/user/liuzhen932/twtxt.txt`,
  "",
];

作用:


内容部分:将博客文章转换为 Twtxt 格式

const postsContent = sortedPosts.map(({ data, slug }) => {
  const timestamp = new Date(
    data.modDatetime ?? data.pubDatetime
  ).toISOString();
  return `${timestamp}\t**${data.title}** ${data.description} ⌘ [Read more](${SITE.website}post/${slug})`;
});

响应生成:输出符合标准的文本文件

将元数据和文章内容拼接成一个纯文本字符串,通过 Response 对象返回文本内容,设置 Content-Type: text/plain 确保客户端能正确解析。

const twtxt = [...comments, ...postsContent].join("\n");
return new Response(twtxt, {
  headers: {
    "Content-Type": "text/plain",
  },
});

第二版的代码显示效果

0x04 总结

本文详细介绍了如何在个人博客中集成 Twtxt 这一去中心化微型博客系统。Twtxt 是一种基于纯文本文件的极简微博客格式,通过简单的文本文件实现自主可控的内容发布。作者以 Astro 框架为例,演示了如何通过动态生成 Twtxt 文本文件,将博客文章转化为 Twtxt 格式。此外,作者展示了如何在 Yarn.social 等平台订阅自己的 Twtxt feed,并优化内容呈现形式,例如添加文章标题、摘要及跳转链接。文章还强调了 Twtxt 的去中心化特性与隐私优势,通过元数据配置和内容格式化,实现了博客与 Twtxt 生态的无缝衔接。最终,用户可通过客户端实时查看博客更新,体现了 Twtxt 在技术自主性和内容分发上的灵活性。

好了,这就是今天的全部内容了,如果有任何内容欢迎留言反馈~ 我先去睡觉啦!


分享这篇文章:

上一篇
五月小结:聊聊我的 Homelab 和基础设施
下一篇
在 Debian 12 上安装 step-ca 配置 PKI 和证书颁发机构教程

人机验证:请刷新页面以加载评论区