Add files via upload

This commit is contained in:
HibiKier 2021-05-20 19:23:32 +08:00 committed by GitHub
parent 32f303a2c8
commit 7207982a30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 6873 additions and 0 deletions

View File

@ -0,0 +1,174 @@
from nonebot import on_regex, on_keyword
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from .genshin_handle import genshin_draw, update_genshin_info, reset_count
from .prts_handle import update_prts_info, prts_draw, reload_pool
from .pretty_handle import update_pretty_info, pretty_draw
from .update_game_info import update_info
from util.utils import is_number, scheduler
from services.log import logger
import re
prts = on_regex(r'.*?方舟[1-9|一][0-9]{0,2}[抽|井]', priority=5, block=True)
prts_update = on_keyword({'更新方舟信息', '更新明日方舟信息'}, permission=SUPERUSER, priority=1, block=True)
prts_reload = on_keyword({'重载方舟卡池'}, priority=1, block=True)
genshin = on_regex('.*?原神[1-9|一][0-9]{0,2}[抽|井]', priority=5, block=True)
genshin_reset = on_keyword({'重置原神抽卡'}, priority=1, block=True)
genshin_update = on_keyword({'更新原神信息'}, permission=SUPERUSER, priority=1, block=True)
pretty = on_regex('.*?马娘卡?[1-9|一][0-9]{0,2}[抽|井]', priority=5, block=True)
pretty_update = on_keyword({'更新马娘信息', '更新赛马娘信息'}, permission=SUPERUSER, priority=1, block=True)
@prts.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
if msg in ['方舟一井', '方舟1井']:
num = 300
else:
rmsg = re.search(r'.*?方舟(.*)抽', msg)
if rmsg and is_number(rmsg.group(1)):
try:
num = int(rmsg.group(1))
except ValueError:
await prts.finish('必!须!是!数!字!', at_sender=True)
if num > 300:
await prts.finish('一井都满不足不了你嘛!快爬开!', at_sender=True)
if num < 1:
await prts.finish('虚空抽卡???', at_sender=True)
else:
return
# print(num)
await prts.send(await prts_draw(num), at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})"
f" 方舟{num}")
@prts_reload.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await reload_pool()
await prts_reload.finish('重载完成!')
@genshin.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
if msg in ['原神一井', '原神1井']:
num = 180
else:
rmsg = re.search(r'.*?原神(.*)抽', msg)
if rmsg and is_number(rmsg.group(1)):
try:
num = int(rmsg.group(1))
except ValueError:
await genshin.finish('必!须!是!数!字!', at_sender=True)
if num > 300:
await genshin.finish('一井都满不足不了你嘛!快爬开!', at_sender=True)
if num < 1:
await genshin.finish('虚空抽卡???', at_sender=True)
else:
return
await genshin.send(await genshin_draw(event.user_id, num), at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})"
f" 原神{num}")
@genshin_reset.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
reset_count(event.user_id)
await genshin_reset.send('重置了原神抽卡次数', at_sender=True)
@pretty.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = str(event.get_message()).strip()
if msg in ['赛马娘一井', '赛马娘1井', '马娘一井', '马娘1井', '赛马娘卡一井', '赛马娘卡1井', '马娘卡一井', '马娘卡1井']:
num = 200
if msg.find("") == -1:
pool_name = 'horse'
else:
pool_name = 'card'
else:
rmsg = re.search(r'.*?马娘(.*)抽', msg)
if rmsg:
num = rmsg.group(1)
if num[0] == '':
num = num[1:]
pool_name = 'card'
else:
pool_name = 'horse'
if is_number(num):
try:
num = int(num)
except ValueError:
await genshin.finish('必!须!是!数!字!', at_sender=True)
if num > 200:
await genshin.finish('一井都满不足不了你嘛!快爬开!', at_sender=True)
if num < 1:
await genshin.finish('虚空抽卡???', at_sender=True)
else:
return
await pretty.send(await pretty_draw(num, pool_name), at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})"
f" 赛马娘{num}")
@prts_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_prts_info()
await reload_pool()
await prts_update.finish('更新完成!')
@genshin_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_genshin_info()
await genshin_update.finish('更新完成!')
@pretty_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_pretty_info()
await genshin_update.finish('更新完成!')
# 更新资源
@scheduler.scheduled_job(
'cron',
hour=4,
minute=1,
)
async def _():
try:
await update_prts_info()
logger.info('自动更新明日方舟信息')
except Exception as e:
logger.error(f'自动更新明日方舟信息出错 e:{e}')
try:
await update_genshin_info()
logger.info('自动更新原神信息')
except Exception as e:
logger.error(f'自动更新原神信息出错 e:{e}')
try:
await update_pretty_info()
logger.info('自动更新赛马娘信息')
except Exception as e:
logger.error(f'自动更新赛马娘信息出错 e:{e}')
# 每天四点重载up卡池
@scheduler.scheduled_job(
'cron',
hour=4,
minute=1,
)
async def _():
await reload_pool()

View File

@ -0,0 +1,119 @@
import aiohttp
from bs4 import BeautifulSoup
import re
from datetime import datetime
from pathlib import Path
from configs.path_config import DRAW_PATH
from util.user_agent import get_user_agent
try:
import ujson as json
except ModuleNotFoundError:
import json
up_char_file = Path(DRAW_PATH) / "draw_card_up" / "prts_up_char.json"
prts_url = "https://wiki.biligame.com/arknights/%E6%96%B0%E9%97%BB%E5%85%AC%E5%91%8A"
def _get_up_char(r: str, text: str):
pr = re.search(r, text)
chars = pr.group(1)
probability = pr.group(2)
chars = chars.replace('[限定]', '').replace('[', '').replace(']', '')
probability = probability.replace('', '')
return chars, probability
class PrtsAnnouncement:
@staticmethod
async def get_announcement_text():
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(prts_url, timeout=7) as res:
soup = BeautifulSoup(await res.text(), 'lxml')
trs = soup.find('table').find('tbody').find_all('tr')
for tr in trs:
a = tr.find_all('td')[-1].find('a')
if a.text.find('寻访') != -1:
url = a.get('href')
break
async with session.get(f'https://wiki.biligame.com/{url}', timeout=7) as res:
return await res.text(), a.text[:-4]
@staticmethod
async def update_up_char():
up_char_file.parent.mkdir(parents=True, exist_ok=True)
data = {'up_char': {'6': {}, '5': {}, '4': {}}, 'title': '', 'time': ''}
text, title = await PrtsAnnouncement.get_announcement_text()
soup = BeautifulSoup(text, 'lxml')
data['title'] = title
context = soup.find('div', {'id': 'mw-content-text'}).find('div')
data['pool_img'] = str(context.find('div', {'class': 'center'}).find('div').find('a').
find('img').get('srcset')).split(' ')[-2]
# print(context.find_all('p'))
for p in context.find_all('p')[1:]:
if p.text.find('活动时间') != -1:
pr = re.search(r'.*?活动时间:(.*)', p.text)
data['time'] = pr.group(1)
elif p.text.find('★★★★★★') != -1:
chars, probability = _get_up_char(r'.*?★★★★★★:(.*?).*?出率的?(.*?)%.*?.*?', p.text)
slt = '/'
if chars.find('\\') != -1:
slt = '\\'
for char in chars.split(slt):
data['up_char']['6'][char.strip()] = probability.strip()
elif p.text.find('★★★★★') != -1:
chars, probability = _get_up_char(r'.*?★★★★★:(.*?).*?出率的?(.*?)%.*?.*?', p.text)
slt = '/'
if chars.find('\\') != -1:
slt = '\\'
for char in chars.split(slt):
data['up_char']['5'][char.strip()] = probability.strip()
elif p.text.find('★★★★') != -1:
chars, probability = _get_up_char(r'.*?★★★★:(.*?).*?出率的?(.*?)%.*?.*?', p.text)
slt = '/'
if chars.find('\\') != -1:
slt = '\\'
for char in chars.split(slt):
data['up_char']['4'][char.strip()] = probability.strip()
break
pr = re.search(r'.*?★:(.*?)(在(.*?)★.*?以(.*?)倍权值.*?.*?', p.text)
if pr:
char = pr.group(1)
star = pr.group(2)
weight = pr.group(3)
char = char.replace('[限定]', '').replace('[', '').replace(']', '')
data['up_char'][star][char.strip()] = f'{weight}'
# data['time'] = '03月09日16:00 - 05月23日03:59'
if not is_expired(data):
data['title'] = ''
else:
with open(up_char_file, 'w', encoding='utf8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
if not up_char_file.exists():
with open(up_char_file, 'w', encoding='utf8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
else:
with open(up_char_file, 'r', encoding='utf8') as f:
old_data = json.load(f)
if is_expired(old_data):
return old_data
else:
with open(up_char_file, 'w', encoding='utf8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
return data
# 是否过时
def is_expired(data: dict):
times = data['time'].split('-')
for i in range(len(times)):
times[i] = str(datetime.now().year) + '-' + times[i].split('')[0].strip().replace('', '-')
start_date = datetime.strptime(times[0], '%Y-%m-%d').date()
end_date = datetime.strptime(times[1], '%Y-%m-%d').date()
now = datetime.now().date()
return start_date < now < end_date
# ad = Announcement('https://wiki.biligame.com/arknights/%E6%96%B0%E9%97%BB%E5%85%AC%E5%91%8A')
# asyncio.get_event_loop().run_until_complete(check_up_char('prts'))

104
plugins/draw_card/config.py Normal file
View File

@ -0,0 +1,104 @@
import nonebot
from pathlib import Path
try:
import ujson as json
except ModuleNotFoundError:
import json
# 方舟概率
PRTS_SIX_P = 0.02
PRTS_FIVE_P = 0.08
PRTS_FOUR_P = 0.48
PRTS_THREE_P = 0.42
# 原神概率
GENSHIN_FIVE_P = 0.006
GENSHIN_FOUR_P = 0.051
GENSHIN_THREE_P = 0.43
GENSHIN_G_FOUR_P = 0.13
GENSHIN_G_FIVE_P = 0.016
I72_ADD = 0.0585
# 赛马娘概率
PRETTY_THREE = 0.03
PRETTY_TWO = 0.18
PRETTY_ONE = 0.79
path_dict = {
'genshin': '原神',
'prts': '明日方舟',
'pretty': '赛马娘',
}
_draw_config = Path() / "data" / "draw_card" / "draw_card_config" / "draw_card_config.json"
driver: nonebot.Driver = nonebot.get_driver()
@driver.on_startup
def check_config():
global PRTS_SIX_P, PRTS_FOUR_P, PRTS_FIVE_P, PRTS_THREE_P, GENSHIN_G_FIVE_P, \
GENSHIN_G_FOUR_P, GENSHIN_FOUR_P, GENSHIN_FIVE_P, I72_ADD, path_dict, PRETTY_THREE, \
PRETTY_ONE, PRETTY_TWO, GENSHIN_THREE_P
if _draw_config.exists():
data = json.load(open(_draw_config, 'r', encoding='utf8'))
PRTS_SIX_P = float(data['prts']['six'])
PRTS_FIVE_P = float(data['prts']['five'])
PRTS_FOUR_P = float(data['prts']['four'])
PRTS_THREE_P = float(data['prts']['three'])
GENSHIN_FIVE_P = float(data['genshin']['five_char'])
GENSHIN_FOUR_P = float(data['genshin']['four_char'])
GENSHIN_THREE_P = float(data['genshin']['three_char'])
GENSHIN_G_FIVE_P = float(data['genshin']['five_weapon'])
GENSHIN_G_FOUR_P = float(data['genshin']['four_weapon'])
I72_ADD = float(data['genshin']['72_add'])
PRETTY_THREE = float(data['pretty']['three'])
PRETTY_TWO = float(data['pretty']['two'])
PRETTY_ONE = float(data['pretty']['one'])
path_dict = data['path_dict']
else:
_draw_config.parent.mkdir(parents=True, exist_ok=True)
config_dict = {
'path_dict': {
'genshin': '原神',
'prts': '明日方舟',
'pretty': '赛马娘',
},
'prts': {
'six': 0.02,
'five': 0.08,
'four': 0.48,
'three': 0.42,
},
'genshin': {
'five_char': 0.006,
'four_char': 0.051,
'three_char': 0.43,
'five_weapon': 0.13,
'four_weapon': 0.016,
'72_add': 0.0585,
},
'pretty': {
'three': 0.03,
'two': 0.18,
'one': 0.79,
}
}
json.dump(config_dict, open(_draw_config, 'w', encoding='utf8'), indent=4, ensure_ascii=False)

View File

@ -0,0 +1,149 @@
import os
import nonebot
import random
from .update_game_info import update_info
from .util import generate_img, init_star_rst, BaseData, set_list
from .config import GENSHIN_FIVE_P, GENSHIN_FOUR_P, GENSHIN_G_FIVE_P, GENSHIN_THREE_P, I72_ADD
from dataclasses import dataclass
from .init_card_pool import init_game_pool
from configs.path_config import DRAW_PATH
from util.init_result import image
try:
import ujson as json
except ModuleNotFoundError:
import json
driver: nonebot.Driver = nonebot.get_driver()
genshin_five = {}
genshin_count = {}
genshin_pl_count = {}
ALL_CHAR = []
ALL_ARM = []
@dataclass
class GenshinChar(BaseData):
pass
async def genshin_draw(user_id: int, count: int):
# 0 1 2
cnlist = ['★★★★★', '★★★★', '★★★']
genshin_list, five_list, five_olist, five_dict, star_list = _format_card_information(count, user_id)
rst = init_star_rst(star_list, cnlist, five_list, five_olist)
print(five_list)
temp = ''
if count > 90:
genshin_list = set_list(genshin_list)
return image(b64=await generate_img(genshin_list, 'genshin', star_list)) + '\n' + rst[:-1] + \
temp[:-1] + f'\n距离保底发还剩 {90 - genshin_count[user_id] if genshin_count.get(user_id) else "^"}' \
+ "\n【五星0.6%四星5.1%\n第72抽开始五星概率每抽加0.585%"
async def update_genshin_info():
global ALL_CHAR, ALL_ARM
url = 'https://wiki.biligame.com/ys/角色筛选'
data, code = await update_info(url, 'genshin')
if code == 200:
ALL_CHAR = init_game_pool('genshin', data, GenshinChar)
url = 'https://wiki.biligame.com/ys/武器图鉴'
data, code = await update_info(url, 'genshin_arm', ['头像', '名称', '类型', '稀有度.alt', '初始基础属性1',
'初始基础属性2', '攻击力MAX', '副属性MAX', '技能'])
if code == 200:
ALL_ARM = init_game_pool('genshin', data, GenshinChar)
# asyncio.get_event_loop().run_until_complete(update_genshin_info())
@driver.on_startup
async def init_data():
global ALL_CHAR, ALL_ARM
if not os.path.exists(DRAW_PATH + '/draw_card_config/genshin.json') or \
not os.path.exists(DRAW_PATH + '/draw_card_config/genshin_arm.json'):
await update_genshin_info()
else:
with open(DRAW_PATH + '/draw_card_config/genshin.json', 'r', encoding='utf8') as f:
genshin_dict = json.load(f)
with open(DRAW_PATH + '/draw_card_config/genshin_arm.json', 'r', encoding='utf8') as f:
genshin_arm_dict = json.load(f)
ALL_CHAR = init_game_pool('genshin', genshin_dict, GenshinChar)
ALL_ARM = init_game_pool('genshin', genshin_arm_dict, GenshinChar)
# 抽取卡池
def _get_genshin_card(mode: int = 1, add: float = 0.0):
global ALL_ARM, ALL_CHAR
if mode == 1:
star = random.sample([5, 4, 3],
counts=[int(GENSHIN_FIVE_P * 1000) + int(add * 1000), int(GENSHIN_FOUR_P * 1000),
int(GENSHIN_THREE_P * 1000)],
k=1)[0]
elif mode == 2:
star = random.sample([5, 4],
counts=[int(GENSHIN_G_FIVE_P * 1000) + int(add * 1000), int(GENSHIN_FOUR_P * 1000)],
k=1)[0]
else:
star = 5
chars = [x for x in (ALL_ARM if random.random() < 0.5 or star == 3 else ALL_CHAR) if x.star == star]
return random.choice(chars), abs(star - 5)
def _format_card_information(_count: int, user_id):
genshin_list = []
star_list = [0, 0, 0]
five_index_list = []
five_list = []
five_dict = {}
add = 0.0
if genshin_count.get(user_id) and _count <= 90:
f_count = genshin_count[user_id]
else:
f_count = 0
if genshin_pl_count.get(user_id) and _count <= 90:
count = genshin_pl_count[user_id]
else:
count = 0
for i in range(_count):
count += 1
f_count += 1
# 十连保底
if count == 10 and f_count != 90:
if f_count >= 72:
add += I72_ADD
char, code = _get_genshin_card(2, add)
count = 0
# 大保底
elif f_count == 90:
char, code = _get_genshin_card(3)
else:
if f_count >= 72:
add += I72_ADD
char, code = _get_genshin_card(add=add)
if code == 1:
count = 0
star_list[code] += 1
if code == 0:
if _count <= 90:
genshin_five[user_id] = f_count
add = 0.0
f_count = 0
five_list.append(char.name)
five_index_list.append(i)
try:
five_dict[char.name] += 1
except KeyError:
five_dict[char.name] = 1
genshin_list.append(char)
if _count <= 90:
genshin_count[user_id] = f_count
genshin_pl_count[user_id] = count
return genshin_list, five_list, five_index_list, five_dict, star_list
def reset_count(user_id: int):
genshin_count[user_id] = 0
genshin_pl_count[user_id] = 0

View File

@ -0,0 +1,33 @@
from typing import Any
def init_game_pool(game: str, data: dict, Operator: Any):
tmp_lst = []
if game == 'prts':
for key in data.keys():
limited = False
recruit_only = False
event_only = False
if '限定寻访' in data[key]['获取途径']:
limited = True
if len(data[key]['获取途径']) == 1 and data[key]['获取途径'][0] == '公开招募':
recruit_only = True
if '活动获取' in data[key]['获取途径']:
event_only = True
if key.find('阿米娅') != -1:
continue
tmp_lst.append(Operator(name=key, star=int(data[key]['星级']),
limited=limited, recruit_only=recruit_only, event_only=event_only))
if game == 'genshin':
for key in data.keys():
if key.find('旅行者') != -1:
continue
tmp_lst.append(Operator(name=key, star=int(data[key]['稀有度'][:1]), limited=False))
if game == 'pretty':
for key in data.keys():
tmp_lst.append(Operator(name=key, star=data[key]['初始星级'], limited=False))
if game == 'pretty_card':
for key in data.keys():
tmp_lst.append(Operator(name=data[key]['中文名'], star=len(data[key]['稀有度']), limited=False))
return tmp_lst

View File

@ -0,0 +1,105 @@
import os
import nonebot
from util.init_result import image
from configs.path_config import DRAW_PATH
from .update_game_info import update_info
from .util import download_img, init_star_rst, generate_img, max_card, BaseData, set_list
import random
from .config import PRETTY_THREE, PRETTY_TWO, PRETTY_ONE
from dataclasses import dataclass
from .init_card_pool import init_game_pool
try:
import ujson as json
except ModuleNotFoundError:
import json
driver: nonebot.Driver = nonebot.get_driver()
ALL_CHAR = []
ALL_CARD = []
@dataclass
class PrettyChar(BaseData):
pass
async def pretty_draw(count: int, pool_name):
if pool_name == 'card':
cnlist = ['SSR', 'SR', 'R']
else:
cnlist = ['★★★', '★★', '']
obj_list, obj_dict, three_list, star_list, three_olist = _format_card_information(count, pool_name)
rst = init_star_rst(star_list, cnlist, three_list, three_olist)
if count > 90:
obj_list = set_list(obj_list)
return image(b64=await generate_img(obj_list, 'pretty', star_list)) \
+ '\n' + rst[:-1] + '\n' + max_card(obj_dict)
async def update_pretty_info():
global ALL_CHAR, ALL_CARD
url = 'https://wiki.biligame.com/umamusume/赛马娘图鉴'
data, code = await update_info(url, 'pretty')
if code == 200:
ALL_CHAR = init_game_pool('pretty', data, PrettyChar)
url = 'https://wiki.biligame.com/umamusume/支援卡图鉴'
data, code = await update_info(url, 'pretty_card')
if code == 200:
ALL_CARD = init_game_pool('pretty_card', data, PrettyChar)
@driver.on_startup
async def init_data():
global ALL_CHAR, ALL_CARD
if not os.path.exists(DRAW_PATH + '/draw_card_config/pretty.json') or\
not os.path.exists(DRAW_PATH + '/draw_card_config/pretty_card.json'):
await update_pretty_info()
for icon_url in [
'https://patchwiki.biligame.com/images/umamusume/thumb/0/06/q23szwkbtd7pfkqrk3wcjlxxt9z595o.png'
'/40px-SSR.png',
'https://patchwiki.biligame.com/images/umamusume/thumb/3/3b/d1jmpwrsk4irkes1gdvoos4ic6rmuht.png'
'/40px-SR.png',
'https://patchwiki.biligame.com/images/umamusume/thumb/f/f7/afqs7h4snmvovsrlifq5ib8vlpu2wvk.png'
'/40px-R.png']:
await download_img(icon_url, 'pretty', icon_url.split('-')[-1][:-4])
else:
with open(DRAW_PATH + '/draw_card_config/pretty.json', 'r', encoding='utf8') as f:
pretty_char_dict = json.load(f)
with open(DRAW_PATH + '/draw_card_config/pretty_card.json', 'r', encoding='utf8') as f:
pretty_card_dict = json.load(f)
ALL_CHAR = init_game_pool('pretty', pretty_char_dict, PrettyChar)
ALL_CARD = init_game_pool('pretty_card', pretty_card_dict, PrettyChar)
# 抽取卡池
def _get_pretty_card(itype):
global ALL_CHAR, ALL_CARD
star = random.sample([3, 2, 1],
counts=[int(PRETTY_THREE * 100), int(PRETTY_TWO * 100),
int(PRETTY_ONE * 100)],
k=1)[0]
chars = [x for x in (ALL_CARD if itype == 'card' else ALL_CHAR) if x.star == star]
return random.choice(chars), abs(star - 3)
# 整理数据
def _format_card_information(count: int, pool_name: str):
three_list = []
three_olist = []
obj_list = []
obj_dict = {}
star_list = [0, 0, 0]
for i in range(count):
obj, code = _get_pretty_card(pool_name)
star_list[code] += 1
if code == 0:
three_list.append(obj.name)
three_olist.append(i)
try:
obj_dict[obj.name] += 1
except KeyError:
obj_dict[obj.name] = 1
obj_list.append(obj)
return obj_list, obj_dict, three_list, star_list, three_olist

View File

@ -0,0 +1,162 @@
import os
import nonebot
import random
from .config import PRTS_FIVE_P, PRTS_FOUR_P, PRTS_SIX_P, PRTS_THREE_P
from .update_game_info import update_info
from .util import generate_img, init_star_rst, max_card, BaseData, UpEvent, set_list
from .init_card_pool import init_game_pool
from pathlib import Path
from .announcement import PrtsAnnouncement
from dataclasses import dataclass
from util.init_result import image
from configs.path_config import DRAW_PATH
from services.log import logger
try:
import ujson as json
except ModuleNotFoundError:
import json
driver: nonebot.Driver = nonebot.get_driver()
up_char_file = Path() / "data" / "draw_card" / "draw_card_up" / "prts_up_char.json"
prts_dict = {}
UP_OPERATOR = []
ALL_OPERATOR = []
_CURRENT_POOL_TITLE = ''
@dataclass
class Operator(BaseData):
recruit_only: bool # 公招限定
event_only: bool # 活动获得干员
# special_only: bool # 升变/异格干员
async def prts_draw(count: int = 300):
cnlist = ['★★★★★★', '★★★★★', '★★★★', '★★★']
operator_list, operator_dict, six_list, star_list, six_olist = _format_card_information(count)
up_list = []
if _CURRENT_POOL_TITLE:
for x in UP_OPERATOR:
for operator in x.operators:
up_list.append(operator)
rst = init_star_rst(star_list, cnlist, six_list, six_olist, up_list)
if count > 90:
operator_list = set_list(operator_list)
pool_info = "当前up池: " if _CURRENT_POOL_TITLE else ""
return pool_info + _CURRENT_POOL_TITLE + image(b64=await generate_img(operator_list, 'prts', star_list)) \
+ '\n' + rst[:-1] + '\n' + max_card(operator_dict)
async def update_prts_info():
global prts_dict, ALL_OPERATOR
url = 'https://wiki.biligame.com/arknights/干员数据表'
data, code = await update_info(url, 'prts', ['头像', '名称', '阵营', '星级', '性别', '是否感染', '初始生命', '初始防御',
'初始法抗', '再部署', '部署费用', '阻挡数', '攻击速度', '标签'])
if code == 200:
prts_dict = data
ALL_OPERATOR = init_game_pool('prts', prts_dict, Operator)
@driver.on_startup
async def init_data():
global prts_dict, ALL_OPERATOR
if not os.path.exists(DRAW_PATH + '/draw_card_config/prts.json'):
await update_prts_info()
else:
with open(DRAW_PATH + '/draw_card_config/prts.json', 'r', encoding='utf8') as f:
prts_dict = json.load(f)
ALL_OPERATOR = init_game_pool('prts', prts_dict, Operator)
await _init_up_char()
# print([x.operators for x in UP_OPERATOR if x.star == 5 and x.zoom > 1])
# 抽取干员
def _get_operator_card():
star = random.sample([6, 5, 4, 3],
counts=[int(PRTS_SIX_P * 100), int(PRTS_FIVE_P * 100),
int(PRTS_FOUR_P * 100), int(PRTS_THREE_P * 100)],
k=1)[0]
if _CURRENT_POOL_TITLE:
zooms = [x.zoom for x in UP_OPERATOR if x.star == star]
zoom = 0
weight = 0
# 分配概率和权重
for z in zooms:
if z < 1:
zoom = z
else:
weight = z
# UP
if random.random() < zoom:
up_operators = [x.operators for x in UP_OPERATOR if x.star == star and x.zoom < 1][0]
up_operator_name = random.choice(up_operators)
# print(up_operator_name)
acquire_operator = [x for x in ALL_OPERATOR if x.name == up_operator_name][0]
else:
all_star_operators = [x for x in ALL_OPERATOR if x.star == star
and not any([x.limited, x.event_only, x.recruit_only])]
weight_up_operators = [x.operators for x in UP_OPERATOR if x.star == star and x.zoom > 1]
# 权重
if weight_up_operators and random.random() < 1.0 / float(len(all_star_operators)) * weight:
up_operator_name = random.choice(weight_up_operators[0])
acquire_operator = [x for x in ALL_OPERATOR if x.name == up_operator_name][0]
else:
acquire_operator = random.choice(all_star_operators)
else:
acquire_operator = random.choice([x for x in ALL_OPERATOR if x.star == star
and not any([x.limited, x.event_only, x.recruit_only])])
# print(f'{acquire_operator}: {star}')
return acquire_operator, abs(star - 6)
# 整理抽卡数据
def _format_card_information(count: int):
operator_list = [] # 抽取的干员列表
operator_dict = {} # 抽取各干员次数
star_list = [0, 0, 0, 0] # 各个星级次数
six_list = [] # 六星干员列表
six_index_list = [] # 六星干员获取位置
for i in range(count):
operator, code = _get_operator_card()
star_list[code] += 1
if code == 0:
six_list.append(operator.name)
six_index_list.append(i)
try:
operator_dict[operator.name] += 1
except KeyError:
operator_dict[operator.name] = 1
operator_list.append(operator)
return operator_list, operator_dict, six_list, star_list, six_index_list
# 获取up干员和概率
async def _init_up_char():
global up_char_dict, _CURRENT_POOL_TITLE
up_char_dict = await PrtsAnnouncement.update_up_char()
# print(up_char_dict)
_CURRENT_POOL_TITLE = up_char_dict['title']
up_char_dict = up_char_dict['up_char']
logger.info(f'成功获取明日方舟当前up信息...当前up池: {_CURRENT_POOL_TITLE}')
average_dict = {'6': {}, '5': {}, '4': {}}
for star in up_char_dict.keys():
for key in up_char_dict[star].keys():
if average_dict[star].get(up_char_dict[star][key]):
average_dict[star][up_char_dict[star][key]].append(key)
else:
average_dict[star][up_char_dict[star][key]] = [key]
up_char_dict = {'6': {}, '5': {}, '4': {}}
for star in average_dict.keys():
for str_zoom in average_dict[star].keys():
if str_zoom[0] == '':
zoom = float(str_zoom[1:])
else:
zoom = float(str_zoom) / 100
UP_OPERATOR.append(UpEvent(star=int(star), operators=average_dict[star][str_zoom], zoom=zoom))
async def reload_pool():
await _init_up_char()

View File

@ -0,0 +1,162 @@
#coding:utf-8
import aiohttp
from configs.path_config import DRAW_PATH
from asyncio.exceptions import TimeoutError
from services.log import logger
from bs4 import BeautifulSoup
from .util import download_img
from urllib.parse import unquote
import bs4
from util.user_agent import get_user_agent
import re
try:
import ujson as json
except ModuleNotFoundError:
import json
async def update_info(url: str, game_name: str, info_list: list = None) -> 'dict, int':
try:
with open(DRAW_PATH + f'/draw_card_config/{game_name}.json', 'r', encoding='utf8') as f:
data = json.load(f)
except (ValueError, FileNotFoundError):
data = {}
try:
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(url, timeout=7) as response:
soup = BeautifulSoup(await response.text(), 'lxml')
max_count = 0
_tbody = None
for tbody in soup.find_all('tbody'):
if len(tbody.find_all('tr')) > max_count:
_tbody = tbody
max_count = len(tbody.find_all('tr'))
trs = _tbody.find_all('tr')
att_dict = {'头像': 0, '名称': 1}
index = 2
for th in trs[0].find_all('th')[2:]:
text = th.text
if text[-1] == '\n':
text = text[:-1]
att_dict[text] = index
index += 1
for tr in trs[1:]:
member_dict = {}
k_name = ''
tds = tr.find_all('td')
if not info_list:
info_list = att_dict.keys()
for key in info_list:
attr = ''
if key.find('.') != -1:
key = key.split('.')
attr = key[-1]
key = key[0]
td = tds[att_dict[key]]
last_tag = unquote(_find_last_tag(td, attr), 'utf-8')
if game_name.find('pretty') == -1 and last_tag.find('http') == -1:
last_tag = last_tag.split('.')[0]
if key == '名称':
k_name = last_tag
member_dict[key] = last_tag
if game_name == 'pretty' and key == '初始星级':
member_dict['初始星级'] = len(td.find_all('img'))
avatar_img = await _modify_avatar_url(session, game_name, member_dict["名称"])
if avatar_img:
member_dict['头像'] = avatar_img
name = member_dict['名称']
if game_name == 'pretty_card':
name = member_dict['中文名']
await download_img(member_dict['头像'], game_name, name)
if k_name:
data[k_name] = member_dict
logger.info(f'{k_name} is update...')
data = await _last_check(data, game_name, session)
except TimeoutError:
return {}, 999
with open(DRAW_PATH + f'/draw_card_config/{game_name}.json', 'w', encoding='utf8') as wf:
wf.write(json.dumps(data, ensure_ascii=False, indent=4))
return data, 200
def _find_last_tag(element: bs4.element.Tag, attr: str) -> str:
last_tag = []
for des in element.descendants:
last_tag.append(des)
if len(last_tag) == 1 and last_tag[0] == '\n':
last_tag = ''
elif last_tag[-1] == '\n':
last_tag = last_tag[-2]
else:
last_tag = last_tag[-1]
if attr and str(last_tag):
last_tag = last_tag[attr]
elif str(last_tag).find('<img') != -1:
if last_tag.get('srcset'):
last_tag = str(last_tag.get('srcset')).strip().split(' ')[-2].strip()
else:
last_tag = last_tag['src']
else:
last_tag = str(last_tag)
if str(last_tag) and str(last_tag)[-1] == '\n':
last_tag = str(last_tag)[:-1]
return last_tag
# 获取大图(小图快爬)
async def _modify_avatar_url(session: aiohttp.ClientSession, game_name: str, char_name: str):
if game_name == 'prts':
async with session.get(f'https://wiki.biligame.com/arknights/{char_name}', timeout=7) as res:
soup = BeautifulSoup(await res.text(), 'lxml')
try:
img_url = str(soup.find('img', {'class': 'img-bg'})['srcset']).split(' ')[-2]
except KeyError:
img_url = str(soup.find('img', {'class': 'img-bg'})['src'])
return img_url
if game_name == 'genshin':
return None
if game_name == 'pretty_card':
async with session.get(f'https://wiki.biligame.com/umamusume/{char_name}', timeout=7) as res:
soup = BeautifulSoup(await res.text(), 'lxml')
img_url = soup.find('div', {'class': 'support_card-left'}).find('div').find('img').get('src')
return img_url
# 数据最后处理(是否需要额外数据)
async def _last_check(data: dict, game_name: str, session: aiohttp.ClientSession):
if game_name == 'prts':
for key in data.keys():
async with session.get(f'https://wiki.biligame.com/arknights/{key}', timeout=7) as res:
soup = BeautifulSoup(await res.text(), 'lxml')
obtain = str(soup.find('table', {'class': 'wikitable'}).find('tbody').find_all('td')[-1])
obtain = re.search(r'<td.*?>([\s\S]*)</.*?', obtain).group(1)
obtain = obtain[:-1] if obtain[-1] == '\n' else obtain
if obtain.find('<br/>'):
obtain = obtain.split('<br/>')
elif obtain.find('<br>'):
obtain = obtain.split('<br>')
data[key]['获取途径'] = obtain
# if game_name == 'genshin':
# for key in data.keys():
# async with session.get(f'https://wiki.biligame.com/ys/{key}', timeout=7) as res:
# soup = BeautifulSoup(await res.text(), 'lxml')
# trs = soup.find('div', {'class': 'poke-bg'}).find('table').find('tbody').find_all('tr')
# for tr in trs:
# if tr.find('th').text.find('常驻/限定') != -1:
# data[key]['常驻/限定'] = tr.find('td').text
# break
if game_name == 'pretty':
for keys in data.keys():
for key in data[keys].keys():
# print(f'key --> {data[keys][key]}')
r = re.search(r'.*?40px-(.*)图标.png', str(data[keys][key]))
if r:
data[keys][key] = r.group(1)
return data
# ul = soup.find('div', {'class': 'savelist_bot'}).find('ul')

161
plugins/draw_card/util.py Normal file
View File

@ -0,0 +1,161 @@
import os
import aiohttp
import aiofiles
from asyncio.exceptions import TimeoutError
from aiohttp.client_exceptions import InvalidURL
from typing import List, Union, Set
import asyncio
from pathlib import Path
from .config import path_dict
import nonebot
from util.utils import cn2py
from util.img_utils import CreateImg
from util.user_agent import get_user_agent
from configs.path_config import IMAGE_PATH
from dataclasses import dataclass
from services.log import logger
try:
import ujson as json
except ModuleNotFoundError:
import json
driver: nonebot.Driver = nonebot.get_driver()
@dataclass
class BaseData:
name: str
star: int
limited: bool # 限定
@dataclass
class UpEvent:
star: int # 对应up星级
operators: List[BaseData] # 干员列表
zoom: float # up提升倍率
async def download_img(url: str, path: str, name: str) -> bool:
path = path.split('_')[0]
codename = cn2py(name)
# if not _p.exists():
# _p.mkdir(parents=True, exist_ok=True)
if not os.path.exists(IMAGE_PATH + f'/draw_card/{path}/{codename}.png'):
try:
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(url, timeout=7) as response:
async with aiofiles.open(IMAGE_PATH + f'/draw_card/{path}/{codename}.png', 'wb') as f:
await f.write(await response.read())
logger.info(f'下载 {path_dict[path]} 图片成功,名称:{name}url{url}')
return True
except TimeoutError:
logger.info(f'下载 {path_dict[path]} 图片超时,名称:{name}url{url}')
return False
except InvalidURL:
logger.info(f'下载 {path_dict[path]} 链接错误,名称:{name}url{url}')
return False
else:
# logger.info(f'{path_dict[path]} 图片 {name} 已存在')
return False
@driver.on_startup
def _check_dir():
for dir_name in path_dict.keys():
_p = Path(IMAGE_PATH + f'/draw_card/' + dir_name)
if not _p.exists():
_p.mkdir(parents=True, exist_ok=True)
async def generate_img(card_set: Union[Set[BaseData], List[BaseData]], game_name: str, star_list: list) -> str:
# try:
img_list = []
color_list = []
for x in card_set:
if game_name == 'prts':
if x.star == 6:
color_list.append('#FFD700')
elif x.star == 5:
color_list.append('#DAA520')
elif x.star == 4:
color_list.append('#9370D8')
else:
color_list.append('white')
pyname = cn2py(x.name)
img_list.append(IMAGE_PATH + f'/draw_card/{game_name}/{pyname}.png')
img_len = len(img_list)
w = 100 * 10
if img_len <= 10:
w = 100 * img_len
h = 100
elif img_len % 10 == 0:
h = 100 * int(img_len / 10)
else:
h = 100 * int(img_len / 10) + 100
card_img = await asyncio.get_event_loop().run_in_executor(None, _pst, h, img_list, game_name, color_list)
num = 0
for n in star_list:
num += n
A = CreateImg(w, h)
A.paste(card_img)
return A.pic2bs4()
def _pst(h: int, img_list: list, game_name: str, color_list: list):
card_img = CreateImg(100 * 10, h, 100, 100)
idx = 0
for img in img_list:
try:
if game_name == 'prts':
bk = CreateImg(100, 100, color=color_list[idx])
b = CreateImg(94, 94, background=img)
bk.paste(b, (3, 3))
b = bk
idx += 1
else:
b = CreateImg(100, 100, background=img)
except FileNotFoundError:
print(f'{img} not exists')
b = CreateImg(100, 100, color='black')
card_img.paste(b)
return card_img
def init_star_rst(star_list: list, cnlist: list, max_star_list: list, max_star_olist: list, up_list: list = None) -> str:
if not up_list:
up_list = []
rst = ''
for i in range(len(star_list)):
if star_list[i]:
rst += f'[{cnlist[i]}×{star_list[i]}] '
rst += '\n'
for i in range(len(max_star_list)):
if max_star_list[i] in up_list:
rst += f'{max_star_olist[i]+1} 抽获取UP {max_star_list[i]}\n'
else:
rst += f'{max_star_olist[i]+1} 抽获取 {max_star_list[i]}\n'
return rst
def max_card(_dict: dict):
_max_value = max(_dict.values())
_max_user = list(_dict.keys())[list(_dict.values()).index(_max_value)]
return f'抽取到最多的是{_max_user},共抽取了{_max_value}'
# ThreeHighest = nlargest(3, operator_dict, key=operator_dict.get)
# rst = '最喜欢你的前三位是干员是:\n'
# for name in ThreeHighest:
# rst += f'{name} 共投了 {operator_dict[name]} 份简历\n'
# return rst[:-1]
def set_list(lst: List[BaseData]) -> list:
tmp = []
name_lst = []
for x in lst:
if x.name not in name_lst:
tmp.append(x)
name_lst.append(x.name)
return tmp

60
plugins/epic/__init__.py Normal file
View File

@ -0,0 +1,60 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.typing import T_State
from util.utils import scheduler, get_bot
from .data_source import get_epic_game
from models.group_remind import GroupRemind
from nonebot.adapters.cqhttp.exception import ActionFailed
__plugin_usage__ = 'epic免费游戏提醒'
epic = on_command("epic", priority=5, block=True)
@epic.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
# try:
if str(event.get_message()) in ['帮助']:
await epic.finish(__plugin_usage__)
try:
result = await get_epic_game()
except:
result = '网络出错了!'
await epic.send(result)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})"
f" 获取epic免费游戏")
# except Exception as e:
# logger.error(f'epic 出错 e:{e}')
# await epic.finish('网络好像炸了,再试一次?', at_sender=True)
# epic免费游戏
@scheduler.scheduled_job(
'cron',
hour=12,
minute=1,
)
async def _():
# try:
bot = get_bot()
gl = await bot.get_group_list(self_id=bot.self_id)
gl = [g['group_id'] for g in gl]
for g in gl:
if await GroupRemind.get_status(g, 'epic'):
result = await get_epic_game()
if result == '今天没有游戏可以白嫖了!':
return
try:
await bot.send_group_msg(group_id=g,
message=result)
except ActionFailed:
logger.error(f'{g}群 epic免费游戏推送错误')
# except Exception as e:
# logger.error(f'epic免费游戏推送错误 e:{e}')

