UNPKG

koishi-plugin-hangman

Version:
127 lines (126 loc) 5.28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.apply = exports.Config = exports.name = void 0; const koishi_1 = require("koishi"); const path_1 = require("path"); exports.name = 'hangman'; exports.Config = koishi_1.Schema.object({ chances: koishi_1.Schema.number().default(10).description('允许猜测的最大次数。'), wordList: koishi_1.Schema.string().description('存储单词表的文件路径。').hidden(process.env.KOISHI_ENV === 'browser'), submission: koishi_1.Schema.union([ koishi_1.Schema.const('strict').description('只接受指令输入'), koishi_1.Schema.const('loose').description('允许直接输入答案文本'), koishi_1.Schema.const('mention').description('仅在私聊或被提及时接受直接输入'), ]).role('radio').description('答案提交方式。').default('mention'), }); function Word(word) { if (typeof word !== 'string') return word; return { text: word }; } function apply(ctx, config) { function getWordList() { if (process.env.KOISHI_ENV === 'browser' || !config.wordList) { return require('../words.json'); } else { const filename = (0, path_1.resolve)(ctx.baseDir, config.wordList); return require(filename); } } const wordList = getWordList(); const stages = Object.create(null); ctx.i18n.define('zh-CN', require('./locales/zh-CN')); ctx.middleware(async (session, next) => { const state = stages[session.cid]; if (!state || config.submission === 'strict') return next(); const { content, atSelf } = session.stripped; if (!session.isDirect && !atSelf && config.submission !== 'loose') return next(); if (!/^[a-z]+$/i.test(content)) return next(); return session.execute({ name: 'hangman', args: [content], }); }); ctx.command('hangman [letter:string]') .alias('hang') .alias('吊死鬼') .option('quit', '-q', { notUsage: true }) .action(async ({ session, options }, letters = '') => { const id = session.cid; if (!stages[id]) { if (letters.length || options.quit) { return session.text('.idle'); } const word = Word(koishi_1.Random.pick(wordList)); const current = '?'.repeat(word.text.length); stages[id] = { ...word, current, history: '', chances: config.chances }; const output = [session.text('.start', [current])]; ctx.emit(session, 'hangman/start', stages[id], output); return output.join('\n'); } const { chances: _chances, history: _history, text } = stages[id]; if (options.quit) { const output = [session.text('.stop')]; ctx.emit(session, 'hangman/stop', stages[id], output); delete stages[id]; return output.join('\n'); } if (!letters.length) { if (_history) { return session.text('.history', stages[id]); } else { return session.text('.history-clean', stages[id]); } } for (const letter of letters.toLowerCase()) { if (letter < 'a' || letter > 'z' || stages[id].history.includes(letter)) continue; const history = stages[id].history += letter; if (text.includes(letter)) { const current = stages[id].current = text.split('').map(c => history.includes(c) ? c : '?').join(''); if (current === text) { const answer = session.text('.answer', stages[id]); const output = [session.text('.win', [answer, session.username])]; delete stages[id]; ctx.emit(session, 'hangman/win', stages[id], output); return output.join('\n'); } } else { if (!(stages[id].chances -= 1)) { const answer = session.text('.answer', stages[id]); const output = [session.text('.lose', [answer, session.username])]; delete stages[id]; ctx.emit(session, 'hangman/lose', stages[id], output); return output.join('\n'); } } } const { chances, history } = stages[id]; const charCount = history.length - _history.length; if (!charCount) { if (letters.match(/[a-zA-Z]/)) { return session.text('.char-used'); } else { return session.text('.char-invalid'); } } if (_chances - chances === charCount) { const output = [session.text('.wrong', stages[id])]; ctx.emit(session, 'hangman/wrong', stages[id], output); return output.join('\n'); } else { const output = [session.text('.right', stages[id])]; ctx.emit(session, 'hangman/right', stages[id], output); return output.join('\n'); } }); } exports.apply = apply;