Skip to content

Instantly share code, notes, and snippets.

@irhdevel
Last active July 25, 2023 05:36
Show Gist options
  • Save irhdevel/82e0ef6907ba7be26b4eec5edf67470d to your computer and use it in GitHub Desktop.
Save irhdevel/82e0ef6907ba7be26b4eec5edf67470d to your computer and use it in GitHub Desktop.
EmojiSuggest - Misskey

🗃️ Readme - 読んでください。本当に。

Gist上での更新を終了しています。 新規インストールの方はGithubからイントールしてください。\

[!NOTE]
Misskey/Firefishのアップデートで使えなくなる場合が予想されます。
その場合はこのページで再度インストールを行ってUserScriptをアップデートしても改善しなければ、すぐにこのUserScriptを無効化してください。
誤動作の恐れがあり危険です

アップデートはTempermonkeyのダッシュボードもしくはアイコンから可能です。
自動更新がされる場合もあります。
アップデート後は再度Tempermonkeyの設定から使用中のインスタンスのURLを指定する必要がある場合があります。参考


🌟 EmojiSuggest for Misskey v13

※割とやばい処理の書き方です(既存のDOMに勝手に属性をつけて汚すなどをしています)。注意を読んでください。※

  • Milkteaのように、Misskeyで自分の居るインスタンスにない絵文字をクリックした際、検索欄に絵文字名を入力し類似の絵文字を検索します。
  • ご自分のインスタンスをmatchに設定するなどしてからご利用ください(Tempermonkyの設定を開き、利用するインスタンスのアドレスを追加)。

⚠️ 危険性 - とても大切です

このReadme及び同時に提供されるemoji_suggest_GPL.user.jsなどはライセンスはGPLv3です無保証で提供されます!!!!

  • つまり、このUserScriptを書いたIrihiは、このUserScriptを使用したことで利用者に生じたいかなる損害に対しても一切責任を取ることができません。
  • 冒頭に書いたとおりかなりやばい書き方なのでソースコードを一度読んで処理内容を把握することをおすすめします。
  • 勝手にボタンを押す機能、勝手に入力する機能があります
    • おそらくランダム生成されるであろうタグ名を使用してDOMを取得している部分があります
    • Misskeyの仕様でこのタグのクラス名はなかなか変わらないものであるということが言われていますが、これがかわってしまった際に意図しないボタンを押すことがあるかもしれません。
  • これらの特性により、Misskey/Firefishのアップデートによって勝手に意味不明のノートをしてしまったり、
    • もしも今後のアップデートで課金機能が導入されたとしたら、誤動作で課金ボタンを押してしまう恐れさえあります
  • また、今後のアップデートにより簡単に動かなくなってしまう可能性が大きいです。
  • Misskeyそのものを使えなくしてしまう可能性もあります。
  • またDOMの変更があったら毎回関数を読んでいるので、必要ない処理は減らしているものの、おそらく大きなパフォーマンスの低下があります。

🚀 動作環境

検証はFirefoxでしか行っていません。
Tempermonkeyのみの対応です。
他では動作検証しておらず危険ですので使わないことを強くおすすめします。

✅ インストール、有効化

Gist上での更新を終了しています。 新規インストールの方はGithubからイントールしてください。\

📜 Changelog

変更履歴です。

  • 0.1 - 公開
  • 0.2 - 英語環境でしか動かなかった問題を修正
    重くなっていた原因、クラスが何も指定されてないオブジェクトをスルーするようにした。
  • 0.2.1 - 同意しなくても同意されているとして処理されていたので修正
  • 0.2.2 - 4回行っていたforループを一回に減らして軽量化、エラーダイアログの再利用を可能にした、既存のタグの属性にリスナ付与済みかどうかを追加する際のもともとの動作に干渉する確率を減らした
  • 0.2.3 - Firefish版を追加。Firefish用に最適化したもので、このバージョンはFirefish専用です。
  • 0.2.4 - Misskey版のアップデートURLを更新しました。
    今後はこのリポジトリのものがアップデートされます。Misskey専用のバージョンです。
  • 0.2.5 - Firefish版のアップデートURLを更新しました。Firefish専用のバージョンです。
  • 0.2.6 - バージョンを間違えて公開してしまったため、アップデートさせるためにバージョン番号のみ更新しました。
