def trigger_msg_add(self, contact, trigger, content, symbol, location=None, **kwargs): """ 触发消息添加 """ assert isinstance(contact, Contact) assert trigger in mc.TriggerType, f'trigger_error {contact.pk} {trigger} {symbol}' conv_info = contact.conv_info msg_body = dict(trigger=trigger, **kwargs) last_msg = conv_info.last_self_msg(contact.usrid) if isinstance(last_msg, Message) and last_msg.is_trigger and last_msg.is_conv_newest: created_at = deal_time.time_floor_ts(last_msg.created_at) if deal_time.get_now().diff(created_at).in_minutes() < 30: return last_msg # 30分钟内,重复触发消息,之前返回之前的消息 read_at = deal_time.get_now() # 触发消息,默认已读 conv_info.update_symbol(symbol) msg_type = mc.MSGType.Trigger msg = self._msg_create( convid=contact.convid, sender=contact.usrid, receiver=contact.touchid, symbol=symbol, msg_type=msg_type, msg_body=msg_body, content=content, location=location, read_at=read_at, ) return msg
def run_pipelines(pipelines): """ 执行 """ from server.corelib.dealer.deal_time import get_now c = Connection(Host.DaowoApi.value) result = disk_free(c) print(f'=> {disk_free.__doc__}: {result}\n') for stage, (doc, command) in enumerate(pipelines): dt_start = get_now() time_str = dt_start.format('HH:mm:ss') print(f'\n\n[{time_str}] Stage {stage + 1} => {doc}:\n{command} ...\n') pty = str(command).startswith('sudo') c.run(command, pty=pty, watchers=[sudopass]).stdout.strip() ts_us = (get_now() - dt_start).in_seconds() print(f'Stage {stage + 1} use {ts_us}S') print('\n\nrun_pipelines done :)')
def fe_oss_token(scene, ext, usrid): """ 客户端直接上传OSS,服务端签名 """ assert isinstance(usrid, int) and usrid > 0, usrid name = f'{idshift.generate_captcha()}.{ext}' oss_key = get_oss_key(scene, name, usrid) expire_syncpoint = int(get_now().add(seconds=30).timestamp()) expire_str = pendulum.from_timestamp(expire_syncpoint).to_iso8601_string() condition_array = [{'key': oss_key.key}] policy_dict = {'expiration': expire_str, 'conditions': condition_array} policy = json.dumps(policy_dict).strip() policy_encode = base64.b64encode(policy.encode()) hsha = hmac.new(ak_cfg.secret.encode(), policy_encode, sha) sign_result = base64.encodebytes(hsha.digest()).strip() result = { 'akid': ak_cfg.ak, 'key': oss_key.key, 'name': oss_key.name, 'updir': oss_key.updir, 'url': oss_sign_url(oss_key.key), 'policy': policy_encode.decode(), 'signature': sign_result.decode(), 'host': bucket_cfg.bucket_public_url, 'expire': expire_syncpoint, } return result
def send_wxsm_for_staymsg(): """ 发送未读消息提醒,每三分钟执行一次 """ from server.applibs.convert.models import Message now = deal_time.get_now().replace(second=0) assert isinstance(now, pendulum.DateTime) time_begin = now.add(minutes=-5) time_end = now.add(minutes=-2) msg_qs = Message.objects.filter( msg_type=mc.MSGType.StayMsg, created_at__gte=time_begin, created_at__lt=time_end, read_at__isnull=True, is_del=False, ).order_by('-pk') count = msg_qs.count() receiver_set = set() for msg in msg_qs: if msg.receiver in receiver_set: logger.info(f'send_wxsm_for_staymsg__repeat {msg.pk} {msg.receiver}') continue receiver_set.add(msg.receiver) task_wxsm = send_wxsm_for_msg_one.delay(msg.pk) logger.info(f'send_wxsm_for_msg_one__task {msg.pk} {task_wxsm}') result = dict( task='send_wxsm_for_staymsg', time_begin=time_begin.isoformat(), time_end=time_end.isoformat(), receivers=list(receiver_set), dealed=len(receiver_set), count=count, ) return result
def init_to_prepared(self, request, queryset): now = deal_time.get_now() rows_updated = queryset.filter(status=mc.PublishStatus.Init, ).update( published_at=now, status=mc.PublishStatus.Prepared, ) self.message_user(request, f'[{rows_updated}]条[初始化]记录已标记为[已就绪]。')
def mark_delete(self, memo=''): """ 标记删除 """ if self.is_del: return self.is_del = True self.save(update_fields=['is_del', 'updated_at']) now = deal_time.get_now() self.extra_log('del', pk=self.pk, now=now, memo=memo)
def extra_log(self, key, **kwargs): """ 添加扩展信息 """ now = deal_time.get_now() now_ts = int(now.timestamp()) new_key = f'log-{key}-{now_ts}' kwargs['_at'] = now.isoformat() value = json.loads(json.dumps(kwargs, cls=DjangoJSONEncoder)) self.extra[new_key] = encrypt_dic(value) self.save(update_fields=['extra', 'updated_at'])
def is_ucoff_switch(self): """ 是否用户码及通话关闭 """ now = deal_time.get_now() is_off = self.filter( cate=mc.ConfCate.UCOff, begin_at__lte=now, finish_at__gt=now, is_active=True, ).exists() return is_off
def mark_read(self): """ 标记已读 """ now = deal_time.get_now() if self.unread == 0: logger.info(f'contact__marked_read {self.usrid}') return for msg in self.unread_msg_qs: msg.mark_read(self.usrid, now) self.unread, self.read_at = 0, now self.save(update_fields=['unread', 'read_at', 'updated_at']) self.rtm_event_open_conv() # 更新不同设备未读消息量
def need_refresh(self): """ 是否需要刷新 """ if self.expire_time is None: logger.info(f'{self.tk_desc} need_refresh no expire_time') return True now = get_now() expire = get_tzcn_parse(self.expire_time) # 失效时间与当前系统时间比较,提前2分钟刷新Token if (expire - now).seconds < 120: logger.info(f'{self.tk_desc} need_refresh {now} ~ {expire}') return True return False
def idcard_approve(self, img_front, img_back, front_dic, back_dic, usrid): assert isinstance(usrid, int) and usrid > 0, usrid if not all( [front_dic.get('type') == 'front', back_dic.get('type') == 'back']): return False, '无法识别' if any([front_dic.get('_rate', 0) < 95, back_dic.get('_rate', 0) < 95]): return False, '无法准确识别' name = front_dic.get('name') end_date = back_dic.get('endDate') number = str(front_dic.get('number')).upper() if not (name and number and end_date): return False, '无法识别有效信息' if not is_valid_idcard(number): return False, '身份证号不合法' today = get_now().date() end_date = get_tzcn_date_parse(end_date) if end_date and ((end_date - today).days < 50): return False, '身份证已过期' if ( (end_date - today).days < 0) else '身份证到期时间不足50天' if self.filter(number=number, is_valid=True).exclude(usrid=usrid).exists(): return False, '已被其他用户认证' is_ok, third_msg = self.check_idcard_third(name, number) if not is_ok: return False, third_msg oss_keys = dict(front=img_front, back=img_back) defaults = dict( usrid=usrid, oss_keys=oss_keys, name=front_dic['name'], sex=front_dic['sex'], nationality=front_dic['nationality'], birth=get_tzcn_date_parse(front_dic['birth']), address=front_dic['address'], authority=back_dic['authority'], start_date=get_tzcn_date_parse(back_dic['startDate']), end_date=get_tzcn_date_parse(back_dic['endDate']), ) inst, is_created = self.get_or_create( number=number, shahash=idshift.hash_sha1(number), defaults=defaults, ) if not is_created: for k, v in defaults.items(): setattr(inst, k, v) inst.save(update_fields=defaults.keys()) inst.extra_log('third-msg', msg=third_msg) inst.extra_log('usrid', usrid=usrid) is_ok, resp = inst.img_hold_on() return is_ok, resp
def check_valid(self): """ 检查是否有效 """ if not self.is_valid: return False if not self.session: self.logout(self.usrid, 'no session') return False now = get_now() if self.session.expire_date < now: self.logout(self.usrid, 'expired') return False return True
def logout(self, usrid, reason=''): """ 退出登录 """ if not self.is_valid: return if not self.usrid == usrid: return store = SessionStore() assert isinstance(store, SessionBase) store.delete(self.key) self.is_valid = False self.logout_at = get_now() self.save(update_fields=['is_valid', 'logout_at', 'updated_at']) self.extra_log('logout', usrid=usrid, reason=reason)
def bind_user(self, user): from .authuser import AuthUser assert isinstance(user, AuthUser) if self.usrid == user.pk: logger.info(f'oauth_wechat_bind_user__same {self.pk}:{self.usrid}') return # 已绑定过相同用户 if self.usrid: logger.warning( f'oauth_wechat_bind_user__warn {self.pk}:{self.usrid} {user.pk}' ) return self.usrid = user.pk self.link_at = get_now() self.save(update_fields=['usrid', 'link_at', 'updated_at'])
def get_oss_key(scene, filename, instid): """ 根据场景获取OSS路径 """ now = get_now() prefix = now.format('HHmm') today = now.format('YYYYMMDD') upload_dir = f'{scene}/{today}' name, ext = os.path.splitext(filename) uuid_key = idshift.generate_uuid5().hex[:8] name_key = idshift.generate_name_uuid(name).hex[-6:] instid = str(instid or f'none_{now.second}').lower() assert isinstance(scene, str) and scene in OSSDir, f'{scene}' new_name = f'{prefix}-{name_key}-{uuid_key}-{instid}{ext}' key = f'{upload_dir}/{new_name}' oss_key = OSSkey(key=key, name=new_name, updir=upload_dir) return oss_key
def do_action(self): now = get_now() now_str = now.format('YYYYMMDDHHmmss') sign = hash_md5(f'{const.ACCOUNT_SID}{const.AUTH_TOKEN}{now_str}') authorization = base64.b64encode( f'{const.ACCOUNT_SID}|{now_str}'.encode()).decode() headers = { 'Accept': 'application/json;', 'Content-Type': 'application/json;charset=utf-8;', 'Authorization': authorization, } resp_dic = self._request.post( self.url, json=self._params, params=dict(Sign=sign), headers=headers, ).json() return resp_dic
def query_call_ytx(self): """ 云讯,话单获取 """ if not (self.req_id and (self.provider == mc.ThirdProvider.YTX)): warn_msg = f'query_ytx__info_error {self.pk} {self.provider}' capture_message(warn_msg) logger.warning(warn_msg) return now = deal_time.get_now() created_at = deal_time.time_floor_ts(self.created_at) cut_seconds = (now - created_at).seconds if cut_seconds < 20: logger.warning(f'query_ytx__too_early {self.pk} {cut_seconds}') return # 查询太早没有结果 result = ytx_apis.YTXCallCdrByResIdOneApi( lastresid=self.req_id ).fetch_result() if not isinstance(result, dict): return # 无查询结果 self.call_result_ytx_up(result, action='query')
def count_thirdapi_increase(self, provider, action, result_type='success', use_ms=0): inst, _ = self.get_or_create( dt_req=get_now().date(), provider=provider, action=action, ) up_fields = ['count'] inst.count = models.F('count') + 1 field_name = f'ct_{result_type}' if not hasattr(inst, field_name): logger.warning(f'count_thirdapi_increase__field_error {inst.pk} {field_name}') return inst up_fields.append(field_name) setattr(inst, field_name, models.F(field_name) + 1) if result_type == mc.ThirdResultType.Success: inst.ms_success = models.F('ms_success') + use_ms up_fields.append('ms_success') inst.save(update_fields=up_fields) return inst
def oauth_wechat_mpa_goc(self, code, encrypted, iv): """ 微信小程序OAuth记录 """ try: if len(code) > 20: # 微信Code,兼容老逻辑 inst_app = OAuthWechatApp.objects.oauth_wechat_mpapp_up(code) else: app_id = pk_hashid_decode(code) inst_app = OAuthWechatApp.objects.get(pk=app_id) context = wx_data_decrypt(encrypted, inst_app.session_key, iv) unionid = context['unionId'] except (IndexError, OAuthWechatApp.DoesNotExist) as exc: exc_msg = f'wx_get_session_key__error {str(exc)}' logger.exception(exc_msg) capture_message(exc_msg) capture_exception(exc) raise Exception('获取登录凭证失败') except Exception as exc: exc_msg = f'wx_data_decrypt__error {str(exc)}' logger.exception(exc_msg) capture_message(exc_msg) capture_exception(exc) raise Exception('登录凭证已失效请重试') from server.applibs.account.models.authuser import AuthUser inst_wx, is_created = self.get_or_create( unionid=unionid, defaults=dict(context=context)) if is_created: inst_wx.load_wechat_info() inst_wx.link_at = get_now() inst_wx.usrid = AuthUser.objects.create_authuser(inst_wx.name).pk inst_wx.save(update_fields=['usrid', 'link_at', 'updated_at']) inst_wx.wxinfo_sync_profile() else: inst_wx.context = context inst_wx.save(update_fields=['context', 'updated_at']) inst_wx.load_wechat_info() inst_wx.openids[mc.WXAPPType.MPA.value] = inst_app.openid inst_wx.save(update_fields=['openids', 'updated_at']) inst_app.unionid, inst_app.usrid = unionid, inst_wx.usrid inst_app.save(update_fields=['unionid', 'usrid', 'updated_at']) logger.info(f'oauth_wechat_mpa_goc__done {inst_wx.pk} {is_created}') return inst_wx
def activate(self, usrid): """ 场景码激活绑定 """ if self.usrid: return False, f'{self.scened}已被绑定' if not (self.status == mc.PublishStatus.Prepared): return False, f'{self.scened}暂不可用' self.usrid = usrid self.activated_at = deal_time.get_now() self.status = mc.PublishStatus.Activated self.save( update_fields=['usrid', 'status', 'activated_at', 'updated_at']) from server.applibs.release.models import Symbol inst = Symbol.objects.create( symbol=self.symbol, usrid=self.usrid, scene=self.scene, status=mc.SymbolStatus.Bound, bound_at=self.activated_at, version=self.version, ) return True, inst
def daily_status_count(date=None): """ 每日通信状态统计 """ from server.applibs.account.models import PNVerify from server.applibs.outside.models import SmsRecord, CallRecord now = deal_time.get_now() if not isinstance(date, datetime.date): date = now.add(days=-1).date() time_start = datetime.datetime.combine(date, datetime.time.min) time_start = pendulum.instance(time_start, tz=TZCN) time_end = time_start.add(days=1) pnv_qs = PNVerify.objects.filter( created_at__gte=time_start, created_at__lt=time_end, ).values_list('status').annotate(total=Count('status'), ).order_by('total') pnv_dic = OrderedDict(pnv_qs) sms_qs = SmsRecord.objects.filter( created_at__gte=time_start, created_at__lt=time_end, ).values_list('status').annotate(total=Count('status')).order_by('total') sms_dic = OrderedDict(sms_qs) call_qs = CallRecord.objects.filter( created_at__gte=time_start, created_at__lt=time_end, ).values_list('status').annotate(total=Count('status')).order_by('total') call_dic = OrderedDict(call_qs) dd_msg = f'每日通信统计:' dd_msg += f'\n短信验证码:{json.dumps(pnv_dic)}' dd_msg += f'\n短信通知:{json.dumps(sms_dic)}' dd_msg += f'\n语音通话:{json.dumps(call_dic)}' send_dd_msg__task(dd_msg) result = dict( task='daily_status_count', pnv_dic=pnv_dic, sms_dic=sms_dic, call_dic=call_dic, end_at=time_end.isoformat(), start_at=time_start.isoformat(), now=now.isoformat(), ) return result
def oauth_wechat_mpapp_up(self, code): """ 微信小程序WXCodeSession """ try: openid, skey = WXCodeSession(code=code).get_result() except Exception as exc: exc_msg = f'wx_code_session__error' logger.warning(f'{exc_msg} {str(exc)}') logger.exception(exc_msg) capture_message(exc_msg) capture_exception(exc) raise Exception('登录凭证校验失败') inst_app, is_created = self.get_or_create( app_type=mc.WXAPPType.MPA, openid=openid, ) inst_app.session_key = skey inst_app.session_at = get_now() inst_app.save( update_fields=['session_key', 'session_at', 'updated_at']) logger.info( f'oauth_wechat_mpapp_up__done {openid} {inst_app.pk} {is_created}') return inst_app