Skip to content

Instantly share code, notes, and snippets.

@hexium310
Last active July 10, 2023 10:07
Show Gist options
  • Save hexium310/45cad452f14d6a6bab3ddee581e6eba7 to your computer and use it in GitHub Desktop.
Save hexium310/45cad452f14d6a6bab3ddee581e6eba7 to your computer and use it in GitHub Desktop.
A bookmarklet to save an image opening on Twitter
javascript:(async()=>{var[,t,e]=location.href.match(/\/status\/(\d+)\/photo\/(\d)/),a=document.querySelector('div[style*="transition-duration:"][style*="background-color:"]'),i=[...a.querySelectorAll("ul")].find(t=>[...t.style].includes("transform")),o='img[src^="https://pbs.twimg.com/media/"]',i=(void 0!==i?[...i.querySelectorAll(o)][e-1]:[...a.querySelectorAll(o)].find(t=>"tweetPhoto"!==t.parentNode.getAttribute("data-testid"))).src,a=await fetch(i).then(t=>t.blob()),o=a?.type;/^image\/.+$/.test(o)&&(await(i=await(await window.showSaveFilePicker({startIn:"downloads",suggestedName:`twitter_${t}_`+e,types:[{accept:{[o]:"."+o.match(/image\/(.+)/)[1]}}]})).createWritable()).write(a),await i.close())})();
(async () => {
const url = location.href;
const [_, tweetId, nth] = url.match(/\/status\/(\d+)\/photo\/(\d)/);
const modal = document.querySelector('div[style*="transition-duration:"][style*="background-color:"]');
const ul = [...modal.querySelectorAll('ul')].find((elm) => [...elm.style].includes('transform'));
const imgQuery = 'img[src^="https://pbs.twimg.com/media/"]';
const img = ul !== undefined ?
[...ul.querySelectorAll(imgQuery)][nth - 1] :
[...modal.querySelectorAll(imgQuery)].find((elm) => elm.parentNode.getAttribute('data-testid') !== 'tweetPhoto');
const imgUrl = img.src;
const blob = await fetch(imgUrl).then((res) => res.blob());
const blobType = blob?.type;
if (!/^image\/.+$/.test(blobType)) {
return;
}
const fileSystemFileHandle = await window.showSaveFilePicker({
startIn: 'downloads',
suggestedName: `twitter_${ tweetId }_${ nth }`,
types: [
{
accept: {
// Twitterの画像はJPEG、PNG、GIFだけだった気がするから拡張子はこれでも問題ないはず
[blobType]: `.${ blobType.match(/image\/(.+)/)[1] }`,
},
},
],
});
const writableStream = await fileSystemFileHandle.createWritable();
await writableStream.write(blob);
await writableStream.close();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment