您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
(The 2nd version) Automatically finish DAU task at bilibili to get experience point.
// ==UserScript== // @name bilibiliGetExpV2 // @namespace https://iconquestion.github.io // @version 2.22 // @description (The 2nd version) Automatically finish DAU task at bilibili to get experience point. // @author ICONQUESTION // @match https://t.bilibili.com/* // @icon https://bilibili.com/favicon.ico // @grant none // @require https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.js // ==/UserScript== var urlList = { checkTasks: 'https://api.bilibili.com/x/member/web/exp/reward', watchVideo: 'https://api.bilibili.com/x/click-interface/web/heartbeat', shareVideo: 'https://api.biliapi.net/x/share/finish', dynamic: 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all?timezone_offset=-480&type=video&page=1', videoProperty: 'https://api.bilibili.com/x/player/pagelist', getAccess_key: 'https://passport.bilibili.com/login/app/third?appkey=1d8b6e7d45233436&api=http://link.acg.tv/forum.php&sign=5f9c0a5c2360c80b858d546a23a4a9dd', } //将document.cookie中的'; '替换为'&', 从而满足生成URL对象的条件, 再利用URL对象的searchParam功能完成cookie检索 var cookies = new URL('http://hello.world/test?' + document.cookie.replaceAll('; ', '&')) var shareVideoDone = cookies.searchParams.get('shareVideoDone'), watchVideoDone = cookies.searchParams.get('watchVideoDone') var csrftoken = cookies.searchParams.get('bili_jct') var mid = cookies.searchParams.get('DedeUserID') var access_key = cookies.searchParams.get('access_key') //date用来设置记录性cookies过期时间为第二天0:0:0 var date = new Date() var currentTime = parseInt((date.getTime()) / 1000); date.setTime(date.getTime() + 3600 * 24 * 1000) date.setHours(0, 0, 0, 0) //调试性开关 /* var debugMode = { 'true': '无论返回数据显示任务是否完成, 都再执行一次', 'false': '根据返回数据情况, 有选择地执行(默认值)' } */ var debugMode = localStorage && localStorage.getItem('debugMode') != undefined ? localStorage.getItem('debugMode') : false /* var cookieRecordComesFirst={ 'true':'以cookies中的任务完成记录为准(默认值)', 'false':'以fetch请求返回的数据为准' } */ var cookieRecordComesFirst = localStorage && localStorage.getItem('cookieRecordComesFirst') != undefined ? localStorage.getItem('cookieRecordComesFirst') : true //从这里开始执行 window.onload = async function () { //1.检查登录态 if (!csrftoken || !mid) { console.log('csrf或mid不存在, 请登录。如果您已经登录, 请尝试清空cookies后重新登录。') return; } //2.检查可完成的任务, 存储到taskList if (debugMode) console.log('debug模式已开启') if (cookieRecordComesFirst) { console.log('当前模式:cookies记录优先') var taskList = { 'share': shareVideoDone, 'watch': watchVideoDone } } else { console.log('当前模式:fetch请求优先') var taskList = await checkTasks() } console.log(taskList) if (!debugMode && taskList.share && taskList.watch) { console.log('所有任务已经完成!') return } //3.从动态列表拉取视频 var videoProp = await grabVideo() //console.log(videoProp) //4.1 完成观看视频任务 if (!taskList.watch || debugMode) { setTimeout(function(){ watchVideo(videoProp) }, Math.random() * 100000) } else { console.log('观看视频任务已经完成!') } //4.2 完成分享视频任务 if (!taskList.share || debugMode) { if (!access_key || access_key == 'null') { //4.2.1 获取access_key getAccessKey() } else { //4.2.1 分享视频 setTimeout(function(){ shareVideo(videoProp) }, Math.random() * 100000) } } else { console.log('分享视频任务已经完成!') } } //检查可获得经验值的任务 async function checkTasks() { console.log('正在检查任务列表') var data = await fetch(urlList.checkTasks, { credentials: 'include', headers: { 'Accept': 'application/json, text/plain, */*', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9', }, }).then(function (res) { return res.headers.get('Content-Type').search('application/json') != -1 ? res.json() : undefined }).then(function (data) { //console.log(data) if (!data || !data.data) { throw 'fetch(urlList.checkTasks) 返回数据异常。' } else { //传回最内层data(对象) return data.data } }) return data } //抓取视频 async function grabVideo() { console.log('正在抓取视频') //获取aid,bvid var videoProp = [] await fetch(urlList.dynamic, { credentials: 'include', }).then(function (res) { return res.headers.get('Content-Type').search('application/json') != -1 ? res.json() : undefined }).then(function (data) { //console.log(data) if (!data || !data.data || !data.data.items || !data.data.items[0].basic.comment_id_str || !data.data.items[0].modules.module_dynamic.major.archive.bvid) { throw ('fetch(urlList.dynamic) 返回数据类型异常, 或返回列表为空, 或相应数据不存在') } videoProp[0] = data.data.items[0].basic.comment_id_str videoProp[1] = data.data.items[0].modules.module_dynamic.major.archive.bvid }) //获取cid await fetch(urlList.videoProperty + '?bvid=' + videoProp[1] + '&jsonp=jsonp', { method: 'GET', credentials: 'include', headers: { 'Accept': '*/*', 'Content-Type': 'application/x-www-form-urlencoded', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9', }, }).then(function (res) { return res.headers.get('Content-Type').search('application/json') != -1 ? res.json() : undefined }).then(function (data) { //console.log(data) if (!data || !data.data || !data.data[0].cid) { throw 'fetch(urlList.videoProperty) 返回数据类型异常, 或相应数据不存在' } videoProp[2] = data.data[0].cid }) console.log('获取到以下视频数据: aid=' + videoProp[0] + ', bvid=' + videoProp[1] + ', cid=' + videoProp[2]) return videoProp } //获取access_key async function getAccessKey() { console.log('access_key不存在, 正在获取新access_key'); await fetch(urlList.getAccess_key, { credentials: 'include', }).then(function (res) { return res.headers.get('Content-Type').search('application/json') != -1 ? res.json() : undefined }).then(function (data) { //console.log(data) if (!data || !data.data || !data.data.confirm_uri) { throw 'fetch(urlList.getAccess_key) 返回数据异常' } console.log('请右键以下链接, 点击"在新标签页中打开", 然后复制查询字符串中的access_key字段, 粘贴到对话框中') console.log(data.data.confirm_uri) var input1 = prompt('请打开浏览器控制台, 右键最下方的链接, 点击"在新标签页中打开", 然后复制查询字符串中的access_key字段, 粘贴到这里'); if (input1) { document.cookie = 'access_key=' + input1 + '; max-age=15552000; domain=.bilibili.com'; console.log('access_key已存储. 请刷新此页面以重新运行该脚本. 若需再次更改access_key, 您可手动访问浏览器的Cookies存储设置.') } else { console.log('用户已取消操作。') } }) } //这个...不用解释了吧 function shareVideo(videoProp) { if (!access_key) { console.log('缺少access_key, 无法分享视频') return; } var aid = videoProp[0], bvid = videoProp[1], cid = videoProp[2] //share_session_id生成方式和作用未知, 欢迎补充! var body = 'access_key=' + access_key + '&appkey=1d8b6e7d45233436&build=6800300&c_locale=zh_CN&channel=bili&disable_rcmd=0&from_spmid=dt.dt.video.0&mobi_app=android&oid=' + aid + '&panel_type=1&platform=android&s_locale=zh_CN&share_channel=biliDynamic&share_id=main.ugc-video-detail.0.0.pv&share_origin=vinfo_share&share_session_id=' + '6609bb15-ac05-4118-8f12-cb' + currentTime + '&sid=' + cid + '&spm_id=main.ugc-video-detail.0.0&statistics=%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%226.80.0%22%2C%22abtest%22%3A%22%22%7D&success=true&ts=' + currentTime + '&sign=' body = body + md5(body + '560c52ccd288fed045859ed18bffd973') console.log('正在分享视频, aid=' + aid) fetch(urlList.shareVideo, { method: 'post', mode: 'cors', //referrer: "no-referrer", headers: { //'Buvid': 'XXAF685A25ED66209F45C4248C26054E197A8', //'Fp_local': '9ca222f943ae8680669b6cdf2da959e120220715131357006bc66326e8302881', //'Fp_remote': '9ca222f943ae8680669b6cdf2da959e1202207131056235c836389e254a11b4e', //'Session_id': '831ec2b1',//暂时不知道如何处理 //'Env': 'prod', //'App-Key': 'android', //'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1 Edg/109.0.0.0', //'X-Bili-Trace-Id': '390743e355a59747842729ca1962d222:8427c9ca1962d222:0:0',//暂时不知道如何处理 //'X-Bili-Aurora-Eid': 'UlYITlUAD1ID', //'X-Bili-Mid': mid, //'X-Bili-Aurora-Zone': '', 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', //'Accept-Encoding': 'gzip', }, body: body, }).then(function (res) { return res.headers.get('Content-Type').search('application/json') != -1 ? res.json() : undefined }).then(function (data) { //console.log(data) if (!data) { console.log('fetch(urlList.shareVideo) 返回数据异常') return } //每天第一次分享, 返回的toast不为空, 之后的分享toast为空 console.log(data.data.toast ? data.data.toast : '分享视频任务成功完成') document.cookie = 'shareVideoDone=true; expires=' + date.toGMTString() }) } //观看视频 function watchVideo(videoProp) { var aid = videoProp[0], bvid = videoProp[1], cid = videoProp[2] console.log('正在观看视频, aid=' + aid + ', bvid=' + bvid + ', cid=' + cid) fetch(urlList.watchVideo, { method: 'post', credentials: 'include', headers: { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'aid=' + aid + '&cid=' + cid + '&bvid=' + bvid + '&mid=' + mid + '&csrf=' + csrftoken + '&played_time=11&real_played_time=12&realtime=11&start_ts=' + currentTime + '&type=3&dt=2&play_type=2&from_spmid=444.41.list.card_archive.click&spmid=333.788.0.0&auto_continued_play=0&refer_url=https%3A%2F%2Ft.bilibili.com%2F%3Ftab%3Dvideo&bsource=' }).then(function (res) { return res.headers.get('Content-Type').search('application/json') != -1 ? res.json() : undefined }).then(function (data) { //console.log(data) if (!data) { console.log('fetch(urlList.watchVideo) 返回数据异常') return } //正常情况返回string'0', 否则返回具体信息 console.log(data.message == '0' ? '观看视频任务成功完成' : data.message) document.cookie = 'watchVideoDone=true; expires=' + date.toGMTString() }) }