If that FIG.,I pocketed the input method of the user group broke a Robot,As the user off the grid input method more and more,Some admiring novice more。Many common problems repeated questions,Made people battered,If you can have a robot,Like Siri as,It automatically captures those keywords and then respond to these users,Not Miya? So that users can get answers carefully edited,And I can free up more time for you to write code on behalf wan xi。
of course,Such a robot I've ever seen,So I think there must be something ready-made,Obviously,Under the first search I found this:https://github.com/zeruniverse/QQRobot author experiment to learn to do a QQ small yellow chicken,Based on Python,easy and convenient,What I like is that it can run on linux,That is, you can run on my vps。
But this is not convenient to use them,It is through the two-dimensional code scanning to login,And my vps graphics and no end ...... so I had to carry the two-dimensional code download,Too bother。Later, I passed its description link,I found this https://github.com/zeruniverse/QBotWebWrap
He integrated the above mentioned QQRobot,You can control it in the end of the page! But unfortunately,Configuration is complex,php plugin required also more,Focus is not stable,Almost out an on-line。
principle
After pondering such a pass,I also understand how these tools hook,In fact, it cracked web QQ protocol (that is smart qq),Although advanced features can not,But the chat function properly or a duly,Such as the ability to monitor messages,AI is then sent to a third party interface to give each other feedback sent back so。This is the principle of intelligent chat robot friends!
later,I found a more active project:https://github.com/Yinzo/SmartQQBot
This principle and the same as above QQRobot,But someone has to maintain,It is also very active,Project stability。Nothing to say,According to the needs of the installation package will be able to start after,Remember to open the firewall 8888 port,Then you can use python run.py --no-gui --http start up,So it,Then open the corresponding page vps,The same scan code Login。
custom made
SmartQQBot comes with several plug-ins such as weather and within a group can be molested autoresponders plugin,You can use it to teach a fixed syntax,Then it will get back to you so,Although this can be a little my purpose,But not enough。As a special Q & A Robot,How allows users to easily add or delete it, right? Another advantage is the plug-SmartQQBot to increase functionality,It comes with several plug-ins,For example, Satoru ,We do not have this,Turn it off。Project Description There is no description,In fact, also comes with a plug-in, called tucao,This plug-in is different with Satoru,It supports user matched in the statement instead of the full text of the statement to match! Which is good,if you are willing to,Can be done naturally reply is not it?
so,We have to change this,SmartQQBot supports three message tag:
1 2 3 4 5 |
from smart_qq_bot.signals import ( on_all_message, //包括了群消息和私聊消息 on_group_message, //群消息 on_private_message, //私聊消息 ) |
Given different labels through your function,It allows you to plug in response to the different message。
The first is to change to change messaging,I reduce the rights group messages,Control syntax is no longer detected,Only reply,At the same time to also accept whisper,There I can do this test yourself。So the code something like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
@on_all_message(name='loginput[学习遗忘]') def loginput(msg, bot): global core reply = bot.reply_msg(msg, return_function=True) group_id = "16788008" core.load(group_id) for key in list(core.loginput_dict[group_id].keys()): if str(key) in msg.content and core.loginput_dict[group_id][key]: logger.info("RUNTIMELOG loginput pattern detected, replying...") reply(random.choice(core.loginput_dict[group_id][key])) return True return False |
Since tucao This plugin is for different groups of population numbers do processing,Here I have written directly to a fixed pocketed input user base group number,Not hide the,We casually look :)
Here we must note,While the program itself passed in group number is int ,But tucao are handled in accordance with str,So here to write a string。
Then whisper control functions,Here I In addition to modifying the tucao own display list function (big list simply could not send,Too,I read a number of displayed),Also added a reload function,This facilitates I change the background data of the unified add content:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
@on_private_message(name='loginput[管理]') def current_loginput_list(msg, bot): # webqq接受的消息会以空格结尾 global core reply = bot.reply_msg(msg, return_function=True) group_id = "16788008" match = re.match(r'^(?:!|!)(learn|delete|list|reload)(?:\s?){(.+)}(?:\s?){(.+)}', msg.content) if match: core.load(group_id) logger.info("RUNTIMELOG loginput command detected.") command = str(match.group(1)).decode('utf8') key = str(match.group(2)).decode('utf8') value = str(match.group(3)).decode('utf8') if command == 'learn': if group_id not in core.loginput_dict: core.load(group_id) if key in core.loginput_dict[group_id] and value not in core.loginput_dict[group_id][key]: core.loginput_dict[group_id][key].append(value) else: core.loginput_dict[group_id][key] = [value] reply("学习成功!快对我说" + str(key) + "试试吧!") core.save(group_id) return True elif command == 'reload' : loginput_file_path = LOGINPUT_PATH + str(group_id) + ".loginput" try: core.loginput_dict[str(group_id)] = core.readdatafromfile(loginput_file_path) logger.info("RUNTIMELOG loginput loaded. Now loginput list: {0}".format(str(core.loginput_dict))) except: core.loginput_dict[str(group_id)] = dict() logger.info("RUNTIMELOG loginput file is empty.") reply("重新加载完成!") return True elif command == 'delete': if key in core.loginput_dict[group_id] and core.loginput_dict[group_id][key].count(value): core.loginput_dict[group_id][key].remove(value) reply("呜呜呜我再也不说" + str(value) + "了") core.save(group_id) return True elif command == 'list': result = 0 for key in list(core.loginput_dict[group_id].keys()): result += 1 logger.info("RUNTIMELOG Replying the list of loginput for group {}".format(group_id)) reply("总共有关键字" + result + "条") return True return |
In fact, the keyword is detected from the regular expression,Along expression format can guess,Add a reply is so: !learn {test}{test reply!} 。
Then delete it? The same format,Because it can be carried out in accordance with a plurality of random keywords Reply,So if you delete,Must correspond,Can not be left blank: !delete {test}{test reply!}
However, due to the fixed format,So see how many are needed and reload this format,Only the contents of brackets is invalid,Casually write: !reload {test}{test reply!}
At last,Since tucao itself using Python serialization,Save the file against editing,We put it into JSON format,This requires an additional package json。
Since I usually use is Python 3,So here I pulled the other items in the code used to take over,Then add:
1 2 3 4 5 6 7 8 9 10 11 |
import json import io def writejson2file(self,obj, filename): with io.open(filename, 'w', encoding='utf8') as outfile: data = json.dumps(obj, indent=4, sort_keys=True, ensure_ascii=False) outfile.write(data) def readdatafromfile(self,filename): with io.open(filename, encoding='utf8') as outfile: return json.load(outfile) |
So that you can save and change the code to load the:
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 31 32 33 |
def save(self, group_id): """ :type group_id: int, 用于保存指定群的吐槽存档 """ global LOGINPUT_PATH try: loginput_file_path = LOGINPUT_PATH + str(group_id) + ".loginput" self.writejson2file(self.loginput_dict[str(group_id)],loginput_file_path) logger.info("RUNTIMELOG loginput saved. Now loginput list: {0}".format(str(self.loginput_dict))) except Exception: logger.error("RUNTIMELOG Fail to save loginput.") raise IOError("Fail to save loginput.") def load(self, group_id): """ :type group_id: int, 用于读取指定群的吐槽存档 """ global LOGINPUT_PATH if str(group_id) in set(self.loginput_dict.keys()): return loginput_file_path = LOGINPUT_PATH + str(group_id) + ".loginput" if not os.path.isdir(LOGINPUT_PATH): os.makedirs(LOGINPUT_PATH) if not os.path.exists(loginput_file_path): with open(loginput_file_path, "w") as tmp: tmp.close() try: self.loginput_dict[str(group_id)] = self.readdatafromfile(loginput_file_path) logger.info("RUNTIMELOG loginput loaded. Now loginput list: {0}".format(str(self.loginput_dict))) except : self.loginput_dict[str(group_id)] = dict() logger.info("RUNTIMELOG loginput file is empty.") |
At last,To configure, select load this plugin:
1 2 3 4 5 6 7 8 9 10 11 |
vi config/plugin.json { "plugin_packages": [], "plugin_on": [ "basic", "manager", "weather", "loginput" ] } |
Then plug into the edited smart_qq_plugins In it。
Widget
if you need,All codes of this file you can copy directly here,Create a loginput.py And write to:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# -*- coding: utf-8 -*- import re import os import random import json import io from smart_qq_bot.logger import logger from smart_qq_bot.signals import ( on_all_message, on_private_message, ) LOGINPUT_PATH = 'smart_qq_plugins/loginput/' class LogInputCore(object): def __init__(self): self.loginput_dict = dict() def writejson2file(self,obj, filename): with io.open(filename, 'w', encoding='utf8') as outfile: data = json.dumps(obj, indent=4, sort_keys=True, ensure_ascii=False) outfile.write(data) def readdatafromfile(self,filename): with io.open(filename, encoding='utf8') as outfile: return json.load(outfile) def save(self, group_id): """ :type group_id: int, 用于保存指定群的吐槽存档 """ global LOGINPUT_PATH try: loginput_file_path = LOGINPUT_PATH + str(group_id) + ".loginput" self.writejson2file(self.loginput_dict[str(group_id)],loginput_file_path) logger.info("RUNTIMELOG loginput saved. Now loginput list: {0}".format(str(self.loginput_dict))) except Exception: logger.error("RUNTIMELOG Fail to save loginput.") raise IOError("Fail to save loginput.") def load(self, group_id): """ :type group_id: int, 用于读取指定群的吐槽存档 """ global LOGINPUT_PATH if str(group_id) in set(self.loginput_dict.keys()): return loginput_file_path = LOGINPUT_PATH + str(group_id) + ".loginput" if not os.path.isdir(LOGINPUT_PATH): os.makedirs(LOGINPUT_PATH) if not os.path.exists(loginput_file_path): with open(loginput_file_path, "w") as tmp: tmp.close() try: self.loginput_dict[str(group_id)] = self.readdatafromfile(loginput_file_path) logger.info("RUNTIMELOG loginput loaded. Now loginput list: {0}".format(str(self.loginput_dict))) except : self.loginput_dict[str(group_id)] = dict() logger.info("RUNTIMELOG loginput file is empty.") core = LogInputCore() @on_all_message(name='loginput[学习遗忘]') def loginput(msg, bot): global core reply = bot.reply_msg(msg, return_function=True) group_id = "16788008" core.load(group_id) for key in list(core.loginput_dict[group_id].keys()): if str(key) in msg.content and core.loginput_dict[group_id][key]: logger.info("RUNTIMELOG loginput pattern detected, replying...") reply(random.choice(core.loginput_dict[group_id][key])) return True return False @on_private_message(name='loginput[管理]') def current_loginput_list(msg, bot): # webqq接受的消息会以空格结尾 global core reply = bot.reply_msg(msg, return_function=True) group_id = "16788008" match = re.match(r'^(?:!|!)(learn|delete|list|reload)(?:\s?){(.+)}(?:\s?){(.+)}', msg.content) if match: core.load(group_id) logger.info("RUNTIMELOG loginput command detected.") command = str(match.group(1)).decode('utf8') key = str(match.group(2)).decode('utf8') value = str(match.group(3)).decode('utf8') if command == 'learn': if group_id not in core.loginput_dict: core.load(group_id) if key in core.loginput_dict[group_id] and value not in core.loginput_dict[group_id][key]: core.loginput_dict[group_id][key].append(value) else: core.loginput_dict[group_id][key] = [value] reply("学习成功!快对我说" + str(key) + "试试吧!") core.save(group_id) return True elif command == 'reload' : loginput_file_path = LOGINPUT_PATH + str(group_id) + ".loginput" try: core.loginput_dict[str(group_id)] = core.readdatafromfile(loginput_file_path) logger.info("RUNTIMELOG loginput loaded. Now loginput list: {0}".format(str(core.loginput_dict))) except: core.loginput_dict[str(group_id)] = dict() logger.info("RUNTIMELOG loginput file is empty.") reply("重新加载完成!") return True elif command == 'delete': if key in core.loginput_dict[group_id] and core.loginput_dict[group_id][key].count(value): core.loginput_dict[group_id][key].remove(value) reply("呜呜呜我再也不说" + str(value) + "了") core.save(group_id) return True elif command == 'list': result = 0 for key in list(core.loginput_dict[group_id].keys()): result += 1 logger.info("RUNTIMELOG Replying the list of loginput for group {}".format(group_id)) reply("总共有关键字" + result + "条") return True return |
Original article written by LogStudio:R0uter's Blog » I pocketed the input method users add automatic reply robot
Reproduced Please keep the source and description link:https://www.logcg.com/archives/2507.html
Ah ha ha now there are a lot of websites have begun to call a good strong artificial intelligence replace the Mark