✅ニコニコのURLからサムネイル画像を貼り付けるUserScriptを作る
開発着手前に考えていた仕様
メニューにニコニコのアイコンを追加する
クリックするとモーダルでURL入力を促される
[サムネイルURL https://www.nicovideo.jp/watch/sm37956838]が貼り付けられる
---
サムネのURLを取得する
方法1
レスポンスがXMLで帰ってくる....
方法2
こっちは想定されていそうだしURLの意味がわかりやすいのでこっちをやってみる
帰ってこない動画がある
対応済み
せっかくなのでdenoで開発をしてみる
haederのURLが入っているmetaタグは次のように取れるが、ここからURLをとるのに苦戦
nodeをconsole.log()してみるとattributesにURLがある。これを取得したい
code:zsh
attributes: NamedNodeMap {
property: "og:image",
},
deno-dom-wasmで取得したNodeからURLの文字列を取得できない
このMeta nodeはElementである
code:ts
// 1 = Element
しかしElementにあるはずのattributesを取得しようとするとNodeにattributesはないとエラーが出る
code:zsh
error: TS2339 ERROR: Property 'attributes' does not exist on type 'Node'. attributesはElementの要素なのでNodeをElementにしたい
問題:castしても同種のエラーが出る
code:zsh
error: TS2304 ERROR: Cannot find name 'Element'. 解決策:deno-domのElementをロードしておけばcastできる
code:これをimportする必要があった.ts
/watch/smXXXからサムネイルのURLを取得することができるようになった
code:mod.ts
import {
DOMParser,
Element
export async function getThumUrl(url: string): Promise<string> {
const res = await fetch(url);
const doc = new DOMParser().parseFromString(await res.text(), "text/html");
if (doc == null) {
throw new Error("document not found");
}
const thumbUrl = node.getAttribute("content");
if (thumbUrl == null) {
throw new Error("document not found");
}
console.log(thumbUrl);
return thumbUrl;
}
どうやって?
URLの取得はこうすればいい
1. prompt方式
2. 範囲選択の文字列から正規表現で抽出
denoのプログラムをどうUserScriptにすればいい?
やってみたらサイズが大きすぎた
minifyしたい
code:zsh
error: TS2322 ERROR: Type '"esm"' is not assignable to type '"module" | "classic" | undefined'. bundle: 'esm',
~~~~~~
https://scrapbox.io/motoso/%E3%83%8B%E3%82%B3%E3%83%8B%E3%82%B3%E3%81%AEURL%E3%81%8B%E3%82%89%E3%82%B5%E3%83%A0%E3%83%8D%E3%82%A4%E3%83%AB%E7%94%BB%E5%83%8F%E3%82%92%E8%B2%BC%E3%82%8A%E4%BB%98%E3%81%91%E3%82%8BUserScript
この結果をScrapboxに貼り付けようとすると、imput is too largeになってしまう
コードをScrapbox上で動かすのは諦めてAPIにすることにした
Cloud functionsにデプロイしてみる?
Denoはそのままだと対応していない
ここまで大げさにするならタイトルとコメント載っけるのをSVGを作るまでやりたい
ダッシュボードでエラーが出て進めなかった
AWSにデプロイしてみる
derror: Module not found "file:///var/runtime/mod.ts".
zipでダウンロードするサンプルコードが誤っている
罠すぎる基素.icon
修正したら動いた
なんやかんやあり完成
ブラウザのセキュリティがあるからこれをそのまま使うことはできない
takkerさんのURL開くのはどうやっているか見てみたらScrapboxのAPIを使っていた
CLI版(動作確認のために作った副産物)
使い方
code:zsh
URLは正しい前提
code:cli.ts
async function getThumUrlAndTitle(url: string): Promise<string[]> {
let res = await fetch(url);
let text = await res.text();
let doc = new DOMParser().parseFromString(text, "text/html");
// HTMLからog:imageを取得する
if (doc) {
if (meta) {
const thumbUrl = meta.getAttribute("content");
if (thumbUrl) {
const titleNode = doc.querySelector("head > title");
const title = titleNode ? titleNode.textContent : "";
}
}
}
// fallback: 動画IDを抽出してXML APIから取得する
const videoIdMatch = url.match(/watch\/(^/?+)/); if (!videoIdMatch) {
throw new Error("動画IDを抽出できませんでした");
}
const videoId = videoIdMatch1; const fallbackUrl = https://ext.nicovideo.jp/api/getthumbinfo/${videoId};
res = await fetch(fallbackUrl);
text = await res.text();
// DenoのDOMParserは"text/xml"をサポートしていないため、"text/html"でパースする
const xmlDoc = new DOMParser().parseFromString(text, "text/html");
if (!xmlDoc) {
throw new Error("XMLのパースに失敗しました");
}
const thumbNode = xmlDoc.querySelector("thumbnail_url");
if (!thumbNode || !thumbNode.textContent) {
throw new Error("XMLからthumbnail_urlを取得できませんでした");
}
const thumbUrlFallback = thumbNode.textContent;
const titleNodeFallback = xmlDoc.querySelector("title");
const titleFallback = titleNodeFallback ? titleNodeFallback.textContent : "";
}
if (import.meta.main) {
// コマンドライン引数からURLを取得。指定がなければデフォルトでsm41994908を利用
try {
const result = { thumbnailUrl, title };
console.log(JSON.stringify(result, null, 2));
} catch (error) {
console.error("Error:", error);
Deno.exit(1);
}
}
code:cli-old1.ts
import {
DOMParser,
Element
async function getThumUrl(url: string): Promise<string> {
const res = await fetch(url);
const doc = new DOMParser().parseFromString(await res.text(), "text/html");
if (doc == null) {
throw new Error("document not found");
}
const title = doc.querySelectorAll('head > title')0 as Element; console.log(title.textContent);
const thumbUrl = node.getAttribute("content");
if (thumbUrl == null) {
throw new Error("document not found");
}
console.log(thumbUrl);
return thumbUrl;
}
const parsedArgs = parse(Deno.args);
getThumUrl(parsedArgs.url);
--
So far Deno DOM only implements the Element class. .href is a property of HTMLAnchorElement, a more specific DOM element implementation, of which there are many, and I haven't got around to implementing yet. So for now you can use the getAttribute("href") method of Element. tsconfigを追加したら大量のエラーが出るようになった
Deno は TypeScript の設定ファイルをサポートしていますが、他と違い、設定ファイルの検出を使用は自動ではありません。Deno で TypeScript 設定ファイルを使うには、コマンドラインでパスを指定する必要があります