Compare commits

...

No commits in common. "master" and "to-matrix" have entirely different histories.

10 changed files with 113 additions and 746 deletions

2
.gitignore vendored
View File

@ -1,2 +0,0 @@
credentials.json
known_ids.csv

View File

@ -1,4 +0,0 @@
{
"deno.enable": true,
"deno.lint": false
}

113
app.deno.js Normal file
View File

@ -0,0 +1,113 @@
import ky from 'https://esm.sh/ky';
import credentials from "./credentials.json" with { type: "json" };
var {matrix_token, pixiv_cookie, pixiv_user_id} = credentials;
var ke = ky.create({
hooks: {
beforeRequest: [request => console.log(`${request.method} ${request.url}`)],
afterResponse: [(_request, _options, response) => console.log(response.status)]
},
retry: {
limit: 100,
delay: attemptCount => (2 ** (attemptCount - 1)) * 1000
},
timeout: false
});
var matrix = {
ky: ke.extend({headers: {"Authorization": `Bearer ${credentials.matrix_token}`}}),
rooms: {
default: "!mxhaBcBiEmnGxrffll:matrix.org",
pixiv_sfw: "!zStOGJAGxEaQgwxGYI:matrix.org",
pixiv_nsfw: "!HtXDHeAhEKBFGfAJTi:matrix.org"
},
async sendMessage({room = this.rooms.default, type = "m.text", body, filename, info, url}) {
return await this.ky.put(`https://matrix-client.matrix.org/_matrix/client/v3/rooms/${encodeURIComponent(room)}/send/m.room.message/${Math.random().toString()}`, {
json: {msgtype: type, body, filename, info, url}
}).json();
},
async uploadFile(filename, data) {
var {content_uri} = await this.ky.post(`https://matrix-client.matrix.org/_matrix/media/v3/upload?filename=${encodeURIComponent(filename)}`, {body: data}).json();
return content_uri;
},
async sendImage({room = this.rooms.default, body, filename, data, info}) {
var content_uri = await this.uploadFile(filename, data);
return await this.sendMessage({room, type: "m.image", body: body || filename, filename, url: content_uri, info});
}
}
async function downloadPixivIllust(illust_id) {
var html = await ke.get(`https://www.pixiv.net/en/artworks/${illust_id}`, {headers: {"Cookie": credentials.pixiv_cookie}}).text();
var illust = Object.values(JSON.parse(html.match(/<meta name="preload-data" id="meta-preload-data" content='(.*)'>/)[1]).illust)[0];
var images = [];
for (let i = 0; i < illust.pageCount; i++) {
let url = illust.urls.original.replace('p0', 'p'+i);
let data = await ke.get(url, {headers: {"Referer": "https://www.pixiv.net/"}}).then(res => res.blob());
images.push({url, name: url.split('/').pop(), data});
};
return {illust, images};
}
export async function pixivToMatrix(illust_id) {
try {
var {illust, images} = await downloadPixivIllust(illust_id);
var room = illust.xRestrict ? matrix.rooms.pixiv_nsfw : matrix.rooms.pixiv_sfw;
await matrix.sendMessage({room, body: `https://www.pixiv.net/en/artworks/${illust_id}`});
for (var image of images) {
try {
await matrix.sendImage({
room,
filename: image.name,
data: image.data,
info: {
mimetype: image.data.type,
size: image.data.size
}
});
} catch (error) {
onError(error);
}
}
} catch (error) {
onError(error);
}
function onError(error) {
console.error(error.stack);
matrix.sendMessage({room: room || matrix.rooms.pixiv_sfw, body: error.stack}).catch(error => {
console.error(error.stack);
});
}
}
var new_ids = [];
top: for (var offset = 0;;) {
let url = `https://www.pixiv.net/ajax/user/${pixiv_user_id}/illusts/bookmarks?tag=&offset=${offset}&limit=100&rest=show&lang=en&version=5dc84ab282403a049abea4e2f2214b6a69d31da6`;
console.log("get", url);
let data = await fetch(url, {headers: {Cookie: pixiv_cookie}}).then(res => res.json());
let ids = data.body.works.map(x => x.id);
if (!ids.length) break;
for (let id of ids) {
if (["119320087", "119534122"].includes(id)) break top;
new_ids.push(id);
}
offset += ids.length;
}
console.log("new ids", new_ids);
for (let id of new_ids.reverse()) {
await pixivToMatrix(id);
}

View File

