kboss/b/user/mobilecode.dspy
2026-05-11 15:51:49 +08:00

140 lines
5.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

async def handle_login_failed(mobile: str) -> bool:
"""检查短信发送限制,十分钟内最多发送三次"""
from datetime import datetime, timedelta
db = DBPools()
async with db.sqlorContext('kboss') as sor:
# 查询该手机号的发送记录
records = await sor.R('sms_limit', {'mobile': mobile})
current_time = datetime.now()
if len(records) == 0:
# 首次发送,创建记录
await sor.C('sms_limit', {
'mobile': mobile,
'first_send_time': current_time,
'send_count': 1,
'last_send_time': current_time,
'lock_until': None
})
return True
record = records[0]
lock_until = record.get('lock_until', None)
if lock_until:
lock_until = datetime.strptime(lock_until, '%Y-%m-%d %H:%M:%S')
# 检查是否在锁定时间内
if record.get('lock_until') and current_time < lock_until:
return False
# 检查十分钟内的发送次数
if record.get('first_send_time'):
first_send_time = datetime.strptime(record['first_send_time'], '%Y-%m-%d %H:%M:%S')
time_diff = current_time - first_send_time
if time_diff < timedelta(minutes=10):
# 十分钟内,检查发送次数
if record.get('send_count', 0) >= 3:
# 超过三次锁定10分钟
lock_time = current_time + timedelta(minutes=10)
sql = "update sms_limit set lock_until='%s' where mobile='%s'" % (
lock_time,
mobile
)
await sor.sqlExe(sql, {})
return False
else:
# 未超过三次,增加计数
sql = "update sms_limit set send_count='%s', last_send_time='%s' where mobile='%s'" % (
record['send_count'] + 1,
current_time,
mobile
)
await sor.sqlExe(sql, {})
return True
else:
# 超过十分钟,重置计数
sql = "update sms_limit set first_send_time='%s', send_count='%s', last_send_time='%s', lock_until=NULL where mobile='%s'" % (
current_time,
1,
current_time,
mobile
)
await sor.sqlExe(sql, {})
return True
return True
async def mobilecode(ns):
"""发送短信验证码,支持注册和登录筛选"""
db = DBPools()
async with db.sqlorContext('kboss') as sor:
# 获取操作类型register 或 login
action_type = ns.get('action_type') # register 或 login
if not action_type:
return {'status': False, 'msg': '操作类型action_type不能为空'}
# 通过手机号查找用户
mobile = ns.get('mobile')
if not mobile:
return {'status': False, 'msg': '手机号不能为空'}
# 检查短信发送限制
can_send = await handle_login_failed(mobile)
if not can_send:
return {'status': False, 'msg': '发送过于频繁请10分钟后再试'}
userreacs = await sor.R('users', {'mobile': mobile, 'del_flg': '0'})
# 注册逻辑:检查手机号是否已存在
if action_type == 'register':
if len(userreacs) >= 1:
return {'status': False, 'msg': '手机号已注册,请直接登录'}
else:
# 注册时手机号不存在,可以发送验证码
code = await generate_vcode()
nss = await send_vcode(mobile, '用户注册登录验证', {'SMSvCode': code.get('vcode')})
if nss['status']:
return {'status': True, 'msg': '注册验证码发送成功', 'codeid': code.get('id')}
else:
return {'status': False, 'msg': '发送失败'}
# 登录逻辑:检查手机号是否存在
elif action_type == 'login':
if len(userreacs) >= 1:
# 登录时手机号存在,可以发送验证码
code = await generate_vcode()
nss = await send_vcode(userreacs[0]['mobile'], '用户注册登录验证', {'SMSvCode': code.get('vcode')})
if nss['status']:
return {'status': True, 'msg': '登录验证码发送成功', 'codeid': code.get('id')}
else:
return {'status': False, 'msg': '发送失败'}
else:
return {'status': False, 'action': 'redirect', 'msg': '用户未注册, 请到注册页面注册'}
# 原有逻辑如果没有指定action_type保持原有逻辑
else:
type = 0
ns['del_flg'] = '0'
userreacs = await sor.R('users', ns)
if len(userreacs) >= 1:
type += 1
else:
userreacs = await sor.R('users', {'mobile': ns['username'], 'del_flg': '0'})
if len(userreacs) >= 1:
type += 1
if type >= 1:
code = await generate_vcode()
nss = await send_vcode(userreacs[0]['mobile'], '用户注册登录验证', {'SMSvCode': code.get('vcode')})
# return {'1':nss}
if nss:
return {'status': True, 'msg': '发送成功', 'codeid': code.get('id')}
else:
return {'status': False, 'msg': '发送失败'}
else:
return {'status': False, 'action': 'redirect', 'msg': '用户未注册, 请到注册页面注册'}
ret = await mobilecode(params_kw)
return ret