From 1ec0a530bf17fcd253acd64acdfeef5adf2148a0 Mon Sep 17 00:00:00 2001
From: zhayujie <yjzha1996@163.com>
Date: Wed, 10 Aug 2022 00:04:10 +0800
Subject: [PATCH] init: build minimum viable version

---
 .gitignore                                    |   2 +
 app.py                                        |  10 +++++
 bot/__pycache__/bot.cpython-36.pyc            | Bin 0 -> 574 bytes
 bot/__pycache__/bot_factory.cpython-36.pyc    | Bin 0 -> 491 bytes
 .../__pycache__/baidu_unit_bot.cpython-36.pyc | Bin 0 -> 1537 bytes
 bot/baidu/baidu_unit_bot.py                   |  26 ++++++++++++
 bot/bot.py                                    |  13 ++++++
 bot/bot_factory.py                            |  16 +++++++
 bridge/__pycache__/bridge.cpython-36.pyc      | Bin 0 -> 616 bytes
 bridge/bridge.py                              |   9 ++++
 channel/__pycache__/channel.cpython-36.pyc    | Bin 0 -> 1200 bytes
 .../channel_factory.cpython-36.pyc            | Bin 0 -> 510 bytes
 channel/channel.py                            |  31 ++++++++++++++
 channel/channel_factory.py                    |  15 +++++++
 .../__pycache__/wechat_channel.cpython-36.pyc | Bin 0 -> 1552 bytes
 channel/wechat/wechat_channel.py              |  39 ++++++++++++++++++
 16 files changed, 161 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 app.py
 create mode 100644 bot/__pycache__/bot.cpython-36.pyc
 create mode 100644 bot/__pycache__/bot_factory.cpython-36.pyc
 create mode 100644 bot/baidu/__pycache__/baidu_unit_bot.cpython-36.pyc
 create mode 100644 bot/baidu/baidu_unit_bot.py
 create mode 100644 bot/bot.py
 create mode 100644 bot/bot_factory.py
 create mode 100644 bridge/__pycache__/bridge.cpython-36.pyc
 create mode 100644 bridge/bridge.py
 create mode 100644 channel/__pycache__/channel.cpython-36.pyc
 create mode 100644 channel/__pycache__/channel_factory.cpython-36.pyc
 create mode 100644 channel/channel.py
 create mode 100644 channel/channel_factory.py
 create mode 100644 channel/wechat/__pycache__/wechat_channel.cpython-36.pyc
 create mode 100644 channel/wechat/wechat_channel.py

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d2d9075
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.idea/
+venv
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..78e6c4e
--- /dev/null
+++ b/app.py
@@ -0,0 +1,10 @@
+from channel import channel_factory
+
+if __name__ == '__main__':
+    # create channel
+    channel = channel_factory.create_channel("wx")
+
+    # startup channel
+    channel.startup()
+
+    print("Hello bot")
\ No newline at end of file
diff --git a/bot/__pycache__/bot.cpython-36.pyc b/bot/__pycache__/bot.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a006b4219279b4c5140baccecf890864dda4fb8b
GIT binary patch
literal 574
zcmZWly-ve05O#k0LqsPS7_*@uwHeqdgbD~DmM(~;i{-=zZI#5S?I0y1@G?9MFW{92
zU`Gs`(;tvH>APHfci(q+r-MPD-#?RYLdXYVXFf&~ggQdU$&B0(?r`^&a2K2xZ{~9E
zjzoTQ99&dd3?-BqtHX58bSOn4bjT8=B};XfW=yFdMVg(t7)=oB5FL=2g97fFe&(%-
zjdv+@Y74E|uY<Tks6IMPo*nMs1a6ZB;l^6o?KC)yC^Qs$mmZf)vOJWq8ly{L@dP}~
zK`HhKzeN&sB@0_oX8$>+kz)>~Lf__P205|=zm`(S$Thx#?7?(a70CLH$PP~VbrRnz
zkScEKW!%hJT`d<7+anFxVu<6$8;r`@bXvup-LPG|+w9>9M(yh~@=c%8g5^M|2`J44
zuQD6&Q@W~Hw$4b~-75caUHfK_XM>iy@3jBZ$TK}kxk!<xE0QIox=s9Pwp&QsX!>Vs
K&2w){<9k2Bs*NN7

literal 0
HcmV?d00001

diff --git a/bot/__pycache__/bot_factory.cpython-36.pyc b/bot/__pycache__/bot_factory.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..68002af308cf84209367eeecb85f7cad0b4d40c5
GIT binary patch
literal 491
zcmY*VJx{|h5Vf5&L{W>xf*2UGW@sb9Rw0CnSUXU4$zr*-QB(3!InI!X3HUSorASN+
zh>4wvv)hPr(mnfh@7_K8ax@A)-@jKAjL-)<2m<#T$m$$GpacmlNQQHg5R8N)+*g!1
zVz5Aw*PaA?&5A;1;REBkR88;&Lny-CaK=(mFN;*qO3h)14Rad(Tgd7Z;0e?pi8|Kk
z1uc-q&#()Woi+<X2(Bd4GGt-DCM_z>3NCGTx@C&xeUIv9E2n)GnkwX_*i)6%wJQGF
z|Admk%DA0JL>YJ8@V+i|n#((-N)_S6UzOU*zaixU;pZY=R#H`Q+ic=?&6;|X${0NA
zF-yllj`vCT-!j=YU9fu$g_dug?*Sms#~xPZI*;7$h*D8<N|Q4nO{}LK(i%R}Oj>`I
aZ;c$l05m%PDlbKy$!iCy%2;*D(D?=YD1Wp7

literal 0
HcmV?d00001

diff --git a/bot/baidu/__pycache__/baidu_unit_bot.cpython-36.pyc b/bot/baidu/__pycache__/baidu_unit_bot.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9a1fff91fc1d8789e0cc130ecc9e5c53a58aaa33
GIT binary patch
literal 1537
zcmZ`(&2QsG6rb@&l4i5C!0whx9EuM}k(zkhvNS4mchzl0ksx$Q!-oMG*E4CHI<`AA
zZW}j|kkZ2*;Ep(P;lK%TL}>pJ-w=h>p15=3&A7Xi0~5XHH_vZ=@6CHZXZ8B^D*x@T
z{aF*C-_ez2fPEi??|>qR;1D^*6FV68TBr?mN5|+LM08@DBVtf}syhZXiFv58En1?+
z6b;IxG{sYl0ilEH<)?s#+I5`ko3Zfa=GoG~xDUc#1x1le;%EdD?HoCJk-{;E2_U7s
zw&?{V?M8u+DDtFSWe~UqdH}+|1T{tjG({6Y8Ef-sq7!Y5=b>D%4S~moDhn_JJTZkf
z(8v1N7(mfula#*EC#7+TeLgM?%qb$}1w<+!Ga%Ik)PYt&CD+>7gT4?6U$<>9NSgby
ztbLz0{dj1z#J5+Px9t?lv^izRfluw@Rom}-;-2UGlyg_ahcw#AzCN>#DdRyLS?ktn
z^R~5QT^?`)0<O;5>hju}@^TqfcwryL2Zg=1cBge`Wm$$C24M(JZmoZ2Ew8LBw_0yn
zUo2US9;K8EYyHd;lnsN(lTiTPk_!&PYc_&?wrVXcTK!Q%nVWdb8v@eenI+41{gjJ%
z=<dhDO<3FuLJIGeCzDB5^W#X+NHhc-%wF@7Bn*5{K(Y2|<K*O|(Tmxzk+P6ReoQE-
zYq>!@;pOE%^$1)(FEPr~P~>HWbSj(|JD+yk-4C}r-S@Y*+?{tjdrvV;73M#4Kt<8J
z+)P*yiM(=oJ)Rp$%tc-*(&WZ~$5FkU8=Qu{+*EhWP1W{XhiaS|8SctTnB<NG;z=BF
z`XgdD!14E6b{A&B?QAr#v%WV<2LV+xY<NKf8euDugSXZAT{&;rp=L75O-7S&Gy^z%
z4iv%__|=rYfeoC!bd|_W73|A9$|cK@)K+xf1cTrSd=5ZoUD4Q>M+L0~8sM=$#S>#}
zu)9J766;eW$z52)d`{R>+j-@Lv`>=btp7%DleJE>y>yrEe(-U>>nv_}#e1KOSbWgi
zd-zc+iUyG%9ksW6bQJGwb&opP!~Z3F?4_cw=&pKu?|^v`j0m`};fDe6!u1&?@C>|=
zzkcZo$VN8%Y{Mx;hz+N9_0y;u>>AuW*J0qS3Kn|-RNZ8=@NlY^p@($jREzU2*tyY%
znX;E<xEx`jZc0l|Li)LcK`;RW&*3WQ8qRM0XBN*H)~=g*#dRZZNL@Fty6!M0X(;WQ
z>mH?ESiE7k08rsy$*Hod#5%mKfN=T03M8m9>5;%gFNj<>l~EUuzkl-G`IARK|MA1)
zKfnFy;@7V(etA@{s5`4ZIAzHz5GIMCAlQPmRBKcP|6cfc^1SkPQS)7ylgn5|Lw)XM
G1^)vox}_=r

literal 0
HcmV?d00001

diff --git a/bot/baidu/baidu_unit_bot.py b/bot/baidu/baidu_unit_bot.py
new file mode 100644
index 0000000..284eff5
--- /dev/null
+++ b/bot/baidu/baidu_unit_bot.py
@@ -0,0 +1,26 @@
+# encoding:utf-8
+
+import json
+import requests
+from bot.bot import Bot
+
+
+class BaiduUnitBot(Bot):
+    def reply(self, query):
+        token = self.get_token()
+        url = 'https://aip.baidubce.com/rpc/2.0/unit/service/v3/chat?access_token=' + token
+        post_data = "{\"version\":\"3.0\",\"service_id\":\"S73177\",\"session_id\":\"\",\"log_id\":\"7758521\",\"skill_ids\":[\"1221886\"],\"request\":{\"terminal_id\":\"88888\",\"query\":\"" + query + "\", \"hyper_params\": {\"chat_custom_bot_profile\": 1}}}"
+        print(post_data)
+        headers = {'content-type': 'application/x-www-form-urlencoded'}
+        response = requests.post(url, data=post_data.encode(), headers=headers)
+        if response:
+            return response.json()['result']['context']['SYS_PRESUMED_HIST'][1]
+
+    def get_token(self):
+        access_key = '${YOUR_ACCESS_KEY}'
+        secret_key = '${YOUR_SECRET_KEY}'
+        host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + access_key + '&client_secret=' + secret_key
+        response = requests.get(host)
+        if response:
+            print(response.json())
+            return response.json()['access_token']
diff --git a/bot/bot.py b/bot/bot.py
new file mode 100644
index 0000000..8b441e9
--- /dev/null
+++ b/bot/bot.py
@@ -0,0 +1,13 @@
+"""
+Auto-replay chat robot abstract class
+"""
+
+
+class Bot(object):
+    def reply(self, query):
+        """
+        bot auto-reply content
+        :param req: received message
+        :return: reply content
+        """
+        raise NotImplementedError
diff --git a/bot/bot_factory.py b/bot/bot_factory.py
new file mode 100644
index 0000000..919215f
--- /dev/null
+++ b/bot/bot_factory.py
@@ -0,0 +1,16 @@
+"""
+channel factory
+"""
+
+from bot.baidu.baidu_unit_bot import BaiduUnitBot
+
+
+def create_bot(bot_type):
+    """
+    create a channel instance
+    :param channel_type: channel type code
+    :return: channel instance
+    """
+    if bot_type == 'baidu':
+        return BaiduUnitBot()
+    raise RuntimeError
\ No newline at end of file
diff --git a/bridge/__pycache__/bridge.cpython-36.pyc b/bridge/__pycache__/bridge.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d25ba0cae902ab5786e64c1df1d148c19feaf39a
GIT binary patch
literal 616
zcmZuuJx{|h5Ix692~c2QLrAb@XoJLxP*n!DE{G+ImBcPhlqTRfLn^lR&+r@gCmC3n
znAn-Pb0{pFbRW8VdiQ+3JUG}pd;3gY0pK0|*IcY7==C`U36d4CWD#R<3(}E%1ClFe
z%_A<|I|#fFL_xs1{iHHt9;c?#ZA!hZIao~4>r)I0A|@enB$LhtkONsTyV66hK{uG{
zOg^ZTA(V_V`3-ta!XzM$&0c7uTdQKOscXa6MR;E;U5BeS4_Ax0ZSqWo=^{3xI2)n5
zFtOx6Y5drBz7ScN86iC4C!xSrN4<vec9z;cjwq8`F^5<f$k`fl=b5dUl@)MJfM__4
zGuhlD^|UgPr`2Q829BmJo%hrz-Tuke1L_{nl}Q)EB1Kx2MwQ0L!B*7CkEnlOv%sT=
zl<`st(d`MbtYlMAJrv@piHm-scaTo+QusYtUy%UKF;L%L*=Ihtomt>U98YJT)eWj7
VSE;d+|42Ijs^5K0e`ci*`8RpPhUWkP

literal 0
HcmV?d00001

diff --git a/bridge/bridge.py b/bridge/bridge.py
new file mode 100644
index 0000000..3e5af00
--- /dev/null
+++ b/bridge/bridge.py
@@ -0,0 +1,9 @@
+from bot import bot_factory
+
+
+class Bridge(object):
+    def __init__(self):
+        pass
+
+    def fetch_reply_content(self, query):
+        return bot_factory.BaiduUnitBot().reply(query)
diff --git a/channel/__pycache__/channel.cpython-36.pyc b/channel/__pycache__/channel.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d38f44b04d40435678ee4a8b80d7eb709a800702
GIT binary patch
literal 1200
zcmZ`&J8#rL5Z<+YwqspF5m6yUE+{xbauReWgb)!zDYypFxLNJ(ZZ1CgaqO;<&Y~iz
z`58$3B^NYQRP<EL_(c*WEA7sBXLjcMX2vh}_oJsj|E#_{g#04cmIwN4*yb@Dk|ab@
z>0~r_5{Hs^M7q+uBGOatrJHzi@`23!`bqR&8N=5qHmZ<mv5v(BFA9~#d}XZW!p0)w
z#zem%CYjO3f1^{mRsuhV1wgvQ&p=Tmp^)6c<X0qdyR?{4`tUuGfeb<Vat{DRO>o-f
z6SR+p689-=6T)H1S1KtuJM~c%_bV+@K-N7SFPDJta9P^3e4D9U6;{c&T9+EGJ)^So
zA4K~Q@bB~aN29cv*SpQUzTmrRld3rcv&TF=UX>Pgtid2pw!0=UmTOyW5s^W{#H%0l
z*iU+!Xz#&<@;(k{BiyYn1r$HlN~rX+l5uX<qj9n2n&)`6i1WTh<!YmZ9bJH~#-7g{
zJps|U;M@}IjsWj`U?MYh0D6adQXdScJCkt1h709=pudetaZE-)wu~#N<Y>GLv?!qu
z#edYjPfuDe2KstvXUv5ttLrbcvXw3t@t9|1?zYVJ9zbuxA>{2EK<^9r5L~(n1od>N
z02*#I4I9@E-V_u|F3E;|p_e#(bO~ifb8>jDthiuWZL=Ng*$pk2e5#b*-3D;Ds?to}
zd~r15q4lEy&mDftS<r-x6+BmrH4$TZDXR?iDPx~1o^=+DbEzXd5W2>OUxR^TuW=wW
zb{UoS*9vLqhe5d4-Y#d8CSXjKg0W<O)&AxuooI<Sem8%u^Ifr<@MQ<?6(%t_nw~Rt
F{sBmc7$^V$

literal 0
HcmV?d00001

diff --git a/channel/__pycache__/channel_factory.cpython-36.pyc b/channel/__pycache__/channel_factory.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d4c4ddc787f41d191ad4ebd030355765207241c4
GIT binary patch
literal 510
zcmY*VO-sW-5Z&FRX$ft?izkI#b7*t$R#b%IwFip`xh&i4N>lSuHXCY!AgDjUzu{lX
z)srXho}Aq#SO@ma3~%Pm?3|58?(_Ti>H;J5i4KfFd<CyK0pKV^9CMQ3l!OE$ZgKk!
zg%<BEk?+(;ZnS1uCKB(SMJkt-`vpzN$Ia+Y0Hx-8I)Wj_wATaX@QP!ACy;+2a;(rR
zS|WvCU>HbSb>ezpkrYe`k9pmkI4cy(B4OCsmPwX&997j;%(~3enHS}}EtNu*GW(<d
z2{mN*xbTV8t2M)$GE;FXuBFVSkHcX*+vtBF*@L2=S#VnjSp;>p3F<Yg%1tZ+{o@IX
zC#ziPSRbbIv^~&tTQ%eTuV`D+*SBy0kTbvzmO5YfcGIVn=MkmhX<InmnVYt*Yd1@q
aCbQWAXw7DDp60wv#H9sUVFTD?NPYpN)rUd=

literal 0
HcmV?d00001

diff --git a/channel/channel.py b/channel/channel.py
new file mode 100644
index 0000000..94f7b8b
--- /dev/null
+++ b/channel/channel.py
@@ -0,0 +1,31 @@
+"""
+Message sending channel abstract class
+"""
+
+from bridge.bridge import Bridge
+
+class Channel(object):
+    def startup(self):
+        """
+        init channel
+        """
+        raise NotImplementedError
+
+    def handle(self, msg):
+        """
+        process received msg
+        :param msg: message object
+        """
+        raise NotImplementedError
+
+    def send(self, msg, receiver):
+        """
+        send message to user
+        :param msg: message content
+        :param receiver: receiver channel account
+        :return: 
+        """
+        raise NotImplementedError
+
+    def build_reply_content(self, query):
+        return Bridge().fetch_reply_content(query)
diff --git a/channel/channel_factory.py b/channel/channel_factory.py
new file mode 100644
index 0000000..5ecdbeb
--- /dev/null
+++ b/channel/channel_factory.py
@@ -0,0 +1,15 @@
+"""
+channel factory
+"""
+
+from channel.wechat.wechat_channel import WechatChannel
+
+def create_channel(channel_type):
+    """
+    create a channel instance
+    :param channel_type: channel type code
+    :return: channel instance
+    """
+    if channel_type == 'wx':
+        return WechatChannel()
+    raise RuntimeError
\ No newline at end of file
diff --git a/channel/wechat/__pycache__/wechat_channel.cpython-36.pyc b/channel/wechat/__pycache__/wechat_channel.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..1efc97cdabf7425e83637443f128f9fddcef2f65
GIT binary patch
literal 1552
zcmZvc&5zwQ5WwwxZ<^PS-EFItIP3{2NZls^rwXA;73KDX#6ut>WU{e$H)&q-upMBd
zaC$5C)IWrODc7Es3pWm&m~j$yUqzzK*v@!7^YhrBEf(=V@BTjj%O&I;x$}6?egU8U
z8H6B=2r8V4GHSKM9IIXCTJ13pv|IUWwDYQ96S9yJNy|tcT+$sCz6fr}j<Wb`B0>?}
z5E036=dydk`Ie*y-NX1dnO|k*6hvLiD!zqv$ttA-{RBk#avaVn4#R`mf$t@J`XLBI
zcBG^|tU)1O@JUyxGc3NhUZ>eZ0A55T!J)g+mwyr!!pwhPEWguI>1B6aF1xGjx-AR2
z#9*Ff#k2FqU>jpvjv-EpPorns>)~khtGJT6EPj<7yeAkLhDaQB05Zqs`~YtI=+8k(
z0$9n2^o9UZS9qYkH{@aj7cqZ?#)3D*BP>K@3b$yF2Qsld@Xy4+W(fIuT2>dfGl~dI
zhKTc`E)3^~&>Lf=-IG0JXS2!wuXGF(4RGJVhJbcZ&-C3PC=6m`an_oKSIuQnGgq~B
zN>vOKKMW_-CR3)}KE`M;2jWC-_jo^^$tJgC!36Dm_>ibxgD_BnJ>5ANkfEj1L*WYd
zt%HRDZSREqfn)v&5dpN_-s#=fj{2r2rE5GWA|L*SCs0VegI;Vp(W;BaJ$`=rDy1xu
zwQiN<na+!XC9hPo!5Ug+8_7IuvFLq&Eq^y@F!)<l)MoHX-PD6G+Rawuw$x(qb-RTr
zN9S!(38<lMb<OjpHnKLUH=+t4GnQPyI=lt<ybx^Bm@8;aUD)FT&hskMn)CO2tdPw|
z$Oh|?(3l?5$Vq5KyW@SZV|w{qnW&MiEvQeSf!l1H(jNGorD?o=Vr2X>0BY`2(mTR?
zJ5%#lw^)<6=&K7(e}uF26Tpj2Gs8*4!7~Lw^K~WVb_f(4&}PFz)Idw!hp7rfSC2rX
z?j0J@blB7fb!06+25XJb2qYZS?r=X@#GXcY0BYDW&WD)uO(WV0+X?5tv{^O&QTM=y
zTA)Cb*7>lQNawPuX4-g_Kw%%D5uPr4J~3#Gy@*C`6eh79O_L$yTr@e%wYfb(`==-#
zfMEB>b8|M;0DCZBHIr5dlqGP<K(SmF+CcGm>#u%T+l$67afb;8W+NJ+FUB0d#QFBt
N^q>&tH*t^s{{Z#1VUqv=

literal 0
HcmV?d00001

diff --git a/channel/wechat/wechat_channel.py b/channel/wechat/wechat_channel.py
new file mode 100644
index 0000000..bcae08e
--- /dev/null
+++ b/channel/wechat/wechat_channel.py
@@ -0,0 +1,39 @@
+"""
+wechat channel
+"""
+import itchat
+import time
+import random
+import json
+from itchat.content import *
+from channel.channel import Channel
+
+
+@itchat.msg_register([TEXT])
+def handler_receive_msg(msg):
+    WechatChannel().handle(msg)
+
+
+class WechatChannel(Channel):
+    def __init__(self):
+        pass
+
+    def startup(self):
+        # login by scan QRCode
+        itchat.auto_login()
+
+        # start message listener
+        itchat.run()
+
+    def handle(self, msg):
+        print("handle: ", msg)
+        print(json.dumps(msg, ensure_ascii=False))
+        from_user_id = msg['FromUserName']
+        other_user_id = msg['User']['UserName']
+        if from_user_id == other_user_id:
+            self.send(super().build_reply_content(msg['Text']), from_user_id)
+
+    def send(self, msg, receiver):
+        time.sleep(random.randint(1, 3))
+        print(msg, receiver)
+        itchat.send(msg + " [bot]", toUserName=receiver)