feat(dodo.py): [M] add logger; 缓存event_id避免重复发送消息
[M] add logger; 缓存event_id避免重复发送消息 Signed-off-by: Ching <loooching@gmail.com>
This commit is contained in:
parent
a8fff9c533
commit
78ef05b68e
@ -30,3 +30,4 @@ ua-parser==0.10.0
|
|||||||
user-agents==2.2.0
|
user-agents==2.2.0
|
||||||
wcwidth==0.2.5
|
wcwidth==0.2.5
|
||||||
zipp==3.5.0
|
zipp==3.5.0
|
||||||
|
redis==4.1.0
|
||||||
|
|||||||
@ -9,16 +9,16 @@ import base64
|
|||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
from mastodon import Mastodon
|
from mastodon import Mastodon
|
||||||
import logging
|
import logging
|
||||||
|
import redis
|
||||||
# from utils import get_tenant_access_token, isreciept
|
import requests
|
||||||
# from Function import *
|
import time
|
||||||
# from Private import APP_VERIFICATION_TOKEN
|
|
||||||
|
|
||||||
APP_VERIFICATION_TOKEN = 'uKQQiOVMYg2cTgrjkyBmodrHTUaCXzG3'
|
APP_VERIFICATION_TOKEN = 'uKQQiOVMYg2cTgrjkyBmodrHTUaCXzG3'
|
||||||
APP_ID = 'cli_a115fe8b83f9100c'
|
APP_ID = 'cli_a115fe8b83f9100c'
|
||||||
APP_SECRET = 'yuSQenId0VfvwdZ3qL9wMd8FpCMEUL0u'
|
APP_SECRET = 'yuSQenId0VfvwdZ3qL9wMd8FpCMEUL0u'
|
||||||
ENCRYPT_KEY = '4XfjcA5xou3pztBD4g5V7dgHtr0BBYDE'
|
ENCRYPT_KEY = '4XfjcA5xou3pztBD4g5V7dgHtr0BBYDE'
|
||||||
EVENT_TYPE = ['im.message.receive_v1']
|
EVENT_TYPE = ['im.message.receive_v1']
|
||||||
|
ADD_GROUP_NAME = True
|
||||||
|
|
||||||
logging.basicConfig(filename='/root/develop/log/dodo.log', level=logging.INFO)
|
logging.basicConfig(filename='/root/develop/log/dodo.log', level=logging.INFO)
|
||||||
logger = logging.getLogger('/root/develop/log/dodo.log')
|
logger = logging.getLogger('/root/develop/log/dodo.log')
|
||||||
@ -28,6 +28,9 @@ mastodon = Mastodon(
|
|||||||
api_base_url = 'https://nofan.xyz'
|
api_base_url = 'https://nofan.xyz'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
|
||||||
|
redis_cli = redis.Redis(host='localhost', port=6379, decode_responses=True)
|
||||||
|
|
||||||
class AESCipher(object):
|
class AESCipher(object):
|
||||||
def __init__(self, key):
|
def __init__(self, key):
|
||||||
self.bs = AES.block_size
|
self.bs = AES.block_size
|
||||||
@ -50,6 +53,9 @@ class AESCipher(object):
|
|||||||
return self.decrypt(enc).decode('utf8')
|
return self.decrypt(enc).decode('utf8')
|
||||||
|
|
||||||
def get_tenant_access_token(): # 获取token
|
def get_tenant_access_token(): # 获取token
|
||||||
|
token = redis_cli.get('tenant_access_token_%s' % APP_ID)
|
||||||
|
if token:
|
||||||
|
return token
|
||||||
|
|
||||||
url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/"
|
url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/"
|
||||||
headers = {
|
headers = {
|
||||||
@ -65,16 +71,42 @@ def get_tenant_access_token(): # 获取token
|
|||||||
try:
|
try:
|
||||||
response = request.urlopen(req)
|
response = request.urlopen(req)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e.read().decode())
|
logger.error('get tenant token error: %s', e.read().decode())
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
rsp_body = response.read().decode('utf-8')
|
rsp_body = response.read().decode('utf-8')
|
||||||
rsp_dict = json.loads(rsp_body)
|
rsp_dict = json.loads(rsp_body)
|
||||||
code = rsp_dict.get("code", -1)
|
code = rsp_dict.get("code", -1)
|
||||||
if code != 0:
|
if code != 0:
|
||||||
print("get tenant_access_token error, code =", code)
|
logger.error("get tenant_access_token error, code =%s", code)
|
||||||
return ""
|
return ""
|
||||||
return rsp_dict.get("tenant_access_token", "")
|
token = redis_cli.set('tenant_access_token_%s' % APP_ID,
|
||||||
|
rsp_dict.get("tenant_access_token", ""),
|
||||||
|
ex=60*30)
|
||||||
|
|
||||||
|
return token
|
||||||
|
|
||||||
|
def get_group_name(chat_id):
|
||||||
|
group_name = redis_cli.get('group_name_%s' % chat_id)
|
||||||
|
if not group_name:
|
||||||
|
url = "https://open.feishu.cn/open-apis/im/v1/chats/"
|
||||||
|
headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": "Bearer " + get_tenant_access_token()
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
resp = requests.get(url+chat_id, headers=headers)
|
||||||
|
resp_data = resp.json()
|
||||||
|
code = resp_data.get("code", -1)
|
||||||
|
if code == 0:
|
||||||
|
group_name = resp_data.get('data', {}).get('name')
|
||||||
|
redis_cli.set('group_name_%s' % chat_id,
|
||||||
|
group_name,
|
||||||
|
ex=60*60*24)
|
||||||
|
except:
|
||||||
|
# todo: log
|
||||||
|
return
|
||||||
|
return group_name
|
||||||
|
|
||||||
|
|
||||||
class RequestHandler(BaseHTTPRequestHandler):
|
class RequestHandler(BaseHTTPRequestHandler):
|
||||||
@ -84,15 +116,14 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|||||||
obj = json.loads(req_body.decode("utf-8"))
|
obj = json.loads(req_body.decode("utf-8"))
|
||||||
cipher = AESCipher(ENCRYPT_KEY)
|
cipher = AESCipher(ENCRYPT_KEY)
|
||||||
obj = json.loads(cipher.decrypt_string(obj['encrypt']))
|
obj = json.loads(cipher.decrypt_string(obj['encrypt']))
|
||||||
print(req_body)
|
logger.info('lark request body: %s', obj)
|
||||||
print(obj)
|
|
||||||
|
|
||||||
# 校验 verification token 是否匹配,token 不匹配说明该回调并非来自开发平台
|
# 校验 verification token 是否匹配,token 不匹配说明该回调并非来自开发平台
|
||||||
token = obj.get("token", "")
|
token = obj.get("token", "")
|
||||||
if not token:
|
if not token:
|
||||||
token = obj.get('header', {}).get('token', '')
|
token = obj.get('header', {}).get('token', '')
|
||||||
if token != APP_VERIFICATION_TOKEN:
|
if token != APP_VERIFICATION_TOKEN:
|
||||||
print("verification token not match, token =", token)
|
logger.error("verification token not match, token =%s", token)
|
||||||
self.response("")
|
self.response("")
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -104,10 +135,15 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|||||||
self.handle_request_url_verify(obj)
|
self.handle_request_url_verify(obj)
|
||||||
elif type in EVENT_TYPE: # 事件回调
|
elif type in EVENT_TYPE: # 事件回调
|
||||||
# 获取事件内容和类型,并进行相应处理,此处只关注给机器人推送的消息事件
|
# 获取事件内容和类型,并进行相应处理,此处只关注给机器人推送的消息事件
|
||||||
|
event_id = obj.get('header', {}).get('event_id', '')
|
||||||
|
# 重复收到的事件不处理
|
||||||
|
if event_id and redis_cli.get(event_id):
|
||||||
|
self.response("")
|
||||||
|
return
|
||||||
event = obj.get("event")
|
event = obj.get("event")
|
||||||
if event.get("message"):
|
if event.get("message"):
|
||||||
self.handle_message(event)
|
self.handle_message(event, event_id)
|
||||||
return
|
return
|
||||||
return
|
return
|
||||||
|
|
||||||
def handle_request_url_verify(self, post_obj):
|
def handle_request_url_verify(self, post_obj):
|
||||||
@ -117,7 +153,7 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|||||||
self.response(json.dumps(rsp))
|
self.response(json.dumps(rsp))
|
||||||
return
|
return
|
||||||
|
|
||||||
def handle_message(self, event):
|
def handle_message(self, event, event_id=None):
|
||||||
# 此处只处理 text 类型消息,其他类型消息忽略
|
# 此处只处理 text 类型消息,其他类型消息忽略
|
||||||
msg = event.get('message', {})
|
msg = event.get('message', {})
|
||||||
msg_type = msg.get("message_type", "")
|
msg_type = msg.get("message_type", "")
|
||||||
@ -135,6 +171,9 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|||||||
for mention in msg.get('mentions'):
|
for mention in msg.get('mentions'):
|
||||||
text = text.replace(mention['key'], '')
|
text = text.replace(mention['key'], '')
|
||||||
text = text.lstrip()
|
text = text.lstrip()
|
||||||
|
if ADD_GROUP_NAME:
|
||||||
|
group_name = get_group_name(msg.get("chat_id"))
|
||||||
|
text = '%s #%s' % (text, group_name)
|
||||||
else:
|
else:
|
||||||
open_id = {"open_id": event.get("sender", {}).get(
|
open_id = {"open_id": event.get("sender", {}).get(
|
||||||
'sender_id', {}).get('open_id')}
|
'sender_id', {}).get('open_id')}
|
||||||
@ -143,8 +182,14 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|||||||
toot_resp = mastodon.status_post(text)
|
toot_resp = mastodon.status_post(text)
|
||||||
if toot_resp.get('id'):
|
if toot_resp.get('id'):
|
||||||
self.msg_compoment(access_token, open_id, '📟 dodo 📟')
|
self.msg_compoment(access_token, open_id, '📟 dodo 📟')
|
||||||
except:
|
redis_cli.set(event_id, int(time.time()), ex=60*60*7)
|
||||||
pass
|
else:
|
||||||
|
self.msg_compoment(access_token, open_id, """⚠️ didi ⚠️
|
||||||
|
%s
|
||||||
|
""" % json.loads(toot_resp))
|
||||||
|
except Exception as exc:
|
||||||
|
logger.error('send toot error: %s', str(exc))
|
||||||
|
|
||||||
return
|
return
|
||||||
elif msg_type == "image":
|
elif msg_type == "image":
|
||||||
self.response("")
|
self.response("")
|
||||||
@ -175,14 +220,16 @@ class RequestHandler(BaseHTTPRequestHandler):
|
|||||||
try:
|
try:
|
||||||
response = request.urlopen(req)
|
response = request.urlopen(req)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e.read().decode())
|
logger.error('send message error: %s', e.read().decode())
|
||||||
return
|
return
|
||||||
|
|
||||||
rsp_body = response.read().decode('utf-8')
|
rsp_body = response.read().decode('utf-8')
|
||||||
rsp_dict = json.loads(rsp_body)
|
rsp_dict = json.loads(rsp_body)
|
||||||
code = rsp_dict.get("code", -1)
|
code = rsp_dict.get("code", -1)
|
||||||
if code != 0:
|
if code != 0:
|
||||||
print("send message error, code = ", code, ", msg =", rsp_dict.get("msg", ""))
|
logger.error("send message error, code = %s, msg =%s",
|
||||||
|
code,
|
||||||
|
rsp_dict.get("msg", ""))
|
||||||
|
|
||||||
def msg_compoment(self, token, open_id, text):
|
def msg_compoment(self, token, open_id, text):
|
||||||
self.send_message(token, open_id, text)
|
self.send_message(token, open_id, text)
|
||||||
@ -191,7 +238,7 @@ def run():
|
|||||||
port = 5000
|
port = 5000
|
||||||
server_address = ('', port)
|
server_address = ('', port)
|
||||||
httpd = HTTPServer(server_address, RequestHandler)
|
httpd = HTTPServer(server_address, RequestHandler)
|
||||||
print("start.....")
|
logger.info("start...")
|
||||||
httpd.serve_forever()
|
httpd.serve_forever()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user