Quantumult X的JavaScript编写

b站签到>.<

抓签到包

F12,签到,找签到数据包

image-20220510170502967

image-20220510170538309

编写脚本

其实Quantumult X有自动生成脚本,但是面对复杂的,它是解决不了的啦。

下面是我写的一个类,可以方便以后进行操作哈。

function initEnv() {
    //读取Quantumult X数据库里面的数据
	this.read = (key) => {
		return $prefs.valueForKey(key);
	}
    //通知
	this.notify = (title, subtitle, message) => {
		$notify(title, subtitle, message);
	}
	//随机数
    this.getRandom = (min,max) => {
        return Math.floor(Math.random() * (max - min + 1) ) + min;
    }
    //延迟
    this.sleep = (milliseconds) => {
        const date = Date.now();
        let currentDate = null;
        do {
            currentDate = Date.now();
        } while (currentDate - date < milliseconds);
    }
    //get请求
    this.get = (options, callback) => {
        options["method"] = "GET"
        $task.fetch(options).then(response => {
            callback(null, response)
        }, reason => callback(reason.error, null))
    }
    //post请求
	this.post = (options, callback) => {
        options["method"] = "POST"
        $task.fetch(options).then(response => {
            callback(null, response)
        }, reason => callback(reason.error, null))
	}
    //结束
	this.done = () => {
		$done();
	}
};

先在Quantumult X下创建一个js文件

image-20220510171348307

把刚刚的类复制到最下面,然后就可以写代码啦。

//先初始化一个类
const $ = new initEnv();

咱们开始写一个函数,完成签到的操作。

function dosign(){
    const url = "https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign";
    const headers = {
        "cookie":"自己的cookie",
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39"
    };

    const myRequest = {
        url:url,
        headers:headers
    }
	//发一个get请求
    $.get(myRequest,(error,response)=>{
        if(error){
            console.log(error);
        }else{
            console.log(response.body);
            let body = JSON.parse(response.body);
            console.log(body.data);
        }
        $.done();//这个代表结束整个程序。
    })

}
//调用函数即可
dosign();

image-20220510172959875

根据俩次的请求回应,我们修改一下签到函数。

function dosign(){
    const url = "https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign";
    const headers = {
        "cookie":"your cookie",
        "user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39"
    };

    const myRequest = {
        url:url,
        headers:headers
    }

    $.get(myRequest,(error,response)=>{
        if(error){
            console.log(error);
        }else{
            let body = JSON.parse(response.body);
            if(body.code===0){
                $.notify("bili签到~",body.data.text,body.data.specialText);
            }else{
                $.notify("bili签到~",body.message,"");
            }
        }
        $.done();
    })
}

运行结果如下

image-20220510173731266

自动获取COOKIE

Quantumult X内部有一个小型的数据库,也就是官网的数据持久化操作。

image-20220510174340728

image-20220510174424044

同时Quantumult X的rewrite操作可以运行js脚本,我们只需要,把cookie放入这里面就行啦。

cookie存入函数

下面的代码是在Github上找到一个获取COOKIE的模板。

function getCookie(name, key){
    var currentC = $request.headers.Cookie;
    var existC = key => $prefs.valueForKey(key);
    var create = (currentC, key) => $prefs.setValueForKey(currentC, key);
    if(currentC && existC(key)){
      currentC != existC(key) ?
      (create(currentC, key),
      $notify(name, "更新Cookie成功", "")) :
      console.log(name + "目前的cookie一致")
      }else{
          currentC != undefined ? 
          (create(currentC, key),
          $notify(name, "获取cookie成功", "")) : 
          $notify(name, "获取Cookie失败", "")
      }
  }
$done({})

编辑一个重写,当打开b站直播中心时自动运行,获取cookie,放入数据库中。

if($request.url.indexOf("DoSign")!=1){
    getCookie("BiliBili", "biliCookie");
}