@ -1,319 +0,0 @@
var missing = `136867257,https://pleroma.lamp.wtf/notice/Azj5c12GPx7hN5XdBI
136697083,https://pleroma.lamp.wtf/notice/Azj5fjeqy8eYdNMhGK
136826879,https://pleroma.lamp.wtf/notice/AzmaDLM9PO4nD0RFWy
136682087,https://pleroma.lamp.wtf/notice/AzmaJ7MYLh7DXvNcrQ
136052499,https://pleroma.lamp.wtf/notice/AzmaQtouaGCBrSM4yu
135824596,https://pleroma.lamp.wtf/notice/AzmxyOBf00mKXovxK4
136836069,https://pleroma.lamp.wtf/notice/Azmy5oW7VGT6EU2n4q
136871085,https://pleroma.lamp.wtf/notice/Azmy7LsOxXjrz6CQUq
136916244,https://pleroma.lamp.wtf/notice/Azmy8H30On5bIUbCRE
136801943,https://pleroma.lamp.wtf/notice/AzmyB4GoMRvUXPOATY
136643294,https://pleroma.lamp.wtf/notice/AzmyFFtP5hgpk6R95U
136697241,https://pleroma.lamp.wtf/notice/AzmyS4gS4ohkk9UWm0
136359059,https://pleroma.lamp.wtf/notice/AzmyeSn4H4KSz4Uei8
136524574,https://pleroma.lamp.wtf/notice/AzmyhwnZA54SvAO6TY
136621780,https://pleroma.lamp.wtf/notice/Azmyp6FYQ5gKGFtD6W
136589864,https://pleroma.lamp.wtf/notice/AzmypgKQHSy09mRbgu
136411464,https://pleroma.lamp.wtf/notice/AzmzBLywboMpQMjQo4
136473005,https://pleroma.lamp.wtf/notice/AzmzKvIyeDk3aDfIrQ
135935362,https://pleroma.lamp.wtf/notice/AzmzOAOF1ENpEkfqTI
136080564,https://pleroma.lamp.wtf/notice/AzmzSN0s1plpXqkMmO
135437540,https://pleroma.lamp.wtf/notice/AzmzTjMkPHBJA1d1Xc
135752737,https://pleroma.lamp.wtf/notice/AzmzWZCYebbgVODN5s
134997694,https://pleroma.lamp.wtf/notice/AzmzXnTB5i3j2wZiYC
135889428,https://pleroma.lamp.wtf/notice/AzmzZWCCHn3O3GSARE
136775174,https://pleroma.lamp.wtf/notice/AzmzcU2ekakeExP972
136878063,https://pleroma.lamp.wtf/notice/AzmzgdVbUjbyl9vOPg
136888593,https://pleroma.lamp.wtf/notice/AzmzszBCkSRDRiGuxs
136873957,https://pleroma.lamp.wtf/notice/Azn0IBL8fqUuOqvuJE
135060762,https://pleroma.lamp.wtf/notice/Azn0SrGPeo49JtoTqq
136793405,https://pleroma.lamp.wtf/notice/Azn0YMGBqBVItxKcLY
136233931,https://pleroma.lamp.wtf/notice/Azn0wpwV8LivuTnKPQ
136166314,https://pleroma.lamp.wtf/notice/Azn0zak06qKVdEGGAK
135697656,https://pleroma.lamp.wtf/notice/Azn14O6yUcB9uUIIi0
136613468,https://pleroma.lamp.wtf/notice/Azn1NQzM1IoSKqoOIK
136685147,https://pleroma.lamp.wtf/notice/Azn1Q2zdgtIYmeBuEK
135652835,https://pleroma.lamp.wtf/notice/Azn1h5EMcoX8e7CZn6
136722374,https://pleroma.lamp.wtf/notice/Azn1jQkzYtmzzIaBHM
136529508,https://pleroma.lamp.wtf/notice/Azn1p1kdRggYAg5IOm
136377525,https://pleroma.lamp.wtf/notice/Azn1rX7hmAEm374PNQ
136387072,https://pleroma.lamp.wtf/notice/Azn1s83kRq3abYVGqW
135998022,https://pleroma.lamp.wtf/notice/Azn1vCnjH7jSBBTftY
136660281,https://pleroma.lamp.wtf/notice/Azn1vj6z949IOAjVLs
136746554,https://pleroma.lamp.wtf/notice/Azn1xz5Oiw44Vn4DJY
136452701,https://pleroma.lamp.wtf/notice/Azn2232FyxHnv1XGPA
136652509,https://pleroma.lamp.wtf/notice/Azn23qYhLEBrnmZEsi
136675607,https://pleroma.lamp.wtf/notice/Azn2BOVhVZs180lSBU
136797482,https://pleroma.lamp.wtf/notice/Azn2EXBDjOLysxgLpo
136808553,https://pleroma.lamp.wtf/notice/Azn2GanZFTUMgfbGjo
136686071,https://pleroma.lamp.wtf/notice/Azn2T5OXJmxR3Sqioq
136515007,https://pleroma.lamp.wtf/notice/Azn2TTnsZDUQl0tIeW
135654053,https://pleroma.lamp.wtf/notice/Azn2W9IlFVEU2ZbnCC
136291590,https://pleroma.lamp.wtf/notice/Azn2Yw7Oijw81Qcf0C
136750044,https://pleroma.lamp.wtf/notice/Azn2es8ASXDBONoTIG
136496965,https://pleroma.lamp.wtf/notice/Azn2hEPaadtj4h5Ria
136309938,https://pleroma.lamp.wtf/notice/Azn2j7y1WPxffN668O
136293036,https://pleroma.lamp.wtf/notice/Azn2kesedV782EJeSG
136185591,https://pleroma.lamp.wtf/notice/Azn2kyryJkS41u9OAS
130873619,https://pleroma.lamp.wtf/notice/Azn2ouuYyZVMubEu5A
134243940,https://pleroma.lamp.wtf/notice/Azn2yR2msQeRAxcnoW
129850526,https://pleroma.lamp.wtf/notice/Azn3BwUNHD36Sty9WC
134568941,https://pleroma.lamp.wtf/notice/Azn3EOoUwBSgtKYMzI
136139720,https://pleroma.lamp.wtf/notice/Azn3FPT3zSkXD60dpA
133153504,https://pleroma.lamp.wtf/notice/Azn3Ju4a8vwZHxhWts
135054855,https://pleroma.lamp.wtf/notice/Azn3YnW8nZQ1Iih4V6
136569959,https://pleroma.lamp.wtf/notice/Azn3z3IyisDdnL3Y0W
136564001,https://pleroma.lamp.wtf/notice/Azn42T6DHFyUf8iLXk
136788645,https://pleroma.lamp.wtf/notice/Azn4B5WEJm4y8SzfEW
136530000,https://pleroma.lamp.wtf/notice/Azn4BmQMnRwHCja5Z2
136878547,https://pleroma.lamp.wtf/notice/Azn4KmYTgBysDTfRg0
136768413,https://pleroma.lamp.wtf/notice/Azn4Mj9VImtsF3ui36
136900352,https://pleroma.lamp.wtf/notice/Azn4Qw5z7aAPXjH5Ie
136782836,https://pleroma.lamp.wtf/notice/Azn4XNX41buGNG0qP2
136887510,https://pleroma.lamp.wtf/notice/Azn4YypwoSpsMUbp56
136411595,https://pleroma.lamp.wtf/notice/Azn4g6GnZjLfRTYzey
136103976,https://pleroma.lamp.wtf/notice/Azn4hK8FWPfSiy9Esy
136826001,https://pleroma.lamp.wtf/notice/Azn4kE4aVPgwnjorAW
136680366,https://pleroma.lamp.wtf/notice/Azn4lv8Rt2AYe7QvGS
136681369,https://pleroma.lamp.wtf/notice/Azn4of4m3EEzhx1O8e
136306259,https://pleroma.lamp.wtf/notice/Azn4vMuXzDExOhR5xA
136900144,https://pleroma.lamp.wtf/notice/Azn4vW7HlDmFwoStYe
136898930,https://pleroma.lamp.wtf/notice/Azn4wtCtOdlfqok4bA
136638549,https://pleroma.lamp.wtf/notice/Azn4y3XyRDPcD39vSC
136630668,https://pleroma.lamp.wtf/notice/Azn4ySXpUt9RjqHfCS
136515360,https://pleroma.lamp.wtf/notice/Azn507q9Rm0Y6UeFYe
136654849,https://pleroma.lamp.wtf/notice/Azn564CtrqrcZc7c6i
136654762,https://pleroma.lamp.wtf/notice/Azn5AOYo8Vd2rAQtSi
136566091,https://pleroma.lamp.wtf/notice/Azn5DDzns6CkxZPQKu
135483421,https://pleroma.lamp.wtf/notice/Azn5F2EYZcYR3lAmsi
133671217,https://pleroma.lamp.wtf/notice/Azn5Jc2JP1VXG1d1E0
136683876,https://pleroma.lamp.wtf/notice/Azn5WLqEvRFsnM3X5U
136654389,https://pleroma.lamp.wtf/notice/Azn5bNAXPxHaMMwdP6
136725238,https://pleroma.lamp.wtf/notice/Azn5f9v4cXXsQSW6QS
136508597,https://pleroma.lamp.wtf/notice/Azn5kfvF3wtH81E4Aa
136753972,https://pleroma.lamp.wtf/notice/Azn5mfHUPwlrida4QK
136757016,https://pleroma.lamp.wtf/notice/Azn61HY8vsQCSeLAAK
136682282,https://pleroma.lamp.wtf/notice/Azn6937uRPpi2rm1C4
136745113,https://pleroma.lamp.wtf/notice/Azn6CdX5XZslpFGGGG
135878068,https://pleroma.lamp.wtf/notice/Azn6GhEhiGuWTCb8am
131985088,https://pleroma.lamp.wtf/notice/Azn6LZK8YghRNVSjzM
136483664,https://pleroma.lamp.wtf/notice/Azn6OyD0UdMvQUkWfY
136588328,https://pleroma.lamp.wtf/notice/Azn6W8oFTiyYKZaXMO
136629232,https://pleroma.lamp.wtf/notice/Azn6X3GtYPAFRdQCmm
136671049,https://pleroma.lamp.wtf/notice/Azn6ZCeZdw8D7aWUeu
136083812,https://pleroma.lamp.wtf/notice/Azn6b4St3hhyIvwnY0
125830803,https://pleroma.lamp.wtf/notice/Azn6fXdmWg0lwwAuUC
136765666,https://pleroma.lamp.wtf/notice/Azn6oT0b7JqSBq6RKC
136804484,https://pleroma.lamp.wtf/notice/Azn6xcFQ8TbTS0OmeG
136808644,https://pleroma.lamp.wtf/notice/Azn7DKTFztPAwyMaRM
136319282,https://pleroma.lamp.wtf/notice/Azn7MFfRE4jQetJchc
136321268,https://pleroma.lamp.wtf/notice/Azn7WGupRL1vQSIBPM
136319603,https://pleroma.lamp.wtf/notice/Azn7gjW7xFtb1mj7Vg
136179505,https://pleroma.lamp.wtf/notice/Azn7vqanvlNzJd7aO8
136009498,https://pleroma.lamp.wtf/notice/Azn89acM7cs1pAOr5s
136827220,https://pleroma.lamp.wtf/notice/Azn89gph0x6V6GgaiO
136325265,https://pleroma.lamp.wtf/notice/Azn8BzvJ0VYst5Paoi
136360463,https://pleroma.lamp.wtf/notice/Azn8Dc8uOTrRiEXru4
130598488,https://pleroma.lamp.wtf/notice/Azn8GpeKdGEsTJmH0i
125171112,https://pleroma.lamp.wtf/notice/AzrEpVEltQopenZqd6
125163564,https://pleroma.lamp.wtf/notice/AzrErV1xdGFZayXMsS
123860415,https://pleroma.lamp.wtf/notice/AzrFO7GkztWTSP0jfE
137045026,https://pleroma.lamp.wtf/notice/AzrHRc7AyFs5tqKCie
136788164,https://pleroma.lamp.wtf/notice/AzrHlFeaBsiK1sJZFg
134322622,https://pleroma.lamp.wtf/notice/AzrHp4ZpJcjMpkucF6
134903624,https://pleroma.lamp.wtf/notice/AzrHpd6cwBAbvKWI5Y
135058195,https://pleroma.lamp.wtf/notice/AzrI1WheZJhTXaVlce
135053477,https://pleroma.lamp.wtf/notice/AzrI556P86Dd63mdkG
135098439,https://pleroma.lamp.wtf/notice/AzrICCAZFiaF2g7gxc
135415056,https://pleroma.lamp.wtf/notice/AzrIKJ4xRlyCmwMoYC
131769687,https://pleroma.lamp.wtf/notice/AzrIMStDwSCjnLuKrg
135930870,https://pleroma.lamp.wtf/notice/AzrIvNlH05FY1dq3Y8
134166845,https://pleroma.lamp.wtf/notice/AzrIwC5BuItK5tXfXM
131628099,https://pleroma.lamp.wtf/notice/AzrIyAfa8EUUI5VSCG
135659800,https://pleroma.lamp.wtf/notice/AzrJ1SgLcQJh1XQwiG
130828955,https://pleroma.lamp.wtf/notice/AzrJ2Jog4BTHoijqYS
136874996,https://pleroma.lamp.wtf/notice/AzrJ7UHoZCutjkpdOi
132366555,https://pleroma.lamp.wtf/notice/AzrJ8w8iUj7EPbGdiC
136836217,https://pleroma.lamp.wtf/notice/AzrJI1xuCjaR5OXyAC
130939583,https://pleroma.lamp.wtf/notice/AzrJIPsPIpRtFI9uvQ
130838430,https://pleroma.lamp.wtf/notice/AzrJLaTkL9mCzr8VKy
131062834,https://pleroma.lamp.wtf/notice/AzrJN9YNQ27G4J34WO
131204643,https://pleroma.lamp.wtf/notice/AzrJNxft4NphW4wmAa
131324076,https://pleroma.lamp.wtf/notice/AzrJPepm5b8Bf9Neeu
131888772,https://pleroma.lamp.wtf/notice/AzrJVVucApgtjHR96G
132113082,https://pleroma.lamp.wtf/notice/AzrJWi6YKND3pjaiyu
132796033,https://pleroma.lamp.wtf/notice/AzrJY6gKR6vWLazVgW
135789706,https://pleroma.lamp.wtf/notice/AzrJhxMxujU2MTdApc
134241114,https://pleroma.lamp.wtf/notice/AzrJn7czCWR9cpaUEK
136807296,https://pleroma.lamp.wtf/notice/AzrJvEKGBLKciPh8NM
136974077,https://pleroma.lamp.wtf/notice/AzrK38fT6NRhU5NzSi
136860070,https://pleroma.lamp.wtf/notice/AzrK38KuKp00SJlZPk
137014997,https://pleroma.lamp.wtf/notice/AzrK8IlD0OAyEYX5pw
136971031,https://pleroma.lamp.wtf/notice/AzrKAJnK8D8m1JU2zI
136916938,https://pleroma.lamp.wtf/notice/AzrKCcZnGwHmqlFlFg
131268271,https://pleroma.lamp.wtf/notice/AzrKEdPr7Zbq28Z5cG
136167612,https://pleroma.lamp.wtf/notice/AzrKOMCDzzzvWTpDaS
135930839,https://pleroma.lamp.wtf/notice/AzrKilMa8cvJMvOqrA
136441463,https://pleroma.lamp.wtf/notice/AzrKkkBrTCQsJIKWiu
136441418,https://pleroma.lamp.wtf/notice/AzrKm9LnPV4adIeBmq
136441491,https://pleroma.lamp.wtf/notice/AzrKnPNxHL98eaG0yu
136451147,https://pleroma.lamp.wtf/notice/AzrKoa3x49WM3gSZRA
136451511,https://pleroma.lamp.wtf/notice/AzrKq3GVycdmv02O9Y
136260376,https://pleroma.lamp.wtf/notice/AzrLHAAyOK1qAbNCOe
134197399,https://pleroma.lamp.wtf/notice/AzrLSu9jmLbZxaOUXg
134508073,https://pleroma.lamp.wtf/notice/AzrLh0eSQRUg9xUMlc
130265258,https://pleroma.lamp.wtf/notice/AzrLsJpLTHj0oiySYq
130301558,https://pleroma.lamp.wtf/notice/AzrLy4WDIjXp4llinw
136700760,https://pleroma.lamp.wtf/notice/AzrQT2Ilzbm2ziVD8q
136522363,https://pleroma.lamp.wtf/notice/AzrQWeZWA6GUYW3kLA
136876200,https://pleroma.lamp.wtf/notice/AzrQjAXZ85mzBB7928
136854398,https://pleroma.lamp.wtf/notice/AzrQut1o47M6LCqXxo
136830735,https://pleroma.lamp.wtf/notice/AzrQz4Jq1ofkW8H6Wm
134832890,https://pleroma.lamp.wtf/notice/AzrR9XA1eNRordfvpw
135890728,https://pleroma.lamp.wtf/notice/AzrRGuOLfzRiwOtK6q
136061504,https://pleroma.lamp.wtf/notice/AzrROIWKMfxpnm9A8G
136084279,https://pleroma.lamp.wtf/notice/AzrRcVgODyUIg6d8d6
135465155,https://pleroma.lamp.wtf/notice/AzrRsxMp3utzAnJuk4
134905511,https://pleroma.lamp.wtf/notice/AzrSCnEATEp7W8jN1E
132074079,https://pleroma.lamp.wtf/notice/AzrSEwYekdEr2CL6v2
136736446,https://pleroma.lamp.wtf/notice/AzrSPqAaqHeqPKHRGS
136046966,https://pleroma.lamp.wtf/notice/AzrScdnKAGpFn5V4EK
136763135,https://pleroma.lamp.wtf/notice/AzrSd2qN257JTm7Lwu
134571483,https://pleroma.lamp.wtf/notice/AzrSi8316zOt4DSOtU
135257351,https://pleroma.lamp.wtf/notice/AzrSnS0GLRHGPEhrPs
136858973,https://pleroma.lamp.wtf/notice/AzrT3jvZTDeIdAHNKK
136898015,https://pleroma.lamp.wtf/notice/AzrT5mWSnE1hG4VcK8
136953151,https://pleroma.lamp.wtf/notice/AzrT9gcAhUNu5r2aoq
136994127,https://pleroma.lamp.wtf/notice/AzrTGu8CqObo2eSzJI
137037471,https://pleroma.lamp.wtf/notice/AzrTIgcU3EBiiPTim8
137043440,https://pleroma.lamp.wtf/notice/AzrTIw3ydI5oc1SODA
136989167,https://pleroma.lamp.wtf/notice/AzrTOYKfmADukZwdY8
136707599,https://pleroma.lamp.wtf/notice/AzrTT47DY7pcTvnqS0
136750602,https://pleroma.lamp.wtf/notice/AzrTU5w6GWxyPz5s0W
136980948,https://pleroma.lamp.wtf/notice/AzrTWQWEi5Qypl6lKC
136815179,https://pleroma.lamp.wtf/notice/AzrTb0tnON1kp4JaTY
136928211,https://pleroma.lamp.wtf/notice/AzrThmhEayXInjfUCu
126565094,https://pleroma.lamp.wtf/notice/AzrTlmMZmBMuvTuURE
136576903,https://pleroma.lamp.wtf/notice/AzrToUkphYavBMYEZU
136589904,https://pleroma.lamp.wtf/notice/AzrTpYT3NhaYzKjy1Q
136646215,https://pleroma.lamp.wtf/notice/AzrTq1Z5CMdvEQmgwi
131192740,https://pleroma.lamp.wtf/notice/AzrU1Aa21IywNTXhrM
136948249,https://pleroma.lamp.wtf/notice/AzrU8WUow3lENMbz2u
127733116,https://pleroma.lamp.wtf/notice/AzrUEMslam0eISbDd2
126734846,https://pleroma.lamp.wtf/notice/AzrUI84sZr8vXV3gMC
127628788,https://pleroma.lamp.wtf/notice/AzrUQWJ2NfRWzzgKcS
132047954,https://pleroma.lamp.wtf/notice/AzrUanvLjTaEXHVQH2
126383042,https://pleroma.lamp.wtf/notice/AzrUcHM5nE2u6ZiZ5k
136684606,https://pleroma.lamp.wtf/notice/AzrUhtzTZkKBNUovnE
136585789,https://pleroma.lamp.wtf/notice/AzrUo1yYndNhshJZ7g
136592132,https://pleroma.lamp.wtf/notice/AzrUyin8SzBZZG4IrY
136701517,https://pleroma.lamp.wtf/notice/AzrV01hbdrtKVZ6WzQ
136871554,https://pleroma.lamp.wtf/notice/AzrV77RAiaBaK0ncSe
135972121,https://pleroma.lamp.wtf/notice/AzrVAnPd70QTNFpbiC
136835074,https://pleroma.lamp.wtf/notice/AzrVHFkMg6gWzOboZ6
136841577,https://pleroma.lamp.wtf/notice/AzrVLMsg5zqqH1SYQS
128852021,https://pleroma.lamp.wtf/notice/AzrWW0h31qkKbEerbs
136786983,https://pleroma.lamp.wtf/notice/AzrWyzSeglynAykFA8
136348934,https://pleroma.lamp.wtf/notice/AzrX0uqWommdRTpUOW
136538949,https://pleroma.lamp.wtf/notice/AzrX4u7PSw3ALMcxV2
135875117,https://pleroma.lamp.wtf/notice/AzrX7mhNVcaOCSpCHA
136014091,https://pleroma.lamp.wtf/notice/AzrXFW9ysp4xDstIrQ
134347591,https://pleroma.lamp.wtf/notice/AzrXOWLHZhfmOWTCwi
132571295,https://pleroma.lamp.wtf/notice/AzrXYXYBwBzD2OHmme
136438303,https://pleroma.lamp.wtf/notice/AzrXbXILLPpL76Iku8
135591773,https://pleroma.lamp.wtf/notice/AzrXepSKHL1eJ8Xbmq
136156799,https://pleroma.lamp.wtf/notice/AzrXkecPU6akQx2G7k
135892863,https://pleroma.lamp.wtf/notice/AzrXnxZfSpCo5oKSoK
136901727,https://pleroma.lamp.wtf/notice/AzrXoGTHCoNmhUU7zE
135743904,https://pleroma.lamp.wtf/notice/AzrXsr0lIBupBaKsbo
129911976,https://pleroma.lamp.wtf/notice/AzrXxgwY9UnjPOfkh6
135975041,https://pleroma.lamp.wtf/notice/AzrY2oKc6vPDlpMwiG
135924117,https://pleroma.lamp.wtf/notice/AzrY6NcJNPsQ4iLhTs
135842050,https://pleroma.lamp.wtf/notice/AzrY7yOa7WiaQngdKC
135824319,https://pleroma.lamp.wtf/notice/AzrY9jF7Qcum1167Cy
135781809,https://pleroma.lamp.wtf/notice/AzrYBSHdSDVNzo68UC
135780630,https://pleroma.lamp.wtf/notice/AzrYDVrr6CwHgv1M4e
135741755,https://pleroma.lamp.wtf/notice/AzrYFQOYPvCzIVE8QK
135711616,https://pleroma.lamp.wtf/notice/AzrYG57yyRJXcymymm
136039345,https://pleroma.lamp.wtf/notice/AzrYKUzGlr9OzIotFI
136042129,https://pleroma.lamp.wtf/notice/AzrYKv2hthLhnUd0DI
136860568,https://pleroma.lamp.wtf/notice/AzrYNvidq5PWlPg7Oq
136861929,https://pleroma.lamp.wtf/notice/AzrYS9BNiwTvg88Fvs
136886884,https://pleroma.lamp.wtf/notice/AzrYVE3s2axjg95SF6
136141918,https://pleroma.lamp.wtf/notice/AzrYal2eqcnTPi9pTM
128343535,https://pleroma.lamp.wtf/notice/AzrYbe8a0JDKI0Lpq4
136594577,https://pleroma.lamp.wtf/notice/AzrYjm5qJAUbHSwlXs
136630767,https://pleroma.lamp.wtf/notice/AzrYl2h64Wdf3aycRU
136222098,https://pleroma.lamp.wtf/notice/AzrYpbek1fuMeF3EYq
132279707,https://pleroma.lamp.wtf/notice/AzrYrxq8WBm21rVOam
136628371,https://pleroma.lamp.wtf/notice/AzrYtsXpB2pkBWqx4S
136424743,https://pleroma.lamp.wtf/notice/AzrYz79cHpZwwZ1hxY
136049058,https://pleroma.lamp.wtf/notice/AzrZ3UYTDzU0g7jsp6
136241440,https://pleroma.lamp.wtf/notice/AzrZ76nnTkq8AWdHoO
136766134,https://pleroma.lamp.wtf/notice/AzrZJAJWFT4KXEDfSy
135487682,https://pleroma.lamp.wtf/notice/AzrZJoLLQ6IQgTNgrg
134768936,https://pleroma.lamp.wtf/notice/AzrZLU3Bq5ZMKHgf0S
136723046,https://pleroma.lamp.wtf/notice/AzrZQKCRtJELDsKI5Y
136338270,https://pleroma.lamp.wtf/notice/AzrZV0lZZVdgOmzR68
136789734,https://pleroma.lamp.wtf/notice/AzrZcofcQcSdCTvW0u
136725318,https://pleroma.lamp.wtf/notice/AzrZdeSHtQh7oC5bSC
136979492,https://pleroma.lamp.wtf/notice/AzrZgM52fPvHgkVPXs
136979466,https://pleroma.lamp.wtf/notice/AzrZmxaO8R19kPJigi
136742688,https://pleroma.lamp.wtf/notice/AzrZog9TvQ4YFwYF6W
136958315,https://pleroma.lamp.wtf/notice/AzrZqo1vbaSjGk24em
136281560,https://pleroma.lamp.wtf/notice/AzrZrmeeCl5LICbqL2
136278781,https://pleroma.lamp.wtf/notice/AzrZtiFHZK66CHfHSi
136259979,https://pleroma.lamp.wtf/notice/AzrZvMeeoV09oWJzAu
136212777,https://pleroma.lamp.wtf/notice/AzrZwsIEfUv4ECYPHE
136482617,https://pleroma.lamp.wtf/notice/Azra1CMlyjn1dsjoYa
136373137,https://pleroma.lamp.wtf/notice/Azra2a3FP5GrOEGR3w
136345796,https://pleroma.lamp.wtf/notice/Azra5Skf05lHcPwcRU
135865709,https://pleroma.lamp.wtf/notice/Azra5fEWasmSKW0deq
136491676,https://pleroma.lamp.wtf/notice/Azra9HvrAWXTDm0PIW
135460083,https://pleroma.lamp.wtf/notice/AzraEDoJv6KXt0pi2C
136642933,https://pleroma.lamp.wtf/notice/AzraKt5zKurPfPH9Pc
135795087,https://pleroma.lamp.wtf/notice/AzraPhESs4huJzX7zs
133752127,https://pleroma.lamp.wtf/notice/AzraQFo6K5PnYMT4GO
133149003,https://pleroma.lamp.wtf/notice/AzraTeQJFykylfxXyS
132986315,https://pleroma.lamp.wtf/notice/AzraUReAFFxDQpons8
131425161,https://pleroma.lamp.wtf/notice/AzraaqNvBNqrtQGwAi
134490813,https://pleroma.lamp.wtf/notice/Azrali8IChpTU88yO0
134219690,https://pleroma.lamp.wtf/notice/Azrap78FiIAZt6kQ7M
131496664,https://pleroma.lamp.wtf/notice/Azrau9CHSmmDjx22iG
135909731,https://pleroma.lamp.wtf/notice/AzrawFMjV2NhS0vE3M
136274697,https://pleroma.lamp.wtf/notice/AzrayyTekLKtwQSdo8
136128862,https://pleroma.lamp.wtf/notice/Azrb92fxzVx9rJ1Hd2
134599714,https://pleroma.lamp.wtf/notice/AzrbEk6lwE8q0fHAv2
133280017,https://pleroma.lamp.wtf/notice/AzrbTTzy7FmYOF7eD2
130689167,https://pleroma.lamp.wtf/notice/AzrbXun2Rpq6dmBhjc
132564582,https://pleroma.lamp.wtf/notice/AzrbsBYznIUgSEHjrU
125185583,https://pleroma.lamp.wtf/notice/Azrbu8wwU0XqvXQ4UC
136869883,https://pleroma.lamp.wtf/notice/Azrby4g2JK0CplO10i
136618093,https://pleroma.lamp.wtf/notice/Azrc11hnob9OUEcVfc
135654368,https://pleroma.lamp.wtf/notice/Azrc5MYuDGrwKXWheK
134801788,https://pleroma.lamp.wtf/notice/AzrcKFDtmTUnufnSYC
136522377,https://pleroma.lamp.wtf/notice/AzrcLqt7EII11AqH2W
134536937,https://pleroma.lamp.wtf/notice/AzrcMezuvHRIQkPPaC
134517552,https://pleroma.lamp.wtf/notice/AzrcNSyZ6a4DR2A2Pw
136904026,https://pleroma.lamp.wtf/notice/AzrcQ5m7oxy4Leau9o
136118695,https://pleroma.lamp.wtf/notice/AzrcUfAMBGVLGl6kiW
136935099,https://pleroma.lamp.wtf/notice/AzrcVtuOqyUbHZEb2G`.split('\n').map(x => x.split(','));
import { downloadPixivIllust } from "./common.js";
import { postPixivIllustToMatrix, matrix } from "./matrix.js";
for (let [id, url] of missing) {
console.log(id, url);
try {
let {illust, images} = await downloadPixivIllust(id);
await postPixivIllustToMatrix(illust, images, url);
} catch (error) {
matrix.sendMessage({
room: matrix.rooms.pixiv_sfw,
body: `${error.stack}\n\n${url}`
}).catch(error => {
console.error(error.stack);
});
}
}

