// ==UserScript==
// @namespace https://github.com/andywang425
// @name B站直播间挂机助手
// @name:en B站直播间挂机助手
// @author andywang425
// @description 自动获取小心心,直播区签到,应援团签到,银瓜子换硬币,完成主站每日任务(登录(不可用),观看视频,投币,分享视频),批量送礼、点亮勋章,参与Bilibili直播区礼物抽奖(现在极少),参加被广播的节奏风暴(几乎没有),定时发弹幕,快捷购买粉丝勋章
// @description:en 自动获取小心心,直播区签到,应援团签到,银瓜子换硬币,完成主站每日任务(登录(不可用),观看视频,投币,分享视频),批量送礼、点亮勋章,参与Bilibili直播区礼物抽奖(现在极少),参加被广播的节奏风暴(几乎没有),定时发弹幕,快捷购买粉丝勋章
// @homepageURL https://github.com/andywang425/BLTH/
// @supportURL https://github.com/andywang425/BLTH/issues
// @icon data:image/png;base64,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
// @copyright 2020, andywang425 (https://github.com/andywang425)
// @license MIT
// @compatible chrome 80 or later
// @compatible firefox 77 or later
// @compatible opera 69 or later
// @version 4.4.2
// @include /https?:\/\/live\.bilibili\.com\/[blanc\/]?[^?]*?\d+\??.*/
// @run-at document-start
// @connect passport.bilibili.com
// @connect api.live.bilibili.com
// @connect live-trace.bilibili.com
// @require https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js
// @require https://cdn.jsdelivr.net/gh/andywang425/BLTH@ae50298c8b1ce34108d737606ae254f448b0a22e/library_files/BilibiliAPI_Mod.min.js
// @require https://cdn.jsdelivr.net/gh/andywang425/BLTH@ae50298c8b1ce34108d737606ae254f448b0a22e/library_files/layer.js
// @require https://cdn.jsdelivr.net/gh/andywang425/BLTH@ae50298c8b1ce34108d737606ae254f448b0a22e/library_files/libBilibiliToken.js
// @require https://cdn.jsdelivr.net/gh/andywang425/BLTH@ae50298c8b1ce34108d737606ae254f448b0a22e/library_files/libWasmHash.js
// @resource layerCss https://cdn.jsdelivr.net/gh/andywang425/BLTH@a00d57126c9b2591cc93389cac78dc91db4b66e0/library_files/layer.css
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @grant GM_getResourceText
// @grant GM_addStyle
// ==/UserScript==
(function () {
const NAME = 'IGIFTMSG',
debugSwitch = true, //日志控制开关
BAPI = BilibiliAPI,
UA = navigator.userAgent,
tz_offset = new Date().getTimezoneOffset() + 480,
ts_ms = () => Date.now(),//当前毫秒
ts_s = () => Math.round(ts_ms() / 1000),//当前秒
runUntilSucceed = (callback, delay = 0, period = 100) => {
setTimeout(() => {
if (!callback()) runUntilSucceed(callback, period, period);
}, delay);
},
delayCall = (callback, delay = 10e3) => {
const p = $.Deferred();
setTimeout(() => {
const t = callback();
if (t && t.then) t.then((arg1, arg2, arg3, arg4, arg5, arg6) => p.resolve(arg1, arg2, arg3, arg4, arg5, arg6));
else p.resolve();
}, delay);
return p;
},
MYDEBUG = (sign, ...data) => {
if (!debugSwitch) return;
let d = new Date();
d = `[${NAME}][${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}:${d.getMilliseconds()}]`;
if (data.length === 1) { console.log(d, `${sign}:`, data[0]); return }
console.log(d, `${sign}:`, data);
},
runMidnight = (callback, msg) => {//明天凌晨0点1分再次运行(因为12点时任务可能没刷新)
const t = new Date();
let name = msg || ' ';
t.setMinutes(t.getMinutes() + tz_offset);
t.setDate(t.getDate() + 1);
t.setHours(0, 1, 0, 0);
t.setMinutes(t.getMinutes() - tz_offset);
setTimeout(callback, t - ts_ms());
MYDEBUG('runMidnight', name + " " + t.toString());
},
runExactMidnight = (callback, msg) => {//明天凌晨0点再次运行(清空统计)
const t = new Date();
let name = msg || ' ';
t.setMinutes(t.getMinutes() + tz_offset);
t.setDate(t.getDate() + 1);
t.setHours(0, 0, 0, 0);
t.setMinutes(t.getMinutes() - tz_offset);
setTimeout(callback, t - ts_ms());
MYDEBUG('runExactMidnight', name + " " + t.toString());
},
runTomorrow = (callback, hour, minute, msg) => {//明天运行,可自定义时间
const t = new Date();
let name = msg || ' ';
t.setMinutes(t.getMinutes() + tz_offset);
t.setDate(t.getDate() + 1);
t.setHours(hour, minute, 0, 0);
t.setMinutes(t.getMinutes() - tz_offset);
setTimeout(callback, t - ts_ms());
MYDEBUG('runTomorrow', name + " " + t.toString());
},
appToken = new BilibiliToken(),
baseQuery = `actionKey=appkey&appkey=${BilibiliToken.appKey}&build=5561000&channel=bili&device=android&mobi_app=android&platform=android&statistics=%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%225.57.0%22%2C%22abtest%22%3A%22%22%7D`,
setToken = async () => {
if (tokenData.time > ts_s()) {
userToken = tokenData;
} else {
tokenData = await appToken.getToken();
tokenData.time = ts_s() + tokenData.expires_in;
localStorage.setItem(`${NAME}_Token`, JSON.stringify(tokenData));
userToken = tokenData;
};
MYDEBUG(`${NAME}_Token`, tokenData);
return 'OK';
},
newWindow = {
init: () => {
return newWindow.Toast.init().then(() => {
});
},
Toast: { //设置右上角弹窗
init: () => {
try {
const list = [];
window.toast = (msg, type = 'info', timeout = 5e3) => {
switch (type) {
case 'success':
case 'info':
break;
case 'caution':
break;
case 'error':
break;
default:
type = 'info';
}
const a = $(`<div class="link-toast ${type} fixed"><span class="toast-text">${msg}</span></div>`)[0];
document.body.appendChild(a);
a.style.top = (document.body.scrollTop + list.length * 40 + 10) + 'px';
a.style.left = (document.body.offsetWidth + document.body.scrollLeft - a.offsetWidth - 5) + 'px';
if (msgHide == 'hide') {
$('.link-toast').hide();
}
list.push(a);
setTimeout(() => {
a.className += ' out';
setTimeout(() => {
list.shift();
list.forEach((v) => {
v.style.top = (parseInt(v.style.top, 10) - 40) + 'px';
});
$(a).remove();
}, 200);
}, timeout);
};
return $.Deferred().resolve();
} catch (err) {
console.error(`初始化浮动提示时出现异常`, err);
return $.Deferred().reject();
}
}
}// Need Init
},
addStyle = async () => {
const layerCss = await GM_getResourceText('layerCss');
const myCss = ".igiftMsg_input{outline:none;border:1px solid #e9eaec;background-color:#fff;border-radius:4px;padding:1px 0 0;overflow:hidden;font-size:12px;line-height:19px;width:30px;z-index:'10001';}.igiftMsg_btn{background-color:#23ade5;color:#fff;border-radius:4px;border:none;padding:5px;cursor:pointer;box-shadow:0 0 2px #00000075;line-height:10px;z-index:10001;}.igiftMsg_fs{border:2px solid #d4d4d4;z-index:10001;}";
const AllCss = layerCss + myCss;
return await GM_addStyle(AllCss);
},
ct = $('#chat-history-list');
let msgHide = localStorage.getItem(`${NAME}_msgHide`) || 'hide',//UI隐藏开关
gift_join_try = 0,
guard_join_try = 0,
pk_join_try = 0,
SEND_GIFT_NOW = false,//立刻送出礼物
SEND_DANMU_NOW = false,//立刻发弹幕
LIGHT_MEDAL_NOW = false,//立刻点亮勋章
hideBtnClickable = true,
Live_info = {
room_id: undefined,
uid: undefined,
ruid: undefined,
tid: undefined,
mobile_verify: undefined,
gift_list: undefined,
rnd: undefined,
visit_id: undefined,
identification: undefined,
bili_jct: undefined
},
userToken = undefined,
tokenData = JSON.parse(localStorage.getItem(`${NAME}_Token`)) || {};
newWindow.init();
$(() => {//DOM完毕,等待弹幕加载完成
const loadInfo = (delay) => {
setTimeout(async () => {
const W = typeof unsafeWindow === 'undefined' ? window : unsafeWindow;
if ((W.BilibiliLive === undefined || parseInt(W.BilibiliLive.UID) === 0 || isNaN(parseInt(W.BilibiliLive.UID)))) {
//window.toast(`[${GM_info.script.name}]无配置信息`, 'warning');
//MYDEBUG(`${GM_info.script.name}`,'无配置信息');
return loadInfo(1000);
} else {
Live_info.room_id = W.BilibiliLive.ROOMID;
Live_info.uid = W.BilibiliLive.UID;
Live_info.tid = W.BilibiliLive.ANCHOR_UID;
await BAPI.live_user.get_info_in_room(Live_info.room_id).then((response) => {
MYDEBUG('InitData: API.live_user.get_info_in_room', response);
Live_info.mobile_verify = response.data.info.mobile_verify;
Live_info.identification = response.data.info.identification;
});
await BAPI.gift.gift_config().then((response) => {
MYDEBUG('InitData: API.gift.gift_config', response);
if (!!response.data && $.isArray(response.data)) {
Live_info.gift_list = response.data;
} else if (!!response.data.list && $.isArray(response.data.list)) {
Live_info.gift_list = response.data.list;
} else {
Live_info.gift_list = [
{
"id": 6,//亿圆
"price": 1000
}, {
"id": 1,//辣条
"price": 100
}, {
'id': 30607, //小心心
'price': 5000
}];
window.toast('直播间礼物数据获取失败,使用备用数据', 'error');
}
});
Live_info.bili_jct = BAPI.getCookie('bili_jct');
Live_info.ruid = W.BilibiliLive.ANCHOR_UID;
Live_info.rnd = W.BilibiliLive.RND;
Live_info.visit_id = W.__statisObserver ? W.__statisObserver.__visitId : '';
MYDEBUG("Live_info", Live_info);
init();
}
}, delay);
};
loadInfo(1000);
addStyle();//加载style
});
/**
* 删除一维数组元素
* @param val 数组中一个元素的值
*/
Array.prototype.remove = function (val) {
const index = this.indexOf(val);
if (index > -1) {
this.splice(index, 1);
}
};
function init() {//API初始化
const MY_API = {
CONFIG_DEFAULT: {
AUTO_DANMU: false,//发送弹幕
AUTO_GIFT: false,//自动送礼
AUTO_GIFT_ROOMID: ["0"],//送礼优先房间
AUTO_GROUP_SIGN: true,//应援团签到开关
CHECK_HOUR_ROOM: false,//检查小时榜
CHECK_HOUR_ROOM_INTERVAL: 600,//小时间检查间隔时间(秒)
COIN: false,//投币
COIN_NUMBER: 0,//投币数量
COIN_TYPE: "COIN_DYN",//投币方法 动态/UID
COIN_UID: 0,//投币up主
DANMU_CONTENT: ["这是一条弹幕"],//弹幕内容
DANMU_ROOMID: ["22474988"],//发弹幕房间号
DANMU_INTERVAL_TIME: ["10m"],//弹幕发送时间
EXCLUDE_ROOMID: ["0"],//送礼排除房间号
FORCE_LOTTERY: false,//黑屋强制抽奖
FORCE_LIGHT: false,//忽略亲密上限点亮
GIFT_LIMIT: 1,//礼物到期时间(天)
GIFT_SEND_HOUR: 23,//送礼小时
GIFT_SEND_MINUTE: 59,//送礼分钟
GIFT_INTERVAL: 5,//送礼间隔
GIFT_METHOD: "GIFT_SEND_TIME",//送礼策略
GIFT_SORT: 'high',//送礼优先高等级
IN_TIME_RELOAD_DISABLE: false,//休眠时段是否禁止刷新直播间 false为刷新
LOTTERY: true,//参与抽奖
LIVE_SIGN: true,//直播区签到
LOGIN: true,//主站登陆
LITTLE_HEART: true,//获取小心心
LIGHT_MEDALS: ["0"],//点亮勋章
LIGHT_METHOD: "LIGHT_WHITE",
MAX_GIFT: 99999,//辣条上限
NOSLEEP: true,//屏蔽挂机检测
RANDOM_DELAY: true,//抽奖随机延迟
RANDOM_SEND_DANMU: 0,//随机弹幕发送概率
RANDOM_SKIP: 0,//随机跳过抽奖概率
REMOVE_ELEMENT_2233: false,//移除2233
REMOVE_ELEMENT_activity: false,//移除活动入口
REMOVE_ELEMENT_rank: true,//移除上榜入口
RND_DELAY_END: 5,//延迟最大值
RND_DELAY_START: 2,//延迟最小值
SEND_ALL_GIFT: false,//送满全部勋章
SHARE: true,//分享
SILVER2COIN: false,//银瓜子换硬币
SPARE_GIFT_ROOM: "0",//剩余礼物送礼房间
STORM: false,//节奏风暴
STORM_MAX_COUNT: 100,//单个风暴最大尝试次数
STORM_ONE_LIMIT: 200,//单个风暴参与次数间隔(毫秒)
STORM_QUEUE_SIZE: 3,//允许同时参与的风暴次数
TIME_AREA_DISABLE: true,//不抽奖时段开关
TIME_AREA_END_H0UR: 8,//不抽奖结束小时
TIME_AREA_END_MINUTE: 0,//不抽奖结束分钟
TIME_AREA_START_H0UR: 2,//不抽奖开始小时
TIME_AREA_START_MINUTE: 0,//不抽奖开始分钟
TIME_RELOAD: false,//定时刷新直播间
TIME_RELOAD_MINUTE: 120,//直播间重载时间
WATCH: true,//观看视频
},
CACHE_DEFAULT: {
UNIQUE_CHECK: 0,//唯一运行检测
AUTO_SEND_DANMU_TS: [],//弹幕发送
AUTO_GROUP_SIGH_TS: 0,//应援团执行时间,用于判断是否为新的一天
DailyReward_TS: 0,//其它每日任务
LiveReward_TS: 0,//直播每日任务
Silver2Coin_TS: 0,//银瓜子换硬币
Gift_TS: 0,//自动送礼(定时)
GiftInterval_TS: 0,//自动送礼(间隔)
LittleHeart_TS: 0//小心心
},
CONFIG: {},
CACHE: {},
GIFT_COUNT: {
COUNT: 0,
SILVER_COUNT: 0,
CLEAR_TS: 0,
},
init: () => {
try {
BAPI.setCommonArgs(Live_info.bili_jct);// 设置token
} catch (err) {
console.error(`[${NAME}]`, err);
return;
}
let p = $.Deferred();
try {
MY_API.loadConfig().then(() => {
MY_API.chatLog('脚本载入配置成功', 'success');
p.resolve()
});
} catch (e) {
console.error('API初始化出错', e);
MY_API.chatLog('API初始化出错', 'error');
p.reject()
}
try {
MY_API.loadCache().then(() => {
window.toast('CACHE载入成功', 'success')
p.resolve()
});
} catch (e) {
console.error('CACHE初始化出错', e);
window.toast('CACHE初始化出错', 'error')
p.reject()
}
return p;
},
loadConfig: () => {//加载配置函数
let p = $.Deferred();
try {
let config = JSON.parse(localStorage.getItem(`${NAME}_CONFIG`));
$.extend(true, MY_API.CONFIG, MY_API.CONFIG_DEFAULT);
for (let item in MY_API.CONFIG) {
if (!MY_API.CONFIG.hasOwnProperty(item)) continue;
if (config[item] !== undefined && config[item] !== null) MY_API.CONFIG[item] = config[item];
}
MY_API.loadGiftCount();//载入礼物统计
p.resolve()
} catch (e) {
MYDEBUG('API载入配置失败,加载默认配置', e);
MY_API.setDefaults();
p.reject()
}
return p
},
loadCache: () => {//加载CACHE
let p = $.Deferred();
try {
let cache = JSON.parse(localStorage.getItem(`${NAME}_CACHE`));
$.extend(true, MY_API.CACHE, MY_API.CACHE_DEFAULT);
for (let item in MY_API.CACHE) {
if (!MY_API.CACHE.hasOwnProperty(item)) continue;
if (cache[item] !== undefined && cache[item] !== null) MY_API.CACHE[item] = cache[item];
}
p.resolve()
} catch (e) {
MYDEBUG('CACHE载入配置失败,加载默认配置', e);
MY_API.setDefaults();
p.reject()
}
return p
},
newMessage: (version) => {
try {
const cache = localStorage.getItem(`${NAME}_NEWMSG_CACHE`);
if ((cache == undefined || cache == null || cache != '4.4.2') &&
version == '4.4.2') { //更新公告时需要修改
const linkMsg = (msg, link) => {
return '<a href=\"' + link + '\"target=\"_blank\">' + msg + '</a>';
};
layer.open({
title: `${version}更新提示`,
content: `1.修复送礼失败的问题<br>
2.优化了自动投币的检测机制<br>
3.优化了隐藏/显示脚本提示时聊天栏信息的滚动<br>
<hr>
<em style="color:grey;">
如果使用过程中遇到问题,欢迎去${linkMsg('github', 'https://github.com/andywang425/BLTH/issues')}
(或者进qq群${linkMsg('1106094437', "https://jq.qq.com/?_wv=1027&k=fCSfWf1O")})反馈。
</em>`
});
localStorage.setItem(`${NAME}_NEWMSG_CACHE`, version);
}
} catch (e) {
MYDEBUG('提示信息CACHE载入失败', e);
}
},
saveConfig: () => {//保存配置函数
try {
localStorage.setItem(`${NAME}_CONFIG`, JSON.stringify(MY_API.CONFIG));
MY_API.chatLog('配置已保存');
MYDEBUG('MY_API.CONFIG', MY_API.CONFIG);
return true
} catch (e) {
MYDEBUG('API保存出错', e);
return false
}
},
saveCache: (logswitch = true) => {//保存配置函数
try {
localStorage.setItem(`${NAME}_CACHE`, JSON.stringify(MY_API.CACHE));
if (logswitch) {
MYDEBUG('CACHE已保存', MY_API.CACHE)
};
return true
} catch (e) {
MYDEBUG('CACHE保存出错', e);
return false
}
},
setDefaults: () => {//重置配置函数
MY_API.CONFIG = MY_API.CONFIG_DEFAULT;
MY_API.CACHE = MY_API.CACHE_DEFAULT;
MY_API.saveConfig();
MY_API.saveCache();
MY_API.chatLog('配置和CACHE已重置为默认。3秒后刷新页面');
setTimeout(() => {
window.location.reload()
}, 3000);
},
ReDoDailyTasks: () => {
window.toast('3秒后再次执行所有任务', 'info')
setTimeout(() => {
MY_API.CACHE = MY_API.CACHE_DEFAULT;
MY_API.GroupSign.run();//应援团签到
MY_API.DailyReward.run();//每日任务
MY_API.LiveReward.run();//直播每日任务
MY_API.Exchange.runS2C();//银瓜子换硬币
MY_API.Gift.run();//送礼物
MY_API.LITTLE_HEART.run();//小心心
MY_API.AUTO_DANMU.run();//发弹幕
}, 3000);
},
loadGiftCount: () => {//读取礼物数量
try {
let config = JSON.parse(localStorage.getItem(`${NAME}_GIFT_COUNT`));
for (let item in MY_API.GIFT_COUNT) {
if (!MY_API.GIFT_COUNT.hasOwnProperty(item)) continue;
if (config[item] !== undefined && config[item] !== null) MY_API.GIFT_COUNT[item] = config[item];
}
MYDEBUG('MY_API.GIFT_COUNT', MY_API.GIFT_COUNT);
} catch (e) {
MYDEBUG('读取统计失败', e);
}
},
saveGiftCount: () => {
try {
localStorage.setItem(`${NAME}_GIFT_COUNT`, JSON.stringify(MY_API.GIFT_COUNT));
MYDEBUG('统计保存成功', MY_API.GIFT_COUNT);
return true
} catch (e) {
MYDEBUG('统计保存出错', e);
return false
}
},
addGift: (count) => {
MY_API.GIFT_COUNT.COUNT += count;
$('#giftCount span:eq(0)').text(MY_API.GIFT_COUNT.COUNT);
MY_API.saveGiftCount();
},
addSilver: (count) => {
MY_API.GIFT_COUNT.SILVER_COUNT += (count);
$('#giftCount span:eq(1)').text(MY_API.GIFT_COUNT.SILVER_COUNT);
MY_API.saveGiftCount();
},
removeUnnecessary: () => {//移除不必要的页面元素
const unnecessaryList = [
'#my-dear-haruna-vm',//2233
'.activity-entry',//活动入口
'.activity-rank'//排行榜
];
const settingNameList = [
'REMOVE_ELEMENT_2233',
'REMOVE_ELEMENT_activity',
'REMOVE_ELEMENT_rank'
];
const removeUntiSucceed = (list_id) => {
if (MY_API.CONFIG[settingNameList[list_id]]) {
setInterval(() => {
if ($(unnecessaryList[list_id]).length > 0) {
$(unnecessaryList[list_id]).remove();
} else {
return
}
}, 200);
}
};
for (let i = 0; i < unnecessaryList.length; i++) {
removeUntiSucceed(i);
};
if (MY_API.CONFIG.NOSLEEP) {
setInterval(() => document.dispatchEvent(new Event('visibilitychange')), 10 * 60 * 1000);
}
},
creatSetBox: () => {//创建设置框
//const eleList = ['.chat-history-list', '.attention-btn-ctnr', '.live-player-mounter']必要元素
//添加按钮
const btnmsg = msgHide == 'hide' ? '显示窗口和提示信息' : '隐藏窗口和提示信息';
let btn = $(`<button style="display: inline-block; float: left; margin-right: 7px;background-color: #23ade5;color: #fff;border-radius: 4px;border: none; padding:4px; cursor: pointer;box-shadow: 1px 1px 2px #00000075;" id="hiderbtn">${btnmsg}<br></button>`);
const div = '#allsettings';
const lockBtn = 'span[title=\"弹幕滚动锁定\"]';
let mainIndex;
const settingTableHeight = $('.live-player-mounter').height();
const settingTableoffset = $('.live-player-mounter').offset();
let fieldsetStyle = '\"float:left\"';
if (UA.toLowerCase().indexOf("firefox") > -1) fieldsetStyle = '\"\"';
const html = `
<div id='allsettings' class = "igiftMsg_main">
<fieldset class="igiftMsg_fs">
<legend style="color: black">今日统计</legend>
<div id="giftCount" style="font-size: large; text-shadow: 1px 1px #00000066; color: blueviolet;">
辣条 <span>${MY_API.GIFT_COUNT.COUNT}</span>
银瓜子 <span>${MY_API.GIFT_COUNT.SILVER_COUNT}万</span>
<button style="font-size: small" class="igiftMsg_btn" data-action="save">保存所有设置</button>
</div>
</fieldset>
<div id="left_fieldset" style=${fieldsetStyle}>
<fieldset class="igiftMsg_fs">
<legend style="color: black">抽奖设置</legend>
<div data-toggle="LOTTERY">
<label style="margin: 5px auto; color: purple;line-height:30px";>
<input style="vertical-align: text-top;" type="checkbox">
参与礼物抽奖
</label>
</div>
<div data-toggle="RANDOM_DELAY">
<label style="margin: 5px auto; color: darkgreen">
<input style="vertical-align: text-top;" type="checkbox">
抽奖附加随机延迟
<input class="RND_DELAY_START igiftMsg_input" style="width: 30px;vertical-align: top;" type="text">~
<input class="RND_DELAY_END igiftMsg_input" style="width: 30px;vertical-align: top;" type="text">s
</label>
</div>
<div data-toggle="TIME_AREA_DISABLE">
<label style="margin: 5px auto; color: darkgreen">
<input style="vertical-align: text-top;" type="checkbox">
启用
<input class="startHour igiftMsg_input" style="width: 20px;" type="text">点
<input class="startMinute igiftMsg_input" style="width: 20px;" type="text">分至
<input class="endHour igiftMsg_input" style="width: 20px;" type="text">点
<input class="endMinute igiftMsg_input" style="width: 20px;" type="text">分不抽奖(24小时制)
</label>
</div>
<div data-toggle="RANDOM_SKIP">
<label style="margin: 5px auto; color: darkgreen">
随机跳过礼物(0到100,为0则不跳过)<input class="per igiftMsg_input" style="width: 30px;" type="text">%
</label>
</div>
<div data-toggle="MAX_GIFT">
<label style="margin: 5px auto; color: darkgreen">
当天最多抢辣条数量<input class="num igiftMsg_input" style="width: 100px;" type="text">
</label>
</div>
<div data-toggle="RANDOM_SEND_DANMU">
<label style="margin: 5px auto; color: darkgreen">
抽奖时活跃弹幕发送概率(0到5,为0则不发送)<input class="per igiftMsg_input" style="width: 30px;" type="text">%
</label>
</div>
<div data-toggle="CHECK_HOUR_ROOM">
<label style="margin: 5px auto; color: darkgreen">
<input style="vertical-align: text-top;" type="checkbox">
检查小时榜(间隔时间<input class="num igiftMsg_input" style="width: 25px;" type="text">秒)
</label>
</div>
<div data-toggle="FORCE_LOTTERY" style="line-height: 20px">
<label style="margin: 5px auto; color: red;">
<input style="vertical-align: text-top;" type="checkbox">
访问被拒绝后强制重复抽奖(最多5次)
</label>
</div>
</fieldset>
<fieldset class="igiftMsg_fs" style ="line-height:16px;">
<legend style="color: black">每日任务设置</legend>
<div data-toggle="LOGIN" style=" color: black">
<input style="vertical-align: text-top;" type="checkbox">
登陆
</div>
<div data-toggle="WATCH" style=" color: black">
<input style="vertical-align: text-top;" type="checkbox">
观看视频
</div>
<div data-toggle="COIN" style=" color: black">
<label style="cursor: pointer">
<input style="vertical-align: text-top;" type="checkbox">
自动投币<input class="coin_number igiftMsg_input" style="width: 40px;" type="text">个(0-5)
</label>
</div>
<div data-toggle="COIN_TYPE" style=" color: black">
<div data-toggle="COIN_UID">
<input style="vertical-align: text-top;" type="radio" name="COIN_TYPE">
给用户(UID:<input class="num igiftMsg_input" style="width: 80px;" type="text">)
的视频投币
</div>
<div data-toggle="COIN_DYN">
<input style="vertical-align: text-top;" type="radio" name="COIN_TYPE">
给动态中的的视频投币
</div>
</div>
<div data-toggle="SHARE" style=" color: black">
<input style="vertical-align: text-top;" type="checkbox">
分享视频
</div>
<div data-toggle="SILVER2COIN" style=" color: black">
<input style="vertical-align: text-top;" type="checkbox">
银瓜子换硬币
</div>
<div data-toggle="LIVE_SIGN" style=" color: black">
<input style="vertical-align: text-top;" type="checkbox">
直播区签到
</div>
<div data-toggle="AUTO_GROUP_SIGN" style=" color: darkgreen">
<input style="vertical-align: text-top;" type="checkbox">
应援团签到
</div>
</fieldset>
<fieldset class="igiftMsg_fs">
<legend style="color: black">自动送礼设置</legend>
<div data-toggle="AUTO_GIFT" style=" color: purple">
<input style="vertical-align: text-top;" type="checkbox">
自动送礼
</div>
<div data-toggle="AUTO_GIFT_ROOMID" style=" color: purple">
优先送礼房间
<input class="num igiftMsg_input" style="width: 150px;" type="text">
</div>
<div data-toggle="EXCLUDE_ROOMID" style=" color: purple">
不送礼房间
<input class="num igiftMsg_input" style="width: 150px;" type="text">
</div>
<div data-toggle="GIFT_INTERVAL" style=" color: black">
<input style="vertical-align: text-top;" type="radio" name="GIFT_TYPE">
间隔
<input class="num igiftMsg_input" style="width: 30px;" type="text">
分钟送礼
</div>
<div data-toggle="GIFT_SEND_TIME" style=" color: purple">
<input style="vertical-align: text-top;" type="radio" name="GIFT_TYPE">
定时送礼<br>
送礼时间
<input class="Hour igiftMsg_input" style="width: 20px;" type="text">点
<input class="Minute igiftMsg_input" style="width: 20px;" type="text">分
<button style="font-size: small" class="igiftMsg_btn" data-action="sendGiftNow">立刻开始送礼</button>
</div>
<div data-toggle="GIFT_LIMIT" style=" color: purple">
礼物到期时间
<input class="num igiftMsg_input" style="width: 20px;" type="text">
天
</div>
<div data-toggle="GIFT_SORT_HIGH" style=" color: black;line-height: 20px;">
粉丝牌送礼优先级<br>
<input style="vertical-align: text-top;" type="radio" name = "GIFT_SORT">
优先<strong style="color: purple">高</strong>等级粉丝牌
</div>
<div data-toggle="GIFT_SORT_LOW" style=" color: black">
<input style="vertical-align: text-top;" type="radio" name = "GIFT_SORT">
优先<strong style="color: purple">低</strong>等级粉丝牌
</div>
<div data-toggle="SEND_ALL_GIFT" style="color: #ff5200;line-height:15px;">
<input style="vertical-align: text-top;" type="checkbox">
无视礼物类型和到期时间限制
</div>
<div data-toggle="SPARE_GIFT_ROOM" style="color: black;line-height:20px;">
剩余礼物送礼直播间:
<input class="num igiftMsg_input" type="text" style="width: 100px;">
</div>
</fieldset>
<fieldset class="igiftMsg_fs">
<legend style="color: black">节奏风暴设置</legend>
<div data-toggle="STORM" style="line-height: 15px">
<label style="margin: 5px auto; color: #ff5200">
<input style="vertical-align: text-top;" type="checkbox">
参与节奏风暴
</label>
</div>
<div data-toggle="STORM_QUEUE_SIZE" style="color: black">
允许同时参与的节奏风暴次数:
<input class="num igiftMsg_input" type="text" style="width: 30px;">
</div>
<div data-toggle="STORM_MAX_COUNT" style="color: black">
单个风暴最大尝试次数:
<input class="num igiftMsg_input" type="text" style="width: 30px;">
</div>
<div data-toggle="STORM_ONE_LIMIT" style="color: black">
单个风暴参与次数间隔:
<input class="num igiftMsg_input" type="text" style="width: 30px;">
毫秒
</div>
</fieldset>
</div>
<div id="right_fieldset" style=${fieldsetStyle}>
<fieldset class="igiftMsg_fs">
<legend style="color: black">购买粉丝勋章</legend>
<div data-toggle="BUY_MEDAL" style="color: black; line-height: 15px">
输入粉丝勋章对应房间号:<input class="num igiftMsg_input" type="text" value = ${Live_info.room_id} onclick="select();" style="width: 70px">
<button class="igiftMsg_btn" data-action="buy_medal">点击购买勋章</button>
(花费20硬币)
</div>
</fieldset>
<fieldset class="igiftMsg_fs">
<legend style="color: black">小心心</legend>
<div data-toggle="LITTLE_HEART" style="line-height: 15px">
<label style="margin: 5px auto; color: black">
<input style="vertical-align: text-top;" type="checkbox"> 自动获取小心心
</label>
</div>
<div data-toggle="LIGHT_MEDALS" style=" color: purple">
自动点亮勋章房间号
<input class="num igiftMsg_input" style="width: 300px;" type="text">
</div>
<div data-toggle="LIGHT_METHOD" style="line-height: 15px; color: black; display:inline">
勋章点亮模式:
<div data-toggle="LIGHT_WHITE" style="color: black; display:inline">
<input style="vertical-align: text-top;" type="radio" name="LIGHT_TYPE">
白名单
</div>
<div data-toggle="LIGHT_BLACK" style="color: black; display:inline">
<input style="vertical-align: text-top;" type="radio" name="LIGHT_TYPE">
黑名单
</div>
<button style="font-size: small" class="igiftMsg_btn" data-action="lightMedalNow">立刻点亮勋章</button>
</div>
<div data-toggle="FORCE_LIGHT" style="line-height: 15px">
<label style="margin: 5px auto; color: black">
<input style="vertical-align: text-top;" type="checkbox"> 点亮勋章时忽略亲密度上限
</label>
</div>
</fieldset>
<fieldset class="igiftMsg_fs">
<legend style="color: black">内容屏蔽</legend>
<div data-toggle="REMOVE_ELEMENT_2233" style="line-height: 15px">
<label style="margin: 5px auto; color: black">
<input style="vertical-align: text-top;" type="checkbox">
移除2233模型
</label>
</div>
<div data-toggle="REMOVE_ELEMENT_activity" style="line-height: 15px">
<label style="margin: 5px auto; color: black">
<input style="vertical-align: text-top;" type="checkbox">
移除活动入口
</label>
</div>
<div data-toggle="REMOVE_ELEMENT_rank" style="line-height: 15px">
<label style="margin: 5px auto; color: black">
<input style="vertical-align: text-top;" type="checkbox">
移除排行榜
</label>
</div>
<div data-toggle="NOSLEEP">
<label style="margin: 5px auto; color: black">
<input style="vertical-align: text-top;" type="checkbox">
屏蔽挂机检测
</label>
</div>
</fieldset>
<fieldset class="igiftMsg_fs" style="line-height: 25px">
<legend style="color: black">弹幕设置</legend>
<div data-toggle="AUTO_DANMU">
<input style="vertical-align: text-top;" type="checkbox">
自动发弹幕<br>
弹幕内容
<input class="Danmu igiftMsg_input" style="width: 330px;" type="text"><br>
房间号
<input class="Roomid igiftMsg_input" style="width: 330px;" type="text"><br>
发送时间
<input class="Time igiftMsg_input" style="width: 330px;" type="text">
</div>
<button style="font-size: small" class="igiftMsg_btn" data-action="sendDanmuNow">立刻发送弹幕</button>
<button style="font-size: small" class="igiftMsg_btn" data-action="clearDanmuCache">清除弹幕缓存</button>
</fieldset>
<fieldset class="igiftMsg_fs" style="line-height: 15px">
<legend style="color: black">其他设置</legend>
<div data-toggle="TIME_RELOAD" style="color: black">
<input style="vertical-align: text-top;" type="checkbox">
每
<input class="delay-seconds igiftMsg_input" type="text" style="width: 30px;">
分钟刷新一次页面
</div>
<div data-toggle="IN_TIME_RELOAD_DISABLE" style="line-height: 20px">
<label style="margin: 5px auto; color: darkgreen">
<input style="vertical-align: text-top;" type="checkbox">
不抽奖时段不刷新直播间
</label>
</div>
<div id="resetArea">
<button data-action="reset" style="color: red;" class="igiftMsg_btn">重置所有为默认</button>
<button data-action="redo_dailyTasks" style="color: red;" class="igiftMsg_btn">再次执行所有任务</button>
<button style="font-size: small" class="igiftMsg_btn" data-action="countReset">重置统计</button>
</div>
</fieldset>
<label style="color: darkblue; font-size:large;">
<a href="https://github.com/andywang425/BLTH"
target="_blank">v${GM_info.script.version} 更多信息见github上的项目说明(点我)</a>
</label>
</div>
</div>`;
const getScrollPosition = (el = window) => ({
x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
});
const openMainWindow = () => {
mainIndex = layer.open({
type: 1,
title: false,
offset: [String(settingTableoffset.top - getScrollPosition().y) + 'px', String(settingTableoffset.left) + 'px'],
closeBtn: 0,
shade: 0,
zIndex: 9999,
fixed: false,
area: [, String(settingTableHeight) + 'px'], //宽高
content: html,
success: () => {
//显示对应配置状态
$(div).find('div[data-toggle="AUTO_DANMU"] .Time').val(MY_API.CONFIG.DANMU_INTERVAL_TIME.toString());
$(div).find('div[data-toggle="AUTO_DANMU"] .Roomid').val(MY_API.CONFIG.DANMU_ROOMID.toString());
$(div).find('div[data-toggle="AUTO_DANMU"] .Danmu').val(MY_API.CONFIG.DANMU_CONTENT.toString());
$(div).find('div[data-toggle="MAX_TAB"] .num').val(parseInt(MY_API.CONFIG.MAX_TAB).toString());
$(div).find('div[data-toggle="GIFT_INTERVAL"] .num').val(parseInt(MY_API.CONFIG.GIFT_INTERVAL).toString());
$(div).find('div[data-toggle="LIGHT_MEDALS"] .num').val(MY_API.CONFIG.LIGHT_MEDALS.toString());
$(div).find('div[data-toggle="STORM_MAX_COUNT"] .num').val(parseInt(MY_API.CONFIG.STORM_MAX_COUNT).toString());
$(div).find('div[data-toggle="STORM_ONE_LIMIT"] .num').val(parseInt(MY_API.CONFIG.STORM_ONE_LIMIT).toString());
$(div).find('div[data-toggle="STORM_QUEUE_SIZE"] .num').val(parseInt(MY_API.CONFIG.STORM_QUEUE_SIZE).toString());
$(div).find('div[data-toggle="SPARE_GIFT_ROOM"] .num').val(MY_API.CONFIG.SPARE_GIFT_ROOM.toString());
$(div).find('div[data-toggle="TIME_RELOAD"] .delay-seconds').val(parseInt(MY_API.CONFIG.TIME_RELOAD_MINUTE).toString());
$(div).find('div[data-toggle="RANDOM_SKIP"] .per').val((parseFloat(MY_API.CONFIG.RANDOM_SKIP)).toString());
$(div).find('div[data-toggle="RANDOM_SEND_DANMU"] .per').val((parseFloat(MY_API.CONFIG.RANDOM_SEND_DANMU)).toString());
$(div).find('div[data-toggle="MAX_GIFT"] .num').val((parseInt(MY_API.CONFIG.MAX_GIFT)).toString());
$(div).find('div[data-toggle="COIN"] .coin_number').val(parseInt(MY_API.CONFIG.COIN_NUMBER).toString());
$(div).find('div[data-toggle="COIN_UID"] .num').val(parseInt(MY_API.CONFIG.COIN_UID).toString());
$(div).find('div[data-toggle="RANDOM_DELAY"] .RND_DELAY_START').val(parseFloat(MY_API.CONFIG.RND_DELAY_START).toString());
$(div).find('div[data-toggle="RANDOM_DELAY"] .RND_DELAY_END').val(parseFloat(MY_API.CONFIG.RND_DELAY_END).toString());
$(div).find('div[data-toggle="TIME_AREA_DISABLE"] .startHour').val(parseInt(MY_API.CONFIG.TIME_AREA_START_H0UR).toString());
$(div).find('div[data-toggle="TIME_AREA_DISABLE"] .endHour').val(parseInt(MY_API.CONFIG.TIME_AREA_END_H0UR).toString());
$(div).find('div[data-toggle="TIME_AREA_DISABLE"] .startMinute').val(parseInt(MY_API.CONFIG.TIME_AREA_START_MINUTE).toString());
$(div).find('div[data-toggle="TIME_AREA_DISABLE"] .endMinute').val(parseInt(MY_API.CONFIG.TIME_AREA_END_MINUTE).toString());
$(div).find('div[data-toggle="CHECK_HOUR_ROOM"] .num').val(parseInt(MY_API.CONFIG.CHECK_HOUR_ROOM_INTERVAL).toString());
$(div).find('div[data-toggle="AUTO_GIFT_ROOMID"] .num').val((MY_API.CONFIG.AUTO_GIFT_ROOMID).toString());
$(div).find('div[data-toggle="EXCLUDE_ROOMID"] .num').val((MY_API.CONFIG.EXCLUDE_ROOMID).toString());
$(div).find('div[data-toggle="GIFT_SEND_TIME"] .Hour').val(MY_API.CONFIG.GIFT_SEND_HOUR.toString());
$(div).find('div[data-toggle="GIFT_SEND_TIME"] .Minute').val(MY_API.CONFIG.GIFT_SEND_MINUTE.toString());
$(div).find('div[data-toggle="GIFT_LIMIT"] .num').val(parseInt(MY_API.CONFIG.GIFT_LIMIT).toString());
function saveAction() {
//TIME_AREA_DISABLE(控制输入的两个小时两个分钟)
let val = undefined;
let valArray = undefined;
let val1 = parseInt($(div).find('div[data-toggle="TIME_AREA_DISABLE"] .startHour').val());
let val2 = parseInt($(div).find('div[data-toggle="TIME_AREA_DISABLE"] .endHour').val());
let val3 = parseInt($(div).find('div[data-toggle="TIME_AREA_DISABLE"] .startMinute').val());
let val4 = parseInt($(div).find('div[data-toggle="TIME_AREA_DISABLE"] .endMinute').val());
if (val1 >= 24 || val2 >= 24 || val3 >= 60 || val4 >= 60 || val1 < 0 || val2 < 0 || val3 < 0 || val4 < 0) {
MY_API.chatLog("[定时休眠]时间错误", 'warning');
return
}
MY_API.CONFIG.TIME_AREA_START_H0UR = val1;
MY_API.CONFIG.TIME_AREA_END_H0UR = val2;
MY_API.CONFIG.TIME_AREA_START_MINUTE = val3;
MY_API.CONFIG.TIME_AREA_END_MINUTE = val4;
//RANDOM_SKIP save
val = parseFloat($(div).find('div[data-toggle="RANDOM_SKIP"] .per').val());
if (val < 0 || val > 100) {
MY_API.chatLog('[随机跳过礼物]数据小于0或大于100', 'warning');
return
}
MY_API.CONFIG.RANDOM_SKIP = val;
//RANDOM_SEND_DANMU save
val = parseFloat($(div).find('div[data-toggle="RANDOM_SEND_DANMU"] .per').val());
if (val > 5) {
MY_API.chatLog("[活跃弹幕]为维护直播间弹幕氛围,弹幕发送概率不得大于5%", 'warning');
return
}
else if (val < 0) {
MY_API.chatLog("[活跃弹幕]数据小于0", 'warning');
return
}
MY_API.CONFIG.RANDOM_SEND_DANMU = val;
//MAX_GIFT save
val = parseInt($(div).find('div[data-toggle="MAX_GIFT"] .num').val());
MY_API.CONFIG.MAX_GIFT = val;
//TIME_RELOAD save
val = parseInt($(div).find('div[data-toggle="TIME_RELOAD"] .delay-seconds').val());
if (val <= 0 || val > 10000) {
MY_API.chatLog('[直播间重载时间]数据小于等于0或大于10000', 'warning');
return
}
MY_API.CONFIG.TIME_RELOAD_MINUTE = val;
//RANDOM_DELAY
val = parseFloat($(div).find('div[data-toggle="RANDOM_DELAY"] .RND_DELAY_START').val());
val2 = parseFloat($(div).find('div[data-toggle="RANDOM_DELAY"] .RND_DELAY_END').val());
if (val < 0 || val2 > 100) {
MY_API.chatLog('[抽奖延时]数据小于0或大于100', 'warning');
return
}
else if (val2 <= val) {
MY_API.chatLog('[抽奖延时]数据大小关系不正确', 'warning');
return
}
MY_API.CONFIG.RND_DELAY_START = val;
MY_API.CONFIG.RND_DELAY_END = val2;
//COIN
val = parseInt($(div).find('div[data-toggle="COIN"] .coin_number').val());
if (val < 0 || val > 5) {
MY_API.chatLog("[自动投币]数据小于0或大于5", 'warning');
return
}
MY_API.CONFIG.COIN_NUMBER = val;
//CHECK_HOUR_ROOM_INTERVAL
val = parseInt($(div).find('div[data-toggle="CHECK_HOUR_ROOM"] .num').val());
if (val <= 0) {
MY_API.chatLog("[检查小时榜间隔]数据小于等于0", 'warning');
return
}
MY_API.CONFIG.CHECK_HOUR_ROOM_INTERVAL = val;
//AUTO_GIFT_ROOMID
val = $(div).find('div[data-toggle="AUTO_GIFT_ROOMID"] .num').val();
valArray = val.split(",");
for (let i = 0; i < valArray.length; i++) {
if (valArray[i] === '') {
valArray[i] = 22474988;
}
};
MY_API.CONFIG.AUTO_GIFT_ROOMID = valArray;
//EXCLUDE_ROOMID
val = $(div).find('div[data-toggle="EXCLUDE_ROOMID"] .num').val();
valArray = val.split(",");
for (let i = 0; i < valArray.length; i++) {
if (valArray[i] === '') {
valArray[i] = 0;
}
};
MY_API.CONFIG.EXCLUDE_ROOMID = valArray;
//GIFT_LIMIT
val = parseInt($(div).find('div[data-toggle="GIFT_LIMIT"] .num').val());
MY_API.CONFIG.GIFT_LIMIT = val;
//GIFT_SEND_TIME
val1 = parseInt($(div).find('div[data-toggle="GIFT_SEND_TIME"] .Hour').val());
val2 = parseInt($(div).find('div[data-toggle="GIFT_SEND_TIME"] .Minute').val());
if (val1 < 0 || val2 < 0) {
MY_API.chatLog("[送礼时间]数据小于0", 'warning');
return
}
else if (val1 >= 24 || val2 >= 60) {
MY_API.chatLog("[送礼时间]时间错误", 'warning');
return
}
MY_API.CONFIG.GIFT_SEND_HOUR = val1;
MY_API.CONFIG.GIFT_SEND_MINUTE = val2;
//SPARE_GIFT_ROOM
val = $(div).find('div[data-toggle="SPARE_GIFT_ROOM"] .num').val();
MY_API.CONFIG.SPARE_GIFT_ROOM = val;
//STORM_QUEUE_SIZE
val = parseInt($(div).find('div[data-toggle="STORM_QUEUE_SIZE"] .num').val());
MY_API.CONFIG.STORM_QUEUE_SIZE = val;
//STORM_MAX_COUNT
val = parseInt($(div).find('div[data-toggle="STORM_MAX_COUNT"] .num').val());
MY_API.CONFIG.STORM_MAX_COUNT = val;
//STORM_ONE_LIMIT
val = parseInt($(div).find('div[data-toggle="STORM_ONE_LIMIT"] .num').val());
MY_API.CONFIG.STORM_ONE_LIMIT = val;
//COIN_UID
val = parseInt($(div).find('div[data-toggle="COIN_UID"] .num').val());
MY_API.CONFIG.COIN_UID = val;
//LIGHT_MEDALS
val = $(div).find('div[data-toggle="LIGHT_MEDALS"] .num').val();
valArray = val.split(",");
for (let i = 0; i < valArray.length; i++) {
if (valArray[i] === '') {
valArray[i] = 0;
}
};
MY_API.CONFIG.LIGHT_MEDALS = valArray;
//MAX_TAB
val = parseInt($(div).find('div[data-toggle="MAX_TAB"] .num').val());
MY_API.CONFIG.MAX_TAB = val;
//AUTO_DANMU
val1 = $(div).find('div[data-toggle="AUTO_DANMU"] .Danmu').val();
valArray = val1.split(",");
for (let i = 0; i < valArray.length; i++) {
if (valArray[i] === '') {
valArray[i] = '这是一条弹幕';
}
};
val1 = valArray;
val2 = $(div).find('div[data-toggle="AUTO_DANMU"] .Roomid').val();
valArray = val2.split(",");
for (let i = 0; i < valArray.length; i++) {
if (valArray[i] === '') {
valArray[i] = '22474988';
}
};
val2 = valArray;
val3 = $(div).find('div[data-toggle="AUTO_DANMU"] .Time').val();
valArray = val3.split(",");
for (let i = 0; i < valArray.length; i++) {
if (valArray[i] === '') {
valArray[i] = '10m';
}
};
val3 = valArray;
MY_API.CONFIG.DANMU_CONTENT = val1;
MY_API.CONFIG.DANMU_ROOMID = val2;
MY_API.CONFIG.DANMU_INTERVAL_TIME = val3;
MY_API.saveConfig();
};
function buyFanMedal(room_id) {
return BAPI.live_user.get_anchor_in_room(room_id).then(function (response) {
MYDEBUG('API.live_user.get_anchor_in_room response', response)
if (response.code === 0 && !!response.data.info) {
layer.confirm(`是否消耗20硬币购买UP主【${response.data.info.uname}】的粉丝勋章?`, {
title: '购买勋章',
btn: ['是', '否'] //按钮
}, function () {
return BAPI.link_group.buy_medal(response.data.info.uid).then((re) => {
MYDEBUG('API.link_group.buy_medal re', re);
if (re.code === 0) {
layer.msg('购买成功', {
time: 2000,
icon: 1
});
} else {
layer.msg(`购买失败 ${re.message}`, {
time: 2500,
icon: 2
});
}
});
}, function () {
layer.msg('已取消购买', {
time: 2000
});
});
}
else if (response.code === 0 && response.data.info === undefined) {
layer.msg(`房间不存在`, {
time: 2500
});
}
else {
layer.msg(`检查房间出错 ${response.message}`, {
time: 2500
});
}
});
}
$(div).find('div[id="giftCount"] [data-action="save"]').click(() => {//保存按钮
saveAction();
});
$(div).find('div[data-toggle="BUY_MEDAL"] [data-action="buy_medal"]').click(function () {//购买勋章
const room_id = parseInt($(div).find('div[data-toggle="BUY_MEDAL"] .num').val());
buyFanMedal(room_id);
});
$(div).find('button[data-action="reset"]').click(() => {//重置按钮
MY_API.setDefaults();
});
$(div).find('button[data-action="checkUpdate"]').click(() => {//检查更新按钮
MY_API.checkUpdate();
});
$(div).find('button[data-action="redo_dailyTasks"]').click(() => {//重置每日任务状态
MY_API.ReDoDailyTasks();
});
$(div).find('#resetArea [data-action="countReset"]').click(() => {//清空统计数据按钮
MY_API.GIFT_COUNT = {
COUNT: 0,
SILVER_COUNT: 0,
CLEAR_TS: 0,
};
MY_API.saveGiftCount();
$('#giftCount span:eq(0)').text(MY_API.GIFT_COUNT.COUNT);
$('#giftCount span:eq(1)').text(MY_API.GIFT_COUNT.SILVER_COUNT);
MY_API.chatLog('已重置统计数据');
});
$(div).find('button[data-action="sendGiftNow"]').click(() => {//立刻开始送礼
if (!MY_API.CONFIG.AUTO_GIFT) {
window.toast('[立刻开始送礼]请先勾选【自动送礼】再点击此按钮', 'info');
return
}
SEND_GIFT_NOW = true;
MY_API.Gift.run();
});
$(div).find('button[data-action="lightMedalNow"]').click(() => {//立刻点亮勋章
if (!MY_API.CONFIG.AUTO_GIFT) {
window.toast('[立刻点亮勋章]请先勾选【自动送礼】再点击此按钮', 'info');
return
}
LIGHT_MEDAL_NOW = true;
MY_API.Gift.run();
});
$(div).find('button[data-action="sendDanmuNow"]').click(() => {//立刻发送弹幕
SEND_DANMU_NOW = true;
MY_API.AUTO_DANMU.run();
});
$(div).find('button[data-action="clearDanmuCache"]').click(() => {//清除弹幕缓存
MY_API.CACHE.AUTO_SEND_DANMU_TS = [];
if (MY_API.saveCache()) MY_API.chatLog('清除弹幕缓存成功', 'success');
});
const checkList = [
'AUTO_DANMU',
'RANDOM_DELAY',
'TIME_AREA_DISABLE',
'AUTO_GROUP_SIGN',
'FORCE_LOTTERY',
'LOGIN',
'WATCH',
'COIN',
'SHARE',
'SILVER2COIN',
'LIVE_SIGN',
'IN_TIME_RELOAD_DISABLE',
'TIME_RELOAD',
'IN_TIME_RELOAD_DISABLE',
"AUTO_GIFT",
"SEND_ALL_GIFT",
'STORM',
'LITTLE_HEART',
'REMOVE_ELEMENT_2233',
'REMOVE_ELEMENT_activity',
'REMOVE_ELEMENT_rank',
"FORCE_LIGHT",
"LOTTERY",
"CHECK_HOUR_ROOM",
"NOSLEEP"
];
for (const i of checkList) {//绑定所有checkbox事件
let input = $(div).find(`div[data-toggle="${i}"] input:checkbox`);
if (MY_API.CONFIG[i]) input.attr('checked', '');
input.change(function () {
MY_API.CONFIG[i] = $(this).prop('checked');
MY_API.saveConfig();
});
};
$('input:text').bind('keydown', function (event) {//绑定回车保存
if (event.keyCode == "13") {
saveAction();
}
});
if (MY_API.CONFIG.COIN_TYPE == 'COIN_DYN') {
$("div[data-toggle='COIN_DYN'] input:radio").attr('checked', '');
} else {
$("div[data-toggle='COIN_UID'] input:radio").attr('checked', '');
};
if (MY_API.CONFIG.LIGHT_METHOD == 'LIGHT_WHITE') {
$("div[data-toggle='LIGHT_WHITE'] input:radio").attr('checked', '');
} else {
$("div[data-toggle='LIGHT_BLACK'] input:radio").attr('checked', '');
};
if (MY_API.CONFIG.GIFT_METHOD == 'GIFT_INTERVAL') {
$("div[data-toggle='GIFT_INTERVAL'] input:radio").attr('checked', '');
} else {
$("div[data-toggle='GIFT_SEND_TIME'] input:radio").attr('checked', '');
};
if (MY_API.CONFIG.GIFT_SORT == 'high') {
$("div[data-toggle='GIFT_SORT_HIGH'] input:radio").attr('checked', '');
} else {
$("div[data-toggle='GIFT_SORT_LOW'] input:radio").attr('checked', '');
}
$("input:radio[name='COIN_TYPE']").change(function () { //投币模式变化
if ($("div[data-toggle='COIN_DYN'] input:radio").is(':checked')) {
MY_API.CONFIG.COIN_TYPE = 'COIN_DYN';
}
else {
MY_API.CONFIG.COIN_TYPE = 'COIN_UID';
}
MY_API.saveConfig();
});
$("input:radio[name='LIGHT_TYPE']").change(function () { //点亮勋章模式变化
if ($("div[data-toggle='LIGHT_WHITE'] input:radio").is(':checked')) {
MY_API.CONFIG.LIGHT_METHOD = 'LIGHT_WHITE';
}
else {
MY_API.CONFIG.LIGHT_METHOD = 'LIGHT_BLACK';
}
MY_API.saveConfig();
});
$("input:radio[name='GIFT_TYPE']").change(function () { //送礼模式变化
if ($("div[data-toggle='GIFT_INTERVAL'] input:radio").is(':checked')) {
MY_API.CONFIG.GIFT_METHOD = 'GIFT_INTERVAL';
}
else {
MY_API.CONFIG.GIFT_METHOD = 'GIFT_SEND_TIME';
}
MY_API.saveConfig();
});
$("input:radio[name='GIFT_SORT']").change(function () { //送礼模式变化
if ($("div[data-toggle='GIFT_SORT_HIGH'] input:radio").is(':checked')) {
MY_API.CONFIG.GIFT_SORT = 'high';
}
else {
MY_API.CONFIG.GIFT_SORT = 'low';
}
MY_API.saveConfig();
});
},
end: () => {
msgHide = 'hide';
localStorage.setItem(`${NAME}_msgHide`, msgHide);
$('.igiftMsg').hide();
$('.link-toast').hide();
if ($(lockBtn).attr('class') === 'icon-item icon-font icon-lock-1 active')
$(lockBtn).trigger('click');
else $(lockBtn).trigger('click').trigger('click');
//ct.animate({ scrollTop: 0 }, 0);
//setTimeout(() => { ct.animate({ scrollTop: ct.prop("scrollHeight") }, 10) }, 100);
document.getElementById('hiderbtn').innerHTML = "显示窗口和提示信息";
}
});
};
btn.click(() => {
if (hideBtnClickable) {
hideBtnClickable = false;
setTimeout(function () { hideBtnClickable = true }, 200);
if (msgHide == 'show') {//显示=>隐藏
msgHide = 'hide';
localStorage.setItem(`${NAME}_msgHide`, msgHide);
$('.igiftMsg').hide();
$('.link-toast').hide();
layer.close(mainIndex);
//ct.animate({ scrollTop: 0 }, 0);
//setTimeout(() => { ct.animate({ scrollTop: ct.prop("scrollHeight") }, 10) }, 100);
if ($(lockBtn).attr('class') === 'icon-item icon-font icon-lock-1 active')
$(lockBtn).trigger('click');
else $(lockBtn).trigger('click').trigger('click');
document.getElementById('hiderbtn').innerHTML = "显示窗口和提示信息";
}
else {
msgHide = 'show';
localStorage.setItem(`${NAME}_msgHide`, msgHide);
$('.igiftMsg').show();
$('.link-toast').show();
openMainWindow();
//ct.animate({ scrollTop: ct.prop("scrollHeight") }, 0);
if ($(lockBtn).attr('class') === 'icon-item icon-font icon-lock-1 active')
$(lockBtn).trigger('click');
else $(lockBtn).trigger('click').trigger('click');
document.getElementById('hiderbtn').innerHTML = "隐藏窗口和提示信息";
}
}
});
$('.attention-btn-ctnr').append(btn);
if (!MY_API.CACHE.DailyReward_TS) {
layer.tips('点我隐藏/显示控制面板', '#hiderbtn', {
tips: 1
})
}
if (msgHide == 'show') {
openMainWindow()
}
},
chatLog: function (text, type = 'info') {//自定义提示
let div = $("<div class='igiftMsg'>");
let msg = $("<div>");
let myDate = new Date();
msg.text(text);
div.text(myDate.toLocaleString());
div.append(msg);
div.css({
'text-align': 'center',
'border-radius': '4px',
'min-height': '30px',
'width': '256px',
'color': '#9585FF',
'line-height': '30px',
'padding': '0 10px',
'margin': '10px auto',
});
msg.css({
'word-wrap': 'break-word',
'width': '100%',
'line-height': '1em',
'margin-bottom': '10px',
});
switch (type) {
case 'warning':
div.css({
'border': '1px solid rgb(236, 221, 192)',
'color': 'rgb(218, 142, 36)',
'background': 'rgb(245, 235, 221) none repeat scroll 0% 0%',
});
break;
case 'success':
div.css({
'border': '1px solid rgba(22, 140, 0, 0.28)',
'color': 'rgb(69, 171, 69)',
'background': 'none 0% 0% repeat scroll rgba(16, 255, 0, 0.18)',
});
break;
case 'error':
div.css({
'border': '1px solid rgb(255, 46, 0)',
'color': 'white',
'background': 'none 0% 0% repeat scroll #ff4c4c',
});
break;
default:
div.css({
'border': '1px solid rgb(203, 195, 255)',
'background': 'rgb(233, 230, 255) none repeat scroll 0% 0%',
});
}
if (msgHide == 'show') {//false
ct.find('#chat-items').append(div);//向聊天框加入信息
} else {
ct.find('#chat-items').append(div.hide());//向聊天框加入信息
}
ct.scrollTop(ct.prop("scrollHeight"));//滚动到底部
},
blocked: false,
max_blocked: false,
listen: (roomId, uid, area = '本直播间') => {
BAPI.room.getConf(roomId).then((response) => {
//DanMuServerHost = response.data.host;
MYDEBUG(`获取弹幕服务器信息 ${area}`, response);
let wst = new BAPI.DanmuWebSocket(uid, roomId, response.data.host_server_list, response.data.token);
wst.bind((newWst) => {
wst = newWst;
MY_API.chatLog(`${area}弹幕服务器连接断开,尝试重连`, 'warning');
}, () => {
MY_API.chatLog(`——————连接弹幕服务器成功——————\n房间号: ${roomId} 分区: ${area}`
, 'success');
}, () => {
if (MY_API.blocked || MY_API.stormBlack) {
wst.close();
MY_API.chatLog(`进了小黑屋主动与弹幕服务器断开连接-${area}`, 'warning')
}
if (MY_API.max_blocked && !MY_API.CONFIG.STORM) {
wst.close();
MY_API.chatLog(`辣条最大值主动与弹幕服务器断开连接-${area}`, 'warning')
}
}, (obj) => {
if (inTimeArea(MY_API.CONFIG.TIME_AREA_START_H0UR, MY_API.CONFIG.TIME_AREA_END_H0UR, MY_API.CONFIG.TIME_AREA_START_MINUTE, MY_API.CONFIG.TIME_AREA_END_MINUTE) && MY_API.CONFIG.TIME_AREA_DISABLE) return;//当前是否在两点到八点 如果在则返回
MYDEBUG('弹幕公告' + area, obj);
switch (obj.cmd) {
case 'GUARD_MSG':
if (obj.roomid === obj.real_roomid) {
MY_API.checkRoom(obj.roomid, area);
} else {
MY_API.checkRoom(obj.roomid, area);
MY_API.checkRoom(obj.real_roomid, area);
}
break;
case 'PK_BATTLE_SETTLE_USER':
if (!!obj.data.winner) {
MY_API.checkRoom(obj.data.winner.room_id, area);
} else {
MY_API.checkRoom(obj.data.my_info.room_id, area);
}
MY_API.checkRoom(obj.data.winner.room_id, area);
break;
case 'NOTICE_MSG':
switch (obj.msg_type) {
case 1:// 系统
break;
case 2:
case 3:// 舰队领奖
case 4:// 登船
case 8:// 礼物抽奖
if (obj.roomid === obj.real_roomid) {
MY_API.checkRoom(obj.roomid, area);
} else {
MY_API.checkRoom(obj.roomid, area);
MY_API.checkRoom(obj.real_roomid, area);
}
break;
/*case 4:
// 登船
break;*/
case 5:
// 获奖
break;
case 6:
// 节奏风暴
window.toast(`监控到房间 ${obj.roomid} 的节奏风暴`, 'info');
MY_API.Storm.run(obj.roomid);
break;
}
break;
case 'SPECIAL_GIFT':
//DEBUG(`DanmuWebSocket${area}(${roomid})`, str);
if (obj.data['39']) {
switch (obj.data['39'].action) {
case 'start':
// 节奏风暴开始
window.toast(`监控到房间 ${obj.roomid} 的节奏风暴`, 'info');
MY_API.Storm.run(obj.roomid);
case 'end':
// 节奏风暴结束
}
};
break;
default:
return;
}
});
}, () => {
MY_API.chatLog('获取弹幕服务器地址错误', 'error')
});
},
EntryRoom_list_history: {//进入房间历史记录缓存
add: function (EntryRoom) {
let EntryRoom_list = [];
try {
let config = JSON.parse(localStorage.getItem(`${NAME}_EntryRoom_list`));
EntryRoom_list = [].concat(config.list);
EntryRoom_list.push(EntryRoom);
if (EntryRoom_list.length > 100) {
EntryRoom_list.splice(0, 50);//删除前50条数据
}
localStorage.setItem(`${NAME}_EntryRoom_list`, JSON.stringify({ list: EntryRoom_list }));
MYDEBUG(`${NAME}_EntryRoom_list_add`, EntryRoom_list);
} catch (e) {
EntryRoom_list.push(EntryRoom);
localStorage.setItem(`${NAME}_EntryRoom_list`, JSON.stringify({ list: EntryRoom_list }));
}
},
isIn: function (EntryRoom) {
let EntryRoom_list = [];
try {
let config = JSON.parse(localStorage.getItem(`${NAME}_EntryRoom_list`));
if (config === null) {
EntryRoom_list = [];
} else {
EntryRoom_list = [].concat(config.list);
}
MYDEBUG(`${NAME}_EntryRoom_list_read`, config);
return EntryRoom_list.indexOf(EntryRoom) > -1
} catch (e) {
localStorage.setItem(`${NAME}_EntryRoom_list`, JSON.stringify({ list: EntryRoom_list }));
MYDEBUG('读取' + `${NAME}_EntryRoom_list` + '缓存错误已重置');
return EntryRoom_list.indexOf(EntryRoom) > -1
}
}
},
RoomId_list: [],
err_roomId: [],
auto_danmu_list: ["(=・ω・=)", "( ̄▽ ̄)", "nice", "666", "kksk", "(⌒▽⌒)", "(`・ω・´)", "╮( ̄▽ ̄)╭", "( ̄3 ̄)", "Σ(  ̄□ ̄||)",
"(^・ω・^ )", "_(:3」∠)_"],//共11个
checkRoom: function (roomId, area = '本直播间') {
if (MY_API.blocked || MY_API.max_blocked) {
return
}
if (MY_API.RoomId_list.indexOf(roomId) >= 0) {//防止重复检查直播间
return
} else {
MY_API.RoomId_list.push(roomId);
}
if (!MY_API.EntryRoom_list_history.isIn(roomId) && MY_API.CONFIG.LOTTERY) {
BAPI.room.room_entry_action(roomId);//直播间进入记录
MY_API.EntryRoom_list_history.add(roomId);//加入列表
}
if (probability(MY_API.CONFIG.RANDOM_SEND_DANMU)) {//概率发活跃弹幕
BAPI.room.get_info(roomId).then((res) => {
MYDEBUG(`API.room.get_info roomId=${roomId} res`, res);
BAPI.sendLiveDanmu(MY_API.auto_danmu_list[Math.floor(Math.random() * 12)], res.data.room_id).then((response) => {
MYDEBUG('[活跃弹幕]弹幕发送返回信息', response);
})
})
}//Math.floor(Math.random() * (max - min + 1) ) + min
BAPI.xlive.lottery.check(roomId).then((re) => {
MY_API.RoomId_list.remove(roomId);//移除房间号
MYDEBUG('检查房间返回信息', re);
const data = re.data;
if (re.code === 0) {
if (data.gift) {
const list = data.gift;
for (let i in list) {
if (!list.hasOwnProperty(i)) continue;
MY_API.creat_join(roomId, list[i], 'gift', area)
}
}
if (data.guard) {
const list = data.guard;
for (let i in list) {
if (!list.hasOwnProperty(i)) continue;
MY_API.creat_join(roomId, list[i], 'guard', area)
}
}
if (data.pk) {
const list = data.pk;
for (let i in list) {
if (!list.hasOwnProperty(i)) continue;
MY_API.creat_join(roomId, list[i], 'pk', area)
}
}
} else {
MY_API.chatLog(`[检查房间出错]${response.msg}`, 'error');
if (MY_API.err_roomId.indexOf(roomId) > -1) {
MYDEBUG(`[检查此房间出错多次]${roomId}${re.message}`);
}
else {
MY_API.err_roomId.push(roomId);
MY_API.checkRoom(roomId, area);
MYDEBUG(`[检查房间出错_重试一次]${roomId}${re.message}`);
}
}
})
},
Id_list_history: {//礼物历史记录缓存
add: function (id, type) {
let id_list = [];
try {
let config = JSON.parse(localStorage.getItem(`${NAME}_${type}Id_list`));
id_list = [].concat(config.list);
id_list.push(id);
if (id_list.length > 200) {
id_list.splice(0, 50);//删除前50条数据
}
localStorage.setItem(`${NAME}_${type}Id_list`, JSON.stringify({ list: id_list }));
MYDEBUG(`${NAME}_${type}Id_list_add`, id_list);
} catch (e) {
id_list.push(id);
localStorage.setItem(`${NAME}_${type}Id_list`, JSON.stringify({ list: id_list }));
}
},
isIn: function (id, type) {
let id_list = [];
try {
let config = JSON.parse(localStorage.getItem(`${NAME}_${type}Id_list`));
if (config === null) {
id_list = [];
} else {
id_list = [].concat(config.list);
}
MYDEBUG(`${NAME}_${type}Id_list_read`, config);
return id_list.indexOf(id) > -1
} catch (e) {
localStorage.setItem(`${NAME}_${type}Id_list`, JSON.stringify({ list: id_list }));
MYDEBUG('读取' + `${NAME}_${type}Id_list` + '缓存错误已重置');
return id_list.indexOf(id) > -1
}
}
},
raffleId_list: [],
guardId_list: [],
pkId_list: [],
creat_join: function (roomId, data, type, area = '本直播间') {
MYDEBUG('礼物信息', data);
if (MY_API.GIFT_COUNT.COUNT >= MY_API.CONFIG.MAX_GIFT) {//判断是否超过辣条限制
MYDEBUG('超过今日辣条限制,不参与抽奖');
MY_API.max_blocked = true;
return
}
switch (type) {//防止重复抽奖上船PK
case 'gift':
if (MY_API.Id_list_history.isIn(data.raffleId, 'raffle')) {
MYDEBUG('礼物重复', `raffleId ${data.raffleId}`);
return
} else {
MY_API.raffleId_list.push(data.raffleId);
MY_API.Id_list_history.add(data.raffleId, 'raffle');
}
break;
case 'guard':
if (MY_API.Id_list_history.isIn(data.id, 'guard')) {
MYDEBUG('舰长重复', `id ${data.id}`);
return
} else {
MY_API.guardId_list.push(data.id);
MY_API.Id_list_history.add(data.id, 'guard');
}
break;
case 'pk':
if (MY_API.Id_list_history.isIn(data.id, 'pk')) {
MYDEBUG('pk重复', `id ${data.id}`);
return
} else {
MY_API.pkId_list.push(data.id);
MY_API.Id_list_history.add(data.id, 'pk');
}
break;
}
let delay = data.time_wait || 0;
if (MY_API.CONFIG.RANDOM_DELAY)
delay += Math.floor(Math.random() * (MY_API.CONFIG.RND_DELAY_END - MY_API.CONFIG.RND_DELAY_START + 1)) + MY_API.CONFIG.RND_DELAY_START;
//随机延迟 return Math.floor(Math.random() * (max - min + 1) ) + min; min,max都包括
let div = $("<div class='igiftMsg'>");
let msg = $("<div>");
let aa = $("<div>");
let myDate = new Date();
msg.text(`[${area}]` + data.thank_text.split('<%')[1].split('%>')[0] + data.thank_text.split('%>')[1]);
div.text(myDate.toLocaleString());
div.append(msg);
aa.css('color', 'red');
aa.text('等待抽奖');
msg.append(aa);
div.css({
'text-align': 'center',
'border-radius': '4px',
'min-height': '30px',
'width': '256px',
'color': '#9585FF',
'line-height': '30px',
'padding': '0 10px',
'margin': '10px auto',
'border': '1px solid rgb(203, 195, 255)',
'background': 'rgb(233, 230, 255) none repeat scroll 0% 0%',
});
msg.css({
'word-wrap': 'break-word',
'width': '100%',
'line-height': '1em',
'margin-bottom': '10px',
});
if (msgHide == 'show') {//false
ct.find('#chat-items').append(div);//向聊天框加入信息
} else {
ct.find('#chat-items').append(div.hide());//向聊天框加入信息
}
ct.scrollTop(ct.prop("scrollHeight"));//滚动到底部
let timer = setInterval(() => {
aa.text(`等待抽奖倒计时${delay}秒`);
if (delay <= 0) {
if (probability(MY_API.CONFIG.RANDOM_SKIP)) {
aa.text(`跳过此礼物抽奖`);
} else {
aa.text(`进行抽奖...`);
switch (type) {
case 'gift':
MY_API.gift_join(roomId, data.raffleId, data.type).then(function (msg, num) {
aa.text(msg);
if (num) {
if (msg.indexOf('辣条') > -1) {
MY_API.addGift(num);
}
else if (msg.indexOf('银瓜子') > -1) {
MY_API.addSilver(num);
}
}
MY_API.raffleId_list.remove(data.raffleId);//移除礼物id列表
});
break;
case 'guard':
MY_API.guard_join(roomId, data.id).then(function (msg, num) {
aa.text(msg);
if (num) {
if (msg.indexOf('辣条') > -1) {
MY_API.addGift(num);
}
else if (msg.indexOf('银瓜子') > -1) {
MY_API.addSilver(num);
}
}
MY_API.guardId_list.remove(data.id);//移除礼物id列表
});
break;
case 'pk':
MY_API.pk_join(roomId, data.id).then(function (msg, num) {
aa.text(msg);
if (num) {
if (msg.indexOf('辣条') > -1) {
MY_API.addGift(num);
}
else if (msg.indexOf('银瓜子') > -1) {
MY_API.addSilver(num);
}
}
MY_API.pkId_list.remove(data.id);//移除礼物id列表
});
break;
}
}
aa.css('color', 'green');
clearInterval(timer)
}
delay--;
}, 1000);
},
gift_join: function (roomid, raffleId, type) {
let p = $.Deferred();
BAPI.Lottery.Gift.join(roomid, raffleId, type).then((response) => {
MYDEBUG('抽奖返回信息', response);
switch (response.code) {
case 0:
if (response.data.award_text) {
p.resolve(response.data.award_text, response.data.award_num);
} else {
p.resolve(response.data.award_name + 'X' + response.data.award_num.toString()
, response.data.award_num);
}
break;
default:
if (response.msg.indexOf('拒绝') > -1) {
if (MY_API.CONFIG.FORCE_LOTTERY == false) {
MY_API.blocked = true;//停止抽奖
p.resolve('访问被拒绝,您的帐号可能已经被关小黑屋,已停止');
} else if (++gift_join_try <= 5) {
MY_API.gift_join(roomid, raffleId, type);
} else {
gift_join_try = 0;
p.resolve(`[礼物抽奖](roomid=${roomid},id=${raffleId},type=${type})${response.msg}`);
}
} else {
p.resolve(`[礼物抽奖](roomid=${roomid},id=${raffleId},type=${type})${response.msg}`);
}
}
});
return p
},
guard_join: function (roomid, Id) {
let p = $.Deferred();
BAPI.Lottery.Guard.join(roomid, Id).then((response) => {
MYDEBUG('上船抽奖返回信息', response);
switch (response.code) {
case 0:
if (response.data.award_text) {
p.resolve(response.data.award_text, response.data.award_num);
} else {
p.resolve(response.data.award_name + 'X' + response.data.award_num.toString()
, response.data.award_num);
}
break;
default:
if (response.msg.indexOf('拒绝') > -1) {
if (MY_API.CONFIG.FORCE_LOTTERY == false) {
MY_API.blocked = true;//停止抽奖
p.resolve('访问被拒绝,您的帐号可能已经被关小黑屋,已停止');
} else if (++guard_join_try <= 5) { //若被拒绝则再次尝试,最高五次
MY_API.guard_join(roomid, id);
} else {
guard_join_try = 0;
p.resolve(`[礼物抽奖](roomid=${roomid},id=${raffleId},type=${type})${response.msg}`);
}
} else {
p.resolve(`[上船](roomid=${roomid},id=${Id})${response.msg}`);
}
break;
}
});
return p
},
pk_join: function (roomid, Id) {
let p = $.Deferred();
BAPI.Lottery.Pk.join(roomid, Id).then((response) => {
MYDEBUG('PK抽奖返回信息', response);
switch (response.code) {
case 0:
if (response.data.award_text) {
p.resolve(response.data.award_text, response.data.award_num);
} else {
p.resolve(response.data.award_name + 'X' + response.data.award_num.toString()
, response.data.award_num);
}
break;
default:
if (response.msg.indexOf('拒绝') > -1) {
if (MY_API.CONFIG.FORCE_LOTTERY == false) {
MY_API.blocked = true;//停止抽奖
p.resolve('访问被拒绝,您的帐号可能已经被关小黑屋,已停止');
} else if (++pk_join_try <= 5) {
MY_API.pk_join(roomid, id);
} else {
pk_join_try = 0;
p.resolve(`[礼物抽奖](roomid=${roomid},id=${raffleId},type=${type})${response.msg}`);
}
} else {
p.resolve(`[PK](roomid=${roomid},id=${Id})${response.msg}`);
}
break;
}
});
return p
},
GroupSign: {
getGroups: () => {//获取应援团列表
return BAPI.Group.my_groups().then((response) => {
MYDEBUG('GroupSign.getGroups: API.Group.my_groups', response);
if (response.code === 0) return $.Deferred().resolve(response.data.list);
window.toast(`[自动应援团签到]'${response.msg}`, 'caution');
return $.Deferred().reject();
}, () => {
window.toast('[自动应援团签到]获取应援团列表失败,请检查网络', 'error');
return delayCall(() => MY_API.GroupSign.getGroups());
});
},
signInList: (list, i = 0) => {//应援团签到
if (i >= list.length) return $.Deferred().resolve();
const obj = list[i];
//自己不能给自己的应援团应援
if (obj.owner_uid == Live_info.uid) return MY_API.GroupSign.signInList(list, i + 1);
return BAPI.Group.sign_in(obj.group_id, obj.owner_uid).then((response) => {
MYDEBUG('GroupSign.signInList: API.Group.sign_in', response);
let p = $.Deferred();
if (response.code === 0) {
if (response.data.add_num > 0) {// || response.data.status === 1
window.toast(`[自动应援团签到]应援团(group_id=${obj.group_id},owner_uid=${obj.owner_uid})签到成功,当前勋章亲密度+${response.data.add_num}`, 'success');
p.resolve();
}
else if (response.data.add_num == 0) {
window.toast(`[自动应援团签到]应援团(group_id=${obj.group_id},owner_uid=${obj.owner_uid})已签到`, 'caution');
p.resolve();
}
else {
p.reject();
}
} else {
window.toast(`[自动应援团签到]'${response.msg}`, 'caution');
//return MY_API.GroupSign.signInList(list, i);
return $.Deferred().reject();
}
return $.when(MY_API.GroupSign.signInList(list, i + 1), p);
}, () => {
window.toast(`[自动应援团签到]应援团(group_id=${obj.group_id},owner_uid=${obj.owner_uid})签到失败,请检查网络`, 'error');
return delayCall(() => MY_API.GroupSign.signInList(list, i));
});
},
run: () => {//执行应援团任务
try {
if (!MY_API.CONFIG.AUTO_GROUP_SIGN) return $.Deferred().resolve();
if (!checkNewDay(MY_API.CACHE.AUTO_GROUP_SIGH_TS)) {
runTomorrow(MY_API.GroupSign.run, 8, 0, '应援团签到');
return $.Deferred().resolve();
} else if (new Date().getHours() < 8 && MY_API.CACHE.AUTO_GROUP_SIGH_TS != 0) {
setTimeout(MY_API.GroupSign.run, getIntervalTime(8, 0));
return $.Deferred().resolve();
}
return MY_API.GroupSign.getGroups().then((list) => {
return MY_API.GroupSign.signInList(list).then(() => {
MY_API.CACHE.AUTO_GROUP_SIGH_TS = ts_ms();
MY_API.saveCache();
runTomorrow(MY_API.GroupSign.run, 8, 0, '应援团签到');
return $.Deferred().resolve();
}, () => delayCall(() => MY_API.GroupSign.run()));
}, () => delayCall(() => MY_API.GroupSign.run()));
} catch (err) {
window.toast('[自动应援团签到]运行时出现异常,已停止', 'error');
console.error(`[${NAME}]`, err);
return $.Deferred().reject();
}
}
}, //"api.live.bilibili.com"
DailyReward: {//每日任务
coin_exp: 0,
login: () => {
return BAPI.DailyReward.login().then(() => {
MYDEBUG('DailyReward.login: API.DailyReward.login');
window.toast('[自动每日奖励][每日登录(不可用)]完成', 'success');
}, () => {
window.toast('[自动每日奖励][每日登录(不可用)]完成失败,请检查网络', 'error');
return delayCall(() => MY_API.DailyReward.login());
});
},
watch: (aid, cid) => {
if (!MY_API.CONFIG.WATCH) return $.Deferred().resolve();
return BAPI.DailyReward.watch(aid, cid, Live_info.uid, ts_s()).then((response) => {
MYDEBUG('DailyReward.watch: API.DailyReward.watch', response);
if (response.code === 0) {
window.toast(`[自动每日奖励][每日观看]完成(av=${aid})`, 'success');
} else {
window.toast(`[自动每日奖励][每日观看]'${response.msg}`, 'caution');
}
}, () => {
window.toast('[自动每日奖励][每日观看]完成失败,请检查网络', 'error');
return delayCall(() => MY_API.DailyReward.watch(aid, cid));
});
},
coin: (cards, n, i = 0, one = false) => {
if (!MY_API.CONFIG.COIN) return $.Deferred().resolve();
if (MY_API.DailyReward.coin_exp >= MY_API.CONFIG.COIN_NUMBER * 10) {
window.toast('[自动每日奖励][每日投币]今日投币已完成', 'info');
return $.Deferred().resolve();
}
if (i >= cards.length) {
window.toast('[自动每日奖励][每日投币]动态里可投币的视频不足', 'caution');
return $.Deferred().resolve();
}
const obj = JSON.parse(cards[i].card);
let num = Math.min(2, n);
if (one) num = 1;
return BAPI.x.getCoinInfo('', 'jsonp', obj.aid, ts_ms()).then((re) => {
if (re.data.multiply === 2) {
MYDEBUG('API.x.getCoinInfo', `已投币两个 aid = ${obj.aid}`)
return MY_API.DailyReward.coin(vlist, n, i + 1);
}
else {
if (re.data.multiply === 1) num = 1;
return BAPI.DailyReward.coin(obj.aid, num).then((response) => {
MYDEBUG('DailyReward.coin: API.DailyReward.coin', response);
if (response.code === 0) {
MY_API.DailyReward.coin_exp += num * 10;
window.toast(`[自动每日奖励][每日投币]投币成功(av=${obj.aid},num=${num})`, 'success');
return MY_API.DailyReward.coin(cards, n - num, i + 1);
} else if (response.code === -110) {
window.toast('[自动每日奖励][每日投币]未绑定手机,已停止', 'error');
return $.Deferred().reject();
} else if (response.code === 34003) {
// 非法的投币数量
if (one) return MY_API.DailyReward.coin(cards, n, i + 1);
return MY_API.DailyReward.coin(cards, n, i, true);
} else if (response.code === 34005) {
// 塞满啦!先看看库存吧~
return MY_API.DailyReward.coin(cards, n, i + 1);
} else if (response.code === -104) {
//硬币余额不足
window.toast('[自动每日奖励][每日投币]剩余硬币不足,已停止', 'warning');
return $.Deferred().reject();
}
window.toast(`[自动每日奖励][每日投币]'${response.msg}`, 'caution');
return MY_API.DailyReward.coin(cards, n, i + 1);
}, () => delayCall(() => MY_API.DailyReward.coin(cards, n, i)));
}
})
},
coin_uid: (vlist, n, pagenum, uid, i = 0, one = false) => {
if (!MY_API.CONFIG.COIN) return $.Deferred().resolve();
if (MY_API.DailyReward.coin_exp >= MY_API.CONFIG.COIN_NUMBER * 10) {
window.toast('[自动每日奖励][每日投币]今日投币已完成', 'info');
return $.Deferred().resolve();
}
if (i >= vlist.length) {
MY_API.DailyReward.UserSpace(MY_API.CONFIG.COIN_UID, 30, 0, pagenum++, '', 'pubdate', 'jsonp');
}
const obj = vlist[i];
if (obj.is_union_video === 1 || obj.mid != uid) {
MYDEBUG('DailyReward.coin_uid', `联合投稿且UP不是指定UID用户 aid = ${obj.aid}`)
return MY_API.DailyReward.coin_uid(vlist, n, pagenum, uid, i + 1);
}
let num = Math.min(2, n);
if (one) num = 1;
return BAPI.x.getCoinInfo('', 'jsonp', obj.aid, ts_ms()).then((re) => {
if (re.data.multiply === 2) {
MYDEBUG('API.x.getCoinInfo', `已投币两个 aid = ${obj.aid}`)
return MY_API.DailyReward.coin_uid(vlist, n, pagenum, uid, i + 1);
}
else {
if (re.data.multiply === 1) num = 1;
return BAPI.DailyReward.coin(obj.aid, num).then((response) => {
MYDEBUG('DailyReward.coin_uid: API.DailyReward.coin_uid', response);
if (response.code === 0) {
MY_API.DailyReward.coin_exp += num * 10;
window.toast(`[自动每日奖励][每日投币]投币成功(av=${obj.aid},num=${num})`, 'success');
return MY_API.DailyReward.coin_uid(vlist, n - num, pagenum, uid, i + 1);
} else if (response.code === -110) {
window.toast('[自动每日奖励][每日投币]未绑定手机,已停止', 'error');
return $.Deferred().reject();
} else if (response.code === 34003) {
// 非法的投币数量
if (one) return MY_API.DailyReward.coin_uid(vlist, n, pagenum, uid, i + 1);
return MY_API.DailyReward.coin_uid(vlist, n, i, pagenum, uid, true);
} else if (response.code === 34005) {
// 塞满啦!先看看库存吧~
return MY_API.DailyReward.coin_uid(vlist, n, pagenum, uid, i + 1);
} else if (response.code === -104) {
//硬币余额不足
window.toast('[自动每日奖励][每日投币]剩余硬币不足,已停止', 'warning');
return $.Deferred().reject();
}
window.toast(`[自动每日奖励][每日投币]'${response.msg}`, 'caution');
return MY_API.DailyReward.coin_uid(vlist, n, pagenum, uid, i + 1);
}, () => delayCall(() => MY_API.DailyReward.coin_uid(vlist, n, pagenum, uid, i)));
}
});
},
share: (aid) => {
if (!MY_API.CONFIG.SHARE) return $.Deferred().resolve();
return BAPI.DailyReward.share(aid).then((response) => {
MYDEBUG('DailyReward.share: API.DailyReward.share', response);
if (response.code === 0) {
window.toast(`[自动每日奖励][每日分享]分享成功(av=${aid})`, 'success');
} else if (response.code === 71000) {
// 重复分享
window.toast('[自动每日奖励][每日分享]今日分享已完成', 'info');
} else {
window.toast(`[自动每日奖励][每日分享]'${response.msg}`, 'caution');
}
}, () => {
window.toast('[自动每日奖励][每日分享]分享失败,请检查网络', 'error');
return delayCall(() => MY_API.DailyReward.share(aid));
});
},
dynamic: async () => {
const coinNum = MY_API.CONFIG.COIN_NUMBER - MY_API.DailyReward.coin_exp / 10;
const throwCoinNum = await BAPI.getuserinfo().then((re) => {
MYDEBUG('DailyReward.dynamic: API.getuserinfo', re);
if (re.data.biliCoin < coinNum) return re.data.biliCoin
else return coinNum
});
if (throwCoinNum < coinNum) window.toast(`[自动每日奖励][每日投币]剩余硬币不足,仅能投${throwCoinNum}个币`, 'warning');
return BAPI.dynamic_svr.dynamic_new(Live_info.uid, 8).then((response) => {
MYDEBUG('DailyReward.dynamic: API.dynamic_svr.dynamic_new', response);
if (response.code === 0) {
if (!!response.data.cards) {
const obj = JSON.parse(response.data.cards[0].card);
const p1 = MY_API.DailyReward.watch(obj.aid, obj.cid);
let p2;
if (MY_API.CONFIG.COIN_UID == 0 || MY_API.CONFIG.COIN_TYPE == 'COIN_DYN') {
p2 = MY_API.DailyReward.coin(response.data.cards, Math.max(throwCoinNum, 0));
} else {
p2 = MY_API.DailyReward.UserSpace(MY_API.CONFIG.COIN_UID, 30, 0, 1, '', 'pubdate', 'jsonp');
}
const p3 = MY_API.DailyReward.share(obj.aid);
return $.when(p1, p2, p3);
} else {
window.toast('[自动每日奖励]"动态-投稿视频"中暂无动态', 'info');
}
} else {
window.toast(`[自动每日奖励]获取"动态-投稿视频"'${response.msg}`, 'caution');
}
}, () => {
window.toast('[自动每日奖励]获取"动态-投稿视频"失败,请检查网络', 'error');
return delayCall(() => MY_API.DailyReward.dynamic());
});
},
UserSpace: (uid, ps, tid, pn, keyword, order, jsonp) => {
return BAPI.x.getUserSpace(uid, ps, tid, pn, keyword, order, jsonp).then((response) => {
MYDEBUG('DailyReward.UserSpace: API.dynamic_svr.UserSpace', response);
if (response.code === 0) {
if (!!response.data.list.vlist) {
const throwCoinNum = MY_API.CONFIG.COIN_NUMBER - MY_API.DailyReward.coin_exp / 10;
const p1 = MY_API.DailyReward.coin_uid(response.data.list.vlist, Math.max(throwCoinNum, 0), pn, uid);
return p1;
} else {
window.toast('[自动每日奖励]"空间-投稿视频"中暂无视频', 'info');
}
}
else {
window.toast(`[自动每日奖励]获取"空间-投稿视频"'${response.msg}`, 'caution');
}
}, () => {
window.toast('[自动每日奖励]获取"空间-投稿视频"失败,请检查网络', 'error');
return delayCall(() => MY_API.DailyReward.UserSpace(uid, ps, tid, pn, keyword, order, jsonp));
})
},
run: () => {
try {
if (!MY_API.CONFIG.LOGIN && !MY_API.CONFIG.COIN && !MY_API.CONFIG.WATCH) return $.Deferred().resolve();
if (!checkNewDay(MY_API.CACHE.DailyReward_TS)) {
// 同一天,不执行每日任务
runMidnight(MY_API.DailyReward.run, '每日任务');
return $.Deferred().resolve();
}
return BAPI.DailyReward.exp().then((response) => {
MYDEBUG('DailyReward.run: API.DailyReward.exp', response);
if (response.code === 0) {
MY_API.DailyReward.coin_exp = response.number;
MY_API.DailyReward.login();
MY_API.DailyReward.dynamic();
MY_API.CACHE.DailyReward_TS = ts_ms();
MY_API.saveCache();
runMidnight(MY_API.DailyReward.run, '每日任务');
} else {
window.toast(`[自动每日奖励]${response.message}`, 'caution');
}
}, () => {
window.toast('[自动每日奖励]获取每日奖励信息失败,请检查网络', 'error');
return delayCall(() => MY_API.DailyReward.run());
});
} catch (err) {
window.toast('[自动每日奖励]运行时出现异常', 'error');
console.error(`[${NAME}]`, err);
return $.Deferred().reject();
}
}
}, // Once Run every day "api.live.bilibili.com"
LiveReward: {
dailySignIn: () => {
return BAPI.xlive.dosign().then((response) => {
MYDEBUG('LiveReward.dailySignIn: API.xlive.dosign', response);
if (response.code === 0) {
window.toast('[自动直播签到]完成', 'success')
} else if (response.code === 1011040) {
window.toast('[自动直播签到]今日直播签到已完成', 'info')
} else {
window.toast(`[自动直播签到]${response.message}`, 'caution')
}
}, () => {
window.toast('[自动直播签到]直播签到失败,请检查网络', 'error');
return delayCall(() => MY_API.LiveReward.dailySignIn());
});
},
run: () => {
try {
if (!MY_API.CONFIG.LIVE_SIGN) return $.Deferred().resolve();
if (!checkNewDay(MY_API.CACHE.LiveReward_TS)) {
// 同一天,不执行
runMidnight(MY_API.LiveReward.run, '直播签到');
return $.Deferred().resolve();
}
MY_API.LiveReward.dailySignIn()
MY_API.CACHE.LiveReward_TS = ts_ms();
MY_API.saveCache();
runMidnight(MY_API.LiveReward.run, '直播签到');
} catch (err) {
window.toast('[自动直播签到]运行时出现异常', 'error');
console.error(`[${NAME}]`, err);
return $.Deferred().reject();
}
}
},
Exchange: {
silver2coin: () => {
return BAPI.Exchange.silver2coin().then((response) => {
MYDEBUG('Exchange.silver2coin: API.SilverCoinExchange.silver2coin', response);
if (response.code === 0) {
window.toast(`[银瓜子换硬币]${response.msg}`, 'success');// 兑换成功
} else if (response.code === 403) {
window.toast(`[银瓜子换硬币]${response.msg}`, 'info');// 每天最多能兑换 1 个or银瓜子余额不足
} else {
window.toast(`[银瓜子换硬币]${response.msg}`, 'caution');
}
}, () => {
window.toast('[银瓜子换硬币]兑换失败,请检查网络', 'error');
return delayCall(() => MY_API.Exchange.silver2coin());
});
},
runS2C: () => {
try {
if (!MY_API.CONFIG.SILVER2COIN) return $.Deferred().resolve();
if (!checkNewDay(MY_API.CACHE.Silver2Coin_TS)) {
// 同一天,不再兑换硬币
runMidnight(MY_API.Exchange.runS2C, '瓜子换硬币');
return $.Deferred().resolve();
}
return MY_API.Exchange.silver2coin().then(() => {
MY_API.CACHE.Silver2Coin_TS = ts_ms();
MY_API.saveCache();
runMidnight(MY_API.Exchange.runS2C, '瓜子换硬币');
}, () => delayCall(() => MY_API.Exchange.runS2C()));
} catch (err) {
window.toast('[银瓜子换硬币]运行时出现异常,已停止', 'error');
console.error(`[${NAME}]`, err);
return $.Deferred().reject();
}
}
}, // Once Run every day
Gift: {
run_timer: undefined,
ruid: undefined,
room_id: undefined,
medal_list: undefined,
bag_list: undefined,
time: undefined,
remain_feed: undefined,
over: false,
run_timer: undefined,
//notSendGiftList: [3, 4, 9, 10, 39, 30588, 30587, 30586, 30585],
//B坷垃,喵娘,爱心便当,蓝白胖次,节奏风暴,如意小香包,软糯白糖粽,飘香大肉粽,端午茗茶
sendGiftList: [1, 6, 30607],//辣条,亿圆, 小心心
getMedalList: async (page = 1) => {
if (page === 1) MY_API.Gift.medal_list = [];
return await BAPI.i.medal(page, 25).then((response) => {
MYDEBUG('Gift.getMedalList: API.i.medal', response);
MY_API.Gift.medal_list = MY_API.Gift.medal_list.concat(response.data.fansMedalList);
if (response.data.pageinfo.curPage < response.data.pageinfo.totalpages) return MY_API.Gift.getMedalList(page + 1);
}, () => {
window.toast('[自动送礼]获取勋章列表失败,请检查网络', 'error');
return delayCall(() => MY_API.Gift.getMedalList());
});
},
getBagList: async () => {
return await BAPI.gift.bag_list().then((response) => {
MYDEBUG('Gift.getBagList: API.gift.bag_list', response);
MY_API.Gift.bag_list = response.data.list;
MY_API.Gift.time = response.data.time;
}, () => {
window.toast('[自动送礼]获取包裹列表失败,请检查网络', 'error');
return delayCall(() => MY_API.Gift.getBagList());
});
},
getFeedByGiftID: (gift_id) => {
if (gift_id === 30607) return 50;//小心心
for (let i = Live_info.gift_list.length - 1; i >= 0; --i) {
if (Live_info.gift_list[i].id === gift_id) {
return Math.ceil(Live_info.gift_list[i].price / 100);
}
}
return 0;
},
sort_medals: (medals) => {
if (MY_API.CONFIG.GIFT_SORT == 'high') {
medals.sort((a, b) => {
if (b.level - a.level == 0) {
return b.intimacy - a.intimacy;
}
return b.level - a.level;
});
} else {
medals.sort((a, b) => {
if (a.level - b.level == 0) {
return a.intimacy - b.intimacy;
}
return a.level - b.level;
});
}
if (MY_API.CONFIG.AUTO_GIFT_ROOMID && MY_API.CONFIG.AUTO_GIFT_ROOMID.length > 0) {
let sortRooms = MY_API.CONFIG.AUTO_GIFT_ROOMID;
sortRooms.reverse();
for (let froom of sortRooms) {
let rindex = medals.findIndex(r => r.roomid == froom);
if (rindex != -1) {
let tmp = medals[rindex];
medals.splice(rindex, 1);
medals.unshift(tmp);
}
}
}
return medals;
},
auto_light: async (medal_list) => {
try {
const feed = MY_API.Gift.getFeedByGiftID(30607);//小心心
let light_roomid = MY_API.CONFIG.LIGHT_MEDALS;
let unLightedMedals = undefined;
if (MY_API.CONFIG.LIGHT_METHOD == 'LIGHT_WHITE') {//白名单
unLightedMedals = medal_list.filter(m => m.is_lighted == 0 && m.day_limit - m.today_feed >= feed &&
light_roomid.findIndex(it => it == m.roomid) >= 0)
} else {//黑名单
unLightedMedals = medal_list.filter(m => m.is_lighted == 0 && m.day_limit - m.today_feed >= feed &&
light_roomid.findIndex(it => it == m.roomid) == -1)
};
MYDEBUG('[auto_light]即将点亮勋章房间列表', unLightedMedals);
if (unLightedMedals && unLightedMedals.length > 0) {
unLightedMedals = MY_API.Gift.sort_medals(unLightedMedals);
await MY_API.Gift.getBagList();
let heartBags = MY_API.Gift.bag_list.filter(r => r.gift_id == 30607);
if (heartBags && heartBags.length > 0) {
for (let medal of unLightedMedals) {
let gift = heartBags.find(g => g.gift_id == 30607 && g.gift_num > 0);
if (gift) {
let remain_feed = medal.day_limit - medal.today_feed;
if (remain_feed - feed >= 0 || MY_API.CONFIG.FORCE_LIGHT) {
let response = await BAPI.room.room_init(parseInt(medal.roomid, 10));
let send_room_id = parseInt(response.data.room_id, 10);
let feed_num = 1;
let rsp = await BAPI.gift.bag_send(Live_info.uid, 30607, medal.target_id, feed_num, gift.bag_id, send_room_id, Live_info.rnd)
if (rsp.code === 0) {
gift.gift_num -= feed_num;
medal.today_feed += feed_num * feed;
remain_feed -= feed_num * feed;
window.toast(`[自动送礼]勋章[${medal.medalName}]点亮成功,送出${feed_num}个${gift.gift_name},[${medal.today_feed}/${medal.day_limit}]距离升级还需[${remain_feed}]`, 'success');
MYDEBUG('Gift.auto_light', `勋章[${medal.medalName}]点亮成功,送出${feed_num}个${gift.gift_name},[${medal.today_feed}/${medal.day_limit}]`)
} else {
window.toast(`[自动送礼]勋章[${medal.medalName}]点亮失败【${rsp.msg}】`, 'caution');
}
}
continue;
}
break;
}
}
}
} catch (e) {
console.error(e);
window.toast(`[自动送礼]点亮勋章出错:${e}`, 'error');
}
},
run: async () => {
const FailFunc = () => {
window.toast('[自动送礼]送礼失败,请检查网络', 'error');
return delayCall(() => MY_API.Gift.run());
};
const nextTimeDebug = () => {
if (MY_API.CONFIG.GIFT_METHOD == "GIFT_SEND_TIME") {
let alternateTime = getIntervalTime(MY_API.CONFIG.GIFT_SEND_HOUR, MY_API.CONFIG.GIFT_SEND_MINUTE);
MY_API.Gift.run_timer = setTimeout(MY_API.Gift.run, alternateTime);
let runTime = new Date(ts_ms() + alternateTime).toLocaleString();
MYDEBUG("[自动送礼]", `将在${runTime}进行自动送礼`);
MY_API.CACHE.Gift_TS = ts_ms();
MY_API.saveCache();
} else {
MYDEBUG("[自动送礼]", `将在${MY_API.CONFIG.GIFT_INTERVAL}分钟后进行自动送礼`);
MY_API.CACHE.GiftInterval_TS = ts_ms();
MY_API.saveCache();
}
return
}
try {
if (!MY_API.CONFIG.AUTO_GIFT) return $.Deferred().resolve();
if (MY_API.Gift.run_timer) clearTimeout(MY_API.Gift.run_timer);
if (MY_API.CONFIG.GIFT_METHOD == "GIFT_SEND_TIME" && !isTime(MY_API.CONFIG.GIFT_SEND_HOUR, MY_API.CONFIG.GIFT_SEND_MINUTE) && !SEND_GIFT_NOW && !LIGHT_MEDAL_NOW) {
let alternateTime = getIntervalTime(MY_API.CONFIG.GIFT_SEND_HOUR, MY_API.CONFIG.GIFT_SEND_MINUTE);
MY_API.Gift.run_timer = setTimeout(MY_API.Gift.run, alternateTime);
let runTime = new Date(ts_ms() + alternateTime).toLocaleString();
MYDEBUG("[自动送礼]", `将在${runTime}进行自动送礼`);
return $.Deferred().resolve();
} else if (MY_API.CONFIG.GIFT_METHOD == "GIFT_INTERVAL" && !SEND_GIFT_NOW && !LIGHT_MEDAL_NOW) {
let GiftInterval = MY_API.CONFIG.GIFT_INTERVAL * 60e3;
if (MY_API.CACHE.GiftInterval_TS) {
const interval = ts_ms() - MY_API.CACHE.GiftInterval_TS;
if (interval < GiftInterval) {
let intervalTime = GiftInterval - interval;
MY_API.Gift.run_timer = setTimeout(MY_API.Gift.run, intervalTime);
MYDEBUG("[自动送礼]", `将在${intervalTime}毫秒后进行自动送礼`);
return;
}
}
else {
MY_API.CACHE.GiftInterval_TS = ts_ms();
MY_API.saveCache();
}
}
MY_API.Gift.over = false
await MY_API.Gift.getMedalList();
let medal_list = MY_API.Gift.medal_list;
MYDEBUG('Gift.run: Gift.getMedalList().then: Gift.medal_list', medal_list);
if (medal_list && medal_list.length > 0) {
medal_list = medal_list.filter(it => it.day_limit - it.today_feed > 0 && it.level < 20);
medal_list = MY_API.Gift.sort_medals(medal_list);
//排除直播间
if (MY_API.CONFIG.EXCLUDE_ROOMID && MY_API.CONFIG.EXCLUDE_ROOMID.length > 0) {
const ArrayEXCLUDE_ROOMID = MY_API.CONFIG.EXCLUDE_ROOMID;
medal_list = medal_list.filter(Er => ArrayEXCLUDE_ROOMID.findIndex(exp => exp == Er.roomid) == -1);
};
await MY_API.Gift.auto_light(medal_list);//点亮勋章
if (LIGHT_MEDAL_NOW) {
LIGHT_MEDAL_NOW = false;
return $.Deferred().resolve();
}
for (let v of medal_list) {
if (MY_API.Gift.over) break;
let response = await BAPI.room.room_init(parseInt(v.roomid, 10));
MY_API.Gift.room_id = parseInt(response.data.room_id, 10);
MY_API.Gift.ruid = v.target_id;
MY_API.Gift.remain_feed = v.day_limit - v.today_feed;
if (MY_API.Gift.remain_feed > 0) {
await MY_API.Gift.getBagList();
if (MY_API.Gift.remain_feed > 0) {
window.toast(`[自动送礼]勋章[${v.medalName}] 今日亲密度未满[${v.today_feed}/${v.day_limit}],预计需要[${MY_API.Gift.remain_feed}]送礼开始`, 'info');
await MY_API.Gift.sendGift(v);
} else {
window.toast(`[自动送礼]勋章[${v.medalName}] 今日亲密度已满`, 'info');
}
}
}
}
await MY_API.Gift.sendRemainGift(MY_API.CONFIG.SPARE_GIFT_ROOM);
} catch (err) {
FailFunc();
window.toast('[自动送礼]运行时出现异常,已停止', 'error');
console.error(`[${NAME}]`, err);
return $.Deferred().reject();
}
SEND_GIFT_NOW = false;
nextTimeDebug();
return $.Deferred().resolve();
},
sendGift: async (medal) => {
await MY_API.Gift.getBagList();
let bag_list;
if (MY_API.Gift.remain_feed <= 0) {
window.toast(`[自动送礼]勋章[${medal.medalName}] 送礼结束,今日亲密度已满[${medal.today_feed}/${medal.day_limit}]`, 'info');
return $.Deferred().resolve();
}
if (MY_API.Gift.time <= 0) MY_API.Gift.time = ts_s();
if (!MY_API.CONFIG.SEND_ALL_GIFT) {
//送之前查一次有没有可送的
let pass = MY_API.Gift.bag_list.filter(r => MY_API.Gift.sendGiftList.includes(r.gift_id) && r.gift_num > 0 &&
r.corner_mark.substring(0, r.corner_mark.indexOf("天")) <= MY_API.CONFIG.GIFT_LIMIT);
MYDEBUG("pass", pass)
if (pass.length == 0) {
MY_API.Gift.over = true;
return;
} else {
bag_list = pass;
}
} else {
let pass = MY_API.Gift.bag_list.filter(r => r.gift_num > 0 && r.corner_mark != '永久');
if (pass.length == 0) {
MY_API.Gift.over = true;
return;
} else {
bag_list = pass;
}
}
MYDEBUG('bag_list', bag_list)
for (let v of bag_list) {
if (medal.day_limit - medal.today_feed <= 0) {
window.toast(`[自动送礼]勋章[${medal.medalName}] 送礼结束,今日亲密度已满[${medal.today_feed}/${medal.day_limit}]`, 'info');
return;
}
let feed = MY_API.Gift.getFeedByGiftID(v.gift_id);
if (feed > 0) {
let feed_num = Math.floor(MY_API.Gift.remain_feed / feed);
if (feed_num > v.gift_num) feed_num = v.gift_num;
if (feed_num > 0) {
MYDEBUG('[自动送礼]送出礼物类型', v.gift_name);
await BAPI.gift.bag_send(Live_info.uid, v.gift_id, MY_API.Gift.ruid, feed_num, v.bag_id, MY_API.Gift.room_id, Live_info.rnd).then((response) => {
MYDEBUG('Gift.sendGift: API.gift.bag_send', response);
if (response.code === 0) {
v.gift_num -= feed_num;
medal.today_feed += feed_num * feed;
MY_API.Gift.remain_feed -= feed_num * feed;
window.toast(`[自动送礼]勋章[${medal.medalName}] 送礼成功,送出${feed_num}个${v.gift_name},[${medal.today_feed}/${medal.day_limit}]距离升级还需[${MY_API.Gift.remain_feed}]`, 'success');
} else {
window.toast(`[自动送礼]勋章[${medal.medalName}] 送礼异常:${response.msg}`, 'caution');
}
}, () => {
window.toast('[自动送礼]包裹送礼失败,请检查网络', 'error');
return delayCall(() => MY_API.Gift.sendGift(medal));
});
}
}
}
},
sendRemainGift: async (ROOM_ID) => {
if (ROOM_ID == 0) return $.Deferred().resolve();
let UID = undefined;
await BAPI.live_user.get_anchor_in_room(ROOM_ID).then((response) => {
MYDEBUG('API.live_user.get_anchor_in_room', response);
if (!!response.data.info.uid) UID = response.data.info.uid;
else {
window.toast('[自动送礼]【剩余礼物】检查房间出错');
return $.Deferred().reject();
}
})
await MY_API.Gift.getBagList();
let bag_list;
if (MY_API.Gift.time <= 0) MY_API.Gift.time = ts_s();
if (!MY_API.CONFIG.SEND_ALL_GIFT) {
//送之前查一次有没有可送的
let pass = MY_API.Gift.bag_list.filter(r => MY_API.Gift.sendGiftList.includes(r.gift_id) && r.gift_num > 0 &&
r.corner_mark == `1天`);
if (pass.length == 0) {
MY_API.Gift.over = true;
return;
} else {
bag_list = pass;
}
} else {
let pass = MY_API.Gift.bag_list.filter(r => r.gift_num > 0 && r.corner_mark != '永久');
if (pass.length == 0) {
MY_API.Gift.over = true;
return;
} else {
bag_list = pass;
}
}
MYDEBUG('[自动送礼]【剩余礼物】bag_list', bag_list);
for (let v of bag_list) {
const feed = MY_API.Gift.getFeedByGiftID(v.gift_id);
if (feed > 0) {
let feed_num = v.gift_num;
if (feed_num > 0) {
await BAPI.gift.bag_send(Live_info.uid, v.gift_id, UID, feed_num, v.bag_id, ROOM_ID, Live_info.rnd).then((response) => {
MYDEBUG('Gift.sendGift: API.gift.bag_send', response);
if (response.code === 0) {
v.gift_num -= feed_num;
window.toast(`[自动送礼]【剩余礼物】房间[${ROOM_ID}] 送礼成功,送出${feed_num}个${v.gift_name}`, 'success');
} else {
window.toast(`[自动送礼]【剩余礼物】房间[${ROOM_ID}] 送礼异常:${response.msg}`, 'caution');
}
}, () => {
window.toast('[自动送礼]【剩余礼物】包裹送礼失败,请检查网络', 'error');
return delayCall(() => MY_API.Gift.sendGift(medal));
});
}
}
}
}
},
stormQueue: [],//n节奏风暴队列
stormBlack: false,//n节奏风暴黑屋
stormIdSet: {//风暴历史记录缓存
add: function (id) {
let storm_id_list = [];
try {
let config = JSON.parse(localStorage.getItem(`${NAME}stormIdSet`));
storm_id_list = [].concat(config.list);
storm_id_list.push(id);
if (storm_id_list.length > 50) {
storm_id_list.splice(0, 10);//删除前10条数据
}
localStorage.setItem(`${NAME}stormIdSet`, JSON.stringify({ list: storm_id_list }));
MYDEBUG(`${NAME}storm_Id_list_add`, storm_id_list);
} catch (e) {
storm_id_list.push(id);
localStorage.setItem(`${NAME}stormIdSet`, JSON.stringify({ list: storm_id_list }));
}
},
isIn: function (id) {
let storm_id_list = [];
try {
let config = JSON.parse(localStorage.getItem(`${NAME}stormIdSet`));
if (config === null) {
storm_id_list = [];
} else {
storm_id_list = [].concat(config.list);
}
MYDEBUG(`${NAME}storm_Id_list_read`, config);
return storm_id_list.indexOf(id) > -1
} catch (e) {
localStorage.setItem(`${NAME}stormIdSet`, JSON.stringify({ list: storm_id_list }));
MYDEBUG('读取' + `${NAME}stormIdSet` + '缓存错误已重置');
return storm_id_list.indexOf(id) > -1
}
}
},
Storm: {
check: (id) => {
return MY_API.stormQueue.indexOf(id) > -1;
},
append: (id) => {
MY_API.stormQueue.push(id);
if (MY_API.stormQueue.length > MY_API.CONFIG.STORM_QUEUE_SIZE) {
MY_API.stormQueue.shift();
}
},
over: (id) => {
var index = MY_API.stormQueue.indexOf(id);
if (index > -1) {
MY_API.stormQueue.splice(id, 1);
}
},
run: (roomid) => {
try {
if (!MY_API.CONFIG.STORM) return $.Deferred().resolve();
//if (Info.blocked) return $.Deferred().resolve();
if (MY_API.stormBlack) return $.Deferred().resolve();
if (inTimeArea(MY_API.CONFIG.TIME_AREA_START_H0UR, MY_API.CONFIG.TIME_AREA_END_H0UR, MY_API.CONFIG.TIME_AREA_START_MINUTE, MY_API.CONFIG.TIME_AREA_END_MINUTE) && MY_API.CONFIG.TIME_AREA_DISABLE) {
MYDEBUG(`节奏风暴`, `自动休眠,跳过检测roomid=${roomid}`);
return $.Deferred().resolve();
}
return BAPI.Storm.check(roomid).then((response) => {
MYDEBUG('MY_API.Storm.run: MY_API.API.Storm.check', response);
if (response.code === 0) {
var data = response.data;
MY_API.Storm.join(data.id, data.roomid, Math.round(new Date().getTime() / 1000) + data.time);
return $.Deferred().resolve();
} else {
window.toast(`[自动抽奖][节奏风暴](roomid=${roomid})${response.msg}`, 'caution');
}
}, () => {
window.toast(`[自动抽奖][节奏风暴]检查直播间(${roomid})失败,请检查网络`, 'error');
//return delayCall(() => MY_API.Storm.run(roomid));
});
} catch (err) {
window.toast('[自动抽奖][节奏风暴]运行时出现异常', 'error');
console.error(`[${NAME}]`, err);
return $.Deferred().reject();
}
},
join: (id, roomid, endtime) => {
//if (Info.blocked) return $.Deferred().resolve();
roomid = parseInt(roomid, 10);
id = parseInt(id, 10);
if (isNaN(roomid) || isNaN(id)) return $.Deferred().reject();
var tid = Math.round(id / 1000000);
if (MY_API.stormIdSet.isIn(tid)) return $.Deferred().resolve();
MY_API.stormIdSet.add(tid);
if (MY_API.Storm.check(id)) {
return;
}
MY_API.Storm.append(id);
var stormInterval = 0;
if (endtime <= 0) {
endtime = Math.round(new Date().getTime() / 1000) + 90;
}
var count = 0;
window.toast(`[自动抽奖][节奏风暴]尝试抽奖(roomid=${roomid},id=${id})`, 'success');
async function process() {
try {
if (!MY_API.Storm.check(id)) {
clearInterval(stormInterval);
return;
}
var timenow = Math.round(new Date().getTime() / 1000);
//console.log('stormdebug:',id,count,timenow,endtime);
if (timenow > endtime && endtime > 0) {
MY_API.Storm.over(id);
clearInterval(stormInterval);
//window.toast(`[自动抽奖][节奏风暴]抽奖(roomid=${roomid},id=${id})过期。\r\n尝试次数:${count}`, 'caution');
return;
}
count++;
if (count > MY_API.CONFIG.STORM_MAX_COUNT && MY_API.CONFIG.STORM_MAX_COUNT > 0) {
MY_API.Storm.over(id);
clearInterval(stormInterval);
window.toast(`[自动抽奖][节奏风暴]抽奖(roomid=${roomid},id=${id})到达尝试次数。\r\n尝试次数:${count},距离到期:${endtime - timenow}s`, 'caution');
return;
}
let response;
try {
if (userToken && appToken && tokenData.access_token) {
response = await BAPI.Storm.join_ex(id, roomid, tokenData.access_token, BilibiliToken.appKey, BilibiliToken.headers);
} else {
response = await BAPI.Storm.join(id, captcha_token = '', captcha_phrase = '', roomid);
}
MYDEBUG('MY_API.Storm.join: MY_API.API.Storm.join', response);
if (response.code) {
if (response.msg.indexOf("领取") != -1) {
MY_API.Storm.over(id);
clearInterval(stormInterval);
window.toast(`[自动抽奖][节奏风暴]领取(roomid=${roomid},id=${id})成功,${response.msg}\r\n尝试次数:${count}`, 'success');
return;
}
if (response.msg.indexOf("验证码") != -1) {
MY_API.Storm.over(id);
clearInterval(stormInterval);
MY_API.stormBlack = true;
window.toast(`[自动抽奖][节奏风暴]抽奖(roomid=${roomid},id=${id})失败,疑似账号不支持,${response.msg}`, 'caution');
return;
}
if (response.data && response.data.length == 0 && response.msg.indexOf("下次要更快一点") != -1) {
MY_API.Storm.over(id);
window.toast(`[自动抽奖][节奏风暴]抽奖(roomid=${roomid},id=${id})疑似风暴黑屋,终止!`, 'error');
clearInterval(stormInterval);
MY_API.stormBlack = true;
setTimeout(() => { MY_API.stormBlack = false; }, 3600 * 1000);
return;
}
if (response.msg.indexOf("下次要更快一点") == -1) {
clearInterval(stormInterval);
return;
}
//setTimeout(()=>process(),CONFIG.AUTO_LOTTERY_CONFIG.STORM_CONFIG.STORM_ONE_LIMIT);
} else {
MY_API.Storm.over(id);
Statistics.appendGift(response.data.gift_name, response.data.gift_num);
window.toast(`[自动抽奖][节奏风暴]领取(roomid=${roomid},id=${id})成功,${response.data.gift_name + "x" + response.data.gift_num}\r\n${response.data.mobile_content}\r\n尝试次数:${count}`, 'success');
clearInterval(stormInterval);
return;
}
} catch (e) {
MY_API.Storm.over(id);
window.toast(`[自动抽奖][节奏风暴]抽奖(roomid=${roomid},id=${id})疑似触发风控,终止!\r\n尝试次数:${count}`, 'error');
console.error(e);
clearInterval(stormInterval);
return;
}
}
catch (e) {
MY_API.Storm.over(id);
window.toast(`[自动抽奖][节奏风暴]抽奖(roomid=${roomid},id=${id})抽奖异常,终止!`, 'error');
console.error(e);
clearInterval(stormInterval);
return;
}
}
//setTimeout(()=>process(),1);
stormInterval = setInterval(() => process(), MY_API.CONFIG.STORM_ONE_LIMIT);
return $.Deferred().resolve();
}
},
LITTLE_HEART: {
getInfo: () => XHR({
GM: true,
anonymous: true,
method: 'GET',
url: `https://passport.bilibili.com/x/passport-login/oauth2/info?${appToken.signLoginQuery(`access_key=${tokenData.access_token}`)}`,
responseType: 'json',
headers: appToken.headers
}),
mobileOnline: () => XHR({
GM: true,
anonymous: true,
method: 'POST',
url: `https://api.live.bilibili.com/heartbeat/v1/OnLine/mobileOnline?${BilibiliToken.signQuery(`access_key=${tokenData.access_token}&${baseQuery}`)}`,
data: `room_id=${Live_info.room_id}&scale=xxhdpi`,
responseType: 'json',
headers: appToken.headers
}),
RandomHex: (length) => {
const words = '0123456789abcdef';
let randomID = '';
randomID += words[Math.floor(Math.random() * 15) + 1];
for (let i = 0; i < length - 1; i++)
randomID += words[Math.floor(Math.random() * 16)];
return randomID;
},
uuid: () => MY_API.LITTLE_HEART.RandomHex(32).replace(/(\w{8})(\w{4})\w(\w{3})\w(\w{3})(\w{12})/, `$1-$2-4$3-${'89ab'[Math.floor(Math.random() * 4)]}$4-$5`),
getFansMedal: async () => {
const funsMedals = await XHR({
GM: true,
anonymous: true,
method: 'GET',
url: `https://api.live.bilibili.com/fans_medal/v1/FansMedal/get_list_in_room?${BilibiliToken.signQuery(`access_key=${tokenData.access_token}&target_id=${Live_info.tid}&uid=${Live_info.uid}&${baseQuery}`)}`,
responseType: 'json',
headers: appToken.headers
});
if (funsMedals !== undefined && funsMedals.response.status === 200)
if (funsMedals.body.code === 0)
if (funsMedals.body.data.length > 0)
return funsMedals.body.data;
},
getGiftNum: async () => {
let todayHeart = 0;
await BAPI.gift.bag_list().then((re) => {
MYDEBUG('[小心心]检查包裹', re);
const allHeart = re.data.list.filter(r => r.gift_id == 30607 && r.corner_mark == "7天");
for (const heart of allHeart) {
todayHeart += heart.gift_num;
}
});
MYDEBUG(`[小心心]检测到包裹内7天小心心数量`, todayHeart);
return todayHeart
},
mobileHeartBeat: async (postJSON) => {
const wasm = new WasmHash();
await wasm.init();
const clientSign = (data) => wasm.hash('BLAKE2b512', wasm.hash('SHA3-384', wasm.hash('SHA384', wasm.hash('SHA3-512', wasm.hash('SHA512', JSON.stringify(data))))));
const sign = clientSign(postJSON);
let postData = '';
for (const i in postJSON)
postData += `${i}=${encodeURIComponent(postJSON[i])}&`;
postData += `client_sign=${sign}`;
const mobileHeartBeat = await XHR({
GM: true,
anonymous: true,
method: 'POST',
url: 'https://live-trace.bilibili.com/xlive/data-interface/v1/heartbeat/mobileHeartBeat',
data: BilibiliToken.signQuery(`access_key=${tokenData.access_token}&${postData}&${baseQuery}`),
responseType: 'json',
headers: appToken.headers
});
if (mobileHeartBeat !== undefined && mobileHeartBeat.response.status === 200)
if (mobileHeartBeat.body.code === 0)
return true;
return false;
},
run: async () => {
if (!MY_API.CONFIG.LITTLE_HEART) return $.Deferred().resolve();
if (!checkNewDay(MY_API.CACHE.LittleHeart_TS)) {
runMidnight(MY_API.LITTLE_HEART.run, '获取小心心');
return $.Deferred().resolve();
}
const mobileHeartBeatJSON = {
platform: 'android',
uuid: MY_API.LITTLE_HEART.uuid(),
buvid: appToken.buvid,
seq_id: '1',
room_id: '{room_id}',
parent_id: '6',
area_id: '283',
timestamp: '{timestamp}',
secret_key: 'axoaadsffcazxksectbbb',
watch_time: '300',
up_id: '{target_id}',
up_level: '40',
jump_from: '30000',
gu_id: MY_API.LITTLE_HEART.RandomHex(43),
play_type: '0',
play_url: '',
s_time: '0',
data_behavior_id: '',
data_source_id: '',
up_session: 'l:one:live:record:{room_id}:{last_wear_time}',
visit_id: MY_API.LITTLE_HEART.RandomHex(32),
watch_status: '%7B%22pk_id%22%3A0%2C%22screen_status%22%3A1%7D',
click_id: MY_API.LITTLE_HEART.uuid(),
session_id: '',
player_type: '0',
client_ts: '{client_ts}'
};
const endFunc = () => {
window.toast('[小心心]今日小心心已全部获取', 'success');
clearInterval(mobileOnlineTimer);
MY_API.CACHE.LittleHeart_TS = ts_ms();
MY_API.saveCache();
runMidnight(MY_API.LITTLE_HEART.run, '获取小心心');
}
if (tokenData.access_token === undefined && await setToken() === undefined)
return;
else if (!tokenData.access_token && !tokenData.mid && !tokenData.refresh_token) {
const userInfo = await MY_API.LITTLE_HEART.getInfo();
MYDEBUG('[小心心]userInfo', userInfo);
if (userInfo === undefined)
return console.error(GM_info.script.name, '获取用户信息错误');
if (userInfo.body.code !== 0 && await setToken() === undefined)
return;
else if (userInfo.body.data.mid !== Live_info.uid && await setToken() === undefined)
return;
}
MYDEBUG('[小心心]', '开始客户端心跳');
window.toast('[小心心]开始获取小心心', 'success');
MY_API.LITTLE_HEART.mobileOnline();
let mobileOnlineTimer = setInterval(() => MY_API.LITTLE_HEART.mobileOnline(), 5 * 60 * 1000);
const giftNum = await MY_API.LITTLE_HEART.getGiftNum();
if (giftNum < 24) {
const fansMedal = await MY_API.LITTLE_HEART.getFansMedal();
if (fansMedal !== undefined) {
const control = 24 - giftNum;
const loopNum = Math.ceil(control / fansMedal.length);
let count = 0;
for (let i = 0; i < loopNum; i++) {
for (const funsMedalData of fansMedal) {
if (count >= control)
break;
const postData = Object.assign({}, mobileHeartBeatJSON, {
room_id: funsMedalData.room_id.toString(),
timestamp: (BilibiliToken.TS - 300).toString(),
up_id: funsMedalData.target_id.toString(),
up_session: `l:one:live:record:${funsMedalData.room_id}:${funsMedalData.last_wear_time}`,
client_ts: BilibiliToken.TS.toString()
});
await MY_API.LITTLE_HEART.mobileHeartBeat(postData);
count++;
}
if (count >= control) {
endFunc();
break;
}
else
await sleep(300 * 1000);
}
}
} else {
endFunc();
}
return $.Deferred().resolve();
}
},
AUTO_DANMU: {
setValue: (array, index) => {
if (MY_API.CONFIG[array][index] === undefined && index > 0)
return MY_API.AUTO_DANMU.setValue(array, index - 1);
else return MY_API.CONFIG[array][index];
},
sendDanmu: async (danmuContent, roomId) => {
//console.log('prepare to sendDanmu', danmuContent, roomId)
return BAPI.room.get_info(roomId).then((res) => {
MYDEBUG(`API.room.get_info roomId=${roomId} res`, res);//可能是短号,要用长号发弹幕
return BAPI.sendLiveDanmu(danmuContent, res.data.room_id).then((response) => {
MYDEBUG(`[自动发弹幕]弹幕发送内容【${danmuContent}】,房间号【${roomId}】`, response);
if (response.code === 0 && !response.msg)
window.toast(`[自动发弹幕]弹幕【${danmuContent}】(房间号【${roomId}】)发送成功`, 'success');
else window.toast(`[自动发弹幕]弹幕【${danmuContent}】(房间号【${roomId}】)出错 ${response.msg}`, 'caution')
}, () => {
window.toast(`[自动发弹幕]弹幕【${danmuContent}】(房间号【${roomId}】)发送失败`, 'error')
})
});
},
getMaxLength: () => {
let maxLength = undefined;
const contentLength = MY_API.CONFIG.DANMU_CONTENT.length,
roomidLength = MY_API.CONFIG.DANMU_ROOMID.length,
intervalTimeLength = MY_API.CONFIG.DANMU_INTERVAL_TIME.length;
if (contentLength >= roomidLength) maxLength = contentLength;
else maxLength = roomidLength;
if (maxLength < intervalTimeLength)
maxLength = intervalTimeLength;
return maxLength
},
run: async () => {
if (!MY_API.CONFIG.AUTO_DANMU) return $.Deferred().resolve();
let maxLength = MY_API.AUTO_DANMU.getMaxLength();
for (let i = 0; i < maxLength; i++) {
let danmu_content = MY_API.AUTO_DANMU.setValue('DANMU_CONTENT', i),
danmu_roomid = parseInt(MY_API.AUTO_DANMU.setValue('DANMU_ROOMID', i)),
danmu_intervalTime = MY_API.AUTO_DANMU.setValue('DANMU_INTERVAL_TIME', i),//设置-发送时间
lastSendTime = undefined,//上次发弹幕的时间戳(毫秒)
jsonCache = MY_API.CACHE.AUTO_SEND_DANMU_TS,
objIndex = undefined,//弹幕缓存下标
isTimeData = undefined,//是否是时间数据(eg 9:01)
intervalTime = undefined,//据上次发弹幕的时间(毫秒)
danmu_intervalTime_Ts = undefined,//间隔时间
sleepTime = 0;
if (danmu_intervalTime.indexOf(':') > -1) {//时间
isTimeData = true;
const danmu_time = danmu_intervalTime.split(':');//小时,分钟,秒
const hour = parseInt(danmu_time[0]), minute = parseInt(danmu_time[1]), second = parseInt(danmu_time[2]);
if (!isTime(hour, minute, second)) {
sleepTime = getIntervalTime(hour, minute, second);
}
}
else {
isTimeData = false;
danmu_intervalTime = danmu_intervalTime.toLowerCase();
if (danmu_intervalTime.indexOf('h') > -1 || danmu_intervalTime.indexOf('m') > -1 || danmu_intervalTime.indexOf('s') > -1) {
const hourArray = danmu_intervalTime.split('h');//1h5m3s
const minuteArray = (hourArray[1] === undefined) ? hourArray[0].split('m') : hourArray[1].split('m');
const secondArray = (minuteArray[1] === undefined) ? minuteArray[0].split('s') : minuteArray[1].split('s');
const hour = hourArray[0],
minute = minuteArray[0],
second = secondArray[0];
const finalHour = isNaN(hour) ? 0 : hour || 0,
finalMinute = isNaN(minute) ? 0 : minute || 0,
finalSecond = isNaN(second) ? 0 : second || 0;
danmu_intervalTime_Ts = finalHour * 3600000 + finalMinute * 60000 + finalSecond * 1000;
} else {//没有h或m或s则默认是分钟
danmu_intervalTime_Ts = danmu_intervalTime * 60000;
}
}
MYDEBUG('[自动发弹幕]MY_API.CACHE.AUTO_SEND_DANMU_TS => jsoncache', jsonCache);
for (const obj of jsonCache) {
if (obj.roomid == danmu_roomid && obj.content == danmu_content) {
lastSendTime = obj.sendTs
objIndex = jsonCache.indexOf(obj);
break;
}
}
if (!isTimeData) {
if (!!lastSendTime) intervalTime = ts_ms() - lastSendTime;
else intervalTime = ts_ms();
}
const setCache = () => {
const newJson = {
roomid: danmu_roomid,
content: danmu_content,
sendTs: ts_ms()
};
if (!lastSendTime) {
jsonCache.push(newJson);
} else {
jsonCache[objIndex].sendTs = ts_ms();
}
MY_API.CACHE.AUTO_SEND_DANMU_TS = jsonCache;
MY_API.saveCache(false);
};
const sendNextDanmu = (intervalTS, isTime) => {
if (!isTime) setCache();
setTimeout(async () => {
await MY_API.AUTO_DANMU.sendDanmu(danmu_content, danmu_roomid);
if (!isTime) setCache();
sendNextDanmu(intervalTS, isTime);
}, intervalTS);
}
if (!isTimeData && (intervalTime >= danmu_intervalTime_Ts || SEND_DANMU_NOW)) {
SEND_DANMU_NOW = false;
await MY_API.AUTO_DANMU.sendDanmu(danmu_content, danmu_roomid);
MYDEBUG(`[自动发弹幕]弹幕发送内容【${danmu_content}】,房间号【${danmu_roomid}】,距下次发送还有`, danmu_intervalTime);
sendNextDanmu(danmu_intervalTime_Ts, isTimeData);
} else if ((isTimeData && !sleepTime) || SEND_DANMU_NOW) {
SEND_DANMU_NOW = false;
await MY_API.AUTO_DANMU.sendDanmu(danmu_content, danmu_roomid);
sleepTime = getIntervalTime(danmu_time[0], danmu_time[1], danmu_time[2]);
MYDEBUG(`[自动发弹幕]弹幕发送内容【${danmu_content}】,房间号【${danmu_roomid}】,距下次发送还有`, '约24小时');
sendNextDanmu(sleepTime, isTimeData);
}
else {
MYDEBUG(`[自动发弹幕]弹幕发送内容【${danmu_content}】,房间号【${danmu_roomid}】,距下次发送还有`, `${(!isTimeData) ? (danmu_intervalTime_Ts - intervalTime) / 60000 : sleepTime / 60000}分钟`);
setTimeout(async () => {
await MY_API.AUTO_DANMU.sendDanmu(danmu_content, danmu_roomid);
sendNextDanmu((isTimeData) ? 86400000 : danmu_intervalTime_Ts, isTimeData);
}, (isTimeData) ? sleepTime : danmu_intervalTime_Ts - intervalTime);
}
await sleep(1100);
}
}
}
};
MY_API.init().then(() => {//主函数
try {
const promiseInit = $.Deferred();
const uniqueCheck = () => {
const t = ts_ms();
if (t - MY_API.CACHE.UNIQUE_CHECK >= 0 && t - MY_API.CACHE.UNIQUE_CHECK <= 15e3) {
// 其他脚本正在运行
$('.link-toast').remove();
$('.igiftMsg').remove();
window.toast('有其他直播间页面的脚本正在运行,本页面脚本停止运行', 'caution');
return promiseInit.reject();
} else {
// 没有其他脚本正在运行
return promiseInit.resolve();
}
};
uniqueCheck().then(() => {
let timer_unique;
const uniqueMark = () => {
timer_unique = setTimeout(uniqueMark, 10e3);
MY_API.CACHE.UNIQUE_CHECK = Date.now();
MY_API.saveCache(false);
};
window.addEventListener('unload', () => {
if (timer_unique) {
clearTimeout(timer_unique);
MY_API.CACHE.UNIQUE_CHECK = 0;
MY_API.saveCache();
}
});
uniqueMark();
if (parseInt(Live_info.uid) === 0 || isNaN(parseInt(Live_info.uid))) {//登陆判断
MY_API.chatLog('未登录(不可用),请先登录(不可用)再使用脚本', 'warning');
return
};
localStorage.setItem(`${NAME}_CONFIG`, JSON.stringify(MY_API.CONFIG));//修复一下因版本差异造成的变量类型错误
MY_API.newMessage(GM_info.script.version);//新版本提示信息
MYDEBUG('MY_API.CONFIG', MY_API.CONFIG);
StartPlunder(MY_API);
})
}
catch (e) {
console.error('重复运行检测错误', e);
}
});
}
function StartPlunder(API) {
'use strict';
//清空辣条数量
let clearStat = () => {
API.GIFT_COUNT.COUNT = 0;
API.GIFT_COUNT.CLEAR_TS = dateNow();
API.saveGiftCount();
MYDEBUG('已清空辣条数量')
}
if (checkNewDay(API.GIFT_COUNT.CLEAR_TS)) clearStat();
runExactMidnight(clearStat, '重置统计');
API.creatSetBox();//创建设置框
API.removeUnnecessary();//移除页面元素
setTimeout(() => {
API.AUTO_DANMU.run();//自动发弹幕
API.LITTLE_HEART.run();//小心心
API.GroupSign.run();//应援团签到
API.DailyReward.run();//每日任务
API.LiveReward.run();//直播每日任务
API.Exchange.runS2C();//银瓜子换硬币
API.Gift.run();//送礼物
}, 6e3);//脚本加载后6秒执行任务
if (API.CONFIG.LOTTERY) {
BAPI.room.getList().then((response) => {//获取各分区的房间号
MYDEBUG('直播间列表', response);
for (const obj of response.data) {
BAPI.room.getRoomList(obj.id, 0, 0, 1, 1).then((response) => {
MYDEBUG('直播间号列表', response);
for (let j = 0; j < response.data.length; ++j) {
API.listen(response.data[j].roomid, Live_info.uid, `${obj.name}区`);
}
});
}
});
if (API.CONFIG.CHECK_HOUR_ROOM) {
let check_top_room = () => { //检查小时榜房间
if (API.GIFT_COUNT.COUNT >= API.CONFIG.MAX_GIFT) {//判断是否超过辣条限制
MYDEBUG('超过今日辣条限制,不参与抽奖');
API.max_blocked = true;
}
if (API.blocked || API.max_blocked) {//如果被禁用则停止
if (API.blocked) {
API.chatLog('进入小黑屋检查小时榜已停止运行');
clearInterval(check_timer);
return
}
else {
API.chatLog('辣条已达到最大值检查小时榜已停止运行');
return
}
}
if (inTimeArea(API.CONFIG.TIME_AREA_START_H0UR, API.CONFIG.TIME_AREA_END_H0UR, API.CONFIG.TIME_AREA_START_MINUTE, API.CONFIG.TIME_AREA_END_MINUTE) && API.CONFIG.TIME_AREA_DISABLE) {//判断时间段
API.chatLog('当前时间段不检查小时榜礼物', 'warning');
return
}
const AreaIdList = [
'小时总榜',
'娱乐小时榜',
'网游小时榜',
'手游小时榜',
'绘画小时榜',
'电台小时榜',
'单机小时榜',
];
let AreaNum = 1;//总榜中的抽奖肯定在对应分区榜,无需检查
let checkHourRank = (areaId) => {
BAPI.rankdb.getTopRealTimeHour(areaId).then((data) => {
let list = data.data.list;// [{id: ,link:}]
API.chatLog(`检查${AreaIdList[areaId]}房间的礼物`, 'warning');
MYDEBUG(`${AreaIdList[areaId]}房间列表`, list);
for (let i of list) {
API.checkRoom(i.roomid, `小时榜-${i.area_v2_parent_name}区`);
}
})
};
let timer = setInterval(() => {
if (AreaNum <= AreaIdList.length - 1) {
checkHourRank(AreaNum);
AreaNum++;
}
else {
clearInterval(timer)
}
}, 1000);
};
setTimeout(check_top_room, 6e3);//加载脚本后6秒检查一次小时榜
let check_timer = setInterval(check_top_room, parseInt(API.CONFIG.CHECK_HOUR_ROOM_INTERVAL * 1000));
}
}
let reset = (delay) => {
let resetTimer = setTimeout(() => {//重置直播间
if (API.raffleId_list.length > 0 || API.guardId_list.length > 0 || API.pkId_list.length > 0) {
MYDEBUG('[刷新直播间]', '还有礼物没抽,延迟15s后刷新直播间');
reset(15000);
return
}
if (checkNewDay(API.CACHE.LittleHeart_TS)) {
MYDEBUG('[刷新直播间]', '正在获取小心心,10分钟后再次检查');
clearTimeout(resetTimer);
reset(600e3);
return
}
if (inTimeArea(API.CONFIG.TIME_AREA_START_H0UR, API.CONFIG.TIME_AREA_END_H0UR, API.CONFIG.TIME_AREA_START_MINUTE, API.CONFIG.TIME_AREA_END_MINUTE)
&& API.CONFIG.IN_TIME_RELOAD_DISABLE) {//在不抽奖时段且不抽奖时段不刷新开启
let resetTime = getIntervalTime(API.CONFIG.TIME_AREA_START_MINUTE, API.CONFIG.TIME_AREA_END_MINUTE) + 60e3;
reset(resetTime);
MYDEBUG('[刷新直播间]', `处于休眠时间段,将在${resetTime}毫秒后刷新直播间`);
return;
}
window.location.reload();
}, delay);
};
if (API.CONFIG.TIME_RELOAD) reset(API.CONFIG.TIME_RELOAD_MINUTE * 60000);//单位1分钟,重新加载直播间
}
/**
* (23,50) 获取与目标时间在时间轴上的间隔时间,24小时制(毫秒)
* @param hour 整数 小时
* @param minute 整数 分钟
* @param second 整数 秒(可不填)
* @returns {number} intervalTime
*/
function getIntervalTime(hour, minute, second) {
const myDate = new Date();
const h = myDate.getHours();
const m = myDate.getMinutes();
const s = myDate.getSeconds();
const TargetTime = hour * 3600 * 1e3 + minute * 60 * 1e3 + ((!second) ? 0 : second * 1e3);
const nowTime = h * 3600 * 1e3 + m * 60 * 1e3 + s * 1e3;
const intervalTime = TargetTime - nowTime;
MYDEBUG("[getIntervalTime]获取间隔时间", `${intervalTime}毫秒`);
if (intervalTime < 0) {
return 24 * 3600 * 1e3 + intervalTime
}
else {
return intervalTime
}
}
/**
* (23,50) 当前时间是否为23:50
* @param hour 整数 小时
* @param minute 整数 分钟
* @param second 整数 秒(可不填)
* @returns {boolean}
*/
function isTime(hour, minute, second) {
let myDate = new Date();
let h = myDate.getHours();
let m = myDate.getMinutes();
let s = myDate.getSeconds();
if ((h == hour && m == minute && !second) || (h == hour && m == minute && s == second)) {
return true
} else {
MYDEBUG("isTime 错误时间", `目标时间${hour}时${minute}分${second || 0}秒,当前时间${h}时${m}分${s}秒`);
return false
}
}
/**
* (2,10,0,1) 当前是否在两点0分到十点1分之间
* @param sH 整数 起始小时
* @param eH 整数 终止小时
* @param sM 整数 起始分钟
* @param eM 整数 终止分钟
* @returns {boolean}
*/
function inTimeArea(sH, eH, sM, eM) {
if (sH > 23 || eH > 24 || sH < 0 || eH < 1 || sM > 59 || sM < 0 || eM > 59 || eM < 0) {
return false
}
let myDate = new Date();
let h = myDate.getHours();
let m = myDate.getMinutes();
if (sH < eH) {//如(2,8,0,0)
if (h >= sH && h < eH)
return true;
else if (h == eH && m >= sM && m < eM)
return true;
else return false;
}
else if (sH > eH) {//如(22,12,0,0)
if (h >= sH || h < eH)
return true;
else if (h == eH && m >= sM && m < eM)
return true;
else return false;
}
else if (sH == eH) {
if (h == sH && sM <= eM && m >= sM && m < eM)
return true
else if (h == sH && sM > eM && m <= eM && m > sM)
return true
else return false;
}
};
function sleep(millisecond) {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, millisecond)
})
}
/**
* 概率
* @param val
* @returns {boolean}
*/
function probability(val) {
if (val <= 0) return false;
let rad = Math.random();
return (val / 100) >= rad
}
const dateNow = () => Date.now();
/**
* 检查是否为新一天
* @param ts
* @returns {boolean}
*/
const checkNewDay = (ts) => {
if (ts === 0) return true;
let t = new Date(ts);
let d = new Date();
let td = t.getDate();
let dd = d.getDate();
return (dd !== td);
};
function XHR(XHROptions) {
return new Promise(resolve => {
const onerror = (error) => {
console.error(GM_info.script.name, error);
resolve(undefined);
};
if (XHROptions.GM) {
if (XHROptions.method === 'POST') {
if (XHROptions.headers === undefined)
XHROptions.headers = {};
if (XHROptions.headers['Content-Type'] === undefined)
XHROptions.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
}
XHROptions.timeout = 30 * 1000;
XHROptions.onload = res => resolve({ response: res, body: res.response });
XHROptions.onerror = onerror;
XHROptions.ontimeout = onerror;
GM_xmlhttpRequest(XHROptions);
}
else {
const xhr = new XMLHttpRequest();
xhr.open(XHROptions.method, XHROptions.url);
if (XHROptions.method === 'POST' && xhr.getResponseHeader('Content-Type') === null)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=utf-8');
if (XHROptions.cookie)
xhr.withCredentials = true;
if (XHROptions.responseType !== undefined)
xhr.responseType = XHROptions.responseType;
xhr.timeout = 30 * 1000;
xhr.onload = ev => {
const res = ev.target;
resolve({ response: res, body: res.response });
};
xhr.onerror = onerror;
xhr.ontimeout = onerror;
xhr.send(XHROptions.data);
}
});
}
})();