View File

@ -0,0 +1,46 @@
import aiohttp
import aiofiles
from util.utils import get_local_proxy
import feedparser
import platform
from util.init_result import image
from configs.path_config import IMAGE_PATH
from util.user_agent import get_user_agent
if platform.system() == 'Windows':
import asyncio
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
url = 'https://rsshub.app/epicgames/freegames'
async def get_epic_game() -> str:
result = ''
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(url, proxy=get_local_proxy(), timeout=7) as response:
data = feedparser.parse(await response.text())['entries']
if len(data) == 0:
return result
index = 0
for item in data:
title = item['title']
img_url = item['summary'][item['summary'].find('src="')+5: item['summary'].rfind('"')]
async with session.get(img_url, proxy=get_local_proxy(), timeout=7) as res:
async with aiofiles.open(IMAGE_PATH + f'temp/epic_{index}.jpg', 'wb') as f:
await f.write(await res.read())
link = item['link']
result += image(f'epic_{index}.jpg', 'temp') + f'\n【游戏】| {title}\n【链接】 | {link}\n'
index += 1
if result != '':
result = 'epic限免游戏速速白嫖\n' + result
else:
result = '今天没有游戏可以白嫖了!'
print(result)
return result
# print(asyncio.get_event_loop().run_until_complete(get_epic_game()))

View File

@ -0,0 +1,125 @@
from nonebot import on_notice, on_request
from configs.path_config import IMAGE_PATH, DATA_PATH
from util.init_result import image
import os
import random
from models.group_member_info import GroupInfoUser
from datetime import datetime
from services.log import logger
from models.group_remind import GroupRemind
from nonebot.adapters.cqhttp import Bot, GroupIncreaseNoticeEvent, GroupDecreaseNoticeEvent, GroupRequestEvent
from nonebot.adapters.cqhttp.exception import ActionFailed
from pathlib import Path
from nonebot import require
try:
import ujson as json
except ModuleNotFoundError:
import json
export = require("admin_bot_manage")
# 群员增加处理
group_increase_handle = on_notice(priority=5)
# 群员减少处理
group_decrease_handle = on_notice(priority=5)
# (群管理)加群同意请求
add_group = on_request(priority=5)
@group_increase_handle.handle()
async def _(bot: Bot, event: GroupIncreaseNoticeEvent, state: dict):
if event.user_id == int(bot.self_id):
await export.update_member_info(event.group_id)
else:
join_time = datetime.now()
user_info = await bot.get_group_member_info(group_id=event.group_id, user_id=event.user_id)
if await GroupInfoUser.insert(
user_info['user_id'],
user_info['group_id'],
user_info['nickname'],
join_time,
):
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
else:
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败")
if await GroupRemind.get_status(event.group_id, 'hy'):
msg = ''
img = ''
at_flag = False
custom_welcome_msg_json = Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
if custom_welcome_msg_json.exists():
data = json.load(open(custom_welcome_msg_json, 'r'))
if data.get(str(event.group_id)):
msg = data[str(event.group_id)]
if msg.find('[at]') != -1:
msg = msg.replace('[at]', '')
at_flag = True
if os.path.exists(DATA_PATH + f'custom_welcome_msg/{event.group_id}.jpg'):
img = image(abspath=DATA_PATH + f'custom_welcome_msg/{event.group_id}.jpg')
if msg or img:
await group_increase_handle.send("\n" + msg + img, at_sender=at_flag)
else:
await group_increase_handle.send(
'新人快跑啊!!本群现状↓(快使用自定义!)' + image(random.choice(os.listdir(IMAGE_PATH + "qxz/")), "qxz"))
@group_decrease_handle.handle()
async def _(bot: Bot, event: GroupDecreaseNoticeEvent, state: dict):
# 真寻被踢出群
if event.sub_type == 'kick_me':
group_id = event.group_id
operator_id = event.operator_id
try:
operator_name = (await GroupInfoUser.select_member_info(event.operator_id, event.group_id)).user_name
except AttributeError:
operator_name = 'None'
coffee = int(list(bot.config.superusers)[0])
await bot.send_private_msg(
user_id=coffee,
message=f'报告..\n'
f'我被 {operator_name}({operator_id})\n'
f'踢出了 {group_id}')
return
try:
user_name = (await GroupInfoUser.select_member_info(event.user_id, event.group_id)).user_name
except AttributeError:
user_name = str(event.user_id)
rst = ''
if event.sub_type == 'leave':
rst = f'{user_name}离开了我们...'
if event.sub_type == 'kick':
try:
operator_name = (await GroupInfoUser.select_member_info(event.operator_id, event.group_id)).user_name
except AttributeError:
operator_name = event.operator_id
rst = f'{user_name}{operator_name} 送走了.'
try:
await group_decrease_handle.send(f"{rst}")
except ActionFailed:
return
if await GroupInfoUser.delete_member_info(event.user_id, event.group_id):
logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除成功")
else:
logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除失败")
@add_group.handle()
async def _(bot: Bot, event: GroupRequestEvent, state: dict):
pass
# user_info = await bot._get_vip_info(user_id=event.user_id)
# if user_info['level'] > 16:
# bot.set

35
plugins/help/__init__.py Normal file
View File

@ -0,0 +1,35 @@
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, PrivateMessageEvent
from nonebot.typing import T_State
from nonebot.rule import to_me
from configs.path_config import DATA_PATH
from util.init_result import image
import os
from .data_source import create_help_img, create_group_help_img
from nonebot import require
export = require("nonebot_plugin_manager")
__plugin_name__ = '帮助'
if not os.path.exists(DATA_PATH + 'group_help/'):
os.mkdir(DATA_PATH + 'group_help/')
create_help_img()
for file in os.listdir(DATA_PATH + 'group_help/'):
os.remove(DATA_PATH + 'group_help/' + file)
_help = on_command("功能", rule=to_me(), aliases={"帮助", 'help'}, priority=1, block=True)
@_help.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if not os.path.exists(DATA_PATH + f'group_help/{event.group_id}.png'):
create_group_help_img(event.group_id)
await _help.finish(image(abspath=DATA_PATH + f'group_help/{event.group_id}.png'))
@_help.handle()
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
await _help.finish(image('help.png'))

52
plugins/help/config.py Normal file
View File

@ -0,0 +1,52 @@
# 实用
utility_help = {
'update_pic': '一些对图片的操作 --> 指令:操作图片/图片/修改图片(包含 10 种图片操作)',
'search_buff_skin_price': 'BUFF皮肤底价查询 --> 指令:查询皮肤(代理ip不得劲)',
'weather': '天气查询 --> 指令:xx天气',
'yiqing': '实时疫情数据 --> 指令:疫情查询/疫情/查询疫情',
'bt': 'bt(磁力搜索){仅支持私聊,懂的都懂} --> 指令:bt',
'reimu': '老司机必备!{仅支持私聊,懂的都懂}-> 指令:上车',
'what_anime': '靠图识番 --> 指令:识番',
'nonebot_plugin_picsearcher': '以图搜图 --> 指令:识图/这是什么/上一张图是什么',
'search_anime': '找不到想看的动漫吗? --> 指令:搜番',
'songpicker2': '来一首歌听听? --> 指令:点歌',
'epic': 'epic速速白嫖 --> 指令:epic',
'pixiv_r': 'P站排行榜直接冲 --> 指令:p站排行(可含参数)',
'pixiv_s': 'P站的图随便搜搜 --> 指令:搜图(可含参数)',
'translate': '出国旅游助手(狗头) --> 指令:英翻/翻英/日翻/翻日/韩翻/翻韩'
}
# 娱乐
entertainment_help = {
'sign_in': '签到(影响色图几率和开箱次数) --> 指令:签到/我的签到/好感度排行',
'send_img': '发送图片 --> 指令:美图/萝莉/壁纸',
'send_setu': '不要小看涩图啊混蛋! --> 指令:色图/n张色图/n张xx色图/查色图/...(请查看 色图 帮助)',
'white2black_img': '黑白草图 --> 指令:黑白图/黑白草图',
'coser': '三次元也不戳 --> 指令:coser',
'jitang': '不喝点什么不舒服 --> 指令:鸡汤/语录',
'send_dinggong_voice': '骂我(傲娇?) --> 指令:骂老子',
'poke': '戳一戳发送语音美图萝莉图不美哉?',
'open_cases': '模拟开箱(戒赌) --> 指令:开箱(N连开箱[N<=30])/我的开箱/群开箱统计/我的金色',
'luxun': '鲁迅说过 --> 指令:鲁迅说',
'fake_msg': '构造一个假消息 --> 指令:假消息',
'shop': '商店系统初始送100金币 --> 指令:商店/我的金币/购买道具/使用道具',
'draw_card_p': '换个地方当非酋TvT... --> 指令:方舟一井/方舟N抽0<N<300',
'draw_card_g': '提瓦特是个好地方! --> 指令:原神一井/原神N抽0<N<300/重置原神抽卡次数',
'draw_card_h': '赛马娘!!!! --> 指令:赛马娘一井/赛马娘N抽/赛马娘卡一井/赛马娘卡N抽(0<N<300)',
'nonebot_plugin_cocdicer': '骰子娘 --> 直接查看 骰子娘帮助!',
'one_friend': '我有一个朋友想问问... --> 指令:我有一个朋友想问问xxx(内容)',
'nickname': '区区昵称! --> 指令:以后叫我xx(昵称)/我是谁/取消昵称',
'almanac': '这是一张正经的黄历 --> 指令:原神黄历',
'material_remind': '看看原神今天要刷什么 --> 指令:今日素材/天赋材料',
'qiu_qiu_translation': '这家伙到底在说什么? --> 指令:丘丘翻译/丘丘一下/丘丘语翻译',
'query_resource_points': '地图资源速速查看 --> 指令:原神资源查询xx/原神资源列表/哪里有xx/xx在哪(xx=资源名称)',
}
# 其他
other_help = [
'群内csgo服务器指定群 --> 指令:服务器/ip(其他群请私聊)',
'查看当前的群欢迎消息 --> 指令:群欢迎消息',
'这是一份正经的自我介绍 --> 指令:自我介绍',
'不得看看自己权力多大? --> 指令:我的权限',
'有人记得你是什么时候加入我们的 --> 指令:我的信息',
'让我看看更新了什么 --> 指令:更新信息'
]

175
plugins/help/data_source.py Normal file
View File

@ -0,0 +1,175 @@
from util.img_utils import CreateImg
from configs.path_config import IMAGE_PATH, DATA_PATH
import ujson as json
import os
from .config import *
from nonebot import require
export = require("nonebot_plugin_manager")
width = 1200
e_height = 0
u_height = 700
o_height = 1250
# f_height =
def create_help_img():
if os.path.exists(IMAGE_PATH + 'help.png'):
os.remove(IMAGE_PATH + 'help.png')
h = (100 + len(utility_help) * 24 + len(entertainment_help) * 24 + len(other_help) * 24) * 2
A = CreateImg(width, h - 200, font_size=24)
e = CreateImg(width, len(entertainment_help) * 42, font_size=24)
rst = ''
i = 0
for cmd in entertainment_help:
rst += f'{i + 1}.{entertainment_help[cmd]}\n'
i += 1
e.text((10, 10), '娱乐功能:')
e.text((40, 40), rst)
u = CreateImg(width, len(utility_help) * 40 + 50, font_size=24, color='black')
rst = ''
i = 0
for cmd in utility_help:
rst += f'{i + 1}.{utility_help[cmd]}\n'
i += 1
u.text((10, 10), '实用功能:', fill=(255, 255, 255))
u.text((40, 40), rst, fill=(255, 255, 255))
o = CreateImg(width, len(other_help) * 40, font_size=24)
rst = ''
i = 0
for i in range(len(other_help)):
rst += f'{i + 1}.{other_help[i]}\n'
i += 1
o.text((10, 10), '其他功能:')
o.text((40, 40), rst)
A.paste(e, (0, 0))
A.paste(u, (0, u_height))
A.paste(o, (0, o_height))
A.text((10, h * 0.72), '大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对我说 “指令名 帮助” 获取对应详细帮助\n'
'可以通过 “滴滴滴- 后接内容” 联系管理员(有趣的想法尽管来吧!<还有Bug和建议>\n[群管理员请看 管理员帮助(群主与管理员自带 5 级权限)]')
A.text((10, h * 0.79), f"【注】「色图概率:好感度 + 70%\n"
f"\t\t每 3 点好感度 + 1次开箱初始 20 次\n"
f"\t\t开启/关闭功能只需输入‘开启/关闭 指令名’(每个功能的第一个指令)」\n"
f"\t\t示例:开启签到")
A.save(IMAGE_PATH + 'help.png')
def create_group_help_img(group_id: int):
group_id = str(group_id)
try:
with open(DATA_PATH + 'manager/plugin_list.json', 'r', encoding='utf8') as f:
plugin_list = json.load(f)
except (ValueError, FileNotFoundError):
pass
h = (100 + len(utility_help) * 24 + len(entertainment_help) * 24 + len(other_help) * 24) * 2
A = CreateImg(1200, h - 200, font_size=24)
u = CreateImg(1200, len(utility_help) * 40, font_size=24, color='black')
o = CreateImg(1200, len(other_help) * 40, font_size=24)
e = CreateImg(width, len(entertainment_help) * 42, font_size=24)
rst = ''
i = 1
# print(plugin_list)
for cmd in entertainment_help.keys():
# dfg = '_'
# if cmd == 'draw_card_p':
# cmd = 'draw_card'
# dfg = 'p'
# elif cmd == 'draw_card_g':
# cmd = 'draw_card'
# dfg = 'g'
# flag = '√'
# if group_id in plugin_list[cmd]:
# if not plugin_list[cmd][group_id]:
# flag = '×'
# if cmd in ['nickname']:
# flag = '-'
flag, dfg = parse_cmd(cmd, group_id, plugin_list)
if dfg:
cmd = rcmd(dfg)
# if dfg == 'p':
# cmd = 'draw_card_p'
# elif dfg == 'g':
# cmd = 'draw_card_g'
rst += f'{flag}{i}.{entertainment_help[cmd]}\n'
i += 1
e.text((10, 10), '娱乐功能:')
e.text((40, 40), rst)
rst = ''
i = 1
for cmd in utility_help.keys():
# flag = '√'
# if group_id in plugin_list[cmd]:
# if not plugin_list[cmd][group_id]:
# flag = '×'
# if cmd in ['bt', 'reimu']:
# flag = '-'
flag, dfg = parse_cmd(cmd, group_id, plugin_list)
rst += f'{flag}{i}.{utility_help[cmd]}\n'
i += 1
u.text((10, 10), '实用功能:', fill=(255, 255, 255))
u.text((40, 40), rst, fill=(255, 255, 255))
rst = ''
for i in range(len(other_help)):
rst += f'{i + 1}.{other_help[i]}\n'
o.text((10, 10), '其他功能:')
o.text((40, 40), rst)
A.paste(e, (0, 0))
A.paste(u, (0, u_height))
A.paste(o, (0, o_height))
# A.text((width, 10), f'总开关【{"√" if data["总开关"] else "×"}】')
A.text((10, h * 0.72), '大部分交互功能可以通过输入‘取消’,‘算了’来取消当前交互\n对我说 “指令名 帮助” 获取对应详细帮助\n'
'可以通过 “滴滴滴- 后接内容” 联系管理员(有趣的想法尽管来吧!<还有Bug和建议>'
'\n[群管理员请看 管理员帮助(群主与管理员自带 5 级权限)]')
A.text((10, h * 0.79), f"【注】「色图概率:好感度 + 70%\n"
f"\t\t每 3 点好感度 + 1次开箱初始 20 次\n"
f"\t\t开启/关闭功能只需输入‘开启/关闭 指令名’(每个功能的第一个指令)」\n"
f"\t\t示例:开启签到\n"
f"\t\t可以通过管理员开关自动发送消息(早晚安等)\n"
f"\t\t^请查看管理员帮助^")
A.save(DATA_PATH + f'group_help/{group_id}.png')
def parse_cmd(cmd, group_id, plugin_list):
flag = ''
dfg = None
if cmd == 'draw_card_p':
cmd = 'draw_card'
dfg = 'p'
elif cmd == 'draw_card_g':
cmd = 'draw_card'
dfg = 'g'
elif cmd == 'draw_card_h':
cmd = 'draw_card'
dfg = 'h'
elif cmd == 'pixiv_r':
cmd = 'pixiv'
dfg = 'r'
elif cmd == 'pixiv_s':
cmd = 'pixiv'
dfg = 's'
if group_id in plugin_list[cmd]:
if not plugin_list[cmd][group_id]:
flag = '×'
if cmd in ['bt', 'reimu', 'nickname']:
flag = '- '
return flag, dfg
def rcmd(dfg):
if dfg == 'p':
return 'draw_card_p'
if dfg == 'g':
return 'draw_card_g'
if dfg == 'g':
return 'draw_card_h'
if dfg == 'r':
return 'pixiv_r'
if dfg == 's':
return 'pixiv_s'

View File

@ -0,0 +1,53 @@
from nonebot import on_message
from nonebot.adapters.cqhttp.permission import GROUP
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
import time
from .data_source import cancel_all_notice, save_data, get_data, set_data_value
from services.log import logger
__plugin_name__ = '查看群最后聊天时间 [Hidden]'
last_chat = on_message(priority=1, block=False, permission=GROUP)
@last_chat.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
time_data = await get_data()
set_data_value(event.group_id, time.time())
if event.group_id in time_data['_group']:
time_data['_group'].remove(event.group_id)
set_data_value('_group', time_data['_group'])
for key in time_data.keys():
if key not in ['check_time', '_group']:
if key not in time_data['_group']:
if time.time() - time_data[key] > 60 * 60 * 36:
await cancel_all_notice(key)
time_data["_group"].append(key)
set_data_value('_group', time_data['_group'])
logger.info(f'GROUP {event.group_id} 因群内发言时间大于36小时被取消全部通知')
if time.time() - time_data['check_time'] > 60 * 60 * 1:
set_data_value('check_time', time.time())
save_data()

View File

@ -0,0 +1,74 @@
from configs.path_config import DATA_PATH
from util.utils import get_bot
from models.group_remind import GroupRemind
from datetime import datetime
import time
from services.log import logger
try:
import ujson as json
except ModuleNotFoundError:
import json
time_data = {}
async def init():
global time_data
bot = get_bot()
gl = await bot.get_group_list(self_id=bot.self_id)
gl = [g['group_id'] for g in gl]
data = read_data('group_last_chat_time.json')
for g in gl:
if not data.get(g):
time_data[g] = time.time()
if not time_data.get('check_time'):
time_data['check_time'] = time.time()
if not time_data.get('_group'):
time_data['_group'] = []
save_data()
return time_data
def read_data(file_name: str):
try:
with open(DATA_PATH + file_name, 'r', encoding='utf8') as f:
return json.load(f)
except (ValueError, FileNotFoundError):
return {}
def save_data():
with open(DATA_PATH + 'group_last_chat_time.json', 'w') as f:
json.dump(time_data, f, indent=4)
logger.info(f'自动存储 group_last_chat_time.json 时间:{str(datetime.now()).split(".")[0]}')
command_list = ['zwa', 'hy', 'kxcz', 'blpar', 'epic', 'pa']
# 取消全部通知
async def cancel_all_notice(group_id):
group_id = int(group_id)
for command in command_list:
if await GroupRemind.get_status(group_id, command):
await GroupRemind.set_status(group_id, command, False)
logger.info(f'关闭了 {group_id} 群的全部通知')
async def get_data():
global time_data
if not time_data:
time_data = await init()
return time_data
def set_data_value(key, value):
global time_data
time_data[key] = value

64
plugins/luxun/__init__.py Normal file
View File

