辛宝Otto

辛宝Otto 的玄酒清谈

北漂前端程序员儿 / 探索新事物 / Web Worker 主播之一/内向话痨
xiaoyuzhou
email

技术折腾 xLog 1 可行性探索

技术折腾 xLog 1 可行性探索

内部链接

  • [[技术折腾 xLog 1 可行性探索]]
  • [[技术折腾 xLog 2 深入理解 xlog 的鉴权]]
  • [[技术折腾 xLog 3 实现一个 obsidian 插件]]
  • [[技术折腾 xLog 4 用 unStorage 封装 xLogDriver]]
  • [[速通 - xLog 背后的 CrossBell SDK]]
  • [[从官方 XLOG Obsidian 插件中能学到什么]]
  • [[开发 Obsidian Sync To Xlog 插件之 处理 obsidian 的图片]]
  • [[速通 - CrossBell 的开源作品]]
  • [[速通 Obsidian Docs - 侧重插件开发]]

想写个系列文章,从技术角度折腾地球上最好的 blog 平台 xlog.app, 争取做到以下事情(又开始夸海口了,新朋友,这是我的一种表达风格哈):

  • 坚守心爱的文本编辑器,不离开 obsidian,一样发布 xlog 博客
  • 不开网页,依然可以访问 xlog ,阅读其他人的博客和互动
  • 同步 xlog 博客,用自己的域名和服务器展示自己的内容
  • github + xlog = 多租户 cms
  • 成为 xlog 成员

口嗨完毕,开始尝试技术的可行性探索。本次内容我们来谈,如何通过官方提供的 openapi 访问 xlog 内容。

需求背景#

xlog 作为地球上最好的 blog 平台,有两个小问题,国内大陆访问可能会稍慢;全量迁移博客到 xlog 之后,自己的服务器就闲置了。

或者干脆一点,能不能拿在 xlog 上发布文章,自己部署一份儿?展望后面,谁说 xlog.app 才是访问 xlog 的唯一方式,我们是不是限制了 xlog 成为地球上最好的 headlessCMS 的潜力?

那么开搞。

技术探索#

从目前公开的信息来看,xlog 官方提供了多种方式获取 xlog 内容,以访问自己的数据为例:

  • 可以通过 crossbell SDK 访问数据
  • 可以通过 http restful API 访问数据

接下来我们通过两种方式分别访问自己的数据,当然是已发布的公开文章。

前置准备#

看下面的内容的大前提是,你需要是 xlog 的用户,没有的快去注册吧。

获取公开的地址 Address,访问 https://xlog.app/dashboard ,按照图片圈选位置,点击,会提示 【已复制】,可以把这个视为当前用户在 xlog 上的唯一 ID。如果你有多个角色,ID 是不同的。

我们找个小本本把他记录上,以我的为例,后续使用它来访问: 0xA0fb033D4849b13A16690EEbdd575Dd90bF29711

image.png

接下来我们使用不同的方式获取数据。

通过 SDK 访问数据#

这里需要自备 Node.js 环境,如果你是非 Node 技术栈,直接看下面 通过官方 API 访问章节

官方 SDK 的 Github 地址 https://github.com/Crossbell-Box/crossbell.js

吐槽:官方的文档不是很好,回头给他贡献修改下。

我们先使用只读用户访问数据。这里对应官方文档的 Class Indexer

首先启动项目

mkdir xlog-api-demo
cd xlog-api-demo && pnpm init
pnpm i crossbell
# 准备 ts 环境
pnpm i typescript tsx -D
touch index.ts

我们在 index.ts 中组织下面代码

import { createIndexer } from "crossbell";

const indexer = createIndexer();
const Address = process.env.USER_ADDRESS as `0x${string}`;

const getUserByAddress = async () => {
  const res = await indexer.character.getMany(Address);

  console.log(res);
};
getUserByAddress();

具体执行,看对应的仓库,主要是根据 address 获取角色信息。可以获取 metadata 和 charactorId

