def __init__(self): self._data = PluginData('ff14', config=True) # 新闻数据的地址 self._url = 'http://api.act.sdo.com/UnionNews/List?gameCode=ff&category=5309,5310,5311,5312,5313&pageIndex=0&pageSize=5' # 定时任务 self._job = None # 根据配置启动 if bool(int(self._data.get_config('ff14', 'push_news', '0'))): self.enable()
def __init__(self): self._data = PluginData('ff14', config=True) # 定时任务 self._job = None # 当前状态 self._status = None # 根据配置启动 if bool( int(self._data.get_config('ff14', 'monitor_server_status', '0')) ): self.enable()
subprocess.run(f'cd "{YOBOT_DIR}" && git checkout . && git pull', shell=True, check=True) return '升级成功,请重新启动' if not YOBOT_DIR.exists(): download_yobot() # 配置 Yobot configure_yobot() from .yobot.src.client.yobot import Yobot DATA = PluginData('pcr') verinfo = { "run-as": "nonebot-plugin", "ver_name": "yobot{}".format(Yobot.Version), } cqbot = get_bot() bot = Yobot( data_path=str(DATA._base_path), verinfo=verinfo, scheduler=scheduler, quart_app=cqbot.server_app, bot_api=cqbot._api, )
""" 每日早安插件 """ import re from random import randint import requests from nonebot import CommandSession, on_command from coolqbot import PluginData, bot DATA = PluginData('morning', config=True) HOUR = int(DATA.config_get('morning', 'hour', fallback='7')) MINUTE = int(DATA.config_get('morning', 'minute', fallback='30')) SECOND = int(DATA.config_get('morning', 'second', fallback='0')) @bot.scheduler.scheduled_job('cron', hour=HOUR, minute=MINUTE, second=SECOND, id='morning') async def morning(): """ 早安 """ hello_str = get_message() await bot.get_bot().send_msg(message_type='group', group_id=bot.get_bot().config.GROUP_ID, message=hello_str) bot.logger.info('发送早安信息')
""" 记录数据 """ from datetime import datetime, timedelta from coolqbot import PluginData, bot def get_history_pkl_name(dt): time_str = dt.strftime('%Y-%m') return time_str DATA = PluginData('recorder') class Recorder: def __init__(self, data=None): self._name = 'recorder' # 运行数据 self.last_message_on = datetime.now() self._msg_send_time = [] self._repeat_list = {} self._msg_number_list = {} # 酷Q 状态 self.start_time = datetime.now() self.coolq_status = False # 是否需要发送问好 self.send_hello = False
""" 图灵机器人 http://www.turingapi.com/ """ import json from typing import Optional import httpx from nonebot import CommandSession from nonebot.helpers import context_id from coolqbot import PluginData DATA = PluginData('robot', config=True) TULING_API_KEY = DATA.get_config('tuling', 'api_key') async def call_tuling_api(session: CommandSession, text: str) -> Optional[str]: """ 调用图灵机器人的 API 获取回复 """ if not TULING_API_KEY: return None if not text: return None url = 'http://openapi.tuling123.com/openapi/api/v2' # 构造请求数据 payload = { 'reqType': 0,
""" import hashlib import json import random import string import time from typing import Optional from urllib import parse import aiohttp from nonebot import CommandSession from nonebot.helpers import context_id from coolqbot import PluginData DATA = PluginData('robot', config=True) TENCENT_AI_APP_ID = DATA.config_get('tencent', 'app_id') TENCENT_AI_APP_KEY = DATA.config_get('tencent', 'app_key') async def call_tencent_api(session: CommandSession, text: str) -> Optional[str]: """ 调用腾讯机器人的 API 获取回复 """ if not TENCENT_AI_APP_KEY: return None if not text: return None url = 'https://api.ai.qq.com/fcgi-bin/nlp/nlp_textchat'
""" from nonebot import CommandGroup from coolqbot import PluginData __plugin_name__ = 'repeat' __plugin_usage__ = r""" 人类本质 用来模仿人类,同时提供排行榜,历史记录和记录复读状态功能。 例如: -------排行榜--------- /rank /rank 30n0 -------历史记录------- /history /history 2020-01 /history 2020-01-01 -------状态----------- /status 命令均需要在群里使用。 """.strip() cg = CommandGroup('repeat') DATA = PluginData('repeat', config=True) from . import commands, nlp
class ServerMonitor: """ 服务器状态监控 """ def __init__(self): self._data = PluginData('ff14', config=True) # 定时任务 self._job = None # 当前状态 self._status = None # 根据配置启动 if bool( int(self._data.get_config('ff14', 'monitor_server_status', '0')) ): self.enable() def enable(self): self._job = scheduler.add_job( self.monitor_server_status, 'interval', seconds=self.interval ) self._data.set_config('ff14', 'monitor_server_status', '1') def disable(self): self._job.remove() self._data.set_config('ff14', 'monitor_server_status', '0') @property def is_enabled(self): """ 是否启用服务器状态监控 """ if self._job: return True else: return False @property def status(self): """ 服务器状态 返回格式化字符串 """ status = self._status if status: resp = f'当前的服务器状态({status["time"].strftime("%Y-%m-%d %H:%M:%S")})' for name, is_open in status['data'].items(): resp += f'\n{name}:{"在线" if is_open else "离线"}' return resp else: return '无数据' @property def interval(self): return int( self._data.get_config('ff14', 'monitor_server_interval', '60') ) @staticmethod async def is_open(ip, port): """ 查询端口是否开启 """ conn = asyncio.open_connection(ip, port) try: _reader, writer = await asyncio.wait_for(conn, timeout=1) writer.close() await writer.wait_closed() return True except asyncio.TimeoutError: return False async def monitor_server_status(self): """ 监控服务器状态 """ group_id = get_bot().config.GROUP_ID[0] if not self._status: self._status = await self.get_server_status() else: current_status = await self.get_server_status() if self._status['data'] == current_status['data']: pass else: await get_bot().send_msg( message_type='group', group_id=group_id, message=self.status ) self._status = current_status async def get_server_status(self): """ 获取服务器状态 """ # data = { # '陆行鸟': await self.is_open('109.244.5.5', 54994), # '莫古力': await self.is_open('109.244.5.162', 54994), # '猫小胖': await self.is_open('116.211.8.5', 54994), # } data = { '猫小胖': await self.is_open('116.211.8.5', 54994), '静语庄园': await self.is_open('116.211.8.46', 55022), } return {'time': datetime.now(), 'data': data}
class News: def __init__(self): self._data = PluginData('ff14', config=True) # 新闻数据的地址 self._url = 'http://api.act.sdo.com/UnionNews/List?gameCode=ff&category=5309,5310,5311,5312,5313&pageIndex=0&pageSize=5' # 定时任务 self._job = None # 根据配置启动 if bool(int(self._data.get_config('ff14', 'push_news', '0'))): self.enable() def enable(self): """ 开启新闻自动推送 """ logger.info('初始化 最终幻想XIV 新闻推送') # 开启后先运行一次 scheduler.add_job(self.push_news, 'date', run_date=(datetime.now() + timedelta(seconds=30))) self._job = scheduler.add_job(self.push_news, 'interval', minutes=self.interval) self._data.set_config('ff14', 'push_news', '1') def disable(self): """ 关闭新闻自动推送 """ self._job.remove() self._data.set_config('ff14', 'push_news', '0') @property def is_enabled(self): """ 是否启用新闻自动推送 """ if self._job: return True else: return False @property def interval(self): """ 自动推送新闻的间隔,单位 分钟 """ return int(self._data.get_config('ff14', 'push_news_interval', '30')) @property def last_news_id(self) -> int: """ 上次推送新闻的发布 ID """ return int(self._data.get_config('ff14', 'push_news_last_news_id', '0')) @last_news_id.setter def last_news_id(self, news_id: int): self._data.set_config('ff14', 'push_news_last_news_id', str(news_id)) async def get_news(self): """ 获取最新的新闻 """ try: async with httpx.AsyncClient() as client: r = await client.get(self._url) if r.status_code != 200: # 如果 HTTP 响应状态码不是 200,说明调用失败 return None return r.json() except (httpx.HTTPError, KeyError) as e: logger.error(f'获取新闻出错,{e}') # 抛出上面任何异常,说明调用失败 return None def format_message(self, item): """ 格式化消息 """ message = '' message += f'{item["Title"]}\n' message += f'{item["Author"]}\n' message += f'{item["Summary"]}' return message async def push_news(self): """ 推送消息 """ logger.info('开始检查 最终幻想XIV 新闻') news_list = [] news = await self.get_news() if news is None: logger.error('最终幻想XIV 新闻获取失败') return if not self.last_news_id: # 如果初次运行,则记录并发送第一条新闻 self.last_news_id = news['Data'][0]['Id'] news_list.append(news['Data'][0]) for item in news['Data']: if item['Id'] <= self.last_news_id: break news_list.append(item) if news_list: # 添加最新的那一条新闻的 ID self.last_news_id = news_list[0]['Id'] group_id = get_bot().config.GROUP_ID[0] for item in news_list: await get_bot().send_msg(message_type='group', group_id=group_id, message=self.format_message(item))
""" 一些数据 副本与职业数据 """ from dataclasses import dataclass from typing import Dict, List, Optional from coolqbot import PluginData DATA = PluginData('fflogs', config=True) # (zone, encounter, difficulty): [nicknames] boss_list = { (28, 1045, 100): ['提坦妮雅歼殛战', '缇坦妮雅', '妖精', '极妖精', '妖灵王', '妖精王', '老婆', '10王'], (28, 1046, 100): ['无瑕灵君歼殛战', '无瑕灵君', '肥宅', '极肥宅', '全能王'], (28, 1049, 100): ['哈迪斯歼殛战', '哈迪斯', '老公'], (29, 65, 100): ['伊甸希望乐园 觉醒之章1', 'E1', 'e1'], (29, 66, 100): ['伊甸希望乐园 觉醒之章2', 'E2', 'e2'], (29, 67, 100): ['伊甸希望乐园 觉醒之章3', 'E3', 'e3'], (29, 68, 100): ['伊甸希望乐园 觉醒之章4', 'E4', 'e4'], (29, 65, 0): ['伊甸零式希望乐园 觉醒之章1', 'E1S', 'e1s', 'E1s', 'e1S'], (29, 66, 0): ['伊甸零式希望乐园 觉醒之章2', 'E2S', 'e2s', 'E2s', 'e2S'], (29, 67, 0): ['伊甸零式希望乐园 觉醒之章3', 'E3S', 'e3s', 'E3s', 'e3S'], (29, 68, 0): ['伊甸零式希望乐园 觉醒之章4', 'E4S', 'e4s', 'E4s', 'e4S'], } # yapf: disable # spec: [nicknames] job_list = { 1: ['占星术士', '占星'], 2: ['吟游诗人', '诗人'], 3: ['黑魔法师', '黑魔', '伏地魔', '永动机'],
""" 历史记录插件 """ import re from calendar import monthrange from datetime import datetime, timedelta from dateutil.relativedelta import relativedelta from nonebot import CommandSession, on_command, permission from coolqbot import PluginData, bot from .rank import Ranking from .recorder import Recorder, get_history_pkl_name, recorder DATA = PluginData('history') @bot.scheduler.scheduled_job('cron', day=1, hour=0, minute=0, second=0, id='clear_data') async def clear_data(): """ 每个月最后一天 24 点(下月 0 点)保存记录于历史记录文件夹,并重置记录 """ # 保存数据到历史文件夹 date = datetime.now() - timedelta(hours=1) DATA.save_pkl(recorder.get_data(), get_history_pkl_name(date)) # 清除现有数据 recorder.init_data()
""" 和风天气 """ import json import re import urllib import requests from coolqbot import PluginData DATA = PluginData('weather', config=True) KEY = DATA.config_get('heweather', 'key') def heweather(city): """ 和风天气 API 日本 东京 当前温度:25(体感温度:29) 2018-08-13 中雨 降水概率:0% 温度:32~26℃ 2018-08-14 小雨 降水概率:13% 温度:33~26℃ 2018-08-15 小雨 降水概率:11% 温度:32~25℃ """ if not KEY: return None try: city_name = urllib.parse.quote(city.encode('utf-8')) url_str = f'https://free-api.heweather.com/s6/weather?location={city_name}&key={KEY}' response = requests.get(url_str) data = response.content.decode('utf-8')
""" 复读插件 """ import re import secrets from datetime import datetime, timedelta from nonebot import (CommandSession, IntentCommand, NLPSession, on_command, on_natural_language, on_notice, permission) from coolqbot import PluginData, bot from .recorder import recorder DATA = PluginData('repeat', config=True) # 复读概率 REPEAT_RATE = int(DATA.config_get('bot', 'repeat_rate', fallback='10')) # 复读间隔 REPEAT_INTERVAL = int(DATA.config_get('bot', 'repeat_interval', fallback='1')) def is_repeat(session: CommandSession, message): group_id = session.ctx['group_id'] user_id = session.ctx['sender']['user_id'] # 只复读指定群内消息 if group_id not in session.bot.config.GROUP_ID: return False # 不要复读指令 match = re.match(r'^\/', message) if match: return False
""" 和风天气 """ import re import urllib import httpx from coolqbot import PluginData DATA = PluginData('weather', config=True) KEY = DATA.get_config('heweather', 'key') async def heweather(city): """ 和风天气 API 日本 东京 当前温度:25(体感温度:29) 2018-08-13 中雨 降水概率:0% 温度:32~26℃ 2018-08-14 小雨 降水概率:13% 温度:33~26℃ 2018-08-15 小雨 降水概率:11% 温度:32~25℃ """ if not KEY: return None try: city_name = urllib.parse.quote(city.encode('utf-8')) url_str = f'https://free-api.heweather.com/s6/weather?location={city_name}&key={KEY}' async with httpx.AsyncClient() as client: resp = await client.get(url_str) weather_result = resp.json()['HeWeather6'][0]