@ -0,0 +1,64 @@
from PIL import ImageFont, ImageDraw, Image
import textwrap
from configs.path_config import IMAGE_PATH, TTF_PATH
from nonebot import on_command
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
from util.init_result import image
from services.log import logger
from util.utils import UserExistLimiter, get_message_text
from util.img_utils import pic2b64
_ulmt = UserExistLimiter()
luxun = on_command("鲁迅说过", aliases={"鲁迅说"})
@luxun.handle()
async def handle(bot: Bot, event: MessageEvent, state: T_State):
if _ulmt.check(event.user_id):
await luxun.finish('你的鲁迅正在说,等会', at_sender=True)
args = get_message_text(event.json())
if args:
state["content"] = args if args else '烦了,不说了'
@luxun.got("content", prompt="你让鲁迅说点啥?")
async def handle_event(bot: Bot, event: MessageEvent, state: T_State):
filename = str(event.user_id) + "_.jpg"
content = state["content"].strip()
if content.startswith(',') or content.startswith(''):
content = content[1:]
_ulmt.set_True(event.user_id)
if len(content) > 20:
_ulmt.set_False(event.user_id)
await luxun.finish("太长了, 鲁迅说不完!", at_sender=True)
else:
if len(content) >= 12:
content = content[:12] + '\n' + content[12:]
img = image(b64=process_pic(content, filename))
logger.info(f"USER {event.user_id} GROUP "
f"{event.group_id if event.message_type != 'private' else 'private'} 鲁迅说过 {content}")
await luxun.send(img)
_ulmt.set_False(event.user_id)
def process_pic(content, filename) -> str:
text = content
para = textwrap.wrap(text, width=15)
MAX_W, MAX_H = 480, 280
bk_img = Image.open(IMAGE_PATH + "other/luxun.jpg")
font_path = TTF_PATH + "/msyh.ttf"
font = ImageFont.truetype(font_path, 37)
font2 = ImageFont.truetype(font_path, 30)
draw = ImageDraw.Draw(bk_img)
current_h, pad = 300, 10
for line in para:
w, h = draw.textsize(line, font=font)
draw.text(((MAX_W - w) / 2, current_h), line, font=font)
current_h += h + pad
draw.text((320, 400), "——鲁迅", font=font2, fill=(255, 255, 255))
return pic2b64(bk_img)

View File

@ -0,0 +1,84 @@
import os
from services.log import logger
from nonebot import on_command
from nonebot.rule import to_me
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
from configs.config import IMAGE_DIR_LIST
from util.utils import is_number, cn2py
from configs.path_config import IMAGE_PATH
__plugin_name__ = '移动图片'
__plugin_usage__ = '移动图片帮助:\n\t' \
'1.查看列表 --> 指令: 移动图片 列表/目录\n\t' \
'2.移动图片 源 目的 id\n\t\t示例: 移动图片 色图 美图 1234'
move_img = on_command('移动图片', priority=5, rule=to_me(), block=True)
@move_img.args_parser
async def parse(bot: Bot, event: MessageEvent, state: T_State):
if str(event.get_message()) in ['取消', '算了']:
await move_img.finish("已取消操作..", at_sender=True)
if state["_current_key"] in ['source_path', 'destination_path']:
if str(event.get_message()) not in IMAGE_DIR_LIST:
await move_img.reject("此目录不正确,请重新输入目录!")
state[state["_current_key"]] = str(event.get_message())
if state["_current_key"] == 'id':
if not is_number(str(event.get_message())):
await move_img.reject("id不正确请重新输入数字...")
state[state["_current_key"]] = str(event.get_message())
@move_img.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
raw_arg = str(event.get_message()).strip()
if raw_arg:
args = raw_arg.split(" ")
if args[0] in ['帮助']:
await move_img.finish(__plugin_usage__)
if len(args) >= 3 and args[0] in IMAGE_DIR_LIST and args[1] in IMAGE_DIR_LIST and is_number(args[2]):
state['source_path'] = args[0]
state['destination_path'] = args[1]
state['id'] = args[2]
else:
await move_img.finish("参数错误,请重试", at_sender=True)
@move_img.got("source_path", prompt="要从哪个图库移出?")
@move_img.got("destination_path", prompt="要移动到哪个图库?")
@move_img.got("id", prompt="要移动的图片id是")
async def _(bot: Bot, event: MessageEvent, state: T_State):
img_id = state['id']
source_path = IMAGE_PATH + cn2py(state['source_path'])
destination_path = IMAGE_PATH + cn2py(state['destination_path'])
max_id = len(os.listdir(source_path)) - 1
des_max_id = len(os.listdir(destination_path))
if int(img_id) > max_id or int(img_id) < 0:
await move_img.finish(f"Id超过上下限上限{max_id}", at_sender=True)
try:
os.rename(source_path + img_id + ".jpg", destination_path + str(des_max_id) + ".jpg")
logger.info(f"移动 {source_path}{img_id}.jpg ---> {destination_path}{des_max_id} 移动成功")
except Exception as e:
logger.warning(f"移动 {source_path}{img_id}.jpg ---> {destination_path}{des_max_id} 移动失败 e:{e}")
await move_img.finish(f"移动图片id{img_id} 失败了...", at_sender=True)
if max_id > 0:
try:
os.rename(source_path + str(max_id) + ".jpg", source_path + img_id + ".jpg")
logger.info(f"{source_path}{max_id}.jpg 替换 {source_path}{img_id}.jpg 成功")
except Exception as e:
logger.warning(f"{source_path}{max_id}.jpg 替换 {source_path}{img_id}.jpg 失败 e:{e}")
await move_img.finish(f"替换图片id{max_id} -> {img_id} 失败了...", at_sender=True)
logger.info(f"USER {event.user_id} GROUP {event.group_id if event.message_type != 'private' else 'private'} ->"
f" {source_path} --> {destination_path} (id{img_id}) 移动图片成功")
await move_img.finish(f"移动图片 id{img_id} --> id{des_max_id}成功", at_sender=True)

View File

@ -0,0 +1,72 @@
from .data_source import rd, help_message, st, en
from .madness import ti, li
from .create import Investigator
from .san_check import sc
from nonebot.plugin import on_startswith
from nonebot.adapters.cqhttp import Bot, Event
rdhelp = on_startswith("骰子娘帮助", priority=2)
stcommand = on_startswith(".st", priority=2)
encommand = on_startswith(".en", priority=2)
ticommand = on_startswith(".ti", priority=2)
licommand = on_startswith(".li", priority=2)
coc = on_startswith(".coc", priority=2)
sccommand = on_startswith(".sc", priority=2)
rdcommand = on_startswith(".r", priority=3)
@rdhelp.handle()
async def rdhelphandler(bot: Bot):
await rdhelp.finish(help_message())
@stcommand.handle()
async def stcommandhandler(bot: Bot):
await rdhelp.finish(st())
@encommand.handle()
async def enhandler(bot: Bot, event: Event):
args = str(event.get_message())[3:].strip()
await encommand.finish(en(args))
@rdcommand.handle()
async def rdcommandhandler(bot: Bot, event: Event):
args = str(event.get_message())[2:].strip()
uid = event.get_session_id()
if args and not("." in args):
rrd = rd(args)
if type(rrd) == str:
await rdcommand.finish(rrd)
elif type(rrd) == list:
await bot.send_private_msg(user_id=uid, message=rrd[0])
@coc.handle()
async def cochandler(bot: Bot, event: Event):
args = str(event.get_message())[4:].strip()
try:
args = int(args)
except:
args = 20
inv = Investigator()
inv.age_change(args)
await coc.finish(inv.output())
@ticommand.handle()
async def ticommandhandler(bot: Bot):
await ticommand.finish(ti())
@licommand.handle()
async def licommandhandler(bot: Bot):
await licommand.finish(li())
@sccommand.handle()
async def schandler(bot: Bot, event: Event):
args = str(event.get_message())[3:].strip()
await sccommand.finish(sc(args.lower()))

View File

@ -0,0 +1,147 @@
import random
build_dict = {64: -2, 84: -1, 124: 0, 164: 1,
204: 2, 284: 3, 364: 4, 444: 5, 524: 6}
db_dict = {-2: "-2", -1: "-1", 0: "0", 1: "1d4",
2: "1d6", 3: "2d6", 4: "3d6", 5: "4d6", 6: "5d6"}
def randattr(time: int = 3, ex: int = 0):
r = 0
for _ in range(time):
r += random.randint(1, 6)
return (r+ex)*5
class Investigator(object):
def __init__(self) -> None:
self.age = 20
self.str = randattr()
self.con = randattr()
self.siz = randattr(2, 6)
self.dex = randattr()
self.app = randattr()
self.int = randattr(2, 6)
self.pow = randattr()
self.edu = randattr(2, 6)
self.luc = randattr()
def body_build(self) -> int:
build = self.str + self.con
for i, j in build_dict.items():
if build <= i:
return j
return
def db(self) -> str:
return db_dict[self.body_build()]
def lp_max(self) -> int:
return (self.con+self.siz)//10
def mov(self) -> int:
r = 8
if self.age >= 80:
r -= 5
elif self.age >= 70:
r -= 4
elif self.age >= 60:
r -= 3
elif self.age >= 50:
r -= 2
elif self.age >= 40:
r -= 1
if self.str < self.siz and self.dex < self.siz:
return r-1
elif self.str > self.siz and self.dex > self.siz:
return r+1
else:
return r
def edu_up(self) -> str:
edu_check = random.randint(1, 100)
if edu_check > self.edu:
edu_en = random.randint(1, 10)
self.edu += edu_en
else:
return "教育成长检定D100=%d,小于%d,无增长。" % (edu_check, self.edu)
if self.edu > 99:
self.edu = 99
return "教育成长检定D100=%d成长1D10=%d成长到了最高值99" % (edu_check, edu_en)
else:
return "教育成长检定D100=%d成长1D10=%d,成长到了%d" % (edu_check, edu_en, self.edu)
def edu_ups(self, times) -> str:
r = ""
for _ in range(times):
r += self.edu_up()
return r
def sum_down(self, sum) -> str:
if self.str + self.con + self.dex-45 < sum:
self.str = 15
self.con = 15
self.dex = 15
else:
str_lost = random.randint(0, min(sum, self.str-15))
while sum - str_lost > self.con + self.dex-30:
str_lost = random.randint(0, min(sum, self.str-15))
self.str -= str_lost
sum -= str_lost
con_lost = random.randint(0, min(sum, self.con-15))
while sum - con_lost > self.dex-15:
con_lost = random.randint(0, min(sum, self.con-15))
self.con -= con_lost
sum -= con_lost
self.dex -= sum
return
def age_change(self, age: int = 20) -> str:
if age < 15:
return "年龄过小,无法担当调查员"
elif age >= 90:
return "该调查员已经作古。"
self.age = age
if 15 <= age < 20:
self.str -= 5
self.siz -= 5
self.edu -= 5
luc = randattr()
self.luc = luc if luc > self.luc else self.luc
return "力量、体型、教育值-5幸运增强判定一次"
elif age < 40:
self.edu_up()
return "教育增强判定一次"
elif age < 50:
self.app -= 5
self.sum_down(5)
self.edu_ups(2)
return "外貌-5力量、体型、敏捷合计降低5教育增强判定两次"
elif age < 60:
self.app -= 10
self.sum_down(10)
self.edu_ups(3)
return "外貌-10力量、体型、敏捷合计降低10教育增强判定三次"
elif age < 70:
self.app -= 15
self.sum_down(20)
self.edu_ups(4)
return "外貌-15力量、体型、敏捷合计降低20教育增强判定四次"
elif age < 80:
self.app -= 20
self.sum_down(40)
self.edu_ups(4)
return "外貌-20力量、体型、敏捷合计降低40教育增强判定四次"
elif age < 90:
self.app -= 25
self.sum_down(80)
self.edu_ups(4)
return "外貌-25力量、体型、敏捷合计降低80教育增强判定四次"
def __repr__(self) -> str:
return "调查员 年龄:%d\n力量:%d 体质:%d 体型:%d\n敏捷:%d 外貌:%d 智力:%d\n意志:%d 教育:%d 幸运:%d\nDB:%s 生命值:%d 移动速度:%d" % (
self.age, self.str, self.con, self.siz, self.dex, self.app, self.int, self.pow, self.edu, self.luc, self.db(), self.lp_max(), self.mov())
def output(self) -> str:
return self.__repr__()

View File

