diff --git a/apps/jqr/models.py b/apps/jqr/models.py index 44f59cf..5ecfcf6 100644 --- a/apps/jqr/models.py +++ b/apps/jqr/models.py @@ -50,8 +50,7 @@ class JqrHookUser(models.Model): time_qun = models.BooleanField(default=True, verbose_name='定时群聊开关') time_private = models.BooleanField(default=True, verbose_name='定时私聊开关') time_quan = models.BooleanField(default=True, verbose_name='定时朋友圈开关') - hook_time = models.DateTimeField( - null=True, blank=True, verbose_name='hook时间') + keyword = models.BooleanField(default=True, verbose_name='关键字回复开关') utime = models.DateTimeField(verbose_name='更新时间', null=True, blank=True) name = models.CharField( max_length=255, verbose_name='用户名', null=True, blank=True) @@ -69,6 +68,9 @@ class JqrHookUser(models.Model): verbose_name='对外展示信息', null=True, blank=True) qrcode = models.CharField( max_length=255, verbose_name='二维码', null=True, blank=True) + 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) class Meta: unique_together = ('corpid', 'userid', 'vid') diff --git a/apps/jqr/serializers.py b/apps/jqr/serializers.py index 3376f62..7a60c34 100644 --- a/apps/jqr/serializers.py +++ b/apps/jqr/serializers.py @@ -2,9 +2,11 @@ import base64 from rest_framework import serializers +from apps.jqr.models import JqrHookUser 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 +from utils.base_serializer import BaseSerializer import xml.etree.cElementTree as ET @@ -153,3 +155,11 @@ class WechatEncryptSerializer(serializers.Serializer): """ print('客户群解散事件') print(data) + + +class HeartBeatSerializer(BaseSerializer): + HookStartData = serializers.DateTimeField(source='') + + class Meta: + model = JqrHookUser + fields = '__all__' diff --git a/apps/jqr/tasks.py b/apps/jqr/tasks.py index b28f246..e3048ee 100644 --- a/apps/jqr/tasks.py +++ b/apps/jqr/tasks.py @@ -40,9 +40,12 @@ def save_add_contact(data, corpinfo, *args, **kwargs): qrcodeid = data.get('qrcodeid') if qrcodeid: check_qrcode.delay(qrcodeid, userid, corpinfo) - tag_remark_contact.delay(qrcodeid, userid, externaluserid, corpinfo) alarm_userid_by_qrcodeid.delay(qrcodeid) - edit_add_contact.delay(data, corpinfo, *args, **kwargs) + # 打标签备注 + tag_remark_contact(qrcodeid, userid, externaluserid, corpinfo) + # 修复客户关系 + edit_add_contact(data, corpinfo, *args, **kwargs) + # TODO 请求API 发送消息 @shared_task(name='edit_add_contact', queue='contact') diff --git a/apps/jqr/urls.py b/apps/jqr/urls.py index 6fe0bfb..8cdfea9 100644 --- a/apps/jqr/urls.py +++ b/apps/jqr/urls.py @@ -3,5 +3,6 @@ from . import views router = SimpleRouter(trailing_slash=False) router.register('event', views.WechatWorkerViewSet, basename='wechat-worker') +router.register('hook/client', views.HookClientController, basename='hook-client') urlpatterns = router.urls diff --git a/apps/jqr/views.py b/apps/jqr/views.py index 0c10143..5ee076a 100644 --- a/apps/jqr/views.py +++ b/apps/jqr/views.py @@ -8,6 +8,7 @@ from apps.jqr.parsers import WechatContentParser from apps.jqr.renderers import WechatPublicContentRenderer from apps.jqr.serializers import WechatPublicTokenSerializer, WechatEncryptSerializer from apps.qc.models import QcCorpinfo +from utils.base_viewsets import BaseViewSet class WechatWorkerViewSet(viewsets.GenericViewSet): @@ -61,3 +62,16 @@ class WechatWorkerViewSet(viewsets.GenericViewSet): if self.request.method == 'POST': return [WechatPublicContentRenderer()] return super().get_renderers() + + +class HookClientController(BaseViewSet): + permission_classes = [] + authentication_classes = [] + + @action(methods=['post'], detail=False, url_path='heartbeat') + def heartbeat(self, request, *args, **kwargs): + pass + + @action(methods=['post'], detail=False, url_path='pushmsg') + def pushmsg(self, request, *args, **kwargs): + pass diff --git a/apps/system/__init__.py b/apps/system/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/system/admin.py b/apps/system/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/apps/system/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/system/apps.py b/apps/system/apps.py new file mode 100644 index 0000000..b6e1e55 --- /dev/null +++ b/apps/system/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class SystemConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'apps.system' diff --git a/apps/system/choices.py b/apps/system/choices.py new file mode 100644 index 0000000..f2f25e1 --- /dev/null +++ b/apps/system/choices.py @@ -0,0 +1,76 @@ +from django.db import models + + +class PaymentType(models.IntegerChoices): + YFD = 1, '云发单' + JFJC = 2, '接粉检测' + ALIVE_ACTIVITY_PAGE = 3, '活动单页(活)' + DEAD_ACTIVITY_PAGE = 4, '活动单页(死)' + + +class PaymentActivityType(models.IntegerChoices): + ELM = 1, 'elm' + ALIPAY = 2, '支付宝' + COMPLAINT_PAGE = 3, '投诉页' + + +class ActivityType(models.IntegerChoices): + ELM = 1, 'elm赏金' + ALIPAY = 2, '支付宝' + COMPLAINT_PAGE = 3, '投诉页' + MIDDLE_PAGE = 4, '中间页' + + +class ActivityLinkType(models.IntegerChoices): + DEAD = 0, '死链接' + ALIVE = 1, '活链接' + + +class AuthorizationPlatformType(models.IntegerChoices): + # ALIPAY = 1, '支付宝' + ELM = 2, '饿了么' + MT = 3, '美团' + TB = 4, '淘宝' + PDD = 5, '拼多多' + JD = 6, '京东' + + +class AuthorizationType(models.IntegerChoices): + COOKIE = 1, '插件模拟登录' + APP_SECRET = 2, 'app_secret' + AUTHORIZATION = 3, '账号授权' + + +class DomainBusinessType(models.IntegerChoices): + SHORT_CHAIN = 1, '短链' + LANDING_PAGE = 2, '落地页' + QUICK_CODE = 3, '快码' + + +class DomainType(models.IntegerChoices): + QUICK_CODE = 1, '快码' + SELF_BIND = 2, '自己绑定' + QUICK_STATION = 3, '快站' + + +class QuickCodeCreateMethodType(models.IntegerChoices): + PROGRAM = 1, '程序生成' + MANUAL = 2, '人工生成' + MANUAL_COPY = 3, '手动复制' + + +class QuickCodeType(models.IntegerChoices): + OFFICIAL = 1, '官方' + PRIVATE = 2, '自己' + + +class AuthorizationCookieCheckResultChoices(models.IntegerChoices): + FAIL = 0, '检测失败' + SUCCESS = 1, '检测成功' + + +class DbEnum(models.TextChoices): + XBTOOL = 'xbtool', '小程序工具' + HDY = 'hdy', '活动页' + QWHM = 'qwhm', '企微活码' + QWJQR = 'qwjqr', '企微机器人' diff --git a/apps/system/migrations/__init__.py b/apps/system/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/system/models.py b/apps/system/models.py new file mode 100644 index 0000000..66286e8 --- /dev/null +++ b/apps/system/models.py @@ -0,0 +1,240 @@ +import uuid + +from .choices import * +from apps.user.models import User + + +class PaymentRecord(models.Model): + user = models.ForeignKey( + User, on_delete=models.DO_NOTHING, verbose_name="用户", db_constraint=False, related_name='payment_records') + pay_type = models.IntegerField( + choices=PaymentType.choices, verbose_name="付费类型") + activity_type = models.IntegerField( + choices=PaymentActivityType.choices, verbose_name="活动类型") + pay_amount = models.IntegerField(verbose_name="付费金额") + pay_time = models.DateTimeField(verbose_name="付费时间") + expire_time = models.DateTimeField(verbose_name="到期时间") + create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") + update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间") + + class Meta: + db_table = "py_payment_record" + verbose_name = "付费记录" + verbose_name_plural = verbose_name + ordering = ['-create_time'] + + +class Activity(models.Model): + user = models.ForeignKey( + User, on_delete=models.DO_NOTHING, verbose_name="用户", db_constraint=False, related_name='activities', + db_index=True) + template = models.ForeignKey('Activity', + on_delete=models.DO_NOTHING, verbose_name="模板", db_constraint=False, + related_name='children', null=True, blank=True) + title = models.CharField(max_length=100, verbose_name="标题") + remark = models.TextField(verbose_name="备注", null=True, blank=True) + create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") + update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间") + pv = models.IntegerField(verbose_name="pv", default=0) + # business_domain = models.ForeignKey('Domain', to_field='domain', db_constraint=False, on_delete=models.DO_NOTHING, + # verbose_name='业务域名', related_name='business_activities', null=True, + # blank=True, + # db_column='business_domain') + # short_chain_domain = models.ForeignKey('Domain', to_field='domain', db_constraint=False, + # on_delete=models.DO_NOTHING, null=True, blank=True, + # verbose_name='短链域名', related_name='short_chain_activities', + # db_column='short_chain_domain') + domain = models.ForeignKey('Domain', db_constraint=False, on_delete=models.DO_NOTHING, + verbose_name='业务域名', related_name='activities', null=True, blank=True) + business_domain = models.CharField( + max_length=100, verbose_name="业务域名", null=True, blank=True) + short_chain_domain = models.CharField( + max_length=100, verbose_name="短链域名", null=True, blank=True) + activity_type = models.IntegerField(choices=ActivityType.choices, + verbose_name="活动类型") + link_type = models.IntegerField(choices=ActivityLinkType.choices, + verbose_name="链接类型") + is_top = models.BooleanField(default=False, verbose_name="是否置顶") + create_json = models.JSONField( + verbose_name="创建json", null=True, blank=True) + request_json = models.JSONField( + verbose_name="请求json", null=True, blank=True) + response_json = models.JSONField( + verbose_name="响应json", null=True, blank=True) + platform_id = models.IntegerField( + verbose_name="平台id", null=True, blank=True) + is_quick_code = models.BooleanField(default=False, verbose_name="是否是快码") + is_delete = models.BooleanField(default=False, verbose_name="是否删除") + corpid = models.CharField(max_length=32, verbose_name="企业微信corpid", null=True, blank=True) + externaluserid = models.CharField( + max_length=32, verbose_name="外部联系人id", null=True, blank=True) + tklexpiretime = models.DateTimeField( + verbose_name="淘口令过期时间", null=True, blank=True) + + class Meta: + db_table = 'py_activity' + verbose_name = '活动表' + ordering = ['-create_time'] + + def add_activity_history(self): + activity_history = ActivityHistory() + activity_history.activity = self + for field in self._meta.fields: + if field.name in ['id']: + continue + + if hasattr(activity_history, field.name): + setattr(activity_history, field.name, getattr(self, field.name)) + activity_history.save() + + +class ActivityHistory(models.Model): + activity = models.ForeignKey('Activity', + on_delete=models.DO_NOTHING, verbose_name="活动", db_constraint=False, + related_name='history') + user = models.ForeignKey( + User, on_delete=models.DO_NOTHING, verbose_name="用户", db_constraint=False, related_name='history_activities', + db_index=True) + template = models.ForeignKey('Activity', + on_delete=models.DO_NOTHING, verbose_name="模板", db_constraint=False, + related_name='history_templates', null=True, blank=True) + title = models.CharField(max_length=100, verbose_name="标题") + remark = models.TextField(verbose_name="备注", null=True, blank=True) + create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") + update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间") + pv = models.IntegerField(verbose_name="pv", default=0) + domain = models.ForeignKey('Domain', db_constraint=False, on_delete=models.DO_NOTHING, + verbose_name='业务域名', related_name='history_activities', null=True, blank=True) + business_domain = models.CharField( + max_length=100, verbose_name="业务域名", null=True, blank=True) + short_chain_domain = models.CharField( + max_length=100, verbose_name="短链域名", null=True, blank=True) + activity_type = models.IntegerField(choices=ActivityType.choices, + verbose_name="活动类型") + link_type = models.IntegerField(choices=ActivityLinkType.choices, + verbose_name="链接类型") + is_top = models.BooleanField(default=False, verbose_name="是否置顶") + create_json = models.JSONField( + verbose_name="创建json", null=True, blank=True) + request_json = models.JSONField( + verbose_name="请求json", null=True, blank=True) + response_json = models.JSONField( + verbose_name="响应json", null=True, blank=True) + platform_id = models.IntegerField( + verbose_name="平台id", null=True, blank=True) + is_quick_code = models.BooleanField(default=False, verbose_name="是否是快码") + is_delete = models.BooleanField(default=False, verbose_name="是否删除") + + class Meta: + db_table = 'py_activity_history' + verbose_name = '历史表' + ordering = ['-create_time'] + + +class Domain(models.Model): + user = models.ForeignKey( + User, on_delete=models.DO_NOTHING, verbose_name="用户", db_constraint=False, related_name='domains', + db_index=True + ) + domain = models.CharField( + max_length=100, verbose_name="域名", null=True, blank=True) + business_type = models.IntegerField( + verbose_name="业务类型", choices=DomainBusinessType.choices) + is_system = models.BooleanField(verbose_name="是否是系统", default=False) + domain_type = models.IntegerField( + verbose_name="域名类型", choices=DomainType.choices) + app_key = models.CharField( + max_length=100, verbose_name="app_key", null=True, blank=True) + secret = models.CharField( + max_length=100, verbose_name="secret", null=True, blank=True) + is_delete = models.BooleanField(default=False, verbose_name="是否删除") + create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") + update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间") + + class Meta: + db_table = 'py_domain' + verbose_name = '域名表' + ordering = ['-create_time'] + + +class Authorization(models.Model): + name = models.CharField(max_length=100, verbose_name="名称") + remark = models.TextField(verbose_name="备注", blank=True, null=True) + cookie_key = models.CharField( + verbose_name="cookie key", max_length=32, null=True, blank=True, default=lambda: uuid.uuid4().hex) + user = models.ForeignKey( + User, on_delete=models.DO_NOTHING, verbose_name="用户", db_constraint=False, related_name='authorizations', + db_index=True) + platform_type = models.IntegerField( + verbose_name="平台类型", choices=AuthorizationPlatformType.choices) + uid = models.CharField( + max_length=100, verbose_name="平台uid", null=True, blank=True) + # authorization_type = models.IntegerField( + # verbose_name="授权类型", choices=AuthorizationType.choices) + account = models.CharField( + max_length=100, verbose_name="账号", null=True, blank=True) + password = models.CharField( + max_length=100, verbose_name="密码", null=True, blank=True) + app_key_secret_info = models.JSONField( + null=True, blank=True, verbose_name="app_key_secret授权信息") + cookie_info = models.JSONField( + null=True, blank=True, verbose_name="cookie授权信息") + auth_info = models.JSONField(null=True, blank=True, verbose_name="授权信息") + is_delete = models.BooleanField(default=False, verbose_name="是否删除") + create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") + update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间") + cookie_update_time = models.DateTimeField( + null=True, blank=True, verbose_name="cookie更新时间") + auth_update_time = models.DateTimeField( + null=True, blank=True, verbose_name="授权更新时间") + app_key_secret_update_time = models.DateTimeField( + null=True, blank=True, verbose_name="授权更新时间") + cookie_warning_setting = models.IntegerField(verbose_name='cookie报警设置', null=True, blank=True) + cookie_check_result = models.IntegerField(verbose_name='cookie检测结果', null=True, blank=True, + choices=AuthorizationCookieCheckResultChoices.choices) + cookie_check_time = models.DateTimeField(verbose_name='cookie检测时间', null=True, blank=True) + + class Meta: + db_table = 'py_authorization' + verbose_name = '授权表' + ordering = ['-create_time'] + + +class ComplaintPageRecord(models.Model): + user = models.ForeignKey( + User, on_delete=models.DO_NOTHING, verbose_name="用户", db_constraint=False, + related_name='complaint_page_records', db_index=True) + activity = models.ForeignKey('Activity', on_delete=models.DO_NOTHING, + verbose_name="活动", db_constraint=False, related_name='complaint_page_records', + db_index=True) + info = models.JSONField(null=True, blank=True, verbose_name="投诉信息") + create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") + update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间") + + class Meta: + db_table = 'py_complaint_page_record' + verbose_name = '投诉页记录' + ordering = ['-create_time'] + + +class QuickCode(models.Model): + user = models.ForeignKey( + User, on_delete=models.DO_NOTHING, verbose_name="用户", db_constraint=False, + related_name='quick_codes', db_index=True) + activity = models.ForeignKey('Activity', on_delete=models.DO_NOTHING, + verbose_name="活动", db_constraint=False, related_name='quick_codes', + db_index=True) + create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") + create_method = models.IntegerField( + choices=QuickCodeCreateMethodType.choices, default=QuickCodeCreateMethodType.MANUAL, verbose_name="创建方式") + quick_code_url = models.CharField( + max_length=255, null=True, blank=True, verbose_name="快码url") + converted_url = models.CharField( + max_length=255, null=True, blank=True, verbose_name="被转链url") + quick_code_type = models.IntegerField( + choices=QuickCodeType.choices, default=QuickCodeType.OFFICIAL, verbose_name="快码类型") + + class Meta: + db_table = 'py_quick_code' + verbose_name = '快码记录' + ordering = ['-create_time'] diff --git a/apps/system/serializers.py b/apps/system/serializers.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/system/tasks.py b/apps/system/tasks.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/system/tests.py b/apps/system/tests.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/system/urls.py b/apps/system/urls.py new file mode 100644 index 0000000..2018cd6 --- /dev/null +++ b/apps/system/urls.py @@ -0,0 +1,6 @@ +from rest_framework.routers import SimpleRouter +from . import views + +router = SimpleRouter(trailing_slash=False) + +urlpatterns = router.urls diff --git a/apps/system/utils.py b/apps/system/utils.py new file mode 100644 index 0000000..c39c3e5 --- /dev/null +++ b/apps/system/utils.py @@ -0,0 +1,155 @@ +import requests +from django.conf import settings + +from apps.system.choices import ActivityType, AuthorizationPlatformType, QuickCodeCreateMethodType, QuickCodeType, \ + DbEnum +from django.core.files.storage import default_storage +from datetime import date, datetime +from apps.system.models import Authorization, Activity, QuickCode +from libs.kz import KZ +from libs.topsdk.top import TopUtils +from utils.exceptions import CustomProjectException +from utils.tools import InviteCode +from yzk.settings.constant import MiddlePageConstant + + +def get_alipay_link_by_bid(bid): + return settings.ALIPAY_ACTIVITY_LINK.format(bid) + + +def get_response_json_by_activity(activity): + activity_type = activity.activity_type + request_json = activity.request_json + data = None + if activity_type == ActivityType.ELM: + authorization_id = request_json.get('authorization_id') + authorization = Authorization.objects.get( + pk=authorization_id, platform_type=AuthorizationPlatformType.ELM) + app_key_secret_info = authorization.app_key_secret_info + appkey = app_key_secret_info.get('appkey') + secret = app_key_secret_info.get('secret') + pid = request_json.get('pid') + sid = request_json.get('sid') + activity_id = request_json.get( + 'activity_id', MiddlePageConstant.ELM_ACTIVITY_ID) + top_utils = TopUtils(appkey, secret) + response_json = top_utils.get_official_activity( + pid, activity_id, sid=sid) + activity.response_json = response_json + activity.save() + data = { + 'kl': response_json.get('link').get('eleme_word'), + 'l': response_json.get('link').get('h5_url'), + 'r': activity.title, + } + elif activity_type == ActivityType.ALIPAY: + bid = request_json.get('bid') + data = { + 'link': get_alipay_link_by_bid(bid) + } + activity.response_json = data + activity.save() + return data + + +def get_activity_by_short_chain_key(short_chain_key, select_user=False): + activity_id = InviteCode.decode(short_chain_key) + queryset = Activity.objects.filter(id=activity_id, is_delete=False) + if select_user: + queryset = queryset.select_related('user') + activity = queryset.first() + return activity + + +def create_quick_code(instance, link, domain=None, create_method=QuickCodeCreateMethodType.PROGRAM): + domain = domain or instance.domain + if domain is None: + return None, None + app_key = domain.app_key + secret = domain.secret + success, quick_code_link = KZ( + appkey=app_key, secret=secret).gen_short_link(link, domain=domain) + if not success: + raise CustomProjectException(detail=quick_code_link) + quick_code = None + if quick_code_link: + quick_code = QuickCode.objects.create( + user=instance.user, + activity=instance, + quick_code_url=quick_code_link, + converted_url=link, + create_method=create_method, + quick_code_type=QuickCodeType.PRIVATE if domain.user_id > 0 else QuickCodeType.OFFICIAL + ) + return quick_code_link, quick_code + + +def save_files(files, business=None, return_path=False, user_id=0): + data = [] + folder = business or DbEnum.HDY + for file in files: + fs = default_storage + timestamp = datetime.now().strftime('%Y%m%d%H%M%S') + file_name = f'{folder}/{user_id}/{timestamp}_{file.name}' + fs.save(file_name, file) + file_url = fs.url(file_name) + if return_path: + data.append({ + 'path': file_name, + 'url': file_url, + }) + else: + data.append(f'{file_url}') + return data + + +def test_authorization(instance: Authorization, field): + field_info = getattr(instance, field) + if not field_info: + return False + platform_type = instance.platform_type + success = False + if platform_type == AuthorizationPlatformType.ELM: + if field == 'cookie_info': + cookies = [] + xsrf_token = '' + for info in field_info: + cookie = f'{info.get("name")}={info.get("value")}' + cookies.append(cookie) + if info.get('name') == 'XSRF-TOKEN': + xsrf_token = info.get('value') + cookie = ';'.join(cookies) + url = f'https://union.ele.me/user/userinfo?_csrf={xsrf_token}' + headers = { + 'Cookie': cookie, + 'X-Csrf-Token': xsrf_token, + 'X-Xsrf-Token': xsrf_token, + } + res = requests.get(url, headers=headers).json() + success = res.get('success') and str(res.get('result', {}).get('userId')) == instance.uid + if field == 'app_key_secret_info': + appkey = field_info.get('appkey') + secret = field_info.get('secret') + top_util = TopUtils(appkey=appkey, secret=secret) + res = top_util.get_zone_list() + success = res is not None + elif platform_type == AuthorizationPlatformType.MT: + if field == 'cookie_info': + cookies = [] + for info in field_info: + cookie = f'{info.get("name")}={info.get("value")}' + cookies.append(cookie) + cookie = ';'.join(cookies) + headers = { + 'Cookie': cookie, + } + url = f'https://union.meituan.com/api/account/info' + res = requests.get(url, headers=headers) + if res.status_code < 400: + res = res.json() + success = res.get('status') == 0 and str(res.get('data', {}).get('uid')) == instance.uid + if field == 'cookie_info': + instance.cookie_check_result = int(success) + instance.cookie_check_time = datetime.now() + instance.save() + return success diff --git a/apps/system/views.py b/apps/system/views.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/user/__init__.py b/apps/user/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/user/admin.py b/apps/user/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/apps/user/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/user/apps.py b/apps/user/apps.py new file mode 100644 index 0000000..172a94e --- /dev/null +++ b/apps/user/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class UserConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'apps.user' diff --git a/apps/user/choices.py b/apps/user/choices.py new file mode 100644 index 0000000..2458084 --- /dev/null +++ b/apps/user/choices.py @@ -0,0 +1,9 @@ +from django.db import models + + +class UserAccountTypeChoices(models.IntegerChoices): + """ + 用户账号类型 + """ + NORMAL = 1, '普通用户' + ADMIN = 2, '管理员' diff --git a/apps/user/migrations/__init__.py b/apps/user/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/user/models.py b/apps/user/models.py new file mode 100644 index 0000000..f7f8a35 --- /dev/null +++ b/apps/user/models.py @@ -0,0 +1,29 @@ +import uuid + +from .choices import * + + +class User(models.Model): + username = models.CharField(max_length=50, verbose_name='用户名', unique=True) + nick_name = models.CharField( + max_length=50, verbose_name='昵称', null=True, blank=True) + password = models.CharField(max_length=255, verbose_name='密码') + mobile = models.CharField(max_length=20, verbose_name='手机号', unique=True) + desc = models.TextField(null=True, blank=True, verbose_name='简介') + account_type = models.IntegerField( + default=UserAccountTypeChoices.NORMAL, verbose_name='账号类型') + avatar = models.URLField( + default='https://q1.qlogo.cn/g?b=qq&nk=190848757&s=640', verbose_name='头像') + home_path = models.CharField( + max_length=50, verbose_name='登录后跳转的页面', default='/qc/rule') + app_secret = models.CharField(default=lambda: uuid.uuid4().hex, editable=False, unique=True, max_length=32, + verbose_name='app_secret') + is_active = models.BooleanField(default=True, verbose_name='是否激活') + last_login = models.DateTimeField( + null=True, blank=True, verbose_name='上次登录时间') + create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') + update_time = models.DateTimeField(auto_now=True, verbose_name='创建时间') + + class Meta: + db_table = 'pb_user' + verbose_name = '用户' diff --git a/apps/user/serializers.py b/apps/user/serializers.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/user/tests.py b/apps/user/tests.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/user/urls.py b/apps/user/urls.py new file mode 100644 index 0000000..2018cd6 --- /dev/null +++ b/apps/user/urls.py @@ -0,0 +1,6 @@ +from rest_framework.routers import SimpleRouter +from . import views + +router = SimpleRouter(trailing_slash=False) + +urlpatterns = router.urls diff --git a/apps/user/views.py b/apps/user/views.py new file mode 100644 index 0000000..e69de29 diff --git a/yzk_wechat_event/settings/base.py b/yzk_wechat_event/settings/base.py index d0efdbf..08fb2f6 100644 --- a/yzk_wechat_event/settings/base.py +++ b/yzk_wechat_event/settings/base.py @@ -33,7 +33,7 @@ THIRD_PARTY_APPS = [ "rest_framework", ] -LOCAL_APPS = ["apps.jqr", "apps.qc", "apps.warning"] +LOCAL_APPS = ["apps.jqr", "apps.qc", "apps.warning", "apps.user", "apps.system"] INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS