拍爱

views.py 31KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. # -*- coding: utf-8 -*-
  2. from django.conf import settings
  3. from django.core.files.storage import default_storage
  4. from django.db import connection, transaction
  5. from django.http import JsonResponse
  6. from django.shortcuts import render
  7. from rest_framework import viewsets
  8. from account.models import UserInfo
  9. from group.models import GroupInfo, GroupUserInfo, GroupPhotoInfo, PhotoCommentInfo, PhotoThumbUpInfo
  10. from message.models import UserMessageInfo
  11. from group.serializers import GroupInfoSerializer, GroupUserInfoSerializer, GroupPhotoInfoSerializer
  12. from utils.page_utils import pagination
  13. from utils.thumbnail_utils import make_thumbnail
  14. from utils.url_utils import img_url
  15. from utils.error.errno_utils import UserStatusCode, GroupStatusCode, GroupUserStatusCode, GroupPhotoStatusCode
  16. from utils.error.response_utils import response
  17. from utils.redis.rkeys import (
  18. GROUP_USERS_APPLYING_SET, GROUP_USERS_PASSED_SET, GROUP_USERS_REFUSED_SET, GROUP_USERS_DELETED_SET,
  19. GROUP_USERS_QUIT_SET,
  20. )
  21. from utils.redis.rkeys import GROUP_LAST_PHOTO_PK
  22. from utils.redis.rkeys import LENSMAN_PHOTO_PRICE, LENSMAN_PHOTO_HAGGLE_TIMES
  23. from utils.redis.rgroup import set_group_info, get_group_info, set_group_users_info, get_group_users_info
  24. from utils.redis.rgroup import set_group_photo_thumbup_flag, del_group_photo_thumbup_flag, get_group_photo_thumbup_flag
  25. from utils.redis.rorder import get_lensman_order_record
  26. from utils.sql.raw import PAI2_HOME_API
  27. from curtail_uuid import CurtailUUID
  28. from TimeConvert import TimeConvert as tc
  29. import os
  30. import random
  31. import shortuuid
  32. r = settings.REDIS_CACHE
  33. @transaction.atomic
  34. def group_create_api(request):
  35. """
  36. 群组创建
  37. :param request:
  38. :return:
  39. """
  40. user_id = request.POST.get('user_id', '')
  41. group_name = request.POST.get('group_name', '')
  42. group_default_avatar = int(request.POST.get('group_default_avatar', 0))
  43. # 用户校验
  44. try:
  45. user = UserInfo.objects.get(user_id=user_id)
  46. except UserInfo.DoesNotExist:
  47. return response(UserStatusCode.USER_NOT_FOUND)
  48. # 群组唯一标识
  49. group_id = CurtailUUID.uuid(GroupInfo, 'group_id')
  50. # 群组记录创建
  51. group = GroupInfo.objects.create(
  52. group_id=group_id,
  53. admin_id=user_id,
  54. group_name=group_name,
  55. group_default_avatar=group_default_avatar,
  56. group_from=GroupInfo.APP_GROUP,
  57. )
  58. # Redis 群组数据缓存
  59. group_info = set_group_info(group)
  60. # 群组用户记录创建
  61. GroupUserInfo.objects.create(
  62. group_id=group_id,
  63. user_id=user_id,
  64. nickname=user.final_nickname,
  65. avatar=user.avatar,
  66. admin=True,
  67. user_status=GroupUserInfo.PASSED,
  68. passed_at=tc.utc_datetime(),
  69. )
  70. # Redis 群组用户数据缓存
  71. group_users = set_group_users_info(group)
  72. # Redis 群组通过集合缓存
  73. r.sadd(GROUP_USERS_PASSED_SET % group_id, user_id)
  74. return JsonResponse({
  75. 'status': 200,
  76. 'message': u'群组创建成功',
  77. 'data': {
  78. 'group_id': group_id,
  79. 'group': group_info,
  80. 'users': group_users,
  81. },
  82. })
  83. def group_detail_api(request):
  84. """
  85. 群组详情
  86. :param request:
  87. :return:
  88. """
  89. group_id = request.POST.get('group_id', '')
  90. user_id = request.POST.get('user_id', '')
  91. return JsonResponse({
  92. 'status': 200,
  93. 'message': u'获取群组详情成功',
  94. 'data': {
  95. 'group_id': group_id,
  96. 'group': get_group_info(group_id),
  97. 'users': get_group_users_info(group_id, user_id),
  98. },
  99. })
  100. def group_update_api(request):
  101. """
  102. 群组更新
  103. :param request:
  104. :return:
  105. """
  106. group_id = request.POST.get('group_id', '')
  107. admin_id = request.POST.get('admin_id', '') or request.POST.get('user_id', '')
  108. group_name = request.POST.get('group_name', '')
  109. group_desc = request.POST.get('group_desc', '')
  110. group_avatar = request.FILES.get('group_avatar', '')
  111. # 群组校验
  112. try:
  113. group = GroupInfo.objects.get(group_id=group_id)
  114. except GroupInfo.DoesNotExist:
  115. return response(GroupStatusCode.GROUP_NOT_FOUND)
  116. # 权限校验
  117. if group.admin_id != admin_id:
  118. return response(GroupStatusCode.NO_UPDATE_PERMISSION)
  119. # 群组名称更新
  120. if group_name:
  121. group.group_name = group_name
  122. # 群组描述更新
  123. if group_desc:
  124. group.group_desc = group_desc
  125. # 群组头像更新
  126. if group_avatar:
  127. _, extension = os.path.splitext(group_avatar.name)
  128. group_avatar_path = 'group/{uuid}_{extension}'.format(uuid=shortuuid.uuid(), extension=extension)
  129. if default_storage.exists(group_avatar_path):
  130. default_storage.delete(group_avatar_path)
  131. default_storage.save(group_avatar_path, group_avatar)
  132. group.group_avatar = group_avatar_path
  133. group.save()
  134. # Redis 群组数据缓存更新
  135. group_info = set_group_info(group)
  136. return JsonResponse({
  137. 'status': 200,
  138. 'message': u'群组更新成功',
  139. 'data': {
  140. 'group_id': group_id,
  141. 'group': group_info,
  142. 'users': get_group_users_info(group_id, admin_id),
  143. },
  144. })
  145. def group_list_api(request):
  146. """
  147. 群组列表
  148. :param request:
  149. :return:
  150. """
  151. user_id = request.POST.get('user_id', '')
  152. page = int(request.POST.get('page', 1))
  153. num = int(request.POST.get('num', settings.GROUP_PER_PAGE))
  154. group_users = GroupUserInfo.objects.filter(user_id=user_id, user_status=GroupUserInfo.PASSED)
  155. group_users, left = pagination(group_users, page, num)
  156. groups = []
  157. for group_user in group_users:
  158. group_info = get_group_info(group_user.group_id)
  159. groups.append(group_info) if group_info else None
  160. return JsonResponse({
  161. 'status': 200,
  162. 'message': u'获取群组列表成功',
  163. 'data': {
  164. 'groups': groups,
  165. 'left': left,
  166. },
  167. })
  168. def group_join_api(request):
  169. """
  170. 申请加群
  171. :param request:
  172. :return:
  173. """
  174. group_id = request.POST.get('group_id', '')
  175. user_id = request.POST.get('user_id', '')
  176. nickname = request.POST.get('nickname', '')
  177. # 用户校验
  178. try:
  179. user = UserInfo.objects.get(user_id=user_id)
  180. except UserInfo.DoesNotExist:
  181. return response(UserStatusCode.USER_NOT_FOUND)
  182. # 群组校验
  183. try:
  184. group = GroupInfo.objects.get(group_id=group_id)
  185. except GroupInfo.DoesNotExist:
  186. return response(GroupStatusCode.GROUP_NOT_FOUND)
  187. # 群组锁定校验
  188. if group.group_lock:
  189. return response(GroupStatusCode.GROUP_HAS_LOCKED)
  190. # 群组用户记录创建,若记录不存在,则创建,若记录已存在,则更新
  191. group_user, created = GroupUserInfo.objects.get_or_create(
  192. group_id=group_id,
  193. user_id=user_id,
  194. )
  195. if group_user.user_status != GroupUserInfo.PASSED:
  196. group_user.current_id = int(r.get(GROUP_LAST_PHOTO_PK % group_id) or -1)
  197. group_user.nickname = nickname or user.final_nickname
  198. group_user.avatar = user.avatar
  199. # group_user.admin = False # Admin Field Default False, Should Not Assign
  200. group_user.user_status = GroupUserInfo.PASSED
  201. group_user.passed_at = tc.utc_datetime()
  202. group_user.save()
  203. # Redis 群组用户数据缓存
  204. set_group_users_info(group)
  205. # Redis 群组通过集合缓存
  206. r.srem(GROUP_USERS_REFUSED_SET % group_id, user_id)
  207. r.srem(GROUP_USERS_DELETED_SET % group_id, user_id)
  208. r.srem(GROUP_USERS_QUIT_SET % group_id, user_id)
  209. r.sadd(GROUP_USERS_PASSED_SET % group_id, user_id)
  210. return JsonResponse({
  211. 'status': 200,
  212. 'message': u'申请成功',
  213. 'data': {
  214. 'current_id': group_user.current_id,
  215. 'photos': [],
  216. 'group_id': group_id,
  217. 'group': get_group_info(group_id),
  218. 'user_id': user_id,
  219. 'users': get_group_users_info(group_id, user_id),
  220. },
  221. })
  222. def group_lock_api(request):
  223. """
  224. 群组锁定
  225. :param request:
  226. :return:
  227. """
  228. group_id = request.POST.get('group_id', '')
  229. admin_id = request.POST.get('admin_id', '') or request.POST.get('user_id', '')
  230. # 群组校验
  231. try:
  232. group = GroupInfo.objects.get(group_id=group_id)
  233. except GroupInfo.DoesNotExist:
  234. return response(GroupStatusCode.GROUP_NOT_FOUND)
  235. # 权限校验
  236. if group.admin_id != admin_id:
  237. return response(GroupStatusCode.NO_LOCK_PERMISSION)
  238. # 群组锁定
  239. group.group_lock = True
  240. group.save()
  241. # Redis 群组数据缓存更新
  242. set_group_info(group)
  243. return JsonResponse({
  244. 'status': 200,
  245. 'message': u'锁定成功',
  246. })
  247. def group_unlock_api(request):
  248. """
  249. 群组解锁
  250. :param request:
  251. :return:
  252. """
  253. group_id = request.POST.get('group_id', '')
  254. admin_id = request.POST.get('admin_id', '') or request.POST.get('user_id', '')
  255. # 群组校验
  256. try:
  257. group = GroupInfo.objects.get(group_id=group_id)
  258. except GroupInfo.DoesNotExist:
  259. return response(GroupStatusCode.GROUP_NOT_FOUND)
  260. # 权限校验
  261. if group.admin_id != admin_id:
  262. return response(GroupStatusCode.NO_UNLOCK_PERMISSION)
  263. # 群组解锁
  264. group.group_lock = False
  265. group.save()
  266. # Redis 群组数据缓存更新
  267. set_group_info(group)
  268. return JsonResponse({
  269. 'status': 200,
  270. 'message': u'解锁成功',
  271. })
  272. def group_remove_api(request):
  273. """
  274. 成员移除
  275. :param request:
  276. :return:
  277. """
  278. group_id = request.POST.get('group_id', '')
  279. admin_id = request.POST.get('admin_id', '')
  280. user_id = request.POST.get('user_id', '')
  281. # 群组校验
  282. try:
  283. group = GroupInfo.objects.get(group_id=group_id)
  284. except GroupInfo.DoesNotExist:
  285. return response(GroupStatusCode.GROUP_NOT_FOUND)
  286. # 权限校验
  287. if group.admin_id != admin_id or group.admin_id == user_id: # 管理员也不允许将自己移除
  288. return response(GroupStatusCode.NO_REMOVE_PERMISSION)
  289. # 群组用户校验
  290. try:
  291. group_user = GroupUserInfo.objects.get(group_id=group_id, user_id=user_id, user_status=GroupUserInfo.PASSED)
  292. except GroupUserInfo.DoesNotExist:
  293. return response(GroupUserStatusCode.GROUP_USER_NOT_FOUND)
  294. # 群组用户移除
  295. group_user.user_status = GroupUserInfo.DELETED
  296. group_user.deleted_at = tc.utc_datetime()
  297. group_user.save()
  298. # Redis 群组数据缓存更新
  299. group_users = set_group_info(group)
  300. # Redis 群组删除集合缓存
  301. r.srem(GROUP_USERS_PASSED_SET % group_id, user_id)
  302. r.sadd(GROUP_USERS_DELETED_SET % group_id, user_id)
  303. return JsonResponse({
  304. 'status': 200,
  305. 'message': u'用户移除成功',
  306. 'data': {
  307. 'group_id': group_id,
  308. 'users': group_users,
  309. },
  310. })
  311. def group_quit_api(request):
  312. """
  313. 成员退出
  314. :param request:
  315. :return:
  316. """
  317. group_id = request.POST.get('group_id', '')
  318. user_id = request.POST.get('user_id', '')
  319. # 群组校验
  320. try:
  321. group = GroupInfo.objects.get(group_id=group_id)
  322. except GroupInfo.DoesNotExist:
  323. return response(GroupStatusCode.GROUP_NOT_FOUND)
  324. # 权限校验
  325. if group.admin_id == user_id: # 管理员也不允许自己退出
  326. return response(GroupStatusCode.NO_QUIT_PERMISSION)
  327. # 群组用户校验
  328. try:
  329. group_user = GroupUserInfo.objects.get(group_id=group_id, user_id=user_id, user_status=GroupUserInfo.PASSED)
  330. except GroupUserInfo.DoesNotExist:
  331. return response(GroupUserStatusCode.GROUP_USER_NOT_FOUND)
  332. # 群组用户移除
  333. group_user.user_status = GroupUserInfo.QUIT
  334. group_user.quit_at = tc.utc_datetime()
  335. group_user.save()
  336. # Redis 群组数据缓存更新
  337. group_users = set_group_info(group)
  338. # Redis 群组删除集合缓存
  339. r.srem(GROUP_USERS_PASSED_SET % group_id, user_id)
  340. r.sadd(GROUP_USERS_QUIT_SET % group_id, user_id)
  341. return JsonResponse({
  342. 'status': 200,
  343. 'message': u'用户退出成功',
  344. 'data': {
  345. 'group_id': group_id,
  346. 'users': group_users,
  347. },
  348. })
  349. def group_pass_api(request):
  350. """
  351. 申请通过
  352. :param request:
  353. :return:
  354. """
  355. group_id = request.POST.get('group_id', '')
  356. admin_id = request.POST.get('admin_id', '')
  357. user_id = request.POST.get('user_id', '')
  358. # 群组校验
  359. try:
  360. group = GroupInfo.objects.get(group_id=group_id)
  361. except GroupInfo.DoesNotExist:
  362. return response(GroupStatusCode.GROUP_NOT_FOUND)
  363. # 权限校验
  364. if group.admin_id != admin_id:
  365. return response(GroupStatusCode.NO_PASS_PERMISSION)
  366. # 群组用户校验
  367. try:
  368. group_user = GroupUserInfo.objects.get(group_id=group_id, user_id=user_id, user_status=GroupUserInfo.APPLYING)
  369. except GroupUserInfo.DoesNotExist:
  370. return response(GroupStatusCode.JOIN_REQUEST_NOT_FOUND)
  371. # 群组用户通过
  372. group_user.user_status = GroupUserInfo.PASSED
  373. group_user.passed_at = tc.utc_datetime()
  374. group_user.save()
  375. # Redis 群组数据缓存更新
  376. group_users = set_group_info(group)
  377. # Redis 群组通过集合缓存
  378. r.srem(GROUP_USERS_APPLYING_SET % group_id, user_id)
  379. r.sadd(GROUP_USERS_PASSED_SET % group_id, user_id)
  380. return JsonResponse({
  381. 'status': 200,
  382. 'message': u'申请通过成功',
  383. 'data': {
  384. 'group_id': group_id,
  385. 'users': group_users,
  386. },
  387. })
  388. def group_refuse_api(request):
  389. """
  390. 申请拒绝
  391. :param request:
  392. :return:
  393. """
  394. group_id = request.POST.get('group_id', '')
  395. admin_id = request.POST.get('admin_id', '')
  396. user_id = request.POST.get('user_id', '')
  397. # 群组校验
  398. try:
  399. group = GroupInfo.objects.get(group_id=group_id)
  400. except GroupInfo.DoesNotExist:
  401. return response(GroupStatusCode.GROUP_NOT_FOUND)
  402. # 权限校验
  403. if group.admin_id != admin_id:
  404. return response(GroupStatusCode.NO_REFUSE_PERMISSION)
  405. # 群组用户校验
  406. try:
  407. group_user = GroupUserInfo.objects.get(group_id=group_id, user_id=user_id, user_status=GroupUserInfo.APPLYING)
  408. except GroupUserInfo.DoesNotExist:
  409. return response(GroupStatusCode.JOIN_REQUEST_NOT_FOUND)
  410. # 群组用户拒绝
  411. group_user.user_status = GroupUserInfo.REFUSED
  412. group_user.refused_at = tc.utc_datetime()
  413. group_user.save()
  414. # Redis 群组数据缓存更新
  415. group_users = set_group_info(group)
  416. # Redis 群组拒绝集合缓存
  417. r.srem(GROUP_USERS_APPLYING_SET % group_id, user_id)
  418. r.sadd(GROUP_USERS_REFUSED_SET % group_id, user_id)
  419. return JsonResponse({
  420. 'status': 200,
  421. 'message': u'申请拒绝成功',
  422. 'data': {
  423. 'group_id': group_id,
  424. 'users': group_users,
  425. },
  426. })
  427. def flyimg_upload_api(request):
  428. """
  429. 飞图上传/飞图列表
  430. :param request:
  431. :return:
  432. """
  433. group_id = request.POST.get('group_id', '')
  434. user_id = request.POST.get('user_id', '')
  435. nickname = request.POST.get('nickname', '')
  436. photo = request.FILES.get('photo', '')
  437. current_id = int(request.POST.get('current_id', -1))
  438. # 用户校验
  439. try:
  440. user = UserInfo.objects.get(user_id=user_id)
  441. except UserInfo.DoesNotExist:
  442. return response(UserStatusCode.USER_NOT_FOUND)
  443. # 群组用户校验
  444. try:
  445. group_user = GroupUserInfo.objects.get(group_id=group_id, user_id=user_id, user_status=GroupUserInfo.PASSED)
  446. except GroupUserInfo.DoesNotExist:
  447. return response(GroupUserStatusCode.GROUP_USER_NOT_FOUND)
  448. if photo:
  449. photo_path = 'fly/{uuid}{extension}'.format(uuid=shortuuid.uuid(), extension=os.path.splitext(photo.name)[1] or 'jpeg')
  450. photo_thumbnail_path = photo_path.replace('.', '_thumbnail.')
  451. photo_thumbnail2_path = photo_path.replace('.', '_thumbnail2.')
  452. if default_storage.exists(photo_path):
  453. default_storage.delete(photo_path)
  454. default_storage.save(photo_path, photo)
  455. # if default_storage.exists(photo_thumbnail_path):
  456. # default_storage.delete(photo_thumbnail_path)
  457. # default_storage.save(photo_thumbnail_path, photo)
  458. # 群组照片缩略图生成
  459. # 双列: 540, 40-50K
  460. photo_w, photo_h, photo_thumbnail_w, photo_thumbnail_h = make_thumbnail(
  461. os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
  462. os.path.join(settings.MEDIA_ROOT, photo_thumbnail_path).replace('\\', '/'),
  463. settings.THUMBNAIL_MAX_WIDTH
  464. )
  465. # 单列: 1080, xx-100K
  466. photo_w, photo_h, photo_thumbnail2_w, photo_thumbnail2_h = make_thumbnail(
  467. os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
  468. os.path.join(settings.MEDIA_ROOT, photo_thumbnail2_path).replace('\\', '/'),
  469. settings.THUMBNAIL_MAX_WIDTH2
  470. )
  471. # 群组照片记录创建
  472. group_photo = GroupPhotoInfo.objects.create(
  473. group_id=group_id,
  474. user_id=user_id,
  475. nickname=nickname or user.final_nickname,
  476. avatar=user.avatar,
  477. photo_path=photo_path,
  478. photo_w=photo_w,
  479. photo_h=photo_h,
  480. photo_thumbnail_path=photo_thumbnail_path,
  481. photo_thumbnail_w=photo_thumbnail_w,
  482. photo_thumbnail_h=photo_thumbnail_h,
  483. photo_thumbnail2_path=photo_thumbnail2_path,
  484. photo_thumbnail2_w=photo_thumbnail2_w,
  485. photo_thumbnail2_h=photo_thumbnail2_h,
  486. )
  487. # 设置群组最后一张照片PK
  488. r.set(GROUP_LAST_PHOTO_PK % group_id, group_photo.pk)
  489. # 获取从 current_id 到 now 的群组照片列表
  490. group_photos = GroupPhotoInfo.objects.filter(
  491. group_id=group_id,
  492. status=True,
  493. pk__gt=max(current_id, group_user.current_id),
  494. ).order_by(
  495. '-pk'
  496. )
  497. latest_photo = group_photos.first()
  498. return JsonResponse({
  499. 'status': 200,
  500. 'message': u'飞图上传成功',
  501. 'data': {
  502. 'current_id': latest_photo and latest_photo.pk or current_id,
  503. 'photos': [photo.photo_info(user_id) for photo in group_photos],
  504. }
  505. })
  506. def comment_submit_api(request):
  507. """
  508. 飞图评论提交/飞图评论列表
  509. :param request:
  510. :return:
  511. """
  512. group_id = request.POST.get('group_id', '')
  513. user_id = request.POST.get('user_id', '')
  514. photo_id = request.POST.get('photo_id', '')
  515. comment = request.POST.get('comment', '')
  516. # 群组用户校验
  517. try:
  518. group_user = GroupUserInfo.objects.get(group_id=group_id, user_id=user_id, user_status=GroupUserInfo.PASSED)
  519. except GroupUserInfo.DoesNotExist:
  520. return response(GroupUserStatusCode.GROUP_USER_NOT_FOUND)
  521. # 群组照片校验
  522. try:
  523. group_photo = GroupPhotoInfo.objects.get(pk=photo_id)
  524. except GroupPhotoInfo.DoesNotExist:
  525. return response(GroupPhotoStatusCode.GROUP_PHOTO_NOT_FOUND)
  526. if comment:
  527. # 群组照片评论记录创建
  528. PhotoCommentInfo.objects.create(
  529. photo_id=photo_id,
  530. user_id=user_id,
  531. nickname=group_user.nickname,
  532. avatar=group_user.avatar,
  533. comment=comment,
  534. )
  535. # 群组照片评论数更新
  536. group_photo.comment_num += 1
  537. group_photo.save()
  538. # 判断群组照片发布者是否已经被管理员移除/主动退出,如若移除/退出,则不给发布者提醒
  539. if r.sismember(GROUP_USERS_PASSED_SET % group_photo.group_id, group_photo.user_id):
  540. UserMessageInfo.objects.create(
  541. from_uid=user_id,
  542. from_nickname=group_user.nickname,
  543. from_avatar=group_user.avatar,
  544. to_uid=group_photo.user_id,
  545. group_id=group_photo.group_id,
  546. photo_id=group_photo.pk,
  547. msg_type=UserMessageInfo.COMMENT,
  548. msg_title=u'评论',
  549. msg_content=comment,
  550. )
  551. # 群组照片评论列表
  552. photo_comments = PhotoCommentInfo.objects.filter(
  553. photo_id=photo_id,
  554. )
  555. return JsonResponse({
  556. 'status': 200,
  557. 'message': u'评论成功',
  558. 'data': {
  559. 'comments': [comment.comment_info for comment in photo_comments],
  560. }
  561. })
  562. def thumbup_submit_api(request):
  563. """
  564. 飞图点赞提交
  565. :param request:
  566. :return:
  567. """
  568. group_id = request.POST.get('group_id', '')
  569. user_id = request.POST.get('user_id', '')
  570. photo_id = request.POST.get('photo_id', '')
  571. # 群组用户校验
  572. try:
  573. group_user = GroupUserInfo.objects.get(group_id=group_id, user_id=user_id, user_status=GroupUserInfo.PASSED)
  574. except GroupUserInfo.DoesNotExist:
  575. return response(GroupUserStatusCode.GROUP_USER_NOT_FOUND)
  576. # 群组照片校验
  577. try:
  578. group_photo = GroupPhotoInfo.objects.get(pk=photo_id)
  579. except GroupPhotoInfo.DoesNotExist:
  580. return response(GroupPhotoStatusCode.GROUP_PHOTO_NOT_FOUND)
  581. # user_id 是否点赞 photo_id
  582. if PhotoThumbUpInfo.objects.filter(photo_id=photo_id, user_id=user_id, thumbup=True).exists():
  583. return response(GroupPhotoStatusCode.DUPLICATE_THUMB_UP)
  584. # 群组照片点赞记录创建/更新
  585. photo_thumbup, created = PhotoThumbUpInfo.objects.get_or_create(
  586. photo_id=photo_id,
  587. user_id=user_id,
  588. )
  589. photo_thumbup.nickname = group_user.nickname
  590. photo_thumbup.avatar = group_user.avatar
  591. photo_thumbup.thumbup = True
  592. photo_thumbup.save()
  593. # Redis 群组照片点赞数据缓存
  594. set_group_photo_thumbup_flag(photo_id, user_id)
  595. # 群组照片点赞数更新
  596. group_photo.thumbup_num += 1
  597. group_photo.save()
  598. # 判断群组照片发布者是否已经被管理员移除/主动退出,如若移除/退出,则不给发布者提醒
  599. if r.sismember(GROUP_USERS_PASSED_SET % group_photo.group_id, group_photo.user_id):
  600. UserMessageInfo.objects.create(
  601. from_uid=user_id,
  602. from_nickname=group_user.nickname,
  603. from_avatar=group_user.avatar,
  604. to_uid=group_photo.user_id,
  605. group_id=group_photo.group_id,
  606. photo_id=group_photo.pk,
  607. msg_type=UserMessageInfo.THUMBUP,
  608. msg_title=u'点赞',
  609. msg_content=u'点赞',
  610. )
  611. # 群组照片点赞列表
  612. photo_thumbups = PhotoThumbUpInfo.objects.filter(
  613. photo_id=photo_id,
  614. thumbup=True,
  615. )
  616. return JsonResponse({
  617. 'status': 200,
  618. 'message': u'点赞提交成功',
  619. 'data': {
  620. 'thumbup': True,
  621. 'thumbups': [thumbup.thumbup_info for thumbup in photo_thumbups],
  622. }
  623. })
  624. def thumbup_list_api(request):
  625. """
  626. 飞图点赞列表
  627. :param request:
  628. :return:
  629. """
  630. group_id = request.POST.get('group_id', '')
  631. user_id = request.POST.get('user_id', '')
  632. photo_id = request.POST.get('photo_id', '')
  633. # user_id 是否点赞 photo_id
  634. thumbup = PhotoThumbUpInfo.objects.filter(photo_id=photo_id, user_id=user_id, thumbup=True).exists()
  635. # 群组照片点赞列表
  636. photo_thumbups = PhotoThumbUpInfo.objects.filter(
  637. photo_id=photo_id,
  638. thumbup=True,
  639. )
  640. return JsonResponse({
  641. 'status': 200,
  642. 'message': u'获取点赞列表成功',
  643. 'data': {
  644. 'thumbup': thumbup,
  645. 'thumbups': [thumbup.thumbup_info for thumbup in photo_thumbups],
  646. }
  647. })
  648. def thumbup_cancel_api(request):
  649. """
  650. 飞图点赞取消
  651. :param request:
  652. :return:
  653. """
  654. group_id = request.POST.get('group_id', '')
  655. user_id = request.POST.get('user_id', '')
  656. photo_id = request.POST.get('photo_id', '')
  657. # 群组用户校验
  658. try:
  659. group_user = GroupUserInfo.objects.get(group_id=group_id, user_id=user_id, user_status=GroupUserInfo.PASSED)
  660. except GroupUserInfo.DoesNotExist:
  661. return response(GroupUserStatusCode.GROUP_USER_NOT_FOUND)
  662. # 群组照片校验
  663. try:
  664. group_photo = GroupPhotoInfo.objects.get(pk=photo_id)
  665. except GroupPhotoInfo.DoesNotExist:
  666. return response(GroupPhotoStatusCode.GROUP_PHOTO_NOT_FOUND)
  667. # user_id 是否点赞 photo_id
  668. if not PhotoThumbUpInfo.objects.filter(photo_id=photo_id, user_id=user_id, thumbup=True).exists():
  669. return response(GroupPhotoStatusCode.THUMB_UP_NOT_FOUND)
  670. # 群组照片点赞取消
  671. photo_thumbup, created = PhotoThumbUpInfo.objects.get_or_create(
  672. photo_id=photo_id,
  673. user_id=user_id,
  674. )
  675. photo_thumbup.thumbup = False
  676. photo_thumbup.save()
  677. # Redis 群组照片点赞数据移除
  678. del_group_photo_thumbup_flag(photo_id, user_id)
  679. # 群组照片点赞数更新
  680. group_photo.thumbup_num -= 1
  681. group_photo.save()
  682. # 判断群组照片发布者是否已经被管理员移除/主动退出,如若移除/退出,则不给发布者提醒
  683. if r.sismember(GROUP_USERS_PASSED_SET % group_photo.group_id, group_photo.user_id):
  684. UserMessageInfo.objects.create(
  685. from_uid=user_id,
  686. from_nickname=group_user.nickname,
  687. from_avatar=group_user.avatar,
  688. to_uid=group_photo.user_id,
  689. group_id=group_photo.group_id,
  690. photo_id=group_photo.pk,
  691. msg_type=UserMessageInfo.THUMBUP,
  692. msg_title=u'取消点赞',
  693. msg_content=u'取消点赞',
  694. )
  695. # 群组照片点赞列表
  696. photo_thumbups = PhotoThumbUpInfo.objects.filter(
  697. photo_id=photo_id,
  698. thumbup=True,
  699. )
  700. return JsonResponse({
  701. 'status': 200,
  702. 'message': u'点赞取消成功',
  703. 'data': {
  704. 'thumbup': False,
  705. 'thumbups': [thumbup.thumbup_info for thumbup in photo_thumbups],
  706. }
  707. })
  708. def pai2_home_api(request):
  709. """
  710. 首页信息
  711. :param request:
  712. :return:
  713. """
  714. user_id = request.POST.get('user_id', '')
  715. page = int(request.POST.get('page', 1))
  716. num = int(request.POST.get('num', settings.PAI2_HOME_PER_PAGE))
  717. # 执行原生 SQL 语句,获取首页照片列表
  718. cursor = connection.cursor()
  719. cursor.execute(PAI2_HOME_API.format(
  720. user_id=user_id,
  721. offset=0,
  722. rows=settings.PAI2_HOME_MAX_ROWS,
  723. ))
  724. rows = cursor.fetchall()
  725. # 首页照片分页
  726. rows, left = pagination(rows, page, num)
  727. # 首页照片信息
  728. rows = [{
  729. 'group_id': row[0],
  730. 'group_name': row[1],
  731. 'group_default_avatar': row[2],
  732. 'group_avatar': row[3],
  733. 'group_from': row[4],
  734. 'photo_id': row[5],
  735. 'photo_url': img_url(row[6]),
  736. 'photo_w': row[7],
  737. 'photo_h': row[8],
  738. 'photo_thumbnail_url': img_url(row[9]),
  739. 'photo_thumbnail_w': row[10],
  740. 'photo_thumbnail_h': row[11],
  741. 'photo_thumbnail2_url': img_url(row[12]),
  742. 'photo_thumbnail2_w': row[13],
  743. 'photo_thumbnail2_h': row[14],
  744. 'user_id': row[15],
  745. 'nickname': row[16],
  746. 'avatar': row[17],
  747. 'comment_num': row[18],
  748. 'thumbup_num': row[19],
  749. 'photo_from': row[20],
  750. 'created_at': row[21],
  751. } for row in rows]
  752. [row.update({
  753. 'thumbup': get_group_photo_thumbup_flag(row['photo_id'], user_id),
  754. 'porder': get_lensman_order_record(row['photo_id'], user_id) if row['photo_from'] == GroupPhotoInfo.SESSION_GROUP else {}
  755. }) for row in rows]
  756. return JsonResponse({
  757. 'status': 200,
  758. 'message': u'获取首页列表成功',
  759. 'data': {
  760. 'photos': rows,
  761. 'left': left,
  762. }
  763. })
  764. def lensman_photo_price(request):
  765. """
  766. 摄影师照片价格获取
  767. :param request:
  768. :return:
  769. """
  770. user_id = request.POST.get('user_id', '')
  771. photo_id = request.POST.get('photo_id', '')
  772. photo_type = request.POST.get('photo_type', 'nomark') # nomark for 去除水印, origin for 获取高清图
  773. # 处理价格逻辑
  774. lensman_photo_price_key = LENSMAN_PHOTO_PRICE % (user_id, photo_id, photo_type)
  775. lensman_photo_haggle_times_key = LENSMAN_PHOTO_HAGGLE_TIMES % (user_id, photo_id, photo_type)
  776. # Redis 获取存储的价格
  777. price = int(r.get(lensman_photo_price_key) or 0)
  778. if price:
  779. haggle_times = int(r.get(lensman_photo_haggle_times_key) or 0)
  780. # 砍价逻辑
  781. if haggle_times < settings.LENSMAN_PHOTO_HAGGLE_MAX_TIMES:
  782. price -= random.choice([50, 100])
  783. r.incr(lensman_photo_haggle_times_key)
  784. else:
  785. # 获取摄影师定价
  786. # TODO, 此处需要完整的摄影师定价
  787. price = 999 if photo_type == 'origin' else 666
  788. r.set(lensman_photo_price_key, price)
  789. return JsonResponse({
  790. 'status': 200,
  791. 'message': u'获取价格成功',
  792. 'data': {
  793. 'price': price
  794. }
  795. })
  796. def lensman_photo_bought(request):
  797. """
  798. 摄影师照片已购买
  799. :param request:
  800. :return:
  801. """
  802. user_id = request.POST.get('user_id', '')
  803. photo_id = request.POST.get('photo_id', '')
  804. return JsonResponse({
  805. 'status': 200,
  806. 'message': u'获取购买数据成功',
  807. 'data': {
  808. 'porder': get_lensman_order_record(photo_id, user_id)
  809. }
  810. })
  811. def group_detail(request, group_id):
  812. return render(request, 'page/download.html', {})
  813. class GroupInfoViewSet(viewsets.ModelViewSet):
  814. queryset = GroupInfo.objects.all().order_by('-pk')
  815. serializer_class = GroupInfoSerializer
  816. class GroupUserInfoViewSet(viewsets.ModelViewSet):
  817. queryset = GroupUserInfo.objects.all().order_by('-pk')
  818. serializer_class = GroupUserInfoSerializer
  819. class GroupPhotoInfoViewSet(viewsets.ModelViewSet):
  820. queryset = GroupPhotoInfo.objects.all().order_by('-pk')
  821. serializer_class = GroupPhotoInfoSerializer
  822. # Only Once Function
  823. def refresh_thumbnail():
  824. photos = GroupPhotoInfo.objects.filter(status=True)
  825. for photo in photos:
  826. try:
  827. photo_path = photo.photo_path
  828. photo_thumbnail_path = photo_path.replace('.', '_thumbnail.')
  829. photo_thumbnail2_path = photo_path.replace('.', '_thumbnail2.')
  830. # 群组照片缩略图生成
  831. # 双列: 540, 40-50K
  832. photo_w, photo_h, photo_thumbnail_w, photo_thumbnail_h = make_thumbnail(
  833. os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
  834. os.path.join(settings.MEDIA_ROOT, photo_thumbnail_path).replace('\\', '/'),
  835. settings.THUMBNAIL_MAX_WIDTH
  836. )
  837. # 单列: 1080, xx-100K
  838. photo_w, photo_h, photo_thumbnail2_w, photo_thumbnail2_h = make_thumbnail(
  839. os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
  840. os.path.join(settings.MEDIA_ROOT, photo_thumbnail2_path).replace('\\', '/'),
  841. settings.THUMBNAIL_MAX_WIDTH2
  842. )
  843. photo.photo_w = photo_w
  844. photo.photo_h = photo_h
  845. photo.photo_thumbnail_path = photo_thumbnail_path
  846. photo.photo_thumbnail_w = photo_thumbnail_w
  847. photo.photo_thumbnail_h = photo_thumbnail_h
  848. photo.photo_thumbnail2_path = photo_thumbnail2_path
  849. photo.photo_thumbnail2_w = photo_thumbnail2_w
  850. photo.photo_thumbnail2_h = photo_thumbnail2_h
  851. photo.save()
  852. except Exception as e:
  853. pass
  854. return 'Refresh Thumbnail OK'