@ -0,0 +1,249 @@
# 参考[OlivaDiceDocs](https://oliva.dicer.wiki/userdoc)实现的nonebot2骰娘插件
import re
import random
from .messages import *
class Mylist(list):
def next(self, index: int):
if index < self.__len__()-1:
return self[index+1]
else:
return ""
def help_message():
return main_help_message
def dhr(t, o):
if t == 0 and o == 0:
return 100
else:
return t*10+o
def st():
result = random.randint(1, 20)
if result < 4:
rstr = "右腿"
elif result < 7:
rstr = "左腿"
elif result < 11:
rstr = "腹部"
elif result < 16:
rstr = "胸部"
elif result < 18:
rstr = "右臂"
elif result < 20:
rstr = "左臂"
elif result < 21:
rstr = "头部"
return "D20=%d:命中了%s" % (result, rstr)
def en(arg: str) -> str:
try:
arg = int(arg)
except:
return en_help_message
check = random.randint(1, 100)
if check > arg or check > 95:
plus = random.randint(1, 10)
r = "判定值%d,判定成功,技能成长%d+%d=%d" % (check, arg, plus, arg+plus)
return r + "\n温馨提示如果技能提高到90%或更高增加2D6理智点数。"
else:
return "判定值%d,判定失败,技能无成长。" % check
class Dices(object):
def __init__(self):
self.dices = 1
self.faces = 100
self.a = False
self.anum = 0
self.h = False
self.times = 1
self.bp = 0
self._bp_result = ""
self._tens_place = None
self._ones_place = None
self._head = ""
self._mid = ""
self._end = ""
self.result = 0
self.a_check_mode = self.a_check
self._a_check_result = ""
self.ex_dice = None
self.ex_dice_type = 1
self._ex_result = ""
def real_dice(self):
if self.faces == 100:
self._tens_place = random.randint(0, 9)
self._ones_place = random.randint(0, 9)
self.result += dhr(self._tens_place, self._ones_place)
return dhr(self._tens_place, self._ones_place)
else:
rint = random.randint(1, self.faces)
self.result += rint
return rint
def bp_dice(self):
if not self.bp or self.faces != 100 or self.dices != 1:
self._bp_result = ""
return self._bp_result
self._bp_result = " -> 十位:%d,个位:%d" % (
self._tens_place, self._ones_place)
bp = self.bp
while bp > 0:
bd = random.randint(0, 9)
self._bp_result += ",奖励:%d" % bd
if dhr(bd, self._ones_place) < dhr(self._tens_place, self._ones_place):
self._tens_place = bd
self.result = dhr(self._tens_place, self._ones_place)
bp -= 1
while bp < 0:
bd = random.randint(0, 9)
self._bp_result += ",惩罚:%d" % bd
if dhr(bd, self._ones_place) > dhr(self._tens_place, self._ones_place):
self._tens_place = bd
self.set_result()
bp += 1
return self._bp_result
def a_check(self):
if not (self.a and self.anum and self.faces == 100 and self.dices == 1):
self._a_check_result = ""
return self._a_check_result
if self.result == 100:
self._a_check_result = " 大失败!"
elif self.anum < 50 and self.result > 95:
self._a_check_result = "\n检定值%d %d>95 大失败!" % (
self.anum, self.result)
elif self.result == 1:
self._a_check_result = " 大成功!"
elif self.result <= self.anum // 5:
self._a_check_result = "\n检定值%d %d%d 极难成功" % (
self.anum, self.result, self.anum // 5)
elif self.result <= self.anum // 2:
self._a_check_result = "\n检定值%d %d%d 困难成功" % (
self.anum, self.result, self.anum // 2)
elif self.result <= self.anum:
self._a_check_result = "\n检定值%d %d%d 成功" % (
self.anum, self.result, self.anum)
else:
self._a_check_result = "\n检定值%d %d>%d 失败" % (
self.anum, self.result, self.anum)
return self._a_check_result
def xdy(self):
self.result = 0
if self.dices == 1:
self.real_dice()
self.bp_dice()
self.a_check()
return ""
else:
dice_results = []
for _ in range(self.dices):
dice_result = self.real_dice()
dice_results.append(str(dice_result))
return "(%s)" % "+".join(dice_results)
def _ex_handle(self):
if not self.ex_dice:
self._ex_result = ""
elif type(self.ex_dice) == int:
ex_result = self.ex_dice_type*self.ex_dice
self._ex_result = "%s%s%d" % (str(
self.result) if self.dices == 1 else "", "+" if self.ex_dice_type == 1 else "-", self.ex_dice)
self.result += ex_result
elif type(self.ex_dice) == Dices:
self.ex_dice.roll
ex_result = self.ex_dice_type*self.ex_dice.result
self._ex_result = "%s%s%d" % (str(
self.result) if self.dices == 1 else "", "+" if self.ex_dice_type == 1 else "-", self.ex_dice)
self.result += ex_result
return self._ex_result
def roll(self):
r = "%d次投掷:" % self.times
if self.times != 1:
r += "\n"
for _ in range(self.times):
xdyr = self.xdy()
self._ex_handle()
self._head = "%sD%d%s=" % (
"" if self.dices == 1 else str(self.dices),
self.faces,
"" if not self.ex_dice else (
("+" if self.ex_dice_type == 1 else "-") + str(self.ex_dice) if type(self.ex_dice) == int else (str(self.ex_dice.dices)+"D"+self.ex_dice.faces))
)
self._mid = "%s%s=" % (xdyr, self._ex_result)
self._end = "%d%s%s" % (
self.result, self._bp_result, self._a_check_result)
r += "%s%s%s" % (self._head, self._mid if self.dices !=
1 or self.ex_dice else "", self._end)
self.times -= 1
if self.times:
r += "\n"
return r
def prework(args: list, start=0):
for i in range(start, len(args), 1):
if not re.search("\\d+", args[i]) and len(args[i]) > 1:
p = args.pop(i)
for j in list(p):
args.insert(i, j)
i += 1
if prework(args, i):
break
return True
def rd(arg: str):
try:
h = False
dices = Dices()
args = re.split("(\\d+)", arg.lower())
prework(args)
args = Mylist(args)
for i in range(len(args)):
if args[i] == "a":
dices.a = True
elif args[i] == "#" and re.search("\\d+", args.next(i)):
dices.times = int(args[i+1])
elif args[i] == "b":
dices.bp += 1
elif args[i] == "p":
dices.bp -= 1
elif args[i] == "d" and re.search("\\d+", args.next(i)):
dices.faces = int(args[i+1])
elif args[i] == " " and re.search("\\d+", args.next(i)) and dices.a:
dices.anum = int(args[i+1])
elif args[i] == "h":
h = True
elif re.search("\\d+", args[i]):
if args.next(i) == "d":
dices.dices = int(args[i])
elif args[i-1] == " " and dices.a:
dices.anum = int(args[i])
elif args[i] in ["-", "+"]:
dices.ex_dice_type = (-1 if args[i] == "-" else 1)
if args.next(i+1) == "d":
dices.ex_dice = Dices()
dices.ex_dice.dices = int(args.next(i))
dices.ex_dice.faces = int(args.next(i+2))
elif args.next(i):
dices.ex_dice = int(args.next(i))
if h:
return [dices.roll()]
return dices.roll()
except:
return r_help_message
if __name__ == "__main__":
rd("2d100")

View File

@ -0,0 +1,36 @@
import random
from .messages import temporary_madness, madness_end, phobias, manias
def ti():
i = random.randint(1, 10)
r = "临时疯狂判定1D10=%d\n" % i
r += temporary_madness[i-1]
if i == 9:
j = random.randint(1, 100)
r += "\n恐惧症状为:\n"
r += phobias[j-1]
elif i == 10:
j = random.randint(1, 100)
r += "\n狂躁症状为:\n"
r += manias[j-1]
r += "\n该症状将会持续1D10=%d" % random.randint(1, 10)
return r
def li():
i = random.randint(1, 10)
r = "总结疯狂判定1D10=%d\n" % i
r += madness_end[i-1]
if i in [2, 3, 6, 9, 10]:
r += "\n调查员将在1D10=%d小时后醒来" % random.randint(1, 10)
if i == 9:
j = random.randint(1, 100)
r += "\n恐惧症状为:\n"
r += phobias[j-1]
elif i == 10:
j = random.randint(1, 100)
r += "\n狂躁症状为:\n"
r += manias[j-1]
return r

View File

@ -0,0 +1,258 @@
main_help_message: str = "本骰娘由nonebot2强力驱动\n" \
".r 投掷指令 todo\n" \
" d 制定骰子面数\n" \
" a 检定\n" \
" h 暗骰\n" \
" # 多轮检定\n" \
" bp 奖励骰&惩罚骰\n" \
" +/- 附加计算 todo\n" \
".sc 疯狂检定\n" \
".st 射击命中判定\n" \
".ti 临时疯狂症状\n" \
".li 总结疯狂症状\n" \
".coc coc角色作成\n" \
".en 技能成长"
r_help_message: str = ".r[dah#bp] a_number [+/-]ex_number\n" \
"d骰子设定指令,标准格式为xdyx为骰子数量y为骰子面数\n" \
"a检定指令根据后续a_number设定数值检定\n" \
"h暗骰指令骰子结构将会私聊发送给该指令者\n" \
"#:多轮投掷指令,#后接数字即可设定多轮投掷;\n" \
"bp奖励骰与惩罚骰\n" \
"+/-:附加计算指令,目前仅支持数字\n" \
"示例:\n" \
".r#2bba 70两次投掷 1D100 附加两个奖励骰判定值为70\n" \
".rahD100暗骰由于没有 a_number 参数,判定将被忽略\n" \
".ra2d8+10 702D8+10由于非D100判定将被忽略"
sc_help_message: str = ".sc success/failure san_number\n" \
"success判定成功降低 san 值,支持 x 或 xdy 语法( x 与 y 为数字);\n" \
"failure判定失败降低 san 值,支持语法如上;\n" \
"san_number当前 san 值。"
en_help_message: str = ".en skill_level\nskill_level需要成长的技能当前等级。"
temporary_madness = [
"1) 失忆: 调查员会发现自己身处于一个安全的地点却没有任何来到这里的记忆。例如调查员前一刻还在家中吃着早饭下一刻就已经直面着不知名的怪物。这将会持续1D10轮。",
"2) 假性残疾:调查员陷入了心理性的失明失聪以及躯体缺失感中持续1D10轮。",
"3) 暴力倾向: 调查员陷入了六亲不认的暴力行为中对周围的敌人与友方进行着无差别的攻击持续1D10轮。",
"4) 偏执: 调查员陷入了严重的偏执妄想之中持续1D10轮。有人在暗中窥视着他们同伴中有人背叛了他们没有人可以信任万事皆虚。",
"5) 人际依赖: 守密人适当参考调查员的背景中重要之人的条目调查员因为一些原因而降他人误认为了他重要的人并且努力的会与那个人保持那种关系持续1D10轮。",
"6) 昏厥: 调查员当场昏倒并需要1D10轮才能苏醒。",
"7) 逃避行为: 调查员会用任何的手段试图逃离现在所处的位置即使这意味着开走唯一一辆交通工具并将其它人抛诸脑后调查员会试图逃离1D10轮。",
"8) 竭嘶底里:调查员表现出大笑哭泣嘶吼害怕等的极端情绪表现持续1D10轮。",
"9) 恐惧: 调查员通过一次D100或者由守密人选择来从恐惧症状表中选择一个恐惧源就算这一恐惧的事物是并不存在的调查员的症状会持续1D10轮。",
"10) 躁狂: 调查员通过一次D100或者由守密人选择来从躁狂症状表中选择一个躁狂的诱因这个症状将会持续1D10轮。"
]
madness_end = [
"1) 失忆Amnesia回过神来调查员们发现自己身处一个陌生的地方并忘记了自己是谁。记忆会随时间恢复。",
"2) 被窃Robbed调查员在1D10小时后恢复清醒发觉自己被盗身体毫发无损。如果调查员携带着宝贵之物见调查员背景做幸运检定来决定其是否被盗。所有有价值的东西无需检定自动消失。",
"3) 遍体鳞伤Battered调查员在1D10小时后恢复清醒发现自己身上满是拳痕和瘀伤。生命值减少到疯狂前的一半但这不会造成重伤。调查员没有被窃。这种伤害如何持续到现在由守秘人决定。",
"4) 暴力倾向Violence调查员陷入强烈的暴力与破坏欲之中。调查员回过神来可能会理解自己做了什么也可能毫无印象。调查员对谁或何物施以暴力他们是杀人还是仅仅造成了伤害由守秘人决定。",
"5) 极端信念Ideology/Beliefs查看调查员背景中的思想信念调查员会采取极端和疯狂的表现手段展示他们的思想信念之一。比如一个信教者会在地铁上高声布道。",
"6) 重要之人Significant People考虑调查员背景中的重要之人及其重要的原因。在1D10小时或更久的时间中调查员将不顾一切地接近那个人并为他们之间的关系做出行动。",
"7) 被收容Institutionalized调查员在精神病院病房或警察局牢房中回过神来他们可能会慢慢回想起导致自己被关在这里的事情。",
"8) 逃避行为Flee in panic调查员恢复清醒时发现自己在很远的地方也许迷失在荒郊野岭或是在驶向远方的列车或长途汽车上。",
"9) 恐惧Phobia调查员患上一个新的恐惧症状。在表Ⅸ恐惧症状表上骰1个D100来决定症状或由守秘人选择一个。调查员在1D10小时后回过神来并开始为避开恐惧源而采取任何措施。",
"10) 狂躁Mania调查员患上一个新的狂躁症状。在表狂躁症状表上骰1个D100来决定症状或由守秘人选择一个。调查员会在1D10小时后恢复理智。在这次疯狂发作中调查员将完全沉浸于其新的狂躁症状。这症状是否会表现给旁人则取决于守秘人和此调查员。"
]
phobias = [
"1) 洗澡恐惧症Ablutophobia对于洗涤或洗澡的恐惧。",
"2) 恐高症Acrophobia对于身处高处的恐惧。",
"3) 飞行恐惧症Aerophobia对飞行的恐惧。",
"4) 广场恐惧症Agoraphobia对于开放的拥挤公共场所的恐惧。",
"5) 恐鸡症Alektorophobia对鸡的恐惧。",
"6) 大蒜恐惧症Alliumphobia对大蒜的恐惧。",
"7) 乘车恐惧症Amaxophobia对于乘坐地面载具的恐惧。",
"8) 恐风症Ancraophobia对风的恐惧。",
"9) 男性恐惧症Androphobia对于成年男性的恐惧。",
"10) 恐英症Anglophobia对英格兰或英格兰文化的恐惧。",
"11) 恐花症Anthophobia对花的恐惧。",
"12) 截肢者恐惧症Apotemnophobia对截肢者的恐惧。",
"13) 蜘蛛恐惧症Arachnophobia对蜘蛛的恐惧。",
"14) 闪电恐惧症Astraphobia对闪电的恐惧。",
"15) 废墟恐惧症Atephobia对遗迹或残址的恐惧。",
"16) 长笛恐惧症Aulophobia对长笛的恐惧。",
"17) 细菌恐惧症Bacteriophobia对细菌的恐惧。",
"18) 导弹/子弹恐惧症Ballistophobia对导弹或子弹的恐惧。",
"19) 跌落恐惧症Basophobia对于跌倒或摔落的恐惧。",
"20) 书籍恐惧症Bibliophobia对书籍的恐惧。",
"21) 植物恐惧症Botanophobia对植物的恐惧。",
"22) 美女恐惧症Caligynephobia对美貌女性的恐惧。",
"23) 寒冷恐惧症Cheimaphobia对寒冷的恐惧。",
"24) 恐钟表症Chronomentrophobia对于钟表的恐惧。",
"25) 幽闭恐惧症Claustrophobia对于处在封闭的空间中的恐惧。",
"26) 小丑恐惧症Coulrophobia对小丑的恐惧。",
"27) 恐犬症Cynophobia对狗的恐惧。",
"28) 恶魔恐惧症Demonophobia对邪灵或恶魔的恐惧。",
"29) 人群恐惧症Demophobia对人群的恐惧。",
"30) 牙科恐惧症①Dentophobia对牙医的恐惧。",
"31) 丢弃恐惧症Disposophobia对于丢弃物件的恐惧贮藏癖",
"32) 皮毛恐惧症Doraphobia对动物皮毛的恐惧。",
"33) 过马路恐惧症Dromophobia对于过马路的恐惧。",
"34) 教堂恐惧症Ecclesiophobia对教堂的恐惧。",
"35) 镜子恐惧症Eisoptrophobia对镜子的恐惧。",
"36) 针尖恐惧症Enetophobia对针或大头针的恐惧。",
"37) 昆虫恐惧症Entomophobia对昆虫的恐惧。",
"38) 恐猫症Felinophobia对猫的恐惧。",
"39) 过桥恐惧症Gephyrophobia对于过桥的恐惧。",
"40) 恐老症Gerontophobia对于老年人或变老的恐惧。",
"41) 恐女症Gynophobia对女性的恐惧。",
"42) 恐血症Haemaphobia对血的恐惧。",
"43) 宗教罪行恐惧症Hamartophobia对宗教罪行的恐惧。",
"44) 触摸恐惧症Haphophobia对于被触摸的恐惧。",
"45) 爬虫恐惧症Herpetophobia对爬行动物的恐惧。",
"46) 迷雾恐惧症Homichlophobia对雾的恐惧。",
"47) 火器恐惧症Hoplophobia对火器的恐惧。",
"48) 恐水症Hydrophobia对水的恐惧。",
"49) 催眠恐惧症Hypnophobia对于睡眠或被催眠的恐惧。",
"50) 白袍恐惧症Iatrophobia对医生的恐惧。",
"51) 鱼类恐惧症Ichthyophobia对鱼的恐惧。",
"52) 蟑螂恐惧症Katsaridaphobia对蟑螂的恐惧。",
"53) 雷鸣恐惧症Keraunophobia对雷声的恐惧。",
"54) 蔬菜恐惧症Lachanophobia对蔬菜的恐惧。",
"55) 噪音恐惧症Ligyrophobia对刺耳噪音的恐惧。",
"56) 恐湖症Limnophobia对湖泊的恐惧。",
"57) 机械恐惧症Mechanophobia对机器或机械的恐惧。",
"58) 巨物恐惧症Megalophobia对于庞大物件的恐惧。",
"59) 捆绑恐惧症Merinthophobia对于被捆绑或紧缚的恐惧。",
"60) 流星恐惧症Meteorophobia对流星或陨石的恐惧。",
"61) 孤独恐惧症Monophobia对于一人独处的恐惧。",
"62) 不洁恐惧症Mysophobia对污垢或污染的恐惧。",
"63) 黏液恐惧症Myxophobia对黏液史莱姆的恐惧。",
"64) 尸体恐惧症Necrophobia对尸体的恐惧。",
"65) 数字8恐惧症Octophobia对数字8的恐惧。",
"66) 恐牙症Odontophobia对牙齿的恐惧。",
"67) 恐梦症Oneirophobia对梦境的恐惧。",
"68) 称呼恐惧症Onomatophobia对于特定词语的恐惧。",
"69) 恐蛇症Ophidiophobia对蛇的恐惧。",
"70) 恐鸟症Ornithophobia对鸟的恐惧。",
"71) 寄生虫恐惧症Parasitophobia对寄生虫的恐惧。",
"72) 人偶恐惧症Pediophobia对人偶的恐惧。",
"73) 吞咽恐惧症Phagophobia对于吞咽或被吞咽的恐惧。",
"74) 药物恐惧症Pharmacophobia对药物的恐惧。",
"75) 幽灵恐惧症Phasmophobia对鬼魂的恐惧。",
"76) 日光恐惧症Phenogophobia对日光的恐惧。",
"77) 胡须恐惧症Pogonophobia对胡须的恐惧。",
"78) 河流恐惧症Potamophobia对河流的恐惧。",
"79) 酒精恐惧症Potophobia对酒或酒精的恐惧。",
"80) 恐火症Pyrophobia对火的恐惧。",
"81) 魔法恐惧症Rhabdophobia对魔法的恐惧。",
"82) 黑暗恐惧症Scotophobia对黑暗或夜晚的恐惧。",
"83) 恐月症Selenophobia对月亮的恐惧。",
"84) 火车恐惧症Siderodromophobia对于乘坐火车出行的恐惧。",
"85) 恐星症Siderophobia对星星的恐惧。",
"86) 狭室恐惧症Stenophobia对狭小物件或地点的恐惧。",
"87) 对称恐惧症Symmetrophobia对对称的恐惧。",
"88) 活埋恐惧症Taphephobia对于被活埋或墓地的恐惧。",
"89) 公牛恐惧症Taurophobia对公牛的恐惧。",
"90) 电话恐惧症Telephonophobia对电话的恐惧。",
"91) 怪物恐惧症①Teratophobia对怪物的恐惧。",
"92) 深海恐惧症Thalassophobia对海洋的恐惧。",
"93) 手术恐惧症Tomophobia对外科手术的恐惧。",
"94) 十三恐惧症Triskadekaphobia对数字13的恐惧症。",
"95) 衣物恐惧症Vestiphobia对衣物的恐惧。",
"96) 女巫恐惧症Wiccaphobia对女巫与巫术的恐惧。",
"97) 黄色恐惧症Xanthophobia对黄色或“黄”字的恐惧。",
"98) 外语恐惧症Xenoglossophobia对外语的恐惧。",
"99) 异域恐惧症Xenophobia对陌生人或外国人的恐惧。",
"100) 动物恐惧症Zoophobia对动物的恐惧。"
]
manias = [
"1) 沐浴癖Ablutomania执着于清洗自己。",
"2) 犹豫癖Aboulomania病态地犹豫不定。",
"3) 喜暗狂Achluomania对黑暗的过度热爱。",
"4) 喜高狂Acromaniaheights狂热迷恋高处。",
"5) 亲切癖Agathomania病态地对他人友好。",
"6) 喜旷症Agromania强烈地倾向于待在开阔空间中。",
"7) 喜尖狂Aichmomania痴迷于尖锐或锋利的物体。",
"8) 恋猫狂Ailuromania近乎病态地对猫友善。",
"9) 疼痛癖Algomania痴迷于疼痛。",
"10) 喜蒜狂Alliomania痴迷于大蒜。",
"11) 乘车癖Amaxomania痴迷于乘坐车辆。",
"12) 欣快癖Amenomania不正常地感到喜悦。",
"13) 喜花狂Anthomania痴迷于花朵。",
"14) 计算癖Arithmomania狂热地痴迷于数字。",
"15) 消费癖Asoticamania鲁莽冲动地消费。",
"16) 隐居癖Automania过度地热爱独自隐居原文如此存疑Automania实际上是恋车癖",
"17) 芭蕾癖Balletmania痴迷于芭蕾舞。",
"18) 窃书癖Biliokleptomania无法克制偷窃书籍的冲动。",
"19) 恋书狂Bibliomania痴迷于书籍和/或阅读。",
"20) 磨牙癖Bruxomania无法克制磨牙的冲动。",
"21) 灵臆症Cacodemomania病态地坚信自己已被一个邪恶的灵体占据。",
"22) 美貌狂Callomania痴迷于自身的美貌。",
"23) 地图狂Cartacoethes在何时何处都无法控制查阅地图的冲动。",
"24) 跳跃狂Catapedamania痴迷于从高处跳下。",
"25) 喜冷症Cheimatomania对寒冷或寒冷的物体的反常喜爱。",
"26) 舞蹈狂Choreomania无法控制地起舞或发颤。",
"27) 恋床癖Clinomania过度地热爱待在床上。",
"28) 恋墓狂Coimetormania痴迷于墓地。",
"29) 色彩狂Coloromania痴迷于某种颜色。",
"30) 小丑狂Coulromania痴迷于小丑。",
"31) 恐惧狂Countermania执着于经历恐怖的场面。",
"32) 杀戮癖Dacnomania痴迷于杀戮。",
"33) 魔臆症Demonomania病态地坚信自己已被恶魔附身。",
"34) 抓挠癖Dermatillomania执着于抓挠自己的皮肤。",
"35) 正义狂Dikemania痴迷于目睹正义被伸张。",
"36) 嗜酒狂Dipsomania反常地渴求酒精。",
"37) 毛皮狂Doramania痴迷于拥有毛皮。存疑",
"38) 赠物癖Doromania痴迷于赠送礼物。",
"39) 漂泊症Drapetomania执着于逃离。",
"40) 漫游癖Ecdemiomania执着于四处漫游。",
"41) 自恋狂Egomania近乎病态地以自我为中心或自我崇拜。",
"42) 职业狂Empleomania对于工作的无尽病态渴求。",
"43) 臆罪症Enosimania病态地坚信自己带有罪孽。",
"44) 学识狂Epistemomania痴迷于获取学识。",
"45) 静止癖Eremiomania执着于保持安静。",
"46) 乙醚上瘾Etheromania渴求乙醚。",
"47) 求婚狂Gamomania痴迷于进行奇特的求婚。",
"48) 狂笑癖Geliomania无法自制地强迫性的大笑。",
"49) 巫术狂Goetomania痴迷于女巫与巫术。",
"50) 写作癖Graphomania痴迷于将每一件事写下来。",
"51) 裸体狂Gymnomania执着于裸露身体。",
"52) 妄想狂Habromania近乎病态地充满愉快的妄想而不顾现实状况如何",
"53) 蠕虫狂Helminthomania过度地喜爱蠕虫。",
"54) 枪械狂Hoplomania痴迷于火器。",
"55) 饮水狂Hydromania反常地渴求水分。",
"56) 喜鱼癖Ichthyomania痴迷于鱼类。",
"57) 图标狂Iconomania痴迷于图标与肖像。",
"58) 偶像狂Idolomania痴迷于甚至愿献身于某个偶像。",
"59) 信息狂Infomania痴迷于积累各种信息与资讯。",
"60) 射击狂Klazomania反常地执着于射击。",
"61) 偷窃癖Kleptomania反常地执着于偷窃。",
"62) 噪音癖Ligyromania无法自制地执着于制造响亮或刺耳的噪音。",
"63) 喜线癖Linonomania痴迷于线绳。",
"64) 彩票狂Lotterymania极端地执着于购买彩票。",
"65) 抑郁症Lypemania近乎病态的重度抑郁倾向。",
"66) 巨石狂Megalithomania当站在石环中或立起的巨石旁时就会近乎病态地写出各种奇怪的创意。",
"67) 旋律狂Melomania痴迷于音乐或一段特定的旋律。",
"68) 作诗癖Metromania无法抑制地想要不停作诗。",
"69) 憎恨癖Misomania憎恨一切事物痴迷于憎恨某个事物或团体。",
"70) 偏执狂Monomania近乎病态地痴迷与专注某个特定的想法或创意。",
"71) 夸大癖Mythomania以一种近乎病态的程度说谎或夸大事物。",
"72) 臆想症Nosomania妄想自己正在被某种臆想出的疾病折磨。",
"73) 记录癖Notomania执着于记录一切事物例如摄影",
"74) 恋名狂Onomamania痴迷于名字人物的、地点的、事物的",
"75) 称名癖Onomatomania无法抑制地不断重复某个词语的冲动。",
"76) 剔指癖Onychotillomania执着于剔指甲。",
"77) 恋食癖Opsomania对某种食物的病态热爱。",
"78) 抱怨癖Paramania一种在抱怨时产生的近乎病态的愉悦感。",
"79) 面具狂Personamania执着于佩戴面具。",
"80) 幽灵狂Phasmomania痴迷于幽灵。",
"81) 谋杀癖Phonomania病态的谋杀倾向。",
"82) 渴光癖Photomania对光的病态渴求。",
"83) 背德癖Planomania病态地渴求违背社会道德原文如此存疑Planomania实际上是漂泊症",
"84) 求财癖Plutomania对财富的强迫性的渴望。",
"85) 欺骗狂Pseudomania无法抑制的执着于撒谎。",
"86) 纵火狂Pyromania执着于纵火。",
"87) 提问狂Questiong-Asking Mania执着于提问。",
"88) 挖鼻癖Rhinotillexomania执着于挖鼻子。",
"89) 涂鸦癖Scribbleomania沉迷于涂鸦。",
"90) 列车狂Siderodromomania认为火车或类似的依靠轨道交通的旅行方式充满魅力。",
"91) 臆智症Sophomania臆想自己拥有难以置信的智慧。",
"92) 科技狂Technomania痴迷于新的科技。",
"93) 臆咒狂Thanatomania坚信自己已被某种死亡魔法所诅咒。",
"94) 臆神狂Theomania坚信自己是一位神灵。",
"95) 抓挠癖Titillomaniac抓挠自己的强迫倾向。",
"96) 手术狂Tomomania对进行手术的不正常爱好。",
"97) 拔毛癖Trichotillomania执着于拔下自己的头发。",
"98) 臆盲症Typhlomania病理性的失明。",
"99) 嗜外狂Xenomania痴迷于异国的事物。",
"100) 喜兽癖Zoomania对待动物的态度近乎疯狂地友好。"
]

View File

@ -0,0 +1,38 @@
from .data_source import Dices
from .messages import sc_help_message
import re
def number_or_dice(arg: str):
if "d" in arg:
d = Dices()
if dices := re.search(r"\d+d", arg):
d.dices = int(dices.group()[:-1])
if faces := re.search(r"d\d+", arg):
d.faces = int(faces.group()[1:])
d.roll()
return d
else:
return int(arg)
def sc(arg: str) -> str:
a_num = re.search(r" \d+", arg)
success = re.search(r"\d*d\d+|\d+", arg)
failure = re.search(r"[\/]+(\d*d\d+|\d+)", arg)
if not (a_num and success and failure):
return sc_help_message
check_dice = Dices()
check_dice.a = True
check_dice.anum = int(a_num.group()[1:])
success = number_or_dice(success.group())
failure = number_or_dice(failure.group()[1:])
r = "San Check" + check_dice.roll()[4:]
result = success if check_dice.result <= check_dice.anum else failure
r += "\n理智降低了"
if type(result) == int:
r += "%d" % result
else:
r = r + result._head + str(result.result)
return r

View File

@ -0,0 +1,110 @@
from nonebot.plugin import on_shell_command, get_loaded_plugins, export
from nonebot.matcher import Matcher
from nonebot.typing import T_State
from nonebot.exception import IgnoredException
from nonebot.message import run_preprocessor
from nonebot.adapters.cqhttp import Event, Bot, GroupMessageEvent, PrivateMessageEvent
from configs.config import plugins2name_dict
from models.ban_user import BanUser
from .data import (
block_plugin,
unblock_plugin,
get_group_plugin_list,
auto_update_plugin_list,
)
from .parser import npm_parser
# 导出给其他插件使用
export = export()
export.block_plugin = block_plugin
export.unblock_plugin = unblock_plugin
export.unblock_plugin = unblock_plugin
export.get_group_plugin_list = get_group_plugin_list
# 注册 shell_like 事件响应器
plugin_manager = on_shell_command("npm", parser=npm_parser, priority=1)
# 在 Matcher 运行前检测其是否启用
@run_preprocessor
async def _(matcher: Matcher, bot: Bot, event: Event, state: T_State):
plugin = matcher.module
group_id = _get_group_id(event)
loaded_plugin_list = _get_loaded_plugin_list()
plugin_list = auto_update_plugin_list(loaded_plugin_list)
# 无视本插件的 Matcher
if plugin not in plugins2name_dict or matcher.priority in [1, 9] or await BanUser.isban(event.user_id):
return
try:
if isinstance(event, PrivateMessageEvent) and plugin_list[plugin]["default"]:
return
except:
pass
# print(matcher.module)
# print(f'plugin_list[plugin]["default"] = {plugin_list[plugin]["default"]}')
# print(f'{matcher.module} -> this is hook')
if not plugin_list[plugin]["default"]:
if event.message_type == 'group':
await bot.send_group_msg(group_id=event.group_id, message='此功能正在维护...')
else:
await bot.send_private_msg(user_id=event.user_id, message='此功能正在维护...')
raise IgnoredException(f"Nonebot Plugin Manager has blocked {plugin} !")
# print(plugin_list[plugin])
# print(group_id)
# print(plugin_list[plugin][group_id])
# print(not plugin_list[plugin][group_id])
if group_id in plugin_list[plugin]:
if not plugin_list[plugin][group_id]:
if plugin != 'ai' and matcher.type == 'message':
await bot.send_group_msg(group_id=event.group_id, message='该群未开启此功能..')
raise IgnoredException(f"Nonebot Plugin Manager has blocked {plugin} !")
@plugin_manager.handle()
async def _(bot: Bot, event: Event, state: T_State):
args = state["args"]
group_id = _get_group_id(event)
is_admin = _is_admin(event)
is_superuser = _is_superuser(bot, event)
if group_id == 0:
group_id = 'default'
if hasattr(args, "handle"):
await plugin_manager.finish(args.handle(args, group_id, is_admin, is_superuser))
# 获取插件列表,并自动排除本插件
def _get_loaded_plugin_list() -> list:
return list(
filter(
lambda plugin: plugin != "nonebot_plugin_manager",
map(lambda plugin: plugin.name, get_loaded_plugins()),
)
)
def _get_group_id(event: Event) -> str:
try:
group_id = event.group_id
except AttributeError:
group_id = "default"
return str(group_id) if group_id else "default"
def _is_admin(event: Event) -> bool:
return (
event.sender.role in ["admin", "owner"]
if isinstance(event, GroupMessageEvent)
else False
)
def _is_superuser(bot: Bot, event: Event) -> bool:
return str(event.user_id) in bot.config.superusers
plugins_dict = {
}

View File

@ -0,0 +1,121 @@
import json
import httpx
from pathlib import Path
from configs.config import plugins2name_dict
_DATA_PATH = Path() / "data" / "manager" / "plugin_list.json"
def get_store_plugin_info(plugin: str) -> str:
store_plugin_list = _get_store_plugin_list()
if plugin in store_plugin_list:
plugin = store_plugin_list[plugin]
return (
f"ID: {plugin['id']}\n"
f"Name: {plugin['name']}\n"
f"Description: {plugin['desc']}\n"
f"Version: {httpx.get('https://pypi.org/pypi/'+plugin['link']+'/json').json()['info']['version']}\n"
f"Author: {plugin['author']}\n"
f"Repo: https://github.com/{plugin['repo']}"
)
else:
return "查无此插件!"
def get_group_plugin_list(group_id: str) -> dict:
plugin_list = _load_plugin_list()
group_plugin_list = {}
for plugin in plugin_list:
if group_id in plugin_list[plugin]:
group_plugin_list[plugin] = plugin_list[plugin][group_id]
else:
group_plugin_list[plugin] = plugin_list[plugin]["default"]
return group_plugin_list
def get_store_pulgin_list() -> str:
message = "商店插件列表如下:"
for plugin in _get_store_plugin_list():
if plugin in _load_plugin_list() or plugin == "nonebot_plugin_manager":
message += f"\n[o] {plugin}"
else:
message += f"\n[x] {plugin}"
return message
def auto_update_plugin_list(loaded_plugin_list: list, keep_history: bool = False):
plugin_list = _load_plugin_list()
for plugin in loaded_plugin_list:
if plugin not in plugin_list:
plugin_list[plugin] = {"default": True}
if not keep_history:
plugin_list = {
key: plugin_list[key] for key in plugin_list if key in loaded_plugin_list
}
_dump_plugin_list(plugin_list)
return plugin_list
def block_plugin(group_id: str, *plugins: str):
return _update_plugin_list(group_id, True, *plugins)
def unblock_plugin(group_id: str, *plugins: str):
return _update_plugin_list(group_id, False, *plugins)
# 获取商店插件列表
def _get_store_plugin_list() -> dict:
store_plugin_list = {}
for plugin in httpx.get(
"https://cdn.jsdelivr.net/gh/nonebot/nonebot2@master/docs/.vuepress/public/plugins.json"
).json():
store_plugin_list.update({plugin["id"]: plugin})
return store_plugin_list
# 更新插件列表
def _update_plugin_list(group_id: str, block: bool, *plugins: str) -> str:
plugin_list = _load_plugin_list()
message = "结果如下:"
operate = "屏蔽" if block else "启用"
for plugin in plugins:
for values in plugins2name_dict.values():
if plugin in values:
plugin = list(plugins2name_dict.keys())[list(plugins2name_dict.values()).index(values)]
# print(plugin)
break
message += "\n"
if plugin in plugin_list:
if (
not group_id in plugin_list[plugin]
or plugin_list[plugin][group_id] == block
):
plugin_list[plugin][group_id] = not block
message += f"插件{plugin}{operate}成功!"
print(plugin_list[plugin][group_id])
else:
message += f"插件{plugin}已经{operate}"
else:
message += f"插件{plugin}不存在!"
_dump_plugin_list(plugin_list)
return message
# 加载插件列表
def _load_plugin_list() -> dict:
try:
return json.load(_DATA_PATH.open("r", encoding="utf-8"))
except FileNotFoundError:
return {}
# 保存插件列表
def _dump_plugin_list(plugin_list: dict):
_DATA_PATH.parent.mkdir(parents=True, exist_ok=True)
json.dump(
plugin_list,
_DATA_PATH.open("w", encoding="utf-8"),
indent=4,
separators=(",", ": "),
)

View File

@ -0,0 +1,138 @@
from argparse import Namespace
from .data import *
def handle_list(
args: Namespace,
group_id: str,
is_admin: bool,
is_superuser: bool,
) -> str:
message = ""
if args.store:
if is_superuser:
return get_store_pulgin_list()
else:
return "获取商店插件列表需要超级用户权限!"
if args.default:
if is_superuser:
group_id = "default"
message += "默认"
else:
return "获取默认插件列表需要超级用户权限!"
if args.group:
if is_superuser:
group_id = args.group
message += f"{args.group}"
else:
return "获取指定群插件列表需要超级用户权限!"
message += "插件列表如下:\n"
message += "\n".join(
f"[{'o' if get_group_plugin_list(group_id)[plugin] else 'x'}] {plugin}"
for plugin in get_group_plugin_list(group_id)
)
return message
def handle_block(
args: Namespace,
group_id: str,
is_admin: bool,
is_superuser: bool,
) -> str:
if not is_admin and not is_superuser:
return "管理插件需要群管理员权限!"
message = ""
if args.default:
if is_superuser:
group_id = "default"
message += "默认"
else:
return "管理默认插件需要超级用户权限!"
if args.group:
if is_superuser:
group_id = args.group
message += f"{args.group}"
else:
return "管理指定群插件需要超级用户权限!"
message += block_plugin(group_id, *args.plugins)
return message
def handle_unblock(
args: Namespace,
group_id: str,
is_admin: bool,
is_superuser: bool,
) -> str:
message = ""
if not is_admin and not is_superuser:
return "管理插件需要群管理员权限!"
if args.default:
if is_superuser:
group_id = "default"
message += "默认"
else:
return "管理默认插件需要超级用户权限!"
if args.group:
if is_superuser:
group_id = args.group
message += f"{args.group}"
else:
return "管理指定群插件需要超级用户权限!"
message += unblock_plugin(group_id, *args.plugins)
return message
def handle_info(
args: Namespace,
group_id: str,
is_admin: bool,
is_superuser: bool,
) -> str:
if not is_admin and not is_superuser:
return "管理插件需要超级权限!"
return get_store_plugin_info(args.plugin)
def handle_install(
args: Namespace,
group_id: str,
is_admin: bool,
is_superuser: bool,
) -> str:
pass
def handle_update(
args: Namespace,
group_id: str,
is_admin: bool,
is_superuser: bool,
) -> str:
pass
def handle_uninstall(
args: Namespace,
group_id: str,
is_admin: bool,
is_superuser: bool,
) -> str:
pass

View File

@ -0,0 +1,60 @@
from nonebot.rule import ArgumentParser
from .handle import *
npm_parser = ArgumentParser("npm", add_help=False)
npm_parser.add_argument(
"-h", "--help", action="store_true", help="show this help message and exit"
)
npm_subparsers = npm_parser.add_subparsers()
list_parser = npm_subparsers.add_parser("list", help="show plugin list")
list_parser.add_argument(
"-s", "--store", action="store_true", help="show plugin store list"
)
list_parser.add_argument(
"-d", "--default", action="store_true", help="show default plugin list"
)
list_parser.add_argument("-g", "--group", action="store", help="show group plugin list")
list_parser.set_defaults(handle=handle_list)
block_parser = npm_subparsers.add_parser("block", help="block plugin")
block_parser.add_argument("plugins", nargs="*", help="plugins you want to block")
block_parser.add_argument("-d", "--default", action="store_true", help="set default")
block_parser.add_argument("-a", "--all", action="store_true", help="select all plugin")
block_parser.add_argument("-g", "--group", action="store", help="set in group")
block_parser.set_defaults(handle=handle_block)
unblock_parser = npm_subparsers.add_parser("unblock", help="unblock plugin")
unblock_parser.add_argument("plugins", nargs="*", help="plugins you want to unblock")
unblock_parser.add_argument("-d", "--default", action="store_true", help="set default")
unblock_parser.add_argument(
"-a", "--all", action="store_true", help="select all plugin"
)
unblock_parser.add_argument("-g", "--group", action="store", help="set in group")
unblock_parser.set_defaults(handle=handle_unblock)
info_parser = npm_subparsers.add_parser("info", help="show plugin info")
info_parser.add_argument("plugin", help="plugins you want to know")
info_parser.set_defaults(handle=handle_info)
install_parser = npm_subparsers.add_parser("install", help="install plugin")
install_parser.add_argument("plugins", nargs="*", help="plugins you want to install")
install_parser.add_argument("-i", "--index", action="store", help="point to a mirror")
install_parser.set_defaults(handle=handle_install)
update_parser = npm_subparsers.add_parser("update", help="update plugin")
update_parser.add_argument("plugins", nargs="*", help="plugins you want to update")
update_parser.add_argument("-a", "--all", action="store_true", help="select all plugin")
update_parser.add_argument("-i", "--index", action="store", help="point to a mirror")
update_parser.set_defaults(handle=handle_update)
uninstall_parser = npm_subparsers.add_parser("uninstall", help="uninstall plugin")
uninstall_parser.add_argument(
"plugins", nargs="*", help="plugins you want to uninstall"
)
uninstall_parser.add_argument(
"-a", "--all", action="store_true", help="select all plugin"
)
uninstall_parser.set_defaults(handle=handle_uninstall)

View File

@ -0,0 +1,149 @@
# -*- coding: utf-8 -*-
import traceback
from typing import Dict
from aiohttp.client_exceptions import ClientError
from nonebot.plugin import on_command, on_message
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
from nonebot.typing import T_State
from services.log import logger
from util.utils import get_message_text, get_message_imgs
from configs.config import MAX_FIND_IMG_COUNT
from .ex import get_des as get_des_ex
from .iqdb import get_des as get_des_iqdb
from .saucenao import get_des as get_des_sau
from .ascii2d import get_des as get_des_asc
from .trace import get_des as get_des_trace
from .yandex import get_des as get_des_yandex
async def get_des(url: str, mode: str, user_id: int):
"""
:param url: 图片链接
:param mode: 图源
:return:
"""
if mode == "iqdb":
async for msg in get_des_iqdb(url):
yield msg
elif mode == "ex":
async for msg in get_des_ex(url):
yield msg
elif mode == "trace":
async for msg in get_des_trace(url):
yield msg
elif mode == "yandex":
async for msg in get_des_yandex(url):
yield msg
elif mode.startswith("asc"):
async for msg in get_des_asc(url, user_id):
yield msg
else:
async for msg in get_des_sau(url, user_id):
yield msg
setu = on_command("识图", aliases={"search"}, block=True, priority=5)
@setu.handle()
async def handle_first_receive(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json())
imgs = get_message_imgs(event.json())
if msg in ['帮助']:
await setu.finish('示例:\n\t识图 (图片)\n\t识图asc (图片)')
if imgs:
state["setu"] = imgs[0]
if msg:
state["mod"] = msg
# ex/nao/trace/iqdb/ascii2d
# @setu.got("mod", prompt="从哪里查找呢? ex/nao/trace/iqdb/ascii2d")
# async def get_func(bot: Bot, event: MessageEvent, state: dict):
# pass
@setu.args_parser
async def get_setu(bot: Bot, event: MessageEvent, state: T_State):
imgs = get_message_imgs(event.json())
msg = get_message_text(event.json())
if not imgs:
await setu.reject()
if msg:
state['mod'] = msg
state["setu"] = imgs[0]
@setu.got("setu", prompt="图呢?")
async def get_setu(bot: Bot, event: MessageEvent, state: T_State):
"""
发现没有的时候要发问
:return:
"""
url: str = state["setu"]
mod: str = state["mod"] if state.get("mod") else "nao" # 模式
try:
await bot.send(event=event, message="正在处理图片")
idx = 1
async for msg in get_des(url, mod, event.user_id):
await bot.send(event=event, message=msg)
if idx == MAX_FIND_IMG_COUNT:
break
idx += 1
logger.info(f"(USER {event.user_id}, GROUP "
f"{event.group_id if event.message_type != 'private' else 'private'}) 识图:{url}")
# image_data: List[Tuple] = await get_pic_from_url(url)
# await setu.finish("hso")
except IndexError:
# await bot.send(event, traceback.format_exc())
await setu.finish("参数错误")
except ClientError:
await setu.finish("连接失败")
pic_map: Dict[str, str] = {} # 保存这个群的其阿金一张色图 {"123456":http://xxx"}
async def check_pic(bot: Bot, event: MessageEvent, state: T_State) -> bool:
if isinstance(event, MessageEvent):
for msg in event.message:
if msg.type == "image":
url: str = msg.data["url"]
state["url"] = url
return True
return False
notice_pic = on_message(check_pic, block=False, priority=1)
@notice_pic.handle()
async def handle_pic(bot: Bot, event: GroupMessageEvent, state: T_State):
try:
group_id: str = str(event.group_id)
pic_map.update({group_id: state["url"]})
except AttributeError:
pass
previous = on_command("上一张图是什么", aliases={"上一张", "这是什么"})
@previous.handle()
async def handle_previous(bot: Bot, event: GroupMessageEvent, state: T_State):
await bot.send(event=event, message="processing...")
try:
url: str = pic_map[str(event.group_id)]
idx = 1
async for msg in get_des(url, "nao", event.user_id):
await bot.send(event=event, message=msg)
if idx == MAX_FIND_IMG_COUNT:
break
idx += 1
except IndexError:
await previous.finish("参数错误")
except ClientError:
await previous.finish("连接错误")
except KeyError:
await previous.finish("没有图啊QAQ")

View File

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
from typing import List, Tuple
from urllib.parse import urljoin
import aiofiles
from util.utils import get_local_proxy
from util.user_agent import get_user_agent
from configs.path_config import IMAGE_PATH
from asyncio.exceptions import TimeoutError
from util.init_result import image
from lxml.html import fromstring
import aiohttp
def parse_html(html: str):
selector = fromstring(html)
for tag in selector.xpath('//div[@class="container"]/div[@class="row"]/div/div[@class="row item-box"]')[1:5]:
if pic_url := tag.xpath('./div/img[@loading="lazy"]/@src'): # 缩略图url
pic_url = urljoin("https://ascii2d.net/", pic_url[0])
if description := tag.xpath('./div/div/h6/a[1]/text()'): # 名字
description = description[0]
if author := tag.xpath('./div/div/h6/a[2]/text()'): # 作者
author = author[0]
if origin_url := tag.xpath('./div/div/h6/a[1]/@href'): # 原图地址
origin_url = origin_url[0]
if author_url := tag.xpath('./div/div/h6/a[2]/@href'): # 作者地址
author_url = author_url[0]
yield pic_url, description, author, origin_url, author_url
pass
async def get_pic_from_url(url: str):
real_url = "https://ascii2d.net/search/url/" + url
async with aiohttp.ClientSession() as session:
async with session.get(real_url) as resp:
html: str = await resp.text()
return [i for i in parse_html(html)]
async def get_des(url: str, user_id):
image_data: List[Tuple] = await get_pic_from_url(url)
if not image_data:
msg: str = "找不到高相似度的"
yield msg
return
for pic in image_data:
msg = await download_img(pic[0], user_id) + "\n"
for i in pic[1:]:
msg = msg + f"{i}\n"
yield msg
async def download_img(url, user_id):
try:
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(url, proxy=get_local_proxy(), timeout=7) as response:
async with aiofiles.open(IMAGE_PATH + f'temp/{user_id}_pic_find.png', 'wb') as f:
await f.write(await response.read())
return image(f'{user_id}_pic_find.png', 'temp')
except TimeoutError:
return image(url)

View File

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
from base64 import b64encode
from typing import List, Tuple
import io
from lxml.html import fromstring
import aiohttp
import nonebot
from aiohttp.client_exceptions import InvalidURL
from nonebot.adapters.cqhttp import MessageSegment
from .formdata import FormData
driver = nonebot.get_driver()
cookie: str = driver.config.ex_cookie
proxy: str = driver.config.proxy
target: str = "https://exhentai.org/upload/image_lookup.php"
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryB0NrMSYMfjY5r0l1',
'Host': 'exhentai.org',
'Origin': 'https://exhentai.org',
'Referer': 'https://exhentai.org/?filesearch=1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-User': '?1',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'}
if cookie:
headers['Cookie'] = cookie
else:
headers['Host'] = 'e-hentai.org'
headers['Origin'] = 'https://e-hentai.org'
headers['Referer'] = 'https://e-hentai.org/?filesearch=1'
target: str = "https://e-hentai.org/upload/image_lookup.php"
def parse_html(html: str):
"""
解析exhentai返回的数据
:param html:
:return:
"""
selector = fromstring(html)
hrefs = selector.xpath('//td[@class="gl3c glname"]/a/@href')
names = selector.xpath('//td[@class="gl3c glname"]/a/div[1]/text()')
pics = selector.xpath('//tr/td[@class="gl2c"]/div[@class="glthumb"]/div[1]/img/@src') # 缩略图
for name, href, pic in zip(names, hrefs, pics):
yield name, href, pic
async def get_pic_from_url(url: str):
"""
从接受到的picurl获取图片信息
:param url:
:return:
"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
content = io.BytesIO(await resp.read())
# Content_Length = resp.content_length
data = FormData(boundary="----WebKitFormBoundaryB0NrMSYMfjY5r0l1")
data.add_field(name="sfile", value=content, content_type="image/jpeg",
filename="0.jpg")
data.add_field(name="f_sfile", value="search")
data.add_field(name="fs_similar", value="on")
async with session.post(target, data=data, headers=headers, proxy=proxy) as res:
html = await res.text()
return [i for i in parse_html(html)]
async def get_content_from_url(url: str):
"""
从url 获得b64 encode
:param url:
:return:
"""
try:
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers) as resp:
return "base64://" + b64encode(await resp.read()).decode()
except aiohttp.client_exceptions.InvalidURL:
return url
async def get_des(url: str):
"""
迭代要发送的信息
:param url:
:return:
"""
image_data: List[Tuple] = await get_pic_from_url(url)
if not image_data:
msg: str = "找不到高相似度的"
yield msg
return
for name, href, pic_url in image_data:
content = await get_content_from_url(pic_url)
msg = MessageSegment.image(file=content) + f"\n本子名称:{name}\n" + f"链接{href}\n"
yield msg

View File

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
from typing import Any, Iterable, List, Optional
from aiohttp import FormData as _FormData
import aiohttp.multipart as multipart
class FormData(_FormData):
def __init__(
self,
fields: Iterable[Any] = (),
quote_fields: bool = True,
charset: Optional[str] = None,
boundary: Optional[str] = None
) -> None:
self._writer = multipart.MultipartWriter("form-data", boundary=boundary)
self._fields = [] # type: List[Any]
self._is_multipart = False
self._is_processed = False
self._quote_fields = quote_fields
self._charset = charset
if isinstance(fields, dict):
fields = list(fields.items())
elif not isinstance(fields, (list, tuple)):
fields = (fields,)
self.add_fields(*fields)

View File

@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
import asyncio
from typing import List, Tuple
import io
from urllib.parse import urljoin
from lxml.html import fromstring
import aiohttp
from nonebot.adapters.cqhttp import MessageSegment
from .formdata import FormData
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryuwjSiBcpPag4k159',
'Cookie': 'Hm_lvt_765ecde8c11b85f1ac5f168fa6e6821f=1602471368; Hm_lpvt_765ecde8c11b85f1ac5f168fa6e6821f=1602472300',
'Host': 'iqdb.org', 'Origin': 'http://iqdb.org', 'Referer': 'http://iqdb.org/', 'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'}
def parse_html(html: str):
selector = fromstring(html)
for tag in selector.xpath('//div[@id="pages"]/div[position()>1]/table'):
# 第一个是bestmatch
if pic_url := tag.xpath('./tr[2]/td/a/img/@src'):
pic_url = urljoin("http://iqdb.org/", pic_url[0]) # 缩略图
else:
pic_url = "没有最相似的"
similarity = tag.xpath('./tr[last()]/td/text()')[0] # 相似度
href: List[str] = tag.xpath('./tr/td/a/@href') # 第一个href
href.extend(tag.xpath('./tr/td/span/a/@href')) # 第二个 可能是空
href = list(map(lambda x: "https:" + x if not x.startswith("https") else x, href))
yield pic_url, similarity, href
pass
async def get_pic_from_url(url: str):
"""
返回信息元祖
:param url:
:return:
"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
content = io.BytesIO(await resp.read())
data = FormData(boundary="----WebKitFormBoundaryuwjSiBcpPag4k159")
data.add_field(name="MAX_FILE_SIZE", value="")
for i in range(1, 7):
data.add_field(name="service[]", value=str(i))
data.add_field(name="service[]", value="11")
data.add_field(name="service[]", value="13")
data.add_field(name="file", value=content, content_type="application/octet-stream", filename="0.jpg")
data.add_field(name="url", value="")
async with session.post("http://iqdb.org/", data=data, headers=headers) as res:
html = await res.text()
return [i for i in parse_html(html)]
pass
async def get_des(url: str):
"""
返回详细简介 cq码转义
:param url:
:return:
"""
image_data: List[Tuple] = await get_pic_from_url(url)
if not image_data:
msg: str = "找不到高相似度的"
yield msg
return
for pic in image_data:
msg = MessageSegment.image(file=pic[0]) + f"\n{pic[1]}\n"
for i in pic[2]:
msg = msg + f"{i}\n"
yield msg

View File

@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
import io
from typing import List, Tuple, Union
import aiofiles
from util.utils import get_local_proxy
from util.user_agent import get_user_agent
from configs.path_config import IMAGE_PATH
from asyncio.exceptions import TimeoutError
from util.init_result import image
import aiohttp
from lxml.html import fromstring
from nonebot.adapters.cqhttp import Message
from .formdata import FormData
header = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'max-age=0',
"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryPpuR3EZ1Ap2pXv8W",
'Connection': 'keep-alive',
'Host': 'saucenao.com', 'Origin': 'https://saucenao.com', 'Referer': 'https://saucenao.com/index.php',
'Sec-Fetch-Dest': 'document', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-User': '?1',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'}
def parse_html(html: str):
"""
解析nao返回的html
:param html:
:return:
"""
selector = fromstring(html)
for tag in selector.xpath('//div[@class="result"]/table'):
pic_url = tag.xpath('./tr/td/div/a/img/@src')
if pic_url:
pic_url = pic_url[0]
else:
pic_url = None # 相似度
xsd: List[str] = tag.xpath(
'./tr/td[@class="resulttablecontent"]/div[@class="resultmatchinfo"]/div[@class="resultsimilarityinfo"]/text()')
if xsd:
xsd = xsd[0]
else:
xsd = "没有写" # 相似度
title: List[str] = tag.xpath(
'./tr/td[@class="resulttablecontent"]/div[@class="resultcontent"]/div[@class="resulttitle"]/strong/text()')
if title:
title = title[0]
else:
title = "没有写" # 标题
# pixiv id
pixiv_id: List[str] = tag.xpath(
'./tr/td[@class="resulttablecontent"]/div[@class="resultcontent"]/div[@class="resultcontentcolumn"]/a[1]/@href')
if pixiv_id:
pixiv_id = pixiv_id[0]
else:
pixiv_id = "没有说"
member: List[str] = tag.xpath(
'./tr/td[@class="resulttablecontent"]/div[@class="resultcontent"]/div[@class="resultcontentcolumn"]/a[2]/@href')
if member:
member = member[0]
else:
member = "没有说"
yield pic_url, xsd, title, pixiv_id, member
async def get_pic_from_url(url: str):
"""
从url搜图
:param url:
:return:
"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
content = io.BytesIO(await resp.read())
data = FormData(boundary="----WebKitFormBoundaryPpuR3EZ1Ap2pXv8W")
data.add_field(name="file", value=content, content_type="image/jpeg",
filename="blob")
async with session.post("https://saucenao.com/search.php", data=data, headers=header) as res:
html = await res.text()
image_data = [each for each in parse_html(html)]
return image_data
async def get_des(url: str, user_id: int):
image_data: List[Tuple] = await get_pic_from_url(url)
if not image_data:
msg: Union[str, Message] = "找不到高相似度的"
yield msg
return
for pic in image_data:
# print(pic)
msg = await download_img(pic[0], user_id) \
+ f"\n相似度:{pic[1]}" \
f"\n标题:{pic[2] if (str(pic[2]).strip() != 'Creator:' and len(str(pic[2]).split('-')) < 3) else '未知'}" \
f"\nPID:{pic[3]}" \
f"\nmember:{pic[4]}\n"
yield msg
pass
async def download_img(url, user_id):
try:
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(url, proxy=get_local_proxy(), timeout=7) as response:
async with aiofiles.open(IMAGE_PATH + f'temp/{user_id}_pic_find.png', 'wb') as f:
await f.write(await response.read())
return image(f'{user_id}_pic_find.png', 'temp')
except TimeoutError:
return image(url)

View File

@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
import io
from copy import deepcopy
from base64 import b64encode
from typing import List, Tuple
import aiohttp
from nonebot.adapters.cqhttp import MessageSegment
header = {':authority': 'api.trace.moe',
'accept': '*/*',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundary9cyjY8YBBN8SGdG4',
'origin': 'https://trace.moe',
'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/84.0.4147.105 Safari/537.36'}
async def parse_json(session: aiohttp.ClientSession, data: dict):
count = 0
for i in data["result"]:
title: dict = i["anilist"]["title"]
similarity = i["similarity"]
from_ = i["from"]
to = i["to"]
file = i["filename"] # 名字
is_adult = i["anilist"]["isAdult"]
episode = i["episode"] # 集
header_new = deepcopy(header)
del header_new["content-type"]
header_new[":method"] = 'GET'
header_new["accept"] = "image/webp,image/apng,image/*,*/*;q=0.8"
header_new["sec-fetch-dest"] = "image"
header_new["sec-fetch-mode"] = "no-cors"
async with session.get(i["image"], headers=header_new) as resp:
pic = "base64://" + b64encode(await resp.read()).decode()
yield pic, similarity, file, is_adult, from_, to, title, episode
count += 1
if count > 4:
break
# POST https://api.trace.moe/search?cutBorders=1&anilistID=
async def get_pic_from_url(url: str):
"""
从url搜图
:param url:
:return:
"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
content = io.BytesIO(await resp.read())
# with open("F:\elu.PNG", "rb") as f:
# content = io.BytesIO(f.read())
data = aiohttp.FormData(boundary="----WebKitFormBoundary9cyjY8YBBN8SGdG4")
data.add_field(name="image", value=content, content_type="image/jpeg",
filename="blob")
# data.add_field(name="filter", value="")
# data.add_field(name="trial", value="0")
async with session.post("https://api.trace.moe/search?cutBorders=1&anilistID=", data=data,
headers=header) as res:
data: dict = await res.json()
image_data = [each async for each in parse_json(session, data)]
return image_data
async def get_des(url: str):
image_data: List[Tuple] = await get_pic_from_url(url)
if not image_data:
msg: str = "找不到高相似度的"
yield msg
return
for pic in image_data:
msg = MessageSegment.image(
file=pic[
0]) + f"\n相似度:{pic[1]}%\n标题:{pic[6]['native'] + ' ' + pic[6]['chinese']}\n{pic[7]}\nR18:{pic[3]}\n开始时间:{pic[4]}s\n结束时间{pic[5]}s"
yield msg
pass
if __name__ == "__main__":
import asyncio
data = asyncio.run(get_pic_from_url(
"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1606681978562&di=6d6c90aef5ff1f9f8915bbc2e18e3c98&imgtype=0&src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202011%2F15%2F20201115190356_c5b95.thumb.1000_0.jpg"))
pass

View File

@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
from typing import List, Tuple
import nonebot
from nonebot.adapters.cqhttp import MessageSegment
from lxml.html import fromstring
import aiohttp
"""
http://yandex.com/clck/jsredir?from=yandex.com%3Bimages%2Fsearch%3Bimages%3B%3B&text=&etext=9185.K4iyzsNBG9xrJrSJCUTF4i-XPMAfmBQYR_Igss1ESRc.65568e796f3375fae39da91273ae8a1a82410929&uuid=&state=iric5OQ0sS2054x1_o8yG9mmGMT8WeQxqpuwa4Ft4KVzd9aE_Y4Dfw,,&data=eEwyM2lDYU9Gd1VROE1ZMXhZYkJTYW5fZC1TWjIzaFh5TmR1Z09fQm5DdDB3bFJSSUpVdUxfZmUzcVhfaXhTN1BCU2dINGxmdkY4NFVNcHYyUmw0emFKT2pnOWJoVmlPVzAzX1FIbWh6aXVFV3F0YWFaMGdxeGFtY2dxTzFZZl9VY1huZmlLaGVGOFZleUthZXBlM1pxUGM2elVDLXdvZEo3OGJwdVFqYmVkTDJxWElHSzFZR2NVQUhVcTdzelJwSXlrTjhlS0txdHpYY1RMMHRLOU5HSTYtT0VDb0hpdll6YjVYRXNVcUhCRFJaeDExNTQwZlhMdjh4M2YtTVFUbVJ5ZzBxMTVJcG9DNW51UWhvRzE0WjlFS19uS0VUZWhNRGxOZWlPUkFlRUUs&sign=7ba9ee25d3716868ec8464fb766c9e25&keyno=IMGS_0&b64e=2&l10n=en
"""
driver = nonebot.get_driver()
proxy: str = driver.config.proxy
def parse_html(html: str):
selector = fromstring(html)
for item in selector.xpath('//li[@class="other-sites__item"]'):
pic_url = item.xpath('./a[@class="other-sites__preview-link"]/img/@src')[0].lstrip("//") # 图床
des = item.xpath(
'./div[@class="other-sites__snippet"]/div[@class="other-sites__snippet-title"]/a/text()')[0] # 简介
url = item.xpath(
'./div[@class="other-sites__snippet"]/div[@class="other-sites__snippet-site"]/a/@href')[0] # 链接
yield pic_url, des, url
async def get_pic_from_url(url: str):
real_url = f"https://yandex.com/images/search?rpt=imageview&url={url}"
async with aiohttp.ClientSession() as session:
async with session.get(real_url, proxy=proxy) as resp:
html: str = await resp.text()
return [i for i in parse_html(html)]
async def get_des(url: str):
image_data: List[Tuple] = await get_pic_from_url(url)
if not image_data:
msg: str = "找不到高相似度的"
yield msg
return
for pic in image_data:
msg = MessageSegment.image(file=pic[0]) + "\n"
for i in pic[1:]:
msg = msg + f"{i}\n"
yield msg
if __name__ == "__main__":
with open("yandex.html", "r", encoding="utf-8") as f:
data = f.read()
for item in parse_html(data):
print(item)

View File

@ -0,0 +1,68 @@
import json
import os
import aiohttp
from util.user_agent import get_user_agent
from io import BytesIO
from random import choice
from PIL import Image, ImageDraw, ImageFont
from nonebot import on_regex
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from util.utils import get_message_text, get_local_proxy
from util.img_utils import pic2b64
from configs.path_config import TTF_PATH
import re
from nonebot.adapters.cqhttp import MessageSegment
one_friend = on_regex('^我.*?朋友.*?(想问问|说|让我问问|想问|让我问|想知道|让我帮他问问|让我'
'帮他问|让我帮忙问|让我帮忙问问|问).*', priority=5, block=True)
async def get_pic(qq):
url = f'http://q1.qlogo.cn/g?b=qq&nk={qq}&s=100'
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(url, proxy=get_local_proxy(), timeout=5) as response:
return await response.read()
@one_friend.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
arr = []
member_list = await bot.get_group_member_list(self_id=event.self_id, group_id=event.group_id)
for member in member_list:
arr.append(member['user_id'])
msg = get_message_text(event.json())
msg = re.search(r'^我.*?朋友.*?'
r'(想问问|说|让我问问|想问|让我问|想知道|让我帮他问问|让我帮他问|让我帮忙问|让我帮忙问问|问)(.*)',
msg)
msg = msg.group(2)
if not msg:
msg = '都不知道问什么'
msg = msg.replace('', '').replace('', '')
image = Image.open(BytesIO(await get_pic(choice(arr))))
img_origin = Image.new('RGBA', (100, 100), (255, 255, 255))
scale = 3
# 使用新的半径构建alpha层
r = 100 * scale
alpha_layer = Image.new('L', (r, r), 0)
draw = ImageDraw.Draw(alpha_layer)
draw.ellipse((0, 0, r, r), fill=255)
# 使用ANTIALIAS采样器缩小图像
alpha_layer = alpha_layer.resize((100, 100), Image.ANTIALIAS)
img_origin.paste(image, (0, 0), alpha_layer)
# 创建Font对象:
font = ImageFont.truetype(os.path.join(os.path.dirname(__file__), TTF_PATH + 'yz.ttf'), 30)
font2 = ImageFont.truetype(os.path.join(os.path.dirname(__file__), TTF_PATH + 'yz.ttf'), 25)
# 创建Draw对象:
image_text = Image.new('RGB', (450, 150), (255, 255, 255))
draw = ImageDraw.Draw(image_text)
draw.text((0, 0), '朋友', fill=(0, 0, 0), font=font)
draw.text((0, 40), msg, fill=(125, 125, 125), font=font2)
image_back = Image.new('RGB', (700, 150), (255, 255, 255))
image_back.paste(img_origin, (25, 25))
image_back.paste(image_text, (150, 40))
await one_friend.send(MessageSegment.image(pic2b64(image_back)))

View File

@ -0,0 +1,181 @@
from nonebot import on_command
from util.utils import FreqLimiter, scheduler, get_message_text, is_number
from nonebot.adapters.cqhttp.permission import GROUP
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, MessageEvent
from nonebot.permission import SUPERUSER
import random
from nonebot.plugin import MatcherGroup
import re
from .open_cases_c import open_case, total_open_statistics, group_statistics, my_knifes_name, open_shilian_case
from .utils import util_get_buff_price, util_get_buff_img, update_count_daily
__plugin_name__ = '开箱'
__plugin_usage__ = (
'用法:\n'
'看看你的人品罢了\n'
'目前只支持\n\t'
'1.狂牙大行动武器箱\n\t'
'2.突围大行动武器箱\n\t'
'3.命悬一线武器箱\n\t'
'4.裂空武器箱\n\t'
'5.光谱武器箱\n\t'
'示例:小真寻开箱 突围大行动(不输入指定武器箱则随机)\n'
'示例:我的开箱(开箱统计)\n'
'示例:群开箱统计\n'
'示例:我的金色'
)
_flmt = FreqLimiter(3)
cases_name = ['狂牙大行动', '突围大行动', '命悬一线', '裂空']
cases_matcher_group = MatcherGroup(priority=5, permission=GROUP, block=True)
k_open_case = cases_matcher_group.on_command("开箱")
@k_open_case.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if str(event.get_message()).strip() in ['帮助']:
await k_open_case.finish(__plugin_usage__)
if not _flmt.check(event.user_id):
await k_open_case.finish('着什么急啊,慢慢来!', at_sender=True)
_flmt.start_cd(event.user_id)
case_name = get_message_text(event.json())
if case_name:
result = await open_case(event.user_id, event.group_id, case_name)
else:
result = await open_case(event.user_id, event.group_id, random.choice(cases_name))
await k_open_case.finish(result, at_sender=True)
total_case_data = cases_matcher_group.on_command("我的开箱", aliases={'开箱统计', '开箱查询', '查询开箱'})
@total_case_data.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await total_case_data.finish(
await total_open_statistics(event.user_id, event.group_id),
at_sender=True,
)
group_open_case_statistics = cases_matcher_group.on_command("群开箱统计")
@group_open_case_statistics.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await group_open_case_statistics.finish(await group_statistics(event.group_id))
my_kinfes = on_command("我的金色", priority=1, permission=GROUP, block=True)
@my_kinfes.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await my_kinfes.finish(await my_knifes_name(event.user_id, event.group_id), at_sender=True)
open_shilian = cases_matcher_group.on_regex(".*连开箱")
@open_shilian.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
# if not _flmt.check(event.user_id):
# await k_open_case.finish('着什么急啊,慢慢来!', at_sender=True)
_flmt.start_cd(event.user_id)
msg = get_message_text(event.json())
rs = re.search(r'(.*)连开箱(.*)', msg)
if rs:
num = rs.group(1).strip()
if is_number(num) or num_dict.get(num):
try:
num = num_dict[num]
except KeyError:
num = int(num)
if num > 30:
await open_shilian.finish('开箱次数不要超过30啊笨蛋', at_sender=True)
else:
await open_shilian.finish('必须要是数字切不要超过30啊笨蛋中文也可', at_sender=True)
case_name = rs.group(2).strip()
if case_name.find('武器箱') != -1:
case_name = case_name.replace('武器箱', '').strip()
if not case_name:
case_name = random.choice(cases_name)
elif case_name not in cases_name:
await open_shilian.finish('武器箱未收录!', at_sender=True)
await open_shilian.finish(await open_shilian_case(event.user_id, event.group_id, case_name, num), at_sender=True)
# await open_shilian.send("嘟嘟嘟...开箱中...")
# num = 10
# if str(state["_prefix"]["raw_command"]).find('十') != -1:
# num = 10
# elif str(state["_prefix"]["raw_command"]).find('五') != -1:
# num = 5
# if case_name:
# await open_shilian.finish(await open_shilian_case(event.user_id, event.group_id, case_name, num), at_sender=True)
# else:
# await open_shilian.finish(await open_shilian_case(event.user_id, event.group_id, random.choice(cases_name), num),
# at_sender=True)
num_dict = {
'': 1,
'': 2,
'': 3,
'': 4,
'': 5,
'': 6,
'': 7,
'': 8,
'': 9,
'': 10,
'十一': 11,
'十二': 12,
'十三': 13,
'十四': 14,
'十五': 15,
'十六': 16,
'十七': 17,
'十八': 18,
'十九': 19,
'二十': 20,
'二十一': 21,
'二十二': 22,
'二十三': 23,
'二十四': 24,
'二十五': 25,
'二十六': 26,
'二十七': 27,
'二十八': 28,
'二十九': 29,
'三十': 30
}
update_price = on_command("更新价格", priority=1, permission=SUPERUSER, block=True)
@update_price.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_price.send(await util_get_buff_price(str(event.get_message())))
update_img = on_command("更新图片", priority=1, permission=SUPERUSER, block=True)
@update_img.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
await update_img.send(await util_get_buff_img(str(event.get_message())))
# 重置开箱
@scheduler.scheduled_job(
'cron',
hour=0,
minute=1,
)
async def _():
await update_count_daily()

View File

@ -0,0 +1,180 @@
import random
import pypinyin
BLUE = 0.7981
BLUE_ST = 0.0699
PURPLE = 0.1626
PURPLE_ST = 0.0164
PINK = 0.0315
PINK_ST = 0.0048
RED = 0.0057
RED_ST = 0.00021
KNIFE = 0.0021
KNIFE_ST = 0.000041
# 崭新
FACTORY_NEW_S = 0
FACTORY_NEW_E = 0.0699999
# 略磨
MINIMAL_WEAR_S = 0.07
MINIMAL_WEAR_E = 0.14999
# 久经
FIELD_TESTED_S = 0.15
FIELD_TESTED_E = 0.37999
# 破损
WELL_WORN_S = 0.38
WELL_WORN_E = 0.44999
# 战痕
BATTLE_SCARED_S = 0.45
BATTLE_SCARED_E = 0.99999
# 狂牙大行动
KUANGYADAXINGDONG_CASE_KNIFE = ['摩托手套 | 第三特种兵连', '狂牙手套 | 翡翠', '驾驶手套 | 美洲豹女王', '运动手套 | 弹弓', '专业手套 | 老虎精英'
, '专业手套 | 渐变大理石', '运动手套 | 夜行衣', '驾驶手套 | 西装革履', '摩托手套 | 终点线', '摩托手套 | 血压',
'运动手套 | 猩红头巾', '驾驶手套 | 雪豹', '裹手 | 长颈鹿', '驾驶手套 | 绯红列赞', '裹手 | 沙漠头巾',
'专业手套 | 一线特工', '狂牙手套 | 黄色斑纹', '摩托手套 | 小心烟幕弹', '裹手 | 蟒蛇', '裹手 | 警告!',
'狂牙手套 | 精神错乱', '运动手套 | 大型猎物', '狂牙手套 | 针尖', '专业手套 | 陆军少尉长官']
KUANGYADAXINGDONG_CASE_RED = ['M4A1 | 印花集', '格洛克 | 黑色魅影']
KUANGYADAXINGDONG_CASE_PINK = ['FN57 | 童话城堡', 'M4A4 | 赛博', 'USP | 小绿怪']
KUANGYADAXINGDONG_CASE_PURPLE = ['AWP | 亡灵之主', '双持贝瑞塔 | 灾难', '新星 | 一见青心', 'SSG 08 | 抖枪', 'UMP-45 | 金铋辉煌']
KUANGYADAXINGDONG_CASE_BLUE = ['CZ75 | 世仇', 'P90 | 大怪兽RUSH', 'G3SG1 | 血腥迷彩', '加利尔 AR | 破坏者', 'P250 | 污染物',
'M249 | 等高线', 'MP5-SD | 零点行动']
# 突围大行动
TUWEIDAXINGDONG_CASE_KNIFE = ['蝴蝶刀 | 无涂装', '蝴蝶刀 | 蓝钢', '蝴蝶刀 | 屠夫', '蝴蝶刀 | 森林 DDPAT', '蝴蝶刀 | 北方森林',
'蝴蝶刀 | 狩猎网格', '蝴蝶刀 | 枯焦之色', '蝴蝶刀 | 人工染色', '蝴蝶刀 | 都市伪装', '蝴蝶刀 | 表面淬火',
'蝴蝶刀 | 深红之网', '蝴蝶刀 | 渐变之色', '蝴蝶刀 | 噩梦之夜']
TUWEIDAXINGDONG_CASE_RED = ['P90 | 二西莫夫', 'M4A1 | 次时代']
TUWEIDAXINGDONG_CASE_PINK = ['沙漠之鹰 | 阴谋者', 'FN57 | 狩猎利器', '格洛克 | 水灵']
TUWEIDAXINGDONG_CASE_PURPLE = ['PP-野牛 | 死亡主宰者', 'CZ75 | 猛虎', '新星 | 锦鲤', 'P250 | 超新星']
TUWEIDAXINGDONG_CASE_BLUE = ['MP7 | 都市危机', '内格夫 | 沙漠精英', 'P2000 | 乳白象牙', 'SSG 08 | 无尽深海', 'UMP-45 | 迷之宫']
# 命悬一线
MINGXUANYIXIAN_CASE_KNIFE = ['专业手套 | 大腕', '专业手套 | 深红之网', '专业手套 | 渐变之色', '专业手套 | 狩鹿', '九头蛇手套 | 响尾蛇',
'九头蛇手套 | 红树林', '九头蛇手套 | 翡翠色调', '九头蛇手套 | 表面淬火', '摩托手套 | 交运', '摩托手套 | 嘭!',
'摩托手套 | 多边形', '摩托手套 | 玳瑁', '裹手 | 套印', '裹手 | 森林色调', '裹手 | 钴蓝骷髅', '裹手 | 防水布胶带',
'运动手套 | 双栖', '运动手套 | 欧米伽', '运动手套 | 迈阿密风云', '运动手套 | 青铜形态', '驾驶手套 | 墨绿色调',
'驾驶手套 | 王蛇', '驾驶手套 | 蓝紫格子', '驾驶手套 | 超越']
MINGXUANYIXIAN_CASE_RED = ['M4A4 | 黑色魅影', 'MP7 | 血腥运动']
MINGXUANYIXIAN_CASE_PINK = ['AUG | 湖怪鸟', 'AWP | 死神', 'USP | 脑洞大开']
MINGXUANYIXIAN_CASE_PURPLE = ['MAG-7 | SWAG-7', 'UMP-45 | 白狼', '内格夫 | 狮子鱼', '新星 | 狂野六号', '格洛克 | 城里的月光']
MINGXUANYIXIAN_CASE_BLUE = ['FN57 | 焰色反应', 'MP9 | 黑砂', 'P2000 | 都市危机', 'PP-野牛 | 黑夜暴乱', 'R8 左轮手枪 | 稳',
'SG 553 | 阿罗哈', 'XM1014 | 锈蚀烈焰']
LIEKONG_CASE_KNIFE = ['求生匕首 | 无涂装', '求生匕首 | 人工染色', '求生匕首 | 北方森林', '求生匕首 | 夜色', '求生匕首 | 屠夫',
'求生匕首 | 枯焦之色', '求生匕首 | 森林 DDPAT', '求生匕首 | 深红之网', '求生匕首 | 渐变之色', '求生匕首 | 狩猎网格',
'求生匕首 | 蓝钢', '求生匕首 | 表面淬火', '求生匕首 | 都市伪装', '流浪者匕首 | 无涂装', '流浪者匕首 | 人工染色',
'流浪者匕首 | 北方森林', '流浪者匕首 | 夜色', '流浪者匕首 | 屠夫', '流浪者匕首 | 枯焦之色', '流浪者匕首 | 森林 DDPAT',
'流浪者匕首 | 深红之网', '流浪者匕首 | 渐变之色', '流浪者匕首 | 狩猎网格', '流浪者匕首 | 蓝钢', '流浪者匕首 | 表面淬火',
'流浪者匕首 | 都市伪装', '系绳匕首 | 无涂装', '系绳匕首 | 人工染色', '系绳匕首 | 北方森林', '系绳匕首 | 夜色',
'系绳匕首 | 屠夫', '系绳匕首 | 枯焦之色', '系绳匕首 | 森林 DDPAT', '系绳匕首 | 深红之网', '系绳匕首 | 渐变之色',
'系绳匕首 | 狩猎网格', '系绳匕首 | 蓝钢', '系绳匕首 | 表面淬火', '系绳匕首 | 都市伪装', '骷髅匕首 | 无涂装',
'骷髅匕首 | 人工染色', '骷髅匕首 | 北方森林', '骷髅匕首 | 夜色', '骷髅匕首 | 屠夫', '骷髅匕首 | 枯焦之色',
'骷髅匕首 | 森林 DDPAT', '骷髅匕首 | 深红之网', '骷髅匕首 | 渐变之色', '骷髅匕首 | 狩猎网格', '骷髅匕首 | 蓝钢',
'骷髅匕首 | 表面淬火', '骷髅匕首 | 都市伪装']
LIEKONG_CASE_RED = ['AK-47 | 阿努比斯军团', '沙漠之鹰 | 印花集']
LIEKONG_CASE_PINK = ['M4A4 | 齿仙', 'XM1014 | 埋葬之影', '格洛克 | 摩登时代']
LIEKONG_CASE_PURPLE = ['加利尔 AR | 凤凰商号', 'Tec-9 | 兄弟连', 'MP5-SD | 猛烈冲锋', 'MAG-7 | 北冥有鱼', 'MAC-10 | 魅惑']
LIEKONG_CASE_BLUE = ['内格夫 | 飞羽', 'SSG 08 | 主机001', 'SG 553 | 锈蚀之刃', 'PP-野牛 | 神秘碑文', 'P90 | 集装箱', 'P250 | 卡带',
'P2000 | 盘根错节']
GUANGPU_CASE_KNIFE = ['弯刀 | 外表生锈', '弯刀 | 多普勒', '弯刀 | 大马士革钢', '弯刀 | 渐变大理石', '弯刀 | 致命紫罗兰', '弯刀 | 虎牙',
'暗影双匕 | 外表生锈', '暗影双匕 | 多普勒', '暗影双匕 | 大马士革钢', '暗影双匕 | 渐变大理石', '暗影双匕 | 致命紫罗兰',
'暗影双匕 | 虎牙', '猎杀者匕首 | 外表生锈', '猎杀者匕首 | 多普勒', '猎杀者匕首 | 大马士革钢', '猎杀者匕首 | 渐变大理石',
'猎杀者匕首 | 致命紫罗兰', '猎杀者匕首 | 虎牙', '蝴蝶刀 | 外表生锈', '蝴蝶刀 | 多普勒', '蝴蝶刀 | 大马士革钢',
'蝴蝶刀 | 渐变大理石', '蝴蝶刀 | 致命紫罗兰', '蝴蝶刀 | 虎牙', '鲍伊猎刀 | 外表生锈', '鲍伊猎刀 | 多普勒',
'鲍伊猎刀 | 大马士革钢', '鲍伊猎刀 | 渐变大理石', '鲍伊猎刀 | 致命紫罗兰', '鲍伊猎刀 | 虎牙']
GUANGPU_CASE_RED = ['USP | 黑色魅影', 'AK-47 | 血腥运动']
GUANGPU_CASE_PINK = ['M4A1 | 毁灭者 2000', 'CZ75 | 相柳', 'AWP | 浮生如梦']
GUANGPU_CASE_PURPLE = ['加利尔 AR | 深红海啸', 'XM1014 | 四季', 'UMP-45 | 支架', 'MAC-10 | 绝界之行', 'M249 | 翠绿箭毒蛙']
GUANGPU_CASE_BLUE = ['沙漠之鹰 | 锈蚀烈焰', '截短霰弹枪 | 梭鲈', 'SCAR-20 | 蓝图', 'PP-野牛 | 丛林滑流', 'P250 | 涟漪', 'MP7 | 非洲部落',
'FN57 | 毛细血管']
NO_STA_KNIFE = ['求生匕首 | 北方森林', '求生匕首 | 夜色', '求生匕首 | 枯焦之色', '流浪者匕首 | 夜色', '流浪者匕首 | 枯焦之色', '流浪者匕首 | 森林 DDPAT',
'系绳匕首 | 夜色', '系绳匕首 | 狩猎网格', '骷髅匕首 | 夜色', '骷髅匕首 | 森林 DDPAT', '骷髅匕首 | 狩猎网格']
def get_wear(num: float) -> str:
if num <= FACTORY_NEW_E:
return "崭新出厂"
if MINIMAL_WEAR_S <= num <= MINIMAL_WEAR_E:
return "略有磨损"
if FIELD_TESTED_S <= num <= FIELD_TESTED_E:
return "久经沙场"
if WELL_WORN_S <= num <= WELL_WORN_E:
return "破损不堪"
return "战痕累累"
def get_color_quality(rand: float, case_name: str):
case = ""
mosun = random.random()/2 + random.random()/2
for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL):
case += ''.join(i)
case = case.upper()
CASE_KNIFE = eval(case + "_CASE_KNIFE")
CASE_RED = eval(case + "_CASE_RED")
CASE_PINK = eval(case + "_CASE_PINK")
CASE_PURPLE = eval(case + "_CASE_PURPLE")
CASE_BLUE = eval(case + "_CASE_BLUE")
if rand <= KNIFE:
skin = "罕见级(金色): " + random.choice(CASE_KNIFE)
if random.random() <= KNIFE_ST and (skin[2:4] != "手套" or skin[:2] != "裹手") and skin.split(':')[1] \
not in NO_STA_KNIFE:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
elif KNIFE < rand <= RED:
skin = "隐秘级(红色): " + random.choice(CASE_RED)
if random.random() <= RED_ST:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
elif RED < rand <= PINK:
skin = "保密级(粉色): " + random.choice(CASE_PINK)
if random.random() <= PINK_ST:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
elif PINK < rand <= PURPLE:
skin = "受限级(紫色): " + random.choice(CASE_PURPLE)
if random.random() <= PURPLE_ST:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
else:
skin = "军规级(蓝色): " + random.choice(CASE_BLUE)
if random.random() <= BLUE_ST:
skin_sp = skin.split("|")
skin = skin_sp[0] + "StatTrak™ | " + skin_sp[1]
if skin.find("") != -1:
cpskin = skin.split(":")[1]
ybskin = cpskin.split("|")
temp_skin = ybskin[0].strip()[:-11] + " | " + ybskin[1].strip()
else:
temp_skin = skin.split(":")[1].strip()
# 崭新 -> 略磨
if temp_skin in [] or temp_skin.find('渐变之色') != -1 or temp_skin.find('多普勒') != -1 or temp_skin.find('虎牙') != -1\
or temp_skin.find('渐变大理石') != -1:
mosun = random.uniform(FACTORY_NEW_S, MINIMAL_WEAR_E) / 2 + random.uniform(FACTORY_NEW_S, MINIMAL_WEAR_E) / 2
# 崭新 -> 久经
if temp_skin in ['沙漠之鹰 | 阴谋者', '新星 | 锦鲤'] or temp_skin.find('屠夫') != -1:
mosun = random.uniform(FACTORY_NEW_S, FIELD_TESTED_E) / 2 + random.uniform(FACTORY_NEW_S, FIELD_TESTED_E) / 2
# 崭新 -> 破损
if temp_skin in ['UMP-45 | 迷之宫', 'P250 | 超新星', '系绳匕首 | 深红之网', 'M249 | 翠绿箭毒蛙', 'AK-47 | 血腥运动']:
mosun = random.uniform(FACTORY_NEW_S, WELL_WORN_E) / 2 + random.uniform(FACTORY_NEW_S, WELL_WORN_E) / 2
# 破损 -> 战痕
if temp_skin in [] or temp_skin.find('外表生锈') != -1:
mosun = random.uniform(WELL_WORN_S, BATTLE_SCARED_E) / 2 + random.uniform(WELL_WORN_S, BATTLE_SCARED_E) / 2
if mosun > MINIMAL_WEAR_E:
for _ in range(2):
if random.random() < 5:
if random.random() < 0.2:
mosun /= 3
else:
mosun /= 2
break
skin += " (" + get_wear(mosun) + ")"
return skin, mosun
# M249StatTrak™ | 等高线

