import mute list to Rabbit
by
Nikola
08/21 [2025/08/21 08:18:27]
リレーからkind10000イベントを取得してRabbitにミュートリストをインポートする
@@ -3,7 +3,7 @@
* @description リレーからkind10000イベントを取得して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 {
@@ -32,54 +32,63 @@
const subscription_id = 'getmutelistinrabbit';
let res;
ws.onopen = () => {
- const req = [
- 'REQ',
- subscription_id,
- pubkey ? { 'kinds': [10000], 'authors': [pubkey] } : { 'kinds': [10000], 'limit': 1 }
- ];
+ const req = ['REQ', subscription_id, pubkey ? { kinds: [10000], authors: [pubkey] } : { kinds: [10000], 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 getMuteList = async (event, pubkey) => {
- let mutedPubkeys = event.tags.filter(tag => tag.length >= 2 && tag[0] === 'p').map(tag => tag[1]) ?? [];
- let mutedChannels = event.tags.filter(tag => tag.length >= 2 && tag[0] === 'e').map(tag => tag[1]) ?? [];
- let mutedWords = event.tags.filter(tag => tag.length >= 2 && tag[0] === 'word').map(tag => tag[1]) ?? [];
- let mutedHashtags = event.tags.filter(tag => tag.length >= 2 && tag[0] === 't').map(tag => tag[1]) ?? [];
+ const getDecrypt = (content) => {
const nostr = globalThis.window?.nostr;
- if (event.content && nostr?.nip04?.decrypt) {
- try {
- const content = await nostr.nip04.decrypt(pubkey, event.content);
- const list = JSON.parse(content);
- mutedPubkeys = mutedPubkeys.concat(list.filter(tag => tag.length >= 2 && tag[0] === 'p').map(tag => tag[1]));
- mutedChannels = mutedChannels.concat(list.filter(tag => tag.length >= 2 && tag[0] === 'e').map(tag => tag[1]));
- mutedWords = mutedWords.concat(list.filter(tag => tag.length >= 2 && tag[0] === 'word').map(tag => tag[1]));
- mutedHashtags = mutedHashtags.concat(list.filter(tag => tag.length >= 2 && tag[0] === 't').map(tag => tag[1]));
- } catch (error) {
- console.warn(error);
+ const isNIP04 = content.includes('?iv=');
+ if (isNIP04 && nostr?.nip04?.decrypt !== undefined) {
+ return nostr.nip04.decrypt;
+ } else if (nostr?.nip44?.decrypt !== undefined) {
+ return nostr.nip44.decrypt;
+ }
+ return null;
+ };
+
+ const getMuteList = async (event, pubkey) => {
+ let mutedPubkeys = event.tags.filter((tag) => tag.length >= 2 && tag[0] === 'p').map((tag) => tag[1]) ?? [];
+ let mutedChannels = event.tags.filter((tag) => tag.length >= 2 && tag[0] === 'e').map((tag) => tag[1]) ?? [];
+ let mutedWords = event.tags.filter((tag) => tag.length >= 2 && tag[0] === 'word').map((tag) => tag[1]) ?? [];
+ let mutedHashtags = event.tags.filter((tag) => tag.length >= 2 && tag[0] === 't').map((tag) => tag[1]) ?? [];
+ if (event.content.length > 0) {
+ const decrypt = getDecrypt(event.content);
+ if (decrypt !== null) {
+ try {
+ const content = await decrypt(pubkey, event.content);
+ const list = JSON.parse(content);
+ mutedPubkeys = mutedPubkeys.concat(list.filter((tag) => tag.length >= 2 && tag[0] === 'p').map((tag) => tag[1]));
+ mutedChannels = mutedChannels.concat(list.filter((tag) => tag.length >= 2 && tag[0] === 'e').map((tag) => tag[1]));
+ mutedWords = mutedWords.concat(list.filter((tag) => tag.length >= 2 && tag[0] === 'word').map((tag) => tag[1]));
+ mutedHashtags = mutedHashtags.concat(list.filter((tag) => tag.length >= 2 && tag[0] === 't').map((tag) => tag[1]));
+ } catch (error) {
+ console.warn(error);
+ }
}
}
- return [mutedPubkeys, Array.from(new Set(mutedWords.concat(mutedHashtags.map(t => '#' + t)))), mutedChannels];
+ return [mutedPubkeys, Array.from(new Set(mutedWords.concat(mutedHashtags.map((t) => '#' + t)))), mutedChannels];
};
const main = async () => {
@@ -114,9 +123,8 @@
config.mutedThreads = Array.from(new Set([...config.mutedThreads, ...mutedChannelList]));
localStorage['RabbitConfig'] = JSON.stringify(config);
alert('Complete. Please reload by yourself.');
- }
- else {
- console.log({ mutedPubkeysList, mutedKeywordsList});
+ } else {
+ console.log({ mutedPubkeysList, mutedKeywordsList });
console.log('Complete.');
}
};
/*
* @title import mute list to Rabbit
* @description リレーからkind10000イベントを取得して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 getEvent10000 = async (pubkey) => {
return new Promise((resolve) => {
const ws = new WebSocket(relayUrl);
const subscription_id = 'getmutelistinrabbit';
let res;
ws.onopen = () => {
const req = ['REQ', subscription_id, pubkey ? { kinds: [10000], authors: [pubkey] } : { kinds: [10000], 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 getDecrypt = (content) => {
const nostr = globalThis.window?.nostr;
const isNIP04 = content.includes('?iv=');
if (isNIP04 && nostr?.nip04?.decrypt !== undefined) {
return nostr.nip04.decrypt;
} else if (nostr?.nip44?.decrypt !== undefined) {
return nostr.nip44.decrypt;
}
return null;
};
const getMuteList = async (event, pubkey) => {
let mutedPubkeys = event.tags.filter((tag) => tag.length >= 2 && tag[0] === 'p').map((tag) => tag[1]) ?? [];
let mutedChannels = event.tags.filter((tag) => tag.length >= 2 && tag[0] === 'e').map((tag) => tag[1]) ?? [];
let mutedWords = event.tags.filter((tag) => tag.length >= 2 && tag[0] === 'word').map((tag) => tag[1]) ?? [];
let mutedHashtags = event.tags.filter((tag) => tag.length >= 2 && tag[0] === 't').map((tag) => tag[1]) ?? [];
if (event.content.length > 0) {
const decrypt = getDecrypt(event.content);
if (decrypt !== null) {
try {
const content = await decrypt(pubkey, event.content);
const list = JSON.parse(content);
mutedPubkeys = mutedPubkeys.concat(list.filter((tag) => tag.length >= 2 && tag[0] === 'p').map((tag) => tag[1]));
mutedChannels = mutedChannels.concat(list.filter((tag) => tag.length >= 2 && tag[0] === 'e').map((tag) => tag[1]));
mutedWords = mutedWords.concat(list.filter((tag) => tag.length >= 2 && tag[0] === 'word').map((tag) => tag[1]));
mutedHashtags = mutedHashtags.concat(list.filter((tag) => tag.length >= 2 && tag[0] === 't').map((tag) => tag[1]));
} catch (error) {
console.warn(error);
}
}
}
return [mutedPubkeys, Array.from(new Set(mutedWords.concat(mutedHashtags.map((t) => '#' + t)))), mutedChannels];
};
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 ev10000;
try {
ev10000 = await getEvent10000(pubkey);
} catch (error) {
console.warn(error);
return;
}
const [mutedPubkeysList, mutedKeywordsList, mutedChannelList] = await getMuteList(ev10000, pubkey);
if (globalThis.window) {
const config = JSON.parse(localStorage['RabbitConfig']);
config.mutedPubkeys = Array.from(new Set([...config.mutedPubkeys, ...mutedPubkeysList]));
config.mutedKeywords = Array.from(new Set([...config.mutedKeywords, ...mutedKeywordsList]));
config.mutedThreads = Array.from(new Set([...config.mutedThreads, ...mutedChannelList]));
localStorage['RabbitConfig'] = JSON.stringify(config);
alert('Complete. Please reload by yourself.');
} else {
console.log({ mutedPubkeysList, mutedKeywordsList });
console.log('Complete.');
}
};
main();
})();
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。