ZZZ-Plugin/apps/remind.js
2025-08-20 18:48:30 +08:00

385 lines
No EOL
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import _ from 'lodash';
import settings from '../lib/settings.js';
import { rulePrefix } from '../lib/common.js';
import { Deadly } from '../model/deadly.js';
import { ZZZChallenge } from '../model/abyss.js';
import { ZZZPlugin } from '../lib/plugin.js';
const USER_CONFIGS_KEY = 'ZZZ:REMIND:USER_CONFIGS';
export class Remind extends ZZZPlugin {
constructor() {
super({
name: '[ZZZ-Plugin]Remind',
dsc: '式舆防卫战/危局强袭战未完成提醒',
event: 'message',
priority: _.get(settings.getConfig('priority'), 'remind', 70),
rule: [
{
reg: `${rulePrefix}开启挑战提醒$`,
fnc: 'subscribe',
},
{
reg: `${rulePrefix}关闭挑战提醒$`,
fnc: 'unsubscribe',
},
{
reg: `${rulePrefix}设置式舆阈值\\s*(\\d+)`,
fnc: 'setMyAbyssThreshold',
},
{
reg: `${rulePrefix}设置危局阈值\\s*(\\d+)`,
fnc: 'setMyDeadlyThreshold',
},
{
reg: `${rulePrefix}查询挑战状态$`,
fnc: 'checkNow',
},
{
reg: `${rulePrefix}设置个人提醒时间\\s*(每日\\d+时(?:(\\d+)分)?|每周.\\d+时(?:(\\d+)分)?)`,
fnc: 'setMyRemindTime',
},
{
reg: `${rulePrefix}个人提醒时间$`,
fnc: 'viewMyRemindTime',
},
{
reg: `${rulePrefix}取消个人提醒时间`,
fnc: 'deleteMyRemindTime',
},
{
reg: `${rulePrefix}设置全局提醒时间\\s*(每日\\d+时(?:(\\d+)分)?|每周.\\d+时(?:(\\d+)分)?)`,
fnc: 'setGlobalRemindTime',
},
{
reg: `${rulePrefix}全局提醒时间$`,
fnc: 'viewGlobalRemindTime',
},
],
});
const globalRemindConfig = settings.getConfig('remind');
if (globalRemindConfig.enable) {
this.task = {
name: 'ZZZ-Plugin式舆防卫战/危局强袭战提醒任务',
cron: '0 */10 * * * ?',
fnc: () => this.runTask(),
};
}
}
async getUserConfig(userId) {
const userConfigJson = await redis.hGet(USER_CONFIGS_KEY, String(userId));
return userConfigJson ? JSON.parse(userConfigJson) : null;
}
async setUserConfig(userId, config) {
await redis.hSet(USER_CONFIGS_KEY, String(userId), JSON.stringify(config));
}
isTimeMatch(remindTime, date) {
if (!remindTime) return false;
const currentDay = date.getDay(); // 0 = 周日, 1 = 周一, ..., 6 = 周六
const currentHour = date.getHours();
const currentMinute = date.getMinutes();
if (remindTime.includes('每日')) {
const match = remindTime.match(/每日(\d+)时(?:(\d+)分)?/);
if (match) {
const hour = parseInt(match[1]);
const minute = match[2] ? parseInt(match[2]) : 0;
return currentHour === hour && currentMinute === minute;
}
} else if (remindTime.includes('每周')) {
const dayMap = { '日': 0, '天': 0, '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6 };
const match = remindTime.match(/每周(.)(\d+)时(?:(\d+)分)?/);
if (match) {
const dayChar = match[1];
const day = dayMap[dayChar];
const hour = parseInt(match[2]);
const minute = match[3] ? parseInt(match[3]) : 0;
return currentDay === day && currentHour === hour && currentMinute === minute;
}
}
return false;
}
async subscribe() {
const uid = await this.getUID();
if (!uid) {
await this.reply('未绑定UID请先绑定');
return false;
}
let userConfig = await this.getUserConfig(this.e.user_id);
if (userConfig && userConfig.enable) {
await this.reply('提醒已开启,请勿重复操作');
return false;
}
if (userConfig) {
userConfig.enable = true;
} else {
const defaultConfig = settings.getConfig('remind');
userConfig = {
enable: true,
abyssCheckLevel: defaultConfig.abyssCheckLevel,
deadlyStars: defaultConfig.deadlyStars,
};
}
await this.setUserConfig(this.e.user_id, userConfig);
await this.reply('提醒功能已开启');
}
async unsubscribe() {
let userConfig = await this.getUserConfig(this.e.user_id);
if (!userConfig || !userConfig.enable) {
await this.reply('提醒功能尚未开启');
return false;
}
userConfig.enable = false;
await this.setUserConfig(this.e.user_id, userConfig);
await this.reply('提醒功能已关闭');
}
async setMyAbyssThreshold() {
const match = this.e.msg.match(/设置(?:式舆防卫战|式舆|深渊|防卫战|防卫)阈值\s*(\d+)/);
if (!match) return;
const threshold = Number(match[1]);
if (threshold < 1 || threshold > 7) {
await this.reply('阈值必须在1到7之间');
return false;
}
let userConfig = await this.getUserConfig(this.e.user_id);
if (!userConfig) {
const defaultConfig = settings.getConfig('remind');
userConfig = {
enable: false,
abyssCheckLevel: defaultConfig.abyssCheckLevel,
deadlyStars: defaultConfig.deadlyStars,
};
}
userConfig.abyssCheckLevel = threshold;
await this.setUserConfig(this.e.user_id, userConfig);
await this.reply(`式舆防卫战提醒阈值已设为: 检查前 ${threshold}`);
}
async setMyDeadlyThreshold() {
const match = this.e.msg.match(/设置(?:危局强袭战|危局|强袭|强袭战)阈值\s*(\d+)/);
if (!match) return;
const threshold = Number(match[1]);
let userConfig = await this.getUserConfig(this.e.user_id);
if (!userConfig) {
const defaultConfig = settings.getConfig('remind');
userConfig = {
enable: false,
abyssCheckLevel: defaultConfig.abyssCheckLevel,
deadlyStars: defaultConfig.deadlyStars,
};
}
userConfig.deadlyStars = threshold;
await this.setUserConfig(this.e.user_id, userConfig);
await this.reply(`危局强袭战星星阈值已设为: ${threshold}`);
}
async checkNow() {
const uid = await this.getUID();
if (!uid) return false;
const targetUserId = this.e.user_id;
let userConfig = await this.getUserConfig(targetUserId);
if (!userConfig) {
// 如果没有配置,使用默认配置
const defaultConfig = settings.getConfig('remind');
userConfig = {
enable: false, // 不开启提醒,仅用于查询
abyssCheckLevel: defaultConfig.abyssCheckLevel,
deadlyStars: defaultConfig.deadlyStars,
};
}
await this.reply('正在查询,请稍候...');
const messages = await this.checkUser(targetUserId, userConfig, true); // 主动查询,显示所有状态
if (messages.length > 0) {
await this.reply(messages.join('\n'));
} else {
await this.reply('查询失败,请稍后再试');
}
}
async checkUser(userId, userConfig, showAll = false, contextE = null) {
let messages = [];
const originalE = this.e;
this.e = contextE || this.e;
let api, deviceFp;
try {
// 获取 API 和玩家信息
({ api, deviceFp } = await this.getAPI());
await this.getPlayerInfo(this.e);
} catch (error) {
logger.error(`[ZZZ-Plugin] 为用户 ${userId} 获取API或玩家信息失败: ${error}`);
messages.push('查询失败,请稍后再试');
// 恢复原来的 this.e
this.e = originalE;
return messages;
}
// 检查式舆防卫战
try {
const abyssRawData = await api.getFinalData('zzzChallenge', { deviceFp });
if (!abyssRawData || !abyssRawData.has_data) {
messages.push('式舆防卫战S评级: 0/7');
} else {
const abyssData = new ZZZChallenge(abyssRawData);
const userThreshold = userConfig.abyssCheckLevel || 7;
if (showAll || !abyssData.areAllSUpTo(userThreshold)) {
const sCount = abyssData.getSRankCountUpTo(7);
const status = abyssData.areAllSUpTo(userThreshold) ? ' ✓' : '';
messages.push(`式舆防卫战S评级: ${sCount}/7${status}`);
}
}
} catch (error) {
logger.error(`[ZZZ-Plugin] 为用户 ${userId} 检查式舆防卫战失败: ${error}`);
messages.push(`式舆防卫战查询失败: ${error}`);
}
// 检查危局强袭战
try {
const deadlyRawData = await api.getFinalData('zzzDeadly', { deviceFp });
if (!deadlyRawData || !deadlyRawData.has_data) {
messages.push('危局强袭战星星: 0/9');
} else {
const deadlyData = new Deadly(deadlyRawData);
if (showAll || deadlyData.total_star < userConfig.deadlyStars) {
const status = deadlyData.total_star >= userConfig.deadlyStars ? ' ✓' : '';
messages.push(`危局强袭战星星: ${deadlyData.total_star}/9${status}`);
}
}
} catch (error) {
logger.error(`[ZZZ-Plugin] 为用户 ${userId} 检查危局强袭战失败: ${error}`);
messages.push(`危局强袭战查询失败: ${error}`);
}
// 恢复原来的 this.e
this.e = originalE;
return messages;
}
async runTask() {
const globalRemindConfig = settings.getConfig('remind');
if (!globalRemindConfig.enable) {
return;
}
logger.info('[ZZZ-Plugin] 开始执行式舆防卫战/危局强袭战提醒任务');
const allUserConfigs = await redis.hGetAll(USER_CONFIGS_KEY);
const now = new Date();
const globalRemindTime = globalRemindConfig.globalRemindTime || '每日20时';
for (const userId in allUserConfigs) {
const userConfig = JSON.parse(allUserConfigs[userId]);
if (!userConfig.enable) continue;
const remindTime = userConfig.remindTime || globalRemindTime;
if (this.isTimeMatch(remindTime, now)) {
// 创建一个模拟的 e 对象,用于获取 API
const mockE = {
user_id: userId,
game: 'zzz',
reply: (msg) => logger.info(`[Remind Mock Reply] ${msg}`)
};
const messages = await this.checkUser(userId, userConfig, false, mockE);
if (messages.length > 0) {
await Bot.pickFriend(userId).sendMsg(messages.join('\n'));
}
}
}
logger.info('[ZZZ-Plugin] 式舆防卫战/危局强袭战提醒任务执行完毕');
}
async setMyRemindTime() {
const match = this.e.msg.match(/设置个人提醒时间\s*(每日\d+时(?:(\d+)分)?|每周.\d+时(?:(\d+)分)?)/);
if (!match) return;
const remindTime = match[1];
const minute = Number(match[2]) || Number(match[3]) || 0;
// 验证分钟格式
if (minute % 10 !== 0 || minute < 0 || minute >= 60) {
await this.reply('分钟必须为整十分钟');
return;
}
let userConfig = await this.getUserConfig(this.e.user_id);
if (!userConfig) {
const defaultConfig = settings.getConfig('remind');
userConfig = {
enable: false,
abyssCheckLevel: defaultConfig.abyssCheckLevel,
deadlyStars: defaultConfig.deadlyStars,
};
}
userConfig.remindTime = remindTime;
await this.setUserConfig(this.e.user_id, userConfig);
await this.reply(`您的个人提醒时间已设置为: ${remindTime}`);
}
async viewMyRemindTime() {
const userConfig = await this.getUserConfig(this.e.user_id);
if (userConfig && userConfig.remindTime) {
await this.reply(`当前提醒时间: ${userConfig.remindTime}`);
} else {
const remindConfig = settings.getConfig('remind');
const globalRemindTime = remindConfig.globalRemindTime || '每日20时';
await this.reply(`个人提醒时间未设置,默认使用全局时间: ${globalRemindTime}`);
}
}
async deleteMyRemindTime() {
let userConfig = await this.getUserConfig(this.e.user_id);
if (userConfig && userConfig.remindTime) {
delete userConfig.remindTime;
await this.setUserConfig(this.e.user_id, userConfig);
await this.reply('个人提醒时间已取消');
} else {
await this.reply('个人提醒时间尚未设置');
}
}
async setGlobalRemindTime() {
if (!this.e.isMaster) {
this.reply('仅限主人设置', false, { at: true, recallMsg: 100 });
return false;
}
const match = this.e.msg.match(/设置全局提醒时间\s*(每日\d+时(?:(\d+)分)?)|每周.\d+时(?:(\d+)分)?))/);
if (!match) return;
const globalRemindTime = match[1];
const minute = Number(match[2]) || Number(match[3]) || 0;
// 验证分钟格式
if (minute % 10 !== 0 || minute < 0 || minute >= 60) {
await this.reply('分钟必须为整十分钟');
return;
}
settings.setSingleConfig('remind', 'globalRemindTime', globalRemindTime);
await this.reply(`全局提醒时间已更新为: ${globalRemindTime}`);
}
async viewGlobalRemindTime() {
const globalRemindTime = settings.getConfig('remind').globalRemindTime || '每日20时';
await this.reply(`当前全局提醒时间: ${globalRemindTime}`);
}
}