function getCookie(name, key){
    var currentC = $request.headers.Cookie;
    var existC = key => $prefs.valueForKey(key);
    var create = (currentC, key) => $prefs.setValueForKey(currentC, key);
    if(currentC && existC(key)){
      currentC != existC(key) ?
      (create(currentC, key),
      $notify(name, "更新Cookie成功", "")) :
      console.log(name + "目前的cookie一致")
      }else{
          currentC != undefined ? 
          (create(currentC, key),
          $notify(name, "获取cookie成功", "")) : 
          $notify(name, "获取Cookie失败", "")
      }
  }
  $done({})

挂到到重写上即可

hostname = api.live.bilibili.com

^https:\/\/api\.live\.bilibili\.com\/xlive\/web-ucenter\/v1\/sign\/DoSign url script-request-header https://raw.githubusercontent.com/zhu-jiyuan/myJavaScripts/master/biliGetCookie.js

HTU校园网web认证

quantumult X 的网络请求是异步的,这对于咱一直没用过异步的孩子,多少有些痛苦。

由于这个脚本需要串行执行。

思路是这样的,先访问1.1.1.1,获取web认证的userip和认证ip,然后把获得的ip填入校园网认证表单中,发送POST请求,完成认证。

写了两种方式实现,仅供参考

await串行

await会让等待异步执行完之后,再执行下面的代码。但是只能在异步函数中使用。


const $ = new initEnv();
const stuNo = "学号";
const passwd = "密码";

let ips = "";

(async function(){
    await getIp();
    console.log(ips);
    $.done();
})()


function getIp(){
    const url = "http://1.1.1.1";
    const headers = {};
    const myquests = {
        url: url,
        headers: headers
    }
    return new Promise(resolve => {
        $.get(myquests,(error,response) => {
            try {
                if (error) throw new Error(error);
                let body = response.body;
                //console.log(body);
                ips = body.match(/(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)/g);
                //console.log(ips);
            }catch (e) {
                console.log(e);
            }finally {resolve();}
        })
    })
}

function loginHtu(){
    const url = "http://"+ips[0]+"/portalAuthAction.do";
    const body = {
            "wlanuserip":ips[1],
            "wlanacname":"HNSFDX_H3C-S8808-X",
            "chal_id":" ",
            "chal_vector":" ",
            "auth_type":"PAP",
            "seq_id":" ",
            "req_id":" ",
            "wlanacIp":"210.42.255.60",
            "ssid":" ",
            "vlan":" ",
            "mac":" ",
            "message":" ",
            "bank_acct":" ",
            "isCookies":" ",
            "version":"0",
            "authkey":"88----89",
            "url":" ",
            "usertime":"0 ",
            "listpasscode":"0",
            "listgetpass":"0",
            "getpasstype":"0",
            "randstr":"2880",
            "domain":"",
            "isRadiusProxy":"false",
            "usertype":"0 ",
            "isHaveNotice":"0",
            "times":"12"," weizhi":"0"," smsid":"",
            "freeuser":"",
            "freepasswd":"",
            "listwxauth":"0",
            "templatetype":"1 ",
            "tname":"shida_pc_portal_V1.1",
            "logintype":"0",
            "act":"",
            "is189":"false",
            "terminalType":"",
            "checkterminal":"true",
            "portalpageid":"101",
            "listfreeauth":"0",
            "viewlogin":"1",
            "userid":stuNo,
            "authGroupId":" ",
            "useridtemp":stuNo,
            "passwd":passwd
        }
    const headers = {}
    const myquests ={
        url:url,
        headers:headers,
        body:JSON.stringify(body)
    }
	return new Promise(resolve=>{
		$.post(myquests,(error,response) => {
            try {
                if (error) throw new Error(error);
                console.log(response.body);
            }catch (e) {
                console.log(e);
            }finally {resolve();}
        })
    })


    
}