// ==UserScript==
// @name EmojiSuggest - Misskey
// @namespace irihi_design
// @version 0.2.6
// @description ※割とやばい処理の書き方です※ - Misskeyで自分の居るインスタンスにない絵文字をクリックした際、検索欄に絵文字名を入力し類似の絵文字を検索します。ご自分のインスタンスをmatchに設定するなどしてからご利用ください。
// @author Irihi_design
// @match https://misskey.io/*
// @grant none
// @run-at document-idle
// @updateURL https://github.com/irhdevel/EmojiSuggest/raw/main/GPL_emoji_suggest_for_misskey.user.js
// @downloadURL https://github.com/irhdevel/EmojiSuggest/raw/main/GPL_emoji_suggest_for_misskey.user.js
// @supportURL https://github.com/irhdevel/EmojiSuggest
// ==/UserScript==
(function() {
let agree = false;
// 表示されてるサイトでどれでも良いけど何かしらのDOMが変更されたとき毎回毎回Check関数を実行(なのですごい実行することになる、やばい実装だと思う。)
// ただSPAだし、どのDOMを監視すべきなのか、どのDOMがいつ作成されるかわかんない問題とかあるから、どうすればいいかわかんないしこうしておく
if(agree){(new MutationObserver(check)).observe(document, {childList: true, subtree: true})}else{alert("このダイアログはEmojiSuggestにより表示されています。\n現在EmojiSuggestは無効状態です\n無保証で提供されていること、危険性を理解した上で、Readmeに書いてある方法を読み有効化してください")};
// すでにインスタンスに存在しない絵文字に対しリスナを設定済みかどうか確認(付与済みかどうかはset_onclick属性がついてるかどうかで判断、つまりこのUserScriptは勝手に既存のHTML要素に属性を追加してそれを後の判断材料にしまう!これってやばい???)
// 確認のあと、付与されていないようであればリスナを付与
function setOnclickAttr(info){
// デバッグ用(必要以上にこの関数が呼ばれてないか(まあ呼ばれてるんだけど)一応チェック)
//console.log("ノートの受信が感知されたため、別インスタンス絵文字変換用のUserScriptの関数が呼ばれました")
let emojielems = document.querySelectorAll(".xDRXD._button:not(.xhTzr)")
emojielems.forEach(function(e){
let elem = e
if (!elem.getAttribute("emojisuggest_set_onclick")) {
elem.setAttribute("emojisuggest_set_onclick", "true")
elem.addEventListener(
'click',
function(){
//alert("Hi!")
// 絵文字の名前取得
let emojiName = elem.querySelector("img[title]").title
console.log("selected emoji which no exist in this instance:" + emojiName)
// 投稿の要素全体を取得 -> その中のボタン(classにxviCyがついてて、中にti-plusクラスのついたアイコンがあるやつ)を取得
// そしたらそのボタンをクリックする
if (info == 0) {
elem.closest("article").querySelectorAll("._button.xviCy").forEach((e)=>{
if(e.querySelector("i").classList.contains("ti-plus")){
e.dispatchEvent(new CustomEvent('mousedown'))
// ボタン押してから絵文字ピッカーが開くまでのラグに対応するために仕方なく待たせる
setTimeout(function(){
inputEmojiId(emojiName)
},200);
}
})
} else {
elem.closest("article").querySelectorAll("._button.button").forEach((e)=>{
if(e.querySelector("i").classList.contains("ti-plus")){
e.dispatchEvent(new CustomEvent('mousedown'))
setTimeout(function(){
inputEmojiId(emojiName)
},200);
}
})
}
},
true
)
}
}
)
}
//:<絵文字ID>@<インスタンス名>:という感じになってるので、絵文字IDだけ抽出する
function emojiIdAdjust(id){
// "@"以降削除(split)、冒頭の:削除(slice)
return id.split('@')[0].slice( 1 )
}
function inputEmojiId(name){
let searchInput = document.querySelectorAll(".xr8AW>.omfetrab>input.search[data-prevent-emoji-insert]")
// 一応保険でホントに絵文字セレクタなのか確認するために条件分岐しとく(これで他の場所入力されてたらやばいしね)
if (searchInput.length == 1 && searchInput.item(0).nextElementSibling.classList.contains("emojis")) {
searchInput.item(0).value = emojiIdAdjust(name)
searchInput.item(0).dispatchEvent(new CustomEvent('input'))
} else {
errorDialog("絵文字検索欄が見つかりませんでした。")
}
}
function errorDialog(msg){
alert(msg + "バグもしくはMisskeyのアップデートによりUserScriptが壊れています。\n\n==複数回試してもこのエラーが連発する場合==\n修正のアップデートを確認し、なければ今すぐこのUserScriptを無効化してください。")
}
function check(MutationList, observer) {
// 一応毎回毎回DOM変更あるたびにqueryselectorAllしてたらヤバそうだし、せっかくだから何のDOM変更なのかだけチェックする
// ただこれもDOM変更のたびにチェックが走るのでquerySelectorAllよりは軽そうだけど絶対重い。
MutationList.forEach(
(m)=>{
m.addedNodes.forEach((e)=>{
if(e.classList != undefined && e.classList.contains("note")){
// ノートを詳細表示時のDOM変更
setOnclickAttr(1)
} else if(e.classList != undefined && e.classList.contains("xcSej")) {
// ノートが流れてくる時のDOM変更
setOnclickAttr(0)
} else if(e.classList != undefined && e.classList.contains("xDRXD")) {
// ノートが流れてくる前に絵文字が追加されたとき用の、絵文字追加時のDOM変更
setOnclickAttr(0)
} else if(e.classList != undefined && e.classList.contains("xu3k3")) {
// 下にスクロールしてノートが流れる時のDOM変更
setOnclickAttr(0)
}
}
)
}
)
//observer.disconnect();
// デバッグ用(追加されたノードをすべてコンソールに出力する)
//MutationList.forEach(function(m){m.addedNodes.forEach((e)=>{console.log(e)})})
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment