def event_add(bot_id, group_id, user_id, message, key, value, **argv): MessageLogs.add(group_id, user_id, nAIset=1) #紀錄次數 filter_fuck = (group_id is None or UserSettings.get(group_id, 'filter_fuck', True)) if filter_fuck and isValueHaveKeys(message, cfg['詞組']['髒話']): return '愛醬覺得說髒話是不對的!!' if key is None: return cfg['學習說明'] key = key.lower() if value is None or value == '': reply_message = ['<%s>' % key] if group_id is not None: data = UserKeyword.get(group_id, key) if data is not None: reply_message.append('群組=%s' % data.reply) if user_id is not None: data = UserKeyword.get(user_id, key) if data is not None: reply_message.append('個人=%s' % data.reply) return '\n'.join(reply_message) if len( reply_message) > 1 else '喵喵喵? 愛醬不記得<%s>' % (key) while '***' in key: key = key.replace('***', '**') while '|||' in key: key = key.replace('|||', '||') while '___' in key: key = key.replace('___', '__') for i in value.replace('__', '||').split('||'): i = i.strip() if i[:4] == 'http' and not is_image_and_ready(i): return '<%s>\n愛醬發現圖片網址是錯誤的\n請使用格式(jpg, png)\n短網址或網頁嵌圖片可能無效\n必須使用https' % i break #如果全部都檢查時間會太久 只幫第一個檢查格式 通常使用者圖床也會使用同一個 應該不會有問題 reply_message = ['<%s>記住了喔 ' % key] if group_id is not None and UserKeyword.add_and_update( group_id, user_id, key, value): reply_message.append('(群組)') if user_id is not None and UserKeyword.add_and_update( user_id, user_id, key, value): reply_message.append('(個人)') else: reply_message.append('(不儲存個人)\nhttps://goo.gl/zTwaL2') return ''.join(reply_message)
def list(self): ''' 列出關鍵字 ''' reply_message = [] if self.group is None or self.key in cfg['詞組']['自己的']: if self.user is None: return text['權限不足'] else: reply_message.append('現在群組中預設不使用個人詞庫\n有需要請用「設定」開啟') reply_message.append('\n'.join([k.keyword for k in UserKeyword.get(self.user.id)])) else: reply_message.append('「列表=我」查詢自己') reply_message.append('\n'.join([k.keyword for k in UserKeyword.get(self.group.id)])) reply_message.append('\n\n新功能實驗\n「網頁設定」') return '\n'.join(reply_message)
def main(self): ''' 關鍵字觸發 ''' if 'http:' in self.message or 'https:' in self.message: #如果內容含有網址 做網址檢查 if self.group: self._count({'網頁': 1}) #紀錄次數 return google_safe_browsing(self.message) else: return google_shorten_url(self.message) #短網址 self.message = self.message.lower().strip(' \n') #調整內容 以增加觸發命中率 self._count({ '對話': 1, '髒話': self.message.count('幹') + self.message.count('f**k'), '字數': len(self.message), }) if self.message == '': return None #暫存訊息 用於對話模型訓練 #if self.group: # with open('E:\\bot_log\\%s.log' % self.group_id, 'a+', encoding='utf-8') as f: # f.write(self.message + '\n') #愛醬開頭可以強制呼叫 if self.group: if self.message != text['名稱'] and self.message[:2] == text['名稱']: message_old = self.message self.message = self.message[2:].strip(' \n ') reply_message = self.check(UserKeyword.get(self.group_id)) if reply_message: return reply_message reply_message = self.check(UserKeyword.get(self.user_id)) if reply_message: return reply_message self.message = message_old #睡覺模式 if UserSettings_temp.has_option(self.group_id, '暫停'): if time() > UserSettings_temp.getfloat(self.group_id, '暫停'): UserSettings_temp.remove_option(self.group_id, '暫停') UserSettings_temp.save() return text['睡醒'] #一般模式 else: if not self.group or (self.user and UserSettings.get( self.group.id, self.user.id, '個人詞庫', False)): #檢查是否使用個人詞庫 reply_message = self.check(UserKeyword.get(self.user.id)) if reply_message: return reply_message if self.group and self.user: if not UserSettings.get(self.group.id, self.user.id, '別理我', False): #檢查不理我模式 reply_message = self.check(UserKeyword.get(self.group.id)) if reply_message: return reply_message #全回應模式 if self.message[:2] == text['名稱'] or self.group_id is None: if self.group is None or UserSettings.get( self.group_id, None, '全回應', default=False): if self.message != text['名稱'] and self.message[:2] == text[ '名稱']: #做兩層是為了方便1對1不見得也要愛醬開頭 self.message = self.message[2:].strip(' \n ') reply_message = self.check(UserKeyword.get(), all_reply=True) if reply_message: return reply_message if self.group: return choice(text['未知']) else: return choice(text['未知']) + '\n(全回應模式關閉)\n使用「設定」開啟' if self.group_id is None: return text['預設回覆'] else: return None
def add(self, plus=False): ''' 新增關鍵字 ''' if self.key is None: return text['學習說明'] #文字處理1 self.key = self.key.lower() while '***' in self.key: self.key = self.key.replace('***', '**') #查詢 if self.value is None: if self.group: row = UserKeyword.get(self.group.id, self.key) else: row = UserKeyword.get(self.user.id, self.key) if row: return text_format(text['關鍵字查詢成功'], key=self.key, value=row.reply) else: return text_format(text['關鍵字查詢失敗'], key=self.key) self._count({'調教': 1}) #紀錄次數 #文字處理2 while '|||' in self.value: self.value = self.key.replace('|||', '||') while '___' in self.value: self.value = self.key.replace('___', '__') #新增 ban_key = ['**', '** **', '愛醬**', '**愛醬**'] if self.key in ban_key: return '%s\n%s' % (text['關鍵字禁用'], text['分隔符'].join(ban_key)) if self.value[:2] == '##': return '由於規則問題 沒辦法使用##開頭的內容喔' if self.key != text['名稱'] and self.key[:2] == text['名稱']: self.key = self.key[2:].strip(' \n') #保護模式過濾 之後option寫入database將此邏輯合併計算中 n = self.value.rfind('##') if n > -1 and '保護' in self.value[ n:] and self.key[:2] == '**' and self.key[-2:] == '**': return '為了避免過度觸發\n保護模式關鍵字不接受前後**喔' reply_message = [ '%s 新增 <%s> ' % (self.user.name if self.user else '', self.key) ] try: if self.group: UserKeyword.add_and_update(self.group_id, self.user_id, self.key, self.value, plus=plus) else: UserKeyword.add_and_update(self.user_id, self.user_id, self.key, self.value, plus=plus) except Exception as e: return '學習失敗: %s' % str(e) level = len(self.key) - self.key.count('**') * ( len('**') + 1) #database的UserKeyword.level 懶得改上面 if level < 0: reply_message.append('\n愛醬非常不建議這種會過度觸發的詞喔\n請慎用') elif level == 0: reply_message.append('\n這種容易觸發的詞容易造成過多訊息喔\n請注意使用') elif level >= 7: reply_message.append('\n這種詞命中率較低喔 請善加利用萬用字元雙米號') if '*' in self.key and '**' not in self.key: reply_message.append( '\n愛醬發現你似乎要使用萬用字元?\n如果是的話請把 *(單米號) 換成 **(雙米號)') if '_' in self.value and self.value.count('__') == 0: reply_message.append( '\n愛醬發現你似乎要使用隨機模式?\n如果是的話請把 _(單底線) 換成 __(雙底線)') #for i in self.value.replace('__', '||').split('||'): # i = i.strip() # if i[:4] == 'http' and not is_image_and_ready(i): # reply_message.append('<%s>\n愛醬發現圖片網址是錯誤的\n請使用格式(jpg, png)\n短網址或網頁嵌圖片可能無效\n必須使用https' % i) # break #如果全部都檢查時間會太久 只幫第一個檢查格式 通常使用者圖床也會使用同一個 應該不會有問題 if self.group is None: reply_message.append( '\n現在個人詞庫預設是不會在群組觸發的喔\n請在群組設定開啟全回應模式(預設開)或開啟個人詞庫(預設關)') else: #保護模式提醒 之後option寫入database將此邏輯合併計算中 n = self.value.rfind('##') if n > -1 and '保護' in self.value[n:]: reply_message.append('\n(此為保護關鍵字 只有你可以刪除及修改 為了避免爭議 建議不要濫用)') return ''.join(reply_message) \ + '\n\n使用「網頁設定」更好操作'
def api_keyword(method): if 'token' not in session: abort(400) uid = session['uid'] #request.args.get('user_id') wd = WebUI.query.get(uid) keyword_mode = request.json.get('mode') _id = uid if keyword_mode == '個人' else wd.gid if wd and (datetime.now()-wd.gid_timeout).total_seconds() < 0 else None if method == 'get': if _id is None: return jsonify({ 'result':[], 'total':0, }) keywords = UserKeyword.get(_id) page = int(request.json.get('page', 1)) - 1 length = int(request.json.get('length', len(keywords))) search = request.json.get('search', '') keywords.reverse() results = [] for row in keywords: if search == '' or search in row.keyword or search in row.reply: results.append({ #'id':row._id, 'keyword':row.keyword, 'reply':row.reply, }) return jsonify({ 'result':results[page*length : page*length+length], 'total':len(results), }) if method == 'add': keyword = request.json.get('keyword') reply = request.json.get('reply') try: UserKeyword.add_and_update(_id, uid, keyword, reply) db.session.commit() return 'ok' except Exception as e: abort(400) abort(Response(str(e))) if method == 'edit': old_keyword = request.json.get('old_keyword') keyword = request.json.get('keyword') reply = request.json.get('reply') try: if UserKeyword.add_and_update(_id, uid, keyword, reply): UserKeyword.delete(_id, uid, old_keyword) db.session.commit() return 'ok' except Exception as e: abort(400) abort(Response(str(e))) if method == 'delete': keyword = request.json.get('keyword') try: UserKeyword.delete(_id, uid, keyword) db.session.commit() return 'ok' except Exception as e: abort(400) abort(Response(str(e)))
def event_main(bot_id, group_id, user_id, message, key, value, **argv): #後處理 def later(reply_message): MessageLogs.add(group_id, user_id, nAItrigger=1) #紀錄次數 #取參數 opt = {} if '##' in reply_message: reply_message_new = [] for i in reply_message.split('##'): if '=' in i: a, *b = i.split('=') opt[a] = '='.join(b) else: reply_message_new.append(i) reply_message = ''.join(reply_message_new) #隨機 (算法:比重) if '__' in reply_message: weight_total = 0 result_pool = {} minimum_pool = [] for msg in reply_message.split('__'): if msg == '': continue index = msg.rfind('%') if index > -1 and isFloat(msg[index + 1:].strip()): #if index > -1 and msg[index+1:].strip().isdigit(): weight = float(msg[index + 1:].strip()) msg = msg[:index] else: weight = 1 weight_total += weight is_minimum = msg[:1] == '*' if is_minimum: is_minimum_pool = msg[:2] == '**' msg = msg[2:] if is_minimum_pool else msg[1:] result_pool[msg] = { 'weight': weight, 'is_minimum': is_minimum, } if is_minimum and is_minimum_pool: minimum_pool.append(msg) count = int( message[message.rfind('*') + 1:]) if '*' in message and message[message.rfind('*') + 1:].isdigit() else 1 if count > 10000: count = 10000 if count < 1: count = 1 if count == 1 and '種子' in opt and opt['種子'].isdigit() and int( opt['種子']) > 0: seed_time = int((datetime.now() - datetime(2017, 1, 1)).days * 24 / int(opt['種子'])) seed = int( md5((str(user_id) + str(seed_time) ).encode()).hexdigest().encode(), 16) % weight_total else: try: #random.org的隨機據說為真隨機 if count > 1: r = requests.get( 'https://www.random.org/integers/?num=%s&min=0&max=%s&col=1&base=10&format=plain&rnd=new' % (count, int(weight_total)), timeout=3) if 'Error' in r.text: raise seed = r.text.split('\n')[:-1] else: raise except: seed = [ uniform(0, int(weight_total)) for i in range(count) ] minimum_count = 0 minimum_index = int(opt.get('保底', 10)) reply_message_new = {} reply_message_image = [] for i in range(count): #r = uniform(0, weight_total) if seed == -1 else seed r = float(seed[i]) if type(seed) == list else seed for msg, msg_opt in result_pool.items(): if r > msg_opt['weight']: r -= msg_opt['weight'] else: minimum_count = 0 if msg_opt[ 'is_minimum'] else minimum_count + 1 if minimum_count >= minimum_index and len( minimum_pool) > 0: minimum_count = 0 msg = choice(minimum_pool) if msg[:6] == 'https:': reply_message_image.append(msg) if len(reply_message_image) > 5: break else: reply_message_new[msg] = ( reply_message_new[msg] + 1) if msg in reply_message_new else 1 break if len(reply_message_new) > 0: if count == 1: reply_message = list(reply_message_new.keys()) else: reply_message = [] for msg, num in reply_message_new.items(): reply_message.append('%s x %s' % (msg, num)) reply_message = ['\n'.join(reply_message)] else: reply_message = [] reply_message.extend(reply_message_image[:5]) #這邊有待優化 if type(reply_message) == str: reply_message = [reply_message] reply_message_new = [] for msg in reply_message: for msg_split in msg.split('||'): reply_message_new.append(msg_split) return reply_message_new message = message.lower() if 'http:' in message or 'https:' in message: #如果內容含有網址 不觸發 順便紀錄 MessageLogs.add(group_id, user_id, nUrl=1) #紀錄次數 return None else: MessageLogs.add(group_id, user_id, nText=1, nFuck=(message.count('幹') + message.count('f**k')), nLenght=len(message)) #紀錄次數 if UserSettings_temp.has_option(group_id, '暫停'): if time() > UserSettings_temp.getfloat(group_id, '暫停'): UserSettings_temp.remove_option(group_id, '暫停') UserSettings_temp.save() return '愛醬大復活!' else: return None if group_id is not None: reply_message = UserKeyword.get(group_id, message) if reply_message is not None: return later(reply_message.reply) if user_id is not None: reply_message = UserKeyword.get(user_id, message) if reply_message is not None: return later(reply_message.reply) keys = [] if group_id is not None: for i in UserKeyword.get(group_id): keys.append((i.keyword, i.reply)) if user_id is not None: for i in UserKeyword.get(user_id): keys.append((i.keyword, i.reply)) for k, v in keys: kn = -1 k_arr = k.split('**') for k2 in k_arr: if k2 != '': n = message.find(k2) if n > kn: kn = n else: break #最後檢查前後如果為任意字元的情況 那相對的最前最後一個字元必須相等 雖然使用字串會比較精準 暫時先用一個字元 如果**混在中間有可能誤判 但是問題不大 if k_arr[0] != '' and message[0] != k[0]: break if k_arr[-1] != '' and message[-1] != k[-1]: break else: return later(v) #使用全群組的關鍵字 限無** if group_id is not None and UserSettings.get(group_id, 'all_group_keyword', False): for k in UserKeyword.query.filter_by( super=0, keyword=message).order_by(UserKeyword._id.desc()): return later(k.reply) if group_id is None: message = message.strip() if message[:4] == 'http': return '愛醬幫你申請短網址了喵\n%s' % google_shorten_url(message) else: return '群組指令說明輸入【指令】\n個人服務:\n直接傳給愛醬網址即可產生短網址\n直接傳圖給愛醬即可上傳到圖床\n其他功能如果有建議請使用回報' else: return None
def event_list(bot_id, group_id, user_id, message, key, value, **argv): if (group_id is None) or (key in cfg['詞組']['自己的']): return '、'.join([k.keyword for k in UserKeyword.get(user_id)]) elif user_id is not None: return '、'.join([k.keyword for k in UserKeyword.get(group_id)]) \ + '\n\n查詢個人關鍵字輸入 列表=我'