def test_database_01(): project_id = '224472' db = Database() try: url = db.get_project_url(project_id) logger.info('The url for project {} was {}'.format(project_id, url)) except ProjectNotFoundException: logger.error('The project {} was not in database.'.format(project_id)) pass
async def three_clock(): logger.info('Time to drink tea!!') for strid, bot in get_bots().items(): groups: list = await bot.get_group_list() gids = [ g['group_id'] for g in groups if Enable_Group(g['group_id']).check_enable() and Group_Blocker(g['group_id']).check_block() # 未阻塞 and plugin_name not in group_func_off[str(g['group_id'])] ] # 未关闭功能 shuffle(gids) logger.info(f'Will Send {len(gids)} group(s): {str(gids)}') try: for g in gids: for msg in TEATIME_NOTICE: await bot.send_group_msg(group_id=g, message=msg) await asyncio.sleep(1.5) # 防止消息发送间隔过短导致顺序错乱 await bot.send_group_msg(group_id=g, message=choice(TEATIME_ATTACH)) asyncio.sleep(15) # 结束上一个群的发送开始发送下一个群的间隔 except ActionFailed as err: logger.error( f'Maybe too intensive to send msg, cause error: {err}') # 由用户自定义提醒功能时会需要这个添加、删除定时器的方式 # def sv_teatime(bot: Bot, event: GroupMessageEvent, state): # logger.debug(f'Got command {event.get_message().extract_plain_text().strip()}') # if event.get_message().extract_plain_text().strip() == plugin_name and\ # isinstance(event, GroupMessageEvent) and event.sender.role in ('owner', 'admin'): # return True # teatime_switch = MatcherGroup(type='message') # teatime_on = teatime_switch.on_command('开启', rule=comman_rule(GroupMessageEvent)) # teatime_off = teatime_switch.on_command('关闭', rule=comman_rule(GroupMessageEvent)) # @teatime_on.handle() # async def turn_tt_on(bot: Bot, event: GroupMessageEvent): # scheduler.add_job(test, 'cron', second='*/30', id='3clock', jitter=10) # logger.info(f'{event.group_id} turn the job 3clock On !') # @teatime_off.handle() # async def turn_tt_off(bot: Bot, event: GroupMessageEvent): # scheduler.remove_job('3clock') # logger.info(f'{event.group_id} turn the job 3clock Off !') # tsttea = teatime_switch.on_command('饮茶') # @tsttea.handle() # async def tsteee(bot): # msg = choice(TEATIME_ATTACH) # logger.debug(str(msg)) # await tsttea.finish(msg)
def increase_setu(pid: int, p: int, uid: int, title: str, author: str, url: str, r18: Union[bool, Literal[0, 1]], tags: List[str]): """插入一条lolicon的图片信息""" with GalleryDB() as glrdb: qcmd = 'SELECT 1 FROM lolicon WHERE pid=%s AND p=%s LIMIT 1;' qparams = (pid, p) if glrdb.queryone(qcmd, qparams): logger.warning(f"Record [{str(pid) + '_p' + str(p)}] has exists") else: cmd = "INSERT INTO lolicon (pid, p, uid, title, author, url, r18, tags) VALUES (%s, %s, %s, %s, %s, %s, %s, %s);" params = (pid, p, uid, title, author, url, r18, ','.join(tags)) glrdb.insert(cmd, params) logger.info(f"Insert one record into lolicon: {str(pid) + '_p' + str(p)}")
def turn_on(self) -> bool: ''' 当reason为3时可调用此解禁方式,解禁同时返回true 当reason不为3时不予解禁并且返回false ''' if self.__class__.block_list[self.id]['reason'] == 3: self.rm_block() logger.info(f'Remove group {self.id} from block list') return True else: logger.info( f'Failed to unblock group {self.id} , reason: {self.__class__.block_list[self.id]["reason"]}' ) return False
def GetLoginUserId(user: str) -> (int, str): """ 根据用户ID查看用户是否存在,并返回用户唯一标识ID :param user: 用户姓名 :return: Success:返回用户的唯一标识ID Failed: -1 """ if not isinstance(user, str) or user == None or user == "": return -1, "USER Argument is invalid" # Query user in Mysql valid dbresult = Mysql.MysqlHelper().query(sql.SQL_QUERY_ID_EXISTS, [user]) if dbresult['status'] == Config.QUERY_FALED or dbresult['result'] is None: logger.info("query {u} ID in Mysql failed".format(u=user)) return -1, "Query {u} ID in mysql failed".format(u=user) return dbresult['result'][0][0], "SUCCESS"
async def virify_request(bot: Bot, event: FriendRequestEvent): pure_comment = event.comment.split('\n回答:')[1] if pure_comment == get_hash_code( FRIENDREQUESTCODESALT, event.get_user_id()) and UserLevel(event.user_id).level > 3: # await event.approve() 为啥这个不好使??? await bot.set_friend_add_request(flag=event.flag, approve=True) logger.success(f'Approved friend request with user: {event.user_id}') for sps in SUPERUSERS: await bot.send_private_msg( user_id=sps, message=f'用户 {event.user_id} 通过了好友验证,已添加好友') else: logger.info( f'Wrong request-code, refuse to add friend with: {event.user_id}') await bot.set_friend_add_request(flag=event.flag, approve=False)
def renewal(self, term: int): """续期许可证,如果还未开通则会运行授权函数 Args: term (int): 续期天数 """ if self.gid not in self.__class__.enable_groups: logger.warning( f'Group {self.gid} never approved, will run aprroving program') self.approve(term) else: self.__class__.enable_groups[self.gid]['lease_term'] += term with enable_groups_file.open('w', encoding='utf-8') as j: json.dump(self.__class__.enable_groups, j, indent=4) logger.info(f'Renew group {self.gid} with {term} days')
def setX(key, val, expire_time=3600 * 24) -> dict: try: redis_cli = get_redis() if redis_cli.set(key, val): redis_cli.expire(key, expire_time) logger.info("set {key} expiretime:{expire}".format( key=key, expire=datetime.datetime.fromtimestamp( int(time.time()) + expire_time))) return DBResult.format(TSZ_MODEL_REDIS, EXEC_SUCCESS, None) else: logger.info("set {key} into redis failed".format(key=key)) return DBResult.format(TSZ_MODEL_REDIS, EXEC_FAILED, None) pass except Exception as e: errmsg = "Catch Execption in Redis setX({key},{val}). ErrMsg:{msg}".format( key=key, val=val, msg=e) logger.warning(errmsg) return DBResult.format(TSZ_MODEL_REDIS, EXEC_FAILED, errmsg)
def approve(self, term: int): """授权群使用本bot Args: term (int): 授权天数 Returns: bool: 授权是否成功,如果已经在授权名单中则返回False """ if self.gid in self.__class__.enable_groups: logger.warning(f'Group {self.gid} has approved') return False else: data = { 'authorize_time': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 'lease_term': term } self.__class__.enable_groups[self.gid] = data with enable_groups_file.open('w', encoding='utf-8') as j: json.dump(self.__class__.enable_groups, j, indent=4) logger.info(f'Approve group {self.gid} with {term} days') return True
def post(self)->dict: data = self.parser.parse_args() s_token = data.get('s_token', '') s_user = data.get('s_user','') if not s_token or not s_user: return CommResult.HttpResult.invalid_args() s_tel = data.get('s_tel','') s_sex = data.get('s_sex', '') try: s_sex = Config.Genders[int(s_sex)] except ValueError: s_sex = Config.Genders[2] if not CommonCheck.CheckTelValid(s_tel): return CommResult.HttpResult.invalid_args() s_nichen = data.get('s_nichen', '') s_uni = data.get('s_uni', '') s_desc = data.get('s_desc','') s_age = data.get('s_age','') s_addr = data.get('s_addr','') # check the user is login or not check_ok, message = CommonCheck.CheckLoginStatus(s_token, s_user) if not check_ok: return CommResult.HttpResult.user_not_login() # get user_id s_user_id = CommonCheck.GetLoginUserId(s_user) dbresult = Mysql.MysqlHelper().insert(sql.SQL_INSERT_TSZ_USER,[ s_user_id, s_user, s_nichen, s_uni, s_desc, s_addr, 0, '', s_tel, s_sex, s_age ]) if dbresult['status'] == Config.EXEC_SUCCESS: logger.info("insert user.status {u} ok".format(u=s_user)) return CommResult.HttpResult.format(HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_200_OK, "OK") return CommResult.HttpResult.format(HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_300_BAD_RESULT, dbresult['result'])
def get(self): data = self.parser.parse_args() username = data.get('name', None) utype = data.get('type', None) if utype == None or username == None: return CommResult.HttpResult.invalid_args() logger.info("get {u} and type:{t}".format(u=username, t=utype)) identity_code = self.get_random_number() if utype == 1: # Register Identity Code key = 'R' + username result = Redis.setX(key, identity_code, IDentityCode_TimeOut) if result['status'] == Config.EXEC_FAILED: return CommResult.HttpResult.format( HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_500_INTERNAL_ERROR, result['result']) elif utype == 2: # forget password to Idenity Code key = 'F' + username result = Redis.setX(key, identity_code, IDentityCode_TimeOut) if result['status'] == Config.EXEC_FAILED: return CommResult.HttpResult.format( HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_500_INTERNAL_ERROR, result['result']) else: return CommResult.HttpResult.format( HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_403_UNRESOLVED_TYPE, AppStatus.APP_403_MESSAGE) logger.info( "Get Identity code for {u} OK. identity code:{c} timeout:{t}". format(u=username, c=identity_code, t=IDentityCode_TimeOut)) return CommResult.HttpResult.format(HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_200_OK, "Identity Code has been sent.")
def post(self): data = self.parser.parse_args() username = data.get('name', None) passwd = data.get('passwd', None) identifying_code = data.get('identifying_code', None) if username == None or passwd == None or identifying_code == None: return CommResult.HttpResult.invalid_args() # GET IDentity code from redis key = 'R' + username result = Redis.getX(key) if result['status'] == Config.QUERY_SUCCESS: if result['result'] != None and result[ 'result'] == identifying_code: # update the mysql tsz_user_pswd my = Mysql.MysqlHelper() sqlResult = my.query(sql.SQL_QUERY_ID) if sqlResult['status'] == Config.QUERY_SUCCESS: user_id = sqlResult['result'][0][0] + 1 sqlResult = my.insert(sql.SQL_INSERT_VAL, [user_id, username, passwd]) logger.info( 'flush user={u} to mysql {s} errmsg={e}'.format( u=username, s=sqlResult['status'], e=sqlResult['result'])) if sqlResult['status'] == Config.EXEC_SUCCESS: Redis.delX(key) return CommResult.HttpResult.format( HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_200_OK, "Register OK") else: return CommResult.HttpResult.format( HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_500_INTERNAL_ERROR, AppStatus.APP_500_MESSAGE) else: return CommResult.HttpResult.format( HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_500_INTERNAL_ERROR, AppStatus.APP_500_MESSAGE) else: logger.info( 'user={u} with identity_code={i} Register Failed invalid indentity_code' .format(u=username, i=identifying_code)) return CommResult.HttpResult.format( HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_300_BAD_RESULT, "Incrrorect Identity Code") elif result['status'] == Config.QUERY_FALED: logger.info('user={u} identity_code={i} has been expired.'.format( u=username, i=identifying_code)) return CommResult.HttpResult.format( HttpStatus.HTTP_200_OK, HttpStatus.HTTP_200_MESSAGE, AppStatus.APP_301_INVALID_ARGS, "Register Failed due to expired Identity Code.")
def CheckLoginStatus(token: str, user: str) -> (bool, str): """ 检查用户的登录状态 :param token: 用户token :param user: 用户名 :return: 状态:处理结果 """ if not isinstance(token, str) or token == None or token == "": return False, "Argument is invalid" if not isinstance(user, str) or user == None or user == "": return False, "Argument is invalid" # 1.从mysql获取用户唯一ID dbresult = Mysql.MysqlHelper().query(sql.SQL_QUERY_ID_EXISTS, [user]) if dbresult['status'] == Config.QUERY_FALED or not dbresult['result']: logger.info( "{u}'s token is invalid.query in Mysql failed".format(u=user)) return False, "id is invalid. Query Failed" user_id = dbresult['result'][0][0] # 2.从Reids中获取全量token key = 'T' + user + str(user_id) dbresult = Redis.getX(key) if dbresult['status'] == Config.QUERY_FALED or not dbresult['result']: logger.info( "{u}'s token is invalid.query in Redis failed".format(u=user)) return False, "current User not logined." token_in_redis = dbresult['result'] # 3.检验token if token != HashHelper.hash_md5(token_in_redis): logger.info("{u}'s token is invalid.HashChek Failed".format(u=user)) return False, "token hash check failed" # 4.校验用户的token的合法性,一个用户对应一个token message = HashHelper.Token.certify_token(Config.PROJECT_NAME, user, token) if message != "": logger.info("{u}'s token is invalid in verify token,{m}".format( u=user, m=message)) return False, "token is valid. not belong {u}".format(u=user) return True, "SUCCESS"
key=key, msg=e) logger.warning(errmsg) return DBResult.format(TSZ_MODEL_REDIS, QUERY_FALED, errmsg) def delX(key) -> dict: try: redis_cli = get_redis() redis_cli.delete(key) return DBResult.format(TSZ_MODEL_REDIS, EXEC_SUCCESS, None) except Exception as e: errmsg = "Catch Execption in Redis getX({key}). ErrMsg:{msg}".format( key=key, msg=e) logger.warning(errmsg) return DBResult.format(TSZ_MODEL_REDIS, EXEC_FAILED, errmsg) pass if __name__ == '__main__': setX("Redis", "Test", 5) logger.info("get key:{val} currentTime:{t1}".format( val=getX("Redis", 5), t1=datetime.datetime.fromtimestamp(int(time.time())))) time.sleep(3) logger.info("get key:{val} currentTime:{t1}".format( val=getX("Redis", 5), t1=datetime.datetime.fromtimestamp(int(time.time())))) time.sleep(5) logger.info("get key:{val} currentTime:{t1}".format( val=getX("Redis", 5), t1=datetime.datetime.fromtimestamp(int(time.time()))))
def get_setu(gid: int, kwds: Sequence[str], num: int=1, r18: int=0): """从数据库中获得色图数据 Args: gid (int): 呼叫色图的群号,相同群内会有两个小时的记录去重,私聊传入0以不做处理 kwd (tuple): 关键词,元组内的词会做交集查询 num (int, optional): 查询数量. Defaults to 1. r18 (int, optional): 是否包含r18图片,0:没有R18,1:只有R18,2:混合. Defaults to 0. Returns: tuple: 返回是否调用成功以及返回的结果,如果没有查询结果会返回无结果还是结果已经用尽,如果有结果会返回数据列表 数据结构:{ 'count' (int): 返回数量,为了与lolicon结构保持一致, 'data' (list):{ 'title' (str): 作品名, 'author' (str): 作者, 'source' (str): pid_p, 'file' (Path): 文件路径 } } """ if gid: if gid not in Setu_Called_Data: Setu_Called_Data[gid] = Setu_Called(gid) his = Setu_Called_Data[gid] with GalleryDB() as glrdb: # TODO: 优化随机查询的方式取代orded by rand() cmd = 'SELECT pid, p, title, author, url, id FROM lolicon WHERE ' if r18 != 2: cmd += f'r18={r18} AND ' # 过滤已经调用过的图片 if gid and len(his.called) > 1: cmd += f'id NOT IN {tuple(his.called)} AND ' # 添加关键词条件并随机抽取 cmd += ' AND '.join(['(tags LIKE %s OR title LIKE %s OR author LIKE %s)'] * len(kwds)) cmd += ' ORDER BY RAND() LIMIT %s' # 三个一组的关键词参数与一个limit参数 params = concat_seq(*[(k, k, k) for k in map(lambda x: '%' + x + '%', kwds)]) + (num,) logger.debug(f'执行SQL>>{cmd}'%params) # logger.debug(f'执行SQL>>{cmd}') # logger.debug(f'{params=}') results = glrdb.queryall(cmd, params) if not results: if gid and kwds in his.called_kwds: return False, f'暂时没有更多关于"{"|".join(kwds)}"的涩图了' else: return False, f'没有找到关于"{"|".join(kwds)}"的涩图' # TODO: 换了标签之后再搜索到相同的图用这个标签不太合适,换成"有x张相关图刚才已经发过了" setu_ls = [] # 所有色图列表 for record in results: filestem = str(record[0]) + '_p' + str(record[1]) # 名字是pid_p suffix : str = record[4].split('.')[-1] # 后缀从url里解析 filename = filestem + '.' + suffix filepath = Path(SETUPATH)/filename logger.debug(f'定位本地文件{filepath}') if not filepath.exists(): logger.warning(f'Did not found local file [{filename}]') try: r = requests.get(record[4]) filepath.write_bytes(r.content) logger.info(f'Downloaded file [{filename}] into setupath') except Exception as err: logger.exception(f'Failed to download file [{filename}]: {err}') setu_ls.append(None) continue data = { 'title': record[2], 'author': record[3], 'source': filestem, 'file': filepath } setu_ls.append(data) if gid: his.called.add(record[5]) # 添加id记录 if gid: his.called_kwds.add(kwds) # 添加关键词记录 his.check_expired() # 检查记录是否过期 return True, {'count': len(setu_ls), 'data': setu_ls}