From bfffdf48fc28ffd583cba278fa9679e2a14dcb1d Mon Sep 17 00:00:00 2001 From: AKW <2497744746@qq.com> Date: Thu, 14 Dec 2023 18:43:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=9E=E8=B0=83=E5=9C=B0=E5=9D=80=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jqr/serializers.py | 72 ++++++++++++++++++++++++++++-- apps/jqr/tasks.py | 91 +++++++++++++++++++++++++++++++++++--- apps/jqr/views.py | 30 ++++++------- apps/qc/models.py | 35 ++++++++++++--- libs/wechat/worker.py | 2 +- yzk_wechat_event/celery.py | 3 ++ 6 files changed, 203 insertions(+), 30 deletions(-) diff --git a/apps/jqr/serializers.py b/apps/jqr/serializers.py index 38d3b36..3376f62 100644 --- a/apps/jqr/serializers.py +++ b/apps/jqr/serializers.py @@ -2,6 +2,7 @@ import base64 from rest_framework import serializers +from apps.jqr.tasks import save_add_contact, delete_add_contact, edit_add_contact from libs.weworkapi.callback.WXBizMsgCrypt3 import WXBizMsgCrypt, Prpcrypt from utils.tools import sha1_encoder, get_attribute, camel_to_snake import xml.etree.cElementTree as ET @@ -50,8 +51,9 @@ class WechatEncryptSerializer(serializers.Serializer): data = self.parse_xml(xmltext) print(data) event = data.get('event') - change_type = data.get('change_type') - event_handler = getattr(self, f'handle_{event}_{change_type}', None) + changetype = data.get('changetype') + event_handler = getattr(self, f'handle_{event}_{changetype}', None) + print(f'handle_{event}_{changetype}') if event_handler: event_handler(data) return {} @@ -75,17 +77,79 @@ class WechatEncryptSerializer(serializers.Serializer): for child in xml_tree: tag = child.tag key = camel_to_snake(tag) - data[key] = get_attribute(xml_tree.find(key), 'text') + key = ''.join(key.split('_')) + data[key] = get_attribute(xml_tree.find(tag), 'text') return data def handle_change_external_contact_add_external_contact(self, data): """ 处理添加企业客户事件 """ + print('添加客户事件') + corp = self.context.get('corp') + data.pop('tousername') + data['corpid'] = corp.corpid + data['agentid'] = corp.agentid + data['uid'] = corp.uid print(data) + save_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret'])) def handle_change_external_contact_edit_external_contact(self, data): """ 处理编辑企业客户事件 """ - pass + print('编辑客户事件') + corp = self.context.get('corp') + data.pop('tousername') + data['corpid'] = corp.corpid + data['agentid'] = corp.agentid + data['uid'] = corp.uid + print(data) + edit_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret'])) + + def handle_change_external_contact_add_half_external_contact(self, data): + """ + 处理外部联系人免验证添加成员事件 + """ + print('外部联系人免验证添加成员事件') + corp = self.context.get('corp') + data.pop('tousername') + data['corpid'] = corp.corpid + data['agentid'] = corp.agentid + data['uid'] = corp.uid + print(data) + save_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret'])) + + def handle_change_external_contact_del_follow_user(self, data): + """ + 处理删除跟进成员事件 (客户删我们) + """ + print('删除跟进成员事件') + corp = self.context.get('corp') + data.pop('tousername') + data['corpid'] = corp.corpid + data['agentid'] = corp.agentid + data['uid'] = corp.uid + print(data) + delete_add_contact.delay(data, corp.to_dict(['corpid', 'appsecret'])) + + def handle_change_external_chat_create(self, data): + """ + 处理客户群创建事件 + """ + print('客户群创建事件') + print(data) + + def handle_change_external_chat_update(self, data): + """ + 处理客户群更新事件 + """ + print('客户群更新事件') + print(data) + + def handle_change_external_chat_dismiss(self, data): + """ + 处理客户群解散事件 + """ + print('客户群解散事件') + print(data) diff --git a/apps/jqr/tasks.py b/apps/jqr/tasks.py index ee1f0c0..f77144f 100644 --- a/apps/jqr/tasks.py +++ b/apps/jqr/tasks.py @@ -1,11 +1,92 @@ from celery import shared_task +from datetime import datetime import logging +from apps.jqr.choices import JqrWechatbizuserinfoDeleteTypeChoices, JqrAddTypeChoices +from apps.qc.choices import QcWechatbizeventAddcontactIsDeleteChoices +from apps.qc.models import QcWechatbizeventAddcontact +from apps.jqr.models import JqrExternalFollowUser, JqrExternalUser +from libs.wechat import WechatWorkerUtil + logger = logging.getLogger('apps') -@shared_task(name='save_add_contact') -def save_add_contact(*args, **kwargs): - logger.info('save_add_contact') - while True: - pass +@shared_task(name='save_add_contact', queue='contact') +def save_add_contact(data, corpinfo, *args, **kwargs): + state = data.get('state') + if state and state.startswith('mg'): + [_, _, qrcodeid] = state.split('_') + data['qrcodeid'] = qrcodeid + # TODO 处理我们自己的活码 + userid = data.get('userid') + externaluserid = data.get('externaluserid') + corpid = data.get('corpid') + QcWechatbizeventAddcontact.objects.update_or_create( + userid=userid, + externaluserid=externaluserid, + corpid=corpid, + defaults={ + **data, + 'isdelete': QcWechatbizeventAddcontactIsDeleteChoices.NOT_DELETE, + 'deletetime': None + } + ) + edit_add_contact.delay(data, corpinfo, *args, **kwargs) + + +@shared_task(name='edit_add_contact', queue='contact') +def edit_add_contact(data, corpinfo, *args, **kwargs): + # 更新 关系表 + externaluserid = data.get('externaluserid') + corpid = corpinfo.get('corpid') + appsecret = corpinfo.get('appsecret') + wechat_worker = WechatWorkerUtil(corpid, appsecret) + cursor = '' + while cursor is not None: + success, data = wechat_worker.get_external_contact(externaluserid, cursor=cursor) + if not success: + logger.error(f'获取外部联系人信息失败,{data}') + return + (external_contact, follow_user, cursor) = data + JqrExternalUser.objects.update_or_create( + corpid=corpid, + external_userid=externaluserid, + defaults={ + **external_contact, + 'addtype': JqrAddTypeChoices.EVENT_CALLBACK, + 'deletetype': None, + 'dtime': None + } + ) + for follow_info in follow_user: + userid = follow_info.get('userid') + follow_info['tags'] = [tag.get('tag_id') for tag in follow_info.get('tags', [])] + JqrExternalFollowUser.objects.update_or_create( + userid=userid, + corpid=corpid, + external_userid=externaluserid, + defaults={ + **follow_info, + 'addtype': JqrAddTypeChoices.EVENT_CALLBACK, + 'deletetype': None, + 'dtime': None + } + ) + + +@shared_task(name='delete_add_contact', queue='contact') +def delete_add_contact(data, corpinfo, *args, **kwargs): + userid = data.get('userid') + externaluserid = data.get('externaluserid') + corpid = data.get('corpid') + agentid = data.get('agentid') + # 更新add_contact 表删除字段 + QcWechatbizeventAddcontact.objects.filter(userid=userid, externaluserid=externaluserid, corpid=corpid, + agentid=agentid).update( + isdelete=QcWechatbizeventAddcontactIsDeleteChoices.DELETED, + deletetime=datetime.now() + ) + JqrExternalFollowUser.objects.filter(userid=userid, external_userid=externaluserid, corpid=corpid).update( + deletetype=JqrWechatbizuserinfoDeleteTypeChoices.EVENT_CALLBACK, + dtime=datetime.now() + ) diff --git a/apps/jqr/views.py b/apps/jqr/views.py index fe852be..0c10143 100644 --- a/apps/jqr/views.py +++ b/apps/jqr/views.py @@ -15,13 +15,13 @@ class WechatWorkerViewSet(viewsets.GenericViewSet): @action(methods=['GET'], detail=False, serializer_class=WechatPublicTokenSerializer, url_path=r'callback/(?P\w+)', ) def verify(self, request, path, *args, **kwargs): - if not settings.DEBUG: - params = request.query_params - # cbtest.xbtool.cn - url = f'https://46i859447w.yicp.fun/event/callback/{path}' - res = requests.get(url, params=params) - data = res.text - return Response(data=int(data)) + # if not settings.DEBUG: + # params = request.query_params + # # cbtest.xbtool.cn + # url = f'https://46i859447w.yicp.fun/event/callback/{path}' + # res = requests.get(url, params=params) + # data = res.text + # return Response(data=int(data)) [business, corpid, agentid, uid] = path.split('_') corp = QcCorpinfo.objects.get(corpid=corpid, agentid=agentid, uid=uid) @@ -35,14 +35,14 @@ class WechatWorkerViewSet(viewsets.GenericViewSet): @verify.mapping.post def message(self, request, path, *args, **kwargs): - if not settings.DEBUG: - data = request.data - # cbtest.xbtool.cn - renderer = WechatPublicContentRenderer() - data = renderer.render(data) - url = f'https://46i859447w.yicp.fun/event/callback/{path}' - res = requests.post(url, data=data, headers={'Content-Type': 'text/xml'}) - return Response(data=res.json()) + # if not settings.DEBUG: + # data = request.data + # # cbtest.xbtool.cn + # renderer = WechatPublicContentRenderer() + # data = renderer.render(data) + # url = f'https://46i859447w.yicp.fun/event/callback/{path}' + # res = requests.post(url, data=data, headers={'Content-Type': 'text/xml'}) + # return Response(data=res.json()) [business, corpid, agentid, uid] = path.split('_') corp = QcCorpinfo.objects.get(corpid=corpid, agentid=agentid, uid=uid) context = self.get_serializer_context() diff --git a/apps/qc/models.py b/apps/qc/models.py index 1f6ba87..7d936b2 100644 --- a/apps/qc/models.py +++ b/apps/qc/models.py @@ -34,6 +34,30 @@ class QcCorpinfo(models.Model): ordering = ['-ctime'] unique_together = ('agentid', 'corpid', 'uid', 'business_type') + def to_dict(self, fields=None): + if fields: + return { + field: getattr(self, field) + for field in fields + } + return { + 'id': self.id, + 'uid': self.uid, + 'corpname': self.corpname, + 'corpid': self.corpid, + 'agentid': self.agentid, + 'appsecret': self.appsecret, + 'token': self.token, + 'encodingaeskey': self.encodingaeskey, + 'ctime': self.ctime, + 'utime': self.utime, + 'callbackstatus': self.callbackstatus, + 'callback_validate_time': self.callback_validate_time, + 'business_type': self.business_type, + 'taggroupid': self.taggroupid, + 'settletaggroupid': self.settletaggroupid, + } + class QcQrcodes(models.Model): id = models.BigAutoField(primary_key=True) @@ -114,11 +138,12 @@ class QcWechatbizeventAddcontact(models.Model): isdelete = models.IntegerField(default=QcWechatbizeventAddcontactIsDeleteChoices.NOT_DELETE, verbose_name="是否删除", choices=QcWechatbizeventAddcontactIsDeleteChoices.choices) deletetime = models.DateTimeField(null=True, verbose_name="删除时间") - qrcodeid = models.IntegerField(verbose_name='二维码id') - hook_starttime = models.DateTimeField(null=True, verbose_name="hook最近一次启动时间", blank=True) - hook_wstime = models.DateTimeField(null=True, verbose_name="hook最近一次websocket首发消息时间", blank=True) - hook_connecttime = models.DateTimeField(null=True, verbose_name="hook最近一次通信时间", blank=True) - isfirststart = models.BooleanField(verbose_name="是否首次启动", null=True, blank=True) + qrcodeid = models.IntegerField(verbose_name='二维码id', default=0) + + # hook_starttime = models.DateTimeField(null=True, verbose_name="hook最近一次启动时间", blank=True) + # hook_wstime = models.DateTimeField(null=True, verbose_name="hook最近一次websocket首发消息时间", blank=True) + # hook_connecttime = models.DateTimeField(null=True, verbose_name="hook最近一次通信时间", blank=True) + # isfirststart = models.BooleanField(verbose_name="是否首次启动", null=True, blank=True) class Meta: db_table = 'qc_wechatbizevent_addcontact' diff --git a/libs/wechat/worker.py b/libs/wechat/worker.py index 1829797..2836c6c 100644 --- a/libs/wechat/worker.py +++ b/libs/wechat/worker.py @@ -143,7 +143,7 @@ class WechatWorkerUtil(object): res = requests.get(url, params=params) res = res.json() if res.get('errcode') == 0: - return True, (res.get('external_contact'), res.get('follow_user')) + return True, (res.get('external_contact'), res.get('follow_user'), res.get('next_cursor')) return False, res.get('errmsg') def get_external_contact_batch_by_user(self, userid_list, cursor='', limit=100): diff --git a/yzk_wechat_event/celery.py b/yzk_wechat_event/celery.py index 36f0b63..bbb80cd 100644 --- a/yzk_wechat_event/celery.py +++ b/yzk_wechat_event/celery.py @@ -21,6 +21,9 @@ app.conf.beat_schedule = { } task_routes = { + 'save_add_contact': 'contact', + 'edit_add_contact': 'contact', + 'delete_add_contact': 'contact', } # app.conf.task_routes = task_routes