Browse Source

git initial

chenjunkai 6 years ago
commit
ae6342e384

+ 15 - 0
.gitignore

@@ -0,0 +1,15 @@
+/.idea
+/static
+/Model/migrations
+/Ansjer/__pycache__
+/Controller/__pycache__
+/Model/__pycache__
+/Object/__pycache__
+/Service/__pycache__
+/Object/AWS/__pycache__
+*.log
+*/__pycache__
+/Ansjer/test/__pycache__
+/Ansjer/test/__init__.py
+/sdk_install
+/DB/mydata4vipday2.ipdb

+ 0 - 0
AnsjerPush/__init__.py


+ 102 - 0
AnsjerPush/config.py

@@ -0,0 +1,102 @@
+#!/usr/bin/env python3  
+# -*- coding: utf-8 -*-  
+"""
+@Copyright (C) ansjer cop Video Technology Co.,Ltd.All rights reserved.
+@AUTHOR: ASJRD018
+@NAME: Ansjer
+@software: PyCharm
+@DATE: 2018/7/2 14:06
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: Conf.py
+@Contact: chanjunkai@163.com
+"""
+# 主要静态变量配置文件
+import datetime, os
+
+# 阿里云发邮箱
+ALY_SES_ACCESS_NAME = 'message@dvema.com'
+ALY_SES_ACCESS_PAW = 'SMtp123456'
+ALY_SES_ACCESS_REPLYTO = '***'
+
+# 发送邮件邮箱
+SES_COMPANY_EMAIL = 'user_server@nsst.com'
+AWS_SES_ACCESS_ID = 'AKIAJKPU23EU5QWHFPKQ'
+AWS_SES_ACCESS_SECRET = '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'
+AWS_SES_ACCESS_REGION = 'us-east-1'
+AWS_BUCKET = 'ansjertest'
+# 设定离线时间为5分钟
+OFF_LINE_TIME_DELTA = 5
+
+# token的secret
+OAUTH_ACCESS_TOKEN_SECRET = 'a+jbgnw%@1%zy^=@dn62%'
+OAUTH_REFRESH_TOKEN_SECRET = 'r+jbgnw%@1%zy^=@dn62%'
+# access_token超时
+# OAUTH_ACCESS_TOKEN_TIME = datetime.timedelta(hours=1)
+OAUTH_ACCESS_TOKEN_TIME = datetime.timedelta(days=30)
+# refresh_token超时
+OAUTH_REFRESH_TOKEN_TIME = datetime.timedelta(days=30)
+# 腾讯验证,短信发送
+TX_PHONE_APP_ID = '1400052907'
+TX_PHONE_APP_KEY = '7705976ca6e85fe7b86d6bc2d11f7783'
+
+# 验证码超时时间
+AuthCode_Expire = 600
+
+RTMP_PUSH_URL = 'http://13.56.215.252:8091/hls'
+# 根路径
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+# uid token key
+UID_TOKEN_KEY = 'c+565*j@%^'
+
+# oss param
+OSS_STS_ACCESS_KEY = 'LTAIyMkGfEdogyL9'
+OSS_STS_ACCESS_SECRET = '71uIjpsqVOmF7DAITRyRuc259jHOjO'
+OSS_ROLE_ARN = 'acs:ram::1901342792446414:role/stsoss'
+
+SERVER_TYPE = 'Ansjer.local_settings'
+
+# 不同环境配置
+if SERVER_TYPE == 'Ansjer.local_settings':
+    NGINX_RTMP_STAT = 'http://192.168.136.45:8077/stat'
+    SERVER_DOMAIN = 'http://192.168.136.45:8077/'
+    SERVER_DOMAIN_SSL = 'http://192.168.136.45:8077/'
+    SERVER_HOST = '192.168.136.45'
+    DOMAIN_HOST = '192.168.136.45'
+    RTMP_PUSH_URL = 'rtmp://192.168.136.45:1935/hls'
+    PAYPAL_CRD = {
+        "mode": "sandbox",  # sandbox or live
+        "client_id": "AeuhR7FHisO-lOd2OwtzyDu7PSLMmDZoDLgmzuEQ12WCtTu_8Z1AzcD4gG5SnymnuvJs-n5KBB8H9Z_G",
+        "client_secret": "EGkMCB3RWTcUGJGDYahJ9mCO0AQzEn2AvFfx1GAFjfyyn7-8a0NObcZks89QorlFpvNWTsDXVa2INRNM"
+    }
+    DETECT_PUSH_DOMAIN = 'http://test.push.dvema.com/'
+
+elif SERVER_TYPE == 'Ansjer.test_settings':
+    NGINX_RTMP_STAT = 'http://test.dvema.com/stat'
+    SERVER_DOMAIN = 'http://test.dvema.com/'
+    SERVER_DOMAIN_SSL = 'https://test.dvema.com/'
+
+    DOMAIN_HOST = 'test.dvema.com'
+    SERVER_HOST = 'localhost'
+    PAYPAL_CRD = {
+        "mode": "live",  # sandbox or live
+        "client_id": "AdSRd6WBn-qLl9OiQHQuNYTDFSx0ZX0RUttqa58au8bPzoGYQUrt8bc6591RmH8_pEAIPijdvVYSVXyI",
+        "client_secret": "ENT-J08N3Fw0B0uAokg4RukljAwO9hFHPf8whE6-Dwd8oBWJO8AWMgpdTKpfB1pOy89t4bsFEzMWDowm"
+        # "mode": "sandbox",  # sandbox or live
+        # "client_id": "AeuhR7FHisO-lOd2OwtzyDu7PSLMmDZoDLgmzuEQ12WCtTu_8Z1AzcD4gG5SnymnuvJs-n5KBB8H9Z_G",
+        # "client_secret": "EGkMCB3RWTcUGJGDYahJ9mCO0AQzEn2AvFfx1GAFjfyyn7-8a0NObcZks89QorlFpvNWTsDXVa2INRNM"
+    }
+    DETECT_PUSH_DOMAIN = 'http://test.push.dvema.com/'
+
+elif SERVER_TYPE == 'Ansjer.formal_settings':
+    NGINX_RTMP_STAT = 'http://www.dvema.com/stat'
+    SERVER_DOMAIN = 'http://www.dvema.com/'
+    SERVER_DOMAIN_SSL = 'https://www.dvema.com/'
+    DOMAIN_HOST = 'www.dvema.com'
+    SERVER_HOST = 'localhost'
+    PAYPAL_CRD = {
+        "mode": "live",  # sandbox or live
+        "client_id": "AdSRd6WBn-qLl9OiQHQuNYTDFSx0ZX0RUttqa58au8bPzoGYQUrt8bc6591RmH8_pEAIPijdvVYSVXyI",
+        "client_secret": "ENT-J08N3Fw0B0uAokg4RukljAwO9hFHPf8whE6-Dwd8oBWJO8AWMgpdTKpfB1pOy89t4bsFEzMWDowm"
+    }
+    DETECT_PUSH_DOMAIN = 'http://push.dvema.com/'

