tweet2image-upload
導入
usage.jsimport('/api/code/ci7lus/tweet2image-upload/script.js');
コード中importにトップレベルawaitを使用しているため読み込みに失敗し、iOS Safariなどでは後述のimportに影響するかもしれません、 import()
を用いてください
CHANGELOG
2024/10/21
tweet2imageしれっと復活させたので合わせてx.comのときに無効なURLって返さないようにしました
貼られるURL等は更新していません
2021/10/16
2021/8/20
UserScriptが入ってない場合に新しいタブで導入ページが開くようになりました
2021/7/22
2021/7/6
Font Awesome 5 Free
、バンドルされてる分だとBrandが抜けてる?っぽいのでsvgに置き換え
2021/06/10
Scrapbox側の変更で自動貼り付けに失敗するようになったので、プロンプトでコピーする形式に変更しました
2021/04/24
ホスト名変更、パス変更
now.shがvercel.appにリダイレクトされるようになったのでアップロードできなくなったのが修正されます
2020/10/3
ライセンスを明記
メッセージを全部日本語に(lang=ja&tz=9固定だし…)
ライセンス
> MIT License Copyright (c) 2020 ci7lus
script.js/* https://scrapbox.io/ci7lus/tweet2image-upload */
/* MIT License Copyright (c) 2020 ci7lus */
/*const style = document.createElement("style");
style.innerText = `@import "https://scrapbox.io/api/code/ci7lus/tweet2image-upload/style.css";`;
document.body.appendChild(style);*/
import { insertText } from "/api/code/customize/scrapbox-insert-text/script.js"
scrapbox.PageMenu.addMenu({
title: "tweet2image",
image: "https://scrapbox.io/files/60e9891a6f8d0b0022457e87.svg",
onClick: async () => {
if (!window.get_tweet_card) {
alert("UserScriptが入ってなさそうです?")
window.open("https://scrapbox.io/ci7lus/tweet2image-proxy", "blank")
return
}
const text = prompt("ツイートのURLを入力してください")
if (text === null) return
const gyazoClientId =
"e2bd725244baa768eb100126fa2cd85910445778a25ba7ef1328608750b070d5"
const tweetcard = "https://tweet2image.vercel.app"
const m = text.match(/(twitter|x).com\/(.+)\/status\/(\d+)/)
if (!m) {
alert("無効な形式のURLです")
return
}
const tweetAuthor = m[2]
const tweetId = m[3]
let imageData
// 進捗表示エリア
const progressArea = document.createElement("div")
progressArea.style =
"position: fixed; top: 0; right: 0; margin: 1rem; padding: 1rem; background: #FFF; color: 000; z-index: 9999;"
progressArea.innerText = "ツイートの画像を取得中..."
document.body.appendChild(progressArea)
try {
const tweet2imageUrl = `${tweetcard}/${tweetId}.jpg`
console.log(tweet2imageUrl)
const req = await window.get_tweet_card(tweet2imageUrl)
if (req.status !== 200) {
alert("Image fetch failed(!=200)")
return
}
imageData = req.response
} catch (e) {
console.error(e)
alert("ツイート画像の取得に失敗しました")
document.body.removeChild(progressArea)
return
}
const tweetUrl = `https://twitter.com/${tweetAuthor}/status/${tweetId}`
// upload to gyazo
try {
progressArea.innerText = "Gyazoをチェックしています"
let token = window.gyazoOAuthToken
if (!token) {
const project = await fetch(
`https://scrapbox.io/api/projects/${scrapbox.Project.name}`
)
const { gyazoTeamsName } = await project.json()
if (gyazoTeamsName) {
alert(
"Gyazo Teamsを使ったことがないのでアップロードがおかしくなるかもしれません(可能であればTwitter@ci7lusまで動作確認報告お願いします)"
)
}
const gyazoOAuthToken = await fetch(
`https://scrapbox.io/api/login/gyazo/oauth-upload/token?gyazoTeamsName=${
gyazoTeamsName || ""
}`,
{
headers: {
accept: "application/json, text/plain, */*",
},
method: "GET",
}
)
const tokenResult = await gyazoOAuthToken.json()
token = tokenResult.token
window.gyazoOAuthToken = token
}
if (token) {
progressArea.innerText = "Gyazoにアップロードしています…(OAuth)"
const formData = new FormData()
formData.append("access_token", token)
formData.append("referer_url", tweetUrl)
formData.append("title", tweetUrl)
formData.append("imagedata", imageData)
const upload = await fetch("https://upload.gyazo.com/api/upload", {
headers: {
accept: "application/json, text/plain, */*",
},
referrerPolicy: "same-origin",
body: formData,
method: "POST",
mode: "cors",
credentials: "omit",
})
const { permalink_url } = await upload.json()
console.log(`${tweetUrl} -> ${permalink_url}`)
insertText({ text: `[${permalink_url} ${tweetUrl}]` })
} else {
progressArea.innerText = "Gyazoにアップロードしています…(EasyAuth)"
const imageB64Data = await new Promise((res, rej) => {
const reader = new FileReader()
reader.onerror = rej
reader.onload = () => {
res(reader.result)
}
reader.readAsDataURL(imageData)
})
const formData = new FormData()
formData.append("client_id", gyazoClientId)
formData.append("referer_url", tweetUrl)
formData.append("imagedata", imageB64Data)
const easyAuth = await fetch(
`https://upload.gyazo.com/api/upload/easy_auth`,
{
method: "POST",
mode: "cors",
credentials: "include",
body: formData,
}
)
const uploadResult = await easyAuth.json()
const getImage = await fetch(uploadResult.get_image_url, {
mode: "cors",
credentials: "include",
})
progressArea.innerText = "done!"
console.log(`${tweetUrl} -> ${getImage.url}`)
insertText({ text: `[${getImage.url} ${tweetUrl}]` })
}
} catch (e) {
console.error(e)
alert("アップロードに失敗しました…")
} finally {
document.body.removeChild(progressArea)
}
},
})
style.cssa#tweet2image.tool-btn:hover {
text-decoration: none;
}
a#tweet2image.tool-btn::before {
position: absolute;
left: calc(46px / 3 - 1px);
content: "\f099";
font: 21px/46px "Font Awesome 5 Free";
font-weight: 900;
}