def set_token() -> bool: """设置口袋48的登录token, 返回是否成功""" url = "https://pocketapi.48.cn/user/api/v1/login/app/mobile" data = { "mobile": setting.read_config('pocket48', 'username'), "pwd": setting.read_config('pocket48', 'password') } response = send_request(url, data) if response['status'] == 200: token = response['content']['token'] setting.write_config('pocket48', 'token', token) return True else: logger.error('登录口袋48时出错, 返回消息:%s', response['message']) return False
def send_request(url: str, data: dict, has_login: bool = False) -> dict: """向口袋48服务器发送请求 ### Args: ``url``: API地址.\n ``data``: 需要发送的报文.\n ### Return: ``response``: 读取后的JSON数据.\n """ header = { 'Host': 'pocketapi.48.cn', 'accept': '*/*', 'Accept-Language': 'zh-Hans-CN;q=1', 'User-Agent': 'PocketFans201807/6.0.10 (iPhone; iOS 13.3; Scale/2.00)', 'Accept-Encoding': 'gzip, deflate', 'appInfo': ('{"vendor":"apple","deviceId":"0","appVersion":"6.0.10",' '"appBuild":"200120","osVersion":"13.3.1","osType":"ios",' '"deviceName":"iPhone XS Max","os":"ios"}'), 'Content-Type': 'application/json;charset=utf-8', 'Connection': 'keep-alive' } if has_login: header['token'] = setting.read_config('pocket48', 'token') response = requests.post(url, data=json.dumps(data), headers=header, verify=False).json() return response
def pk_init(): """PK项目初始化""" for pk_data in setting.pk_datas(): if pk_data['title'] in pk_mission_started: continue if pk_data['battle_config']['type'] == 'increase': if time.mktime( time.strptime(pk_data['start_time'], '%Y-%m-%d %H:%M:%S')) > time.time(): # 如果还没开始, 先保存零状态 fund.pk.cache_pk_amount(pk_data) # 获取增量的时间节点 time_list = pk_data['battle_config']['time_spot'] for time_spot in time_list: sched.add_job(fund.pk.cache_pk_amount, 'date', run_date=time_spot, args=[pk_data]) pk_interval = int(setting.read_config('pk', 'interval')) logger.info('对%s项目的PK播报将于%s启动,每%d秒钟一次', pk_data['title'], pk_data['start_time'], pk_interval) sched.add_job(send_pk_message, 'interval', seconds=pk_interval, start_date=pk_data['start_time'], end_date=pk_data['end_time'], args=[pk_data]) pk_mission_started.append(pk_data['title'])
def init_vars(self, ai: bool = False): # 读取设置 (self.bird_color, self.background_index, self.volume, self.sound_volume) = setting.read_config() # 设置音量 pygame.mixer.music.set_volume(self.volume * 0.4 / 100) for i in self.sound.keys(): self.sound[i].set_volume(self.sound_volume * self.sound_default[i] / 100) # 游戏分数 self.score = 0 # 背景 if self.background_index == 2: pipe.PIPE_INDEX = random.choice([0, 1]) elif self.background_index in [0, 1]: pipe.PIPE_INDEX = self.background_index self.background = self.background_list[pipe.PIPE_INDEX] # 是否开挂 self.ai = ai # 游戏开始画面 self.start = True # 排行榜画面 self.ranking = False self.value = None # 设置画面 self.setting = False self.mouse_down = False self.R1_set = setting.Setting_line(self.screen, rect=(64, 199), lenth=40, point=0.5, color=(255, 0, 0), height=3) self.G1_set = setting.Setting_line(self.screen, rect=(125, 199), lenth=40, point=0.5, color=(0, 255, 0), height=3) self.B1_set = setting.Setting_line(self.screen, rect=(189, 199), lenth=40, point=0.5, color=(0, 0, 255), height=3) self.R2_set = setting.Setting_line(self.screen, rect=(64, 249), lenth=40, point=0.5, color=(255, 0, 0), height=3) self.G2_set = setting.Setting_line(self.screen, rect=(125, 249), lenth=40, point=0.5, color=(0, 255, 0), height=3) self.B2_set = setting.Setting_line(self.screen, rect=(189, 249), lenth=40, point=0.5, color=(0, 0, 255), height=3) self.volume_set = setting.Setting_line(self.screen, rect=(105, 358), lenth=110, point=self.volume / 100, color=(230, 100, 0)) self.sound_set = setting.Setting_line(self.screen, rect=(105, 408), lenth=110, point=self.sound_volume / 100, color=(230, 100, 0)) # 游戏画面 self.bird = bird.Bird(self.bg_size, self.land.rect.top, self.bird_color, ai=ai) self.delay = 0 self.paused = False self.pressed = False self.upperpipes = [] self.lowerpipes = [] self.pipe_group = pygame.sprite.Group() if not ai: upipe, dpipe = pipe.get_pipe(self.bg_size, self.land.rect.top, self.width + 200) else: upipe, dpipe = pipe.get_pipe(self.bg_size, self.land.rect.top, self.width) self.upperpipes.append(upipe) self.lowerpipes.append(dpipe) self.pipe_group.add(upipe, dpipe) if not ai: upipe, dpipe = pipe.get_pipe(self.bg_size, self.land.rect.top, 1.5 * self.width + 200) else: upipe, dpipe = pipe.get_pipe(self.bg_size, self.land.rect.top, 1.5 * self.width) self.upperpipes.append(upipe) self.lowerpipes.append(dpipe) self.pipe_group.add(upipe, dpipe) # 游戏结束画面 self.recorded = False # 分享画面 self.share = False
def _deal_messages(owner_id: int, room_id: int) -> list: """返回口袋48主页面的信息 ### Result: ``message_list``: 格式化的口袋消息列表. """ # 发送请求获取消息列表 url = "https://pocketapi.48.cn/im/api/v1/chatroom/msg/list/homeowner" data = {'ownerId': owner_id, 'roomId': room_id} response = send_request(url, data, True) if response['status'] >= 401000: if not set_token(): logger.error('口袋48授权失败, 请检查用户名和密码') return dict() response = send_request(url, data, True) # 处理消息列表 message_list = list() last_time = int(setting.read_config('pocket48', 'message_time')) for data in response['content']['message']: message = '' if data['msgTime'] < last_time: break message_time = time.strftime( '%Y-%m-%d %H:%M:%S', time.localtime(int(data['msgTime'] / 1000))) message_ext = json.loads(data['extInfo']) if data['msgType'] == 'TEXT': # 口袋48好像会出现换行直接打到行首的特殊情况 if 'text' in message_ext: message_ext['text'] = message_ext['text'].replace('\r', '\n') if message_ext['messageType'] == 'TEXT': message = (f'{message_ext["user"]["nickName"]}: ' f'{message_ext["text"]}\n' f'{message_time}') logger.info('收到一条文字消息: %s', message_ext["text"]) elif message_ext['messageType'] == 'REPLY': message = (f'{message_ext["replyName"]}: ' f'{message_ext["replyText"]}\n' f'{message_ext["user"]["nickName"]}: ' f'{message_ext["text"]}\n' f'{message_time}') logger.info('收到一条回复消息: %s, 原文: %s', message_ext["text"], message_ext["replyText"]) elif message_ext['messageType'] == 'VOTE': message = (f'{message_ext["user"]["nickName"]}发起了投票: ' f'{message_ext["text"]}\n' f'{message_time}') logger.info('收到一条投票消息: %s', message_ext["text"]) elif message_ext['messageType'] == 'FLIPCARD': message = (f'{message_ext["user"]["nickName"]}: ' f'{message_ext["text"]}\n' f'问题内容: {message_ext["question"]}\n' f'{message_time}') logger.info('收到一条翻牌消息: %s, 问题: %s', message_ext["text"], message_ext["question"]) elif message_ext['messageType'] == 'LIVEPUSH': idol_nickname = setting.read_config("system", "nickname") # playStreamPath = response['content']['playStreamPath'] message = [ { 'type': 'text', 'data': { 'text': (f'{idol_nickname}开直播啦: ' f'{message_ext["liveTitle"]}\n' '封面: ') } }, { 'type': 'image', 'data': { 'file': f'{message_ext["liveCover"]}' } }, { 'type': 'text', 'data': { 'text': '快去口袋48观看吧! ' } }, ] logger.info('收到一条直播消息,id=%s', str(message_ext["liveId"])) elif data['msgType'] == 'IMAGE': bodys = json.loads(data['bodys']) message = [ { 'type': 'text', 'data': { 'text': f'{message_ext["user"]["nickName"]}: ' } }, { 'type': 'image', 'data': { 'file': f'{bodys["url"]}' } }, { 'type': 'text', 'data': { 'text': f'{message_time}' } }, ] elif data['msgType'] == 'AUDIO' or data['msgType'] == 'VIDEO': bodys = json.loads(data['bodys']) message = [ { 'type': 'text', 'data': { 'text': f'{message_ext["user"]["nickName"]}: ' } }, { 'type': 'record', 'data': { 'file': f'{bodys["url"]}' } }, { 'type': 'text', 'data': { 'text': f'{message_time}' } }, ] elif data['msgType'] == 'EXPRESS': message = (f'{message_ext["user"]["nickName"]}: 发送了表情\n' f'{message_time}') else: logger.error('发现了未知格式的信息: %s', json.dumps(message_ext)) message_list.append(message) logger.info('口袋48信息处理完成, 共收取到%d条信息', len(message_list)) setting.write_config('pocket48', 'message_time', str(int(time.time() * 1000))) return message_list
def get_messages() -> list: owner_id = int(setting.read_config('pocket48', 'ownerid')) room_id = int(setting.read_config('pocket48', 'roomid')) return _deal_messages(owner_id, room_id)
def get_message() -> list: """获取最新的微博内容""" container_id = f'107603{setting.read_config("weibo","id")}' url = ('https://m.weibo.cn/api/container/getIndex?' f'containerid={container_id}') header = { 'User-Agent': ('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) ' 'AppleWebKit/605.1.15 (KHTML, like Gecko) ' 'Version/13.0.5 Safari/605.1.15') } response = requests.get(url, headers=header).json() message_list = list() max_id = int(setting.read_config("weibo", "last_weibo")) for card in response['data']['cards']: try: card_id = int(card['mblog']['id']) except KeyError: card_id = 0 continue if card_id <= int(setting.read_config("weibo", "last_weibo")): continue elif card_id > max_id: max_id = card_id text = re.compile(r'<[^>]+>', re.S).sub('', card['mblog']['text']) logger.info("发现一条新微博, ID:%d", card_id) # 首先查看是否转发 if card['mblog'].get('retweeted_status') is None: # 原创微博 start_text = (f'{setting.read_config("system", "nickname")}' f"刚刚发了一条微博: {text}\n") message = [ { 'type': 'text', 'data': { 'text': start_text } }, ] if card['mblog'].get('pics'): message.append({ 'type': 'image', 'data': { 'file': card['mblog']['pics'][0]['url'] } }) message.append({ 'type': 'text', 'data': { 'text': f"一共有{len(card['mblog']['pics'])}张图哦\n" } }) message.append({ 'type': 'text', 'data': { 'text': f"传送门: {card['scheme']}" } }) else: raw_text = re.compile(r'<[^>]+>', re.S)\ .sub('', card['mblog']['retweeted_status']['text']) message = (f'{setting.read_config("system", "nickname")}' f"刚刚转发了一条微博: {text}\n原微博: {raw_text}" f"传送门: {card['scheme']}") message_list.append(message) setting.write_config("weibo", "last_weibo", str(max_id)) return message_list
import os from sqlalchemy import create_engine from fund.module import Base import pocket48 import setting # 初始化数据库 print("建立数据库表格...") engine = create_engine(setting.db_link()) Base.metadata.create_all(engine) print("完成!") # 建立PK配置和缓存的文件夹 print("建立PK配置文件和缓存文件...") if not os.path.exists(setting.read_config('pk', 'cache_folder')): os.makedirs(setting.read_config('pk', 'cache_folder')) if not os.path.exists(setting.read_config('pk', 'config_folder')): os.makedirs(setting.read_config('pk', 'config_folder')) # 口袋48初始化 print("初始化口袋48设置") pocket48.find_room(setting.read_config('system', 'idolname'))
def handle_msg(context): """关键字响应\n 目前设定了PK, 集资, 补档, 以及关键字撤回和重复刷屏禁言. """ if (context['user_id'] != context['self_id'] and context['message_type'] == 'group'): check_group_list = setting.group_id() + setting.dev_group_id() for pk_data in setting.pk_datas(): if time.mktime( time.strptime(pk_data['end_time'], '%Y-%m-%d %H:%M:%S')) < time.time(): continue if (context['group_id'] in pk_data['extend_qq_groups'] or context['group_id'] in check_group_list): if (context['message'] in ['PK', 'pk', 'Pk'] or context['message'] in pk_data['key_word']): message = fund.pk.get_pk_message(pk_data) bot.send(context, message) if (context['group_id'] in setting.group_id() or context['group_id'] in setting.dev_group_id()): if context['message'] == '集资': session = sessionmaker(bind=engine)() message = '' project_list = fund.get_started_project(session) if project_list.count() > 0: for project in project_list: message += f'{project.title}(准备中):{project.link()}\n' project_list = fund.get_prepared_project(session) if project_list.count() > 0: for project in project_list: message += f'{project.title}(准备中):{project.link()}\n' if message == '': message = '暂时没有集资项目' session.close() bot.send(context, message.rstrip('\n')) if context['message'] == '补档': intro_pos = setting.read_config('system', 'intro') f = open(intro_pos, 'r', -1, 'utf-8') ori_message = f.read() message_list = ori_message.split('$') for message in message_list: bot.send(context, message) # 敏感词撤回与重复刷屏禁言 if context['group_id'] in setting.group_id(): for word in setting.shutword(): if word in context['message']: bot.delete_msg(message_id=context['message_id']) logger.info('成员%s的消息%s因为含有敏感词%s被撤回', context['user_id'], context['message'], word) prev_message = repeat_message[context['group_id']]['message'] prev_user = repeat_message[context['group_id']]['user_id'] if (context['message'] == prev_message and context['user_id'] == prev_user): repeat_message[context['group_id']]['time'] += 1 logger.debug('成员%s重复发言第%d次', context['user_id'], repeat_message[context['group_id']]['time']) else: repeat_message[context['group_id']]['time'] = 0 repeat_message[context['group_id']]['message'] = context['message'] repeat_message[context['group_id']]['user_id'] = context['user_id'] if repeat_message[context['group_id']]['time'] >= 4: bot.set_group_ban(group_id=context['group_id'], user_id=context['user_id'], duration=60 * 60) logger.info('成员%s因为重复发言刷屏被禁言一小时', context['user_id'])
'type': 'text', 'data': { 'text': f'加入本群\n{setting.welcome()}' } }] bot.send(context, message=welcome, auto_escape=True) # TODO:加群验证处理 # TODO:好友验证处理 # TODO:卡牌查询处理 if __name__ == '__main__': # 配置日志记录器 logger.setLevel(logging.DEBUG) fhandler = logging.FileHandler(setting.read_config('system', 'log')) fhandler.setLevel(logging.DEBUG) fhandler.setFormatter( logging.Formatter(("%(asctime)s - %(name)s - " "%(levelname)s - %(module)s - %(message)s"))) logging.root.addHandler(fhandler) shandler = logging.StreamHandler() shandler.setLevel(logging.INFO) shandler.setFormatter( logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) logging.root.addHandler(shandler) # 集资信息播报 raise_interval = int(setting.read_config('fund', 'interval')) if raise_interval: send_raise_message(True)