+ 167 - 0
AnsjerPush/settings.py

@@ -0,0 +1,167 @@
+"""
+Django settings for AnsjerPush project.
+
+Generated by 'django-admin startproject' using Django 2.1.4.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/2.1/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/2.1/ref/settings/
+"""
+
+import os
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = '$2hf5g$a%_^kk0-l25l$!o5)yc=dvtnfpc8(+$rh4fq4twa_xx'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = ["*"]
+
+
+# Application definition
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'corsheaders',
+    'imagekit',
+    'Model'
+]
+
+MIDDLEWARE = [
+    'corsheaders.middleware.CorsMiddleware',
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    # 'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'AnsjerPush.urls'
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [os.path.join(BASE_DIR, 'templates')]
+        ,
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+WSGI_APPLICATION = 'AnsjerPush.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
+# formal
+# DATABASE_DATA = 'Ansjer81'
+# SERVER_HOST = 'localhost'
+# DATABASES_USER = 'ansjer'
+# DATABASES_PASS = '1234'
+# test
+DATABASE_DATA = 'AnsjerTest'
+SERVER_HOST = '13.56.215.252'
+DATABASES_USER = 'ansjer'
+DATABASES_PASS = '1234'
+DATABASES = {'default': {
+    'ENGINE': 'django.db.backends.mysql',
+    'NAME': DATABASE_DATA,
+    'USER': DATABASES_USER,
+    'PASSWORD': DATABASES_PASS,
+    'HOST': SERVER_HOST,
+    'PORT': '3306',
+    'OPTIONS': {'charset': 'utf8mb4', 'use_unicode': True, 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"},
+    'AUTOCOMMIT': True
+}}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/2.1/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/2.1/howto/static-files/
+
+STATIC_URL = '/static/'
+# 跨域增加忽略
+CORS_ALLOW_CREDENTIALS = True
+CORS_ORIGIN_ALLOW_ALL = True
+CORS_ORIGIN_WHITELIST = ('*')
+
+CORS_ALLOW_METHODS = (
+    'DELETE',
+    'GET',
+    'OPTIONS',
+    'PATCH',
+    'POST',
+    'PUT',
+    'VIEW',
+)
+
+CORS_ALLOW_HEADERS = (
+    'XMLHttpRequest',
+    'X_FILENAME',
+    'accept',
+    'accept-encoding',
+    'authorization',
+    'content-type',
+    'dnt',
+    'origin',
+    'user-agent',
+    'x-csrftoken',
+    'x-requested-with',
+    'Pragma',
+)

+ 24 - 0
AnsjerPush/urls.py

@@ -0,0 +1,24 @@
+"""AnsjerPush URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/2.1/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+from django.urls import path
+from Controller import DetectController
+
+
+urlpatterns = [
+    path('admin/', admin.site.urls),
+    path('notify/push', DetectController.NotificationView.as_view())
+]

+ 16 - 0
AnsjerPush/wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for AnsjerPush project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'AnsjerPush.settings')
+
+application = get_wsgi_application()

+ 261 - 0
Controller/DetectController.py

@@ -0,0 +1,261 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+@Copyright (C) ansjer cop Video Technology Co.,Ltd.All rights reserved.
+@AUTHOR: ASJRD018
+@NAME: AnsjerFormal
+@software: PyCharm
+@DATE: 2019/1/14 15:57
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: DetectController.py
+@Contact: chanjunkai@163.com
+"""
+import json
+import os
+import time
+import urllib
+
+import apns2
+import jpush as jpush
+import oss2
+import requests
+from django.utils.decorators import method_decorator
+from django.views.decorators.csrf import csrf_exempt
+from django.views.generic.base import View
+from AnsjerPush.config import OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET, SERVER_DOMAIN, BASE_DIR, DETECT_PUSH_DOMAIN
+from Model.models import Equipment_Info, UidSetModel, UidPushModel
+from Object.ResponseObject import ResponseObject
+from Object.UidTokenObject import UidTokenObject
+from django.http import JsonResponse
+from Object.RedisObject import RedisObject
+from django.db import transaction
+
+
+# http://192.168.136.40:8077/notify/push?uidToken=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiJUTjdNUEUzMjExVUU3NkFQMTExQSJ9.k501567VdnhFpn_ygzGRDat3Kqlz5CsEA9jAC2dDk_g&obj=12341234&n_time=1234561234
+# http://test.dvema.com/notify/push?uidToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJQMldOR0pSRDJFSEE1RVU5MTExQSJ9.xOCI5lerk8JOs5OcAzunrKCfCrtuPIZ3AnkMmnd-bPY&n_time=1526845794&channel=1&event_type=51&is_st=0
+# 移动侦测接口
+class NotificationView(View):
+
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        # operation = kwargs.get('operation')
+        return self.validation(request.GET)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        # operation = kwargs.get('operation')
+        return self.validation(request.POST)
+
+    def validation(self, request_dict):
+        response = ResponseObject()
+        uidToken = request_dict.get('uidToken', None)
+        channel = request_dict.get('channel', None)
+        n_time = request_dict.get('n_time', None)
+        event_type = request_dict.get('event_type', None)
+        is_st = request_dict.get('is_st', None)
+        if not all([uidToken, channel, n_time]):
+            return JsonResponse(status=200, data={
+                'code': 444,
+                'msg': 'param is wrong'})
+            # return response.json(444)
+        utko = UidTokenObject(uidToken)
+        uid = utko.UID
+        uid_set_qs = UidSetModel.objects.filter(uid=uid, detect_status=1)
+        if uid_set_qs.exists():
+            uid_set_id = uid_set_qs[0].id
+            uid_push_qs = UidPushModel.objects.filter(uid_set__id=uid_set_id). \
+                values('token_val', 'app_type', 'appBundleId', 'push_type', 'userID_id', 'userID__NickName')
+            if uid_set_qs.exists():
+                redisObj = RedisObject(db=6)
+                pkey = '{uid}_{channel}_ptl'.format(uid=uid, channel=channel)
+                if redisObj.get_data(key=pkey):
+                    res_data = {'code': 0, 'msg': 'success,!'}
+                    return JsonResponse(status=200, data=res_data)
+                else:
+                    detect_interval = uid_set_qs[0].detect_interval
+                    if detect_interval:
+                        redisObj.set_data(key=pkey, val=1, expire=detect_interval)
+                auth = oss2.Auth(OSS_STS_ACCESS_KEY, OSS_STS_ACCESS_SECRET)
+                bucket = oss2.Bucket(auth, 'oss-cn-shenzhen.aliyuncs.com', 'apg')
+                for up in uid_push_qs:
+                    push_type = up['push_type']
+                    # ios apns
+                    if push_type == 0:
+                        self.do_apns(request_dict, up, response, uid)
+                    # android gcm
+                    elif push_type == 1:
+                        self.do_gmc(request_dict, up, response, uid)
+                    # android jpush
+                    elif push_type == 2:
+                        self.do_jpush(request_dict, up, response, uid)
+                    # self.do_save_equipment_info(ua, n_time, channel, event_type, is_st)
+                # 需求不一样,所以这么做的
+                self.do_bulk_create_info(uid_push_qs, n_time, channel, event_type, is_st, uid)
+                if is_st == '0' or is_st == '2':
+                    return JsonResponse(status=200, data={'code': 0, 'msg': 'success'})
+                else:
+                    # Endpoint以杭州为例,其它Region请按实际情况填写。
+                    obj = '{uid}/{channel}/{filename}.jpeg'.format(uid=uid, channel=channel, filename=n_time)
+                    # 设置此签名URL在60秒内有效。
+                    url = bucket.sign_url('PUT', obj, 7200)
+                    res_data = {'code': 0, 'img_push': url, 'msg': 'success'}
+                    return JsonResponse(status=200, data=res_data)
+            else:
+                return JsonResponse(status=200, data={'code': 404, 'msg': 'data is not exist'})
+        else:
+            return JsonResponse(status=200, data={'code': 404, 'msg': 'data is not exist'})
+
+    def do_jpush(self, request_dict, uaql, response, uid):
+        event_type = request_dict.get('event_type', None)
+        jpush_config = {
+            'com.ansjer.accloud_ab': {
+                'Key': 'f0dc047e5e53fd14199de5b0',
+                'Secret': 'aa7f7db33e9f0a7f3871aa1c'},
+            'com.ansjer.adcloud_ab': {
+                'Key': '76d97b535185114985608234',
+                'Secret': 'c9a92b301043cc9c52778692'},
+            'com.ansjer.zccloud_ab': {
+                'Key': 'd9924f56d3cc7c6017965130',
+                'Secret': '869d832d126a232f158b5987'},
+            'com.ansjer.loocamccloud_ab': {
+                'Key': 'd1cc44797b4642b0e05304fe',
+                'Secret': 'c3e8b4ca8c576de61401e56a'},
+            'com.ansjer.loocamdcloud_ab': {
+                'Key': '76d97b535185114985608234',
+                'Secret': 'c9a92b301043cc9c52778692'},
+            'com.ansjer.zccloud_a': {
+                'Key': '57de2a80d68bf270fd6bdf5a',
+                'Secret': '3d354eb6a0b49c2610decf42'},
+            'com.ansjer.accloud_a': {
+                'Key': 'ff95ee685f49c0dc4013347b',
+                'Secret': 'de2c20959f5516fdeeafe78e'},
+            'com.ansjer.adcloud_a': {
+                'Key': '2e47eb1aee9b164460df3668',
+                'Secret': 'b9137d8d684bc248f1809b6d'},
+            'com.ansjer.loocamccloud_a': {
+                'Key': '23c9213215c7ca0ec945629b',
+                'Secret': '81e4b1e859cc8387e2e6c431'},
+            'com.ansjer.loocamdcloud_a': {
+                'Key': '1dbdd60a16e9892d6f68a073',
+                'Secret': '80a97690e7e043109059b403'},
+            'com.ansjer.customizedb_a': {
+                'Key': '9d79630aa49adfa291fe2568',
+                'Secret': '4d8ff52f88136561875a0212'},
+        }
+        n_time = request_dict.get('n_time', None)
+        appBundleId = uaql['appBundleId']
+        token_val = uaql['token_val']
+
+        response = ResponseObject()
+        app_key = jpush_config[appBundleId]['Key']
+        master_secret = jpush_config[appBundleId]['Secret']
+        # 此处换成各自的app_key和master_secre
+        _jpush = jpush.JPush(app_key, master_secret)
+        push = _jpush.create_push()
+        # if you set the logging level to "DEBUG",it will show the debug logging.
+        _jpush.set_logging("DEBUG")
+        # push.audience = jpush.all_
+        push.audience = jpush.registration_id(token_val)
+        push_data = {"alert": "Motion ", "event_time": n_time, "event_type": event_type, "msg": "",
+                     "received_at": n_time, "sound": "sound.aif", "uid": uid, "zpush": "1"}
+        push.message = jpush.message('Motion', extras=push_data, title='KPNS', content_type='text')
+        push.platform = jpush.all_
+        try:
+            res = push.send()
+            print(res)
+        except Exception as e:
+            print("Exception")
+            print(repr(e))
+            return response.json(10, repr(e))
+        else:
+            return response.json(0)
+
+    def do_gmc(self, request_dict, uaql, response, uid):
+
+        n_time = request_dict.get('n_time')
+        appBundleId = uaql['appBundleId']
+        token_val = uaql['token_val']
+        gcm_config = {
+            'com.ansjer.zccloud_a': 'AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I',
+            'com.ansjer.loocamccloud_a': 'AAAAb9YP3rk:APA91bFCgd-kbVmpK4EVpfdHH_PJZQCYTkOGnTZdIuBWEz2r7aMRsJYHOH3sB-rwcbaRWgnufTyjX9nGQxb6KxQbWVk4ah_H-M3IqGh6Mb60WQQAuR33V6g_Jes5pGL6ViuIxGHqVMaR',
+            'com.ansjer.loocamdcloud_a': 'AAAAb9YP3rk:APA91bGw2I2KMD4i-5T7nZO_wB8kuAOuqgyqe5rxmY-W5qkpYEx9IL2IfmC_qf6B_xOyjIDDSjckvMo-RauN__SEoxvAkis7042GRkoKpw7cjZ_H8lC-d50PC0GclPzccrOGFusyKbFY',
+            'com.ansjer.customizedb_a': 'AAAAb9YP3rk:APA91bE7kI4vcm-9h_CJNFlOZfc-xwP4Btn6AnjOrwoKV6fgYN7fdarkO76sYxVZiAbDnxsFfOJyP7vQfwyan6mdjuyD5iHdt_XgO22VqniC0vA1V4GJiCS8Tp7LxIX8JVKZl9I_Powt',
+            'com.ansjer.customizeda_a': 'AAAAb9YP3rk:APA91bF0HzizVWDc6dKzobY9fsaKDK4veqkOZehDXshVXs8pEEvNWjR_YWbhP60wsRYCHCal8fWN5cECVOWNMMzDsfU88Ty2AUl8S5FtZsmeDTkoGntQOswBr8Ln7Fm_LAp1VqTf9CpM',
+        }
+        serverKey = gcm_config[appBundleId]
+        event_type = request_dict.get('event_type', None)
+        push_data = {"alert": "Motion ", "event_time": n_time, "event_type": event_type, "msg": "",
+                     "received_at": n_time, "sound": "sound.aif", "uid": uid, "zpush": "1"}
+        json_data = {
+            "collapse_key": "WhatYouWant",
+            "data": push_data,
+            "delay_while_idle": False,
+            "time_to_live": 3600,
+            "registration_ids": [token_val]
+        }
+
+        url = 'https://android.googleapis.com/gcm/send'
+        # serverKey = "AAAAb9YP3rk:APA91bHu8u-CTpcd0g6lKPo0WNVqCi8jZub1cPPbSAY9AucT1HxlF65ZDUko9iG8q2ch17bwu9YWHpK1xI1gHSRXCslLvZlXEmHZC0AG3JKg15XuUvlFKACIajUFV-pOeGRT8tM6-31I"
+
+        data = json.dumps(json_data).encode('utf-8')
+        headers = {'Content-Type': 'application/json', 'Authorization': 'key=%s' % serverKey}
+        req = requests.post(url, data, headers=headers)
+        return response.json(0)
+
+    def do_apns(self, request_dict, uaql, response, uid):
+        event_type = request_dict.get('event_type', None)
+        token_val = uaql['token_val']
+        n_time = request_dict.get('n_time')
+        appBundleId = uaql['appBundleId']
+        apns_config = {
+            'com.ansjer.loocamccloud': {
+                'pem_path': os.path.join(BASE_DIR, 'Ansjer/file/apns_pem/apns-dev-test.pem'),
+                'password': '111111'
+            }
+        }
+        try:
+            cli = apns2.APNSClient(mode="dev", client_cert=apns_config[appBundleId]['pem_path'],
+                                   password=apns_config[appBundleId]['password'])
+            push_data = {"alert": "Motion ", "event_time": n_time, "event_type": event_type, "msg": "",
+                         "received_at": n_time, "sound": "sound.aif", "uid": uid, "zpush": "1"}
+            body = json.dumps(push_data)
+            alert = apns2.PayloadAlert(body=body, title="title!")
+            payload = apns2.Payload(alert=alert)
+            n = apns2.Notification(payload=payload, priority=apns2.PRIORITY_LOW)
+            res = cli.push(n=n, device_token=token_val, topic=appBundleId)
+            # assert res.status_code == 200, res.reason
+            # assert res.apns_id 
+            if res.status_code == 200:
+                return response.json(0)
+            else:
+                return response.json(404, res.reason)
+        except Exception as e:
+            return response.json(10, repr(e))
+
+    def do_bulk_create_info(self, uaqs, n_time, channel, event_type, is_st, uid):
+        #
+        qs_list = []
+        nowTime = int(time.time())
+        # 设备昵称
+
+        for dv in uaqs:
+            add_data = {
+                'userID_id': dv["userID_id"],
+                'eventTime': n_time,
+                'eventType': event_type,
+                'devUid': uid,
+                'devNickName': uid,
+                'Channel': channel,
+                'alarm': 'Motion \tChannel:{channel}'.format(channel=channel),
+                'is_st': int(is_st),
+                'receiveTime': n_time,
+                'addTime': nowTime
+            }
+            qs_list.append(Equipment_Info(**add_data))
+        if qs_list:
+            print(1)
+            Equipment_Info.objects.bulk_create(qs_list)
+            return True
+        else:
+            return False

+ 340 - 0
Model/models.py

@@ -0,0 +1,340 @@
+from itertools import chain
+
+from django.contrib.auth.models import AbstractBaseUser,BaseUserManager
+from django.db import models
+from imagekit.models import ProcessedImageField
+from imagekit.processors import ResizeToFill
+from AnsjerPush.config import SERVER_DOMAIN
+from django.utils.encoding import python_2_unicode_compatible
+from django.utils import six
+
+
+class PermissionsManager(models.Manager):
+    use_in_migrations = True
+
+    def get_by_natural_key(self, permName):
+        return self.get(
+            permName=permName
+        )
+
+
+class RoleManager(models.Manager):
+    """
+    The manager for the auth's Role model.
+    """
+    use_in_migrations = True
+
+    def get_by_natural_key(self, roleName):
+        return self.get(roleName=roleName)
+
+
+@python_2_unicode_compatible
+class Permissions(models.Model):
+    permName = models.CharField(blank=True, null=True, max_length=32, unique=True, verbose_name=u'权限名称')
+    description = models.CharField(blank=True, null=True, max_length=128, verbose_name=u'描述信息', default='')
+    objects = PermissionsManager()
+
+    def __str__(self):
+        return "%s" % (
+            six.text_type(self.description))
+
+    class Meta:
+        ordering = ['permName']
+        db_table = 'permissions'
+        verbose_name = u'role permission'
+        verbose_name_plural = verbose_name
+        unique_together = (('permName'),)
+
+    def natural_key(self):
+        return (self.permName)
+
+
+class Role(models.Model):
+    rid = models.SmallIntegerField(primary_key=True, unique=True, verbose_name=u'用户角色组ID')
+    roleName = models.CharField(max_length=32, unique=True,
+                                default='User', verbose_name=u'角色名称')
+    permission = models.ManyToManyField(to='Permissions', blank=True, verbose_name=u'权限', db_table='role_permissions')
+    Description = models.TextField(blank=True, default='', verbose_name=u'描述信息')
+
+    objects = RoleManager()
+
+    class Meta:
+        ordering = ['roleName']
+        db_table = 'role'
+        verbose_name = u'用户角色'
+        verbose_name_plural = verbose_name
+
+    def __str__(self):
+        return self.roleName
+
+    def natural_key(self):
+        return (self.roleName,)
+
+    def get_all_permission(self):
+        perms = self.permission.all()
+
+        permslist = []
+        if self.rid == 100:
+            perms = Permissions.objects.all()
+            for perm in perms:
+                permslist.append(perm.permName)
+            return permslist
+        else:
+            permlist_tmp = []
+            for perm in perms:
+                permlist_tmp.append(perm.permName)
+            permSet = set(permlist_tmp)
+            permslist = list(permSet)
+            permslist.sort()
+            return permslist
+
+
+class UserManager(BaseUserManager):
+
+    def create_user(self, username, password, userID, is_active,
+                    user_isValid, **extra_fields):
+        user = self.model(
+            username=username,
+            userID=userID,
+            is_active=is_active,
+            user_isValid=user_isValid,
+            **extra_fields
+        )
+        user.set_password(password)
+        user.save(using=self._db)
+
+        role = Role.objects.get(rid=1)
+        user.role.add(role)
+        return user
+
+    def create_superuser(self, username, password, userID, is_active,
+                         user_isValid, **extra_fields):
+        # extra_fields.setdefault('is_superuser', is_superuser)
+        is_superuser = extra_fields.get('is_superuser', None)
+        if is_superuser != 100 and is_superuser != 1:
+            raise ValueError('Superuser must have is_superuser=1 or 100.')
+
+        return self.create_user(username, password, userID, is_active,
+                                user_isValid, **extra_fields)
+
+class Device_User(AbstractBaseUser):
+    userID = models.CharField(blank=True, max_length=32, primary_key=True,
+                              verbose_name=u'用户ID', unique=True)
+    role = models.ManyToManyField(to='Role', blank=True, verbose_name=u'用户角色', db_table='user_role')
+
+    username = models.CharField(max_length=64, verbose_name=u'用户名', default='', blank=True)
+    password = models.CharField(max_length=128, verbose_name=u'密码')
+    userEmail = models.EmailField(max_length=64, verbose_name=u'邮箱', default='', blank=True)
+    # 实际的路径就是 MEDIA_ROOT/Image/filename,所以可用upload_to来指定文件存放的前缀路径
+    userIconPath = ProcessedImageField(blank=True, upload_to='User/Images/', default='static/User/default.png',
+                                       verbose_name=u'头像',
+                                       # 图片将处理成85x85的尺寸
+                                       processors=[ResizeToFill(85, 85)], )
+    userIconUrl = models.URLField(blank=True, max_length=128, default=SERVER_DOMAIN
+                                                                      + 'account/getAvatar/User/defaultUser.png')
+    NickName = models.CharField(blank=True, max_length=64, default='', verbose_name=u'用户昵称')
+    is_superuser = models.IntegerField(blank=True, default=0, verbose_name=u'用户类型')
+    is_active = models.BooleanField(blank=True, default=False, verbose_name=u'用户活动状态')
+    data_joined = models.DateTimeField(blank=True, verbose_name=u'加入时间', auto_now_add=True)
+    last_login = models.DateTimeField(blank=True, verbose_name='u最后登录时间', auto_now=True)
+    user_isValid = models.BooleanField(blank=True, default=False, verbose_name=u'用户有效性', help_text=u'是否是认证通过的用户')
+    online = models.BooleanField(blank=True, default=False, verbose_name=u'用户登录状态')
+    machine_code = models.CharField(blank=True, max_length=128, default='', verbose_name=u'机械码')
+
+    language = models.CharField(blank=True, max_length=16, default='en', verbose_name=u'语言地区')
+    # 手机注册增加字段
+    phone = models.CharField(max_length=16, verbose_name=u'手机号', default='', blank=True)
+
+    objects = UserManager()
+
+    USERNAME_FIELD = 'userID'  # 必须有一个唯一标识
+    REQUIRED_FIELDS = ['is_superuser']  # 创建superuser时的必须字段
+
+    class Meta:
+        ordering = ('-data_joined',)
+        verbose_name = u'用户信息'
+        db_table = 'device_user'
+        get_latest_by = 'last_login'
+
+    def __str__(self):
+        return self.username
+
+    def get_role_id(self):
+        rids = []
+        roles = self.role.all()
+        for role in roles:
+            rids.append(role.rid)
+        return rids
+
+    def get_all_permission(self):
+        roles = self.role.all()
+        perms = self.permission.all()
+
+        permslist = []
+        for role in roles:
+            if role.rid == 100:
+                perms = Permissions.objects.all()
+                for perm in perms:
+                    permslist.append(perm.permName)
+                return permslist
+
+        for perm in perms:
+            permslist.append(perm.permName)
+
+        permSet = set(permslist)
+        for role in roles:
+            permlist_tmp = []
+            for perm in role.permission.all():
+                permlist_tmp.append(perm.permName)
+
+            permSet_tmp = set(permlist_tmp)
+            permSet = permSet.union(permSet_tmp)
+            permslist = list(permSet)
+            permslist.sort()
+            return permslist
+
+    @property
+    def is_staff(self):
+        return self.is_superuser
+
+
+# 设备表是建项目开发者设计的,自己看着办
+class Device_Info(models.Model):
+    id = models.CharField(blank=True, max_length=32, primary_key=True)
+    userID = models.ForeignKey(Device_User, blank=True, to_field='userID', on_delete=models.CASCADE)
+    NickName = models.CharField(blank=True, max_length=32, verbose_name=u'设备名称')
+    UID = models.CharField(blank=True, max_length=32, verbose_name=u'设备UID', default='')
+    SID = models.CharField(blank=True, max_length=32, verbose_name=u'服务器ID', default='')
+    View_Account = models.CharField(blank=True, max_length=32, verbose_name=u'设备用户名称', default='')
+    View_Password = models.CharField(blank=True, max_length=32, verbose_name=u'设备密码', default='')
+    AudioFormat = models.IntegerField(blank=True, default=1, verbose_name=u'初始化影像')
+    EventNotification = models.IntegerField(blank=True, verbose_name=u'报警类型', default=0)
+    ChannelIndex = models.IntegerField(blank=True, verbose_name=u'通道号', default=0)
+    Online = models.BooleanField(blank=True, default=False, verbose_name=u'设备是否在线')
+    mMonitorIndex = models.IntegerField(blank=True, default=-1)
+    Type = models.IntegerField(blank=True, verbose_name='设备类型')
+    DebugMode = models.IntegerField(blank=True, verbose_name=u'调试模式', default=0)
+    NotificationMode = models.IntegerField(blank=True, verbose_name=u'是否报警', default=0)
+    qvgaLevel = models.BooleanField(blank=True, verbose_name=u'SD与HD画面', default=0,
+                                    help_text=u'0代表:SD、1代表:HD')
+    isShare = models.BooleanField(blank=True, verbose_name=u'共享设备',
+                                  help_text=u'是否为共享获取的设备', default=False)
+    primaryUserID = models.CharField(blank=True, verbose_name='主用户id', max_length=32, default='')
+    primaryMaster = models.CharField(max_length=64, verbose_name=u'主用户名', default='')
+    data_joined = models.DateTimeField(blank=True, verbose_name=u'设备添加时间', auto_now_add=True)
+    update_time = models.DateTimeField(blank=True, verbose_name=u'更新时间', auto_now=True, null=True)
+
+    ip = models.CharField(blank=True, max_length=20, default='', verbose_name=u'设备区域ip')
+    area = models.CharField(blank=True, max_length=100, default='', verbose_name=u'设备区域area')
+    # ios要求新增字段
+    version = models.CharField(blank=True, max_length=20, default='', verbose_name=u'版本号')
+    SpaceUsable = models.CharField(blank=True, max_length=20, default='', verbose_name=u'可用空间')
+    SpaceSum = models.CharField(blank=True, max_length=20, default='', verbose_name=u'总空间')
+    WIFIName = models.CharField(blank=True, max_length=50, default='', verbose_name=u'无线名称')
+    WIFIIP = models.CharField(blank=True, max_length=20, default='', verbose_name=u'无线ip')
+    WIFIPwd = models.CharField(blank=True, max_length=50, default='', verbose_name=u'无线密码')
+    isDetector = models.BooleanField(blank=True, verbose_name=u'侦测开关0:关闭,1:开启)', default=False)
+    DetectorRank = models.IntegerField(blank=True, default=0, verbose_name=u'侦测灵敏度 1:低,2:中,3:高4:最高')
+    iSNotification = models.BooleanField(blank=True, verbose_name=u'报警通知 0:关闭,1:开启)', default=False)
+    MirrorType = models.IntegerField(blank=True, default=0, verbose_name=u'镜像类型 0:关闭镜像,1:上下镜像,2:左右镜像,3:上下左右镜像')
+    RecordType = models.IntegerField(blank=True, default=0, verbose_name=u'录像模式(0:关闭,1:全是录像,3:报警录像)')
+    TimeZone = models.CharField(blank=True, max_length=50, default='', verbose_name=u'时区')
+    isVod = models.SmallIntegerField(blank=True, default=0, verbose_name='是否支持云存')  # 是否支持云存设备
+    isExist = models.SmallIntegerField(blank=True, default=1, verbose_name='是否被删除')  # 是否被删除了(需主用户交互) 1存在,0不存在
+    ###
+    REQUIRED_FIELDS = []
+
+    def __str__(self):
+        return self.NickName
+
+    def model_to_dict(self, fields=None, exclude=None):
+        opts = self._meta
+        data = {}
+        for f in chain(opts.concrete_fields, opts.private_fields, opts.many_to_many):
+            if not getattr(f, 'editable', False):
+                continue
+            if fields and f.name not in fields:
+                continue
+            if exclude and f.name in exclude:
+                continue
+            data[f.name] = f.value_from_object(self)
+        return data
+
+    class Meta:
+        db_table = 'device_info'
+        ordering = ('-data_joined',)
+        verbose_name = u'用户设备信息表'
+        verbose_name_plural = verbose_name
+
+
+class Equipment_Info(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    devUid = models.CharField(default='', blank=True, max_length=32, verbose_name=u'设备ID')
+    devNickName = models.CharField(blank=True, max_length=32, default='', verbose_name=u'设备昵称')
+    Channel = models.IntegerField(default=1, blank=True, verbose_name=u'设备通道')
+    eventType = models.IntegerField(default=0, blank=True, verbose_name=u'事件类型')
+    status = models.BooleanField(blank=True, default=False, verbose_name=u'事件状态')
+    alarm = models.CharField(blank=True, max_length=256, verbose_name=u'报警信息')
+    eventTime = models.CharField(blank=True, default='', max_length=16, verbose_name=u'设备报警时间')
+    receiveTime = models.CharField(blank=True, default='', max_length=16, verbose_name=u'接收到报警时间')
+    userID = models.ForeignKey(Device_User, null=True, blank=True, to_field='userID', on_delete=models.CASCADE)
+    is_st = models.SmallIntegerField(default=0, verbose_name='是否截图')  # 0 否,1 是图,2,视频
+    addTime = models.IntegerField(verbose_name='添加时间', default=0)
+
+    def __str__(self):
+        return self.id
+
+    class Meta:
+        db_table = 'equipment_info'
+        verbose_name = u'设备信息推送表'
+        verbose_name_plural = verbose_name
+        ordering = ('-id',)
+
+
+# 设备推送重构
+# 设备配置表,新
+class UidSetModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name=u'自增标记ID')
+    uid = models.CharField(max_length=20, verbose_name='设备UID')
+    channel = models.SmallIntegerField(default=0, verbose_name='通道数量')  #
+    detect_status = models.SmallIntegerField(default=0, verbose_name='推送开关')  # 状态[0:关闭,1:开启,2:用户解绑]
+    detect_interval = models.IntegerField(verbose_name='推送间隔', default=0)  # 秒
+    addTime = models.IntegerField(verbose_name='添加时间', default=0)
+    updTime = models.IntegerField(verbose_name='更新时间', default=0)
+    # addTime 2019年 05月 27日 星期一 16:52:55 CST
+    ucode = models.CharField(max_length=32, verbose_name='设备产品码', default='')
+    version = models.CharField(max_length=32, verbose_name='设备版本', default='')
+    p2p_region = models.CharField(max_length=16, verbose_name='设备区域', default='ALL')  # ALL CN EU US
+    # addTime Thu Jun 27 02:32:45 UTC 2019
+    cloud_vod = models.SmallIntegerField(default=2, verbose_name='云存开关')  # 0,关闭,1开启,2,不支持
+    tz = models.CharField(default='', max_length=16, verbose_name='设备时区')  # utc+8
+    video_code = models.SmallIntegerField(default=0, verbose_name='编码类型')  # 0:264,1:265
+
+    nickname = models.CharField(default='', max_length=64, verbose_name='设备昵称')
+    ip = models.CharField(blank=True, max_length=20, default='', verbose_name=u'设备ip')
+
+    class Meta:
+        db_table = 'uid_set'
+        verbose_name = u'设备配置'
+        verbose_name_plural = verbose_name
+        ordering = ('id',)
+
+
+# 设备关联用户推送
+class UidPushModel(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='自增id')
+    userID = models.ForeignKey(Device_User, to_field='userID', on_delete=models.CASCADE)
+    uid_set = models.ForeignKey(UidSetModel, to_field='id', on_delete=models.CASCADE)
+    appBundleId = models.CharField(blank=True, max_length=32, verbose_name=u'appID')
+    app_type = models.IntegerField(default=0, verbose_name=u'app类型 1:ios,2:安卓')
+    push_type = models.IntegerField(default=0, verbose_name=u'推送类型')  # 0,apns 1,安卓gcm 2,极光
+    token_val = models.CharField(default='', max_length=160, verbose_name=u'设备验证令牌')
+    m_code = models.CharField(default='', max_length=64, verbose_name='手机唯一标识')
+    addTime = models.IntegerField(verbose_name='添加时间', default=0)
+    updTime = models.IntegerField(verbose_name='更新时间', default=0)
+
+    class Meta:
+        db_table = 'uid_push'
+        verbose_name = '设备绑定'
+        verbose_name_plural = verbose_name
+        ordering = ('-id',)

+ 86 - 0
Object/RedisObject.py

@@ -0,0 +1,86 @@
+#!/usr/bin/env python3  
+# -*- coding: utf-8 -*-  
+"""
+@Copyright (C) ansjer cop Video Technology Co.,Ltd.All rights reserved.
+@AUTHOR: ASJRD018
+@NAME: AnsjerOA
+@software: PyCharm
+@DATE: 2018/8/8 17:00
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: RedisObject.py
+@Contact: chanjunkai@163.com
+"""
+import redis
+
+from AnsjerPush.config import SERVER_HOST
+from AnsjerPush.config import SERVER_TYPE
+
+# SERVER_HOST = '192.168.136.45'
+
+'''
+db=3  -> 统计在线人数用
+'''
+
+
+class RedisObject:
+
+    def __init__(self, db=0):
+        if db == 3:
+            if SERVER_TYPE != 'Ansjer.formal_settings':
+                db = 4
+        self.POOL = redis.ConnectionPool(host=SERVER_HOST, port=6379, db=db)
+        self.CONN = redis.Redis(connection_pool=self.POOL)
+
+    def set_data(self, key, val, expire=0):
+        try:
+            self.CONN.set(key, val)
+            if expire > 0:
+                self.CONN.expire(key, expire)
+        except Exception as e:
+            return False
+        else:
+            return True
+
+    def get_data(self, key):
+        try:
+            val = self.CONN.get(key)
+        except Exception as e:
+            print(repr(e))
+            return False
+        else:
+            if val:
+                return val.decode('utf-8')
+            else:
+                return False
+
+    def del_data(self, key):
+        try:
+            val = self.CONN.delete(key)
+        except Exception as e:
+            print(repr(e))
+            return False
+        else:
+            return True
+
+    def get_size(self):
+        return self.CONN.dbsize()
+
+    # 向列表插入数据
+    def rpush(self, name, val):
+        self.CONN.rpush(name, val)
+
+    # 获取列表长度
+    def llen(self, name):
+        return self.CONN.llen(name=name)
+
+    # 获取列表所有数据
+    def lrange(self, name, start, end):
+        return self.CONN.lrange(name, start, end)
+
+    def get_ttl(self, key):
+        ttl = self.CONN.ttl(key)
+        if ttl:
+            return ttl
+        else:
+            return 0

+ 134 - 0
Object/ResponseObject.py

@@ -0,0 +1,134 @@
+from django.shortcuts import HttpResponse
+import simplejson as json
+
+
+class ResponseObject(object):
+    def __init__(self, lang='en'):
+        self.lang = lang
+
+    def data(self, code, res={}):
+        data_en = {
+            0: 'Success',
+            5: 'Please try again one minute later!',
+            10: res,
+            12: 'You are not the primary user of the device!',
+            14: 'Device is not belong to you',
+            15: 'Device has been bound',
+            44: 'System error! Can not send email',
+            48: 'System object error!',
+            89: 'Already send the code, please check it or get it again after 10m',
+            90: 'please check code or get it again after 1m',
+            99: 'Mail doesn\'t exist!',
+            100: 'Phone format error!',
+            101: 'Phone already existed!',
+            102: 'Phone doesn\'t exist!',
+            103: 'Mail already existed!',
+            104: 'Account doesn\'t exist!',
+            105: 'Email format error!',
+            107: 'The username not conform to the rules!',
+            109: 'The password not conform to the rules!',
+            110: 'user doesn\'t activated',
+            111: 'Error password',
+            119: 'The qr code has expired',
+            120: 'The code has expired',
+            121: 'The verification code is wrong!',
+            173: 'Data does not exists!',
+            174: 'Data already exists!',
+            176: 'Delete error',
+            177: 'Update error',
+            178: 'ADD error',
+            179: 'Nickname repeated',
+            306: 'The link has expired!',
+            309: 'Please ReLogin! errmsg token',
+            404: 'You don not have permission to access this!',
+            414: 'Please confirm the request url!',
+            424: 'Database Error !',
+            444: 'Wrong parameters!',
+            474: 'System Maintaining!',
+            475: 'App Version too low, please upgrade!',
+            500: 'Query Database Error:',
+            700: 'Upload file error',
+            701: 'The file does not exist!',
+            711: 'Do not downgrade',
+            712: 'Area needs to be consistent',
+            713: 'Storage rules cannot be changed during the validity period',
+            900: 'There is no information about this version!',
+            901: 'Getting URL failure!',
+            902: 'No update!',
+            903: 'Error filename',
+            906: 'Cause of file operation error',
+            907: 'The download file does not exist!',
+        }
+        data_cn = {
+            0: '成功',
+            5: '请一分钟后再尝试',
+            10: res,
+            12: '非设备主用户',
+            14: '设备不属于您',
+            15: '设备已被绑定',
+            44: '系统错误!无法发送电子邮件',
+            48: '系统对象错误',
+            89: '已发验证码,请检测或10分钟后重新获取。',
+            90: '请检测或1分钟后重新获取。',
+            99: '邮箱不存在!',
+            100: '手机格式错误!',
+            101: '手机已存在!',
+            102: '手机不存在!',
+            103: '邮箱已存在!',
+            104: '账户不存在!',
+            105: '邮箱格式错误!',
+            107: '用户名格式不符合!',
+            109: '密码格式不符合!',
+            110: '用户未激活!',
+            111: '密码不正确!',
+            119: '二维码过期',
+            120: '验证码过期',
+            121: '验证码错了!',
+            173: '数据不存在!',
+            174: '数据已存在!',
+            176: '删除错误',
+            177: '更新错误',
+            178: '增加错误',
+            179: '名称不能重复',
+            306: '链接已超过有效期!',
+            309: '请重新登录!',
+            404: '您没有访问的权限!',
+            414: '请确认请求url!',
+            424: '数据库错误!',
+            444: '参数错误!',
+            474: '系统维护中!',
+            475: '版本过低,请升级程序!',
+            500: '查询数据库错误!',
+            700: '上传文件错误',
+            701: '文件不存在',
+            711: '不可降级',
+            712: '区域不一致',
+            713: '有效期内不可更改存储规则',
+            900: '版本信息不存在',
+            901: '获取链接失败',
+            902: '无更新!',
+            903: '文件名不符合!',
+            906: '文件操作错误',
+            907: '文件不存在!',
+        }
+        if self.lang == 'cn':
+            msg = data_cn
+        elif self.lang == 'zh-Hans':
+            msg = data_cn
+        elif self.lang == 'zh-Hant':
+            msg = data_cn
+        else:
+            msg = data_en
+        try:
+            message = msg[code]
+        except Exception as e:
+            message = '系统错误,code不存在'
+        return {'result_code': code, 'reason': message, 'result': res, 'error_code': code}
+
+    def formal(self, code, res={}):
+        formal_data = self.data(code, res)
+        return json.dumps(formal_data, ensure_ascii=False)
+
+    def json(self, code, res={}):
+        result = self.formal(code, res)
+        return HttpResponse(result)

+ 42 - 0
Object/UidTokenObject.py

@@ -0,0 +1,42 @@
+#!/usr/bin/env python3  
+# -*- coding: utf-8 -*-  
+"""
+@Copyright (C) ansjer cop Video Technology Co.,Ltd.All rights reserved.
+@AUTHOR: ASJRD018
+@NAME: AnsjerFormal
+@software: PyCharm
+@DATE: 2018/12/5 11:52
+@Version: python3.6
+@MODIFY DECORD:ansjer dev
+@file: UidTokenObject.py
+@Contact: chanjunkai@163.com
+"""
+from AnsjerPush.config import UID_TOKEN_KEY
+import jwt
+
+
+class UidTokenObject:
+
+    def __init__(self, token=None):
+        self.token = token
+        self.UID = ''
+        self.channel = ''
+        self.flag = self.valid()
+
+    def valid(self):
+        token = self.token
+        if self.token is None:
+            return False
+        res = jwt.decode(token, UID_TOKEN_KEY, algorithms='HS256')
+        print(res)
+        UID = res.get('uid', None)
+        channel = res.get('channel', None)
+        if UID is None:
+            return False
+        self.UID = UID
+        self.channel = channel
+
+    def generate(self, data={}):
+        token = jwt.encode(data, UID_TOKEN_KEY, algorithm='HS256').decode('utf-8')
+        self.token=token
+        return token

+ 15 - 0
manage.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == '__main__':
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'AnsjerPush.settings')
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)

+ 29 - 0
requirements.txt

@@ -0,0 +1,29 @@
+Django > 2
+
+django-cors-headers
+django-imagekit
+django-guardian
+django-rest-framework
+simplejson
+djangorestframework-jwt
+South
+qcloudsms_py
+itsdangerous
+openpyxl
+xlrd
+mysqlclient
+boto3
+requests_aws4auth
+ffmpy
+xmltodict
+var_dump
+django-middleware-global-request
+oss2
+aliyun-python-sdk-sts
+jpush
+pyipip
+boto
+django-ratelimit
+paypalrestsdk
+pymongo
+apns2-client