dog_transfer.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. import hashlib
  2. from django.http import HttpResponse,JsonResponse
  3. from django.views.decorators.csrf import csrf_exempt
  4. from datetime import datetime, timedelta
  5. from django.utils import timezone
  6. from django.core import serializers
  7. import time
  8. import json
  9. import os
  10. import jwt
  11. from .models import DogTrainingNew
  12. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "aiDogProject.settings")
  13. import django
  14. django.setup()
  15. from aiDogApp.models import *
  16. from . import aidog_tools,aidog_request_tools
  17. # 转移一只狗(赠送者)接口
  18. # 使用access_token登录 请求参数:access_token、user_id,dog_id,datetime
  19. # 返回格式:result、message、"transfer_code": "string"
  20. # 赠送中:pending,赠送完成:completed,赠送取消:cancelled,赠送失败:failed
  21. # 2025-5-19 author Feng
  22. @csrf_exempt
  23. @csrf_exempt
  24. def send_dog_2_other(request):
  25. # 记录请求时间
  26. current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  27. try:
  28. # 获取请求参数
  29. access_token = request.POST.get("access_token", '')
  30. user_id = request.POST.get("user_id", '')
  31. dog_id = request.POST.get("dog_id", '')
  32. req_datetime = request.POST.get("datetime", '')
  33. # 验证请求参数
  34. if not all([access_token, dog_id]):
  35. return JsonResponse({
  36. "status": "error",
  37. "date": current_time,
  38. "message": "Please ensure all required fields are provided!",
  39. "end_time": current_time
  40. })
  41. # 验证访问令牌
  42. token_validation = aidog_tools.validate_access_token(access_token)
  43. if isinstance(token_validation, JsonResponse):
  44. return token_validation
  45. # 从令牌验证中获取验证后的用户ID
  46. validated_user_id = token_validation['user_id']
  47. # 确保用户ID与令牌匹配
  48. if user_id and user_id != validated_user_id:
  49. return JsonResponse({
  50. "status": "error",
  51. "date": current_time,
  52. "message": "User ID does not match with access token",
  53. "end_time": current_time
  54. })
  55. # 使用验证过的用户ID
  56. user_id = validated_user_id
  57. try:
  58. # 检查当前用户拥有的狗数量是否 >= 2
  59. # owner_dogs = Doginfo.objects.filter(owner_id=user_id, is_active=True)
  60. owner_dogs = Doginfo.objects.filter(owner_id=user_id)
  61. owner_dog_count = owner_dogs.count()
  62. if owner_dog_count < 2:
  63. return JsonResponse({
  64. "status": "error",
  65. "date": current_time,
  66. "message": "You must have at least 2 dogs to transfer one",
  67. "end_time": current_time
  68. })
  69. # 检查要转移的狗是否存在且属于当前用户
  70. try:
  71. # dog = Doginfo.objects.get(d_id=dog_id, owner_id=user_id, is_active=True)
  72. dog = Doginfo.objects.get(d_id=dog_id, owner_id=user_id)
  73. except Doginfo.DoesNotExist:
  74. return JsonResponse({
  75. "status": "error",
  76. "date": current_time,
  77. "message": f"Dog with ID {dog_id} not found or does not belong to you",
  78. "end_time": current_time
  79. })
  80. # 检查要转移的狗当前是否已经在转移中
  81. if dog.transfer_status == 1:
  82. # 生成一个新的有效期为2分钟的唯一转移码
  83. try:
  84. dog_transfer=DogTransfer.objects.get(d_id=dog_id, sender_id=user_id,status='pending')
  85. except DogTransfer.DoesNotExist:
  86. return JsonResponse({
  87. "status": "error",
  88. "date": current_time,
  89. "message": f"Dog with ID {dog_id} not found or does not belong to you",
  90. "end_time": current_time
  91. })
  92. expiry_time = datetime.now() + timedelta(minutes=2)
  93. dog_transfer.expiry_time = expiry_time
  94. transfer_data = f"{dog_id}:{user_id}:{expiry_time.strftime('%Y%m%d%H%M%S')}"
  95. transfer_code = hashlib.sha256(transfer_data.encode()).hexdigest()[:16]
  96. dog_transfer.transfer_code=transfer_code
  97. dog_transfer.save()
  98. return JsonResponse({
  99. "status": "success",
  100. "code": 200,
  101. "message": "Transfer code refresh successfully",
  102. "transfer_code": transfer_code,
  103. })
  104. # 更新狗的转移状态
  105. dog.transfer_status = 1
  106. dog.save()
  107. # 生成一个有效期为2分钟的唯一转移码
  108. expiry_time = datetime.now() + timedelta(minutes=2)
  109. transfer_data = f"{dog_id}:{user_id}:{expiry_time.strftime('%Y%m%d%H%M%S')}"
  110. transfer_code = hashlib.sha256(transfer_data.encode()).hexdigest()[:16]
  111. # 保存转移记录
  112. DogTransfer.objects.create(
  113. d_id=dog_id,
  114. sender_id=user_id,
  115. transfer_code=transfer_code,
  116. expiry_time=expiry_time,
  117. status='pending'
  118. )
  119. return JsonResponse({
  120. "status": "success",
  121. "code": 200,
  122. "message": "Transfer code generated successfully",
  123. "transfer_code": transfer_code,
  124. })
  125. except Exception as e:
  126. # 处理数据库操作中的异常
  127. return JsonResponse({
  128. "status": "error",
  129. "date": current_time,
  130. "message": f"Database operation error: {str(e)}",
  131. "end_time": current_time
  132. })
  133. except Exception as e:
  134. # 全局异常处理
  135. import traceback
  136. traceback.print_exc()
  137. return JsonResponse({
  138. "status": "error",
  139. "message": f"Server processing exception: {str(e)}",
  140. "date": current_time
  141. })
  142. # 接收转移狗(接受者)接口
  143. # 使用access_token登录 请求参数:access_token、user_id,datetime
  144. # 返回格式:result、message、"transfer_code": "string"
  145. # 赠送中:pending,赠送完成:completed,赠送取消:cancelled,赠送失败:failed
  146. # 2025-5-19 author Feng
  147. @csrf_exempt
  148. def receive_dog_transfer(request):
  149. current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  150. try:
  151. # 获取请求参数
  152. access_token = request.POST.get("access_token", '')
  153. transfer_code = request.POST.get("transfer_code", '')
  154. user_id= request.POST.get("user_id", '')
  155. datetime_request= request.POST.get("datetime", '')
  156. print(f"transfer_code for dog ID------------- {transfer_code}")
  157. # 验证请求参数
  158. if not all([access_token, user_id,transfer_code]):
  159. return JsonResponse({
  160. "status": "error",
  161. "date": current_time,
  162. "message": "Please ensure all required fields are provided!",
  163. "end_time": current_time
  164. })
  165. # 验证访问令牌
  166. token_validation = aidog_tools.validate_access_token(access_token)
  167. if isinstance(token_validation, JsonResponse):
  168. return token_validation
  169. # 获取接收者用户ID
  170. receiver_id = token_validation['user_id']
  171. # 检查接收者拥有的狗数量是否 <= 2
  172. # receiver_dogs = Doginfo.objects.filter(owner_id=receiver_id, is_active=True)
  173. receiver_dogs = Doginfo.objects.filter(owner_id=receiver_id)
  174. receiver_dog_count = receiver_dogs.count()
  175. if receiver_dog_count >= 2:
  176. return JsonResponse({
  177. "status": "error",
  178. "date": current_time,
  179. "message": "You cannot have more than 2 dogs",
  180. "end_time": current_time
  181. })
  182. # 查找转移记录
  183. try:
  184. transfer = DogTransfer.objects.get(
  185. transfer_code=transfer_code,
  186. status='pending'
  187. )
  188. except DogTransfer.DoesNotExist:
  189. return JsonResponse({
  190. "status": "error",
  191. "date": current_time,
  192. "message": "Invalid or expired transfer code",
  193. "end_time": current_time
  194. })
  195. # 新增:检查转移码是否过期
  196. # 从 transfer 记录中获取创建时间,计算是否已过期
  197. expiry_time = transfer.expiry_time
  198. # 检查是否过期(2分钟有效期)
  199. current_datetime = timezone.now()
  200. if current_datetime > expiry_time:
  201. # 转移码已过期,更新状态为过期
  202. # transfer.status = 'expired'
  203. # transfer.completed_time = datetime.now()
  204. # transfer.save()
  205. return JsonResponse({
  206. "status": "error",
  207. "date": current_time,
  208. "error_code": "620",
  209. "message": "Transfer code has expired, please generate a new one",
  210. "end_time": current_time
  211. })
  212. # 阻止用户向自己转移
  213. if transfer.sender_id == receiver_id:
  214. return JsonResponse({
  215. "status": "error",
  216. "date": current_time,
  217. "message": "You cannot transfer a dog to yourself",
  218. "end_time": current_time
  219. })
  220. # 获取要转移的狗
  221. try:
  222. dog = Doginfo.objects.get(d_id=transfer.d_id, transfer_status=1)
  223. dog_relationship_personality = DogPersonalityRelationship.objects.get(d_id=transfer.d_id)
  224. except Doginfo.DoesNotExist:
  225. # 更新转移记录状态
  226. transfer.status = 'failed'
  227. transfer.save()
  228. return JsonResponse({
  229. "status": "error",
  230. "date": current_time,
  231. "message": "Dog not found or not available for transfer",
  232. "end_time": current_time
  233. })
  234. # 执行转移
  235. dog.owner_id = receiver_id
  236. # 重置为可转移状态
  237. dog.transfer_status = 0
  238. dog.save()
  239. # 更新转移记录
  240. transfer.receiver_id = receiver_id
  241. transfer.status = 'completed'
  242. transfer.completed_time = datetime.now()
  243. transfer.save()
  244. # 更新狗与主人关系属性
  245. dog_relationship_personality.intimate = aidog_tools.generate_random_number(20, 30)
  246. dog_relationship_personality.friendly = aidog_tools.generate_random_number(20, 30)
  247. dog_relationship_personality.obedience = aidog_tools.generate_random_number(20, 30)
  248. dog_relationship_personality.friendlyToHost = aidog_tools.generate_random_number(20, 30)
  249. dog_relationship_personality.friendlyToStranger = aidog_tools.generate_random_number(20, 30)
  250. dog_relationship_personality.save()
  251. # 获取用户信息
  252. try:
  253. user = User.objects.get(uid=user_id)
  254. user_info = aidog_tools._build_user_info(user)
  255. except User.DoesNotExist:
  256. user_info = {}
  257. # 获取用户的所有狗列表
  258. try:
  259. dog_info = Doginfo.objects.filter(owner_id=user_id)
  260. dog_list = []
  261. for dog in dog_info:
  262. dog_serialized = serializers.serialize('json', [dog])
  263. dog_data = json.loads(dog_serialized)[0]['fields']
  264. dog_id = dog_data['d_id']
  265. # 获取狗的信息并转换为字典
  266. new_dog_status = aidog_tools.model_to_dict_without_id(DogStatus.objects.filter(d_id=dog_id).first())
  267. new_dog_training = aidog_tools.model_to_dict_without_id(
  268. DogTrainingNew.objects.filter(d_id=dog_id).first())
  269. new_dog_body_attributes = aidog_tools.model_to_dict_without_id(
  270. DogBodyAttributes.objects.filter(d_id=dog_id).first())
  271. new_dog_personality_relationship = aidog_tools.model_to_dict_without_id(
  272. DogPersonalityRelationship.objects.filter(d_id=dog_id).first())
  273. # 合并所有相关信息
  274. dog_info_combined = {
  275. **dog_data,
  276. **new_dog_status,
  277. **new_dog_training,
  278. **new_dog_body_attributes,
  279. **new_dog_personality_relationship,
  280. }
  281. # 只保留字段而不是数据库内部的元数据(如 '_state')
  282. dog_info_clean = {key: value for key, value in dog_info_combined.items() if not key.startswith('_')}
  283. dog_list.append(dog_info_clean)
  284. except Exception as e:
  285. dog_list = []
  286. return JsonResponse({
  287. "status": "success",
  288. "code": 200,
  289. "message": "Dog transfer completed successfully",
  290. "date": current_time,
  291. "dog_id": dog.d_id,
  292. "dog_name": dog.dog_name,
  293. "user_info": user_info,
  294. "dog_list": dog_list
  295. })
  296. except Exception as e:
  297. # 全局异常处理
  298. import traceback
  299. traceback.print_exc()
  300. return JsonResponse({
  301. "status": "error",
  302. "message": f"Server processing exception: {str(e)}",
  303. "date": current_time
  304. })
  305. # 取消转移狗(赠送者)接口
  306. # 使用access_token登录 请求参数:access_token、user_id,transfer_code,datetime
  307. # 返回格式:result、message、"transfer_code": "string"
  308. # 赠送中:pending,赠送完成:completed,赠送取消:cancelled,赠送失败:failed
  309. # 2025-5-19 author Feng
  310. @csrf_exempt
  311. def transfer_dog_cancel(request):
  312. current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
  313. try:
  314. # 获取请求参数
  315. # 获取请求参数
  316. access_token = request.POST.get("access_token", '')
  317. user_id = request.POST.get("user_id", '')
  318. transfer_code = request.POST.get("transfer_code", '')
  319. req_datetime = request.POST.get("datetime", '')
  320. # 验证请求参数
  321. if not all([access_token, transfer_code]):
  322. return JsonResponse({
  323. "status": "error",
  324. "date": current_time,
  325. "message": "Please ensure all required fields are provided!",
  326. "end_time": current_time
  327. })
  328. # 验证访问令牌
  329. token_validation = aidog_tools.validate_access_token(access_token)
  330. if isinstance(token_validation, JsonResponse):
  331. return token_validation
  332. # 从令牌验证中获取验证后的用户ID
  333. validated_user_id = token_validation['user_id']
  334. # 确保用户ID与令牌匹配(提供了user_id)
  335. if user_id and user_id != validated_user_id:
  336. return JsonResponse({
  337. "status": "error",
  338. "date": current_time,
  339. "message": "User ID does not match with access token",
  340. "end_time": current_time
  341. })
  342. # 使用验证过的用户ID
  343. user_id = validated_user_id
  344. try:
  345. # 根据transfer_code查找转移记录
  346. try:
  347. transfer = DogTransfer.objects.get(
  348. transfer_code=transfer_code,
  349. status='pending',
  350. expiry_time__gt=datetime.now()
  351. )
  352. except DogTransfer.DoesNotExist:
  353. return JsonResponse({
  354. "status": "error",
  355. "date": current_time,
  356. "message": "Invalid or expired transfer code",
  357. "end_time": current_time
  358. })
  359. # 验证用户是否为该转移记录的发送者
  360. if transfer.sender_id != user_id:
  361. return JsonResponse({
  362. "status": "error",
  363. "date": current_time,
  364. "message": "You do not have permission to cancel this transfer",
  365. "end_time": current_time
  366. })
  367. # 获取要取消转移的狗
  368. try:
  369. dog = Doginfo.objects.get(d_id=transfer.d_id, transfer_status=1)
  370. except Doginfo.DoesNotExist:
  371. # 转移记录存在但狗不存在或不在转移状态,标记转移记录为失败
  372. transfer.status = 'failed'
  373. transfer.save()
  374. return JsonResponse({
  375. "status": "error",
  376. "date": current_time,
  377. "message": "Dog not found or not in transfer status",
  378. "end_time": current_time
  379. })
  380. # 取消转移记录
  381. transfer.status = 'cancelled'
  382. transfer.cancelled_time = datetime.now()
  383. transfer.save()
  384. # 重置狗的转移状态
  385. dog.transfer_status = 0
  386. dog.save()
  387. return JsonResponse({
  388. "status": "success",
  389. "code": 200,
  390. "message": "Dog transfer cancelled successfully",
  391. "date": current_time,
  392. "dog_id": dog.d_id
  393. })
  394. except Exception as e:
  395. # 处理数据库操作中的异常
  396. return JsonResponse({
  397. "status": "error",
  398. "date": current_time,
  399. "message": f"Database operation error: {str(e)}",
  400. "end_time": current_time
  401. })
  402. except Exception as e:
  403. # 全局异常处理
  404. import traceback
  405. traceback.print_exc()
  406. return JsonResponse({
  407. "status": "error",
  408. "message": f"Server processing exception: {str(e)}",
  409. "date": current_time
  410. })