");
let ct = $('#chat-history-list');
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',
});
msg.css({
'word-wrap': 'break-word',
'width': '100%',
'line-height': '1em',
'margin-bottom': '10px',
});
div.css({
'border': '1px solid rgb(203, 195, 255)',
'background': 'rgb(233, 230, 255) none repeat scroll 0% 0%',
});
if (msgHide == false) {
ct.find('#chat-items').append(div);//向聊天框加入信息
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 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 $.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();
let alternateTime = GetTomorrowIntervalTime(MY_API.CACHE.AUTO_GROUP_SIGH_TS);
if (alternateTime < 86400 * 1e3) { //间隔小于24小时
setTimeout(MY_API.GroupSign.run, alternateTime);
let runTime = new Date(ts_ms() + alternateTime).toLocaleString();
MYDEBUG("[自动应援团签到]", `将在${runTime}进行应援团签到`);
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();
alternateTime = GetTomorrowIntervalTime(MY_API.CACHE.AUTO_GROUP_SIGH_TS);
setTimeout(MY_API.GroupSign.run, alternateTime);
let runTime = new Date(ts_ms() + alternateTime).toLocaleString();
MYDEBUG("[自动应援团签到]", `将在${runTime}进行应援团签到`);
}, () => 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.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);
}
window.toast(`[自动每日奖励][每日投币]'${response.msg}`, 'caution');
return MY_API.DailyReward.coin(cards, n, i + 1);
}, () => delayCall(() => MY_API.DailyReward.coin(cards, n, 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: () => {
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);
const p2 = MY_API.DailyReward.coin(response.data.cards, Math.max(MY_API.CONFIG.COIN_NUMBER - MY_API.DailyReward.coin_exp / 10, 0));
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());
});
},
run: () => {
try {
//if (!MY_API.CONFIG.DailyReward) 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();
return MY_API.DailyReward.dynamic().then(() => {
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
TreasureBox: {//领宝箱
timer: undefined,
time_end: undefined,
time_start: undefined,
promise: {
calc: undefined,
timer: undefined
},
DOM: {
image: undefined,
canvas: undefined,
div_tip: undefined,
div_timer: undefined
},
init: () => {
if (!MY_API.CONFIG.AUTO_TREASUREBOX) return $.Deferred().resolve();
const p = $.Deferred();
runUntilSucceed(() => {
try {
if ($('.draw-box.gift-left-part').length) {
window.toast('[自动领取瓜子]当前直播间有实物抽奖,暂停领瓜子功能', 'caution');
p.resolve();
return true;
}
let treasure_box = $('#gift-control-vm div.treasure-box.p-relative');
if (!treasure_box.length) return false;
treasure_box = treasure_box.first();
treasure_box.attr('id', 'old_treasure_box');
treasure_box.hide();
const div = $(`
`);
MY_API.TreasureBox.DOM.div_tip = $(`
自动
领取中
`);
MY_API.TreasureBox.DOM.div_timer = $(`
0
`);
MY_API.TreasureBox.DOM.image = $(`
![]()
`);
MY_API.TreasureBox.DOM.canvas = $(`
`);
const css_text = 'min-width: 40px;padding: 2px 3px;margin-top: 3px;font-size: 12px;color: #fff;background-color: rgba(0,0,255,.5);border-radius: 10px;';
MY_API.TreasureBox.DOM.div_tip[0].style = css_text;
MY_API.TreasureBox.DOM.div_timer[0].style = css_text;
div.append(MY_API.TreasureBox.DOM.div_tip);
div.append(MY_API.TreasureBox.DOM.image);
div.append(MY_API.TreasureBox.DOM.canvas);
MY_API.TreasureBox.DOM.div_tip.after(MY_API.TreasureBox.DOM.div_timer);
treasure_box.after(div);
if (!Live_info.mobile_verify) {
MY_API.TreasureBox.setMsg('未绑定
手机');
window.toast('[自动领取瓜子]未绑定手机,已停止', 'caution');
p.resolve();
return true;
}
try {
if (OCRAD);
} catch (err) {
MY_API.TreasureBox.setMsg('初始化
失败');
window.toast('[自动领取瓜子]OCRAD初始化失败,请检查网络', 'error');
console.error(`[${NAME}]`, err);
p.resolve();
return true;
}
MY_API.TreasureBox.timer = setInterval(() => {
let t = parseInt(MY_API.TreasureBox.DOM.div_timer.text(), 10);
if (isNaN(t)) t = 0;
if (t > 0) MY_API.TreasureBox.DOM.div_timer.text(`${t - 1}s`);
else MY_API.TreasureBox.DOM.div_timer.hide();
}, 1e3);
MY_API.TreasureBox.DOM.image[0].onload = () => {
// 实现功能类似 https://github.com/bilibili-helper/bilibili-helper-o/tree/master/src/js/modules/treasure
const ctx = MY_API.TreasureBox.DOM.canvas[0].getContext('2d');
ctx.font = '40px agencyfbbold';
ctx.textBaseline = 'top';
ctx.clearRect(0, 0, MY_API.TreasureBox.DOM.canvas[0].width, MY_API.TreasureBox.DOM.canvas[0].height);
ctx.drawImage(MY_API.TreasureBox.DOM.image[0], 0, 0);
const grayscaleMap = MY_API.TreasureBox.captcha.OCR.getGrayscaleMap(ctx);
const filterMap = MY_API.TreasureBox.captcha.OCR.orderFilter2In3x3(grayscaleMap);
ctx.clearRect(0, 0, 120, 40);
for (let i = 0; i < filterMap.length; ++i) {
const gray = filterMap[i];
ctx.fillStyle = `rgb(${gray}, ${gray}, ${gray})`;
ctx.fillRect(i % 120, Math.round(i / 120), 1, 1);
}
try {
const question = MY_API.TreasureBox.captcha.correctQuestion(OCRAD(ctx.getImageData(0, 0, 120, 40)));
MYDEBUG('TreasureBox.DOM.image.load', 'question =', question);
const answer = MY_API.TreasureBox.captcha.eval(question);
MYDEBUG('TreasureBox.DOM.image.load', 'answer =', answer);
if (answer !== undefined) {
//window.toast(`[自动领取瓜子]验证码识别结果: ${question} = ${answer}`, 'info');
console.info(`[${NAME}][自动领取瓜子]验证码识别结果: ${question} = ${answer}`);
MY_API.TreasureBox.promise.calc.resolve(answer);
}
} catch (err) {
MY_API.TreasureBox.promise.calc.reject();
}
};
p.resolve();
return true;
} catch (err) {
window.toast('[自动领取瓜子]初始化时出现异常,已停止', 'error');
console.error(`[${NAME}]`, err);
p.reject();
return true;
}
});
return p;
},
run: () => {
try {
if (!MY_API.CONFIG.AUTO_TREASUREBOX || !MY_API.TreasureBox.timer) return;
if (Live_info.blocked) {
MY_API.TreasureBox.setMsg('小黑屋');
window.toast('[自动领取瓜子]帐号被关小黑屋,停止领取瓜子', 'caution');
return;
}
if (!checkNewDay(MY_API.CACHE.TreasureBox_TS)) {
MY_API.TreasureBox.setMsg('今日
已领完');
runMidnight(MY_API.TreasureBox.run, '领银瓜子宝箱');
return;
}
MY_API.TreasureBox.getCurrentTask().then((response) => {
MYDEBUG('TreasureBox.run: TreasureBox.getCurrentTask().then', response);
if (response.code === 0) {
// 获取任务成功
MY_API.TreasureBox.promise.timer = $.Deferred();
MY_API.TreasureBox.promise.timer.then(() => {
MY_API.TreasureBox.captcha.calc().then((captcha) => {
// 验证码识别完成
MY_API.TreasureBox.getAward(captcha).then(() => MY_API.TreasureBox.run(), () => MY_API.TreasureBox.run());
}, () => TreasureBox.run());
});
MY_API.TreasureBox.time_end = response.data.time_end;
MY_API.TreasureBox.time_start = response.data.time_start;
let t = MY_API.TreasureBox.time_end - ts_s() + 1;
if (t < 0) t = 0;
setTimeout(() => {
if (MY_API.TreasureBox.promise.timer) MY_API.TreasureBox.promise.timer.resolve();
}, t * 1e3);
MY_API.TreasureBox.DOM.div_timer.text(`${t}s`);
MY_API.TreasureBox.DOM.div_timer.show();
MY_API.TreasureBox.DOM.div_tip.html(`轮数
${response.data.times}/${response.data.max_times}
银瓜子
${response.data.silver}`);
} else if (response.code === -10017) {
// 今天所有的宝箱已经领完!
MY_API.TreasureBox.setMsg('今日
已领完');
// window.toast(`[自动领取瓜子]${response.msg}`, 'info');
MY_API.CACHE.TreasureBox_TS = ts_ms();
MY_API.saveCache();
runMidnight(MY_API.TreasureBox.run, '领银瓜子宝箱');
} else if (response.code === -500) {
// 请先登录!
location.reload();
} else {
window.toast(`[自动领取瓜子]${response.msg}`, 'caution');
return MY_API.TreasureBox.run();
}
});
} catch (err) {
MY_API.TreasureBox.setMsg('运行
异常');
window.toast('[自动领取瓜子]运行时出现异常,已停止', 'error');
console.error(`[${NAME}]`, err);
}
},
setMsg: (htmltext) => {
if (!MY_API.CONFIG.AUTO_TREASUREBOX) return;
if (MY_API.TreasureBox.promise.timer) {
MY_API.TreasureBox.promise.timer.reject();
MY_API.TreasureBox.promise.timer = undefined;
}
if (MY_API.TreasureBox.DOM.div_timer) MY_API.TreasureBox.DOM.div_timer.hide();
if (MY_API.TreasureBox.DOM.div_tip) MY_API.TreasureBox.DOM.div_tip.html(htmltext);
},
getAward: (captcha, cnt = 0) => {
if (!MY_API.CONFIG.AUTO_TREASUREBOX) return $.Deferred().reject();
if (cnt > 3) return $.Deferred().resolve(); // 3次时间未到,重新运行任务
return BAPI.TreasureBox.getAward(MY_API.TreasureBox.time_start, MY_API.TreasureBox.time_end, captcha).then((response) => {
MYDEBUG('TreasureBox.getAward: getAward', response);
switch (response.code) {
case 0:
window.toast(`[自动领取瓜子]领取了 ${response.data.awardSilver} 银瓜子`, 'success');
case -903: // -903: 已经领取过这个宝箱
// window.toast('[自动领取瓜子]已经领取过这个宝箱', 'caution');
return $.Deferred().resolve();
case -902: // -902: 验证码错误
case -901: // -901: 验证码过期
case -10017: // -10017: 验证码过期
return MY_API.TreasureBox.captcha.calc().then((captcha) => {
return MY_API.TreasureBox.getAward(captcha, cnt);
});
case -800: // -800:未绑定手机
MY_API.TreasureBox.setMsg('未绑定
手机');
window.toast('[自动领取瓜子]未绑定手机,已停止', 'caution');
return $.Deferred().reject();
case -500: // -500:领取时间未到, 请稍后再试
const p = $.Deferred();
setTimeout(() => {
MY_API.TreasureBox.captcha.calc().then((captcha) => {
MY_API.TreasureBox.getAward(captcha, cnt + 1).then(() => p.resolve(), () => p.reject());
}, () => p.reject());
}, 3e3);
return p;
case 400: // 400: 访问被拒绝
if (response.msg.indexOf('拒绝') > -1) {
Live_info.blocked = true;
MY_API.TreasureBox.setMsg('拒绝
访问');
window.toast('[自动领取瓜子]访问被拒绝,您的帐号可能已经被关小黑屋,已停止', 'error');
return $.Deferred().reject();
}
window.toast(`[自动领取瓜子]${response.msg}`, 'caution');
return $.Deferred().resolve();
default: // 其他错误
window.toast(`[自动领取瓜子]${response.msg}`, 'caution');
}
}, () => {
window.toast('[自动领取瓜子]获取任务失败,请检查网络', 'error');
return delayCall(() => MY_API.TreasureBox.getAward(captcha, cnt));
});
},
getCurrentTask: () => {
if (!MY_API.CONFIG.AUTO_TREASUREBOX) return $.Deferred().reject();
return BAPI.TreasureBox.getCurrentTask().then((response) => {
MYDEBUG('TreasureBox.getCurrentTask: API.TreasureBox.getCurrentTask', response);
return $.Deferred().resolve(response);
}, () => {
window.toast('[自动领取瓜子]获取当前任务失败,请检查网络', 'error');
return delayCall(() => MY_API.TreasureBox.getCurrentTask());
});
},
captcha: {
cnt: 0,
calc: () => {
if (!MY_API.CONFIG.AUTO_TREASUREBOX) {
MY_API.TreasureBox.captcha.cnt = 0;
return $.Deferred().reject();
}
if (MY_API.TreasureBox.captcha.cnt > 20) { // 允许验证码无法识别的次数
// 验证码识别失败
MY_API.TreasureBox.setMsg('验证码
识别
失败');
window.toast('[自动领取瓜子]验证码识别失败,已停止', 'error');
return $.Deferred().reject();
}
return BAPI.TreasureBox.getCaptcha(ts_ms()).then((response) => {
MYDEBUG('TreasureBox.captcha.calc: getCaptcha', response);
if (response.code === 0) {
MY_API.TreasureBox.captcha.cnt++;
const p = $.Deferred();
MY_API.TreasureBox.promise.calc = $.Deferred();
MY_API.TreasureBox.promise.calc.then((captcha) => {
MY_API.TreasureBox.captcha.cnt = 0;
p.resolve(captcha);
}, () => {
MY_API.TreasureBox.captcha.calc().then((captcha) => {
p.resolve(captcha);
}, () => {
p.reject();
});
});
MY_API.TreasureBox.DOM.image.attr('src', response.data.img);
return p;
} else {
window.toast(`[自动领取瓜子]${response.msg}`, 'caution');
return delayCall(() => MY_API.TreasureBox.captcha.calc());
}
}, () => {
window.toast('[自动领取瓜子]加载验证码失败,请检查网络', 'error');
return delayCall(() => MY_API.TreasureBox.captcha.calc());
});
},
// 对B站验证码进行处理
// 代码来源:https://github.com/zacyu/bilibili-helper/blob/master/src/bilibili_live.js
// 删除了未使用的变量
OCR: {
getGrayscaleMap: (context, rate = 235, width = 120, height = 40) => {
const pixelMap = context.getImageData(0, 0, width, height).data;
const map = [];
for (let y = 0; y < height; y++) { // line y
for (let x = 0; x < width; x++) { // column x
const index = (y * width + x) * 4;
const pixel = pixelMap.slice(index, index + 4);
const gray = pixel ? (77 * pixel[0] + 150 * pixel[1] + 29 * pixel[2] + 128) >> 8 : 0;
map.push(gray > rate ? gray : 0);
}
}
return map;
},
orderFilter2In3x3: (grayscaleMap, n = 9, width = 120) => {
const gray = (x, y) => (x + y * width >= 0) ? grayscaleMap[x + y * width] : 255;
const map = [];
const length = grayscaleMap.length;
const catchNumber = n - 1;
for (let i = 0; i < length; ++i) {
const [x, y] = [i % width, Math.floor(i / width)];
const matrix = new Array(9);
matrix[0] = gray(x - 1, y - 1);
matrix[1] = gray(x + 0, y - 1);
matrix[2] = gray(x + 1, y - 1);
matrix[3] = gray(x - 1, y + 0);
matrix[4] = gray(x + 0, y + 0);
matrix[5] = gray(x + 1, y + 0);
matrix[6] = gray(x - 1, y + 1);
matrix[7] = gray(x + 0, y + 1);
matrix[8] = gray(x + 1, y + 1);
matrix.sort((a, b) => a - b);
map.push(matrix[catchNumber]);
}
return map;
},
},
eval: (fn) => {
let Fn = Function;
return new Fn(`return ${fn}`)();
},
// 修正OCRAD识别结果
// 代码来源:https://github.com/zacyu/bilibili-helper
// 修改部分:
// 1.将correctStr声明在correctQuestion函数内部,并修改相关引用
// 2.在correctStr中增加'>': 3
correctStr: {
'i': 1, 'I': 1, '|': 1, 'l': 1,
'o': 0, 'O': 0, 'D': 0,
'S': 6, 's': 6, 'b': 6,
'R': 8, 'B': 8,
'z': 2, 'Z': 2,
'.': '-',
'_': 4,
'g': 9,
'>': 3
},
correctQuestion: (question) => {
let q = '';
question = question.trim();
for (let i in question) {
let a = MY_API.TreasureBox.captcha.correctStr[question[i]];
q += (a !== undefined ? a : question[i]);
}
if (q[2] === '4') q[2] = '+'; //若第三位为4则替换为+
for (let c = 0; c <= parseInt(q.length - 2); c++) {//'1 => 7
if (q[c] === '\'' && q[c + 1] === '1') {
q[c] = '7';
q.splice(c + 1, 1)
}
}
return q;
}
}
}, // Constantly Run, Need Init
Gift: {
run_timer: undefined,
ruid: undefined,
room_id: undefined,
medal_list: undefined,
bag_list: undefined,
time: undefined,
remain_feed: undefined,
notSendGiftList: [3, 4, 9, 10, 39, 30588, 30587, 30586, 30585],
//B坷垃,喵娘,爱心便当,蓝白胖次,节奏风暴,如意小香包,软糯白糖粽,飘香大肉粽,端午茗茶
getMedalList: (page = 1) => {
if (page === 1) MY_API.Gift.medal_list = [];
return 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(page));
});
},
getBagList: () => {
return 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) => {
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;
},
run: async () => {
const FailFunc = () => {
window.toast('[自动送礼]送礼失败,请检查网络', 'error');
return delayCall(() => MY_API.Gift.run());
};
const nextTimeDebug = () => {
let alternateTime = getIntervalTime(MY_API.CONFIG.GIFT_SEND_HOUR, MY_API.CONFIG.GIFT_SEND_MINUTE);
setTimeout(MY_API.Gift.run, alternateTime);
let runTime = new Date(ts_ms() + alternateTime).toLocaleString();
MYDEBUG("[自动送礼]", `将在${runTime}进行自动送礼`);
}
try {
if (!MY_API.CONFIG.AUTO_GIFT) return $.Deferred().resolve();
if (!isTime(MY_API.CONFIG.GIFT_SEND_HOUR, MY_API.CONFIG.GIFT_SEND_MINUTE) && SEND_GIFT_NOW == false) {
let alternateTime = getIntervalTime(MY_API.CONFIG.GIFT_SEND_HOUR, MY_API.CONFIG.GIFT_SEND_MINUTE);
setTimeout(MY_API.Gift.run, alternateTime);
let runTime = new Date(ts_ms() + alternateTime).toLocaleString();
MYDEBUG("[自动送礼]", `将在${runTime}进行自动送礼`);
return $.Deferred().resolve();
};
await MY_API.Gift.getMedalList();
MYDEBUG('Gift.run: Gift.getMedalList().then: Gift.medal_list', MY_API.Gift.medal_list);
if (MY_API.Gift.medal_list && MY_API.Gift.medal_list.length > 0) {
MY_API.Gift.medal_list = MY_API.Gift.medal_list.filter(it => it.dayLimit - it.today_feed > 0 && it.level < 20);
if (MY_API.CONFIG.GIFT_SORT) {
MY_API.Gift.medal_list.sort((a, b) => {
if (b.level - a.level == 0) {
return b.intimacy - a.intimacy;
}
return b.level - a.level;
});
} else {
MY_API.Gift.medal_list.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.split(",");
sortRooms.reverse();
for (let froom of sortRooms) {
let rindex = MY_API.Gift.medal_list.findIndex(r => r.roomid == froom);
if (rindex != -1) {
let tmp = MY_API.Gift.medal_list[rindex];
MY_API.Gift.medal_list.splice(rindex, 1);
MY_API.Gift.medal_list.unshift(tmp);
}
}
}
let limit = MY_API.CONFIG.GIFT_LIMIT;
for (let v of MY_API.Gift.medal_list) {
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();
let now = ts_s();
if (!MY_API.CONFIG.SEND_ALL_GIFT) {
//送之前查一次有没有可送的
let pass = MY_API.Gift.bag_list.filter(r => !MY_API.Gift.notSendGiftList.includes(r.gift_id) && r.gift_num > 0 && r.expire_at > now && (r.expire_at - now < limit));
if (pass.length == 0) {
break;
}
};
MY_API.CACHE.Gift_TS = ts_ms();
MY_API.saveCache();
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);
if (!MY_API.CONFIG.SEND_ALL_GIFT) {
let pass = MY_API.Gift.bag_list.filter(r => !MY_API.Gift.notSendGiftList.includes(r.gift_id) && r.gift_num > 0 && r.expire_at > now && (r.expire_at - now < limit));
if (pass.length == 0) {
break;
}
}
} else {
window.toast(`[自动送礼]勋章[${v.medalName}] 今日亲密度已满`, 'info');
}
}
}
}
await MY_API.Gift.getBagList();
let i = 0;
for (i = 0; i <= MY_API.Gift.bag_list.length - 1; i++) {
if (MY_API.Gift.bag_list[i].gift_id == 1) {
break;
}
}
let v = MY_API.Gift.bag_list[i];
if (v == undefined) {
SEND_GIFT_NOW = false;
nextTimeDebug();
return $.Deferred().resolve();
}
let feed = MY_API.Gift.getFeedByGiftID(v.gift_id);
let limit = 86400;
let now = ts_s();
if (//剩余礼物,今日送完所有牌子后若有小于1天的礼物则送礼。检查有没有可送的
MY_API.Gift.bag_list.filter(r => !MY_API.Gift.notSendGiftList.includes(r.gift_id) && r.gift_num > 0 && r.expire_at > now && (r.expire_at - now < limit)).length != 0
&& //满足到期时间小于一天
v.expire_at > MY_API.Gift.time && (v.expire_at - MY_API.Gift.time < 86400
&& MY_API.CONFIG.SPARE_GIFT_ROOM != '0' && MY_API.CONFIG.SPARE_GIFT_UID != '0'
&& feed > 0)) {
let giftnum = v.gift_num;
return BAPI.gift.bag_send(Live_info.uid, v.gift_id, MY_API.CONFIG.SPARE_GIFT_UID, giftnum, v.bag_id, MY_API.CONFIG.SPARE_GIFT_ROOM, Live_info.rnd).then((response) => {
MYDEBUG('Gift.sendGift(剩余礼物): API.gift.bag_send', response);
if (response.code === 0) {
window.toast(`[自动送礼](剩余礼物)房间[${MY_API.CONFIG.SPARE_GIFT_ROOM}] 送礼成功,送出${giftnum}个${v.gift_name}`, 'success');
} else {
window.toast(`[自动送礼](剩余礼物)房间[${MY_API.CONFIG.SPARE_GIFT_ROOM}] 送礼异常:${response.msg}`, 'caution');
}
}, () => {
window.toast('[自动送礼](剩余礼物)包裹送礼失败,请检查网络', 'error');
return delayCall(() => MY_API.Gift.sendGift(medal, i));
});
}
} catch (err) {
FailFunc();
window.toast('[自动送礼]运行时出现异常,已停止', 'error');
console.error(`[${NAME}]`, err);
return $.Deferred().reject();
}
SEND_GIFT_NOW = false;
nextTimeDebug();
},
sendGift: (medal, i = 0) => {
if (i >= MY_API.Gift.bag_list.length) {
return $.Deferred().resolve();
}
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();
const v = MY_API.Gift.bag_list[i];
if (
//特殊礼物排除
(!MY_API.Gift.notSendGiftList.includes(v.gift_id)
//满足到期时间
&& v.expire_at > MY_API.Gift.time && (v.expire_at - MY_API.Gift.time < MY_API.CONFIG.GIFT_LIMIT)
)
//或者全部送满
|| MY_API.CONFIG.SEND_ALL_GIFT) {
// 检查SEND_ALL_GIFT和礼物到期时间 送当天到期的
if (v.gift_id == undefined) {
return $.Deferred().resolve();
}
if (v == undefined) {
return $.Deferred().resolve();
}
const 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) {
return 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');
}
return MY_API.Gift.sendGift(medal, i + 1);
}, () => {
window.toast('[自动送礼]包裹送礼失败,请检查网络', 'error');
return delayCall(() => MY_API.Gift.sendGift(medal, i));
});
}
}
}
return MY_API.Gift.sendGift(medal, i + 1);
}
},
MobileHeartBeat: {
run:
async () => {
if (MY_API.CONFIG.MOBILE_HEARTBEAT == false) return $.Deferred().resolve();
if (!checkNewDay(MY_API.CACHE.MobileHeartBeat_TS)) {
runMidnight(MY_API.MobileHeartBeat.run, '移动端心跳');
return $.Deferred().resolve();
}
/*
const appToken = new BilibiliToken();
const 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`;
let tokenData = JSON.parse(GM_getValue('userToken', '{}'));
const setToken = async () => {
const userToken = await appToken.getToken();
if (userToken === undefined)
return console.error(GM_info.script.name, '未获取到token');
tokenData = userToken;
GM_setValue('userToken', JSON.stringify(tokenData));
return 'OK';
};*/
const 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
});
const 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
});
};
const getWatchingAward = () => {
if (checkNewDay(MY_API.CACHE.MobileHeartBeat_TS)) {
MY_API.CACHE.MobileHeartBeat_TS = ts_ms();
MY_API.saveCache();
BAPI.activity.receive_award('double_watch_task').then((response) => {
if (response.code === 0) {
window.toast('[双端观看直播]奖励领取成功', 'success');
MYDEBUG('MobileHeartBeat GetAward', response);
clearInterval(HBinterval);
runMidnight(MY_API.MobileHeartBeat.run, '移动端心跳');
return $.Deferred().resolve();
}
else if (response.code === -400) {
window.toast('[双端观看直播]奖励已领取', 'info');
MYDEBUG('MobileHeartBeat GetAward', response);
clearInterval(HBinterval);
runMidnight(MY_API.MobileHeartBeat.run, '移动端心跳');
return $.Deferred().resolve();
}
else {
window.toast('[双端观看直播]其它错误', 'warning');
MYDEBUG('MobileHeartBeat GetAward', response);
clearInterval(HBinterval);
runMidnight(MY_API.MobileHeartBeat.run, '移动端心跳');
return $.Deferred().resolve();
}
}, (err) => {
window.toast('[双端观看直播]奖励领取失败,请检查网络', 'error');
console.error('MobileHeartBeat GetAward', err);
clearInterval(HBinterval);
return delayCall(() => MY_API.MobileHeartBeat.run());
});
}
else {
MYDEBUG('[双端观看直播]', '同一天不领取');
clearInterval(HBinterval);
runMidnight(MY_API.MobileHeartBeat.run, '移动端心跳');
return $.Deferred().resolve();
}
}
if (tokenData.access_token === undefined && await setToken() === undefined)
return;
else {
const userInfo = await getInfo();
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('MobileHeartBeat', '开始客户端心跳');
mobileOnline();
let HBinterval = undefined;
HBinterval = setInterval(() => mobileOnline(), 5 * 60 * 1000);
setTimeout(() => getWatchingAward(), 6 * 60 * 1000);
}
},
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) => {
DEBUG('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);
}
DEBUG('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();
}
},
};
MY_API.init().then(() => {//主函数
try {
const promiseInit = $.Deferred();
const uniqueCheck = () => {
const t = Date.now();
if (t - MY_API.CACHE.UNIQUE_CHECK >= 0 && t - MY_API.CACHE.UNIQUE_CHECK <= 15e3) {
// 其他脚本正在运行
$('.link-toast').hide();
$('.igiftMsg').hide();
MY_API.CONFIG.AUTO_TREASUREBOX = false;
window.toast('有其他直播间页面的脚本正在运行,本页面脚本停止运行', 'caution');
return promiseInit.reject();
}
// 没有其他脚本正在运行
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
}
MYDEBUG('MY_API.CONFIG', MY_API.CONFIG);
StartPlunder(MY_API);
})
}
catch (e) {
console.error('重复运行检测错误', e);
}
});
}
function StartPlunder(API) {
'use strict';
//清空辣条数量
if(checkNewDay(API.GIFT_COUNT.CLEAR_TS)) clearStat();
let clearStat = () => {
API.GIFT_COUNT.COUNT = 0;
API.GIFT_COUNT.CLEAR_TS = dateNow();
API.saveGiftCount();
MYDEBUG('已清空辣条数量')
}
runExactMidnight(clearStat, '重置统计')
setTimeout(() => {
API.removeUnnecessary();
API.GroupSign.run();//应援团签到
API.DailyReward.run();//每日任务
API.LiveReward.run();//直播每日任务
API.Exchange.runS2C();//银瓜子换硬币
API.TreasureBox.run();//领宝箱
API.Gift.run();//送礼物
API.MobileHeartBeat.run();//移动端心跳
}, 6e3);//脚本加载后6秒执行每日任务,移除页面元素
API.creatSetBox();//创建设置框
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}区`);
}
});
}
});
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
}
BAPI.rankdb.getTopRealTimeHour().then(function (data) {
let list = data.data.list;// [{id: ,link:}]
API.chatLog('检查小时榜房间的礼物', 'warning');
MYDEBUG('小时榜房间列表', list);
for (let i of list) {
API.checkRoom(i.roomid, `小时榜-${i.area_v2_parent_name}区`);
}
})
};
setTimeout(check_top_room, 6e3);//加载脚本后6秒检查一次小时榜
let check_timer = setInterval(check_top_room, parseInt(API.CONFIG.CHECK_HOUR_ROOM_INTERVAL * 1000));
let reset = (delay) => {
setTimeout(() => {//重置直播间
if (API.raffleId_list.length > 0 || API.guardId_list.length > 0 || API.pkId_list.length > 0) {
MYDEBUG('还有礼物没抽,延迟30s后刷新直播间');
reset(30000);
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) {//在不抽奖时段且不抽奖时段不刷新开启
return;
}
/* if (API.blocked || API.max_blocked) { //被阻止不刷新直播间
return
}*/
window.location.reload();
}, delay);
};
reset(API.CONFIG.TIME_RELOAD * 60000);//单位1分钟,重新加载直播间
}
/**
* (23,50) 获取与目标时间在时间轴上的间隔时间,24小时制(毫秒)
* @param hour 整数 小时
* @param minute 整数 分钟
* @returns {number} intervalTime
*/
function getIntervalTime(hour, minute) {
let myDate = new Date();
let h = myDate.getHours();
let m = myDate.getMinutes();
let s = myDate.getSeconds();
let TargetTime = hour * 3600 * 1e3 + minute * 60 * 1e3;
let nowTime = h * 3600 * 1e3 + m * 60 * 1e3 + s * 1e3;
let intervalTime = TargetTime - nowTime;
MYDEBUG("[getIntervalTime]获取间隔时间", intervalTime + '毫秒');
if (intervalTime < 0) {
return 24 * 3600 * 1e3 + intervalTime
}
else {
return intervalTime
}
}
/**
* (1000000000) 获取到明天的目标时间戳所在的相同【时间点】所需时间(毫秒)
* @param date 整数 时间戳
* @returns {number} intervalTime
*/
function GetTomorrowIntervalTime(date) {
let intervalTime = ts_ms() - date;
MYDEBUG("[GetTomorrowIntervalTime]获取间隔时间", intervalTime + '毫秒');
if (intervalTime > 24 * 3600 * 1e3) {
return intervalTime;
}
else {
return 24 * 3600 * 1e3 - intervalTime;
}
}
/**
* (23,50) 当前时间是否为23:50
* @param hour 整数 小时
* @param minute 整数 分钟
* @returns {boolean}
*/
function isTime(hour, minute) {
let myDate = new Date();
let h = myDate.getHours();
let m = myDate.getMinutes();
if (h == hour && m == minute) {
return true
} else {
MYDEBUG("错误时间");
return false
}
}
/**
* (2,10,0,1) 当前是否在两点0分到十点0分之间
* @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) {
MYDEBUG('错误时间段');
return false
}
let myDate = new Date();
let h = myDate.getHours();
let m = myDate.getMinutes();
if (sH < eH) {//如(2,0,8,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,0,12,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 (m >= sM && m < eM)
return true
else return false;
}
}
/**
* 概率
* @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);
}
});
};
})();