3
0

v0.3.5 支持原神猜语音小游戏

This commit is contained in:
xtaodada 2022-01-29 17:52:00 +08:00
parent bf1ff94f00
commit cbc3897bbd
No known key found for this signature in database
GPG Key ID: EE4DC37B55E24736
7 changed files with 448 additions and 9 deletions

198
assets/voice/character.json Normal file
View File

@ -0,0 +1,198 @@
{
"神里绫华": [
"神里",
"758"
],
"迪卢克": [
"计量单位",
"迪卢克",
"卢老爷",
"卢姥爷",
"卢锅巴",
"正义人",
"暗夜英雄"
],
"七七": [
"77",
"肚饿真君",
"度厄真君",
"四十九",
"49"
],
"丽莎": [
"图书管理员"
],
"凝光": [
"富婆",
"天权星"
],
"刻晴": [
"刻师傅",
"玉衡星",
"屁斜剑法",
"啊晴"
],
"可莉": [
"kelee",
"蹦蹦八个蛋",
"火花骑士",
"炸鱼禁闭真君",
"哒哒哒"
],
"旅行者": [
"爷",
"卑鄙的外乡人",
"荣誉骑士"
],
"枫原万叶": [
"万叶",
"风男"
],
"温迪": [
"诶嘿",
"卖唱的",
"巴巴托斯",
"风神"
],
"烟绯": [
"璃月罗翔"
],
"班尼特": [
"点赞",
"六星战神",
"点赞哥"
],
"琴": [
"代理团长",
"蒙德砍王",
"琴团长"
],
"砂糖": [
"雷莹术士"
],
"胡桃": [
"往生堂堂主",
"堂主",
"核桃",
"胡堂主"
],
"芭芭拉": [
"内鬼",
"加湿器",
"偶像"
],
"莫娜": [
"半部讨龙真君"
],
"菲谢尔": [
"艾咪",
"小艾咪",
"皇女",
"奥兹发射器"
],
"行秋": [
"秋妹妹"
],
"达达利亚": [
"钱包",
"ATM机",
"达达鸭",
"公子",
"达达利鸭"
],
"迪奥娜": [
"猫猫",
"猫娘",
"DIO娜",
"dio"
],
"重云": [
"冰元素附魔器"
],
"钟离": [
"帝君",
"未来可期真君",
"社会废人",
"契约之神",
"七天神像的噩梦",
"岩王帝君",
"岩王爷"
],
"雷泽": [
"狼崽"
],
"香菱": [
"锅巴发射器",
"香师傅"
],
"魈": [
"快乐风男",
"打桩机",
"降魔大圣",
"护法夜叉大将",
"魈大人"
],
"阿贝多": [
"电梯人",
"白垩之子",
"abd"
],
"甘雨": [
"王小美",
"椰羊"
],
"优菈": [
"游击小队队长",
"尤拉"
],
"北斗": [
"大姐头"
],
"安柏": [
"打火姬",
"侦察骑士"
],
"凯亚": [
"凯子",
"凯子哥",
"矿工头子"
],
"诺艾尔": [
"冰莹术士",
"女仆"
],
"辛焱": [
"黑妹"
],
"罗莎莉亚": [
"修女"
],
"留云借风真君": [
"傲娇真君"
],
"雷电将军": [
"雷神",
"将军"
],
"珊瑚宫心海": [
"心海"
],
"戴因斯雷布": [
"大派蒙"
],
"丘丘人":[
"qq人"
],
"???": [
""
],
"「愚人众」守卫": [
"愚人众守卫"
],
"「怪鸟」": [
"怪鸟"
],
"观察「大盗宝家」":[
"大盗宝家"
]
}

1
ci.py
View File

