Minayotan/src/modules/poll/index.ts

146 lines
6.1 KiB
TypeScript
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 autobind from 'autobind-decorator';
import Message from '@/message';
import Module from '@/module';
import serifs from '@/serifs';
import { genItem } from '../../vocabulary';
import config from '../../config';
import { Note } from '../../misskey/note';
export default class extends Module {
public readonly name = 'poll';
@autobind
public install() {
setInterval(() => {
if (Math.random() < 0.1) {
this.post();
}
}, 1000 * 60 * 60);
return {
mentionHook: this.mentionHook,
timeoutCallback: this.timeoutCallback,
};
}
@autobind
private async post() {
const duration = 1000 * 60 * 30;
const polls = [ // TODO: Extract serif
['珍しそうなもの', 'みなさんは、どれがいちばん珍しいと思いますか?'],
['美味しそうなもの', 'みなさんは、どれがいちばん美味しいと思いますか?'],
['重そうなもの', 'みなさんは、どれがいちばん重いと思いますか?'],
['欲しいもの', 'みなさんは、どれがいちばん欲しいですか?'],
['無人島に持っていきたいもの', 'みなさんは、無人島にひとつ持っていけるとしたらどれにしますか?'],
['家に飾りたいもの', 'みなさんは、家に飾るとしたらどれにしますか?'],
['売れそうなもの', 'みなさんは、どれがいちばん売れそうだと思いますか?'],
['降ってきてほしいもの', 'みなさんは、どれが空から降ってきてほしいですか?'],
['携帯したいもの', 'みなさんは、どれを携帯したいですか?'],
['商品化したいもの', 'みなさんは、商品化するとしたらどれにしますか?'],
['発掘されそうなもの', 'みなさんは、遺跡から発掘されそうなものはどれだと思いますか?'],
['良い香りがしそうなもの', 'みなさんは、どれがいちばんいい香りがすると思いますか?'],
['高値で取引されそうなもの', 'みなさんは、どれがいちばん高値で取引されると思いますか?'],
['地球周回軌道上にありそうなもの', 'みなさんは、どれが地球周回軌道上を漂っていそうだと思いますか?'],
['プレゼントしたいもの', 'みなさんは、私にプレゼントしてくれるとしたらどれにしますか?'],
['プレゼントされたいもの', 'みなさんは、プレゼントでもらうとしたらどれにしますか?'],
['私が持ってそうなもの', 'みなさんは、私が持ってそうなものはどれだと思いますか?'],
['流行りそうなもの', 'みなさんは、どれが流行りそうだと思いますか?'],
['朝ごはん', 'みなさんは、朝ごはんにどれが食べたいですか?'],
['お昼ごはん', 'みなさんは、お昼ごはんにどれが食べたいですか?'],
['お夕飯', 'みなさんは、お夕飯にどれが食べたいですか?'],
['体に良さそうなもの', 'みなさんは、どれが体に良さそうだと思いますか?'],
['後世に遺したいもの', 'みなさんは、どれを後世に遺したいですか?'],
['楽器になりそうなもの', 'みなさんは、どれが楽器になりそうだと思いますか?'],
['お味噌汁の具にしたいもの', 'みなさんは、お味噌汁の具にするとしたらどれがいいですか?'],
['ふりかけにしたいもの', 'みなさんは、どれをごはんにふりかけたいですか?'],
['よく見かけるもの', 'みなさんは、どれをよく見かけますか?'],
['道に落ちてそうなもの', 'みなさんは、道端に落ちてそうなものはどれだと思いますか?'],
['美術館に置いてそうなもの', 'みなさんは、この中で美術館に置いてありそうなものはどれだと思いますか?'],
['教室にありそうなもの', 'みなさんは、教室にありそうなものってどれだと思いますか?'],
['絵文字になってほしいもの', '絵文字になってほしいものはどれですか?'],
['Misskey本部にありそうなもの', 'みなさんは、Misskey本部にありそうなものはどれだと思いますか'],
['燃えるゴミ', 'みなさんは、どれが燃えるゴミだと思いますか?'],
['そして輝くウルトラ', 'みなさんは、そして輝くウルトラ…?'],
];
const poll = polls[Math.floor(Math.random() * polls.length)];
const choices = poll[0] === 'そして輝くウルトラ' ? [
'そう',
'どちらかというとそう',
'どちらでもない',
'どちらかというとそうではない',
'そうではない',
'わからない・回答しない',
] : [
genItem(),
genItem(),
genItem(),
genItem(),
];
const note = await this.ai.post({
text: poll[1],
poll: {
choices,
expiredAfter: duration,
multiple: false,
}
});
// タイマーセット
this.setTimeoutWithPersistence(duration + 3000, {
title: poll[0],
noteId: note.id,
});
}
@autobind
private async mentionHook(msg: Message) {
if (!msg.or(['/poll']) || msg.user.username !== config.master) {
return false;
} else {
this.log('Manualy poll requested');
}
this.post();
return true;
}
@autobind
private async timeoutCallback({ title, noteId }) {
const note: Note = await this.ai.api('notes/show', { noteId });
const choices = note.poll!.choices;
let mostVotedChoice;
for (const choice of choices) {
if (mostVotedChoice == null) {
mostVotedChoice = choice;
continue;
}
// TODO: 同数一位のハンドリング
if (choice.votes > mostVotedChoice.votes) {
mostVotedChoice = choice;
}
}
if (mostVotedChoice.votes === 0) {
this.ai.post({ // TODO: Extract serif
text: '投票はありませんでした',
renoteId: noteId,
});
} else {
this.ai.post({ // TODO: Extract serif
cw: `${title}アンケートの結果発表です!`,
text: `結果は${mostVotedChoice.votes}票を獲得した「${mostVotedChoice.text}」でした!`,
renoteId: noteId,
});
}
}
}