View File

@ -1,27 +0,0 @@
import { fetch, credentials, pixivToPleroma, known_ids } from "./common.js";
var {pixiv_cookie, pixiv_user_id} = credentials;
var new_ids = [];
top: for (var offset = 0;;) {
let url = `https://www.pixiv.net/ajax/user/${pixiv_user_id}/illusts/bookmarks?tag=&offset=${offset}&limit=100&rest=show&lang=en&version=5dc84ab282403a049abea4e2f2214b6a69d31da6`;
let data = await fetch(url, {headers: {Cookie: pixiv_cookie}}).then(res => res.json());
let ids = data.body.works.map(x => x.id);
if (!ids.length) break;
let this_page_has_known_ids = false;
for (let id of ids) {
if (id == Deno.args[0]) break top; //init empty db
if (id in known_ids) {
this_page_has_known_ids = true;
} else {
new_ids.push(id);
}
}
if (this_page_has_known_ids) break;
offset += ids.length;
}
console.log("new ids", new_ids);
for (let id of new_ids.reverse()) {
await pixivToPleroma(id);
}

207
common.js
View File

@ -1,207 +0,0 @@
import { JSZip } from "https://deno.land/x/jszip@0.11.0/mod.ts";
export async function fetch(url, options = {}, nothrow) {
console.log("fetch", url);
options.headers ||= {};
options.headers["User-Agent"] ||= "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36";
for (var i = 3; i; i--) {
try {
var res = await globalThis.fetch(url, options);
break;
} catch (error) {
console.error(error.stack);
if (i <= 1) throw error;
}
console.log("retry");
}
if (!nothrow && !res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`);
return res;
}
export var credentials = JSON.parse(Deno.readTextFileSync("credentials.json"));
var {client_id, client_secret, username, password, pixiv_cookie, access_token, pleroma_user_id} = credentials;
export var known_ids = {};
try {
known_ids = Object.fromEntries(Deno.readTextFileSync("known_ids.csv").trim().split("\n").map(line => line.split(",")));
} catch (e) {}
if (!access_token) {
let form = new FormData();
form.append("client_id", client_id);
form.append("client_secret", client_secret);
form.append("grant_type", "password");
form.append("username", username);
form.append("password", password);
let data = await fetch("https://pleroma.lamp.wtf/oauth/token", {
method: "POST",
body: form
}).then(res => res.json());
console.log ("logged in", data);
credentials.access_token = access_token = data.access_token;
Deno.writeTextFileSync("credentials.json", JSON.stringify(credentials, null, '\t'));
}
export async function getAllStatuses() {
var allStatuses = [];
await (async function getPage(max_id) {
var url = `https://pleroma.lamp.wtf/api/v1/accounts/${pleroma_user_id}/statuses?limit=40`;
if (max_id) url += `&max_id=${max_id}`;
var statuses = await fetch(url, {headers: {"Authorization": `Bearer ${access_token}`}}).then(res => res.json());
if (!statuses.length) return;
allStatuses.push(...statuses);
var last_id = statuses.at(-1).id;
await getPage(last_id);
})();
return allStatuses;
}
async function uploadFile({data, name}) {
var form = new FormData();
form.append("file", data, name);
var res = await fetch("https://pleroma.lamp.wtf/api/v1/media", {
method: "POST",
body: form,
headers: {"Authorization": `Bearer ${access_token}`}
});
var json = await res.json();
console.log("uploaded file", res.status, json.url);
return json;
}
async function postStatus({status, visibility = "unlisted", content_type = "text/plain", media_ids = [], sensitive, files, edit}) {
if (files) {
media_ids = (await Promise.all(files.map(file => uploadFile(file)))).map(d => d.id);
}
var form = new FormData();
form.append("status", status);
form.append("visibility", visibility);
form.append("source", "bot");
form.append("content_type", content_type);
for (let media_id of media_ids) {
form.append("media_ids[]", media_id);
}
if (sensitive) form.append("sensitive", "true");
var res = await fetch("https://pleroma.lamp.wtf/api/v1/statuses" + (edit ? `/${edit}` : ''), {
method: edit ? "PUT" : "POST",
body: form,
headers: {"Authorization": `Bearer ${access_token}`}
});
var json = await res.json();
console.log(edit ? "edited" : "posted", res.status, json.uri || json);
return json;
}
export async function downloadPixivIllust(illust_id) {
var url = `https://www.pixiv.net/ajax/illust/${illust_id}?lang=en`;
var res = await fetch(url, {headers: {"Cookie": pixiv_cookie}}, true);
if (!res.ok) {
console.error(res.status);
var res = await fetch(url);
}
var json = await res.json();
if (json.error) throw new Error(json.message);
var illust = json.body;
if (illust.illustType == 2) {
//ugoira
let res = await fetch(`https://www.pixiv.net/ajax/illust/${illust_id}/ugoira_meta`, {headers: {"Cookie": pixiv_cookie}});
let json = await res.json();
if (json.error) throw new Error(json.message);
let zip = await fetch(json.body.originalSrc, {headers: {"Referer": "https://www.pixiv.net/"}}).then(res => res.arrayBuffer());
let {data, width, height} = await ugoira2webp(zip, json.body.frames);
return {illust, images: [{
name: json.body.originalSrc.split('/').pop() + '.webp',
data: new Blob([data], {type: "image/webp"}),
type: "image/webp",
width, height
}]};
}
try {
let res = await fetch(`https://www.pixiv.net/ajax/illust/${illust_id}/pages`, {headers: {"Cookie": pixiv_cookie}});
let json = await res.json();
var images = json.body.map(x => ({
url: x.urls.original,
width: x.width,
height: x.height
}));
} catch (error) {
console.error(error.stack);
if (!illust.urls.original) {
console.error("missing original urls", illust.urls);
throw error;
}
var images = [];
for (let i = 0; i < illust.pageCount; i++) {
images.push({
url: illust.urls.original.replace('p0', 'p'+i)
});
}
}
for (let image of images) {
image.name = image.url.split('/').pop();
image.data = await fetch(image.url, {headers: {"Referer": "https://www.pixiv.net/"}}).then(res => res.blob());
image.type = "image/" + image.url.split('.').pop();
}
return {illust, images};
}
var decoder = new TextDecoder();
async function ugoira2webp(zip, frames) {
console.log("convert ugoira");
var tmpdir = Deno.makeTempDirSync();
var z = new JSZip();
await z.loadAsync(zip);
var webpmux_args = [];
var width, height;
for (let {file, delay} of frames) {
let file_data = await z.file(file).async("uint8array");
Deno.writeFileSync(tmpdir + "/" + file, file_data);
let output = new Deno.Command("cwebp", {
args: [file, "-o", `${file}.webp`],
cwd: tmpdir
}).outputSync();
let text = decoder.decode(output.stderr);
console.debug(text);
let match = text.match(/Dimension: (\d+) x (\d+)/);
if (match) {
width ||= Number(match[1]);
height ||= Number(match[2]);
} else console.warn("missing dimension match");
webpmux_args.push("-frame", `${file}.webp`, `+${delay}`);
}
new Deno.Command("webpmux", {
args: [...webpmux_args, "-o", "output.webp"],
cwd: tmpdir
}).outputSync();
return {
data: Deno.readFileSync(tmpdir + "/output.webp"),
width, height
}
}
export async function pixivToPleroma(illust_id, status_id) {
try {
var {illust, images} = await downloadPixivIllust(illust_id);
var {url} = await postStatus({
status: `https://www.pixiv.net/en/artworks/${illust_id}`
+ ((images.length > 4) ? `\n⚠ There are ${images.length} attachments` : ''),
files: images,
visibility: "unlisted",
sensitive: Boolean(illust.xRestrict),
edit: status_id
});
Deno.writeTextFileSync("known_ids.csv", `${illust_id},${url}\n`, {append: true});
var {postPixivIllustToMatrix} = await import("./matrix.js"); //circular dependency -.-
await postPixivIllustToMatrix(illust, images, url);
} catch (error) {
console.error(error.stack);
postStatus({
status: `https://www.pixiv.net/en/artworks/${illust_id}\n#error:\n${error.stack}`,
edit: status_id
});
}
}

