您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
イラストの頭をなでるといいねを押してくれます。
// ==UserScript== // @name NADENADE gesture // @namespace http://tampermonkey.net/ // @version 2023-12-30 // @description イラストの頭をなでるといいねを押してくれます。 // @author koragen // @match https://twitter.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=twitter.com // @grant none // @license MIT // ==/UserScript== (()=>{ class ComboManager{ constructor(COMBO_ARRAY_,onSucceedsCombo_,TIME_DIFER_ = 2000,COOLDOWN_ = 600,debugMode=false){ this.DEBUGMODE = debugMode; this.COMBO_ARRAY = COMBO_ARRAY_; this.COMBO_LENGH = COMBO_ARRAY_.length; this.TIME_DIFER = TIME_DIFER_; this.COOLDOWN = COOLDOWN_; this.comboProgress = 0; this.comboStartedTime = -Infinity; this.LastTriggerdTime = -Infinity; this.onSucceedsCombo = onSucceedsCombo_; this.timeOutId=0; } reset(){ let date=new Date(); let currentTime = date.getTime(); this.comboProgress = 0; this.comboStartedTime = currentTime; } _continue(){ clearTimeout(this.timeOutId); this.timeOutId = setTimeout(()=>{ this.reset() },1000) } onEvent(ID,event){ this._continue(); let date=new Date(); let currentTime = date.getTime(); let status = false; if(this.DEBUGMODE)console.log({"ID":ID,"prog":this.comboProgress}) if(this.COMBO_ARRAY[this.comboProgress] == ID){ this.comboProgress++; let d = currentTime - this.comboStartedTime; let d2 = currentTime - this.LastTriggerdTime; if(this.comboProgress == this.COMBO_LENGH){ if((d<this.TIME_DIFER)&&(d2>this.COOLDOWN)){ status = true; this.onSucceedsCombo(event); } this.LastTriggerdTime = currentTime; this.reset(); } }else{ this.reset(); } return status; } } class GestureManager{ constructor(){ this.BufferLen=100; this.currentAcceraration ={x:0,y:0}; this.currentAcceraration_={x:0,y:0}; this.currentMousePos ={x:0,y:0}; this.currentMousePos_={x:0,y:0}; this.currentATheta = 0; this.currentATheta_= 0; this.currentF = 0; this.currentF_= 0; this.currentArrowID = -1; this.currentArrowID_= -1; this.comboManagers = []; } AddComboManager(comboManager){ this.comboManagers.push(comboManager); } onComboEvent(arrowID,event){ for(let cm of this.comboManagers){ let reult = cm.onEvent(arrowID,event); } } // ベクトルの長さを計算する関数 vectorLength(vector) { return Math.sqrt(vector.x * vector.x + vector.y * vector.y); } // 正規化されたベクトルを返す関数 normalizeVector(vector) { var length = this.vectorLength(vector); return {x: vector.x / length, y: vector.y / length}; } isVaildForce(F){ return (1<F&&F<15); } convTheta2ArrowID(theta){ let N=4 theta += (Math.PI*2)/(N*2) let f = Math.floor((theta/(Math.PI*2))*N) return f%N } tick(mx,my,event){ this.currentAcceraration_ = this.currentAcceraration this.currentAcceraration = {} this.currentMousePos_ = this.currentMousePos; this.currentMousePos = {}; this.currentMousePos.x=mx; this.currentMousePos.y=my; this.currentAcceraration.x = this.currentMousePos_.x-this.currentMousePos.x; this.currentAcceraration.y = this.currentMousePos_.y-this.currentMousePos.y; this.currentF_ = this.currentF*0.2; this.currentF = this.vectorLength(this.currentAcceraration)*0.2; this.currentATheta_ = this.currentATheta; this.currentATheta = Math.atan2(this.currentAcceraration.x,this.currentAcceraration.y)+Math.PI; this.currentArrowID = this.convTheta2ArrowID(this.currentATheta); window.mf = Math.max(window.mf,this.currentF) if(this.isVaildForce(this.currentF)&&this.currentArrowID_!=this.currentArrowID){ this.currentArrowID_ = this.currentArrowID; this.onComboEvent(this.currentArrowID,event); } } } window.onload = function(){ function GetArticleFromTargetElm(elm){ if(elm.tagName=="ARTICLE")return elm; if(elm.parentElement)return GetArticleFromTargetElm(elm.parentElement); return null; } function GetMainFromTargetElm(elm){ if(elm.tagName=="MAIN")return elm; if(elm.parentElement)return GetMainFromTargetElm(elm.parentElement); return null; } function GetDialogFromTargetElm(elm){ if(elm.getAttribute("role")=="dialog")return elm; if(elm.parentElement)return GetDialogFromTargetElm(elm.parentElement); return null; } let gm = new GestureManager(); gm.AddComboManager(new ComboManager([3,1,3,1],onSucceedsCombo_= (event)=>{//NADENADE IINE let likeElms = document.querySelectorAll('[data-testid="like"]'); if(likeElms.length==1){ likeElms[0].click(); return; } let article = GetArticleFromTargetElm(event.target); if(article){ let t = article.querySelector('[data-testid="like"]'); if(t)t.click(); return; } let main = GetMainFromTargetElm(event.target); if(main){ let t = main.querySelector('[data-testid="like"]'); if(t)t.click(); return; } let dialog = GetDialogFromTargetElm(event.target); if(dialog){ let t = dialog.querySelectorAll('[data-testid="unlike"],[data-testid="like"]')[0]; if(!t)return; if(t.getAttribute("data-testid")=="like")t.click(); return; } console.log(event.target) },2000,0,false)); gm.AddComboManager(new ComboManager([2,0,2,0],(event)=>{//閉じる,戻る let elm = document.querySelector('[aria-label="閉じる"],[aria-label="戻る"]'); if(elm)elm.click(); })); gm.AddComboManager(new ComboManager([0,3],(event)=>{ let elm = document.querySelector('[aria-label="次のスライド"]'); if(elm)elm.click(); })); gm.AddComboManager(new ComboManager([0,1],(event)=>{ let elm = document.querySelector('[aria-label="前のスライド"]'); if(elm)elm.click(); })); let fc=0; document.body.addEventListener("mousemove", function(e){ var mX = e.pageX; //X座標 var mY = e.pageY; //Y座標 (fc%8==0)?0:gm.tick(mX,mY,e); fc++; }); } })()