Skip to content

Commit

Permalink
Add a new feature to pai dui.
Browse files Browse the repository at this point in the history
  • Loading branch information
grapeot committed Apr 1, 2017
1 parent 186dd28 commit 71ab528
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 11 deletions.
5 changes: 4 additions & 1 deletion GlobalTextHook.py
Expand Up @@ -5,13 +5,16 @@
import logging

class GlobalTextHook(ProcessInterface):
def __init__(self, subdict={}):
def __init__(self, subdict={}, blacklist=[]):
self.dict = subdict
self.blacklist = blacklist
logging.info('GlobalTextHook initialized.')

def process(self, msg, type):
if type != TEXT:
return
if any([ re.search(x, msg['User']['NickName']) is not None for x in self.blacklist ]):
return
for k in self.dict:
if re.search(k, msg['Content']):
v = self.dict[k]
Expand Down
3 changes: 3 additions & 0 deletions GroupMessageForwarder.py
Expand Up @@ -21,6 +21,9 @@ def __init__(self, chatroomDisplayNames, chatroomNames, isBidirectional=True):
self.isInitialized = True

def process(self, msg, type):
if not self.isInitialized:
logging.error('The forwarder was not properly initialized. Please send a message in the groups you want to connect and try again.')
return
shallSendObj = self.shallSend(msg)
if not shallSendObj['shallSend']:
return
Expand Down
4 changes: 2 additions & 2 deletions GroupTagCloud.py
Expand Up @@ -52,9 +52,9 @@ def generateTagCloudForGroup(self, groupName, userName=None):
def isRun(self, msg, type):
if type != TEXT or 'Content' not in msg:
return { 'shallRun': False }
if msg['Content'] == '/tagcloud':
if re.search(r'^\s*/tagcloud$', msg['Content']):
return { 'shallRun': True, 'userName': None, 'groupName': msg['User']['NickName'] }
if msg['Content'] == '/mytag':
if re.search(r'^\s*/mytag$', msg['Content']):
return { 'shallRun': True, 'userName': msg['ActualNickName'], 'groupName': msg['User']['NickName'] }
return { 'shallRun': False }

Expand Down
65 changes: 65 additions & 0 deletions PaiDuiHook.py
@@ -0,0 +1,65 @@
from itchat.content import *
from ProcessInterface import ProcessInterface
import itchat
import re
import logging

class PaiDuiHook(ProcessInterface):
groupContentCacheMaxCapacity = 10

def __init__(self, blacklist=[]):
self.blacklist = blacklist
self.groupLastMsgsDict = {}
logging.info('PaiduiHook initialized.')

def WhatToPaiDui(self, groupName):
msgCount = {}
msgs = self.groupLastMsgsDict[groupName]
for msg in msgs:
if msg['Content'] not in msgCount:
msgCount[msg['Content']] = 0
msgCount[msg['Content']] += 1
if msg['FromSelf']:
# if we replied this before, we will effectively remove it from the group content cache
msgCount[msg['Content']] -= self.groupContentCacheMaxCapacity
contentToPaiDui = [ x for x in msgCount if msgCount[x] > 1 ]
if len(contentToPaiDui) > 1:
logging.error('Something is wrong, len(contentToPaiDui) > 1.')
if len(contentToPaiDui) == 0:
return None
else:
return contentToPaiDui[0]

def isFromSelf(self, msg):
if re.search('^@@', msg['ToUserName']):
return True
else:
return False

def updateGroupContentCache(self, msg, groupName):
if groupName not in self.groupLastMsgsDict:
self.groupLastMsgsDict[groupName] = []
if len(self.groupLastMsgsDict[groupName]) >= self.groupContentCacheMaxCapacity:
self.groupLastMsgsDict[groupName].pop(0)
self.groupLastMsgsDict[groupName].append({ 'Content': msg['Content'], 'FromSelf': 'FromSelf' in msg and msg['FromSelf'] })

def process(self, msg, type):
if type != TEXT:
return
groupName = msg['User']['NickName']
if any([ re.search(x, groupName) is not None for x in self.blacklist ]):
return
if re.search('^/', msg['Content']):
return
if self.isFromSelf(msg):
# Stop processing if the message is from myself
return

self.updateGroupContentCache(msg, groupName)
contentToPaiDui = self.WhatToPaiDui(groupName)
if contentToPaiDui is not None:
# Pai dui!
itchat.send(msg['Content'], msg['FromUserName'])
logging.info('Pai Dui! {0}.'.format(msg['Content']))
# Update data structure to avoid Pai dui for multiple times.
self.updateGroupContentCache({ 'Content': msg['Content'], 'FromSelf': True }, groupName)
7 changes: 4 additions & 3 deletions deploy.sh
@@ -1,5 +1,6 @@
# If using virtualenv
virtualenv .
source bin/activate

# Install dependencies
pip3 install -r requirements.txt

# Launch the program
python3 main.py
Empty file modified launchWechatBot.sh 100644 → 100755
Empty file.
22 changes: 17 additions & 5 deletions main.py
Expand Up @@ -4,6 +4,7 @@
from utilities import *
from sys import argv, exit
from GlobalTextHook import GlobalTextHook
from PaiDuiHook import PaiDuiHook
from HistoryRecorder import HistoryRecorder
from GroupTagCloud import GroupTagCloud
from GroupMessageForwarder import GroupMessageForwarder
Expand All @@ -18,11 +19,13 @@
# Component initialization
itchat.auto_login(True)
plugins = [
GlobalTextHook({ '^ding$': 'dong', '鸭哥': '嘎?' }),
GlobalTextHook({ '^ding$': 'dong', '鸭哥': '嘎?' }, [ '知乎秋名山三年二班', '知乎最牛逼兄弟会没有之一' ]),
PaiDuiHook(),
HistoryRecorder(),
GroupTagCloud('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc'),
ActivityInfo('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc'),
GroupMessageForwarder([ 'Group1', 'Group2' ], [ 'ActualGroupName1', 'ActualGroupName2' ])
GroupMessageForwarder([ '一群', '二群' ], [ '【科大校友AI&Deep-Learning群】', '科大AI二群测试中' ], False),
GroupMessageForwarder([ '二群', '三群' ], [ '科大AI二群测试中', '科大AI三群供测试' ])
]
for plugin in plugins:
if not isinstance(plugin, ProcessInterface):
Expand All @@ -35,21 +38,30 @@ def picture_reply(msg):
if isDebug:
logging.info(msg)
for plugin in plugins:
plugin.process(msg, PICTURE)
try:
plugin.process(msg, PICTURE)
except:
pass # so that one plug's failure won't prevent others from being executed

@itchat.msg_register([SHARING], isGroupChat=True)
def sharing_reply(msg):
if isDebug:
logging.info(msg)
for plugin in plugins:
plugin.process(msg, SHARING)
try:
plugin.process(msg, PICTURE)
except:
pass # so that one plug's failure won't prevent others from being executed

@itchat.msg_register([TEXT], isGroupChat=True)
def text_reply(msg):
if isDebug:
logging.info(msg)
for plugin in plugins:
plugin.process(msg, TEXT)
try:
plugin.process(msg, PICTURE)
except:
pass # so that one plug's failure won't prevent others from being executed

if __name__ == '__main__':
itchat.run()

0 comments on commit 71ab528

Please sign in to comment.