View File

@ -1,85 +0,0 @@
import ky from 'https://esm.sh/ky';
import { credentials } from "./common.js";
var {matrix_token, matrix_url} = credentials;
var ke = ky.create({
hooks: {
beforeRequest: [request => console.log(`${request.method} ${request.url}`)],
afterResponse: [(_request, _options, response) => console.log(response.status)]
},
retry: {
limit: 100,
delay: attemptCount => (2 ** (attemptCount - 1)) * 1000
},
timeout: false
});
export var matrix = {
ky: ke.extend({headers: {"Authorization": `Bearer ${matrix_token}`}}),
rooms: {
default: "!mxhaBcBiEmnGxrffll:matrix.org",
pixiv_sfw: "!zStOGJAGxEaQgwxGYI:matrix.org",
pixiv_nsfw: "!HtXDHeAhEKBFGfAJTi:matrix.org"
},
async sendMessage({room = this.rooms.default, type = "m.text", body, filename, info, url, thread_id, reply_to_id}) {
var json = {msgtype: type, body, filename, info, url};
if (thread_id) json["m.relates_to"] = {
"rel_type": "m.thread",
"event_id": thread_id,
"is_falling_back": true,
"m.in_reply_to": {
"event_id": reply_to_id || thread_id
}
};
return await this.ky.put(`${matrix_url}/_matrix/client/v3/rooms/${encodeURIComponent(room)}/send/m.room.message/${Math.random().toString()}`, {json}).json();
},
async uploadFile(filename, data) {
var {content_uri} = await this.ky.post(`${matrix_url}/_matrix/media/v3/upload?filename=${encodeURIComponent(filename)}`, {body: data}).json();
return content_uri;
},
async sendImage({room = this.rooms.default, body, filename, data, info, thread_id, reply_to_id}) {
var content_uri = await this.uploadFile(filename, data);
return await this.sendMessage({room, type: "m.image", body: body || filename, filename, url: content_uri, info, thread_id, reply_to_id});
}
};
export async function postPixivIllustToMatrix(illust, images, msg) {
try {
var room = illust.xRestrict ? matrix.rooms.pixiv_nsfw : matrix.rooms.pixiv_sfw;
var thread_id;
for (var image of images) {
try {
var {event_id: last_msg_id} = await matrix.sendImage({
room,
filename: image.name,
data: image.data,
info: {
mimetype: image.data.type,
size: image.data.size,
w: image.width,
h: image.height
},
thread_id,
reply_to_id: last_msg_id
});
thread_id ||= last_msg_id;
} catch (error) {
onError(error);
}
}
await matrix.sendMessage({room, body: msg || `https://www.pixiv.net/en/artworks/${illust.id}`, thread_id, reply_to_id: last_msg_id});
} catch (error) {
onError(error);
}
function onError(error) {
console.error(error.stack);
matrix.sendMessage({
room: room || matrix.rooms.pixiv_sfw,
body: `${error.stack}\n\n${msg}`,
thread_id,
reply_to_id: last_msg_id
}).catch(error => {
console.error(error.stack);
});
}
}