View File

@ -0,0 +1,381 @@
from datetime import datetime, timedelta
from .config import *
from services.log import logger
from services.db_context import db
from models.open_cases_user import OpenCasesUser
from models.sigin_group_user import SignGroupUser
from util.init_result import image
import pypinyin
import random
from .utils import get_price
from models.buff_price import BuffPrice
from PIL import Image
from util.img_utils import alphabg2white_PIL, CreateImg
from configs.path_config import IMAGE_PATH
import asyncio
from util.utils import cn2py
from configs.config import INITIAL_OPEN_CASE_COUNT
MAX_COUNT = INITIAL_OPEN_CASE_COUNT
async def open_case(user_qq: int, group: int, case_name: str = "狂牙大行动") -> str:
if case_name not in ["狂牙大行动", "突围大行动", "命悬一线", '裂空', '光谱']:
return "武器箱未收录"
knifes_flag = False
# lan zi fen hong jin price
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0]
case = ""
for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL):
case += ''.join(i)
impression = (await SignGroupUser.ensure(user_qq, group)).impression
rand = random.random()
async with db.transaction():
user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
# 一天次数上限
if user.today_open_total == int(MAX_COUNT + int(impression) / 3):
return _handle_is_MAX_COUNT()
skin, mosun = get_color_quality(rand, case_name)
# 调侃
if skin[:2] == "军规":
if skin.find("StatTrak") == -1:
uplist[0] = 1
else:
uplist[1] = 1
ridicule_result = random.choice(['这样看着才舒服',
'是自己人,大伙把刀收好',
'非常舒适~'])
if skin[:2] == "受限":
if skin.find("StatTrak") == -1:
uplist[2] = 1
else:
uplist[3] = 1
ridicule_result = random.choice(['还行吧,勉强接受一下下',
'居然不是蓝色,太假了',
'运气-1-1-1-1-1...'])
if skin[:2] == "保密":
if skin.find("StatTrak") == -1:
uplist[4] = 1
else:
uplist[5] = 1
ridicule_result = random.choice(['开始不适....',
'你妈妈买菜必涨价!涨三倍!',
'你最近不适合出门,真的'])
if skin[:2] == "隐秘":
if skin.find("StatTrak") == -1:
uplist[6] = 1
else:
uplist[7] = 1
ridicule_result = random.choice(['已经非常不适',
'好兄弟你开的什么箱子啊,一般箱子不是只有蓝色的吗',
'开始拿阳寿开箱子了?'])
if skin[:2] == "罕见":
knifes_flag = True
if skin.find("StatTrak") == -1:
uplist[8] = 1
else:
uplist[9] = 1
ridicule_result = random.choice(['你的好运我收到了,你可以去喂鲨鱼了',
'最近该吃啥就迟点啥吧,哎,好好的一个人怎么就....哎',
'众所周知,欧皇寿命极短.'])
if skin.find("") != -1:
cskin = skin.split("")
skin = cskin[0].strip() + "" + cskin[1].strip()
skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
# 价格
if skin.find('无涂装') == -1:
dbprice = await BuffPrice.ensure(skin[9:])
else:
dbprice = await BuffPrice.ensure(skin[9: skin.rfind('(')].strip())
if dbprice.skin_price != 0:
price_result = dbprice.skin_price
print("数据库查询到价格: ", dbprice.skin_price)
uplist[10] = dbprice.skin_price
else:
price = -1
price_result = "未查询到"
price_list, status = await get_price(skin[9:])
if price_list not in ["访问超时! 请重试或稍后再试!", "访问失败!"]:
for price_l in price_list[1:]:
pcp = price_l.split(":")
if pcp[0] == skin[9:]:
price = float(pcp[1].strip())
break
if price != -1:
print("存储入数据库---->", price)
uplist[10] = price
price_result = str(price)
await dbprice.update(
skin_price=price,
update_date=datetime.now(),
).apply()
# sp = skin.split("|")
# cskin_word = sp[1][:sp[1].find("(") - 1].strip()
if knifes_flag:
await user.update(
knifes_name=user.knifes_name + f"{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]} 价格:{uplist[10]},"
).apply()
cskin_word = skin.split(':')[1].replace('|', '-').replace('StatTrak™', '')
cskin_word = cskin_word[: cskin_word.rfind('(')].strip()
skin_name = cn2py(cskin_word.replace('|', '-').replace('StatTrak™', '').strip())
img = image(f'{skin_name}.png', "cases/" + case)
# if knifes_flag:
# await user.update(
# knifes_name=user.knifes_name + f"{skin} 磨损:{mosun} 价格:{uplist[10]}"
# ).apply()
if await update_user_total(user, uplist):
logger.info(f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun} 价格:{uplist[10]} 数据更新成功")
else:
logger.warning(f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun} 价格:{uplist[10]} 数据更新失败")
user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
over_count = int(MAX_COUNT + int(impression) / 3) - user.today_open_total
return f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n" \
+ img + "\n" + \
f"皮肤:{skin}\n" \
f"磨损:{mosun:.9f}\n" \
f"价格:{price_result}\n" \
f"{ridicule_result}"
async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int = 10):
user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
impression = (await SignGroupUser.ensure(user_qq, group)).impression
if user.today_open_total == int(MAX_COUNT + int(impression) / 3):
return _handle_is_MAX_COUNT()
if int(MAX_COUNT + int(impression) / 3) - user.today_open_total < num:
return f"今天开箱次数不足{num}次噢,请单抽试试看(也许单抽运气更好?)" \
f"\n剩余开箱次数:{int(MAX_COUNT + int(impression) / 3) - user.today_open_total}"
if num < 5:
h = 270
elif num % 5 == 0:
h = 270 * int(num / 5)
else:
h = 270 * int(num / 5) + 270
case = cn2py(case_name)
# lan zi fen hong jin
# skin_list = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# lan zi fen hong jin price
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0]
img_list = []
name_list = ['', '蓝(暗金)', '', '紫(暗金)', '', '粉(暗金)', '', '红(暗金)', '', '金(暗金)']
async with db.transaction():
for _ in range(num):
knifes_flag = False
rand = random.random()
skin, mosun = get_color_quality(rand, case_name)
if skin[:2] == "军规":
if skin.find("StatTrak") == -1:
uplist[0] += 1
else:
uplist[1] += 1
if skin[:2] == "受限":
if skin.find("StatTrak") == -1:
uplist[2] += 1
else:
uplist[3] += 1
if skin[:2] == "保密":
if skin.find("StatTrak") == -1:
uplist[4] += 1
else:
uplist[5] += 1
if skin[:2] == "隐秘":
if skin.find("StatTrak") == -1:
uplist[6] += 1
else:
uplist[7] += 1
if skin[:2] == "罕见":
knifes_flag = True
if skin.find("StatTrak") == -1:
uplist[8] += 1
else:
uplist[9] += 1
if skin.find("") != -1:
cskin = skin.split("")
skin = cskin[0].strip() + "" + cskin[1].strip()
skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
# 价格
if skin.find('无涂装') == -1:
dbprice = await BuffPrice.ensure(skin[9:])
else:
dbprice = await BuffPrice.ensure(skin[9: skin.rfind('(')].strip())
if dbprice.skin_price != 0:
price_result = dbprice.skin_price
uplist[10] += price_result
else:
price_result = '未查询到'
if knifes_flag:
await user.update(
knifes_name=user.knifes_name + f"{case}||{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]} 价格:{dbprice.skin_price},"
).apply()
cskin_word = skin.split(':')[1].replace('|', '-').replace('StatTrak™', '')
cskin_word = cskin_word[: cskin_word.rfind('(')].strip()
skin_name = ""
for i in pypinyin.pinyin(cskin_word.replace('|', '-').replace('StatTrak™', '').strip(),
style=pypinyin.NORMAL):
skin_name += ''.join(i)
# img = image(skin_name, "cases/" + case, "png")
wImg = CreateImg(200, 270, 200, 200)
wImg.paste(alphabg2white_PIL(Image.open(IMAGE_PATH + f'cases/{case}/{skin_name}.png').resize((200, 200), Image.ANTIALIAS)), (0, 0))
wImg.text((5, 200), skin)
wImg.text((5, 220), f'磨损:{str(mosun)[:9]}')
wImg.text((5, 240), f'价格:{price_result}')
img_list.append(wImg)
logger.info(f"USER {user_qq} GROUP {group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun} 价格:{uplist[10]}")
if await update_user_total(user, uplist, num):
logger.info(f"USER {user_qq} GROUP {group} 开启{case_name}武器箱 {num} 次, 数据更新成功")
else:
logger.warning(f"USER {user_qq} GROUP {group} 开启{case_name}武器箱 {num} 次, 价格:{uplist[10]} 数据更新失败")
# markImg = CreateImg(1000, h, 200, 270)
# for img in img_list:
# markImg.paste(img)
markImg = await asyncio.get_event_loop().run_in_executor(None, paste_markImg, h, img_list)
over_count = int(MAX_COUNT + int(impression) / 3) - user.today_open_total
result = ''
for i in range(len(name_list)):
if uplist[i]:
result += f'[{name_list[i]}{uplist[i]}] '
return f"开启{case_name}武器箱\n剩余开箱次数:{over_count}\n" \
+ image(b64=markImg.pic2bs4()) + \
'\n' + result[:-1] + f'\n总获取金额:{uplist[-1]:.2f}\n总花费:{17 * num}'
def paste_markImg(h: int, img_list: list):
markImg = CreateImg(1000, h, 200, 270)
for img in img_list:
markImg.paste(img)
return markImg
def _handle_is_MAX_COUNT() -> str:
return f"今天已达开箱上限了喔,明天再来吧\n(提升好感度可以增加每日开箱数 #疯狂暗示)"
async def update_user_total(user: OpenCasesUser, uplist: list, num: int = 1) -> bool:
try:
await user.update(
total_count=user.total_count + num,
blue_count=user.blue_count + uplist[0],
blue_st_count=user.blue_st_count + uplist[1],
purple_count=user.purple_count + uplist[2],
purple_st_count=user.purple_st_count + uplist[3],
pink_count=user.pink_count + uplist[4],
pink_st_count=user.pink_st_count + uplist[5],
red_count=user.red_count + uplist[6],
red_st_count=user.red_st_count + uplist[7],
knife_count=user.knife_count + uplist[8],
knife_st_count=user.knife_st_count + uplist[9],
spend_money=user.spend_money + 17 * num,
make_money=user.make_money + uplist[10],
today_open_total=user.today_open_total + num,
open_cases_time_last=datetime.now()
).apply()
return True
except:
return False
async def total_open_statistics(user_qq: int, group: int) -> str:
async with db.transaction():
user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
return f"开箱总数:{user.total_count}\n" \
f"今日开箱:{user.today_open_total}\n" \
f"蓝色军规:{user.blue_count}\n" \
f"蓝色暗金:{user.blue_st_count}\n" \
f"紫色受限:{user.purple_count}\n" \
f"紫色暗金:{user.purple_st_count}\n" \
f"粉色保密:{user.pink_count}\n" \
f"粉色暗金:{user.pink_st_count}\n" \
f"红色隐秘:{user.red_count}\n" \
f"红色暗金:{user.red_st_count}\n" \
f"金色罕见:{user.knife_count}\n" \
f"金色暗金:{user.knife_st_count}\n" \
f"花费金额:{user.spend_money}\n" \
f"获取金额:{user.make_money:.2f}\n" \
f"最后开箱日期:{(user.open_cases_time_last + timedelta(hours=8)).date()}"
async def group_statistics(group: int):
user_list = await OpenCasesUser.get_user_all(group)
# lan zi fen hong jin pricei
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0]
for user in user_list:
uplist[0] += user.blue_count
uplist[1] += user.blue_st_count
uplist[2] += user.purple_count
uplist[3] += user.purple_st_count
uplist[4] += user.pink_count
uplist[5] += user.pink_st_count
uplist[6] += user.red_count
uplist[7] += user.red_st_count
uplist[8] += user.knife_count
uplist[9] += user.knife_st_count
uplist[10] += user.make_money
uplist[11] += user.total_count
uplist[12] += user.today_open_total
return f"群开箱总数:{uplist[11]}\n" \
f"群今日开箱:{uplist[12]}\n" \
f"蓝色军规:{uplist[0]}\n" \
f"蓝色暗金:{uplist[1]}\n" \
f"紫色受限:{uplist[2]}\n" \
f"紫色暗金:{uplist[3]}\n" \
f"粉色保密:{uplist[4]}\n" \
f"粉色暗金:{uplist[5]}\n" \
f"红色隐秘:{uplist[6]}\n" \
f"红色暗金:{uplist[7]}\n" \
f"金色罕见:{uplist[8]}\n" \
f"金色暗金:{uplist[9]}\n" \
f"花费金额:{uplist[11] * 17}\n" \
f"获取金额:{uplist[10]:.2f}"
async def my_knifes_name(user_id: int, group: int):
knifes_name = (await OpenCasesUser.ensure(user_id, group)).knifes_name
if knifes_name:
knifes_list = knifes_name[:-1].split(",")
length = len(knifes_list)
if length < 5:
h = 600
w = length * 540
elif length % 5 == 0:
h = 600 * int(length / 5)
w = 540 * 5
else:
h = 600 * int(length / 5) + 600
w = 540 * 5
A = await asyncio.get_event_loop().run_in_executor(None, _pst_my_knife, w, h, knifes_list)
return image(b64=A.pic2bs4())
else:
return "您木有开出金色级别的皮肤喔"
def _pst_my_knife(w, h, knifes_list):
A = CreateImg(w, h, 540, 600)
for knife in knifes_list:
case = knife.split('||')[0]
knife = knife.split('||')[1]
name = knife[:knife.find('(')].strip()
itype = knife[knife.find('(')+1: knife.find(')')].strip()
mosun = knife[knife.find('磨损:')+3: knife.rfind('价格:')].strip()
if mosun[-1] == ',' or mosun[-1] == '':
mosun = mosun[:-1]
price = knife[knife.find('价格:')+3:]
skin_name = ""
for i in pypinyin.pinyin(name.replace('|', '-').replace('StatTrak™', '').strip(),
style=pypinyin.NORMAL):
skin_name += ''.join(i)
knife_img = CreateImg(470, 600, 470, 470, font_size=20)
knife_img.paste(alphabg2white_PIL(
Image.open(IMAGE_PATH + f'cases/{case}/{skin_name}.png').resize((470, 470), Image.ANTIALIAS)), (0, 0))
knife_img.text((5, 500), f'\t{name}({itype})')
knife_img.text((5, 530), f'\t磨损:{mosun}')
knife_img.text((5, 560), f'\t价格:{price}')
A.paste(knife_img)
return A
# G3SG1StatTrak™ | 血腥迷彩 (战痕累累)
# G3SG1StatTrak™ | 血腥迷彩 (战痕累累)
# G3SG1StatTrak™ | 血腥迷彩 (战痕累累)

