Mastodon 連合 or ローカルタイムライン用正規表現フィルタ Fork

    @@ -37,6 +37,9 @@ 更新履歴: + 4/30 + -HTML の構造が変わっていたので追従しました。 + 4/27 -インスタンス名とアカウント名も検索対象になりました。「\tpawoo.net/@pacochi」というような文字列が追加されます。
    @@ -56,7 +59,7 @@ -名前も検索される文字列に含まれます。 */ - ((d = document, l = { childList: 1 }, p = d.querySelector('.columns-area'), r, x, a, f, o, c, b, i, t, m) => { + ((d = document, l = { childList: 1 }, p = d.querySelector('.columns-area>div:nth-child(4)'), k = new Map(), r, x, a, f, o, c, b, i, t, m) => { r = new RegExp( decodeURIComponent((d.cookie.split('let_filter_regexp=')[1] || '').split(';')[0])
    @@ -79,7 +82,7 @@ }); m = n.querySelector('.media-spoiler') ? '\tsensitive\tmedia' : ''; - [...n.querySelectorAll('a[href*=media_attachments], video')].forEach(a => { + [...n.querySelectorAll('a.media-gallery__item-thumbnail, video')].forEach(a => { m += '\tmedia' + ((a.href || a.src).match(/(\.\w+)(?:\?|$)/) || [''])[0];
    @@ -87,7 +90,7 @@ if (r.test( n.querySelector('.display-name').textContent - + '\t' + n.querySelector('.status__display-name').href.replace(/^https?:\/\//, '') + + '\t' + n.querySelector('.status__relative-time').href.replace(/^https?:\/\/|\/\d+$/g, '') + '\t' + n.querySelector('.status__content').textContent + m )) n.style.display = 'none';
    @@ -121,8 +124,15 @@ f = n => { - n = d.querySelector('.column:nth-child(4)>.scrollable>div:last-child'); + n = p.querySelector('.mastodon-column-container[aria-hidden="false"]'); + if (n) { + + if (!k.get(n)) k.set(n, new MutationObserver(s => f()).observe(n, { attributes: 1 })); + n = n.querySelector('.status-list'); + + } + if ((!t || t != n) && n) { t = n;
    @@ -138,7 +148,7 @@ c = d.getElementById('mute-buttons'); if (!c) c = p.appendChild(Object.assign(d.createElement('div'), { id: 'mute-buttons', - style: 'position: fixed; height: 1em; bottom: 2em; right: 0; z-index: 99' + style: 'position: fixed; height: 1em; bottom: 2em; right: 0; z-index: 999' })); b = c.appendChild(Object.assign(d.createElement('button'), {
    @@ -182,6 +192,6 @@ }); f(); - new MutationObserver(s => s.forEach(f)).observe(p, l); + new MutationObserver(s => f()).observe(p, l); })();
  • /*
     * @title Mastodon 連合 or ローカルタイムライン用正規表現フィルタ
     * @description 名前にも適用されます。画像とか動画とか不適切系も判別できます。
     * @include *
     * @license MIT License
     * @javascript_url
     */
    
    /*
    ご多分に漏れず危険性を熟知なり覚悟なりして自己責任で使うタイプのものです。
    ブックマークレットを実行すると入力欄とボタンが出ます。
    入力欄に正規表現を入れてエンターを押してください。ボタンはフィルタのオンオフです。
    諸事情あって、ブックマークレットは自動更新されません。
    新しいバージョンに変更したい場合は、一旦古いブックマークレットを削除して、新しく追加し直してください。
    入力した正規表現は Cookie に保存されます。他のブックマークレット等から覗かれる可能性もゼロではないので、気になる場合は使用を控えるか、Fork して覗けないような仕組みを追加してください。
    
    入力例:
    
    たけのこに関するトゥートを NG
    たけのこ|タケノコ|竹の子|筍
    たけのこに関するトゥートのみ表示
    ^(?![\s\S]*(たけのこ|タケノコ|竹の子|筍))
    不適切なコンテンツを NG
    sensitive
    不適切なコンテンツのみ表示
    ^(?![\s\S]*sensitive)
    画像、動画のみ表示
    ^(?![\s\S]*media)
    画像、動画のみ表示 (誤爆なし)
    ^(?![\s\S]*	media)
    PNG のみ表示 (イラスト多めになる)
    ^(?![\s\S]*media\.png)
    動画 (GIFアニメ含む) のみ表示
    ^(?![\s\S]*media\.mp4)
    mstdn.jp からのトゥートのみ表示
    ^(?![\s\S]*mstdn\.jp)
    
    更新履歴:
    
    4/30
    -HTML の構造が変わっていたので追従しました。
    
    4/27
    -インスタンス名とアカウント名も検索対象になりました。「\tpawoo.net/@pacochi」というような文字列が追加されます。
    
    4/26
    -https://addons.mozilla.org/ja/firefox/addon/bookmarklets-context-menu/
     を使うと Firefox でも mstdn.jp 等での利用ができるみたいなので、その辺の調整をしました。
     jQuery を使うとエラーが出てくるみたいなのでプレーンにしました。
    
    4/24
    -正規表現入力欄が入力後に隠れるようになりました。クリックするとまた出てきます。
    -フィルタが効かなくなる現象の出現頻度が低くなりました。
    -画像や動画がある場合、検索される文字列に「\tmedia」という文字列が追加されます。拡張子が判別できたら「\tmedia.png」のような文字列になります。
    -不適切なコンテンツがある場合、検索される文字列に「\tsensitive」という文字列が追加されます。「\t」はタブ文字です。
    
    4/22
    -https://mstdn.jp/users/soraki_yoshiko2/updates/1277707 こういう経緯で作りました。
    -名前も検索される文字列に含まれます。
    */
    
    ((d = document, l = { childList: 1 }, p = d.querySelector('.columns-area>div:nth-child(4)'), k = new Map(), r, x, a, f, o, c, b, i, t, m) => {
    
    	r = new RegExp(
    	 decodeURIComponent((d.cookie.split('let_filter_regexp=')[1] || '').split(';')[0])
    	 || 'きのこ|たけのこ|すぎのこ', 'i'
    	);
    
    	x = e => {
    
    		[...e.target.querySelectorAll('.status:not(.viewed)')].forEach(n => {
    
    			[...n.querySelectorAll('img[alt]')].forEach(i => {
    				
    				i.parentNode.insertBefore(Object.assign(
    				 d.createElement('span'), {
    				  style: 'display: none;',
    				  textContent: i.alt
    				 }
    				), i);
    				
    			});
    
    			m = n.querySelector('.media-spoiler') ? '\tsensitive\tmedia' : '';
    			[...n.querySelectorAll('a.media-gallery__item-thumbnail, video')].forEach(a => {
    				
    				m += '\tmedia' + ((a.href || a.src).match(/(\.\w+)(?:\?|$)/) || [''])[0];
    				
    			});
    
    			if (r.test(
    			 n.querySelector('.display-name').textContent
    			 + '\t' + n.querySelector('.status__relative-time').href.replace(/^https?:\/\/|\/\d+$/g, '')
    			 + '\t' + n.querySelector('.status__content').textContent + m
    			)) n.style.display = 'none';
    			
    			n.className += ' viewed';
    
    		});
    
    	};
    
    	a = s => {
    
    		if (s == '🔈') {
    
    			b.textContent = '🔇';
    			x({ target: t });
    			o.observe(t, l);
    
    		} else {
    
    			b.textContent = '🔈';
    			o.disconnect();
    			if (t) [...t.querySelectorAll('.status')].forEach(n => {
    
    				n.className = 'status';
    				n.style.display = '';
    
    			});
    		}
    
    	};
    
    	f = n => {
    
    		n = p.querySelector('.mastodon-column-container[aria-hidden="false"]');
    
    		if (n) {
    
    			if (!k.get(n)) k.set(n, new MutationObserver(s => f()).observe(n, { attributes: 1 }));
    			n = n.querySelector('.status-list');
    
    		}
    
    		if ((!t || t != n) && n) {
    
    			t = n;
    			a('🔇');
    			a('🔈');
    
    		}
    
    	};
    
    	o = new MutationObserver(s => s.forEach(x));
    
    	c = d.getElementById('mute-buttons');
    	if (!c) c = p.appendChild(Object.assign(d.createElement('div'), {
    	 id: 'mute-buttons',
    	 style: 'position: fixed; height: 1em; bottom: 2em; right: 0; z-index: 999'
    	}));
    
    	b = c.appendChild(Object.assign(d.createElement('button'), {
    	 textContent: '🔈'
    	}));
    	b.addEventListener('click', e => a(b.textContent));
    
    	i = c.appendChild(Object.assign(d.createElement('input'), {
    	 value: r.source,
    	 style: 'width: 12em'
    	}));
    	i.addEventListener('change', (e, s) => {
    
    		s = e.target.value;
    		a('🔇');
    
    		if (s.length) {
    
    			try { s = new RegExp(s); } catch(e) {}
    
    			if (typeof s == 'object') {
    
    				r = s;
    				d.cookie = `let_filter_regexp=${encodeURIComponent(r.source)}; path=\x2F; expires=Tue, 19 Jan 2038 03:14:07 GMT`;
    				a('🔈');
    
    			}
    
    		}
    
    	});
    	i.addEventListener('focus', e => {
    
    		e.target.style = 'padding-left: 0; width: 12em';
    
    	});
    	i.addEventListener('blur', e => {
    
    		e.target.style = 'padding-left: 2em; width: 0';
    
    	});
    
    	f();
    	new MutationObserver(s => f()).observe(p, l);
    
    })();
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。