Foreword
These days one of my little friends asked if I could do to Ta a flexible configuration of the micro-channel group chat robot, before understood the itchat
use of the library, I readily agreed, and spent a night, finally made a prototype.
A computer running the program as follows:
Information on the phone as follows:
In fact, based on itchat
micro-channel robots already rotten Street, but most are too simple, comparatively speaking, I have this program has the following several distinct characteristics:
1, support for open / close automatic reply specified group chat, simply use Notepad to open group.csv
the file, you want to open automatically fill in reply to a group chat name, losers every time a group chat name, you must wrap.
2, support for custom settings keywords reply, just use Notepad to open keyword.csv
the file, in accordance with the keyword {***, ***} reply formats can be added without having to make any changes in the code. Losers a key-value pair, also need wrap, note that the input comma.
3, the timing of bulk messaging support, and time, the message can be modified dynamically during program execution.
4, there is favorably GUI
interface, wherein the reference color with a simple design of the micro-channel.
DIY play
1, for businesses
As a merchant, when maintenance group may have such needs, time to send a message. For example
回复 xxx 可获得 yyy
, while in thekeyword.csv
pre-written document. In this way, you can make group members what they need, and you do not need to type, copy and paste, can also handle multiple groups at the same time, peace of mind is also efficient.
2, for ordinary individuals
Timing, parents who send blessings to the male and female friends good night messages.
3, Ali goes to deploying server
If you want to have a bug that has been automatically group sent message, your computer must have been open, but deploy to the cloud server can solve this problem. Deployment process can refer to my previous article, Ali cloud server while giving preferential purchase portal.
Detailed design of the code
1, the code architecture
Since the introduction GUI
, GUI
code blocks and code blocks responsible for mass messages, are obstructive, to that end, procedures must be introduced multi-threading mechanism, in which the GUI
interface is the main thread, run a block of code responsible for mass message in a child thread, the thread communication between I use the wxPython
built-in wx.lib.pubsub
module, once the child thread to perform the corresponding action on the adoption of wx.CallAfter(pub.sendMessage)
the interface to send messages to notify GUI
the thread, so as to ensure GUI
timely refresh does not regard Caton.
2, the code flow
First, load the appropriate configuration file to determine which group chat open automatic reply, reply and keyword information. That is why, during program execution, this information can not be changed dynamically.
Wherein the loading keyword
code is as follows:
def load_keyword(self):
global keywords
with open('keyword.csv', 'r', encoding='utf-8', newline='') as f:
reader = csv.reader(f)
for i, line in enumerate(reader):
if i == 0:
continue
keywords[line[0]] = line[1]
The keywords
set of global variables for easy retrieval, to avoid call parameter passing, it is determined i == 0
to remove csv
the first line of the file header information.
The main bulk of the code block following responsible, code comments more clear, will not be repeated
@itchat.msg_register(TEXT, isGroupChat=True)
def group_text(msg):
global keywords
groups = itchat.get_chatrooms(update=True)
for group in groups:
# 群的 NickName 是群名称,UserName 是群id(以两个@开始)
# Python/Java 学习交流群
if group['NickName'] in group_names: # 从群中找到指定的群聊
group_id = msg['FromUserName']
# 防止其他群消息的的干扰
if not group_id == group['UserName']:
break
# 准备回复的消息
keys = keywords.keys()
key = ''
for i in keys:
if i in msg['Text']:
key = i
break
if key == '':
return
message = keywords.get(key)
# 在消息中找到 发送人的id
sender_id = msg['ActualUserName']
# 有时 group['MemberList'] 为空,改变思路由群 id 获取群聊成员
# group_info = itchat.update_chatroom(msg['ToUserName'], detailedMember=True)
# if len(group_info) == 0:
# toUserName 是自己在群聊发消息时,群 id 在消息里的 key
# FromUserName 是别人在群里发时,群 id 在消息里的 key
group_info = itchat.update_chatroom(group_id, detailedMember=True)
memberlist = group_info['MemberList']
for member in memberlist:
# 找到消息的发送者
if member['UserName'] == sender_id:
# 如果有备注名,群聊显示的是备注名
to_user = member['RemarkName']
if len(to_user) == 0:
# 否则显示成员自己修改的在群里的昵称
to_user = member['DisplayName']
if len(to_user) == 0:
# 否则显示他微信号的昵称
to_user = member['NickName']
itchat.send_msg('@{}\n{}'.format(to_user, message), group['UserName'])
wx.CallAfter(pub.sendMessage, "update", msg="回复群聊[{}]成员[{}]成功:[{}]".format(group['NickName'],to_user,message))
Mass responsible for the timing and the above code code more independent, while the child threads started, start timing of execution logic of mass
def run(self):
global t
t = threading.Timer(minutes * 60, self.auto_timer)
t.start()
self.load_keyword()
self.load_group()
itchat.auto_login(hotReload=True)
itchat.run()
One of the major function is threading.Timer(minutes * 60, self.auto_timer)
, what it means is responsible for implementing the bulk of the thread, and then open a thread, the thread interval minutes * 60
after seconds to execute a callback function self.auto_timer
, but this can only be triggered once, no way has been polling, the solution is in go inside the callback function to perform threading.Timer(minutes * 60, self.auto_timer)
, a little similar to the recursive call, and is different from the recursive call is no termination condition, but does not produce memory overflow because of the timer, the time comes and a trigger callback function, this life thread ends here, so the duration of the program is running, the number of active threads just single digits:
def auto_timer(self):
global auto_message
groups = itchat.get_chatrooms(update=True)
for group in groups:
if group['NickName'] in group_names:
itchat.send_msg('{}'.format(auto_message), group['UserName'])
wx.CallAfter(pub.sendMessage, "update",
msg="群聊[{}]定时消息:[{}]发送成功".format(group['NickName'], auto_message))
global t # 把 t 设置为全局变量
t = threading.Timer(minutes * 60, self.auto_timer)
t.start()
GUI
Due to space constraints part of the code, do not stick out.
How to Experience
Public concern No. month long small water background replies micro-channel group robot can be obtained