294
plugins/open_cases/utils.py Normal file
View File

@ -0,0 +1,294 @@
from models.buff_price import BuffPrice
from services.db_context import db
from datetime import datetime, timedelta
from util.user_agent import get_user_agent
from configs.path_config import IMAGE_PATH
import aiohttp
import aiofiles
from models.open_cases_user import OpenCasesUser
import os
from services.log import logger
from util.utils import get_bot
from models.group_remind import GroupRemind
from util.utils import get_cookie_text
from asyncio.exceptions import TimeoutError
import pypinyin
from nonebot.adapters.cqhttp.exception import ActionFailed
<<<<<<< HEAD
from configs.config import buff_proxy
=======
>>>>>>> master
url = "https://buff.163.com/api/market/goods"
# proxies = 'http://49.75.59.242:3128'
async def util_get_buff_price(case_name: str = "狂牙大行动") -> str:
cookie = {'session': get_cookie_text('buff')}
failed_list = []
case = ""
for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL):
case += ''.join(i)
if case_name == "狂牙大行动":
case_id = 1
elif case_name == "突围大行动":
case_id = 2
elif case_name == "命悬一线":
case_id = 3
elif case_name == '裂空':
case_id = 4
elif case_name == '光谱':
case_id = 5
else:
return "未查询到武器箱"
case = case.upper()
CASE_KNIFE = eval(case + "_CASE_KNIFE")
CASE_RED = eval(case + "_CASE_RED")
CASE_PINK = eval(case + "_CASE_PINK")
CASE_PURPLE = eval(case + "_CASE_PURPLE")
CASE_BLUE = eval(case + "_CASE_BLUE")
async with aiohttp.ClientSession(cookies=cookie, headers=get_user_agent()) as session:
for total_list in [CASE_KNIFE, CASE_RED, CASE_PINK, CASE_PURPLE, CASE_BLUE]:
print("----------------------------------")
for skin in total_list:
print(skin)
if skin in ["蝴蝶刀 | 无涂装", '求生匕首 | 无涂装', '流浪者匕首 | 无涂装', '系绳匕首 | 无涂装', '骷髅匕首 | 无涂装']:
skin = skin.split('|')[0].strip()
async with db.transaction():
name_list = []
price_list = []
parameter = {
"game": "csgo",
"page_num": "1",
"search": skin
}
try:
<<<<<<< HEAD
async with session.get(url, proxy=buff_proxy, params=parameter, timeout=20) as response:
=======
async with session.get(url, params=parameter, timeout=20) as response:
>>>>>>> master
if response.status == 200:
data = (await response.json())["data"]
total_page = data["total_page"]
data = data["items"]
flag = False
if skin.find('|') == -1: # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
for i in range(1, total_page + 1):
name_list = []
price_list = []
parameter = {
"game": "csgo",
"page_num": f"{i}",
"search": skin
}
async with session.get(url, params=parameter, timeout=20) as res:
data = (await response.json())["data"]["items"]
for j in range(len(data)):
if data[j]['name'] in [f'{skin}(★)']:
name = data[j]["name"]
price = data[j]["sell_reference_price"]
name_list.append(name.split('')[0].strip() + ' | 无涂装')
price_list.append(price)
print(name_list[-1])
print(price_list[-1])
flag = True
break
if flag:
break
else:
try:
for _ in range(total_page):
for i in range(len(data)):
name = data[i]["name"]
price = data[i]["sell_reference_price"]
name_list.append(name)
price_list.append(price)
except Exception as e:
failed_list.append(skin)
print(f"{skin}更新失败")
else:
failed_list.append(skin)
print(f"{skin}更新失败")
except Exception:
failed_list.append(skin)
print(f"{skin}更新失败")
continue
for i in range(len(name_list)):
name = name_list[i].strip()
price = float(price_list[i])
if name.find("(★)") != -1:
name = name[: name.find("")] + name[name.find("") + 1:]
if name.find("消音") != -1 and name.find("S") != -1:
name = name.split("")[0][:-4] + "" + name.split("")[1]
name = name.split("|")[0].strip() + " | " + name.split("|")[1].strip()
elif name.find("消音") != -1:
name = name.split("|")[0][:-5].strip() + " | " + name.split("|")[1].strip()
if name.find(" 18 ") != -1 and name.find("S") != -1:
name = name.split("")[0][:-5] + "" + name.split("")[1]
name = name.split("|")[0].strip() + " | " + name.split("|")[1].strip()
elif name.find(" 18 ") != -1:
name = name.split("|")[0][:-6].strip() + " | " + name.split("|")[1].strip()
dbskin = await BuffPrice.ensure(name, True)
if (dbskin.update_date + timedelta(8)).date() == datetime.now().date():
continue
await dbskin.update(
case_id=case_id,
skin_price=price,
update_date=datetime.now(),
).apply()
print(f"{name_list[i]}---------->成功更新")
result = None
if failed_list:
result = ""
for fail_skin in failed_list:
result += fail_skin + "\n"
return result[:-1] if result else "更新价格成功"
async def util_get_buff_img(case_name: str = "狂牙大行动") -> str:
cookie = {'session': get_cookie_text('buff')}
error_list = []
case = ""
for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL):
case += ''.join(i)
path = "cases/" + case + "/"
if not os.path.exists(IMAGE_PATH + path):
os.mkdir(IMAGE_PATH + path)
case = case.upper()
CASE_KNIFE = eval(case + "_CASE_KNIFE")
CASE_RED = eval(case + "_CASE_RED")
CASE_PINK = eval(case + "_CASE_PINK")
CASE_PURPLE = eval(case + "_CASE_PURPLE")
CASE_BLUE = eval(case + "_CASE_BLUE")
async with aiohttp.ClientSession(cookies=cookie, headers=get_user_agent()) as session:
for total_list in [CASE_KNIFE, CASE_RED, CASE_PINK, CASE_PURPLE, CASE_BLUE]:
for skin in total_list:
parameter = {
"game": "csgo",
"page_num": "1",
"search": skin
}
if skin in ["蝴蝶刀 | 无涂装", '求生匕首 | 无涂装', '流浪者匕首 | 无涂装', '系绳匕首 | 无涂装', '骷髅匕首 | 无涂装']:
skin = skin.split('|')[0].strip()
print("开始更新----->", skin)
print(skin)
skin_name = ''
# try:
<<<<<<< HEAD
async with session.get(url, proxy=buff_proxy, params=parameter, timeout=20) as response:
=======
async with session.get(url, params=parameter, timeout=20) as response:
>>>>>>> master
if response.status == 200:
data = (await response.json())["data"]
total_page = data["total_page"]
flag = False
if skin.find('|') == -1: # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
for i in range(1, total_page + 1):
async with session.get(url, params=parameter, timeout=20) as res:
data = (await response.json())["data"]["items"]
for j in range(len(data)):
if data[j]['name'] in [f'{skin}(★)']:
img_url = data[j]['goods_info']['icon_url']
for k in pypinyin.pinyin(skin + '无涂装', style=pypinyin.NORMAL):
skin_name += ''.join(k)
async with aiofiles.open(IMAGE_PATH + path + skin_name + ".png", 'wb') as f:
print("------->开始写入 ", skin)
async with session.get(img_url, timeout=7) as res:
await f.write(await res.read())
flag = True
break
if flag:
break
else:
img_url = (await response.json())["data"]['items'][0]['goods_info']['icon_url']
for i in pypinyin.pinyin(skin.replace('|', '-').strip(), style=pypinyin.NORMAL):
skin_name += ''.join(i)
async with aiofiles.open(IMAGE_PATH + path + skin_name + ".png", 'wb') as f:
print("------->开始写入 ", skin)
async with session.get(img_url, timeout=7) as res:
await f.write(await res.read())
# async with session.get(url, params=parameter, timeout=7) as response:
# if response.status == 200:
# img_url = (await response.json())["data"]['items'][0]['goods_info']['icon_url']
# skin_name = ''
# for i in pypinyin.pinyin(skin.split("|")[1].strip(), style=pypinyin.NORMAL):
# skin_name += ''.join(i)
# async with aiofiles.open(IMAGE_PATH + path + skin_name + ".png", 'wb') as f:
# print("------->开始写入 ", skin)
# async with session.get(img_url, timeout=7) as res:
# await f.write(await res.read())
# except Exception:
# print("图片更新失败 ---->", skin)
# error_list.append(skin)
result = None
if error_list:
result = ""
for errskin in error_list:
result += errskin + "\n"
return result[:-1] if result else "更新图片成功"
async def get_price(dname):
cookie = {'session': get_cookie_text('buff')}
name_list = []
price_list = []
parameter = {
"game": "csgo",
"page_num": "1",
"search": dname
}
try:
async with aiohttp.ClientSession(cookies=cookie, headers=get_user_agent()) as session:
async with session.get(url, params=parameter, timeout=7) as response:
if response.status == 200:
try:
data = (await response.json())["data"]
total_page = data["total_page"]
data = data["items"]
for _ in range(total_page):
for i in range(len(data)):
name = data[i]["name"]
price = data[i]["sell_reference_price"]
name_list.append(name)
price_list.append(price)
except Exception as e:
return "没有查询到...", 998
else:
return "访问失败!", response.status
except TimeoutError as e:
return "访问超时! 请重试或稍后再试!", 997
result = f"皮肤: {dname}({len(name_list)})\n"
# result = "皮肤: " + dname + "\n"
for i in range(len(name_list)):
result += name_list[i] + ": " + price_list[i] + "\n"
return result[:-1], 999
async def update_count_daily():
try:
users = await OpenCasesUser.get_user_all()
if users:
for user in users:
await user.update(
today_open_total=0,
).apply()
bot = get_bot()
gl = await bot.get_group_list(self_id=bot.self_id)
gl = [g['group_id'] for g in gl]
for g in gl:
if await GroupRemind.get_status(g, 'kxcz'):
try:
await bot.send_group_msg(group_id=g, message="今日开箱次数重置成功")
except ActionFailed:
logger.warning(f'{g} 群被禁言,无法发送 开箱重置提醒')
logger.info("今日开箱次数重置成功")
except Exception as e:
logger.error(f'开箱重置错误 e:{e}')
# 蝴蝶刀(★) | 噩梦之夜 (久经沙场)
if __name__ == '__main__':
print(util_get_buff_img("xxxx/"))