// const characterId = 53710;
const getNotesByCharacterId = async (characterId: number) => {
  const res = await indexer.note.getMany({
    characterId,
    includeNestedNotes: false,
    limit: 10,
  });
  console.log(res);
};

这个就可以读取到用户的数据了。翻页可以通过 total + cursor + limit 实现, 游标 cursor 在每次请求结果中体现。

查询具体详情,可以通过这个实现

const noteId = 16;
const characterId = 53710;
const getNoteById = async (noteId: number) => {
  const res = await indexer.note.get(characterId, noteId);
  // console.log(res);
  console.log(res?.metadata?.content);
};
getNoteById(noteId);

类推其他方法,这里不一一列举,可以实现各类数据的展示。

通过以上两个方法,我们可以实现个人博客的搭建了,首页网站基础信息、列表页更新列表、详情页信息展示。

这里有两个细节,提一下:

  • 自定义的 embed,比如音视频,需要自己兼容,这个有机会留到后面处理
  • 图片和链接全程用的 ipfs,这里展开说下

ipfs 协议#

ipfs 协议包罗万物,简单说就是一串 hash,或者 cid 对应一个网络资源,细节不展开,对 web 来说 ipfs 并不是 http 协议,要展示图片,需要有一层协议转换的过程,这里面就涉及到 api 网关的解析。

这一块,一开始我是翻源码自己找到了 gateway ,后来返现好像不用特别 geek,访问 https://crossbell-ipfs-utils.vercel.app/img/bafkreiarfgti3xpv2oznl7rzanfbzm7gvklvcwn5poqb53wlhi3n4cwp2a 这个网页,这个网页从不同的 gateway 加载图片,你选择一个顺眼的就可以

image.png

注意,为了更快的加载速度,如果你考虑子托管,显然自己处理资源是最好的。

另外,xlog 有专门的工具库处理这个问题,可以作为编程方案使用,做个备忘

import { ipfsFetch } from "@crossbell/ipfs-fetch";
ipfsFetch(ipfsUrl)
    .then((res) => {
      console.log(1, res);
    })
    .catch((err) => {
      console.log(3, err);
    });

细节就谈这么多,更多的交互翻一翻 api 就好了。

通过官方 API 访问#

刚才的技术方案依赖 Node.js,如果你擅长其他语言,或者想足够简单,官方还提供了 api,通过 restful api 进行交互,侵入性更低。

直接访问

https://indexer.crossbell.io/docs

按照 SDK 里提到的 address 作为入口

  • 访问 Character 第一个 Get characters of an address 获取 characterId /v1/addresses/{address}/characters
  • 访问 Get a character by characterId 获取用户基础信息,给首页使用 /v1/characters/{characterId}
  • 访问 /v1/characters/{characterId}/notes 得到对应人的文章
  • 访问 /v1/notes/{characterId}/{noteId} 得到对应的文章详情页

这里后续会实际使用,细节先略过

通过以上访问,依然可以实现和 sdk 一样的效果。

接下来,我们会继续探索,如果通过 sdk/api 实现后台管理,除了读取内容,我们还希望可以对文章进行增删改查,实现另一个 xlog。

补充 ipfs 文件上传#

实际体验看,在 xlog 上传的图片、音频、视频文件会自动上传到 ipfs ,并替换图片链接为 ipfs 链接。

目前有两种方案,使用 xlog 的 ipfs 上传协议、使用 http 自己的方案。

这里简单给 ipfs 上传指个路,正好熟悉下 xlog 源码。

思路如下:

  • 因为图片上传是触发在拖拽和粘贴,所以源码中可以搜索 drag/patse 定位到 src/components/ui/ImageUploader.tsx#handleDrop
  • 进一步定位到 handleFile - uploadFile - useUploadFile - UploadFile
  • 可以看到是通过 POST 协议提交到指定的 接口上

截图先忽略,我发现没有鉴权...

结论#

以上,是可行性探索,至少可以通过接口实现数据的获取,在下一篇文章中,我们会探索,通过鉴权实现文章的发布等管理操作,在那个时候 xlog 就具有了 headless cms 的能力。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。