import emoji list to Rabbit

    @@ -3,7 +3,7 @@ * @description リレーからkind10030,kind30030イベントを取得してRabbitにカスタム絵文字リストをインポートする * @include https://rabbit.syusui.net/* * @license CC0 1.0 - * @require + * @require */ (async () => { @@ -14,7 +14,7 @@ let relayUrl = 'wss://relay-jp.nostr.wirednet.jp'; const getPubkey = async () => { - let pubkey;//Node.jsでデバッグする際はここに初期値を入れてください。無ければ最新の誰かのイベントで代用します。 + let pubkey; //Node.jsでデバッグする際はここに初期値を入れてください。無ければ最新の誰かのイベントで代用します。 const nostr = globalThis.window?.nostr; if (nostr?.getPublicKey) { try { @@ -35,34 +35,36 @@ const req = [ 'REQ', subscription_id, - pubkey ? { 'kinds': [10030], 'authors': [pubkey] } : { 'kinds': [10030], 'limit': 1 } + pubkey ? { kinds: [10030], authors: [pubkey] } : { kinds: [10030], limit: 1 } ]; ws.send(JSON.stringify(req)); }; ws.onmessage = (e) => { const msg = JSON.parse(e.data); - switch ( msg[0] ) { - case 'EVENT': - res = msg[2]; - break; - case 'EOSE': - ws.send(JSON.stringify(['CLOSE', subscription_id])); - ws.close(); - resolve(res); - break; - default: - console.log(msg); - break; + switch (msg[0]) { + case 'EVENT': + res = msg[2]; + break; + case 'EOSE': + ws.send(JSON.stringify(['CLOSE', subscription_id])); + ws.close(); + resolve(res); + break; + default: + console.log(msg); + break; } }; ws.onerror = () => { console.error('failed to connect'); - } + }; }); }; const getEmojiList = async (ev10030) => { - const atags = ev10030.tags.filter(tag => tag.length >= 2 && tag[0] === 'a').map(tag => tag[1]); + const atags = ev10030.tags + .filter((tag) => tag.length >= 2 && tag[0] === 'a') + .map((tag) => tag[1]); if (atags.length === 0) { return []; } @@ -73,7 +75,9 @@ } const sliceByNumber = (array, number) => { const length = Math.ceil(array.length / number); - return new Array(length).fill(undefined).map((_, i) => array.slice(i * number, (i + 1) * number)); + return new Array(length) + .fill(undefined) + .map((_, i) => array.slice(i * number, (i + 1) * number)); }; let emojiMap = new Map(); for (const filterGroup of sliceByNumber(filters, 10)) { @@ -85,43 +89,40 @@ const ws = new WebSocket(relayUrl); const subscription_id = 'getemojiinrabbit'; ws.onopen = () => { - const req = [ - 'REQ', - subscription_id, - ...filters - ]; + const req = ['REQ', subscription_id, ...filters]; ws.send(JSON.stringify(req)); }; ws.onmessage = (e) => { const msg = JSON.parse(e.data); - switch ( msg[0] ) { - case 'EVENT': - for (const tag of msg[2].tags.filter(tag => tag.length >= 2 && tag[0] === 'emoji')) { - let key = tag[1]; - while (emojiMap.has(key)) { - key += '_'; + switch (msg[0]) { + case 'EVENT': + for (const tag of msg[2].tags.filter( + (tag) => tag.length >= 2 && tag[0] === 'emoji' + )) { + let key = tag[1]; + while (emojiMap.has(key)) { + key += '_'; + } + key = key.replaceAll('-', '_'); + if (/\W/.test(key)) continue; + emojiMap.set(key, tag[2]); } - key = key.replaceAll('-', '_'); - if (/\W/.test(key)) - continue; - emojiMap.set(key, tag[2]); - } - break; - case 'EOSE': - ws.send(JSON.stringify(['CLOSE', subscription_id])); - ws.close(); - resolve(); - break; - default: - console.log(msg); - break; + break; + case 'EOSE': + ws.send(JSON.stringify(['CLOSE', subscription_id])); + ws.close(); + resolve(); + break; + default: + console.log(msg); + break; } }; ws.onerror = () => { console.error('failed to connect'); - } + }; }); - }; + } }; const main = async () => { @@ -157,10 +158,16 @@ for (const [key, value] of emojiMap) { if (config.customEmojis[key] === undefined) { config.customEmojis[key] = { shortcode: key, url: value }; - } - else if (config.customEmojis[key].shortcode === key && config.customEmojis[key].url !== value) { + } else if ( + config.customEmojis[key].shortcode === key && + config.customEmojis[key].url !== value + ) { let newkey = key; - while (config.customEmojis[newkey].shortcode === newkey && config.customEmojis[newkey].url !== value) { + while ( + config.customEmojis[newkey] !== undefined && + config.customEmojis[newkey].shortcode === newkey && + config.customEmojis[newkey].url !== value + ) { newkey += '_'; } config.customEmojis[newkey] = { shortcode: newkey, url: value }; @@ -168,8 +175,7 @@ } localStorage['RabbitConfig'] = JSON.stringify(config); alert('Complete. Please reload by yourself.'); - } - else { + } else { console.log(emojiMap); console.log('Complete.'); }
  • /*
     * @title import emoji list to Rabbit
     * @description リレーからkind10030,kind30030イベントを取得してRabbitにカスタム絵文字リストをインポートする
     * @include https://rabbit.syusui.net/*
     * @license CC0 1.0
     * @require
     */
    
    (async () => {
    	if (typeof window === 'undefined') {
    		await import('websocket-polyfill');
    	}
    
    	let relayUrl = 'wss://relay-jp.nostr.wirednet.jp';
    
    	const getPubkey = async () => {
    		let pubkey; //Node.jsでデバッグする際はここに初期値を入れてください。無ければ最新の誰かのイベントで代用します。
    		const nostr = globalThis.window?.nostr;
    		if (nostr?.getPublicKey) {
    			try {
    				pubkey = await nostr.getPublicKey();
    			} catch (error) {
    				console.warn(error);
    			}
    		}
    		return pubkey;
    	};
    
    	const getEvent10030 = async (pubkey) => {
    		return new Promise((resolve) => {
    			const ws = new WebSocket(relayUrl);
    			const subscription_id = 'getemojilistinrabbit';
    			let res;
    			ws.onopen = () => {
    				const req = [
    					'REQ',
    					subscription_id,
    					pubkey ? { kinds: [10030], authors: [pubkey] } : { kinds: [10030], limit: 1 }
    				];
    				ws.send(JSON.stringify(req));
    			};
    			ws.onmessage = (e) => {
    				const msg = JSON.parse(e.data);
    				switch (msg[0]) {
    					case 'EVENT':
    						res = msg[2];
    						break;
    					case 'EOSE':
    						ws.send(JSON.stringify(['CLOSE', subscription_id]));
    						ws.close();
    						resolve(res);
    						break;
    					default:
    						console.log(msg);
    						break;
    				}
    			};
    			ws.onerror = () => {
    				console.error('failed to connect');
    			};
    		});
    	};
    
    	const getEmojiList = async (ev10030) => {
    		const atags = ev10030.tags
    			.filter((tag) => tag.length >= 2 && tag[0] === 'a')
    			.map((tag) => tag[1]);
    		if (atags.length === 0) {
    			return [];
    		}
    		const filters = [];
    		for (const atag of atags) {
    			const ary = atag.split(':');
    			filters.push({ kinds: [parseInt(ary[0])], authors: [ary[1]], '#d': [ary[2]] });
    		}
    		const sliceByNumber = (array, number) => {
    			const length = Math.ceil(array.length / number);
    			return new Array(length)
    				.fill(undefined)
    				.map((_, i) => array.slice(i * number, (i + 1) * number));
    		};
    		let emojiMap = new Map();
    		for (const filterGroup of sliceByNumber(filters, 10)) {
    			await getEvent30030(filterGroup);
    		}
    		return emojiMap;
    		async function getEvent30030(filters) {
    			return new Promise((resolve) => {
    				const ws = new WebSocket(relayUrl);
    				const subscription_id = 'getemojiinrabbit';
    				ws.onopen = () => {
    					const req = ['REQ', subscription_id, ...filters];
    					ws.send(JSON.stringify(req));
    				};
    				ws.onmessage = (e) => {
    					const msg = JSON.parse(e.data);
    					switch (msg[0]) {
    						case 'EVENT':
    							for (const tag of msg[2].tags.filter(
    								(tag) => tag.length >= 2 && tag[0] === 'emoji'
    							)) {
    								let key = tag[1];
    								while (emojiMap.has(key)) {
    									key += '_';
    								}
    								key = key.replaceAll('-', '_');
    								if (/\W/.test(key)) continue;
    								emojiMap.set(key, tag[2]);
    							}
    							break;
    						case 'EOSE':
    							ws.send(JSON.stringify(['CLOSE', subscription_id]));
    							ws.close();
    							resolve();
    							break;
    						default:
    							console.log(msg);
    							break;
    					}
    				};
    				ws.onerror = () => {
    					console.error('failed to connect');
    				};
    			});
    		}
    	};
    
    	const main = async () => {
    		relayUrl = window.prompt('Input relay URL.', relayUrl);
    		if (!URL.canParse(relayUrl)) {
    			console.warn(`Invalid URL: ${relayUrl}`);
    			return;
    		}
    		let pubkey;
    		try {
    			pubkey = await getPubkey();
    		} catch (error) {
    			console.warn(error);
    			return;
    		}
    		if (globalThis.window && !pubkey) {
    			console.warn('pubkey is empty.');
    			return;
    		}
    		let ev10030;
    		try {
    			ev10030 = await getEvent10030(pubkey);
    		} catch (error) {
    			console.warn(error);
    			return;
    		}
    		if (!ev10030) {
    			return;
    		}
    		const emojiMap = await getEmojiList(ev10030);
    		if (globalThis.window) {
    			const config = JSON.parse(localStorage['RabbitConfig']);
    			for (const [key, value] of emojiMap) {
    				if (config.customEmojis[key] === undefined) {
    					config.customEmojis[key] = { shortcode: key, url: value };
    				} else if (
    					config.customEmojis[key].shortcode === key &&
    					config.customEmojis[key].url !== value
    				) {
    					let newkey = key;
    					while (
    						config.customEmojis[newkey] !== undefined &&
    						config.customEmojis[newkey].shortcode === newkey &&
    						config.customEmojis[newkey].url !== value
    					) {
    						newkey += '_';
    					}
    					config.customEmojis[newkey] = { shortcode: newkey, url: value };
    				}
    			}
    			localStorage['RabbitConfig'] = JSON.stringify(config);
    			alert('Complete. Please reload by yourself.');
    		} else {
    			console.log(emojiMap);
    			console.log('Complete.');
    		}
    	};
    
    	main();
    })();
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2024/12/20 06:26:29 - 2024-12-20
  2. 2024/07/21 07:39:07 - 2024-07-21
  3. 2024/07/19 20:04:18 - 2024-07-19
  4. 2024/07/15 14:08:41 - 2024-07-15
  5. 2024/03/06 09:57:11 - 2024-03-06
  6. 2024/03/06 09:15:02 - 2024-03-06
  7. 2024/03/05 22:42:47 - 2024-03-05
  8. 2024/03/05 20:50:04 - 2024-03-05