1
1
# -*- coding: utf-8 -*-
2
- # filename: main.py
3
2
import web
4
3
import time
5
4
import math
10
9
import channel .wechatmp .receive as receive
11
10
from common .log import logger
12
11
from config import conf
13
-
12
+ from bridge .reply import *
13
+ from bridge .context import *
14
+ from plugins import *
15
+ import traceback
14
16
15
17
class WechatMPServer ():
16
18
def __init__ (self ):
@@ -23,15 +25,14 @@ def startup(self):
23
25
app = web .application (urls , globals ())
24
26
app .run ()
25
27
26
-
27
- from concurrent .futures import ThreadPoolExecutor
28
- thread_pool = ThreadPoolExecutor (max_workers = 8 )
29
-
30
28
cache_dict = dict ()
31
29
query1 = dict ()
32
30
query2 = dict ()
33
31
query3 = dict ()
34
32
33
+ from concurrent .futures import ThreadPoolExecutor
34
+ thread_pool = ThreadPoolExecutor (max_workers = 8 )
35
+
35
36
class WechatMPChannel (Channel ):
36
37
37
38
def GET (self ):
@@ -66,11 +67,79 @@ def _do_build_reply(self, cache_key, fromUser, message):
66
67
reply_text = super ().build_reply_content (message , context )
67
68
# The query is done, record the cache
68
69
logger .info ("[threaded] Get reply for {}: {} \n A: {}" .format (fromUser , message , reply_text ))
69
- reply_cnt = math .ceil (len (reply_text ) / 600 )
70
70
global cache_dict
71
+ reply_cnt = math .ceil (len (reply_text ) / 600 )
71
72
cache_dict [cache_key ] = (reply_cnt , reply_text )
72
73
73
74
75
+ def send (self , reply : Reply , cache_key ):
76
+ global cache_dict
77
+ reply_cnt = math .ceil (len (reply .content ) / 600 )
78
+ cache_dict [cache_key ] = (reply_cnt , reply .content )
79
+
80
+
81
+ def handle (self , context ):
82
+ global cache_dict
83
+ try :
84
+ reply = Reply ()
85
+
86
+ logger .debug ('[wechatmp] ready to handle context: {}' .format (context ))
87
+
88
+ # reply的构建步骤
89
+ e_context = PluginManager ().emit_event (EventContext (Event .ON_HANDLE_CONTEXT , {'channel' : self , 'context' : context , 'reply' : reply }))
90
+ reply = e_context ['reply' ]
91
+ if not e_context .is_pass ():
92
+ logger .debug ('[wechatmp] ready to handle context: type={}, content={}' .format (context .type , context .content ))
93
+ if context .type == ContextType .TEXT or context .type == ContextType .IMAGE_CREATE :
94
+ reply = super ().build_reply_content (context .content , context )
95
+ # elif context.type == ContextType.VOICE:
96
+ # msg = context['msg']
97
+ # file_name = TmpDir().path() + context.content
98
+ # msg.download(file_name)
99
+ # reply = super().build_voice_to_text(file_name)
100
+ # if reply.type != ReplyType.ERROR and reply.type != ReplyType.INFO:
101
+ # context.content = reply.content # 语音转文字后,将文字内容作为新的context
102
+ # context.type = ContextType.TEXT
103
+ # reply = super().build_reply_content(context.content, context)
104
+ # if reply.type == ReplyType.TEXT:
105
+ # if conf().get('voice_reply_voice'):
106
+ # reply = super().build_text_to_voice(reply.content)
107
+ else :
108
+ logger .error ('[wechatmp] unknown context type: {}' .format (context .type ))
109
+ return
110
+
111
+ logger .debug ('[wechatmp] ready to decorate reply: {}' .format (reply ))
112
+
113
+ # reply的包装步骤
114
+ if reply and reply .type :
115
+ e_context = PluginManager ().emit_event (EventContext (Event .ON_DECORATE_REPLY , {'channel' : self , 'context' : context , 'reply' : reply }))
116
+ reply = e_context ['reply' ]
117
+ if not e_context .is_pass () and reply and reply .type :
118
+ if reply .type == ReplyType .TEXT :
119
+ pass
120
+ elif reply .type == ReplyType .ERROR or reply .type == ReplyType .INFO :
121
+ reply .content = str (reply .type )+ ":\n " + reply .content
122
+ elif reply .type == ReplyType .IMAGE_URL or reply .type == ReplyType .VOICE or reply .type == ReplyType .IMAGE :
123
+ pass
124
+ else :
125
+ logger .error ('[wechatmp] unknown reply type: {}' .format (reply .type ))
126
+ return
127
+
128
+ # reply的发送步骤
129
+ if reply and reply .type :
130
+ e_context = PluginManager ().emit_event (EventContext (Event .ON_SEND_REPLY , {'channel' : self , 'context' : context , 'reply' : reply }))
131
+ reply = e_context ['reply' ]
132
+ if not e_context .is_pass () and reply and reply .type :
133
+ logger .debug ('[wechatmp] ready to send reply: {} to {}' .format (reply , context ['receiver' ]))
134
+ self .send (reply , context ['receiver' ])
135
+ else :
136
+ cache_dict [context ['receiver' ]] = (1 , "No reply" )
137
+ except Exception as exc :
138
+ print (traceback .format_exc ())
139
+ cache_dict [context ['receiver' ]] = (1 , "ERROR" )
140
+
141
+
142
+
74
143
def POST (self ):
75
144
try :
76
145
queryTime = time .time ()
@@ -94,12 +163,23 @@ def POST(self):
94
163
cache = cache_dict .get (cache_key )
95
164
96
165
reply_text = ""
97
-
98
166
# New request
99
167
if cache == None :
100
168
# The first query begin, reset the cache
101
169
cache_dict [cache_key ] = (0 , "" )
102
- thread_pool .submit (self ._do_build_reply , cache_key , fromUser , message )
170
+ # thread_pool.submit(self._do_build_reply, cache_key, fromUser, message)
171
+
172
+ context = Context ()
173
+ context .kwargs = {'isgroup' : False , 'receiver' : fromUser , 'session_id' : fromUser }
174
+ img_match_prefix = check_prefix (message , conf ().get ('image_create_prefix' ))
175
+ if img_match_prefix :
176
+ message = message .replace (img_match_prefix , '' , 1 ).strip ()
177
+ context .type = ContextType .IMAGE_CREATE
178
+ else :
179
+ context .type = ContextType .TEXT
180
+ context .content = message
181
+ thread_pool .submit (self .handle , context )
182
+
103
183
query1 [cache_key ] = False
104
184
query2 [cache_key ] = False
105
185
query3 [cache_key ] = False
@@ -183,18 +263,28 @@ def POST(self):
183
263
return replyPost
184
264
185
265
elif isinstance (recMsg , receive .Event ) and recMsg .MsgType == 'event' :
186
- toUser = recMsg .FromUserName
187
- fromUser = recMsg .ToUserName
266
+ logger .info ("[wechatmp] Event {} from {}" .format (recMsg .Event , recMsg .FromUserName ))
188
267
content = textwrap .dedent ("""\
189
268
感谢您的关注!
190
269
这里是ChatGPT,可以自由对话。
191
- 资源有限,回复较慢,请不要着急。
192
- 暂时不支持图片输入输出,但是支持通用表情输入。""" )
193
- replyMsg = reply .TextMsg (toUser , fromUser , content )
270
+ 资源有限,回复较慢,请勿着急。
271
+ 支持通用表情输入。
272
+ 暂时不支持图片输入。
273
+ 支持图片输出,画字开头的问题将回复图片链接。
274
+ 支持角色扮演和文字冒险两种定制模式对话。
275
+ 输入'#帮助' 查看详细指令。""" )
276
+ replyMsg = reply .TextMsg (recMsg .FromUserName , recMsg .ToUserName , content )
194
277
return replyMsg .send ()
195
278
else :
196
279
print ("暂且不处理" )
197
280
return "success"
198
- except Exception as Argment :
199
- print (Argment )
200
- return Argment
281
+ except Exception as exc :
282
+ print (exc )
283
+ return exc
284
+
285
+
286
+ def check_prefix (content , prefix_list ):
287
+ for prefix in prefix_list :
288
+ if content .startswith (prefix ):
289
+ return prefix
290
+ return None
0 commit comments