denoでいい感じにweb API requestをしたい
(あとで冒頭の説明を書く)
📝思っていることのメモ
- 初手の1ファイルのスクリプトをどこから書き始めるかを考えたい
- 最終的にまともな型がつくような状態に遷移させたい
- fetch()のwrapperがあれば十分でクラスとか不要なのでは?
- はじめからライブラリを使うと統合に苦労するのでは?
1st step (ChatGPT API)
class不要でfetch()のwrapperだけあれば良いのでは?という発想のもと
ChatGPTのAPIを元にコードを書いてみる
奮闘の履歴
不足していること
- stream 対応 (SSE?)
- request/responseの型をどうやって定義する?(JSONからtransform.toolsとか?)
- testがない
- ファイルで入出力を受けるならjsonschemaなども生成したい?
- modelをコマンドラインオプションにしたい
ライブラリ的な話
- pathに変数があるAPIへの対応はどうする?
e.g. /usrs/{userId} - backoff対応はどうする?
- trace部分はAPIを作る毎に書き下すの? (自動計装まわりでnode-fetchのpatchとかある?)
- ブラウザ経由で呼び出すのは楽?
2nd step (gemini API)
⚠️googleのweb APIだと認証周りが面倒な気がする。手書きしたくない
🐾 key=<gemini api key> で十分だった。それなりに…機能は…していそう…。
- pathに変数がある場合は? -> plaecholderで指定して fetchの中でreplace
- stream対応は? -> https://jsr.io/@lukeed/fetch-event-stream を使った
-(cli parserのところでchoicesを使うときに補完が効かなくなる問題があった)
path変数の方はfetch()に余分なオプションが与えられるようになったのがキモい。他の方法があれば選択したい。
そろそろweb ui側も考えていきたい気もする
あと、web ui側のようにrequest/responseを繰り返す所作をやってない。
型を真面目に指定したい
- responseの型は https://transform.tools/json-to-io-ts でどうにかなる
- requestの型は documentなどをみて自前で書かないといけない
- request/responseの型を定義してしまうならDocの型も要らなそう
Record<path, url>
- request/responseの型を定義してしまうならDocの型も要らなそう
tempreature とかを指定したいとnumberも指定したくなるのか。
typescriptはinteger型とか無いのだった。
3rd step
bskyに投稿したい。
結構悩ましい事が色々ある
- どうせなので1ファイルで簡潔させたい
- 名前の衝突は避けたい
- namespaceを使うとdeno-lintに怒られるけれどnamespaceを使うことにする
- request/responseがあやふやになる
- パスワードがそのまま表示される(ライブラリ的なものの不備)
💭bsky固有の話としてそもそも文字数制限に引っかかる
使用感を求めるタイミングになったら途端にどうでも良くなってきた感がある。
4th step
gistへの投稿をしてみたい。存在しないファイルを存在しているかのようにして。
認証部分を相手にする必要がある?gh auth loginとかで手に入るから大丈夫。
5th step
- bskyでスレッドで繋げて投稿したい
- 文字数制限を把握したい
-
-が3回以上続いた場合は分けたい - それでもあれなら愚直に分けたい
- とりあえずは文を気にせずに分ける
6th step
一歩戻ってauth周りをgh cliみたいな形で作っていきたい。bsky用のクライアントをそのようなインターフェイスで作ってみる。
- auth周りのサブコマンドを作る(login,logout,status,token,refresh)
- passwordの入力
- postでふつうにpost
できたことは
- auth login
- auth status
- auth token
- auth refresh
- post
気になるところはaccess tokenがrequiredとして載りそのままヘルプメッセージに載ってしまうこととauth tokenやauth statusでacess tokenを所持にしていない場合にauth loginを促すような仕組みを作るのがコードとして面倒ということ
あとpostの方ではfacetsを設定しないとテキストがリンクとして機能しないようだった。
とりあえず import { RichText } from "npm:@atproto/api@0.13.20"; でお茶を濁していた。
jsr:@std/dotenvはコメントにも対応していて便利だった。
手抜きでやった結果型チェックが雑になっていた。
スレッドの投稿はできたけれど内容の加工をどのように加えるかという案が思いつかない。
backoffが必要ななにかがほしいかも?
テストを一切書いていない
いっそのこと次回はatprotoへの依存を許して実装してみるか。
7th step
一旦依存を少なめにするという前提を排除して npm:@atproto/api しながらbskyのクライアントを作ってみる。雛形はchatgptにまかせてみた。
いいことばかりではなかった。
日々の日記的なところに書いていた。
8step OGPのデータをブラウザ上で取得したかった
CLI上ではふつうに deno run -A jsr:@podhmo/ogp/collect-ogp https://github.com/podhmo とかが動くがブラウザ上では上手くいかない。基本的にcors関連のあれこれで上手く動いてくれない。試したことは
- 直接fetch()
- ifarme
- window.openでpopup
追記
bsky.appでどうやっているかが気になった。
bsky.appがどうやっているのかといえば素直に自前のweb APIにリクエストしているだけっぽい。cardyb.bsky.app
- ogp関連のデータを取得するweb API
/v1/extract - カード画像のデータを取得するweb API
/v1/image
詳細
GET https://cardyb.bsky.app/v1/extract?url=https%3A%2F%2Fgithub.com%2Fpodhmo
{
"error": "",
"likely_type": "html",
"url": "https://github.com/podhmo",
"title": "podhmo - Overview",
"description": "podhmo has 255 repositories available. Follow their code on GitHub.",
"image": "https://cardyb.bsky.app/v1/image?url=https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F80613%3Fv%3D4%3Fs%3D400"
}
GET https://cardyb.bsky.app/v1/image?url=https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F80613%3Fv%3D4%3Fs%3D400
09 deno serveでserveしてみる
まだ途中そう。。
- tsx -> ts -> js変換の結果を保持したclient sideのjsの作り方が分からない
- server sideだけの場合はhonoとかのほうが良いかも?
一応文字列直書きのバージョンは03communicate.tsで完成している
honoで楽をしようとしてみる
routingは確かに楽。
ファイル配信も一応アダプターが用意されている。
クライアントサイドは素直にreactとかで良い気がした。
手元での確認レベルではviteとかを使いたい。esm.shで作業するのはだるいかも?
あと分かっていないこと
- esm.sh経由でimportしているときにキャッシュが効いていないような気がする?
- honoの中でscriptタグを挿入するのを試していない