"),
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);
JQmenuWindow.append(div);//向聊天框加入信息
if (layerLogWindow_ScrollY >= layerLogWindow_ScrollHeight)
layerLogWindow.scrollTop(layerLogWindow.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);
removeValinArray(data.raffleId, MY_API.raffleId_list);//移除礼物id列表
});
break;
case 'guard':
MY_API.guard_join(roomId, data.id).then(function (msg, num) {
aa.text(msg);
removeValinArray(data.id, MY_API.guardId_list);//移除礼物id列表
});
break;
case 'pk':
MY_API.pk_join(roomId, data.id).then(function (msg, num) {
aa.text(msg);
removeValinArray(data.id, MY_API.pkId_list);//移除礼物id列表
});
break;
}
}
aa.css('color', 'green');
clearInterval(timer)
}
delay--;
}, 1000);
},
gift_join: function (roomid, raffleId, type) {
return BAPI.Lottery.Gift.join(roomid, raffleId, type).then((response) => {
let p = $.Deferred();
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) {
MY_API.blocked = true;//停止抽奖
p.resolve('访问被拒绝,您的帐号可能已经被关小黑屋,已停止');
} else {
p.resolve(`[礼物抽奖](roomid=${roomid},id=${raffleId},type=${type})${response.msg}`);
}
break;
}
return p
});
},
guard_join: function (roomid, Id) {
return BAPI.Lottery.Guard.join(roomid, Id).then((response) => {
MYDEBUG('上船抽奖返回信息', response);
let p = $.Deferred();
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) {
MY_API.blocked = true;//停止抽奖
p.resolve('访问被拒绝,您的帐号可能已经被关小黑屋,已停止');
} else {
p.resolve(`[上船](roomid=${roomid},id=${Id})${response.msg}`);
}
break;
}
return p
});
},
pk_join: function (roomid, Id) {
return BAPI.Lottery.Pk.join(roomid, Id).then((response) => {
MYDEBUG('PK抽奖返回信息', response);
let p = $.Deferred();
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;
case -1:
//奖品已经飞走啦~
p.resolve(response.message);
break;
case -2:
//您已参加过抽奖
//未中奖~参与大乱斗可提升欧气哦~~
p.resolve(response.message);
break;
default:
if (response.msg.indexOf('拒绝') > -1) {
MY_API.blocked = true;//停止抽奖
p.resolve('访问被拒绝,您的帐号可能已经被关小黑屋,已停止');
} 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');
MYERROR(`自动应援团签到出错`, err);
return $.Deferred().reject();
}
}
},
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, uidIndex, 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) {
return MY_API.DailyReward.UserSpace(uidIndex, 30, 0, pagenum + 1, '', 'pubdate', 'jsonp');
}
const obj = vlist[i], uid = MY_API.CONFIG.COIN_UID[uidIndex];
if (obj.hasOwnProperty('is_union_video') && 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, uidIndex, 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, uidIndex, 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, uidIndex, 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, uidIndex, i + 1);
return MY_API.DailyReward.coin_uid(vlist, n, i, pagenum, uidIndex, true);
} else if (response.code === 34005) {
// 塞满啦!先看看库存吧~
return MY_API.DailyReward.coin_uid(vlist, n, pagenum, uidIndex, 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, uidIndex, i + 1);
}, () => delayCall(() => MY_API.DailyReward.coin_uid(vlist, n, pagenum, uidIndex, 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(0, 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: (uidIndex, ps, tid, pn, keyword, order, jsonp) => {
return BAPI.x.getUserSpace(MY_API.CONFIG.COIN_UID[uidIndex], 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;
return MY_API.DailyReward.coin_uid(response.data.list.vlist, Math.max(throwCoinNum, 0), pn, uidIndex);
} else if (uidIndex < MY_API.CONFIG.COIN_UID.length - 1) {
const throwCoinNum = MY_API.CONFIG.COIN_NUMBER - MY_API.DailyReward.coin_exp / 10;
return MY_API.DailyReward.coin_uid(response.data.list.vlist, Math.max(throwCoinNum, 0), pn, uidIndex + 1);
} else {
window.toast(`[自动每日奖励]"UID = ${String(MY_API.CONFIG.COIN_UID)}的空间-投稿视频"中暂无视频`, 'info');
}
}
else {
window.toast(`[自动每日奖励]获取UID = ${MY_API.CONFIG.COIN_UID[uidIndex]}的"空间-投稿视频"'${response.msg}`, 'caution');
}
}, () => {
window.toast('[自动每日奖励]获取"空间-投稿视频"失败,请检查网络', 'error');
return delayCall(() => MY_API.DailyReward.UserSpace(uid, ps, tid, pn, keyword, order, jsonp));
})
},
run: (forceRun = false) => {
try {
if (!MY_API.CONFIG.LOGIN && !MY_API.CONFIG.COIN && !MY_API.CONFIG.WATCH) return $.Deferred().resolve();
if (!checkNewDay(MY_API.CACHE.DailyReward_TS) && !forceRun) {
// 同一天,不执行每日任务
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');
MYERROR(`自动每日奖励出错`, err);
return $.Deferred().reject();
}
}
},
LiveReward: {
dailySignIn: () => {
return BAPI.xlive.dosign().then((response) => {
MYDEBUG('LiveReward.dailySignIn: API.xlive.dosign', response);
if (response.code === 0) {
window.toast('[自动直播签到]完成', 'success');
$('.hinter').remove();//移除签到按钮和小红点
$('.checkin-btn').remove();
} else if (response.code === 1011040) {
window.toast('[自动直播签到]今日直播签到已完成', 'info')
} else {
window.toast(`[自动直播签到]${response.message},尝试点击签到按钮`, 'caution');
$('.checkin-btn').click();
}
}, () => {
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');
MYERROR(`自动直播签到出错`, err);
return $.Deferred().reject();
}
}
},
Exchange: {
coin2silver: (num) => {
return BAPI.Exchange.coin2silver(num).then((response) => {
MYDEBUG('Exchange.coin2silver: API.Exchange.coin2silver', response);
if (response.code === 0) {
window.toast(`[硬币换银瓜子] ${response.msg},获得${response.data.silver}银瓜子`, 'success');
} else { //其它状态码待补充
window.toast(`[银瓜子换硬币] ${response.msg}`, 'caution');
}
}, () => {
window.toast('[硬币换银瓜子] 兑换失败,请检查网络', 'error');
return delayCall(() => MY_API.Exchange.coin2silver(num));
});
},
silver2coin: () => {
return BAPI.Exchange.silver2coin().then((response) => {
MYDEBUG('Exchange.silver2coin: API.Exchange.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());
});
},
runC2S: () => {
if (!MY_API.CONFIG.COIN2SILVER) return $.Deferred().resolve();
if (!checkNewDay(MY_API.CACHE.Coin2Sliver_TS)) {
// 同一天,不再兑换瓜子
runMidnight(MY_API.Exchange.runC2S, '硬币换瓜子');
return $.Deferred().resolve();
}
return MY_API.Exchange.coin2silver(MY_API.CONFIG.COIN2SILVER_NUM).then(() => {
MY_API.CACHE.Coin2Sliver_TS = ts_ms();
MY_API.saveCache();
runMidnight(MY_API.Exchange.runC2S, '硬币换瓜子');
}, () => delayCall(() => MY_API.Exchange.runC2S()))
},
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');
MYERROR(`银瓜子换硬币出错`, 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,
//B坷垃,喵娘,爱心便当,蓝白胖次,节奏风暴,如意小香包,软糯白糖粽,飘香大肉粽,端午茗茶
sendGiftList: undefined,//辣条,亿圆, 小心心
getMedalList: async (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());
});
},
getBagList: async () => {
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) => {
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 == '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 || 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 {
let alternateTime = MY_API.CONFIG.GIFT_INTERVAL * 60 * 1000;
MY_API.Gift.run_timer = setTimeout(() => MY_API.Gift.run(), alternateTime);
MYDEBUG("[自动送礼]", `将在${MY_API.CONFIG.GIFT_INTERVAL}分钟后进行自动送礼`);
MY_API.CACHE.GiftInterval_TS = ts_ms();
MY_API.saveCache();
}
return
};
const handleGiftList = () => {
MY_API.Gift.sendGiftList = MY_API.CONFIG.GIFT_ALLOW_TYPE;
MYDEBUG('[自动送礼]', `处理前的礼物列表 ${MY_API.Gift.sendGiftList}`);
for (let i = 0; i < MY_API.Gift.sendGiftList.length; i++) {
const listItem = MY_API.Gift.sendGiftList[i];
let matchItem;
if (isNaN(listItem)) {
//如果填了礼物名,转换为id
matchItem = Live_info.gift_list.find(item => item.name === listItem);
if (matchItem) MY_API.Gift.sendGiftList[i] = String(matchItem.id);
}
}
MYDEBUG('[自动送礼]', `处理后得到的礼物id列表 ${MY_API.Gift.sendGiftList}`)
};
try {
if (!MY_API.CONFIG.AUTO_GIFT) return $.Deferred().resolve();
if (medalDanmuRunning) {
window.toast(`[自动送礼]【粉丝牌打卡】任务运行中,暂停运行,30秒后再次检查`, 'warning');
return setTimeout(() => MY_API.Gift.run(), 30e3);
}
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 $.Deferred().resolve();
}
}
else {
MY_API.CACHE.GiftInterval_TS = ts_ms();
MY_API.saveCache();
}
}
MY_API.Gift.over = false;
handleGiftList();
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');
MYERROR(`自动送礼出错`, 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(String(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(String(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 {
const config = JSON.parse(localStorage.getItem(`${NAME}stormIdSet`));
storm_id_list = [...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 {
const config = JSON.parse(localStorage.getItem(`${NAME}stormIdSet`));
if (config === null) {
storm_id_list = [];
} else {
storm_id_list = [...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) => {
let 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();
return BAPI.Storm.check(roomid).then((response) => {
MYDEBUG('MY_API.Storm.run: MY_API.API.Storm.check', response);
if (response.code === 0) {
let 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');
MYERROR(`节奏风暴出错`, 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();
let 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);
let stormInterval = 0;
if (endtime <= 0) {
endtime = Math.round(new Date().getTime() / 1000) + 90;
}
let count = 0;
window.toast(`[自动抽奖][节奏风暴]尝试抽奖(roomid=${roomid},id=${id})`, 'success');
async function process() {
try {
if (!MY_API.Storm.check(id)) {
clearInterval(stormInterval);
return;
}
let timenow = Math.round(new Date().getTime() / 1000);
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');
MYERROR('节奏风暴疑似触发风控', `roomid = ${roomid}`, `id = ${id}`, e);
clearInterval(stormInterval);
return;
}
}
catch (e) {
MY_API.Storm.over(id);
window.toast(`[自动抽奖][节奏风暴]抽奖(roomid=${roomid},id=${id})抽奖异常,终止!`, 'error');
MYERROR('节奏风暴抽奖异常', `roomid = ${roomid}`, `id = ${id}`, 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
}),
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
});
MYDEBUG('[小心心] getFansMedal', funsMedals.response);
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('[小心心]检查包裹 API.gift.bag_list', 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
});
MYDEBUG('[小心心] mobileHeartBeat', mobileHeartBeat.response);
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: '60',
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 = async (check = true) => {
if (check) await sleep(5000);//小心心获取有延时等待5秒
if (!check || await MY_API.LITTLE_HEART.getGiftNum() >= 24) {
window.toast('[小心心]今日小心心已全部获取', 'success');
MY_API.CACHE.LittleHeart_TS = ts_ms();
MY_API.saveCache();
return runMidnight(MY_API.LITTLE_HEART.run, '获取小心心');
} else {//出于某些原因心跳次数到到了但小心心个数没到,再次运行
window.toast('[小心心]小心心未全部获取,60秒后将再次运行', 'info');
return setTimeout(() => MY_API.LITTLE_HEART.run(), 60 * 1000)
}
}
if (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 MYERROR('小心心', '获取用户信息错误');
if (userInfo.body.code !== 0 && await setToken() === undefined)
return;
else if (userInfo.body.data.mid !== Live_info.uid && await setToken() === undefined)
return;
};
MYDEBUG('[小心心] 开始客户端心跳 tokenData', tokenData.access_token);
window.toast('[小心心]开始获取小心心', 'success');
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) * 5;
for (let i = 0; i < loopNum; i++) {
let count = 0;
for (const funsMedalData of fansMedal) {
if (count >= control) break;
const postData = Object.assign({}, mobileHeartBeatJSON, {
room_id: funsMedalData.room_id.toString(),
timestamp: (BilibiliToken.TS - 60).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++;
}
await sleep(60 * 1000);
}
return endFunc();
}
} else {
return endFunc(false);
}
}
},
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) => {
let realRoomId = roomId;
if (Number(roomId) <= 10000) {
realRoomId = await BAPI.room.get_info(roomId).then((res) => {
MYDEBUG(`API.room.get_info roomId=${roomId} res`, res);//可能是短号,要用长号发弹幕
return res.data.room_id;
}), () => {
window.toast(`[自动发弹幕]房间号【${roomId}】信息获取失败`, 'error')
return $.Deferred().reject();
};
}
return BAPI.sendLiveDanmu(danmuContent, realRoomId).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');
return $.Deferred().reject();
})
},
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();
if (medalDanmuRunning) {
window.toast(`[自动发弹幕]【粉丝牌打卡】任务运行中,暂停运行,30秒后再次检查`, 'warning');
return setTimeout(() => MY_API.AUTO_DANMU.run(), 30e3);
}
danmuTaskRunning = true;
if (SEND_DANMU_NOW) {
for (let i = 0; i < MY_API.CONFIG.DANMU_CONTENT.length; i++) {
let danmu_content = MY_API.AUTO_DANMU.setValue('DANMU_CONTENT', i),
danmu_roomid = parseInt(MY_API.AUTO_DANMU.setValue('DANMU_ROOMID', i));
await MY_API.AUTO_DANMU.sendDanmu(danmu_content, danmu_roomid);
await sleep(1000);
}
SEND_DANMU_NOW = false;
} else {
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,//间隔时间
danmuTime = [],//储存时间点格式的数组,eg:[10:0:5]
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]);
danmuTime = [hour, minute, second];
if (!isTime(hour, minute, second)) sleepTime = getIntervalTime(hour, minute, second);
else sleepTime = 86400000;
}
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;
return MY_API.saveCache(false);
};
const sendNextDanmu = (intervalTS, isTime) => {
if (!isTime) setCache();
return setTimeout(async () => {
await MY_API.AUTO_DANMU.sendDanmu(danmu_content, danmu_roomid);
if (!isTime) setCache();
return sendNextDanmu(intervalTS, isTime);
}, intervalTS);
}
if (!isTimeData && intervalTime >= danmu_intervalTime_Ts) {
//非时间数据,距上次发送的时间大于间隔时间
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) {
//时间点数据,立刻发送
await MY_API.AUTO_DANMU.sendDanmu(danmu_content, danmu_roomid);
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(1500);
}
}
danmuTaskRunning = false;
}
},
MEDAL_DANMU: {
medal_list: [],
retryRoomList: [],
getMedalList: async (page = 1) => {
if (page === 1) MY_API.MEDAL_DANMU.medal_list = [];
return BAPI.i.medal(page, 25).then((response) => {
MYDEBUG('MEDAL_DANMU.getMedalList: API.i.medal', response);
MY_API.MEDAL_DANMU.medal_list = MY_API.MEDAL_DANMU.medal_list.concat(response.data.fansMedalList);
if (response.data.pageinfo.curPage < response.data.pageinfo.totalpages) return MY_API.MEDAL_DANMU.getMedalList(page + 1);
}, () => {
MY_API.chatLog('[粉丝牌打卡弹幕]
获取勋章列表失败,请检查网络', 'error');
return delayCall(() => MY_API.MEDAL_DANMU.getRoomList());
});
},
sendDanmu: async (danmuContent, roomId, medal_name) => {
let realRoomId = roomId;
if (Number(roomId) <= 10000) {
realRoomId = await BAPI.room.get_info(roomId).then((res) => {
MYDEBUG(`API.room.get_info roomId=${roomId} res`, res);//可能是短号,要用长号发弹幕
return res.data.room_id;
}), () => {
window.toast(`[粉丝牌打卡弹幕] 房间号【${roomId}】信息获取失败`, 'error')
return $.Deferred().reject();
};
}
return BAPI.sendLiveDanmu(danmuContent, realRoomId).then((response) => {
MYDEBUG(`[粉丝牌打卡弹幕] 弹幕发送内容【${danmuContent}】,房间号【${roomId}】,粉丝勋章【${medal_name}】`, response);
if (response.code === 0 && !response.msg) {
window.toast(`[粉丝牌打卡弹幕] 弹幕【${danmuContent}】发送成功,房间号【${roomId}】,粉丝勋章【${medal_name}】已点亮,当前亲密度+100`, 'success');
} else {
window.toast(`[粉丝牌打卡弹幕] 弹幕【${danmuContent}】(房间号【${roomId}】,粉丝勋章【${medal_name}】)出错 ${response.msg},稍后重试`, 'caution');
retryRoomList.push(realRoomId);
}
}, () => {
window.toast(`[粉丝牌打卡弹幕] 弹幕【${danmuContent}】(房间号【${roomId}】,粉丝勋章【${medal_name}】)发送失败`, 'error');
return $.Deferred().reject();
})
},
run: async () => {
if (!MY_API.CONFIG.MEDAL_DANMU) return $.Deferred().resolve();
if (!checkNewDay(MY_API.CACHE.MedalDanmu_TS)) {
runMidnight(() => MY_API.MEDAL_DANMU.run(), '粉丝勋章打卡弹幕');
return $.Deferred().resolve();
}
if (danmuTaskRunning) {
window.toast(`[粉丝牌打卡]【自动发弹幕】任务运行中,暂停运行,30秒后再次检查`, 'warning');
return setTimeout(() => MY_API.MEDAL_DANMU.run(), 30e3);
}
medalDanmuRunning = true;
await MY_API.MEDAL_DANMU.getMedalList();
let lightMedalList;
MY_API.MEDAL_DANMU.retryRoomList = [];
if (MY_API.CONFIG.MEDAL_DANMU_METHOD === 'MEDAL_DANMU_WHITE')
lightMedalList = MY_API.MEDAL_DANMU.medal_list.filter(r => MY_API.CONFIG.MEDAL_DANMU_ROOM.findIndex(m => m == r.roomid) > -1);
else {
lightMedalList = MY_API.MEDAL_DANMU.medal_list.filter(r => MY_API.CONFIG.MEDAL_DANMU_ROOM.findIndex(m => m == r.roomid) === -1);
}
MYDEBUG('[粉丝牌打卡] 过滤后的粉丝勋章房间列表', lightMedalList);
let danmuContentIndex = 0;
const configDanmuLength = MY_API.CONFIG.MEDAL_DANMU_CONTENT.length;
//第一轮
for (const up of lightMedalList) {
if (danmuContentIndex >= configDanmuLength) danmuContentIndex = 0;
const medal_name = up.medal_name,
roomid = up.roomid,
danmuContent = MY_API.CONFIG.MEDAL_DANMU_CONTENT[danmuContentIndex];
await MY_API.MEDAL_DANMU.sendDanmu(danmuContent, roomid, medal_name);
danmuContentIndex++;
await sleep(MY_API.CONFIG.MEDAL_DANMU_INTERVAL * 1000);
}
//第二轮,再次尝试发送之前失败的
if (MY_API.MEDAL_DANMU.retryRoomList.length > 0) {
for (const up of MY_API.MEDAL_DANMU.retryRoomList) {
if (danmuContentIndex >= configDanmuLength) danmuContentIndex = 0;
const medal_name = up.medal_name,
roomid = up.roomid,
danmuContent = MY_API.CONFIG.MEDAL_DANMU_CONTENT[danmuContentIndex];
await MY_API.MEDAL_DANMU.sendDanmu(danmuContent, roomid, medal_name);
danmuContentIndex++;
await sleep(MY_API.CONFIG.MEDAL_DANMU_INTERVAL * 1000);
}
}
medalDanmuRunning = false;
window.toast('[粉丝牌打卡弹幕] 今日已完成', 'success');
MY_API.CACHE.MedalDanmu_TS = ts_ms();
MY_API.saveCache();
return runMidnight(MY_API.MEDAL_DANMU.run, '粉丝勋章打卡弹幕');
}
},
MaterialObject: {//实物
list: [],
firstAid: undefined,
run: () => {
try {
if (!MY_API.CONFIG.MATERIAL_LOTTERY) return $.Deferred().resolve();
if (MY_API.CACHE.MaterialObject_TS) {
const diff = ts_ms() - MY_API.CACHE.MaterialObject_TS;
const interval = MY_API.CONFIG.MATERIAL_LOTTERY_CHECK_INTERVAL * 60e3 || 600e3;
if (diff < interval) {
MYDEBUG('[实物抽奖]', `${interval - diff}毫秒后再次运行`);
setTimeout(MY_API.MaterialObject.run, interval - diff);
return $.Deferred().resolve();
}
};
MY_API.chatLog('[实物抽奖] 开始寻找可参加的抽奖');
return MY_API.MaterialObject.check().then((aid) => {
if (aid) { // aid有效
MY_API.CACHE.last_aid = aid;
MY_API.CACHE.MaterialObject_TS = ts_ms();
MY_API.saveCache();
}
MYDEBUG('[实物抽奖]', `将在${MY_API.CONFIG.MATERIAL_LOTTERY_CHECK_INTERVAL}分钟后再次运行实物抽奖`);
setTimeout(MY_API.MaterialObject.run, MY_API.CONFIG.MATERIAL_LOTTERY_CHECK_INTERVAL * 60e3 || 600e3);
}, () => delayCall(() => MY_API.MaterialObject.run()));
} catch (err) {
MY_API.chatLog('[实物抽奖]运行时出现异常', 'error');
MYERROR(`实物抽奖出错`, err);
return $.Deferred().reject();
}
},
check: (aid, valid = 639, rem = MY_API.CONFIG.MATERIAL_LOTTERY_REM || 9) => { // TODO valid起始aid rem + 1检查次数
aid = parseInt(aid || (MY_API.CACHE.last_aid), 10);
if (isNaN(aid)) aid = valid;
MYDEBUG('API.MaterialObject.check: aid=', aid);
return BAPI.Lottery.MaterialObject.getStatus(aid).then((response) => {
MYDEBUG('API.MaterialObject.check: API.MY_API.MaterialObject.getStatus', response);
if (response.code === 0 && response.data) {
if (response.data.typeB[response.data.typeB.length - 1].status != 3 && MY_API.MaterialObject.firstAid === undefined)
MY_API.MaterialObject.firstAid = aid;
if (MY_API.CONFIG.MATERIAL_LOTTERY_IGNORE_QUESTIONABLE_LOTTERY) {
for (const str of MY_API.CONFIG.QUESTIONABLE_LOTTERY) {
if (str.charAt(0) != '/' && str.charAt(str.length - 1) != '/') {
if (response.data.title.toLowerCase().indexOf(str.toLowerCase()) > -1) {
MY_API.chatLog(`[实物抽奖] 忽略存疑抽奖
${response.data.title} (aid = ${aid})
含有关键字:` + str, 'warning');
return MY_API.MaterialObject.check(aid + 1, aid);
}
}
else {
const reg = eval(str);
if (reg.test(response.data.title)) {
MY_API.chatLog(`[实物抽奖] 忽略存疑抽奖
${response.data.title} (aid = ${aid})
匹配正则:` + str, 'warning');
return MY_API.MaterialObject.check(aid + 1, aid);
}
}
}
}
return MY_API.MaterialObject.join(aid, response.data.title, response.data.typeB).then(() => MY_API.MaterialObject.check(aid + 1, aid));
} else if (response.code === -400 || response.data == null) { // 活动不存在
if (rem) return MY_API.MaterialObject.check(aid + 1, valid, rem - 1);
return $.Deferred().resolve(MY_API.MaterialObject.firstAid || valid);
} else {
MY_API.chatLog(`[实物抽奖] ${response.msg}`, 'warning');
}
}, () => {
MY_API.chatLog(`[实物抽奖] 检查抽奖(aid = ${aid})失败,请检查网络`, 'error');
return delayCall(() => MY_API.MaterialObject.check(aid, valid));
});
},
join: (aid, title, typeB, i = 0) => {
if (i >= typeB.length) return $.Deferred().resolve();
if (MY_API.MaterialObject.list.some(v => v.aid === aid && v.number === i + 1))
return MY_API.MaterialObject.join(aid, title, typeB, i + 1);
const number = i + 1;
let obj = {
title: title,
aid: aid,
number: number,
status: typeB[i].status,
join_start_time: typeB[i].join_start_time, //开始时间戳
join_end_time: typeB[i].join_end_time, //结束时间戳
list: typeB[i].list, //礼物列表
jpName: ''
};
for (const i of obj.list) {
obj.jpName = obj.jpName.concat(' ', i.jp_name);
}
switch (obj.status) {
case -1: // 未开始
{
MY_API.chatLog(`[实物抽奖] 将在
${new Date((obj.join_start_time + 1) * 1000).toLocaleString()}参加抽奖
"${obj.title}"
aid = ${obj.aid},第${i + 1}轮
奖品:${obj.jpName}`, 'info');
MY_API.MaterialObject.list.push(obj);
const p = $.Deferred();
p.then(() => {
return MY_API.MaterialObject.draw(obj);
});
setTimeout(() => {
p.resolve();
}, (obj.join_start_time - ts_s() + 1) * 1e3);
}
break;
case 0: // 可参加
return MY_API.MaterialObject.draw(obj).then(() => {
return MY_API.MaterialObject.join(aid, title, typeB, i + 1);
});
case 1: // 已参加
{
MY_API.chatLog(`[实物抽奖] 已参加抽奖
"${obj.title}"
aid = ${obj.aid} 第${i + 1}轮
奖品:${obj.jpName}`, 'info');
MY_API.MaterialObject.list.push(obj);
const p = $.Deferred();
p.then(() => {
return MY_API.MaterialObject.notice(obj);
});
setTimeout(() => {
p.resolve();
}, (obj.join_end_time - ts_s() + 1) * 1e3);
}
break;
}
return MY_API.MaterialObject.join(aid, title, typeB, i + 1);
},
draw: (obj) => {
return BAPI.Lottery.MaterialObject.draw(obj.aid, obj.number).then((response) => {
MYDEBUG('API.MaterialObject.check: API.MY_API.MaterialObject.draw',
response);
if (response.code === 0) {
$.each(MY_API.MaterialObject.list, (i, v) => {
if (v.aid === obj.aid && v.number === obj.number) {
v.status = 1;
MY_API.MaterialObject.list[i] = v;
return false;
}
});
MY_API.chatLog(`[实物抽奖] 成功参加抽奖
${obj.title}
aid = ${obj.aid},第${obj.number}轮
奖品:${obj.jpName}`, 'success');
MY_API.addMaterial();
const p = $.Deferred();
p.then(() => {
return MY_API.MaterialObject.notice(obj);
});
setTimeout(() => {
p.resolve();
}, (obj.join_end_time - ts_s() + 1) * 1e3);
} else {
MY_API.chatLog(
`[实物抽奖] "${obj.title}"(aid = ${obj.aid},第${obj.number}轮)
${response.msg}`,
'warning');
}
}, () => {
MY_API.chatLog(
`[实物抽奖] 参加"${obj.title}"(aid = ${obj.aid},第${obj.number}轮)
失败,请检查网络`,
'error');
return delayCall(() => MY_API.MaterialObject.draw(obj));
});
},
notice: (obj) => {
return BAPI.Lottery.MaterialObject.getWinnerGroupInfo(obj.aid, obj.number).then((response) => {
MYDEBUG('API.MaterialObject.check: API.MY_API.MaterialObject.getWinnerGroupInfo', response);
if (response.code === 0) {
$.each(MY_API.MaterialObject.list, (i, v) => {//i下表,v元素
if (v.aid === obj.aid && v.number === obj.number) {
v.status = 3;
MY_API.MaterialObject.list[i] = v;
return false;
}
});
for (const i of response.data.groups) {
for (const g of i.list) {
if (g.uid === Live_info.uid) {
MY_API.chatLog(
`[实物抽奖] 抽奖"${obj.title}"
aid = ${obj.aid},第${obj.number}轮
获得奖励:"${i.giftTitle}"`,
'prize');
winPrizeNum++;
winPrizeTotalCount++;
JQlogRedPoint.text(winPrizeNum);
if (JQlogRedPoint.is(":hidden")) JQlogRedPoint.show();
if (MY_API.CONFIG.FT_NOTICE) {
function FT_notice() {
return FT_sendMsg(MY_API.CONFIG.FT_SCKEY,
`【${GM_info.script.name}】实物抽奖中奖通知 ${obj.title},第${obj.number}轮`,
`###实物抽奖中奖\n###中奖账号id:${Live_info.uname}\n###${obj.title}\n###aid = ${obj.aid}\n###第${obj.number}轮\n###获得奖励:\n###${i.giftTitle}\n###请及时填写领奖信息`
).then((re) => {
MYDEBUG('FT_sendMsg response', re);
if (re.body.errno == 0) {
window.toast('[实物抽奖] 方糖中奖提示发送成功', 'success');
} else {
window.toast(`[实物抽奖] 方糖中奖提示发送失败 ${re.errmsg}`, 'error')
}
}), () => {
MY_API.chatLog(`[实物抽奖] 方糖中奖提示发送出错,请检查网络`, 'error');
return delayCall(() => FT_notice());
};
}
FT_notice();
}
if (MY_API.CONFIG.GM_NOTICE) {
GM_notice("实物抽奖中奖", `${obj.title},奖品:${i.giftTitle}`)
}
return true;
}
}
}
MY_API.chatLog(`[实物抽奖] 抽奖"${obj.title}"(aid = ${obj.aid},第${obj.number}轮)未中奖`, 'info');
} else {
MY_API.chatLog(
`[实物抽奖] 抽奖"${obj.title}"(aid = ${obj.aid},第${obj.number}轮)
${response.msg}`,
'warning');
}
}, () => {
MY_API.chatLog(
`[实物抽奖] 获取抽奖"${obj.title}"(aid = ${obj.aid},第${obj.number}轮)
获取中奖名单失败,请检查网络`,
'error');
return delayCall(() => MY_API.MaterialObject.notice(obj));
});
}
},
AnchorLottery: {
roomidList: [],
oldLotteryResponseList: [],
lotteryResponseList: [],
myLiveRoomid: 0,
followingList: [],
unfollowList: [],
uidInTagList: [],
uidInOriginTag: [],
medal_list: [],
waitForRecheckList: [],
anchorFollowTagid: undefined,
anchorPrizeTagid: undefined,
getMedalList: async (page = 1) => {
if (page === 1) MY_API.AnchorLottery.medal_list = [];
return BAPI.i.medal(page, 25).then((response) => {
MYDEBUG('AnchorLottery.getMedalList: API.i.medal', response);
MY_API.AnchorLottery.medal_list = MY_API.AnchorLottery.medal_list.concat(response.data.fansMedalList);
if (response.data.pageinfo.curPage < response.data.pageinfo.totalpages) return MY_API.AnchorLottery.getMedalList(page + 1);
}, () => {
MY_API.chatLog('[天选时刻]
获取勋章列表失败,请检查网络', 'error');
return delayCall(() => MY_API.AnchorLottery.getMedalList());
});
},
getFollowingList: (pn = 1, ps = 50) => {
if (pn === 1) MY_API.AnchorLottery.followingList = [];
return BAPI.relation.getFollowings(Live_info.uid, pn, ps).then((response) => {
MYDEBUG(`getFollowingList API.relation.getFollowings ${pn}, ${ps}`, response);
let p = $.Deferred();
if (response.code === 0) {
p.resolve();
const total = response.data.total;
for (const up of response.data.list) {
MY_API.AnchorLottery.followingList.push(String(up.mid));
}
const remainUp = total - MY_API.AnchorLottery.followingList.length;
if (remainUp > 0)
return $.when(MY_API.AnchorLottery.getFollowingList(pn + 1, ps), p);
else {
window.toast('[保存当前关注列表为白名单] 保存关注列表成功', 'success');
localStorage.setItem(`${NAME}AnchorFollowingList`, JSON.stringify({ list: MY_API.AnchorLottery.followingList }));
getFollowBtnClickable = true;
return p;
}
} else {
window.toast(`[保存当前关注列表为白名单] 获取关注列表出错 ${response.message}`, 'error');
return p.reject();
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取关注列表出错,请检查网络`, 'error');
return delayCall(() => MY_API.AnchorLottery.getFollowingList());
})
},
getTag: async (tagName, click = false) => {
if (MY_API.AnchorLottery.anchorFollowTagid && MY_API.AnchorLottery.anchorPrizeTagid) return $.Deferred().resolve();
if (typeof tagName === 'string') tagName = [tagName];
return BAPI.relation.getTags().then((response) => {
MYDEBUG('API.relation.getTags', response);
if (response.code === 0) {
for (const tag of response.data) {
if (tag.name === anchorFollowTagName) {
if (tagName.indexOf(anchorFollowTagName) > -1)
MY_API.AnchorLottery.anchorFollowTagid = tag.tagid;
} else if (tag.name === anchorPrizeTagName) {
if (tagName.indexOf(anchorPrizeTagName) > -1)
MY_API.AnchorLottery.anchorPrizeTagid = tag.tagid;
}
}
if (!click) {
//没创建过分组则创建一个新的
let p1 = $.Deferred(), p2 = $.Deferred();
if (MY_API.AnchorLottery.anchorFollowTagid === undefined && MY_API.CONFIG.ANCHOR_MOVETO_FOLLOW_TAG)
MY_API.AnchorLottery.creatTag(anchorFollowTagName).then(() => p1.resolve());
else p1.resolve();
if (MY_API.AnchorLottery.anchorPrizeTagid === undefined && MY_API.CONFIG.ANCHOR_MOVETO_PRIZE_TAG)
p1.then(() => MY_API.AnchorLottery.creatTag(anchorPrizeTagName).then(() => p2.resolve()));
else p2.resolve();
return $.when(p1, p2);
} else {
if (tagName.indexOf(anchorFollowTagName) > -1 && MY_API.AnchorLottery.anchorFollowTagid === undefined)
MY_API.chatLog(`[天选时刻] 分组【${anchorFollowTagName}】不存在,请先勾选【把参与天选时关注的UP移到新分组】和【参加天选时刻抽奖】,再次运行脚本。`, 'warning');
if (tagName.indexOf(anchorPrizeTagName) > -1 && MY_API.AnchorLottery.anchorPrizeTagid === undefined)
MY_API.chatLog(`[天选时刻] 分组【${anchorPrizeTagName}】不存在,请先勾选【把发起抽奖的UP移到新分组】和【参加天选时刻抽奖】,再次运行脚本。`, 'warning');
return $.Deferred().resolve();
}
} else {
MY_API.chatLog(`[天选时刻] 获取关注分组出错 ${response.message}`, 'error');
return p.reject();
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取关注分组出错,请检查网络`, 'error');
return delayCall(() => MY_API.AnchorLottery.getTag(tagName));
});
},
creatTag: (tagName) => {
return BAPI.relation.createTag(tagName).then((re) => {
MYDEBUG(`API.relation.createTag ${tagName}`, re);
let p = $.Deferred();
if (re.code === 0) {
if (tagName === anchorFollowTagName)
MY_API.AnchorLottery.anchorFollowTagid = re.data.tagid;
else if (tagName === anchorPrizeTagName)
MY_API.AnchorLottery.anchorPrizeTagid = re.data.tagid;
return p.resolve();
} else {
MY_API.chatLog(`[天选时刻] 创建分组【${tagName}】出错 ${re.message}`, 'error');
return p.reject();
}
}, () => {
MY_API.chatLog(`[天选时刻] 创建关注分组出错,请检查网络`, 'error');
return delayCall(() => MY_API.AnchorLottery.creatTag(tagName));
})
},
getUpInOriginTag(myuid, tagid = 0, pn = 1, ps = 50) {
return BAPI.relation.getUpInTag(myuid, tagid, pn, ps).then((response) => {
let p = $.Deferred();
MYDEBUG(`API.relation.getUpInOriginTag ${tagid} ${pn} ${ps}`, response);
if (response.code === 0) {
p.resolve();
if (response.data.length === 0) return p;
for (const up of response.data) {
MY_API.AnchorLottery.uidInOriginTag.push(String(up.mid));
}
return $.when(MY_API.AnchorLottery.getUpInOriginTag(myuid, tagid, pn + 1, ps), p);
} else {
window.toast(`获取默认分组关注列表出错 ${response.message}`, 'error');
return p.reject();
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取Tag内UP列表出错,请检查网络`, 'error');
return delayCall(() => MY_API.AnchorLottery.getUpInOriginTag(myuid, tagid = 0, pn = 1, ps = 50));
})
},
delAnchorFollowing: async (mode = 1, pn = 1, ps = 50) => {
function getUpInTag(myuid, tagid, pn = 1, ps = 50) {
if (pn === 1) MY_API.AnchorLottery.unfollowList = [];
return BAPI.relation.getUpInTag(myuid, tagid, pn, ps).then((response) => {
let p = $.Deferred();
MYDEBUG(`API.relation.getUpInTag ${tagid} ${pn} ${ps}`, response);
if (response.code === 0) {
p.resolve();
if (response.data.length === 0) return p;
for (const up of response.data) {
MY_API.AnchorLottery.uidInTagList.push(String(up.mid));
}
return $.when(getUpInTag(myuid, tagid, pn + 1, ps), p);
} else {
window.toast(`[取关BLTH天选分组内的UP] 获取关注列表出错 ${response.message}`, 'error');
return p.reject();
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取Tag内UP列表出错,请检查网络`, 'error');
return delayCall(() => getUpInTag(myuid, tagid, pn = 1, ps = 50));
})
}
function getFollowingList(PN, PS) {
return BAPI.relation.getFollowings(Live_info.uid, PN, PS).then((response) => {
MYDEBUG(`delAnchorFollowing API.relation.getFollowings(${PN}, ${PS})`, response)
let p = $.Deferred();
if (response.code === 0) {
p.resolve();
const total = response.data.total;
for (const up of response.data.list) {
MY_API.AnchorLottery.unfollowList.push(String(up.mid));
}
const remainUp = total - MY_API.AnchorLottery.unfollowList.length;
if (remainUp > 0)
return $.when(getFollowingList(PN + 1, PS), p);
else
return p;
} else {
window.toast(`[取关不在白名单内的UP主] 获取关注列表出错 ${response.message}`, 'error');
return p.reject();
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取关注列表出错,请检查网络`, 'error');
return delayCall(() => getFollowingList(PN, PS));
});
}
function delFollowingList(mode, targetList) {
let config, id_list;
if (mode === 1) {
config = JSON.parse(localStorage.getItem(`${NAME}AnchorFollowingList`)) || { list: [] };
if (config.list.length === 0) {//关注列表为空
window.toast(`[取关不在白名单内的UP主] 请先点击【保存当前关注列表为白名单】!`, 'info');
return $.Deferred().resolve();
}
id_list = [...config.list];
}
let doUnfollowList = [], pList = [];
for (const uid of targetList) {
if (mode === 1) {
if (id_list.indexOf(String(uid)) === -1) {
doUnfollowList.push(uid);
}
} else if (mode === 2 || mode === 3) {
doUnfollowList.push(uid);
}
}
for (let c = 0; c <= doUnfollowList.length; c++) {
pList[c] = $.Deferred();
if (!MY_API.CONFIG.ANCHOR_WAIT_REPLY) pList[c].resolve();
}
pList[0].resolve();
for (let i = 0; i < doUnfollowList.length; i++) {
pList[i].then(() => {
let p = $.Deferred();
setTimeout(() => p.resolve(), MY_API.CONFIG.ANCHOR_INTERVAL);
p.then(() => {
BAPI.relation.modify(doUnfollowList[i], 2).then((response) => {
MYDEBUG(`API.relation.modify ${doUnfollowList[i]}, ${2}`, response);
if (response.code === 0) {
window.toast(`[天选时刻取关UP主] 取关UP(uid = ${doUnfollowList[i]})成功`, 'success');
pList[i + 1].resolve();
}
else {
window.toast(`[天选时刻取关UP主] 取关UP(uid = ${doUnfollowList[i]})出错 ${response.message}`, 'error');
pList[i + 1].reject();
}
}, () => {
MY_API.chatLog(`[天选时刻] 取消关注出错,请检查网络`, 'error');
return delayCall(() => delFollowingList());
})
})
});
}
return $.when(...pList)
}
if (mode === 1) //白名单
return getFollowingList(pn, ps).then(() => delFollowingList(1, MY_API.AnchorLottery.unfollowList).then(() => { unFollowBtnClickable = true }));
else if (mode === 2) //关注分组
return getUpInTag(Live_info.uid, MY_API.AnchorLottery.anchorFollowTagid).then(() => delFollowingList(2, MY_API.AnchorLottery.uidInTagList).then(() => { unFollowBtnClickable = true }));
else if (mode === 3) //中奖分组
return getUpInTag(Live_info.uid, MY_API.AnchorLottery.anchorPrizeTagid).then(() => delFollowingList(2, MY_API.AnchorLottery.uidInTagList).then(() => { unFollowBtnClickable = true }));
},
getRoomList: async () => {
let roomList = await BAPI.room.getList().then((response) => {//获取各分区的房间号
MYDEBUG('直播间列表', response);
return response.data;
}, () => {
MY_API.chatLog(`[天选时刻] 获取各分区的房间号出错,请检查网络`, 'error');
return delayCall(() => MY_API.AnchorLottery.getRoomList());
});
const config = JSON.parse(localStorage.getItem(`${NAME}AnchorRoomidList`)) || { list: [] };
MY_API.AnchorLottery.roomidList = [...config.list];
const checkHourRank = async () => { //小时榜
for (const r of roomList) {
await BAPI.rankdb.getTopRealTimeHour(r.id).then((data) => {
MYDEBUG(`API.rankdb.getTopRealTimeHour(${r.id})`, data);
if (data.code === 0) {
const list = data.data.list;
MY_API.chatLog(`[天选时刻] 获取${r.name + '小时榜'}的直播间`, 'info');
MYDEBUG(`[天选时刻] 获取${r.name + '小时榜'}房间列表`, data);
for (const i of list) {
if (MY_API.AnchorLottery.roomidList.indexOf(i.roomid) === -1) {
MY_API.AnchorLottery.roomidList.unshift(i.roomid)
}
}
} else {
MY_API.chatLog(`[天选时刻] 获取${r.name + '小时榜'}的直播间出错
${data.message}`, 'warning');
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取小时榜直播间出错,请检查网络`, 'error');
return delayCall(() => checkHourRank());
});
await sleep(MY_API.CONFIG.ANCHOR_INTERVAL)
}
};
const checkRoomList = async () => { // 分区列表
for (const r of roomList) {
await BAPI.room.getRoomList(r.id, 0, 0, 1, 50).then((re) => {
MYDEBUG(`API.room.getRoomList(${r.id}, 0, 0, 1, 50)`, re);
if (re.code === 0) {
const list = re.data.list;
MY_API.chatLog(`[天选时刻] 获取${r.name + '分区'}的直播间`, 'info');
MYDEBUG(`[天选时刻] 获取${r.name + '分区'}房间列表`, re);
for (const i of list) {
if (MY_API.AnchorLottery.roomidList.indexOf(i.roomid) === -1) {
MY_API.AnchorLottery.roomidList.unshift(i.roomid)
}
}
} else {
MY_API.chatLog(`[天选时刻] 获取${r.name + '分区'}的直播间出错
${re.message}`, 'warning');
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取分区直播间出错,请检查网络`, 'error');
return delayCall(() => checkRoomList());
});
await sleep(MY_API.CONFIG.ANCHOR_INTERVAL)
}
};
return checkHourRank().then(async () => {
await checkRoomList();
if (MY_API.AnchorLottery.roomidList.length > MY_API.CONFIG.ANCHOR_MAXROOM)
MY_API.AnchorLottery.roomidList = MY_API.AnchorLottery.roomidList.splice(0, MY_API.CONFIG.ANCHOR_MAXROOM);
localStorage.setItem(`${NAME}AnchorRoomidList`, JSON.stringify({ list: MY_API.AnchorLottery.roomidList }));
return $.Deferred().resolve();
});
},
uploadRoomList: async () => {
let description = undefined, p = $.Deferred();
if (MY_API.AnchorLottery.lotteryResponseList.length === 0) {
await BAPI.room.getRoomBaseInfo(MY_API.CONFIG.ANCHOR_GETDATA_ROOM).then((response) => {
MYDEBUG(`API.room.getRoomBaseInfo(${MY_API.CONFIG.ANCHOR_GETDATA_ROOM})`, response);
if (response.code === 0) {
description = response.data.by_room_ids[MY_API.CONFIG.ANCHOR_GETDATA_ROOM].description;
} else {
MY_API.chatLog(`[天选时刻] 获取直播间个人简介错误 ${response.message}`, 'error');
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取直播间个人简介出错,请检查网络`, 'error');
});
let lotteryInfoJson;
try {
if (description === undefined) throw "undefined"
lotteryInfoJson = JSON.parse(Base64.decode64(description.replaceAll('-', '')));
if (typeof lotteryInfoJson !== 'object' || !lotteryInfoJson)
throw 'Not a JSON';
if (!lotteryInfoJson.hasOwnProperty('roomList'))
throw 'Missing property roomList';
if (!lotteryInfoJson.hasOwnProperty('ts'))
throw 'Missing property ts';
} catch (e) {
MYDEBUG('MY_API.AnchorLottery.uploadRoomList', `获取到的直播间简介格式有误 ${e},上传初始值设为undefined`);
lotteryInfoJson = undefined;
}
if (lotteryInfoJson !== undefined) {
for (const i of lotteryInfoJson.roomList) {
MY_API.AnchorLottery.lotteryResponseList.push(i);//旧数据用push
}
MY_API.AnchorLottery.oldLotteryResponseList = [...MY_API.AnchorLottery.lotteryResponseList];
}
}
if (MY_API.AnchorLottery.oldLotteryResponseList.length === MY_API.AnchorLottery.lotteryResponseList.length)
return setTimeout(() => MY_API.AnchorLottery.uploadRoomList(), MY_API.CONFIG.ANCHOR_UPLOAD_DATA_INTERVAL * 1000);
if (MY_API.AnchorLottery.myLiveRoomid === 0) {
await BAPI.room.getRoomInfoOld(Live_info.uid).then((response) => {
MYDEBUG(`API.room.getRoomInfoOld(${Live_info.uid})`, response);
if (response.code === 0) {
MY_API.AnchorLottery.myLiveRoomid = response.data.roomid;//没有则返回0
} else {
MY_API.chatLog('[天选时刻] 获取直播间信息出错 ' + response.data.message, 'error');
return p.reject()
}
}, () => {
MY_API.chatLog('[天选时刻] 获取直播间信息出错,请检查网络', 'error');
return delayCall(() => MY_API.AnchorLottery.uploadRoomList());
});
}
if (MY_API.AnchorLottery.myLiveRoomid === 0) {
MY_API.chatLog('[天选时刻] 请先开通直播间再使用上传数据的功能', 'warning');
return p.reject()
}
if (MY_API.AnchorLottery.lotteryResponseList.length > MY_API.CONFIG.ANCHOR_MAXLIVEROOM_SAVE)//删除超出的旧数据
MY_API.AnchorLottery.lotteryResponseList = MY_API.AnchorLottery.lotteryResponseList.splice(0, MY_API.CONFIG.ANCHOR_MAXLIVEROOM_SAVE);
let uploadRawJson = {
roomList: MY_API.AnchorLottery.lotteryResponseList,
ts: ts_ms()
};
if (MY_API.CONFIG.ANCHOR_UPLOAD_MSG.length > 0) {
uploadRawJson.msg = MY_API.CONFIG.ANCHOR_UPLOAD_MSG_CONTENT;
}
function updateEncodeData(roomId, str) {
return BAPI.room.update(roomId, str).then((re) => {
MYDEBUG(`BAPI.room.update MY_API.AnchorLottery.myLiveRoomid encode64(uploadRawStr)`, re);
if (re.code == 0) {
MY_API.chatLog(`[天选时刻] 房间列表上传成功(共${MY_API.AnchorLottery.lotteryResponseList.length}个房间)`, 'success');
MY_API.AnchorLottery.oldLotteryResponseList = [...MY_API.AnchorLottery.lotteryResponseList];
return p.resolve()
} else if (re.code === 1) {
if (re.message === '出错啦,再试试吧') {
MY_API.chatLog(`[天选时刻] 上传失败,${MY_API.CONFIG.ANCHOR_UPLOAD_DATA_INTERVAL}秒后再次尝试`, 'warning');
return p.resolve()
} else if (re.message === '简介内容过长') {
MY_API.chatLog('[天选时刻] 上传失败,内容过长,清空数据', 'warning');
MY_API.AnchorLottery.lotteryResponseList = [];
MY_API.AnchorLottery.oldLotteryResponseList = [];
return p.resolve()
} else if (re.message === '您所填写的简介可能涉及不符合相关法律法规和政策的内容,请修改') {
MY_API.chatLog(`[天选时刻] 上传失败,${re.message}`, 'warning');
MY_API.AnchorLottery.oldLotteryResponseList = [...MY_API.AnchorLottery.lotteryResponseList];
return p.resolve()
}
else {
MY_API.chatLog('[天选时刻] 上传失败 ' + re.message, 'warning');
return p.reject()
}
}
else {
MY_API.chatLog('[天选时刻] 房间列表上传失败 ' + re.message, 'error');
return p.reject()
}
}, () => {
MY_API.chatLog('[天选时刻] 房间列表上传出错,请检查网络', 'error');
return delayCall(() => MY_API.AnchorLottery.uploadRoomList());
})
}
const encodeData = Base64.encode64(JSON.stringify(uploadRawJson));
let finalStr = '';
for (let i = 0; i < encodeData.length; i++) {
finalStr += (encodeData[i] + (i === encodeData.length - 1 ? '' : '-'));
}
return updateEncodeData(MY_API.AnchorLottery.myLiveRoomid, finalStr).then(() => {
return setTimeout(() => MY_API.AnchorLottery.uploadRoomList(), MY_API.CONFIG.ANCHOR_UPLOAD_DATA_INTERVAL * 1000)
});
},
getLotteryInfoFromRoom: async () => {
let description = undefined;
await BAPI.room.getRoomBaseInfo(MY_API.CONFIG.ANCHOR_GETDATA_ROOM).then((response) => {
MYDEBUG(`API.room.getRoomBaseInfo(${MY_API.CONFIG.ANCHOR_GETDATA_ROOM})`, response);
if (response.code === 0) {
description = response.data.by_room_ids[MY_API.CONFIG.ANCHOR_GETDATA_ROOM].description;
} else {
MY_API.chatLog(`[天选时刻] 获取直播间个人简介错误 ${response.message}`, 'error');
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取直播间个人简介出错,请检查网络`, 'error');
});
let lotteryInfoJson;
try {
if (description === undefined) throw "undefined";
lotteryInfoJson = JSON.parse(Base64.decode64(description.replaceAll('-', '')));
if (typeof lotteryInfoJson !== 'object' || !lotteryInfoJson)
throw 'Not a JSON';
if (!lotteryInfoJson.hasOwnProperty('roomList'))
throw 'Missing property roomList';
if (!lotteryInfoJson.hasOwnProperty('ts'))
throw 'Missing property ts';
} catch (e) {
MY_API.chatLog(`[天选时刻] 直播间${MY_API.CONFIG.ANCHOR_GETDATA_ROOM}个人简介的数据格式不符合要求
` + e, 'error');
return setTimeout(() => MY_API.AnchorLottery.getLotteryInfoFromRoom(), MY_API.CONFIG.ANCHOR_CHECK_INTERVAL * 60000);
}
MY_API.chatLog(`[天选时刻] 开始检查天选(共${lotteryInfoJson.roomList.length}个房间)
数据来源:直播间${linkMsg(MY_API.CONFIG.ANCHOR_GETDATA_ROOM, liveRoomUrl + MY_API.CONFIG.ANCHOR_GETDATA_ROOM)}的个人简介${(!MY_API.CONFIG.ANCHOR_IGNORE_UPLOAD_MSG && lotteryInfoJson.hasOwnProperty('msg') && lotteryInfoJson.msg.length > 0) ? '
附加信息:' + lotteryInfoJson.msg : ''}
该数据最后上传时间:${new Date(lotteryInfoJson.ts).toLocaleString()}`, 'success')
for (const room of lotteryInfoJson.roomList) {
let p = $.Deferred();
if (!MY_API.CONFIG.ANCHOR_WAIT_REPLY) p.resolve();
MY_API.AnchorLottery.check(room).then((re) => {
if (re) {
//数据格式正确,可以参加
if (MY_API.CONFIG.ANCHOR_IGNORE_PWDROOM) {
return MY_API.AnchorLottery.pwdCheck(room).then((res) => {
if (res) {
//加密
MY_API.chatLog(`[天选时刻] 忽略加密直播间的天选
roomid = ${linkMsg(res[3], liveRoomUrl + res[3])}, id = ${res[0]}
${res[8] === 0 ? '' : ('所需金瓜子:' + res[8] + '
')}奖品:${res[4]}
${MY_API.AnchorLottery.countDown(res[5])}`, 'warning');
p.resolve();
} else {
//不加密
MY_API.AnchorLottery.join(re).then(() => p.resolve());
}
}, () => {
MY_API.chatLog('[天选时刻] 直播间加密检查出错,请检查网络', 'error')
})
} else {
MY_API.AnchorLottery.join(re).then(() => p.resolve());
}
} else p.resolve();
});
await p;
await sleep(MY_API.CONFIG.ANCHOR_INTERVAL);
}
MY_API.CACHE.AnchorLottery_TS = ts_ms();
MY_API.saveCache();
const sleepTime = MY_API.AnchorLottery.sleepCheck();
if (sleepTime) {
MYDEBUG('[天选时刻]', `处于休眠时段,${sleepTime}毫秒后再次检查天选`);
MY_API.chatLog(`[天选时刻] 处于休眠时段,将会在
${new Date(ts_ms() + sleepTime).toLocaleString()}
结束休眠并继续检查天选`, 'warning');
return setTimeout(() => MY_API.AnchorLottery.getLotteryInfoFromRoom(), sleepTime);
} else {
MY_API.chatLog(`[天选时刻] 本次检查结束
${MY_API.CONFIG.ANCHOR_CHECK_INTERVAL}分钟后再次检查天选`, 'success');
return setTimeout(() => MY_API.AnchorLottery.getLotteryInfoFromRoom(), MY_API.CONFIG.ANCHOR_CHECK_INTERVAL * 60000);
}
},
moneyCheck: (award_name) => {
const name = award_name.replaceAll(' ', '').toLowerCase();//去空格+转小写
let numberArray = name.match(/\d+(\.\d+)?/g);//提取阿拉伯数字
let chineseNumberArray = name.match(/([一二两三四五六七八九十]千零?[一二两三四五六七八九十]?百?[一二三四五六七八九十]?十?[一二三四五六七八九十]?)|([一二两三四五六七八九十]百[一二三四五六七八九十]?十?[一二三四五六七八九十]?)|([一二三四五六七八九十]?十[一二三四五六七八九十]?)|[一二三四五六七八九十]/g);//提取汉字数字
const chnNumChar = { "零": 0, "一": 1, "二": 2, "三": 3, "四": 4, "五": 5, "六": 6, "七": 7, "八": 8, "九": 9 },
chnNameValue = { "十": { value: 10, secUnit: false }, "百": { value: 100, secUnit: false }, "千": { value: 1e3, secUnit: false }, "万": { value: 1e4, secUnit: true }, "亿": { value: 1e8, secUnit: true } };
if (chineseNumberArray !== null && numberArray === null) { //只提取出汉字数字
return chineseFunc();
} else if (chineseNumberArray === null && numberArray !== null) { //只提取出阿拉伯数字
return arabicNumberFunc();
} else if (chineseNumberArray !== null && numberArray !== null) { //都提取出来了
let arr = arabicNumberFunc();
if (arr[0]) return arr; //数组第一项为true则识别成功
else return chineseFunc()
} else { //都没提取出来
return [false]
}
function chineseFunc() {
//把匹配到的数字由长到段重新排列
let chineseNumIndexList = [];
chineseNumberArray.sort(function (a, b) {
return b.length - a.length;
});
for (const n of chineseNumberArray) {
chineseNumIndexList.push(getIndex(name, n, chineseNumIndexList));
}
for (let n = 0; n < chineseNumberArray.length; n++) {
const chineseNum = chineseNumberArray[n];//中文数字
if (chineseNum !== undefined) {
const num = ChineseToNumber(chineseNum);//阿拉伯数字
const ChineseNumberIndex = chineseNumIndexList[n],//中文数字下表
ChineseNumLength = chineseNum.length,//中文数字长度
nextChineseNumIndex = chineseNumIndexList[n + 1];//下一个数字下标
const unitIndex = ChineseNumberIndex + ChineseNumLength;//数字后一个中文数字的下标 可能为undefined
let strAfterNum = '';//数字后面的字符串
if (unitIndex < nextChineseNumIndex) {
//如果下一个数字的起始位置不在当前数字所占范围内
for (let i = unitIndex; i < name.length; i++) {
if (nextChineseNumIndex !== undefined) {
if (i < nextChineseNumIndex)//不能把下一个数字取进去
strAfterNum = strAfterNum + name[i];
else
break;
} else {
strAfterNum = strAfterNum + name[i];
}
}
} else {
strAfterNum = name.slice(unitIndex, name.length);
}
let finalMoney = getPrice(num, strAfterNum);
if (finalMoney === undefined) {
if (n === chineseNumberArray.length - 1) return [false];
else continue;
}
else return [true, finalMoney];
}
}
}
function arabicNumberFunc() {
//把匹配到的数字由长到段重新排列
let numIndexList = [];
numberArray.sort(function (a, b) {
return b.length - a.length;
});
for (const n of numberArray) { //每个数字在name中的下标
numIndexList.push(getIndex(name, n, numIndexList));
}
for (let n = 0; n < numberArray.length; n++) {
const num = numberArray[n];//数字
const numberIndex = name.indexOf(num),//数字下表
numLength = num.length,//数字长度
nextNumIndex = numIndexList[n + 1];//下一个数字下标
const unitIndex = numberIndex + numLength;//数字后一个字符的下标 可能为undefined
let strAfterNum = '';//数字后面的字符串
if (unitIndex < nextNumIndex) {
//如果下一个数字的起始位置不在当前数字所占范围内
for (let i = unitIndex; i < name.length; i++) {
if (nextNumIndex !== undefined) {
if (i < nextNumIndex)//不能把下一个数字取进去
strAfterNum = strAfterNum + name[i];
else
break;
} else {
strAfterNum = strAfterNum + name[i];
}
}
} else {
strAfterNum = name.slice(unitIndex, name.length);
}
let finalMoney = getPrice(num, strAfterNum);
if (finalMoney === undefined) {//识别失败
if (n === numberArray.length - 1) return [false];
else continue;
} else return [true, finalMoney]
}
}
function getPrice(num, strAfterNum) {
const yuan = ['元', 'r', '块'],//1
yuanWords = ['rmb', 'cny', '人民币', '软妹币', '微信红包', '红包', 'qq红包', '现金'],//1
dime = ['毛', '角'],//0.1
penny = ['分'],//0.01
milliWords = ['金瓜子'];//0.001
const firstChar = strAfterNum[0];
let finalMoney = undefined; //单位:元
const number = Number(num);
for (const w of yuanWords) {
if (strAfterNum.indexOf(w) > -1) {
finalMoney = number;
break;
}
}
for (const w of milliWords) {
if (strAfterNum.indexOf(w) > -1) {
finalMoney = number * 0.001;
break;
}
}
if (finalMoney === undefined) {
if (yuan.indexOf(firstChar) > -1) {
finalMoney = number
} else if (dime.indexOf(firstChar) > -1) {
finalMoney = number * 0.1;
} else if (penny.indexOf(firstChar) > -1) {
//排除特殊奖品名
const ignoreList = ['分钟'];
for (const i of ignoreList) {
if (strAfterNum.indexOf(i) === 0) return undefined
}
finalMoney = number * 0.01;
}
}
return finalMoney;
}
function ChineseToNumber(chnStr) {
let chineseStr = chnStr[0] === '十' ? "一" + chnStr : chnStr;
let rtn = 0,
section = 0,
number = 0,
secUnit = false,
str = chineseStr.split('');
for (let i = 0; i < str.length; i++) {
let num = chnNumChar[str[i]];
if (typeof num !== 'undefined') {
number = num;
if (i === str.length - 1) {
section += number;
}
} else {
if (!chnNameValue.hasOwnProperty(str[i])) return undefined;
let unit = chnNameValue[str[i]].value;
secUnit = chnNameValue[str[i]].secUnit;
if (secUnit) {
section = (section + number) * unit;
rtn += section;
section = 0;
} else {
section += (number * unit);
}
number = 0;
}
}
return rtn + section;
};
/**
* 获取下标,可处理部分特殊情况,如
* 100金瓜子1个
* 1份100金瓜子1个
* @param str 字符串
* @param num 被搜索的数字
* @param array 储存已搜索到的数字的下标的数组
* @param start 搜索数字的开始下标,初始为0,为了防止重复搜索字符串中的一个子串
* @param arrStart 搜索数组的开始下标,初始为0,为了防止重复搜索数组中的某一项
* @returns {number} index
*/
function getIndex(str, num, array, start = 0, arrStart = 0) {
let index = str.indexOf(num, start),
arrayIndex = array.indexOf(index, arrStart);
if (arrayIndex > -1) return getIndex(str, num, array, index + 1, arrayIndex + 1);
else return index
}
},
check: (roomid, add = true) => {
if (MY_API.CONFIG.ANCHOR_IGNORE_ROOM && MY_API.CONFIG.ANCHOR_IGNORE_ROOMLIST.indexOf(String(roomid)) > -1) {
MY_API.chatLog(`[天选时刻] 忽略直播间
不参加直播间${linkMsg(roomid, liveRoomUrl + roomid)}的天选`, 'warning');
return $.Deferred().resolve();
}
return BAPI.xlive.anchor.check(roomid).then((response) => {
MYDEBUG(`API.xlive.anchor.check(${roomid}) response`, response);
if (response.code === 0 && response.data) {
if (response.data.time === 0) {
MY_API.chatLog(`[天选时刻] 忽略过期天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}`, 'info');
return false
}
if (response.data.status === 2) {
MY_API.chatLog(`[天选时刻] 忽略已参加天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
`, 'info');
return false
}
if (add) {
if (MY_API.AnchorLottery.lotteryResponseList.indexOf(response.data.room_id) === -1)
MY_API.AnchorLottery.lotteryResponseList.unshift(response.data.room_id);//有抽奖则加入上传列表,新数据unshift
}
const joinPrice = response.data.gift_num * response.data.gift_price,
joinTextTitle = `${NAME}_ANCHOR_${response.data.id}`,
ts = ts_ms();
let defaultJoinData = {
id: response.data.id,
gift_id: joinPrice === 0 ? undefined : response.data.gift_id,
gift_num: joinPrice === 0 ? undefined : response.data.gift_num,
roomid: roomid,
award_name: response.data.award_name,
time: response.data.time,
require_type: response.data.require_type,
joinPrice: joinPrice,
uid: undefined
};
let medalJson = undefined;
let joinText = null, joinDisplay = "block";
switch (response.data.require_type) {
case 0: /* 无 */
case 1: /* 关注 */ joinText = "点击参加"; break;
case 2: /* 粉丝勋章 */
if (response.data.require_value === 1) joinText = "点击购买粉丝勋章参加";
else joinText = "点击购买粉丝勋章"; break;
/* case 3: 大航海 */
default: joinDisplay = "none";
}
const joinHtml = (text = joinText, display = joinDisplay) => `
${text}
`;
function joinAnchorListener() {
let jqText = $('div' + '[title=\"' + joinTextTitle + '\"]' + '[ts=\"' + ts + '\"]');
let timer = setTimeout(() => jqText.remove(), response.data.time * 1000);
jqText.click(() => {
let p = $.Deferred();
switch (response.data.require_type) {
case 2: //粉丝勋章
let getUid = $.Deferred();
if (!defaultJoinData.uid) {
BAPI.live_user.get_anchor_in_room(roomid).then((res) => {
MYDEBUG(`API.live_user.get_anchor_in_room(${roomid})`, res);
if (res.data) {
defaultJoinData.uid = res.data.info.uid;
medalJson = {
anchorInfo: {
uid: res.data.info.uid,
uname: res.data.info.uname,
face: res.data.info.face
},
medal_level: 1,
target_id: res.data.info.uid
};
getUid.resolve();
} else {
MY_API.chatLog(`[天选时刻] 获取uid出错
roomid = ${roomid}
${res.msg}`, 'error');
getUid.reject();
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取uid出错,请检查网络`, 'error');
getUid.reject();
})
} else getUid.resolve();
getUid.then(() => {
BAPI.link_group.buy_medal(defaultJoinData.uid).then((re) => {
MYDEBUG('API.link_group.buy_medal re', re);
if (re.code === 0) {
if (response.data.require_value === 1) {
layer.msg('粉丝勋章购买成功,约2秒后参加天选', {
time: 2000,
icon: 1
});
setTimeout(() => p.resolve(), 2000);
} else {
layer.msg('粉丝勋章购买成功', {
time: 2000,
icon: 1
});
p.reject();
}
if (medalJson !== undefined)
MY_API.AnchorLottery.medal_list.push(medalJson);
} else {
layer.msg(`粉丝勋章购买失败 ${re.message}`, {
time: 3500,
icon: 2
});
p.reject()
}
}, () => {
MY_API.chatLog('[天选时刻] 购买粉丝勋章出错,请检查网络', 'error');
p.reject()
});
});
break;
default: p.resolve()
}
p.then(() => {
//已经过了一段时间,需再次获取剩余时间
BAPI.xlive.anchor.randTime(response.data.id).then((re) => {
MYDEBUG(`API.xlive.anchor.randTime ${response.data.id}`, re);
if (response.code === 0) {
if (response.data.time > 0) {
defaultJoinData.time = re.data.time;
MY_API.AnchorLottery.join(defaultJoinData);
let allSameJqText = $('div' + '[title=\"' + joinTextTitle + '\"]');
allSameJqText.unbind('click');
allSameJqText.remove();
clearTimeout(timer);
} else {
return MY_API.chatLog(`[天选时刻] 该天选已过期
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}`, 'info')
}
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取天选开奖剩余时间失败,请检查网络`, 'error')
})
})
});
};
if (MY_API.CONFIG.ANCHOR_IGNORE_BLACKLIST) {
// 忽略关键字
for (const str of MY_API.CONFIG.ANCHOR_BLACKLIST_WORD) {
if (str.charAt(0) !== '/' && str.charAt(str.length - 1) !== '/') {
if (response.data.award_name.toLowerCase().indexOf(str.toLowerCase()) > -1) {
MY_API.chatLog(`[天选时刻] 忽略存疑天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
含有关键字:${str}
${response.data.require_text === '无' ? '' : '参加条件:' + response.data.require_text + '
'}${joinPrice === 0 ? '无需金瓜子' : "所需金瓜子:" + joinPrice}
${MY_API.AnchorLottery.countDown(response.data.time)}${joinHtml()}`, 'warning');
joinAnchorListener();
return false
}
}
else {
try {
const reg = eval(str);
if (reg.test(response.data.award_name)) {
MY_API.chatLog(`[天选时刻] 忽略存疑天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
匹配正则:${str}
${response.data.require_text === '无' ? '' : '参加条件:' + response.data.require_text + '
'}${joinPrice === 0 ? '无需金瓜子' : "所需金瓜子:" + joinPrice}
${MY_API.AnchorLottery.countDown(response.data.time)}${joinHtml()}`, 'warning');
joinAnchorListener();
return false
}
} catch (e) {
MYDEBUG('[天选时刻] 正则eval出错:', str);
}
}
}
};
if (MY_API.CONFIG.ANCHOR_IGNORE_MONEY > 0 || MY_API.CONFIG.ANCHOR_MONEY_ONLY) {
//忽略金额或仅参加现金天选
const moneyCheckReturnArray = MY_API.AnchorLottery.moneyCheck(response.data.award_name);
if (moneyCheckReturnArray[0]) {
//有金额
if (moneyCheckReturnArray[1] < MY_API.CONFIG.ANCHOR_IGNORE_MONEY) {
MY_API.chatLog(`[天选时刻] 忽略金额小于${MY_API.CONFIG.ANCHOR_IGNORE_MONEY}元的天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
${response.data.require_text === '无' ? '' : '参加条件:' + response.data.require_text + '
'}识别到的金额:${moneyCheckReturnArray[1]}元
${joinPrice === 0 ? '无需金瓜子' : "所需金瓜子:" + joinPrice}
${MY_API.AnchorLottery.countDown(response.data.time)}${joinHtml()}`, 'warning');
joinAnchorListener();
return false
}
} else if (MY_API.CONFIG.ANCHOR_MONEY_ONLY) {
MY_API.chatLog(`[天选时刻] 忽略非现金抽奖的天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
${response.data.require_text === '无' ? '' : '参加条件:' + response.data.require_text + '
'}${joinPrice === 0 ? '无需金瓜子' : "所需金瓜子:" + joinPrice}
${MY_API.AnchorLottery.countDown(response.data.time)}${joinHtml()}`, 'warning');
return false
}
}
if (joinPrice > MY_API.CONFIG.AHCHOR_NEED_GOLD) {
MY_API.chatLog(`[天选时刻] 忽略付费天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
${response.data.require_text === '无' ? '' : '参加条件:' + response.data.require_text + '
'}${joinPrice === 0 ? '无需金瓜子' : "所需金瓜子:" + joinPrice}
${MY_API.AnchorLottery.countDown(response.data.time)}${joinHtml()}`, 'warning');
joinAnchorListener();
return false
}
switch (response.data.require_type) {
case 0: //无要求
case 1: return defaultJoinData //关注
case 2: { // 粉丝勋章
return BAPI.live_user.get_anchor_in_room(roomid).then((res) => {
MYDEBUG(`API.live_user.get_anchor_in_room(${roomid})`, res);
if (res.data) {
defaultJoinData.uid = res.data.info.uid;
medalJson = {
anchorInfo: {
uid: res.data.info.uid,
uname: res.data.info.uname,
face: res.data.info.face
},
medal_level: 1,
target_id: res.data.info.uid
};
for (const m of MY_API.AnchorLottery.medal_list) {
if (m.target_id === defaultJoinData.uid) {
//m.target_id为勋章对应UP的uid,m.uid是自己的uid
if (m.medal_level < response.data.require_value) {
MY_API.chatLog(`[天选时刻] 忽略粉丝勋章等级不足的天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
所需勋章等级:${response.data.require_value}
你的勋章等级:${m.level}
${MY_API.AnchorLottery.countDown(response.data.time)}`, 'warning');
return false
} else {
return defaultJoinData
}
}
}
MY_API.chatLog(`[天选时刻] 忽略有粉丝勋章要求的天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
所需勋章等级:${response.data.require_value}
你没有该勋章
${MY_API.AnchorLottery.countDown(response.data.time)}${joinHtml()}`, 'warning');
joinAnchorListener();
return false
} else {
MY_API.chatLog(`[天选时刻] 获取uid出错
${res.msg}`, 'error');
return false
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取uid出错,请检查网络`, 'error');
return false
});
}
case 3: { //大航海
return BAPI.xlive.getInfoByUser(roomid).then((re) => {
MYDEBUG(`API.xlive.getInfoByUser ${roomid}`, re);
if (re.code === 0) {
const privilege_type = re.data.privilege.privilege_type;
if (privilege_type !== 0 && privilege_type <= response.data.require_value) {
//0:未上船,1:总督,2:提督,3:舰长。若满足要求则返回数据
return defaultJoinData;
} else {
function getPrivilegeText(typeNum) {
switch (typeNum) {
case 0: return '无';
case 1: return '总督';
case 2: return '提督';
case 3: return '舰长';
default: return '未知';
}
}
const requireText = getPrivilegeText(response.data.require_value),
myText = getPrivilegeText(privilege_type);
MY_API.chatLog(`[天选时刻] 忽略大航海等级不足的天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
所需大航海等级:${requireText}
你的大航海等级:${myText}
${MY_API.AnchorLottery.countDown(response.data.time)}`, 'warning');
return false
}
} else {
return false
}
})
}
case 4: {
//直播等级
if (Live_info.user_level >= response.data.require_value) return defaultJoinData;
else MY_API.chatLog(`[天选时刻] 忽略直播等级不足的天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
所需直播等级:${response.data.require_value}
你的直播等级:UL.${Live_info.user_level}
${MY_API.AnchorLottery.countDown(response.data.time)}`, 'warning');
return false
}
case 5: {
//主站等级
if (Live_info.level >= response.data.require_value) return defaultJoinData;
else MY_API.chatLog(`[天选时刻] 忽略主站等级不足的天选
roomid = ${linkMsg(roomid, liveRoomUrl + roomid)}, id = ${response.data.id}
奖品名:${response.data.award_name}
所需直播等级:${response.data.require_value}
你的主站等级:Lv${Live_info.level}
${MY_API.AnchorLottery.countDown(response.data.time)}`, 'warning');
return false
}
default: {
MYDEBUG(`[天选时刻] 未被收录的类型 require_value = ${response.data.require_value}`, response);
return false
}
}
}
else {
return false
}
}, () => {
MY_API.chatLog(`[天选时刻] 天选检查出错,请检查网络`, 'error');
return delayCall(() => MY_API.AnchorLottery.check(roomid));
});
},
reCheck: (data) => {
return BAPI.xlive.anchor.check(data.roomid).then((response) => {
MYDEBUG(`API.xlive.anchor.reCheck(${data.roomid}) response`, response);
if (response.code === 0 && response.data && response.data.hasOwnProperty('award_users') && response.data.award_users) {
let anchorUid = data.uid, award = false;
for (const i of response.data.award_users) {
if (i.uid === Live_info.uid) {
award = true;
break;
}
}
if (!award) {//运行没中奖的代码
if (MY_API.CONFIG.ANCHOR_AUTO_DEL_FOLLOW) {
const config = JSON.parse(localStorage.getItem(`${NAME}AnchorFollowingList`)) || { list: [] };
const id_list = [...config.list];
if (id_list.indexOf(String(anchorUid)) === -1 && MY_API.AnchorLottery.uidInOriginTag.indexOf(String(anchorUid)) === -1) {
return BAPI.relation.modify(anchorUid, 2).then((response) => {
MYDEBUG(`API.relation.modify response.info.uid, ${2}`, response);
if (response.code === 0) {
window.toast(`[天选自动取关] 取关UP(uid = ${anchorUid})成功`, 'success');
}
else {
window.toast(`[天选自动取关] 取关UP(uid = ${anchorUid})出错 ${response.message}`, 'error');
}
}, () => {
MY_API.chatLog(`[天选自动取关] 取关UP(uid = ${anchorUid})出错,请检查网络`);
})
}
}
} else { //中奖的代码
MY_API.chatLog(`[天选时刻] 天选时刻
roomid = ${linkMsg(data.roomid, liveRoomUrl + data.roomid)}, id = ${data.id}中奖
奖品:${data.award_name}
`, 'prize');
winPrizeNum++;
winPrizeTotalCount++;
JQlogRedPoint.text(winPrizeNum);
if (JQlogRedPoint.is(":hidden")) JQlogRedPoint.show();
if (MY_API.CONFIG.ANCHOR_PRIVATE_LETTER) {
const msg = {
sender_uid: Live_info.uid,
receiver_id: anchorUid,
receiver_type: 1,
msg_type: 1,
msg_status: 0,
content: `{"content":"` + MY_API.CONFIG.ANCHOR_LETTER_CONTENT + `"}`,
dev_id: getMsgDevId()
}
setTimeout(() => {
BAPI.sendMsg(msg).then((res) => {
MYDEBUG(`API.sendMsg ${msg}`, res);
if (res.code === 0) {
window.toast(`[天选自动私信] 私信UP(uid = ${anchorUid})成功`, 'success');
} else {
window.toast(`[天选自动私信] 私信UP(uid = ${anchorUid})失败 ${res.message}`, 'error');
}
}, () => {
MY_API.chatLog(`[天选自动私信] 私信UP(uid = ${anchorUid})出错,请检查网络`);
})
}, 8000);//之前2秒+8秒
}
if (MY_API.CONFIG.ANCHOR_MOVETO_PRIZE_TAG) {
BAPI.relation.addUsers(anchorUid, MY_API.AnchorLottery.anchorPrizeTagid).then((re) => {
MYDEBUG(`API.relation.addUsers ${anchorUid} ${MY_API.AnchorLottery.anchorPrizeTagid}`, re);
if (re.code === 0) window.toast(`[天选时刻] 移动UP(uid = ${anchorUid})至分组【${anchorPrizeTagName}】成功`, 'success');
else window.toast(`[天选时刻] 移动UP(uid = ${anchorUid})至分组【${anchorPrizeTagName}】失败 ${re.message}`, 'warning');
}, () => {
MY_API.chatLog(`[天选时刻] 移动UP(uid = ${anchorUid})到分组【${anchorPrizeTagName}】出错,请检查网络`, 'error');
});
}
if (MY_API.CONFIG.FT_NOTICE) {
function FT_notice() {
return FT_sendMsg(MY_API.CONFIG.FT_SCKEY,
`${GM_info.script.name} 天选时刻中奖通知 ${new Date().toLocaleString()}`,
`###天选时刻中奖\n###中奖账号id:${Live_info.uname}\n###房间号roomid = ${data.roomid}\n###主播uid = ${anchorUid}\n###抽奖id = ${data.id}\n###获得奖品:\n###${data.award_name}\n###请及时私信主播发放奖励`
).then((re) => {
MYDEBUG('FT_sendMsg response', re);
if (re.body.errno == 0) {
window.toast('[天选时刻] 方糖中奖提示发送成功', 'success');
} else {
window.toast(`[天选时刻] 方糖中奖提示发送失败 ${re.errmsg}`, 'error')
}
}, () => {
MY_API.chatLog(`[天选时刻] 方糖中奖提示发送出错,请检查网络`, 'error');
return delayCall(() => FT_notice());
});
}
FT_notice();
}
if (MY_API.CONFIG.GM_NOTICE) {
GM_notice("天选时刻中奖", `房间号:${data.roomid},奖品:${data.award_name}`)
}
if (MY_API.CONFIG.ANCHOR_DANMU) {
const danmuContent = MY_API.CONFIG.ANCHOR_DANMU_CONTENT[Math.floor(Math.random() * MY_API.CONFIG.MEDAL_DANMU_CONTENT.length)];
MY_API.AnchorLottery.sendDanmu(danmuContent, data.roomid)
}
if (MY_API.CONFIG.ANCHOR_ADD_TO_WHITELIST) {
const config = JSON.parse(localStorage.getItem(`${NAME}AnchorFollowingList`)) || { list: [] };
let id_list = [...config.list];
id_list.push(String(anchorUid));
localStorage.setItem(`${NAME}AnchorFollowingList`, JSON.stringify({ list: id_list }));
window.toast(`[天选时刻] 已将UP(uid = ${anchorUid})添加至白名单`, 'success');
}
}
}
}, () => {
MY_API.chatLog(`[天选时刻] 天选检查出错,请检查网络`, 'error');
return delayCall(() => MY_API.AnchorLottery.check(roomid));
});
},
sendDanmu: async (danmuContent, roomId) => {
let realRoomId = roomId;
if (Number(roomId) <= 10000) {
realRoomId = await BAPI.room.get_info(roomId).then((res) => {
MYDEBUG(`API.room.get_info roomId=${roomId} res`, res);//可能是短号,要用长号发弹幕
return res.data.room_id;
}), () => {
window.toast(`[天选中奖弹幕] 房间号【${roomId}】信息获取失败`, 'error')
return $.Deferred().reject();
};
}
return BAPI.sendLiveDanmu(danmuContent, realRoomId).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');
return $.Deferred().reject();
})
},
countDown: (time, color = '#da4939') => {
if (time !== undefined)
return `
距开奖还有${time}秒`;
else return '';
},
pwdCheck: (room_id, pwd = '') => {
return BAPI.room.verify_room_pwd(room_id, pwd).then((response) => {
MYDEBUG(`API.room.verify_room_pwd(${room_id}, ${pwd})`, response);
if (response.code === -1) return true;//message: ╮( ̄▽ ̄)╭请输入密码 / 你确定不是掏错卡了?("▔□▔)/请重新输入密码
else if (response.code === 0) return false; //message: room_not_encrypted
else return true;
}, () => {
MY_API.chatLog('[天选时刻] 直播间加密检查出错,请检查网络', 'error');
});
},
/**
* 参与天选
@param {
{ id: number, gift_id?: number, gift_num?: number, roomid: number, award_name: string, time: number, require_type: number, joinPrice: number, uid: undefined}
} data
*/
join: (data) => {
//console.table('[天选时刻] 参加天选 join(data)\n', { id: data.id, gift_id: data.gift_id, gift_num: data.gift_num, roomid: data.roomid, award_name: data.award_name, time: data.time, require_type: data.require_type, joinPrice: data.joinPrice});
return BAPI.xlive.anchor.join(data.id, data.gift_id, data.gift_num).then((response) => {
MYDEBUG(`API.xlive.anchor.join(${data.id}) response`, response);
if (response.code === 0) {
MY_API.chatLog(`[天选时刻] 成功参加天选
roomid = ${linkMsg(data.roomid, liveRoomUrl + data.roomid)}, id = ${data.id}
${data.joinPrice === 0 ? '' : ('花费金瓜子:' + data.joinPrice + '
')}奖品:${data.award_name}
${MY_API.AnchorLottery.countDown(data.time)}`, 'success');
MY_API.AnchorLottery.waitForRecheckList.push(data.roomid);
let p = $.Deferred();
if (!data.uid) {
BAPI.live_user.get_anchor_in_room(data.roomid).then((res) => { //获取uid
MYDEBUG(`API.live_user.get_anchor_in_room(${data.roomid})`, res);
if (res.code === 0) {
data.uid = res.data.info.uid;
p.resolve();
} else {
MY_API.chatLog(`[天选时刻] 获取uid出错,中断后续操作
roomid = ${linkMsg(data.roomid, liveRoomUrl + data.roomid)}, id = ${data.id}
${res.msg}`, 'error');
p.reject();
}
}, () => {
MY_API.chatLog(`[天选时刻] 获取uid出错,中断后续操作
roomid = ${linkMsg(data.roomid, liveRoomUrl + data.roomid)}, id = ${data.id}
请检查网络`, 'error');
p.reject();
});
} else p.resolve();
p.then(() => {
MY_API.addAnchor();
MYDEBUG('天选时刻join data', data);
if (data.require_type === 1 && MY_API.CONFIG.ANCHOR_MOVETO_FOLLOW_TAG) { //有关注要求
if (MY_API.AnchorLottery.uidInOriginTag.indexOf(String(data.uid)) > -1) return;//之前在默认分组,不移动
setTimeout(() => {
BAPI.relation.addUsers(data.uid, MY_API.AnchorLottery.anchorFollowTagid).then((re) => {
MYDEBUG(`API.relation.addUsers ${data.uid} ${MY_API.AnchorLottery.anchorFollowTagid}`, re);
if (re.code === 0) window.toast(`[天选时刻] 移动UP(uid = ${data.uid})至分组【${anchorFollowTagName}】成功`, 'success');
else window.toast(`[天选时刻] 移动UP(uid = ${data.uid})至分组【${anchorFollowTagName}】失败 ${re.message}`, 'warning');
}, () => {
MY_API.chatLog(`[天选时刻] 移动UP(uid = ${data.uid})到分组【${anchorFollowTagName}】出错,请检查网络`);
});
}, 4000);
}
setTimeout(() => MY_API.AnchorLottery.reCheck(data), data.time * 1000 + 1500);
})
} else if (response.code === 500) {
MY_API.chatLog(`[天选时刻] 天选参加失败
roomid = ${linkMsg(data.roomid, liveRoomUrl + data.roomid)}, id = ${data.id}
奖品:${data.award_name}
${response.msg}
3秒后再次尝试参加`, 'warning');
return setTimeout(() => MY_API.AnchorLottery.join(data), 3000);
}
else {
return MY_API.chatLog(`[天选时刻] 天选参加失败
roomid = ${linkMsg(data.roomid, liveRoomUrl + data.roomid)}, id = ${data.id}
奖品:${data.award_name}
${response.msg}`, 'warning')
}
}, () => {
MY_API.chatLog(`[天选时刻] 天选参加出错,请检查网络`, 'error');
return delayCall(() => MY_API.AnchorLottery.join(data));
})
},
/**
* 检测是否在休眠时间休眠时间
* @returns {boolean} false (不在休眠时间段)
* @returns {number} 距休眠结束的毫秒数 (在休眠时间段)
*/
sleepCheck: () => {
if (!MY_API.CONFIG.TIME_AREA_DISABLE) return false;
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)) {
//判断时间段
return getIntervalTime(MY_API.CONFIG.TIME_AREA_END_H0UR, MY_API.CONFIG.TIME_AREA_END_MINUTE);
} else {
return false
}
},
run: async () => {
if (!MY_API.CONFIG.ANCHOR_LOTTERY) return $.Deferred().resolve();
const settingIntervalTime = MY_API.CONFIG.ANCHOR_CHECK_INTERVAL * 60000;
MY_API.chatLog(`[天选时刻] 开始获取粉丝勋章信息`);
await MY_API.AnchorLottery.getMedalList();
MY_API.chatLog(`[天选时刻] 开始获取关注分组信息`);
if (MY_API.CONFIG.ANCHOR_MOVETO_FOLLOW_TAG || MY_API.CONFIG.ANCHOR_MOVETO_PRIZE_TAG)
await MY_API.AnchorLottery.getTag([anchorFollowTagName, anchorPrizeTagName]);
await MY_API.AnchorLottery.getUpInOriginTag(Live_info.uid);
function waitForNextRun(Fn) {
const sleepTime = MY_API.AnchorLottery.sleepCheck();
if (sleepTime) {
MYDEBUG('[天选时刻]', `处于休眠时段,${sleepTime}毫秒后再次检查天选`);
MY_API.chatLog(`[天选时刻] 处于休眠时段,将会在
${new Date(ts_ms() + sleepTime).toLocaleString()}
结束休眠并继续检查天选`, 'warning');
return setTimeout(() => Fn(), sleepTime);
} else {
const intervalTime = ts_ms() - MY_API.CACHE.AnchorLottery_TS;
const waitTime = intervalTime >= MY_API.CONFIG.ANCHOR_CHECK_INTERVAL * 60000 ? 0 : intervalTime;
MYDEBUG('[天选时刻]', `将在${waitTime}毫秒后再次检查天选`);
return setTimeout(() => Fn(), waitTime);
}
}
if (MY_API.CONFIG.ANCHOR_TYPE == 'ANCHOR_POLLING') {
if (MY_API.CONFIG.ANCHOR_UPLOAD_DATA) {
await MY_API.AnchorLottery.uploadRoomList();
}
async function getRoomListAndJoin() {
await MY_API.AnchorLottery.getRoomList();
const config = JSON.parse(localStorage.getItem(`${NAME}AnchorRoomidList`)) || { list: [] };
const id_list = [...config.list];
MY_API.chatLog(`[天选时刻] 开始检查天选(共${id_list.length}个房间)`, 'success');
for (const room of id_list) {
let p = $.Deferred();
if (!MY_API.CONFIG.ANCHOR_WAIT_REPLY) p.resolve();
MY_API.AnchorLottery.check(room).then((re) => {
if (re) {
//数据格式正确,可以参加
if (MY_API.CONFIG.ANCHOR_IGNORE_PWDROOM) {
return MY_API.AnchorLottery.pwdCheck(room).then((res) => {
if (res) {
//加密
MY_API.chatLog(`[天选时刻] 忽略加密直播间的天选
roomid = ${linkMsg(res[3], liveRoomUrl + res[3])}, id = ${res[0]}
${res[8] === 0 ? '' : ('所需金瓜子:' + res[8] + '
')}奖品:${res[4]}
${MY_API.AnchorLottery.countDown(res[5])}`, 'warning');
p.resolve();
} else {
//不加密
MY_API.AnchorLottery.join(re).then(() => p.resolve());
}
}, () => {
MY_API.chatLog('[天选时刻] 直播间加密检查出错,请检查网络', 'error')
})
} else {
MY_API.AnchorLottery.join(re).then(() => p.resolve());
}
} else p.resolve();
});
await p;
await sleep(MY_API.CONFIG.ANCHOR_INTERVAL);
};
MY_API.CACHE.AnchorLottery_TS = ts_ms();
MY_API.saveCache();
const sleepTime = MY_API.AnchorLottery.sleepCheck();
if (sleepTime) {
MYDEBUG('[天选时刻]', `处于休眠时段,${sleepTime}毫秒后再次检查天选`);
MY_API.chatLog(`[天选时刻] 处于休眠时段,将会在
${new Date(ts_ms() + sleepTime).toLocaleString()}
结束休眠并继续检查天选`, 'warning');
return setTimeout(() => getRoomListAndJoin(), sleepTime);
} else {
MY_API.chatLog(`[天选时刻] 本次轮询结束
${MY_API.CONFIG.ANCHOR_CHECK_INTERVAL}分钟后再次检查天选`, 'success');
return setTimeout(() => getRoomListAndJoin(), settingIntervalTime);
}
};
return waitForNextRun(() => getRoomListAndJoin());
} else {
return waitForNextRun(() => MY_API.AnchorLottery.getLotteryInfoFromRoom());
}
}
}
};
MY_API.init().then(() => {
try {
//登陆判断
let runNext = $.Deferred();
const showEula = localStorage.getItem(`${NAME}_showEula`);
if (showEula !== 'false') {
const eula = GM_getResourceText('eula');
layer.open({
title: `${GM_info.script.name}最终用户许可协议`,
btn: ['同意协议并继续', '不同意'],
closeBtn: 0,
area: [String($(window).width() * 0.618) + 'px', String($(window).height() * 0.8) + 'px'],
content: eula,
yes: function (index) {
localStorage.setItem(`${NAME}_showEula`, false);
layer.close(index);
runNext.resolve();
},
btn2: function () {
layer.msg('脚本已停止运行', {
time: 3000,
icon: 2
});
MY_API.chatLog('由于未同意最终用户许可协议,
脚本已停止运行。', 'warning');
localStorage.setItem(`${NAME}_showEula`, true);
runNext.reject();
},
success: () => { layerTimes++ }
});
} else runNext.resolve();
runNext.then(() => {
if (parseInt(Live_info.uid) === 0 || isNaN(parseInt(Live_info.uid)))
return MY_API.chatLog('未登录,请先登录再使用脚本', 'warning');
//新版本提示信息
if (MY_API.CONFIG.UPDATE_TIP) MY_API.newMessage(GM_info.script.version);
MYDEBUG('MY_API.CONFIG', MY_API.CONFIG);
main(MY_API);
});
}
catch (e) {
MYERROR('初始化错误', e);
}
});
}
async function main(API) {
//修复版本更新产生的兼容性问题
fixVersionDifferences(API, GM_info.script.version);
//清空辣条数量
let clearStat = () => {
for (const i in API.GIFT_COUNT) {
if (i !== 'CLEAR_TS') API.GIFT_COUNT[i] = 0;
}
API.GIFT_COUNT.CLEAR_TS = ts_ms();
API.saveGiftCount();
$('#giftCount .anchor .statNum').text(API.GIFT_COUNT.ANCHOR_COUNT);
$('#giftCount .material .statNum').text(API.GIFT_COUNT.MATERIAL_COUNT);
MYDEBUG('已重置统计')
}
if (checkNewDay(API.GIFT_COUNT.CLEAR_TS)) clearStat();
runExactMidnight(() => clearStat(), '重置统计');
API.creatSetBox();//创建设置框
API.removeUnnecessary();//移除页面元素
const config = JSON.parse(localStorage.getItem(`${NAME}AnchorFollowingList`)) || { list: [] };
let idlist = [...config.list];
if (idlist.length !== 0 && typeof (idlist[0]) === 'number') {
for (let i = 0; i < idlist.length; i++) {
idlist[i] = String(idlist[i])
}
localStorage.setItem(`${NAME}AnchorFollowingList`, JSON.stringify({ list: idlist }));
}
const taskList = [
//每日任务
API.MEDAL_DANMU.run,//粉丝牌打卡弹幕
API.GroupSign.run,//应援团签到
API.DailyReward.run,//每日任务
API.LiveReward.run,//直播每日任务
API.Exchange.runS2C,//银瓜子换硬币
API.Exchange.runC2S,//硬币换银瓜子]
//其它任务
API.AUTO_DANMU.run,//自动发弹幕
API.LITTLE_HEART.run,//小心心
API.Gift.run,//送礼物
API.MaterialObject.run,//实物抽奖
API.AnchorLottery.run//天选时刻
];
runAllTasks(5000, 200, taskList);
if (API.CONFIG.LOTTERY) {
let roomList;
await BAPI.room.getList().then((response) => {//获取各分区的房间号
MYDEBUG('直播间列表', response);
roomList = response.data;
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.list.length; ++j) {
API.listen(response.data.list[j].roomid, Live_info.uid, `${obj.name}区`);
}
}, () => {
MY_API.chatLog(`[礼物抽奖] 获取直播间列表出错,请检查网络`, 'error');
});
}
}, () => {
MY_API.chatLog(`[礼物抽奖] 获取各分区的房间号出错,请检查网络`, 'error');
});
if (API.CONFIG.CHECK_HOUR_ROOM) {
let check_top_room = async () => { //检查小时榜房间
if (API.blocked || API.max_blocked) {//如果被禁用则停止
if (API.blocked) {
API.chatLog('进入小黑屋检查小时榜已停止运行');
clearInterval(check_timer);
return
}
else {
API.chatLog('辣条已达到最大值检查小时榜已停止运行');
return
}
}
if (API.CONFIG.TIME_AREA_DISABLE && 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.chatLog('当前时间段不检查小时榜礼物', 'warning');
return
}
for (const r of roomList) {
await BAPI.rankdb.getTopRealTimeHour(r.id).then((data) => {
let list = data.data.list;
API.chatLog(`检查${r.name + '小时榜'}房间的礼物`, 'warning'); s
for (const 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));
}
}
const reset = (delay) => {
let resetTimer = setTimeout(() => {//刷新直播间
if (API.raffleId_list.length > 0 || API.guardId_list.length > 0 || API.pkId_list.length > 0) {
MYDEBUG('[刷新直播间]', '还有礼物没抽,延迟15s后刷新直播间');
return reset(15000);
}
if (checkNewDay(API.CACHE.LittleHeart_TS)) {
MYDEBUG('[刷新直播间]', '正在获取小心心,10分钟后再次检查');
clearTimeout(resetTimer);
return reset(600e3);
}
if (API.CONFIG.TIME_AREA_DISABLE && 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)) {//在不抽奖时段且不抽奖时段不刷新开启
let resetTime = getIntervalTime(API.CONFIG.TIME_AREA_START_MINUTE, API.CONFIG.TIME_AREA_END_MINUTE) + 60e3;
MYDEBUG('[刷新直播间]', `处于休眠时间段,将在${resetTime}毫秒后刷新直播间`);
return reset(resetTime);
}
window.location.reload();
}, delay);
};
if (API.CONFIG.TIME_RELOAD) reset(API.CONFIG.TIME_RELOAD_MINUTE * 60000);//单位1分钟,重新加载直播间
}
/**
* 删除一维数组元素
* @param val 数组中一个元素的值
*/
function removeValinArray(val, Array) {
const index = Array.indexOf(val);
if (index > -1) return Array.splice(index, 1);
}
/**
* 比较版本号大小
* @param {string} preVersion 当前版本号
* @param {string} lastVersion 过去版本号
* @returns {boolean} 若 当前 >= 过去 返回 true, 否则返回 false
*/
function versionStringCompare(preVersion = '', lastVersion = '') {
let sources = preVersion.split('.'),
dests = lastVersion.split('.'),
maxL = Math.max(sources.length, dests.length),
result = true;
for (let i = 0; i < maxL; i++) {
let preValue = sources.length > i ? sources[i] : 0,
preNum = isNaN(Number(preValue)) ? preValue.charCodeAt() : Number(preValue),
lastValue = dests.length > i ? dests[i] : 0,
lastNum = isNaN(Number(lastValue)) ? lastValue.charCodeAt() : Number(lastValue);
if (preNum < lastNum) {
result = false;
break;
} else if (preNum > lastNum) {
result = true;
break;
}
}
return result;
}
/**
* 执行所有任务
* @param {Number} sleep 休眠时间
* @param {Number} interval 任务间隔
* @param {list} task 任务
*/
function runAllTasks(sleep, interval, task) {
let num = 0;
setTimeout(() => {
for (const i of task) {
setTimeout(() => i(), interval * num++);
}
}, sleep);
}
/**
* 修复因版本差异造成的错误
* @param API MY_API
*/
function fixVersionDifferences(API, version) {
//修复变量类型错误
//添加新的修复后需修改版本号
if (versionStringCompare(storageLastFixVersion, "5.6.4.5")) return;
const configFixList = ['AUTO_GIFT_ROOMID', 'EXCLUDE_ROOMID', 'COIN_UID'];
if (!configFixList.every(i => $.isArray(API.CONFIG[i]))) {
for (const i of configFixList) {
if (!$.isArray(API.CONFIG[i])) {
API.CONFIG[i] = String(API.CONFIG[i]).split(",");
}
}
}
//修复变量值差异
if (API.CONFIG.ANCHOR_TYPE == 'POLLING') API.CONFIG.ANCHOR_TYPE = 'ANCHOR_POLLING';
else if (API.CONFIG.ANCHOR_TYPE == 'LIVEROOM') API.CONFIG.ANCHOR_TYPE = 'ANCHOR_LIVEROOM';
if (API.CONFIG.GIFT_SORT == 'high') API.CONFIG.GIFT_SORT = 'GIFT_SORT_HIGH';
else if (API.CONFIG.GIFT_SORT == 'low') API.CONFIG.GIFT_SORT = 'GIFT_SORT_LOW'
//修复CACHE
const cache = JSON.parse(localStorage.getItem(`${NAME}_CACHE`));
const cacheFixList = [['materialobject_ts', 'MaterialObject_TS'], ['medalDanmu_TS', 'MedalDanmu_TS']];
for (const i of cacheFixList) {
if (cache.hasOwnProperty(i[0])) API.CACHE[i[1]] = cache[i[0]];
}
API.saveConfig(false);
API.saveCache();
localStorage.setItem(`${NAME}_lastFixVersion`, version);
}
/**
* layer动画
* @param {jqdom} jqdom
* @param {boolean} bool
*/
function animChange(jqdom, bool) {
if (bool) {
//show => hide
jqdom.removeClass('layer-anim');
jqdom.removeClass('layer-anim-00');
jqdom.addClass('layer-anim');
jqdom.addClass('layer-anim-close');
} else {
//hide => show
jqdom.removeClass('layer-anim');
jqdom.removeClass('layer-anim-close');
jqdom.addClass('layer-anim');
jqdom.addClass('layer-anim-00');
}
}
/**
* 保存文件到本地
* @param fileName 文件名
* @param fileContent 文件内容
*/
function downFile(fileName, fileContent) {
let elementA = document.createElement("a");
elementA.setAttribute(
"href",
"data:text/plain;charset=utf-8," + JSON.stringify(fileContent)
);
elementA.setAttribute("download", fileName);
elementA.style.display = "none";
document.body.appendChild(elementA);
elementA.click();
document.body.removeChild(elementA);
}
/**
* 导出配置文件
* @param MY_API_CONFIG MY_API.CONFIG
* @param nosleepConfig noSleep
* @param INVISIBLE_ENTER_config invisibleEnter
*/
function exportConfig(MY_API_CONFIG, nosleepConfig, INVISIBLE_ENTER_config) {
const exportJson = {
MY_API_CONFIG: MY_API_CONFIG,
nosleepConfig: nosleepConfig,
INVISIBLE_ENTER_config: INVISIBLE_ENTER_config
};
return downFile('BLTH_CONFIG.json', exportJson);
}
/**
* 导入配置文件
*/
function importConfig() {
let selectedFile = document.getElementById("BLTH_config_file").files[0];
let reader = new FileReader();
reader.readAsText(selectedFile);
reader.onload = function () {
MYDEBUG("importConfig 文件读取结果:", this.result);
try {
readConfigArray[0] = JSON.parse(this.result);
if (typeof readConfigArray[0] == 'object' && readConfigArray[0]) {
const list = ["MY_API_CONFIG", "nosleepConfig", "INVISIBLE_ENTER_config"];
for (const i of list) {
if (!readConfigArray[0].hasOwnProperty(i)) return wrongFile();
}
return readConfigArray[1].resolve();
} else {
return wrongFile();
}
} catch (e) {
MYDEBUG('importConfig error:', e);
return wrongFile();
}
};
function wrongFile() {
return layer.msg('文件格式错误', {
time: 2000,
icon: 2
});
}
}
/**
* (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
}
const hourMs = 3600000, minMs = 60000,
myDate = new Date(),
nowHour = myDate.getHours(),
nowMin = myDate.getMinutes(),
nowTimeTs = nowHour * hourMs + nowMin * minMs,
targetStartTs = sH * hourMs + sM * minMs,
targetEndTs = eH * hourMs + eM * minMs;
if (targetStartTs < targetEndTs) {
if (nowTimeTs >= targetStartTs && nowTimeTs <= targetEndTs)
return true;
else return false;
} else {
if (nowTimeTs >= targetStartTs || nowTimeTs <= targetEndTs)
return true
else return false;
}
};
/**
* 暂停
* @param millisecond
* @returns {Promise} resolve
*/
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
}
/**
* 检查是否为新一天
* @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);
};
/**
* 发送方糖通知
* @param SCKEY
* @param text
* @param desp
* @returns {object} resolve({response: res, body: res.response})
*/
function FT_sendMsg(SCKEY, text, desp) {
return XHR({
GM: true,
anonymous: true,
method: 'POST',
url: `http://sc.ftqq.com/${SCKEY}.send`, //隔离系统:sct.ftqq.com
data: `text=${text}&desp=${desp}`,
responseType: 'json'
})
}
/**
* 浏览器提示
* @param title
* @param text
* @param timeout
*/
function GM_notice(title, text, timeout = 10000) {
const notificationDetails = {
title: title,
text: text,
timeout: timeout,
onclick: function () {
if (logDiv.hasClass("active")) logDiv.click();
}
};
return GM_notification(notificationDetails)
}
/**
* 获取msg[dev_id]
* @param name
* @returns {String} dev_id
*/
function getMsgDevId(name = NAME) {
let deviceid = window.localStorage.getItem("im_deviceid_".concat(name));
if (!name || !deviceid) {
let str = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (function (name) {
let randomInt = 16 * Math.random() | 0;
return ("x" === name ? randomInt : 3 & randomInt | 8).toString(16).toUpperCase()
}
));
return function (name, randomInt) {
Object.keys(localStorage).forEach((function (name) {
name.match(/^im_deviceid_/) && window.localStorage.removeItem(name)
}
)),
window.localStorage.setItem("im_deviceid_".concat(randomInt), name)
}(str, name),
str
}
return deviceid
};
/**
* 发起xmlhttpRequest请求(GM函数和浏览器原生)
* @param XHROptions
* @returns {object} resolve({response: res, body: res.response})
*/
function XHR(XHROptions) {
return new Promise(resolve => {
const onerror = (error) => {
MYERROR('XHR出错', `参数${XHROptions}`, 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);
}
});
}
})();