View File

@ -1,38 +0,0 @@
import { fetch, credentials, pixivToPleroma, getAllStatuses } from "./common.js";
var {pixiv_cookie, pixiv_user_id} = credentials;
console.log("get all pixiv bookmarks");
var all_bookmark_ids = [];
for (var offset = 0;;) {
let url = `https://www.pixiv.net/ajax/user/${pixiv_user_id}/illusts/bookmarks?tag=&offset=${offset}&limit=100&rest=show&lang=en&version=5dc84ab282403a049abea4e2f2214b6a69d31da6`;
let data = await fetch(url, {headers: {Cookie: pixiv_cookie}}).then(res => res.json());
let works = data.body.works;
if (!works.length) break;
offset += works.length;
let ids = works.filter(w => !w.isMasked).map(x => x.id.toString());
all_bookmark_ids.push(...ids);
}
console.log(`${all_bookmark_ids.length} ummasked bookmarks`);
console.log("get all pleroma statuses");
var statuses = await getAllStatuses();
console.log(`${statuses.length} statuses`);
statuses = statuses.map(x => x.content);
var missing_ids = [];
for (let id of all_bookmark_ids.reverse()) {
if (statuses.some(status => status.includes(id) && !status.includes("#error"))) continue;
missing_ids.push(id);
}
console.log("missing_ids", missing_ids);
confirm();
for (let id of missing_ids) {
await pixivToPleroma(id);
}

