内部リンク
- [[技術の試行 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 - プラグイン開発に重点を置く]]
この記事は [[技術の試行 xLog 1 実現可能性の探求]] の内容を引き継いでいます。
この記事では、xlog 記事の管理を実現し、自分のコンテンツの作成、削除、更新、取得を公式の openapi に基づいて行います。この記事の価値は 5 コインの感謝です、えへへ。
背景#
xlog 記事の管理操作を実現するには認証が必要です。どうやってあなたがあなたであることを証明し、他の人の記事を変更できるのでしょうか? web2 の分野では、一般的にアカウントとパスワードを使用して jwt を生成し、ユーザーを模倣したり、oauth を通じて特定の権限範囲の access-token を取得したりします。
私たちの技術的前提は、任意の実行環境をサポートし、ブラウザや node.js などの異なる実行環境を同時にサポートすることですので、ウェブ端末の小狐 metamask による認証は考慮しません。
技術実装#
いくつかの探索を経て、公式メンバーの diygod の指導を受けて、現在少なくともデータ認証管理を実現する方法が二つあります。秘密鍵と認証コードで、後者を推奨します。
プライベートキーによる認証#
まずはプライベートキー、ウォレットの秘密鍵を使用します。これは万能の私が私であることを証明する方法で、公式 sdk もプライベートキーを使用して認証を実現することをサポートしています。
例えば、ここに https://crossbell.js.org/#md:connect-with-private-key
プライベートキーはどこから来るのでしょうか?小狐の例を挙げます:
アカウントの詳細には、Show Private Key という項目があります。公式 SDK と組み合わせることで認証を実現できます。
必ず注意してください:プライベートキーは非常に機密性が高く、使用することは非常に危険です。ここでは技術的な紹介のみです。
ユーザーと開発者には、以下の認証トークンの方法をお勧めします。
siwe 認証による認証#
SIWE は sign in with ethereum
の略です。
siwe 認証には以下のステップがあります:
- siwe 機能を有効にする
- トークンを取得する
- api を通じて認証を得る
siwe 機能を有効にする#
まず、自分の xlog コンソール https://xlog.app/dashboard/ にアクセスし、左側のメニューの最後の列で設定を選択します。
xSettings
を選択すると、以下のように表示されます:
私は web3 にあまり詳しくないので、口語的に表現します。丸い枠内の説明はこう理解できます。主に Sync Operator 部分です:
- 操作の認可。
- 同期操作。Sync Operator を有効にすることで、他の方法で Crossbell にコンテンツを同期することができます。つまり、xlog です。
一旦有効にすれば、コードを通じて xlog にコンテンツを同期する能力を持つことになります。
トークンを取得する#
現在、トークンを取得する最も簡単な方法は、コンソールで以下の操作を行うことです:
xsetting ページで、右クリックして検査を選択するか、開発者モードを有効にするか、F12 を押します。Chrome の使用をお勧めします。モジュールがポップアップし、コンソールを選択して、以下のコードをコピーしてコンソールに貼り付け、Enter を押すと、一連の文字が返されます。
JSON.parse(localStorage.getItem('connect-kit:account')).state.wallet.siwe.token
このコードの目的は、siwe のトークン情報を取得することです。他にも取得方法があるはずですが、現在の方法が最も簡単です。
このコードを入力して返される内容が必要なトークン情報ですので、自分で保存してください。
両端のシングルクォートに注意してください。内容だけで大丈夫です。(まあ、私は防止設計をして、プログラムの互換性を持たせますが。)
コンソールから返されたこの長い文字列をコピーしてください。これが認証トークンと呼ばれ、プラグインで使用されます。
開発者にとっては、node.js プロジェクトで .env に保存し、github で secret に保存します。明文での露出を避けるためです。
api 実践#
補足:crossbell の sdk を使用することもお勧めします。効果は同じです。
先ほど取得したトークンを使って、https://indexer.crossbell.io/docs#/Siwe 公式が提供する文書にアクセスします。必要なすべてのものがここにあります。
ページの最上部に緑色の Authorize ボタンがあります。クリックするとポップアップが表示され、先ほどのトークンを siwe の内容に記入します。
認可をクリックすると、以降のリクエストのヘッダーに Authorization: Bearer ${token}
が追加されます。
例えば、GET /v1/siwe/account
を使用すると、現在の私たちが誰であるかを取得できます。
残りのことは簡単です。以下のいくつかのインターフェースを使って実践できます:
PUT /v1/siwe/contract/characters/{characterId}/notes
ユーザーに新しい記事を作成するPOST /v1/siwe/contract/characters/{characterId}/notes/{noteId}/metadata
指定された noteId の記事を更新するDelete /v1/siwe/contract/characters/{characterId}/notes/{noteId}
指定された記事を削除する
いくつかのコードスニペットを提供します。何度か試した結果、以下のコードスニペットが有効です。
まずは記事を作成する:
const title = '記事のタイトル'
const content = '記事の内容'
const base = "https://indexer.crossbell.io";
const ottoCharId = ''
const token = ''
const createPost = async () => {
const url = `/v1/siwe/contract/characters/${ottoCharId}/notes`;
const finalUrl = base + url;
axios
.request({
method: "put",
url: finalUrl,
headers: {
Authorization: `Bearer ${token}`,
},
data: {
metadata: {
tags: ["post"],
type: "note",
title: title,
content: content,
summary: "",
sources: ["xlog"],
attributes: [
{
value: "play-xlog-01", // ここはカスタムスラッグ
trait_type: "xlog_slug",
},
],
attachments: [
{
name: "cover", // カバー
address: "",
mime_type: "",
},
],
},
locked: false,
linkItemType: null,
},
})
.then((res) => {
console.log(2, res.data);
})
.catch((err) => {
console.log(3, err);
});
};
次に記事を更新します。ここでの mode は文字通り replace が簡単です。
const updatePost = async () => {
const noteId = 29;
const mode = "replace"; //'merge'
const updatePost =
base +
`/v1/siwe/contract/characters/${ottoCharId}/notes/${noteId}/metadata`;
axios
.request({
method: "post",
url: updatePost,
headers: {
Authorization: `Bearer ${token}`,
},
data: {
metadata: {
tags: ["post", "新しいアイデア"],
type: "note",
title: title,
content: content,
sources: ["xlog"],
// summary: "",
attributes: [
{
value: "play-xlog-01",
trait_type: "xlog_slug",
},
],
attachments: [
{
name: "cover",
address: "",
mime_type: "",
},
],
},
mode,
},
})
.then((res) => {
console.log(JSON.stringify(res.data, null, 2));
})
.catch((err) => {
console.log(3, err);
});
};
最後に記事を削除します。
const deletePost = async () => {
const characterId = '';
const noteId = '';
const deletePost =
base + `/v1/siwe/contract/characters/${characterId}/notes/${noteId}`;
axios
.request({
method: "delete",
url: deletePost,
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
console.log(2, res.data);
})
.catch((err) => {
console.log(3, err);
});
};
落とし穴の経験#
記事のボディは、リストページの返却体とは異なり、主に content が一層包まれているかどうか、つまりリクエストパラメータとデータベースに入るデータが異なるため、少し落とし穴があります。最終的に記事作成のパラメータは使用可能です。
公式は入力パラメータに対して比較的寛容で、どんなパラメータでも受け入れます。笑ってしまいますが、誤ったパラメータはリストページの表示を妨げることがあり、長い間排除作業を行い、目が疲れましたが、公式のソースコードに慣れたら、制限を加える必要があります。
展望#
上記の api 実践内容をもとに、今後以下のことが可能になります:
- node スクリプトを作成し、記事の作成と更新を実現する
- 例えば、github actions で、markdown をプッシュするたびに関数を呼び出し、xlog に同期する
- 例えば、obsidian でプラグインを作成し、右クリックで xlog にアップロードする
- 自分の cms バックエンドを接続し、記事管理を行う
次に、私は自分の obsidian プラグインを改造し、ファイルを xlog にアップロードする機能を実現します。
ご期待ください。