194
plugins/pixiv/__init__.py Normal file
View File

@ -0,0 +1,194 @@
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot import on_command
from util.utils import get_message_text, UserExistLimiter, is_number
from .data_source import get_pixiv_urls, download_pixiv_imgs, search_pixiv_urls
import time
from services.log import logger
from nonebot.adapters.cqhttp.exception import NetworkError
__plugin_usage__1 = '''P站排行榜帮助
可选参数
类型
1. 日排行
2. 周排行
3. 月排行
4. 原创排行
5. 新人排行
6. R18日排行
7. R18周排行
8. R18受男性欢迎排行
9. R18重口排行慎重
使用时选择参数序号即可R18仅可私聊
p站排行榜 类型 数量(可选) 日期(可选)
示例
p站排行榜 无参数默认为日榜
p站排行榜 1
p站排行榜 1 5
p站排行榜 1 5 2018-4-25
注意空格在线搜索会较慢
'''
__plugin_usage__2 = '''P站搜图帮助
可选参数
1.热度排序
2.时间排序
使用时选择参数序号即可R18仅可私聊
搜图 关键词 数量(可选) 排序方式(可选) r18(可选)
示例
搜图 樱岛麻衣
搜图 樱岛麻衣 5 1
搜图 樱岛麻衣 5 2 r18
默认为 热度排序
注意空格在线搜索会较慢数量可能不符
'''
rank_dict = {
'1': 'day',
'2': 'week',
'3': 'month',
'4': 'week_original',
'5': 'week_rookie',
'6': 'day_r18',
'7': 'week_r18',
'8': 'day_male_r18',
'9': 'week_r18g'
}
_ulmt = UserExistLimiter()
pixiv_rank = on_command('p站排行', aliases={'P站排行榜', 'p站排行榜', 'P站排行榜'}, priority=5, block=True)
pixiv_keyword = on_command('搜图', priority=5, block=True)
@pixiv_rank.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json()).strip()
if msg in ['帮助']:
await pixiv_rank.finish(__plugin_usage__1)
msg = msg.split(' ')
msg = [m for m in msg if m]
if not msg:
msg = ['1']
if msg[0] in ['6', '7', '8', '9']:
if event.message_type == 'group':
await pixiv_rank.finish('羞羞脸!私聊里自己看!', at_sender=True)
# print(msg)
if _ulmt.check(event.user_id):
await pixiv_rank.finish("P站排行榜正在搜索噢不要重复触发命令呀")
_ulmt.set_True(event.user_id)
if len(msg) == 0 or msg[0] == '':
text_list, urls, code = await get_pixiv_urls(rank_dict.get('1'))
elif len(msg) == 1:
if msg[0] not in ['1', '2', '3', '4', '5', '6', '7', '8', '9']:
await pixiv_rank.finish("要好好输入要看什么类型的排行榜呀!", at_sender=True)
text_list, urls, code = await get_pixiv_urls(rank_dict.get(msg[0]))
elif len(msg) == 2:
text_list, urls, code = await get_pixiv_urls(rank_dict.get(msg[0]), int(msg[1]))
elif len(msg) == 3:
if not check_date(msg[2]):
await pixiv_rank.finish('日期格式错误了', at_sender=True)
text_list, urls, code = await get_pixiv_urls(rank_dict.get(msg[0]), int(msg[1]), msg[2])
else:
_ulmt.set_False(event.user_id)
await pixiv_rank.finish('格式错了噢,看看帮助?', at_sender=True)
if code != 200:
await pixiv_keyword.finish(text_list[0])
else:
if not text_list or not urls:
await pixiv_rank.finish('没有找到啊,等等再试试吧~V', at_sender=True)
for i in range(len(text_list)):
try:
await pixiv_rank.send(text_list[i] + await download_pixiv_imgs(urls[i], event.user_id))
except NetworkError:
await pixiv_keyword.send('这张图网络炸了!', at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})"
f" 查看了P站排行榜 code{msg[0]}")
_ulmt.set_False(event.user_id)
@pixiv_keyword.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
msg = get_message_text(event.json()).strip()
if msg in ['帮助'] or not msg:
await pixiv_keyword.finish(__plugin_usage__2)
if event.message_type == 'group':
if msg.find('r18') != -1:
await pixiv_keyword.finish('(脸红#) 你不会害羞的 八嘎!', at_sender=True)
if msg.find('r18') == -1:
r18 = 1
else:
r18 = 2
msg = msg.replace('r18', '').strip()
if _ulmt.check(event.user_id):
await pixiv_rank.finish("P站关键词正在搜索噢不要重复触发命令呀")
_ulmt.set_True(event.user_id)
msg = msg.split(' ')
msg = [m for m in msg if m]
if len(msg) == 1:
keyword = msg[0].strip()
num = 5
order = 'popular'
elif len(msg) == 2:
keyword = msg[0].strip()
if not is_number(msg[1].strip()):
_ulmt.set_False(event.user_id)
await pixiv_keyword.finish('图片数量必须是数字!', at_sender=True)
num = int(msg[1].strip())
order = 'popular'
elif len(msg) == 3:
keyword = msg[0].strip()
if not is_number(msg[1].strip()):
_ulmt.set_False(event.user_id)
await pixiv_keyword.finish('图片数量必须是数字!', at_sender=True)
num = int(msg[1].strip())
if not is_number(msg[2].strip()):
_ulmt.set_False(event.user_id)
await pixiv_keyword.finish('排序方式必须是数字!', at_sender=True)
if msg[2].strip() == '1':
order = 'popular'
else:
order = 'xxx'
else:
_ulmt.set_False(event.user_id)
await pixiv_keyword.finish('参数不正确,一定要好好看看帮助啊!', at_sender=True)
text_list, urls, code = await search_pixiv_urls(keyword, num, order, r18)
if code != 200:
_ulmt.set_False(event.user_id)
await pixiv_keyword.finish(text_list[0])
else:
for i in range(len(text_list)):
try:
await pixiv_keyword.send(text_list[i] + await download_pixiv_imgs(urls[i], event.user_id))
except NetworkError:
await pixiv_keyword.send('这张图网络炸了!', at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'})"
f" 查看了搜索 {keyword} R18{r18}")
_ulmt.set_False(event.user_id)
def check_date(date):
try:
time.strptime(date, "%Y-%m-%d")
return True
except:
return False

View File

@ -0,0 +1,84 @@
import aiohttp
import aiofiles
from configs.path_config import IMAGE_PATH
from util.utils import get_local_proxy
from util.user_agent import get_user_agent
from bs4 import BeautifulSoup
import feedparser
from util.init_result import image
from asyncio.exceptions import TimeoutError
import platform
if platform.system() == 'Windows':
import asyncio
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
async def get_pixiv_urls(mode: str, num: int = 5, date: str = '') -> 'list, list, int':
url = 'https://rsshub.app/pixiv/ranking/{}'
iurl = url.format(mode)
if date:
iurl += f'/{date}'
return await parser_data(iurl, num)
async def download_pixiv_imgs(urls: list, user_id: int) -> str:
result = ''
index = 0
for img in urls:
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
for _ in range(3):
async with session.get(img, proxy=get_local_proxy(), timeout=3) as response:
async with aiofiles.open(IMAGE_PATH + f'temp/{user_id}_{index}_pixiv.jpg', 'wb') as f:
try:
await f.write(await response.read())
result += image(f'{user_id}_{index}_pixiv.jpg', 'temp')
index += 1
break
except TimeoutError:
# result += '\n这张图下载失败了..\n'
pass
else:
result += '\n这张图下载失败了..\n'
return result
async def search_pixiv_urls(keyword: str, num: int, order: str, r18: int) -> 'list, list':
url = 'https://rsshub.app/pixiv/search/{}/{}/{}'.format(keyword, order, r18)
return await parser_data(url, num)
async def parser_data(url: str, num: int) -> 'list, list, int':
text_list = []
urls = []
async with aiohttp.ClientSession() as session:
for _ in range(3):
try:
async with session.get(url, proxy=get_local_proxy(), timeout=4) as response:
data = feedparser.parse(await response.text())['entries']
break
except TimeoutError:
pass
else:
return ['网络不太好,也许过一会就好了'], [], 998
try:
if len(data) == 0:
return ['没有搜索到喔'], [], 997
if num > len(data):
num = len(data)
data = data[:num]
for data in data:
soup = BeautifulSoup(data['summary'], 'lxml')
title = "标题:" + data['title']
pl = soup.find_all('p')
author = pl[0].text.split('-')[0].strip()
imgs = []
text_list.append(f'{title}\n{author}\n')
for p in pl[1:]:
imgs.append(p.find('img').get('src'))
urls.append(imgs)
except ValueError:
return ['是网站坏了啊,也许过一会就好了'], [], 999
return text_list, urls, 200
# asyncio.get_event_loop().run_until_complete(get_pixiv_urls('day'))

52
plugins/poke/__init__.py Normal file
View File

@ -0,0 +1,52 @@
from nonebot import on_notice
from nonebot.adapters.cqhttp import Bot, PokeNotifyEvent
from nonebot.typing import T_State
from configs.path_config import VOICE_PATH, IMAGE_PATH
import os
from util.init_result import record, image, poke
from services.log import logger
import random
from util.utils import CountLimiter
from models.ban_user import BanUser
# 戳 一 戳
poke__reply = [
"lsp你再戳", "连个可爱美少女都要戳的肥宅真恶心啊。",
"你再戳!", "?再戳试试?", "别戳了别戳了再戳就坏了555", "我爪巴爪巴,球球别再戳了", "你戳你🐎呢?!",
"那...那里...那里不能戳...绝对...", "(。´・ω・)ん?", "有事恁叫我,别天天一个劲戳戳戳!", "欸很烦欸!你戳🔨呢",
"?", "再戳一下试试?", "???", "正在关闭对您的所有服务...关闭成功", "啊呜,太舒服刚刚竟然睡着了。什么事?", "正在定位您的真实地址。。。\r\n定位成功。轰炸机已起飞"
]
_clmt = CountLimiter(3)
poke_ = on_notice(priority=5)
@poke_.handle()
async def _poke_(bot: Bot, event: PokeNotifyEvent, state: T_State) -> None:
if event.notice_type == 'notify' and event.sub_type == 'poke' and event.self_id == event.target_id:
_clmt.add(event.user_id)
if _clmt.check(event.user_id) or random.random() < 0.3:
rst = ''
if random.random() < 0.15:
await BanUser.ban(event.user_id, 1, 60)
rst = '气死我了!'
await poke_.finish(rst + random.choice(poke__reply), at_sender=True)
rand = random.random()
if rand <= 0.3:
path = random.choice(['loli/', 'meitu/'])
index = random.randint(0, len(os.listdir(IMAGE_PATH + path)))
result = f'id{index}' + image(f'{index}.jpg', path)
await poke_.send(result)
logger.info(f'USER {event.user_id} 戳了戳我 回复: {result} \n {result}')
elif 0.3 < rand < 0.6:
voice = random.choice(os.listdir(VOICE_PATH + 'dinggong/'))
result = record(voice, "dinggong")
await poke_.send(result)
await poke_.send(voice.split('_')[1])
logger.info(f'USER {event.user_id} 戳了戳我 回复: {result} \n {voice.split("_")[1]}')
else:
await poke_.send(poke(event.user_id))

96
plugins/reimu/__init__.py Normal file
View File

@ -0,0 +1,96 @@
from nonebot import on_command
from nonebot.adapters.cqhttp.permission import PRIVATE
from .data_source import from_reimu_get_info
from services.log import logger
from nonebot.adapters.cqhttp import Bot, Event
from nonebot.typing import T_State
from util.utils import is_number, get_message_text, UserExistLimiter, scheduler
from models.count_user import UserCount
from configs.config import COUNT_PER_DAY_REIMU
__plugin_name__ = '上车'
__plugin_usage__ = r"""
* 请各位使用后不要转发 *
* 大部分解压密码是⑨ *
/ 每人每天仅提供 5 次上车机会只能私聊更多次数请向管理员申请用爱发电限制小色批乱搜 /
/ 并不推荐小色批使用此功能主要是不够色目的不够明确 /
上车 [目的地]
上车 5 [目的地] 该目的地第5页停车场
ps: 请尽量提供具体的目的地名称
""".strip()
_ulmt = UserExistLimiter()
reimu = on_command('上车', permission=PRIVATE, block=True, priority=1)
@reimu.args_parser
async def _(bot: Bot, event: Event, state: T_State):
if get_message_text(event.json()) in ['取消', '算了']:
await reimu.finish("已取消操作..", at_sender=True)
if not get_message_text(event.json()):
await reimu.reject('没时间等了!快说你要去哪里?', at_sender=True)
state['keyword'] = get_message_text(event.json())
state['page'] = 1
@reimu.handle()
async def _(bot: Bot, event: Event, state: T_State):
if str(event.get_message()) in ['帮助']:
await reimu.finish(__plugin_usage__)
if await UserCount.check_count(event.user_id, 'reimu', COUNT_PER_DAY_REIMU):
await reimu.finish('今天已经没车了,请明天再来...', at_sender=True)
if _ulmt.check(event.user_id):
await reimu.finish('您还没下车呢,请稍等...', at_sender=True)
_ulmt.set_True(event.user_id)
msg = get_message_text(event.json())
args = msg.split(" ")
if msg in ['!', '', '?', '', ',', '', '.', '']:
await reimu.finish(__plugin_usage__)
if msg:
if len(args) > 1 and is_number(args[0]):
state['keyword'] = args[1]
state['page'] = args[0]
else:
state['keyword'] = msg
state['page'] = 1
@reimu.got('keyword', '你的目的地是哪?')
async def _(bot: Bot, event: Event, state: T_State):
try:
keyword = state['keyword']
page = state['page']
print(keyword, page)
await UserCount.add_count(event.user_id, 'reimu')
await reimu.send('已经帮你关好车门了', at_sender=True)
reimu_report = await from_reimu_get_info(keyword, page)
if reimu_report:
await reimu.send(reimu_report)
else:
logger.error("Not found reimuInfo")
await reimu.send("没找着")
_ulmt.set_False(event.user_id)
except:
_ulmt.set_False(event.user_id)
@scheduler.scheduled_job(
'cron',
# year=None,
# month=None,
# day=None,
# week=None,
# day_of_week="mon,tue,wed,thu,fri",
hour=0,
minute=1,
# second=None,
# start_date=None,
# end_date=None,
# timezone=None,
)
async def _():
await UserCount.reset_count()

View File

@ -0,0 +1,116 @@
from lxml import etree
import time
import aiohttp
from services.log import logger
from configs.config import MAXINFO_REIMU
from util.user_agent import get_user_agent
from util.utils import get_local_proxy
from asyncio.exceptions import TimeoutError
async def from_reimu_get_info(key_word: str, page: int) -> str:
if "miku" in key_word.lower():
logger.warning("Taboo words are being triggered")
return None
repass = ""
url = 'https://blog.reimu.net/search/' + key_word + '/page/' + str(page)
url_s = 'https://blog.reimu.net/'
try:
if key_word == "最近的存档":
logger.debug("Now starting get the {}".format(url_s))
repass = await get_repass(url_s)
else:
logger.debug("Now starting get the {}".format(url))
repass = await get_repass(url)
except TimeoutError as e:
logger.error("Timeout! {}".format(e))
return repass
async def get_repass(url: str) -> str:
repass = ""
info = "[Note]注意大部分资源解压密码为⑨\n"
fund = None
print(url)
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(url, proxy=get_local_proxy(), timeout=15) as response:
html = etree.HTML(await response.text())
fund_l = html.xpath('//h1[@class="page-title"]/text()')
if fund_l:
fund = fund_l[0]
if fund == "未找到":
return "老司机也找不到路了……"
else:
pass
headers = html.xpath('//article/header/h2/a/text()')
urls = html.xpath('//article/header/h2/a/@href')
logger.debug("Now get {} post from search page".format(len(headers)))
headers_d = []
urls_d = []
for i, header in enumerate(headers):
if check_need_list(header):
headers_d.append(headers[i])
urls_d.append(urls[i])
else:
logger.debug("This title {} does not meet the requirements".format(header))
header_len = len(headers_d)
logger.debug("Get {} post after processing".format(header_len))
if header_len > MAXINFO_REIMU:
headers_d = headers_d[:MAXINFO_REIMU]
urls_d = urls_d[:MAXINFO_REIMU]
for h_s, url_s in zip(headers_d, urls_d):
if h_s != "审核结果存档":
time.sleep(1.5)
putline = await get_son_html_info(h_s, url_s)
if putline:
if repass:
repass = "\n\n- - - - - - - - \n".join([repass, putline])
else:
repass = putline
else:
logger.info("审核归档页面已跳过")
if repass:
repass = info + repass
return repass
async def get_son_html_info(h_s, url_s) -> str:
repass = ""
logger.debug("Now starting get the {}".format(url_s))
async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(url_s, proxy=get_local_proxy(), timeout=15) as response:
html = etree.HTML(await response.text())
pres = html.xpath('//div[@class="entry-content"]/pre/text()')
a_texts = html.xpath('//div[@class="entry-content"]/pre//a/text()')
a_hrefs = html.xpath('//div[@class="entry-content"]/pre//a/@href')
if pres and a_texts and a_hrefs:
while "" in pres:
pres.remove("")
repass = "【资源名称】 {}\n\n{}".format(h_s, pres[0].strip())
for i, (a_t_s, a_h_s) in enumerate(zip(a_texts, a_hrefs)):
a = "\n {} {} {} ".format(a_t_s, a_h_s, pres[i + 1].strip())
repass += a
else:
logger.warning("Not get putline from {}".format(url_s))
return repass
def check_need_list(header: str) -> bool:
not_need = ['音乐', '御所动态']
for nd in not_need:
if nd in header:
return False
return True
# print(asyncio.get_event_loop().run_until_complete(from_reimu_get_info('萝莉')))

194
plugins/remind/__init__.py Normal file
View File

@ -0,0 +1,194 @@
from util.init_result import image
from util.utils import scheduler, get_bot
from services.log import logger
from models.group_remind import GroupRemind
from models.group_info import GroupInfo
from models.friend_user import FriendUser
from nonebot.adapters.cqhttp.exception import ActionFailed
__name__ = "早晚安 [Hidden]"
# 早上好
@scheduler.scheduled_job(
'cron',
# year=None,
# month=None,
# day=None,
# week=None,
# day_of_week="mon,tue,wed,thu,fri",
hour=6,
minute=1,
# second=None,
# start_date=None,
# end_date=None,
# timezone=None,
)
async def _():
try:
bot = get_bot()
gl = await bot.get_group_list(self_id=bot.self_id)
gl = [g['group_id'] for g in gl]
for g in gl:
if await GroupRemind.get_status(g, 'zwa'):
result = image("zao.jpg", "zhenxun")
try:
await bot.send_group_msg(group_id=g,
message="早上好" + result)
except ActionFailed:
logger.warning(f'{g} 群被禁言中,无法发送早安')
except Exception as e:
logger.error(f'早晚安错误 e:{e}')
# 睡觉了
@scheduler.scheduled_job(
'cron',
hour=23,
minute=59,
)
async def _():
try:
bot = get_bot()
gl = await bot.get_group_list(self_id=bot.self_id)
gl = [g['group_id'] for g in gl]
for g in gl:
if await GroupRemind.get_status(g, 'zwa'):
result = image("sleep.jpg", "zhenxun")
try:
await bot.send_group_msg(group_id=g,
message="小真寻要睡觉了,你们也要早点睡呀" + result)
except ActionFailed:
logger.warning(f'{g} 群被禁言中,无法发送晚安')
except Exception as e:
logger.error(f'早晚安错误 e:{e}')
# 自动更新群组信息
@scheduler.scheduled_job(
'cron',
hour=3,
minute=1,
)
async def _():
try:
bot = get_bot()
gl = await bot.get_group_list(self_id=bot.self_id)
gl = [g['group_id'] for g in gl]
for g in gl:
group_info = await bot.get_group_info(group_id=g)
await GroupInfo.add_group_info(group_info['group_id'], group_info['group_name'],
group_info['max_member_count'], group_info['member_count'])
logger.info(f'自动更新群组 {g} 信息成功')
except Exception as e:
logger.error(f'自动更新群组信息错误 e:{e}')
# 自动更新好友信息
@scheduler.scheduled_job(
'cron',
hour=3,
minute=1,
)
async def _():
try:
bot = get_bot()
fl = await bot.get_friend_list(self_id=bot.self_id)
for f in fl:
if await FriendUser.add_friend_info(f['user_id'], f['nickname']):
logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
else:
logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
except Exception as e:
logger.error(f'自动更新群组信息错误 e:{e}')
# 一次性任务
# 固定时间触发,仅触发一次:
#
# from datetime import datetime
#
# @nonebot.scheduler.scheduled_job(
# 'date',
# run_date=datetime(2021, 1, 1, 0, 0),
# # timezone=None,
# )
# async def _():
# await bot.send_group_msg(group_id=123456,
# message="2021新年快乐")
# 定期任务
# 从 start_date 开始到 end_date 结束,根据类似 Cron
#
# 的规则触发任务:
#
# @nonebot.scheduler.scheduled_job(
# 'cron',
# # year=None,
# # month=None,
# # day=None,
# # week=None,
# day_of_week="mon,tue,wed,thu,fri",
# hour=7,
# # minute=None,
# # second=None,
# # start_date=None,
# # end_date=None,
# # timezone=None,
# )
# async def _():
# await bot.send_group_msg(group_id=123456,
# message="起床啦!")
# 间隔任务
#
# interval 触发器
#
# 从 start_date 开始,每间隔一段时间触发,到 end_date 结束:
#
# @nonebot.scheduler.scheduled_job(
# 'interval',
# # weeks=0,
# # days=0,
# # hours=0,
# minutes=5,
# # seconds=0,
# # start_date=time.now(),
# # end_date=None,
# )
# async def _():
# has_new_item = check_new_item()
# if has_new_item:
# await bot.send_group_msg(group_id=123456,
# message="XX有更新啦")
# 动态的计划任务
# import datetime
#
# from apscheduler.triggers.date import DateTrigger # 一次性触发器
# # from apscheduler.triggers.cron import CronTrigger # 定期触发器
# # from apscheduler.triggers.interval import IntervalTrigger # 间隔触发器
# from nonebot import on_command, scheduler
#
# @on_command('赖床')
# async def _(session: CommandSession):
# await session.send('我会在5分钟后再喊你')
#
# # 制作一个“5分钟后”触发器
# delta = datetime.timedelta(minutes=5)
# trigger = DateTrigger(
# run_date=datetime.datetime.now() + delta
# )
#
# # 添加任务
# scheduler.add_job(
# func=session.send, # 要添加任务的函数,不要带参数
# trigger=trigger, # 触发器
# args=('不要再赖床啦!',), # 函数的参数列表,注意:只有一个值时,不能省略末尾的逗号
# # kwargs=None,
# misfire_grace_time=60, # 允许的误差时间,建议不要省略
# # jobstore='default', # 任务储存库,在下一小节中说明
# )

View File

@ -0,0 +1,56 @@
from nonebot import on_command
from .data_source import from_anime_get_info
from services.log import logger
from nonebot.adapters.cqhttp import Bot, Event
from nonebot.typing import T_State
from configs.config import MAXINFO_GROUP_ANIME, MAXINFO_PRIVATE_ANIME
from util.utils import get_message_text, get_message_type, UserExistLimiter
__plugin_name__ = '搜番'
__plugin_usage__ = r"""
在群内使用此功能只返还5个结果私聊返还 20 个结果绝不能打扰老色批们看色图
搜索动漫资源
搜番 [番剧名称或者关键词]
搜番 Aria
""".strip()
_ulmt = UserExistLimiter()
search_anime = on_command('搜番', aliases={'搜动漫'}, priority=5, block=True)
@search_anime.args_parser
async def _(bot: Bot, event: Event, state: T_State):
msg = get_message_text(event.json())
if not msg:
await search_anime.reject('番名番名番名呢?', at_sender=True)
state['anime'] = msg
@search_anime.handle()
async def _(bot: Bot, event: Event, state: T_State):
if get_message_text(event.json()) in ['帮助'] or get_message_text(event.json()) == '':
await search_anime.finish(__plugin_usage__)
if _ulmt.check(event.user_id):
await search_anime.finish('您有动漫正在搜索,请稍等...', at_sender=True)
_ulmt.set_True(event.user_id)
if get_message_text(event.json()):
state['anime'] = get_message_text(event.json())
@search_anime.got('anime', prompt='是不是少了番名?')
async def _(bot: Bot, event: Event, state: T_State):
key_word = state['anime']
await search_anime.send(f'开始搜番 {key_word}', at_sender=True)
anime_report = await from_anime_get_info(key_word, MAXINFO_GROUP_ANIME if get_message_type(event.json()) in ['group', 'discuss'] else MAXINFO_PRIVATE_ANIME)
if anime_report:
await search_anime.send(anime_report)
logger.info(f"USER {event.user_id} GROUP"
f" {event.group_id if event.message_type != 'private' else 'private'} 搜索番剧 {key_word} 成功")
else:
logger.warning(f"未找到番剧 {key_word}")
await search_anime.send(f"未找到番剧 {key_word}(也有可能是超时,再尝试一下?)")
_ulmt.set_False(event.user_id)

View File

@ -0,0 +1,47 @@
from lxml import etree
import feedparser
from urllib import parse
from services.log import logger
import aiohttp
import time
from util.utils import get_local_proxy
async def from_anime_get_info(key_word: str, max: int) -> str:
s_time = time.time()
repass = ""
url = 'https://share.dmhy.org/topics/rss/rss.xml?keyword=' + parse.quote(key_word)
try:
logger.debug("Now starting get the {}".format(url))
repass = await get_repass(url, max)
except Exception as e:
logger.error("Timeout! {}".format(e))
return f"搜索 {key_word} 结果(耗时 {int(time.time() - s_time)} 秒):\n" + repass
async def get_repass(url: str, max: int) -> str:
putline = []
async with aiohttp.ClientSession() as session:
async with session.get(url, proxy=get_local_proxy(), timeout=20) as response:
d = feedparser.parse(await response.text())
url_list = [e.link for e in d.entries][:max]
for u in url_list:
print(u)
try:
async with session.get(u, proxy=get_local_proxy(), timeout=20) as res:
html = etree.HTML(await res.text())
magent = html.xpath('.//a[@id="a_magnet"]/text()')[0]
title = html.xpath('.//h3/text()')[0]
item = html.xpath('//div[@class="info resource-info right"]/ul/li')
class_a = item[0].xpath('string(.)')[5:].strip().replace("\xa0", "").replace("\t", "")
size = item[3].xpath('string(.)')[5:].strip()
putline.append("{}】| {}\n{}】| {}".format(class_a, title, size, magent))
except Exception as e:
logger.warning(f'搜番超时 e{e}')
repass = '\n\n'.join(putline)
return repass
# print(asyncio.get_event_loop().run_until_complete(from_anime_get_info('进击的巨人', 1234556)))

View File

@ -0,0 +1,75 @@
from nonebot import on_command
from .data_source import get_price, update_buff_cookie
from services.log import logger
from nonebot.typing import T_State
from nonebot.adapters import Bot, Event
from nonebot.rule import to_me
from nonebot.permission import SUPERUSER
from util.utils import UserExistLimiter, get_message_text
__plugin_name__ = '查询皮肤'
__plugin_usage__ = '查询皮肤帮助:\n\t' \
'对我说 "查询皮肤 xxx yyyy"我会回复xxx的底价哦\n\t' \
'示例: 查询皮肤 awp 二西莫夫'
_ulmt = UserExistLimiter()
search_skin = on_command('查询皮肤', aliases={'皮肤查询'}, priority=5, block=True)
@search_skin.args_parser
async def parse(bot: Bot, event: Event, state: T_State):
if get_message_text(event.json()) in ['取消', '算了']:
await search_skin.finish("已取消操作..", at_sender=True)
state[state["_current_key"]] = str(event.get_message())
@search_skin.handle()
async def _(bot: Bot, event: Event, state: T_State):
if str(event.get_message()) in ['帮助']:
await search_skin.finish(__plugin_usage__)
raw_arg = get_message_text(event.json())
if _ulmt.check(event.user_id):
await search_skin.finish('您有皮肤正在搜索,请稍等...', at_sender=True)
if raw_arg:
args = raw_arg.split(" ")
if len(args) >= 2:
state['name'] = args[0]
state['skin'] = args[1]
@search_skin.got('name', prompt="要查询什么武器呢?")
@search_skin.got('skin', prompt="要查询该武器的什么皮肤呢?")
async def arg_handle(bot: Bot, event: Event, state: T_State):
_ulmt.set_True(event.user_id)
if state['name'] in ['ak', 'ak47']:
state['name'] = 'ak-47'
name = state['name'] + " | " + state['skin']
try:
result, status_code = await get_price(name)
except FileNotFoundError:
await search_skin.finish('请先对真寻说"设置cookie"来设置cookie')
if status_code in [996, 997, 998]:
_ulmt.set_False(event.user_id)
await search_skin.finish(result)
if result:
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 查询皮肤:" + name)
_ulmt.set_False(event.user_id)
await search_skin.finish(result)
else:
logger.info(f"USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}"
f" 查询皮肤:{name} 没有查询到")
_ulmt.set_False(event.user_id)
await search_skin.finish("没有查询到哦,请检查格式吧")
update_buff_session = on_command("更新cookie", rule=to_me(), permission=SUPERUSER, priority=1)
@update_buff_session.handle()
async def _(bot: Bot, event: Event, state: T_State):
await update_buff_session.finish(update_buff_cookie(str(event.get_message())), at_sender=True)

View File

