阿龙电竞后端已经修复了提现问题,聊天问题,管式商家分红最新代码
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
# utils/chat_utils.py
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from dingdan.models import Dingdan, DingdanPingtai, DingdanShangjia
|
||||
from dingdan.models import Dingdan, DingdanPingtai, DingdanShangjia, Liaotian
|
||||
from peizhi.models import ClubConfig
|
||||
from yonghu.models import UserMain, UserDashou, UserBoss, UserShangjia
|
||||
|
||||
@@ -137,6 +138,118 @@ def _send_group_message(appkey, secret, group_id, sender_id, sender_name, sender
|
||||
logger.error(f"发送群聊消息异常: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
def _retry_call(func, max_retries=5, delay=0.4, *args, **kwargs):
|
||||
"""对 GoEasy 等外部调用做短重试,提高抢单后建聊成功率"""
|
||||
for attempt in range(1, max_retries + 1):
|
||||
try:
|
||||
if func(*args, **kwargs):
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"{func.__name__} 第{attempt}次失败: {e}")
|
||||
if attempt < max_retries:
|
||||
time.sleep(delay * attempt)
|
||||
return False
|
||||
|
||||
def _send_private_init_message(appkey, secret, sender_id, sender_name, sender_avatar,
|
||||
receiver_id, receiver_name, receiver_avatar, message_text):
|
||||
if not appkey:
|
||||
appkey = _get_self_goeasy_appkey()
|
||||
if not secret:
|
||||
secret = _get_self_goeasy_secret()
|
||||
if not appkey:
|
||||
return False
|
||||
|
||||
url = 'https://rest-hangzhou.goeasy.io/v2/im/message'
|
||||
request_body = {
|
||||
"appkey": appkey,
|
||||
"senderId": sender_id,
|
||||
"senderData": {"avatar": sender_avatar or "", "name": sender_name or sender_id},
|
||||
"to": {
|
||||
"type": "private",
|
||||
"id": receiver_id,
|
||||
"data": {"avatar": receiver_avatar or "", "name": receiver_name or receiver_id}
|
||||
},
|
||||
"type": "text",
|
||||
"payload": message_text
|
||||
}
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if secret:
|
||||
headers["Authorization"] = f"Bearer {secret}"
|
||||
try:
|
||||
resp = requests.post(url, headers=headers, json=request_body, timeout=10)
|
||||
if resp.status_code == 200:
|
||||
return True
|
||||
logger.error(f"私聊初始化消息失败: {resp.status_code} {resp.text}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"私聊初始化消息异常: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
def _ensure_liaotian_record(dingdan_id, partner_goeasy_id, dashou_goeasy_id):
|
||||
try:
|
||||
Liaotian.objects.update_or_create(
|
||||
dingdan_id=dingdan_id,
|
||||
defaults={
|
||||
'user1_id': partner_goeasy_id,
|
||||
'user2_id': dashou_goeasy_id,
|
||||
'zhuangtai': 1,
|
||||
}
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"写入 Liaotian 记录失败 order={dingdan_id}: {e}", exc_info=True)
|
||||
return False
|
||||
|
||||
def _establish_private_chat(appkey, secret, dashou_goeasy_id, dashou_name, dashou_avatar,
|
||||
partner_goeasy_id, partner_name, partner_avatar):
|
||||
msg_dashou = "订单已接单,可在此处沟通。"
|
||||
msg_partner = "打手已接单,可在此处沟通。"
|
||||
ok1 = _retry_call(
|
||||
_send_private_init_message, 3, 0.4,
|
||||
appkey, secret, dashou_goeasy_id, dashou_name, dashou_avatar,
|
||||
partner_goeasy_id, partner_name, partner_avatar, msg_dashou
|
||||
)
|
||||
ok2 = _retry_call(
|
||||
_send_private_init_message, 3, 0.4,
|
||||
appkey, secret, partner_goeasy_id, partner_name, partner_avatar,
|
||||
dashou_goeasy_id, dashou_name, dashou_avatar, msg_partner
|
||||
)
|
||||
return ok1 or ok2
|
||||
|
||||
def _resolve_goeasy_user_display(goeasy_id):
|
||||
if not goeasy_id:
|
||||
return "用户", _full_local_avatar('')
|
||||
avatar = _full_local_avatar('')
|
||||
name = f"用户{goeasy_id[-6:]}"
|
||||
try:
|
||||
if goeasy_id.startswith('Boss'):
|
||||
uid = goeasy_id[4:]
|
||||
boss_user = UserMain.objects.get(yonghuid=uid)
|
||||
avatar = _full_local_avatar(boss_user.avatar or '')
|
||||
boss_profile = UserBoss.objects.get(user=boss_user)
|
||||
if boss_profile.nickname:
|
||||
name = boss_profile.nickname
|
||||
elif goeasy_id.startswith('Sj'):
|
||||
uid = goeasy_id[2:]
|
||||
sj_user = UserMain.objects.get(yonghuid=uid)
|
||||
avatar = _full_local_avatar(sj_user.avatar or '')
|
||||
try:
|
||||
sj_profile = UserShangjia.objects.get(user=sj_user)
|
||||
if sj_profile.nicheng:
|
||||
name = sj_profile.nicheng
|
||||
except Exception:
|
||||
pass
|
||||
elif goeasy_id.startswith('Ds'):
|
||||
uid = goeasy_id[2:]
|
||||
ds_user = UserMain.objects.get(yonghuid=uid)
|
||||
avatar = _full_local_avatar(ds_user.avatar or '')
|
||||
ds_profile = UserDashou.objects.get(user=ds_user)
|
||||
if ds_profile.nicheng:
|
||||
name = ds_profile.nicheng
|
||||
except Exception as e:
|
||||
logger.warning(f"解析 GoEasy 用户展示信息失败 {goeasy_id}: {e}")
|
||||
return name, avatar
|
||||
|
||||
# ========== 核心入口 ==========
|
||||
def establish_order_chat(dingdan_id):
|
||||
try:
|
||||
@@ -177,6 +290,20 @@ def establish_order_chat(dingdan_id):
|
||||
else:
|
||||
return False
|
||||
|
||||
def establish_order_chat_with_retry(dingdan_id, max_rounds=3):
|
||||
"""抢单后建聊入口:多轮重试,尽量保证建立成功"""
|
||||
for round_num in range(1, max_rounds + 1):
|
||||
try:
|
||||
if establish_order_chat(dingdan_id):
|
||||
logger.info(f"订单 {dingdan_id} 建聊成功(第{round_num}轮)")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"订单 {dingdan_id} 建聊第{round_num}轮异常: {e}", exc_info=True)
|
||||
if round_num < max_rounds:
|
||||
time.sleep(0.8 * round_num)
|
||||
logger.error(f"订单 {dingdan_id} 建聊最终失败")
|
||||
return False
|
||||
|
||||
# ========== 普通订单 / 我方派单 ==========
|
||||
def _handle_local_order(order, dashou_goeasy_id, dashou_name, dashou_avatar, appkey, secret):
|
||||
group_id = f"group_{order.dingdan_id}"
|
||||
@@ -185,36 +312,61 @@ def _handle_local_order(order, dashou_goeasy_id, dashou_name, dashou_avatar, app
|
||||
|
||||
partner_goeasy_id, partner_name, partner_avatar = _get_local_partner_info(order)
|
||||
if not partner_goeasy_id:
|
||||
return False
|
||||
logger.error(f"订单 {order.dingdan_id} 无法获取下单方 GoEasy 标识")
|
||||
subscribe_ok = _retry_call(
|
||||
_subscribe_users_to_group, 5, 0.4,
|
||||
[dashou_goeasy_id], [group_id], appkey, secret
|
||||
)
|
||||
msg_ok = _retry_call(
|
||||
_send_group_message, 3, 0.4,
|
||||
appkey, secret, group_id, dashou_goeasy_id, dashou_name, group_avatar,
|
||||
"订单已接单,请等待对方上线。", None, group_name=group_name,
|
||||
order_id=order.dingdan_id, is_cross=order.is_cross
|
||||
)
|
||||
return subscribe_ok or msg_ok
|
||||
|
||||
# 订阅双方
|
||||
if not _subscribe_users_to_group([dashou_goeasy_id, partner_goeasy_id], [group_id], appkey, secret):
|
||||
return False
|
||||
subscribe_ok = _retry_call(
|
||||
_subscribe_users_to_group, 5, 0.4,
|
||||
[dashou_goeasy_id, partner_goeasy_id], [group_id], appkey, secret
|
||||
)
|
||||
|
||||
# 1. 打手发送初始化消息
|
||||
init_msg_text = f"订单已接单,内容:{order.jieshao},备注:{order.beizhu},游戏ID:{order.nicheng}"
|
||||
success1 = _send_group_message(
|
||||
success1 = _retry_call(
|
||||
_send_group_message, 3, 0.4,
|
||||
appkey, secret, group_id, dashou_goeasy_id, dashou_name, group_avatar,
|
||||
init_msg_text, None, group_name=group_name, order_id=order.dingdan_id,
|
||||
is_cross=order.is_cross
|
||||
)
|
||||
|
||||
# 2. 【新增】派单方也发一条消息,确保他也能看到群聊
|
||||
partner_msg = f"订单已确认,请开始服务。"
|
||||
success2 = _send_group_message(
|
||||
partner_msg = "订单已确认,请开始服务。"
|
||||
success2 = _retry_call(
|
||||
_send_group_message, 3, 0.4,
|
||||
appkey, secret, group_id, partner_goeasy_id, partner_name, partner_avatar,
|
||||
partner_msg, None, group_name=group_name, order_id=order.dingdan_id,
|
||||
is_cross=order.is_cross
|
||||
)
|
||||
|
||||
return success1 and success2
|
||||
liaotian_ok = _ensure_liaotian_record(order.dingdan_id, partner_goeasy_id, dashou_goeasy_id)
|
||||
private_ok = _establish_private_chat(
|
||||
appkey, secret, dashou_goeasy_id, dashou_name, dashou_avatar,
|
||||
partner_goeasy_id, partner_name, partner_avatar
|
||||
)
|
||||
|
||||
result = subscribe_ok or success1 or success2 or liaotian_ok or private_ok
|
||||
if not result:
|
||||
logger.error(f"订单 {order.dingdan_id} 群聊/私聊均未建立成功")
|
||||
return result
|
||||
|
||||
def _get_local_partner_info(order):
|
||||
"""本地订单下单方:老板或商家"""
|
||||
if order.fadan_pingtai == 1: # 老板
|
||||
if order.fadan_pingtai == 1:
|
||||
try:
|
||||
ext = order.pingtai_kuozhan
|
||||
laoban_id = ext.laoban_id
|
||||
except Exception:
|
||||
ext = DingdanPingtai.objects.filter(dingdan__dingdan_id=order.dingdan_id).first()
|
||||
laoban_id = ext.laoban_id if ext else None
|
||||
if laoban_id:
|
||||
avatar_full = _full_local_avatar('')
|
||||
nickname = f'老板{laoban_id[:6]}'
|
||||
try:
|
||||
@@ -226,14 +378,20 @@ def _get_local_partner_info(order):
|
||||
except Exception:
|
||||
pass
|
||||
return f"Boss{laoban_id}", nickname, avatar_full
|
||||
except Exception as e:
|
||||
logger.error(f"获取老板信息失败: {e}")
|
||||
return None, None, None
|
||||
elif order.fadan_pingtai == 2: # 商家
|
||||
elif order.fadan_pingtai == 2:
|
||||
try:
|
||||
ext = order.shangjia_kuozhan
|
||||
shangjia_id = ext.shangjia_id
|
||||
nickname = ext.sjnicheng or f'商家{shangjia_id[:6]}'
|
||||
except Exception:
|
||||
ext = DingdanShangjia.objects.filter(dingdan__dingdan_id=order.dingdan_id).first()
|
||||
if not ext:
|
||||
shangjia_id = None
|
||||
nickname = '商家'
|
||||
else:
|
||||
shangjia_id = ext.shangjia_id
|
||||
nickname = ext.sjnicheng or f'商家{shangjia_id[:6]}'
|
||||
if shangjia_id:
|
||||
avatar_full = _full_local_avatar('')
|
||||
try:
|
||||
sj_user = UserMain.objects.get(yonghuid=shangjia_id)
|
||||
@@ -241,13 +399,11 @@ def _get_local_partner_info(order):
|
||||
except Exception:
|
||||
pass
|
||||
return f"Sj{shangjia_id}", nickname, avatar_full
|
||||
except Exception as e:
|
||||
logger.error(f"获取商家信息失败: {e}")
|
||||
return None, None, None
|
||||
else:
|
||||
if order.user1_id:
|
||||
return order.user1_id, "用户", _full_local_avatar('')
|
||||
return None, None, None
|
||||
|
||||
if order.user1_id:
|
||||
name, avatar = _resolve_goeasy_user_display(order.user1_id)
|
||||
return order.user1_id, name, avatar
|
||||
return None, None, None
|
||||
|
||||
# ========== 跨平台 + 对方派单 ==========
|
||||
def _handle_cross_partner_order(order, dashou_goeasy_id, dashou_name, dashou_avatar, appkey, secret):
|
||||
@@ -370,5 +526,16 @@ def _get_cross_partner_identity(order, partner_order_id):
|
||||
|
||||
def _create_local_group_only(order, dashou_goeasy_id, dashou_name, dashou_avatar, appkey, secret):
|
||||
group_id = f"group_{order.dingdan_id}"
|
||||
_subscribe_users_to_group([dashou_goeasy_id], [group_id], appkey, secret)
|
||||
return False
|
||||
group_name = (order.jieshao[:20] + '…') if order.jieshao and len(order.jieshao) > 20 else (order.jieshao or f"订单{order.dingdan_id}")
|
||||
group_avatar = _full_local_avatar(order.tupian) if order.tupian else _full_local_avatar('')
|
||||
subscribe_ok = _retry_call(
|
||||
_subscribe_users_to_group, 5, 0.4,
|
||||
[dashou_goeasy_id], [group_id], appkey, secret
|
||||
)
|
||||
msg_ok = _retry_call(
|
||||
_send_group_message, 3, 0.4,
|
||||
appkey, secret, group_id, dashou_goeasy_id, dashou_name, group_avatar,
|
||||
"订单已接单。", None, group_name=group_name, order_id=order.dingdan_id,
|
||||
is_cross=order.is_cross
|
||||
)
|
||||
return subscribe_ok or msg_ok
|
||||
Reference in New Issue
Block a user