function initEnv() {

	this.read = (key) => {
		return $prefs.valueForKey(key);
	}
	this.notify = (title, subtitle, message) => {
		$notify(title, subtitle, message);
	}

    this.getRandom = (min,max) => {
        return Math.floor(Math.random() * (max - min + 1) ) + min;
    }
    this.sleep = (milliseconds) => {
        const date = Date.now();
        let currentDate = null;
        do {
            currentDate = Date.now();
        } while (currentDate - date < milliseconds);
    }
    //get请求
    this.get = (options, callback) => {
        options["method"] = "GET"
        $task.fetch(options).then(response => {
            callback(null, response)
        }, reason => callback(reason.error, null))
    }
    //post请求
	this.post = (options, callback) => {
        options["method"] = "POST"
        $task.fetch(options).then(response => {
            callback(null, response)
        }, reason => callback(reason.error, null))
	}
    //结束
	this.done = () => {
		$done();
	}
};

回调串行

这个请参考MDN上的JavaScript教程

// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: green; icon-glyph: magic;

/**
 * Connect HTU WIFI
 * by@zhujiyuan
 * version 1.0
 */

 const $ = new initEnv();
 const stdNo = "";
 const passwd = "";
 
 let ips = [];
 
 connectHTU();
 
 function connectHTU() {
	 getIp(()=>{

		//console.log(ips[0]);
		const url = 'http://'+ips[0]+'/portalAuthAction.do';
		const body = 'wlanuserip='+ips[1]+'&wlanacname=HNSFDX_H3C-S8808-X&chal_id=&chal_vector=&auth_type=PAP&seq_id=&req_id=&wlanacIp=210.42.255.60&ssid=&vlan=&mac=&message=&bank_acct=&isCookies=&version=&authkey=88----89&url=&usertime=0&listpasscode=0&listgetpass=0&getpasstype=0&randstr=8289&domain=&isRadiusProxy=false&usertype=0&isHaveNotice=0&times=12&weizhi=0&smsid=&freeuser=&freepasswd=&listwxauth=0&templatetype=1&tname=shida_pc_portal_V1.1&logintype=0&act=&is189=false&terminalType=&checkterminal=false&portalpageid=101&listfreeauth=0&viewlogin=1&userid='+stdNo+'&authGroupId=&useridtemp='+stdNo+'&passwd='+passwd;
		//console.log(url);
		//console.log(body);

		 
		const myquests ={
			url:url,
	
			body:body
		 }
		
		 
		$.post(myquests,(error,response) => {
			if (error) {
				console.log(error);
			}
			let resp = response.body;
			//console.log(resp);
			if(resp.indexOf("河南师范")!=-1){
                $notify("HTU connection success~","","");
            	}else{
                $notify("HTU connection failed","","");
            	}
			$.done();
		})
	 })
 }
 
 
 function getIp(cb){
	 const url = "http://1.1.1.1";
	 const headers = {};
	 const myquests = {
		 url: url,
		 headers: headers
	 }
	 $.get(myquests,(error,response) => {
			 let body = response.body;
			 //console.log(body);
			 ips = body.match(/(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)/g);
			 //console.log(ips[1]);
			 if(ips[0]==="1.1.1.1"){
				 //console.log("over!");
				 $.done();
			 }
			 cb();
	 }) 
 }
 
 
 
 function initEnv() {
 
	 this.read = (key) => {
		 return $prefs.valueForKey(key);
	 }
	 this.notify = (title, subtitle, message) => {
		 $notify(title, subtitle, message);
	 }
 
	 this.getRandom = (min,max) => {
		 return Math.floor(Math.random() * (max - min + 1) ) + min;
	 }
	 this.sleep = (milliseconds) => {
		 const date = Date.now();
		 let currentDate = null;
		 do {
			 currentDate = Date.now();
		 } while (currentDate - date < milliseconds);
	 }
	 //get请求
	 this.get = (options, callback) => {
		 options["method"] = "GET"
		 $task.fetch(options).then(response => {
			 callback(null, response)
		 }, reason => callback(reason.error, null))
	 }
	 //post请求
	 this.post = (options, callback) => {
		 options["method"] = "POST"
		 $task.fetch(options).then(response => {
			 callback(null, response)
		 }, reason => callback(reason.error, null))
	 }
	 //结束
	 this.done = () => {
		 $done();
	 }
 };
 

(待更新,如果你有看到我,请提醒他去更新一下)


Change logs

May 25,2022

  • 更新校园网js示例