Compare commits
	
		
			No commits in common. "master" and "to-matrix" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,2 +0,0 @@
 | 
			
		||||
credentials.json
 | 
			
		||||
known_ids.csv
 | 
			
		||||
							
								
								
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@ -1,4 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
	"deno.enable": true,
 | 
			
		||||
	"deno.lint": false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										113
									
								
								app.deno.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								app.deno.js
									
									
									
									
									
										Normal 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);
 | 
			
		||||
}
 | 
			
		||||
@ -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);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								catchup.js
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								catchup.js
									
									
									
									
									
								
							@ -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
									
									
									
									
									
								
							
							
						
						
									
										207
									
								
								common.js
									
									
									
									
									
								
							@ -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
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								matrix.js
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								matrix.js
									
									
									
									
									
								
							@ -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);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								missing.js
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								missing.js
									
									
									
									
									
								
							@ -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);
 | 
			
		||||
}
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								server.js
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								server.js
									
									
									
									
									
								
							@ -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"
 | 
			
		||||
	});
 | 
			
		||||
});
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user