@ -0,0 +1,66 @@
from util.user_agent import get_user_agent
import aiohttp
from util.utils import get_cookie_text
from configs.path_config import TXT_PATH
from asyncio.exceptions import TimeoutError
from configs.config import buff_proxy
from pathlib import Path
from services.log import logger
url = "https://buff.163.com/api/market/goods"
async def get_price(dname):
cookie = {'session': get_cookie_text('buff')}
name_list = []
price_list = []
parameter = {
"game": "csgo",
"page_num": "1",
"search": dname
}
try:
async with aiohttp.ClientSession(cookies=cookie, headers=get_user_agent()) as session:
async with session.get(url, proxy=buff_proxy, params=parameter, timeout=5) as response:
if response.status == 200:
try:
if str(await response.text()).find("Login Required") != -1:
return "BUFF登录被重置请联系管理员重新登入", 996
data = (await response.json())["data"]
total_page = data["total_page"]
data = data["items"]
for _ in range(total_page):
for i in range(len(data)):
name = data[i]["name"]
price = data[i]["sell_reference_price"]
name_list.append(name)
price_list.append(price)
except Exception as e:
return "没有查询到...", 998
else:
return "访问失败!", response.status
except TimeoutError as e:
return "访问超时! 请重试或稍后再试!", 997
result = f"皮肤: {dname}({len(name_list)})\n"
# result = "皮肤: " + dname + "\n"
for i in range(len(name_list)):
result += name_list[i] + ": " + price_list[i] + "\n"
return result[:-1], 999
def update_buff_cookie(cookie: str):
_cookie = Path(TXT_PATH + "cookie/buff.txt")
try:
_cookie.parent.mkdir(parents=True, exist_ok=True)
with open(_cookie, 'w') as f:
f.write(cookie)
return "更新cookie成功"
except Exception as e:
logger.error(f'更新cookie失败 e:{e}')
return "更新cookie失败"
if __name__ == '__main__':
print(get_price("awp 二西莫夫"))

View File

@ -0,0 +1,33 @@
from nonebot import on_keyword
from util.init_result import record
from configs.path_config import VOICE_PATH
import random
from services.log import logger
from util.utils import FreqLimiter
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
from nonebot.rule import to_me
import os
__plugin_name__ = '骂我'
__plugin_usage__ = '对我说 "骂我",我真的会骂你哦'
_flmt = FreqLimiter(3)
dg_voice = on_keyword({''}, rule=to_me(), priority=5, block=True)
@dg_voice.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
if len(str((event.get_message()))) == 1:
return
if not _flmt.check(event.user_id):
await dg_voice.finish('就...就算求我骂你也得慢慢来...', at_sender=True)
_flmt.start_cd(event.user_id)
voice = random.choice(os.listdir(VOICE_PATH + 'dinggong/'))
result = record(voice, "dinggong")
await dg_voice.send(result)
await dg_voice.send(voice.split('_')[1])
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 发送钉宫骂人:" + result)

View File

@ -0,0 +1,68 @@
from nonebot import on_command, on_keyword
from configs.path_config import IMAGE_PATH
from util.init_result import image
import os
import random
from util.utils import is_number
from services.log import logger
from nonebot.typing import T_State
from nonebot.adapters import Bot, Event
from util.utils import FreqLimiter, cn2py
from models.group_remind import GroupRemind
from configs.config import IMAGE_DIR_LIST
__plugin_name__ = '壁纸/萝莉/美图'
__plugin_usage__ = '用法: 发送"壁纸/萝莉/美图", 回复图片后添加id获得指定图片'
_flmt = FreqLimiter(1)
IMAGE_DIR_LIST.remove('色图')
cmd = set(IMAGE_DIR_LIST)
# print(cmd)
send_img = on_command("img", aliases=cmd, priority=5, block=True)
@send_img.handle()
async def _(bot: Bot, event: Event, state: T_State):
img_id = str(event.get_message())
if img_id in ['帮助']:
await send_img.finish(__plugin_usage__)
path = cn2py(state["_prefix"]["raw_command"]) + '/'
if not os.path.exists(IMAGE_PATH + path):
logger.warning(f'未找到 {path} 文件夹,调用取消!')
return
length = len(os.listdir(IMAGE_PATH + path)) - 1
index = img_id if img_id else str(random.randint(0, length))
if not is_number(index):
await send_img.finish("id错误")
if int(index) > length or int(index) < 0:
await send_img.finish(f"超过当前上下限!({length - 1})")
result = image(f'{index}.jpg', path)
if result:
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 发送{path}:" + result)
await send_img.finish(f"id{index}" + result)
else:
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if event.message_type != 'private' else 'private'}) 发送 {path} 失败")
await send_img.finish(f"不想给你看Ov|")
pa = on_keyword({""}, priority=1, block=True)
@pa.handle()
async def _(bot: Bot, event: Event, state: T_State):
if await GroupRemind.get_status(event.group_id, 'pa'):
try:
if str(event.get_message()[:2]) in ['开启', '关闭']:
return
except:
return
if not _flmt.check(event.user_id):
return
_flmt.start_cd(event.user_id)
await pa.finish(image(random.choice(os.listdir(IMAGE_PATH + "pa")), 'pa'))

View File

@ -0,0 +1,276 @@
import random
from nonebot import on_command, on_regex
from services.log import logger
from models.sigin_group_user import SignGroupUser
from util.utils import FreqLimiter, UserExistLimiter, is_number, get_message_text, get_message_imgs
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, PrivateMessageEvent
from .data_source import get_setu, get_luoxiang, search_online_setu, get_setu_urls, \
check_r18_and_keyword, find_img_index
from nonebot.adapters.cqhttp.exception import ActionFailed
import re
from models.count_user import UserCount
from aiohttp.client_exceptions import ClientConnectorError
from configs.config import LOCAL_SETU
__plugin_name__ = '色图'
__plugin_usage__ = '''示例:
1. 色图 随机本地色图
2. 色图r 随机在线十张r18涩图
3. 色图 666 本地色图id
4. 色图 xx 在线搜索xx色图
5. 色图r xx 搜索十张xx的r18涩图注意空格仅私聊
6. 来n张涩图 本地涩图连发1<=n<=9
7. 来n张xx的涩图 在线搜索xx涩图较慢看网速
色图r每日提供5次
本地涩图没有r18
联网搜索会较慢
如果图片数量与数字不符
原因1网络不好网线被拔QAQ
原因2搜索到的总数小于数字
原因3图太色或者小错误了'''
url = "https://api.lolicon.app/setu/"
_flmt = FreqLimiter(5)
_ulmt = UserExistLimiter()
path = "setu/"
MAX_COUNT = 5
setu = on_command("色图", aliases={"涩图", "不够色", "来一发", "再来点"}, priority=5, block=True)
setu_reg = on_regex('(.*)[份|发|张|个|次|点](.*)[瑟|色|涩]图', priority=5, block=True)
find_setu = on_command("查色图", priority=5, block=True)
@setu.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
img_id = get_message_text(event.json())
if img_id in ['帮助']:
await setu.finish(__plugin_usage__)
impression = (await SignGroupUser.ensure(event.user_id, event.group_id)).impression
luox = get_luoxiang(impression)
if luox:
await setu.finish(luox)
if not _flmt.check(event.user_id):
await setu.finish('您冲得太快了,请稍候再冲', at_sender=True)
_flmt.start_cd(event.user_id)
if _ulmt.check(event.user_id):
await setu.finish(f"您有色图正在处理,请稍等")
_ulmt.set_True(event.user_id)
setu_img, index = get_setu(img_id)
if setu_img and LOCAL_SETU:
try:
await setu.send(setu_img)
except:
_ulmt.set_False(event.user_id)
await setu.finish('这张图色过头了,我自己看看就行了!', at_sender=True)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 发送色图 {index}.jpg 成功")
else:
msg = img_id
if msg.find(list(bot.config.nickname)[0]) != -1:
_ulmt.set_False(event.user_id)
await setu.finish('咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀')
keyword, r18, num = await check_r18_and_keyword(msg, event.user_id)
if r18 == 1:
_ulmt.set_False(event.user_id)
await setu.finish(random.choice([
"这种不好意思的东西怎么可能给这么多人看啦",
"羞羞脸!给我滚出克私聊!",
"变态变态变态变态大变态!"
]))
try:
urls, text_list, code = await get_setu_urls(keyword, num, r18=r18)
except ClientConnectorError:
await setu.finish('网络失败了..别担心!正在靠运气上网!', at_sender=True)
else:
if code == 200:
for i in range(num):
try:
setu_img, index = await search_online_setu(urls[i])
await setu.send(text_list[i] + setu_img)
logger.info(
f"USER {event.user_id} GROUP {event.group_id}"
f" 发送在线色图 {keyword}.jpg 成功")
except Exception as e:
logger.error(f'色图发送错误 e{e}')
await setu.send('图片下载惜败!', at_sender=True)
else:
await setu.send(urls)
_ulmt.set_False(event.user_id)
@setu.handle()
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
img_id = get_message_text(event.json())
if img_id in ['帮助']:
await setu.finish(__plugin_usage__)
if not _flmt.check(event.user_id):
await setu.finish('您冲得太快了,请稍候再冲', at_sender=True)
_flmt.start_cd(event.user_id)
if _ulmt.check(event.user_id):
await setu.finish(f"您有色图正在处理,请稍等")
_ulmt.set_True(event.user_id)
setu_img, index = get_setu(img_id)
if setu_img:
await setu.send(setu_img)
logger.info(
f"USER {event.user_id} GROUP private 发送色图 {index}.jpg 成功")
else:
msg = img_id
if msg.find(list(bot.config.nickname)[0]) != -1:
_ulmt.set_False(event.user_id)
await setu.finish('咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀')
keyword, r18, num = await check_r18_and_keyword(msg, event.user_id)
if r18 == 1:
if await UserCount.check_count(event.user_id, 'setu_r18', MAX_COUNT):
_ulmt.set_False(event.user_id)
await setu.finish('要节制啊,请明天再来...\n【每日提供5次】', at_sender=True)
try:
urls, text_list, code = await get_setu_urls(keyword, num, r18=r18)
except ClientConnectorError:
await UserCount.add_count(event.user_id, 'setu_r18', count=-1)
await setu.finish('网络失败了..别担心!这次搜索不算数喔', at_sender=True)
else:
count = 0
if code == 200:
for i in range(num):
try:
setu_img, index = await search_online_setu(urls[i])
await setu.send(text_list[i] + setu_img)
logger.info(
f"USER {event.user_id} GROUP private"
f" 发送{'r18' if img_id == 'r' else ''}色图 {index}.jpg 成功")
except Exception as e:
logger.error(f'色图发送错误 e{e}')
await setu.send('图片下载惜败!', at_sender=True)
count += 1
if count > 6:
await setu.send('检测到下载惜败的图片过多,这次就不算数了,果咩..', at_sender=True)
await UserCount.add_count(event.user_id, 'setu_r18', count=-1)
else:
if code == 401:
if r18 == 1:
await UserCount.add_count(event.user_id, 'setu_r18', count=-1)
await setu.send(urls + ' 色图r次数返还')
else:
await setu.send(urls, at_sender=True)
else:
if r18 == 1:
await setu.send('这次不是小真寻的戳色图r次数返还', at_sender=True)
await UserCount.add_count(event.user_id, 'setu_r18', count=-1)
else:
await setu.send(urls, at_sender=True)
_ulmt.set_False(event.user_id)
num_key = {
'': 1,
'': 2,
'': 2,
'': 2,
'': 3,
'': 4,
'': 5,
'': 6,
'': 7,
'': 8,
'': 9
}
@setu_reg.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
if event.message_type == "group":
impression = (await SignGroupUser.ensure(event.user_id, event.group_id)).impression
luox = get_luoxiang(impression)
if luox:
await setu.finish(luox, at_sender=True)
if _ulmt.check(event.user_id):
await setu.finish(f"您有色图正在处理,请稍等")
_ulmt.set_True(event.user_id)
if not _flmt.check(event.user_id):
_ulmt.set_False(event.user_id)
await setu.finish('您冲得太快了,请稍候再冲', at_sender=True)
_flmt.start_cd(event.user_id)
msg = get_message_text(event.json())
num = 1
msg = re.search(r'(.*)[份|发|张|个|次|点](.*)[瑟|涩|色]图', msg)
if msg:
num = msg.group(1)
keyword = msg.group(2)
if keyword:
if keyword[-1] == '':
keyword = keyword[:-1]
if num:
num = num[-1]
if num_key.get(num):
num = num_key[num]
elif is_number(num):
try:
num = int(num)
except ValueError:
num = 1
else:
num = 1
else:
return
# try:
if not keyword:
for _ in range(num):
try:
img, index = get_setu('')
await setu_reg.send(img)
except Exception as e:
await setu_reg.send('有图太色了发不出来...')
else:
logger.info(
f"USER {event.user_id} GROUP {event.group_id if event.message_type != 'private' else 'private'}"
f" 发送 {index} 色图成功")
else:
urls, text_list, code = await get_setu_urls(keyword, num)
if code == 200:
for i in range(len(urls)):
try:
setu_img, index = await search_online_setu(urls[i])
await setu_reg.send(text_list[i] + '\n' + setu_img)
except ActionFailed as e:
await setu_reg.send('这图太色了,会教坏小孩子的,不给看..')
else:
logger.info(
f"USER {event.user_id} GROUP {event.group_id if event.message_type != 'private' else 'private'}"
f" 发送 {keyword} {num}连 色图成功")
else:
_ulmt.set_False(event.user_id)
await setu_reg.finish(urls, at_sender=True)
_ulmt.set_False(event.user_id)
@find_setu.args_parser
async def _(bot: Bot, event: MessageEvent, state: T_State):
if str(event.message) == '取消':
await find_setu.finish('取消了操作', at_sender=True)
imgs = get_message_imgs(event.json())
if not imgs:
await find_setu.reject("不搞错了,俺要图!")
state['img'] = imgs[0]
@find_setu.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
if get_message_text(event.json()) in ['帮助']:
await find_setu.finish('通过图片获取本地色图id\n\t示例:查色图(图片)')
imgs = get_message_imgs(event.json())
if imgs:
state['img'] = imgs[0]
@find_setu.got('img', prompt="速速来图!")
async def _(bot: Bot, event: MessageEvent, state: T_State):
img = state['img']
await find_setu.send(await find_img_index(img, event.user_id), at_sender=True)

View File

@ -0,0 +1,62 @@
import os
import imagehash
from PIL import Image
try:
import ujson as json
except ModuleNotFoundError:
import json
IMAGE_PATH = r"/home/hibiki/hibikibot/resources/img/"
TXT_PATH = r"/home/hibiki/hibikibot/resources/txt/"
def get_img_hash(image_file):
with open(image_file, 'rb') as fp:
hash_value = imagehash.average_hash(Image.open(fp))
return hash_value
def check_file_index():
for dir_name in ['setu/', 'r18/']:
lens = len(os.listdir(IMAGE_PATH + dir_name))
for i in range(lens):
if i > lens:
return
if not os.path.exists(f"{IMAGE_PATH}{dir_name}{i}.jpg"):
os.rename(f"{IMAGE_PATH}{dir_name}{lens}.jpg", f"{IMAGE_PATH}{dir_name}{i}.jpg")
print(f'{lens}.jpg --> {i}.jpg')
lens -= 1
if not i % 100:
print(f'已检测 {i} 份数据')
print(f'{dir_name} 检测完毕')
def check_setu_hash():
check_file_index()
for dir_name in ['setu/', 'r18/']:
img_data = {}
if dir_name == 'setu/':
fn = 'setu_img_hash.json'
else:
fn = 'r18_setu_img_hash.json'
file_list_len = len(os.listdir(IMAGE_PATH + dir_name)) - 1
print(file_list_len)
for i in range(file_list_len):
file = f"{i}.jpg"
index = file.split(".")[0]
img_hash = str(get_img_hash(IMAGE_PATH + dir_name + file))
print(f'{index}.jpg --> {img_hash}')
if img_hash in img_data.values():
k = [k for k, v in img_data.items() if v == img_hash]
print(f'文件 {index}.jpg 与 {k}.jpg 重复,使用 {file_list_len}.jpg 进行替换')
os.remove(IMAGE_PATH + dir_name + file)
os.rename(IMAGE_PATH + f'{dir_name}{file_list_len}.jpg', IMAGE_PATH + dir_name + file)
file_list_len -= 1
continue
img_data[index] = img_hash
# print(f'{index}.jpg --> {img_data}')
with open(TXT_PATH + fn, 'w') as f:
json.dump(img_data, f, indent=4)
check_setu_hash()

View File

@ -0,0 +1,168 @@
from configs.path_config import IMAGE_PATH, TXT_PATH
import os
import random
from util.init_result import image
from configs.config import LOLICON_KEY
import aiohttp
import aiofiles
from services.log import logger
from util.img_utils import get_img_hash
from util.utils import get_local_proxy, is_number
from asyncio.exceptions import TimeoutError
from models.count_user import UserCount
from configs.config import DOWNLOAD_SETU
try:
import ujson as json
except ModuleNotFoundError:
import json
url = "https://api.lolicon.app/setu/"
path = 'setu/'
async def get_setu_urls(keyword: str, num: int = 1, r18: int = 0):
# print(keyword)
if r18 == 1:
file_name = 'setu_r18_url.txt'
else:
file_name = 'setu_url.txt'
try:
with open(TXT_PATH + file_name, 'r') as f:
txt_data = f.read()
except FileNotFoundError:
txt_data = ''
params = {
"apikey": LOLICON_KEY, # 添加apikey
'r18': r18, # 添加r18参数 0为否1为是2为混合
'keyword': keyword, # 若指定关键字,将会返回从插画标题、作者、标签中模糊搜索的结果
'num': num, # 一次返回的结果数量范围为1到10不提供 APIKEY 时固定为1
'size1200': 1, # 是否使用 master_1200 缩略图,以节省流量或提升加载速度
}
urls = []
text_list = []
for count in range(3):
print(f'get_setu_url: count --> {count}')
async with aiohttp.ClientSession() as session:
try:
async with session.get(url, proxy=get_local_proxy(), timeout=5, params=params) as response:
if response.status == 429:
return '调用达到上限,明日赶早呀~', '', 429
if response.status == 404:
return "网站裂开了...", '', 998
if response.status == 200:
data = await response.json()
if data['code'] == 0:
# print(len(data['data']))
for i in range(len(data['data'])):
img_url = data['data'][i]['url']
title = data['data'][i]['title']
author = data['data'][i]['author']
pid = data['data'][i]['pid']
urls.append(img_url)
text_list.append(f'title{title}\nauthor{author}\nPID{pid}')
img_url = str(img_url).replace('img-master', 'img-original').replace('_master1200', '')
txt_data += img_url + ','
if DOWNLOAD_SETU:
with open(TXT_PATH + file_name, 'w') as f:
f.write(txt_data)
return urls, text_list, 200
else:
return "没找到符合条件的色图...", '', 401
except TimeoutError:
pass
return '我网线被人拔了..QAQ', '', 999
async def search_online_setu(url: str):
async with aiohttp.ClientSession() as session:
for i in range(3):
print(f'search_online_setu --> {i}')
try:
async with session.get(url, proxy=get_local_proxy(), timeout=7) as res:
if res.status == 200:
index = str(random.randint(1, 100000))
async with aiofiles.open(IMAGE_PATH + 'temp/' + index + "_temp_setu.jpg", 'wb') as f:
try:
await f.write(await res.read())
except TimeoutError:
# return '\n这图没下载过来~(网太差?)', -1, False
continue
logger.info(f"下载 lolicon图片 {url} 成功, id{index}")
return image(f'{index}_temp_setu.jpg', 'temp'), index
else:
logger.warning(f"访问 lolicon图片 {url} 失败 status{res.status}")
# return '\n这图好难下载啊QAQ', -1, False
except TimeoutError:
pass
return '\n图片被小怪兽恰掉啦..!QAQ', -1
def get_setu(index: str):
length = len(os.listdir(IMAGE_PATH + path))
if not index:
index = random.randint(0, length - 1)
if is_number(index):
if int(index) > length or int(index) < 0:
return f"超过当前上下限!({length - 1})", 999
else:
return f'id{index}' + image(f'{index}.jpg', 'setu'), index
return None, None
def get_luoxiang(impression):
probability = impression + 70
if probability < random.randint(1, 101):
return "我为什么要给你发这个?" + image(random.choice(os.listdir(IMAGE_PATH + "luoxiang/")), 'luoxiang') + \
"\n(快向小真寻签到提升好感度吧!)"
return None
async def check_r18_and_keyword(msg: str, user_id) -> 'str, int, int':
msg_list = msg.split(' ')
num = 1
r18 = 0
keyword = ''
if len(msg_list) == 1:
if msg_list[0].strip().lower() in ['r', 'r18']:
r18 = 1
num = 10
else:
keyword = msg_list[0]
elif len(msg_list) == 2:
keyword = msg_list[1].strip()
if msg_list[0].strip().lower() in ['r', 'r18']:
r18 = 1
num = 10
else:
keyword = msg[0]
if r18 == 1:
await UserCount.add_user(user_id)
return keyword, r18, num
# def delete_img(index):
# if os.path.exists(IMAGE_PATH + path + f"{index}.jpg"):
# img_hash = str(get_img_hash(IMAGE_PATH + f"setu/{index}.jpg"))
# tp = list(setu_hash_dict.keys())[list(setu_hash_dict.values()).index(img_hash)]
# logger.info(f"色图 {index}.jpg 与 {tp}.jpg 相似, 删除....")
# os.remove(IMAGE_PATH + path + f"{index}.jpg")
async def find_img_index(img_url, user_id):
try:
setu_hash_dict = json.load(open(TXT_PATH + 'setu_img_hash.json'))
except (FileNotFoundError, ValueError):
setu_hash_dict = {}
async with aiohttp.ClientSession() as session:
async with session.get(img_url, proxy=get_local_proxy(), timeout=5) as res:
async with aiofiles.open(IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg", 'wb') as f:
await f.write(await res.read())
img_hash = str(get_img_hash(IMAGE_PATH + f"temp/{user_id}_find_setu_index.jpg"))
try:
tp = list(setu_hash_dict.keys())[list(setu_hash_dict.values()).index(img_hash)]
return "id --> " + str(tp)
except ValueError:
return "该图不在色图库中!"

78
plugins/shop/buy.py Normal file
View File

@ -0,0 +1,78 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from util.utils import get_message_text, is_number
from models.bag_user import UserBag
from services.db_context import db
from nonebot.adapters.cqhttp.permission import GROUP
__plugin_name__ = '商店购买'
__plugin_usage__ = '格式:购买 名称或序号 数量选填默认为1\n\t示例:购买 好感双倍加持卡Ⅰ\n\t示例:购买 1 4'
buy = on_command("购买", aliases={'购买道具'}, priority=5, block=True, permission=GROUP)
goods = [
'好感双倍加持卡Ⅰ\t\t售价30金币\n\t\t今日双倍好感度的概率 + 10%(谁才是真命天子?)(同类道具将覆盖)',
'好感双倍加持卡Ⅱ\t\t售价140金币\n\t\t今日双倍好感度的概率 + 20%(平平庸庸~)(同类道具将覆盖)',
'好感双倍加持卡Ⅲ\t\t售价250金币\n\t\t今日双倍好感度的概率 + 30%(金币才是真命天子!)(同类道具将覆盖)'
]
glist = []
plist = []
for i in range(len(goods)):
glist.append(goods[i].split('\t\t')[0])
plist.append(int(goods[i].split('\t\t')[1].split('')[1].split('金币')[0]))
@buy.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if get_message_text(event.json()) in ['', '帮助']:
await buy.finish(__plugin_usage__)
if get_message_text(event.json()) in ['神秘药水']:
await buy.finish("你们看看就好啦,这是不可能卖给你们的~", at_sender=True)
msg = get_message_text(event.json()).strip().split(' ')
index = -1
num = 1
if len(msg) > 1:
if is_number(msg[1]):
num = int(msg[1])
print(msg, num)
if is_number(msg[0]):
msg = int(msg[0])
if msg > len(goods) or msg < 1:
await buy.finish('请输入正确的商品id', at_sender=True)
index = msg - 1
else:
if msg[0] in glist:
for i in range(len(glist)):
if msg == glist[i]:
index = i
break
else:
await buy.finish('请输入正确的商品名称!', at_sender=True)
async with db.transaction():
if index != -1:
if (await UserBag.get_gold(event.user_id, event.group_id)) < plist[index] * num:
await buy.finish('您的金币好像不太够哦', at_sender=True)
if await UserBag.spend_glod(event.user_id, event.group_id, plist[index] * num):
for _ in range(num):
await UserBag.add_props(event.user_id, event.group_id, glist[index])
await buy.send(f'花费 {plist[index]*num} 金币购买 {glist[index]} ×{num} 成功!', at_sender=True)
logger.info(f'USER {event.user_id} GROUP {event.group_id} '
f'花费 {plist[index]*num} 金币购买 {glist[index]} ×{num} 成功!')
else:
await buy.send(f'{glist[index]} 购买失败!', at_sender=True)
logger.info(f'USER {event.user_id} GROUP {event.group_id} '
f'花费 {plist[index]*num} 金币购买 {glist[index]} ×{num} 失败!')

26
plugins/shop/my_gold.py Normal file
View File

@ -0,0 +1,26 @@
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from models.bag_user import UserBag
from nonebot.adapters.cqhttp.permission import GROUP
__plugin_name__ = '我的金币'
my_gold = on_command("我的金币", priority=5, block=True, permission=GROUP)
@my_gold.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await my_gold.finish(await UserBag.get_my_total_gold(event.user_id, event.group_id))

46
plugins/shop/my_props.py Normal file
View File

@ -0,0 +1,46 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from models.bag_user import UserBag
from nonebot.adapters.cqhttp.permission import GROUP
__plugin_name__ = '商店基础显示'
my_props = on_command("我的道具", priority=5, block=True, permission=GROUP)
@my_props.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
props = await UserBag.get_props(event.user_id, event.group_id)
if props:
pname_list = []
pnum_list = []
rst = ''
props = props[:-1].split(',')
for p in props:
if p != '':
if p in pname_list:
pnum_list[pname_list.index(p)] += 1
else:
pname_list.append(p)
pnum_list.append(1)
for i in range(len(pname_list)):
rst += f'{i+1}.{pname_list[i]}\t×{pnum_list[i]}\n'
await my_props.send('\n' + rst[:-1], at_sender=True)
logger.info(f'USER {event.user_id} GROUP {event.group_id} 查看我的道具')
else:
await my_props.finish('您的背包里没有任何的道具噢~', at_sender=True)

View File

@ -0,0 +1,41 @@
from util.utils import scheduler
from models.bag_user import UserBag
from services.log import logger
# 重置每日金币
@scheduler.scheduled_job(
'cron',
# year=None,
# month=None,
# day=None,
# week=None,
# day_of_week="mon,tue,wed,thu,fri",
hour=0,
minute=1,
# second=None,
# start_date=None,
# end_date=None,
# timezone=None,
)
async def _():
try:
user_list = await UserBag.get_user_all()
if user_list:
for user in user_list:
await user.update(
get_today_gold=0,
spend_today_gold=0,
).apply()
except Exception as e:
logger.error(f'重置每日金币错误 e:{e}')

41
plugins/shop/shop_help.py Normal file
View File

@ -0,0 +1,41 @@
from nonebot import on_command
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from util.img_utils import CreateImg
from configs.path_config import IMAGE_PATH
from util.init_result import image
__plugin_name__ = '商店'
shop_help = on_command("商店", priority=5, block=True)
goods = [
'好感双倍加持卡Ⅰ\t\t售价30金币\n\t\t下次签到双倍好感度的概率 + 10%(谁才是真命天子?)(同类商品将覆盖)',
'好感双倍加持卡Ⅱ\t\t售价150金币\n\t\t下次签到双倍好感度的概率 + 20%(平平庸庸~)(同类商品将覆盖)',
'好感双倍加持卡Ⅲ\t\t售价250金币\n\t\t下次签到双倍好感度的概率 + 30%(金币才是真命天子!)(同类商品将覆盖)'
]
result = ''
for i in range(len(goods)):
result += f'{i + 1}.{goods[i]}\n'
shop = CreateImg(1000, 1000, background=IMAGE_PATH + 'other/shop.png', font_size=20)
shop.text((100, 170), '注【通过 数字 或者 商品名称 购买】')
shop.text((20, 230), result)
shop.text((20, 900), '神秘药水\t\t售价9999999金币\n\t\t鬼知道会有什么效果~')
shop.save(IMAGE_PATH + 'shop.png')
@shop_help.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await shop_help.send(image('shop.png'))

View File

@ -0,0 +1,61 @@
from nonebot import on_command
from services.log import logger
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from nonebot.typing import T_State
from util.utils import is_number, get_message_text
from models.bag_user import UserBag
from nonebot.adapters.cqhttp.permission import GROUP
from services.db_context import db
from .data_source import effect
__plugin_name__ = '使用道具'
__plugin_usage__ = '输入 “使用道具 xxx序号 或 道具名称)“ 即可使用道具\n【注】序号以我的道具序号为准,更推荐使用道具名称使用道具(怕出错)'
use_props = on_command("使用道具", priority=5, block=True, permission=GROUP)
@use_props.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
msg = get_message_text(event.json())
if msg in ['', '帮助']:
await use_props.finish(__plugin_usage__)
props = await UserBag.get_props(event.user_id, event.group_id)
if props:
async with db.transaction():
pname_list = []
props = props[:-1].split(',')
for p in props:
if p != '':
if p not in pname_list:
pname_list.append(p)
if is_number(msg):
if 0 < int(msg) <= len(pname_list):
name = pname_list[int(msg) - 1]
else:
await use_props.finish('仔细看看自己的道具仓库有没有这个道具?', at_sender=True)
else:
if msg not in pname_list:
await use_props.finish('道具名称错误!', at_sender=True)
name = msg
if await UserBag.del_props(event.user_id, event.group_id, name) and\
await effect(event.user_id, event.group_id, name):
await use_props.send(f'使用道具 {name} 成功!', at_sender=True)
logger.info(f'USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 成功')
else:
await use_props.send(f'使用道具 {name} 失败!', at_sender=True)
logger.info(f'USER {event.user_id} GROUP {event.group_id} 使用道具 {name} 失败')
else:
await use_props.send('您的背包里没有任何的道具噢~', at_sender=True)

View File

@ -0,0 +1,40 @@
from models.sigin_group_user import SignGroupUser
async def effect(user_id: int, group_id: int, name: str) -> bool:
print(name)
# try:
if name == '好感双倍加持卡Ⅰ':
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(
add_probability=0.1
).apply()
if name == '好感双倍加持卡Ⅱ':
user = await SignGroupUser.ensure(user_id, group_id)
await user.update(
add_probability=0.2
).apply()
if name == '好感双倍加持卡Ⅲ':
user = await SignGroupUser.ensure(user_id, group_id)
print(user.user_qq)
await user.update(
add_probability=0.3
).apply()
return True
# except Exception:
# return False