node-mirai-fgo-gacha
Version:
node-mirai-sdk fgo gacha plugin
194 lines (185 loc) • 7.48 kB
JavaScript
const fs = require('fs');
const path = require('path');
const Mirai = require('node-mirai-sdk');
const { At, Image, Plain } = Mirai.MessageComponent;
const init = require('./init');
const gacha = require('./src/gacha');
const generateGachaPng = require('./src/generateGachaPng');
if (!fs.existsSync(path.resolve(process.cwd(), '.fgo-gacha/.init'))) {
init(true, true);
}
const dbPath = path.resolve(process.cwd(), '.fgo-gacha/statics/db.json');
const poolsPath = path.resolve(process.cwd(), '.fgo-gacha/statics/pools.json');
const db = JSON.parse(fs.readFileSync(dbPath));
const saveDb = () => {
fs.writeFileSync(dbPath, JSON.stringify(db));
};
const _onUpdated = [];
/**
* @method FGOGacha
* @description NodeMiraiSDK FGO Gacha plugin
* @param { object } config
* @param { number } [config.cooldown] (ms, default: 60000) gacha cooldown
* @param { boolean } [config.allowGroup] (default: true) allow gacha in group chatting
* @param { boolean } [config.allowPrivate] (default: false) allow gacha in private chatting
* @param { boolean } [config.recall] (default: true) recall result or not
* @param { number } [config.recallDelay] (default: 30000) recall delay
* @param { string } [config.prefix] (default: '') command prefix
* @param { boolean } [config.groupWhitelistMode] use whitelist mode for specific group
* @param { array } [config.groupBlacklist] blacklist groups
* @param { array } [config.groupWhitelist] whitelist groups
* @param { boolean } [config.qqWhitelistMode] use whitelist mode for specific qq
* @param { array } [config.qqBlacklist] blacklist qqs
* @param { array } [config.qqWhitelist] whitelist qqs
* @param { array } [config.superAdmin] super admin list
* @param { object } [config.hints] hint texts
* @param { string } [config.hints.gacha] hint for 召唤结果
* @param { string } [config.hints.listPools] hint for 查询卡池
* @param { string } [config.hints.invalidPoolId] hint for 设置卡池 getting invalid poolid
* @param { string } [config.hints.setPoolSuccess] hint for 设置卡池 success
* @param { string } [config.hints.poolNotSet]
* @param { string } [config.hints.inCooldown]
* @param { string } [config.hints.permissionError]
*/
const FGOGacha = ({
cooldown = 60000,
allowGroup = true,
allowPrivate = false,
recall = true,
recallDelay = 30000,
prefix = '',
groupWhitelistMode = false,
groupBlacklist = [],
groupWhitelist = [],
qqWhitelistMode = false,
qqBlacklist = [],
qqWhitelist = [],
superAdmin = [],
hints: {
gacha: gachaHint = '本次召唤结果',
listPools: listPools = '现在数据库里有这些卡池哦~',
invalidPoolId: invalidPoolId = '卡池编号不正确哦~',
setPoolSuccess: setPoolSuccess = '设置卡池成功',
poolNotSet: poolNotSet = `尚未设置卡池,无法进行召唤`,
inCooldown: inCooldown = `召唤冷却中,每${cooldown / 1000}秒可进行一次召唤`,
permissionError: permissionError = '权限不足',
} = {},
} = {}) => {
const gachaCooldown = {};
if (recallDelay < 5000) recallDelay = 5000;
else if (recallDelay > 60000) recallDelay = 60000;
const isAdmin = sender => sender.permission === 'ADMINISTRATOR' || sender.permission === 'OWNER' || superAdmin.includes(sender.id);
/**
* @method callback
* @param { object } message message object
* @param { Mirai } bot bot instance
*/
const callback = async (message, bot) => {
const { sender, messageChain, reply } = message;
const { group } = sender;
if (qqWhitelistMode) {
if (!qqWhitelist.includes(sender.id)) return;
}
if (qqBlacklist.includes(sender.id)) return;
if (group && groupWhitelistMode) {
if (!groupWhitelist.includes(group.id)) return;
}
if (group && groupBlacklist.includes(group.id)) return;
if (!db.group) db.group = {};
if (!db.sender) db.sender = {};
if (!group && !allowPrivate) return;
if (group && !allowGroup) return;
if (group) {
if (!db.group[group.id]) db.group[group.id] = {};
if (!gachaCooldown[group.id]) gachaCooldown[group.id] = [];
} else {
if (!db.sender[sender.id]) db.sender[sender.id] = {};
}
let msg = '';
messageChain.forEach(chain => {
if (chain.type === 'Plain') msg += Plain.value(chain);
});
msg = msg.trim();
if (!msg.startsWith(prefix)) return;
if (msg === prefix + '更新') {
if (superAdmin.includes(sender.id)) {
reply(`开始更新卡池信息`);
await init().then(() => reply(`更新成功`))
.catch(() => reply(`更新出错,请检查log`));
_onUpdated.forEach(fn => fn());
} else reply(permissionError);
}
if (msg === prefix + '查询卡池') {
const pools = JSON.parse(fs.readFileSync(poolsPath));
return reply(
listPools + '\n' +
pools.map((i, index) => `${index + 1}. ${i.title}`).join('\n') +
`\n发送“${prefix}设置卡池 编号”可以设置召唤的卡池`
);
}
if (msg.startsWith(prefix + '设置卡池')) {
if (!isAdmin(sender)) return reply(permissionError);
const poolId = parseInt(msg.substr(prefix.length + 4));
if (isNaN(poolId)) return reply(invalidPoolId + `发送"${prefix}查询卡池"可以查询已有卡池`);
if (poolId > gacha.poolCounts || poolId < 1) return reply(invalidPoolId + `发送"${prefix}查询卡池"可以查询已有卡池`);
if (group) {
db.group[group.id].selectedPool = poolId;
} else {
db.sender[sender.id].selectedPool = poolId;
}
saveDb();
return reply(setPoolSuccess);
}
if (msg === prefix + '十连召唤' || msg === prefix + '十一连召唤' || msg === prefix + '百连召唤') {
if (group && gachaCooldown[group.id].includes(sender.id)) return reply(inCooldown);
const total = msg === prefix + '百连召唤' ? 100 : (prefix + '十一连召唤' ? 11 : 10);
const poolId = group ? db.group[group.id].selectedPool : db.sender[sender.id].selectedPool;
if (!poolId) return reply(poolNotSet + `发送"${prefix}设置卡池 编号"可以设置卡池`);
const result = gacha(poolId, total);
if (group) gachaCooldown[group.id].push(sender.id);
const imgPath = await generateGachaPng(result);
// let replyMsg = await bot.sendImageMessage(imgPath, message);
const img = await bot.uploadImage(imgPath, message);
const replyMsg = await reply([At(sender.id), Plain(gachaHint + '\n'), Image(img)]);
if (!replyMsg.messageId) {
console.log('[FGOGacha] Unknown error @ sending gacha result');
}
if (group) {
setTimeout(() => {
gachaCooldown[group.id].shift();
}, cooldown);
if (recall && replyMsg.messageId) {
setTimeout(() => {
bot.recall(replyMsg);
}, recallDelay);
}
}
return fs.unlinkSync(imgPath);
}
};
return {
name: 'NodeMiraiFgoGacha',
subscribe: 'message',
callback,
};
};
/**
* @method update
* @description 普通的更新一下
* @returns { Promise }
*/
FGOGacha.update = () => init();
/**
* @method init
* @description 强制初始化
* @returns { Promise }
*/
FGOGacha.init = () => init(true, true);
/**
* @method updated
* @description 更新后触发回调
* @param { Function } callback 回调
* @returns { void }
*/
FGOGacha.updated = callback => _onUpdated.push(callback);
module.exports = FGOGacha;