View File

@ -1,13 +0,0 @@
import { getAllStatuses, pixivToPleroma } from "./common.js";
var statuses = await getAllStatuses();
statuses = statuses.filter(status => status.content.includes("#error"));
statuses = statuses.map(status => {
var pixiv_id = status.content.match(/https:\/\/www.pixiv.net\/en\/artworks\/(\d+)/)[1];
return [status.id, pixiv_id];
});
console.log(statuses.map(([s,p]) => `https://pleroma.lamp.wtf/notice/${s} => https://www.pixiv.net/en/artworks/${p}`).join("\n"));
for (let [status_id, pixiv_id] of statuses) {
await pixivToPleroma(pixiv_id, status_id);
}

View File

@ -1,51 +0,0 @@
import { pixivToPleroma } from "./common.js";
Deno.serve({
port: 18024,
hostname: "127.0.0.1"
}, async (req, info) => {
var {pathname} = new URL(req.url);
console.log(info.remoteAddr.hostname, req.headers.get('x-forwarded-for'), pathname);
try {
switch (pathname) {
case "/ajax/illusts/bookmarks/add":
var payload = await req.clone().json();
console.log(payload);
var {comment, illust_id, restrict, tags} = payload;
pixivToPleroma(illust_id);
break;
case "/ajax/illusts/bookmarks/delete":
var payload = await req.clone().formData();
console.log(payload);
// todo
break;
case "/touch/ajax_api/ajax_api.php":
var payload = await req.clone().formData();
console.log(payload);
var mode = payload.get("mode");
if (mode == "add_bookmark_illust") {
//var restrict = payload.get("restrict");
//var tag = payload.get("tag");
var id = payload.get("id");
//var comment = payload.get("comment");
pixivToPleroma(id);
} else if (mode == "delete_bookmark_illust") {
var id = payload.get("id");
// todo
}
break;
//todo mobile app
}
} catch (error) {
console.error("payload error:", error.stack);
console.debug(req.headers.get("content-type"));
}
return fetch("https://www.pixiv.net"+pathname, {
method: req.method,
headers: req.headers,
body: req.body,
redirect: "manual"
});
});