@ -9,6 +9,7 @@ bot_token: str = ""
admin_id: int = 0 admin_id: int = 0
bot_token = config.get("basic", "bot_token", fallback=bot_token) bot_token = config.get("basic", "bot_token", fallback=bot_token)
admin_id = config.getint("basic", "admin", fallback=admin_id) admin_id = config.getint("basic", "admin", fallback=admin_id)
guess_time = 30 # 猜语音游戏持续时间
""" Init httpx client """ """ Init httpx client """
# 使用自定义 UA # 使用自定义 UA
headers = { headers = {

192
defs/guess_voice.py Normal file
View File

@ -0,0 +1,192 @@
import os
import random
import datetime
import json
import traceback
from os.path import exists
from apscheduler.triggers.date import DateTrigger
from pyrogram import Client
from pyrogram.types import Message
from sqlitedict import SqliteDict
from ci import scheduler, app
data_path = os.path.join("assets", "voice")
def init_db(db_dir, db_name) -> SqliteDict:
return SqliteDict(os.path.join(db_dir, db_name),
encode=json.dumps,
decode=json.loads,
autocommit=True)
def get_chars(data: list) -> list:
data_ = []
for i in data:
char_name = i.split(" ")[0]
if char_name not in data_:
data_.append(i.split(" ")[0])
return data_
def get_key_list(data: list, key: str) -> list:
# 获取包含key的数据
data_ = []
for i in data:
if key in i:
data_.append(i)
return data_
def choice_voice(data: list) -> str:
long_key = ['感兴趣的见闻', '关于神之眼', '生日', '爱好', '讨厌的食物', '想要了解', '有什么想要分享',
'突破的感觉', '喜欢的食物', '烦恼', '角色待机', '角色死亡']
data_ = []
for i in data:
for k in long_key:
if k in i:
data_.append(i)
if not data_:
return ""
return random.choice(data_)
user_db = init_db('temp', 'guess_voice.sqlite')
process = {}
with open(os.path.join(data_path, 'character.json'), 'r', encoding="utf-8") as f:
character_json: dict = json.loads(f.read())
def char_name_by_name(name):
names = character_json.keys()
# 是否就是正确的名字
if name in names:
return name
#
for item in names:
nickname = character_json[item]
if name in nickname:
return item
return name
class Guess:
time: int
group_id: int
group = {}
retry_count = 0
def __init__(self, group_id: int, time=30):
self.time = time
self.group_id = group_id
self.group = process.get(self.group_id)
def is_start(self):
if not self.group:
return False
return self.group['start']
def set_start(self):
process[self.group_id] = {'start': True}
def set_end(self):
process[self.group_id] = {}
async def start(self):
if exists(f"assets{os.sep}voice{os.sep}voice.json"):
with open(f"assets{os.sep}voice{os.sep}voice.json", "r", encoding='utf-8') as f:
mys_list_raw = json.load(f)
else:
return "没有找到声音数据"
mys_list = list(mys_list_raw.keys())
if not mys_list:
return "没有找到声音数据"
chars = get_chars(mys_list)
answer = random.choice(chars)
file_id = get_key_list(mys_list, answer)
file_id = choice_voice(file_id)
if not file_id:
return "没有找到声音数据"
# 记录答案
process[self.group_id] = {
'start': True,
'answer': answer,
'ok': set()
}
job_id = str(self.group_id) + '_guess_voice'
if scheduler.get_job(job_id, 'default'):
scheduler.remove_job(job_id, 'default')
now = datetime.datetime.now()
notify_time = now + datetime.timedelta(seconds=self.time)
scheduler.add_job(self.end_game, trigger=DateTrigger(notify_time),
id=job_id,
misfire_grace_time=60,
coalesce=True,
jobstore='default',
max_instances=1)
print('答案: ' + answer)
return mys_list_raw[file_id]
async def end_game(self):
self.group = process.get(self.group_id)
ok_list = list(process[self.group_id]['ok'])
if len(ok_list) > 1: # 只允许1个人猜对
return
if not ok_list:
msg = '还没有人猜中呢'
else:
msg = '回答正确的人: ' + ' '.join([f"[{qq}](tg://user?id={qq})" for qq in ok_list])
msg = '正确答案是 %s\n%s' % (self.group['answer'], msg)
try:
await app.send_message(self.group_id, msg)
except Exception as e:
traceback.print_exc()
# 清理记录
process[self.group_id] = {}
# 记录到数据库给之后奖励做处理
user_group = user_db.get(self.group_id, {})
if not user_group:
user_db[self.group_id] = {}
for user in ok_list:
info = user_group.get(str(user), {'count': 0})
info['count'] += 1
user_group[user] = info
user_db[self.group_id] = user_group
# 只添加正确的答案
async def add_answer(self, qq: int, msg: str):
if self.group.get('answer') and char_name_by_name(msg) == self.group['answer']:
process[self.group_id]['ok'].add(qq)
job_id = str(self.group_id)
if scheduler.get_job(job_id + '_guess_voice', 'default'):
scheduler.remove_job(job_id + '_guess_voice', 'default')
await self.end_game()
# 获取排行榜
async def get_rank(self, client: Client, message: Message):
user_list = user_db.get(self.group_id, {})
user_list = sorted(user_list.items(), key=lambda v: v[1]['count'])
user_list.reverse()
num = 0
msg = '本群猜语音排行榜:'
for user, data in user_list[:10]:
try:
user = (await client.get_users(int(user))).first_name
except:
user = str(user)
num += 1
msg += f"\n{num}名: {user}, 猜对{data['count']}"
return msg

32
plugins/guess_voice.py Normal file
View File

@ -0,0 +1,32 @@
from pyrogram import Client
from pyrogram.types import Message
from ci import guess_time
from defs.guess_voice import Guess
async def guess_voice(client: Client, message: Message):
text = message.text.replace("原神猜语音", "")
guess = Guess(message.chat.id, time=guess_time)
if text == "排行榜":
return await message.reply(await guess.get_rank(client, message))
if guess.is_start():
return await message.reply('游戏正在进行中哦')
guess.set_start()
await message.reply(f'即将发送一段原神语音,将在 <b>{guess_time}秒</b> 后公布答案')
try:
msg = await guess.start()
if msg == "没有找到声音数据":
await message.reply(msg)
else:
await client.send_voice(message.chat.id, msg)
except Exception as e:
guess.set_end()
await message.reply("出现未知错误,请联系管理员")
async def process_guess(client: Client, message: Message):
msg = message.text
guess = Guess(message.chat.id, time=guess_time)
if guess.is_start():
await guess.add_answer(message.from_user.id, msg)

View File

@ -7,7 +7,9 @@ from pyrogram.types import Message, InlineQuery, CallbackQuery
from pyrogram import filters as Filters from pyrogram import filters as Filters
from ci import me from ci import me
from defs.guess_voice import get_chars
from plugins.enemies import enemies_msg from plugins.enemies import enemies_msg
from plugins.guess_voice import guess_voice, process_guess
from plugins.mys2 import mys2_msg, mys2_qun_msg from plugins.mys2 import mys2_msg, mys2_qun_msg
from plugins.mihoyo import mihoyo_msg, mihoyo_qun_msg from plugins.mihoyo import mihoyo_msg, mihoyo_qun_msg
from plugins.start import welcome_command, ping_command, help_command, leave_command, help_callback from plugins.start import welcome_command, ping_command, help_command, leave_command, help_callback
@ -192,6 +194,10 @@ async def process_group_msg(client: Client, message: Message):
await mys2_qun_msg(client, message) await mys2_qun_msg(client, message)
if text.startswith('mihoyo'): if text.startswith('mihoyo'):
await mihoyo_qun_msg(client, message) await mihoyo_qun_msg(client, message)
if text.startswith("原神猜语音"):
await guess_voice(client, message)
# 处理猜语音游戏
await process_guess(client, message)
@Client.on_message(Filters.photo) @Client.on_message(Filters.photo)
@ -247,6 +253,7 @@ voice_data = None
if exists(f"assets{sep}voice{sep}voice.json"): if exists(f"assets{sep}voice{sep}voice.json"):
with open(f"assets{sep}voice{sep}voice.json", "r", encoding='utf-8') as f: with open(f"assets{sep}voice{sep}voice.json", "r", encoding='utf-8') as f:
voice_data = json.load(f) voice_data = json.load(f)
chara_count = len(get_chars(voice_data))
@Client.on_inline_query() @Client.on_inline_query()
@ -257,10 +264,15 @@ async def inline_process(client: Client, query: InlineQuery):
if not voice_data: if not voice_data:
return return
data_ = voice_data data_ = voice_data
data__ = []
for index, value in enumerate(data_): for index, value in enumerate(data_):
if len(text) == 0: if len(text) == 0:
chara_name = value.split(" ")[0]
if chara_name in data__:
continue
data.append(InlineQueryResultCachedDocument(value, file_id=data_[value], caption=value)) data.append(InlineQueryResultCachedDocument(value, file_id=data_[value], caption=value))
nums += 1 nums += 1
data__.append(chara_name)
else: else:
skip = False skip = False
for i in text: for i in text:
@ -269,12 +281,14 @@ async def inline_process(client: Client, query: InlineQuery):
if not skip: if not skip:
data.append(InlineQueryResultCachedDocument(value, file_id=data_[value], caption=value)) data.append(InlineQueryResultCachedDocument(value, file_id=data_[value], caption=value))
nums += 1 nums += 1
if nums >= 25: if nums >= 30:
break break
if nums == 0: if nums == 0:
return await query.answer( return await query.answer(
results=[], results=[],
switch_pm_text=f'{emoji.CROSS_MARK} 字符串 "{" ".join(text)}" 没有搜索到任何结果', switch_pm_text=f'{emoji.CROSS_MARK} 字符串 "{" ".join(text)}" 没有搜索到任何结果',
switch_pm_parameter="start", switch_pm_parameter="help",
) )
await query.answer(data) await query.answer(data,
switch_pm_text=f'{emoji.KEY} 目前已经索引了 {chara_count} 个角色',
switch_pm_parameter="help",)

View File

@ -2,7 +2,7 @@ from ci import admin_id
from pyrogram import Client from pyrogram import Client
from pyrogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton from pyrogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
HELP_MSG_PRE = '<a href="https://git.io/JcbTD">PaimonBot</a> 0.3.4beta By Xtao-Labs\n\n' \ HELP_MSG_PRE = '<a href="https://git.io/JcbTD">PaimonBot</a> 0.3.5beta By Xtao-Labs\n\n' \
'🔅 以下是小派蒙我学会了的功能(部分):\n' '🔅 以下是小派蒙我学会了的功能(部分):\n'
HELP_MSG = """① [武器/今日武器] 查看今日武器材料和武器 HELP_MSG = """① [武器/今日武器] 查看今日武器材料和武器
[天赋/今日天赋] 查看今日天赋材料和角色 [天赋/今日天赋] 查看今日天赋材料和角色
@ -16,11 +16,11 @@ HELP_MSG = """① [武器/今日武器] 查看今日武器材料和武器
💠 <code>命座 重云一命</code> 💠 <code>命座 重云一命</code>
[武器查询 武器名] 查看武器资料 [武器查询 武器名] 查看武器资料
💠 <code>武器查询 沐浴龙血的剑</code> 💠 <code>武器查询 沐浴龙血的剑</code>
[原魔查询] 查看原魔资料 [原魔查询 原魔名] 查看原魔资料
💠 <code>原魔查询 丘丘人</code> 💠 <code>原魔查询 丘丘人</code>
[食物查询] 查看食物资料 [食物查询 食物/食材名] 查看食物资料
💠 <code>食物查询 甜甜花/甜甜花酿鸡</code> 💠 <code>食物查询 甜甜花/甜甜花酿鸡</code>
[圣遗物查询 武器名] 查看武器资料 [圣遗物查询 圣遗物套装名] 查看圣遗物套装资料
💠 <code>圣遗物查询 逆飞的流星</code> 💠 <code>圣遗物查询 逆飞的流星</code>
====== ======
(11) [原神黄历] 查看随机生成的原神黄历 (11) [原神黄历] 查看随机生成的原神黄历
@ -28,7 +28,8 @@ HELP_MSG = """① [武器/今日武器] 查看今日武器材料和武器
(13) [圣遗物评分] 我也想拥有这种分数的圣遗物(切实) (13) [圣遗物评分] 我也想拥有这种分数的圣遗物(切实)
(14) [哪里有 (资源名)] 查看资源的位置 (14) [哪里有 (资源名)] 查看资源的位置
(15) [资源列表] 查看原神所有资源私聊 (15) [资源列表] 查看原神所有资源私聊
(16) [米游社/mihoyo] 米游社/mihoyo相关功能替换 (16) [原神猜语音] 和群友一起玩猜语音小游戏吧群聊
(17) [米游社/mihoyo] 米游社/mihoyo相关功能替换
💠 <code>米游社添加私聊</code> 💠 <code>米游社添加私聊</code>
💠 <code>米游社推送开启/关闭</code> 💠 <code>米游社推送开启/关闭</code>
💠 <code>米游社自动签到开启/关闭</code> 💠 <code>米游社自动签到开启/关闭</code>

View File

@ -11,4 +11,5 @@ pyyaml>=6.0
httpx>=0.18.1 httpx>=0.18.1
apscheduler>=3.8.1 apscheduler>=3.8.1
wordcloud>=1.8.1 wordcloud>=1.8.1
numpy numpy
sqlitedict