// ==UserScript==
// @name B站剧集券和大会员积分自动签到
// @namespace http://tampermonkey.net/
// @version 2.0.0
// @description B站剧集券和大会员积分自动签到, 可自定义第三天签到日期
// @match https://www.bilibili.com
// @icon https://www.bilibili.com/favicon.ico
// @require https://unpkg.com/[email protected]/dist/jquery.js
// @run-at document-end
// @grant unsafeWindow
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @license @license MIT
// ==/UserScript==
(function() {
'use strict';
// --- 配置 ---
const three_days_sign_check_api = 'https://api.bilibili.com/x/vip/vip_center/sign_in/three_days_sign';
const activity_score_task_sign_api = 'https://api.bilibili.com/pgc/activity/score/task/sign2';
const SETTING_KEY_SIGN_DAY = 'bili_vip_sign_day_v3';
const WEEKDAYS = {
1: '周一', 2: '周二', 3: '周三', 4: '周四', 5: '周五', 6: '周六', 0: '周日'
};
// --- 工具函数 ---
// 日志函数
function the_log(...msg) {
console.log('%c[B站大会员积分自动签到]', 'font-weight: bold; color: white; background-color: #FF9999; padding: 2px; border-radius: 2px;', ...msg);
}
// 注入CSS样式
function injectStyles() {
const style = `
/* 按钮通用悬浮效果 */
#bili-sign-save-btn, #bili-sign-cancel-btn {
transition: all 0.2s ease-in-out;
}
#bili-sign-save-btn:hover {
background-color: #00b5e5 !important;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
#bili-sign-cancel-btn:hover {
background-color: #dcdfe6 !important;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
/* 顶部通知弹窗样式 */
.bili-sign-top-toast {
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%) translateY(-100px);
background-color: #00a1d6;
color: white;
padding: 10px 25px;
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 10000;
font-size: 14px;
opacity: 0;
transition: transform 0.4s ease-out, opacity 0.4s ease-out;
}
.bili-sign-top-toast.show {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
`;
const styleElement = document.createElement('style');
styleElement.textContent = style;
document.head.appendChild(styleElement);
}
// 显示顶部通知
function showTopNotification(message, duration = 3000) {
// 移除已存在的通知
$('.bili-sign-top-toast').remove();
const toast = $(`<div class="bili-sign-top-toast">${message}</div>`);
$('body').append(toast);
// 触发显示动画
setTimeout(() => toast.addClass('show'), 50);
// 到期后触发隐藏动画并移除
setTimeout(() => {
toast.removeClass('show');
setTimeout(() => toast.remove(), 500); // 等待动画结束后再移除DOM
}, duration);
}
// --- 核心逻辑 ---
the_log("自动签到脚本已启动...");
// 注入自定义样式
injectStyles();
// 获取 CSRF Token
const u_frsc = (document.cookie.split(';').map(c => c.trim()).find(c => c.startsWith('bili_jct=')) || '').split('bili_jct=')[1] || '';
const u_frsc_flag = u_frsc !== '';
// POST 签到请求
async function doSign() {
const url = activity_score_task_sign_api + '?csrf=' + u_frsc;
the_log("正在执行POST签到请求...");
try {
const response = await fetch(url, {
method: "POST",
credentials: "include",
headers: {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Referer": "https://big.bilibili.com"},
body: `device=phone`
});
const data = await response.json();
if (data.code === 0) {
if (data.data.count <= 3) {
the_log("签到成功!本轮已签到次数:", data.data.count);
showTopNotification('剧集券自动签到成功!本轮已签到' + data.data.count + '天');
} else {
the_log("大会员积分签到成功!");
showTopNotification('大会员积分自动签到成功!');
}
} else {
the_log("签到失败:", data.message);
}
} catch (error) {
the_log("签到请求失败:", error);
}
}
// GET 检查状态并决定是否签到
async function checkAndSign() {
if (!u_frsc_flag) {
the_log("未登录B站,跳过签到。");
return;
}
the_log("正在检查签到状态...");
try {
const response = await fetch(three_days_sign_check_api, { method: "GET", credentials: "include" });
const res = await response.json();
if (res.code !== 0) {
the_log("获取签到状态失败:", res.message);
return;
}
const { count, signed } = res.data.three_day_sign;
the_log(`今天是否已签到: ${signed}`);
if (signed) {
the_log("今天已经签到过了,无需重复签到。");
return;
}
if (count < 2) {
the_log("本轮已签到天数小于2天,执行签到。");
await doSign();
} else if (count === 2) {
const today = new Date().getDay();
const configuredDay = GM_getValue(SETTING_KEY_SIGN_DAY, 6);
the_log(`今天是 [${WEEKDAYS[today]}],设置的第三天签到日是 [${WEEKDAYS[configuredDay]}]`);
if (today === configuredDay) {
the_log("今天是指定的第三天签到日,执行签到。");
await doSign();
} else {
the_log("今天不是指定的签到日,跳过。");
}
} else {
the_log(`执行大会员积分签到。`);
await doSign();
}
} catch (error) {
the_log("检查签到状态请求失败:", error);
}
}
// --- UI 相关 ---
// 显示设置弹窗
function showSettingsDialog() {
if (document.getElementById('bili-sign-settings-panel')) return;
const configuredDay = GM_getValue(SETTING_KEY_SIGN_DAY, 6);
let optionsHtml = [1, 2, 3, 4, 5, 6, 0].map(day =>
`<option value="${day}" ${day === configuredDay ? 'selected' : ''}>${WEEKDAYS[day]}</option>`
).join('');
const dialogHtml = `
<div id="bili-sign-settings-overlay" style="position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 9998;"></div>
<div id="bili-sign-settings-panel" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #fff; border-radius: 8px; padding: 20px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 9999; border: 1px solid #e3e5e7; width: 320px;">
<h3 style="margin: 0 0 15px; text-align: center; color: #18191c;">设置第三天签到日期</h3>
<div style="font-size: 14px; color: #61666d; margin-bottom: 10px;">请选择星期(剧集券有限期两天):</div>
<select id="bili-sign-day-select" style="width: 100%; padding: 8px; border-radius: 4px; border: 1px solid #ccc; margin-bottom: 20px; outline: none;">
${optionsHtml}
</select>
<div style="display: flex; justify-content: space-around;">
<button id="bili-sign-save-btn" style="padding: 8px 20px; border: none; background-color: #00a1d6; color: white; border-radius: 4px; cursor: pointer;">保存</button>
<button id="bili-sign-cancel-btn" style="padding: 8px 20px; border: none; background-color: #f1f2f3; color: #61666d; border-radius: 4px; cursor: pointer;">取消</button>
</div>
</div>
`;
$('body').append(dialogHtml);
const closeDialog = () => $('#bili-sign-settings-overlay, #bili-sign-settings-panel').remove();
$('#bili-sign-save-btn').on('click', () => {
const selectedDay = parseInt($('#bili-sign-day-select').val());
GM_setValue(SETTING_KEY_SIGN_DAY, selectedDay);
showTopNotification(`设置成功!第三天签到日已保存为 [${WEEKDAYS[selectedDay]}]`);
the_log(`设置已保存,第三天签到日: [${WEEKDAYS[selectedDay]}]`);
closeDialog();
});
$('#bili-sign-cancel-btn, #bili-sign-settings-overlay').on('click', closeDialog);
}
// --- 脚本入口 ---
// 注册油猴菜单
GM_registerMenuCommand('设置第三天签到日期', showSettingsDialog);
checkAndSign();
})();