|
@@ -0,0 +1,337 @@
|
|
|
+import time
|
|
|
+from datetime import datetime
|
|
|
+
|
|
|
+import boto3
|
|
|
+import botocore
|
|
|
+from django.core.paginator import Paginator
|
|
|
+from django.views import View
|
|
|
+from obs import ObsClient
|
|
|
+from Ansjer.config import HUAWEICLOUD_AK, HUAWEICLOUD_SK, HUAWEICLOUD_OBS_SERVER, CONFIG_INFO, CONFIG_CN, CONFIG_TEST, \
|
|
|
+ AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY
|
|
|
+
|
|
|
+from Roomumy.models import TimeAlbum, AlbumMedia, TimeDiary, DiaryAlbumMediaRelation
|
|
|
+from Service.CommonService import CommonService
|
|
|
+
|
|
|
+
|
|
|
+class TimeAlbumView(View):
|
|
|
+ def get(self, request, *args, **kwargs):
|
|
|
+ request.encoding = 'utf-8'
|
|
|
+ operation = kwargs.get('operation')
|
|
|
+ return self.validation(request.GET, request, operation)
|
|
|
+
|
|
|
+ def post(self, request, *args, **kwargs):
|
|
|
+ request.encoding = 'utf-8'
|
|
|
+ operation = kwargs.get('operation')
|
|
|
+ return self.validation(request.POST, request, operation)
|
|
|
+
|
|
|
+ def validation(self, request_dict, request, operation):
|
|
|
+ token_code, user_id, response = CommonService.verify_token_get_user_id(request_dict, request)
|
|
|
+ if operation == 'clearAlbumMedia': # 删除相册媒体
|
|
|
+ return self.clear_album_media(response)
|
|
|
+ else:
|
|
|
+ if token_code != 0:
|
|
|
+ return response.json(token_code)
|
|
|
+ if operation == 'getAlbumPic': # 查询相册列表
|
|
|
+ return self.get_album_pic(user_id, request_dict, response)
|
|
|
+ elif operation == 'getTimeDiary': # 获取时光日记列表
|
|
|
+ return self.get_time_diary(user_id, request_dict, response)
|
|
|
+ elif operation == 'picLiked': # 喜欢图片
|
|
|
+ return self.pic_liked(user_id, request_dict, response)
|
|
|
+ else:
|
|
|
+ return response.json(414)
|
|
|
+
|
|
|
+ def get_album_pic(self, user_id, request_dict, response):
|
|
|
+ device_id = request_dict.get('deviceId', None)
|
|
|
+ start_time = request_dict.get('startTime', None)
|
|
|
+ end_time = request_dict.get('endTime', None)
|
|
|
+ page = request_dict.get('page', 1) # 当前页码,默认为1
|
|
|
+ page_size = request_dict.get('pageSize', 10) # 每页显示的记录数,默认为10
|
|
|
+
|
|
|
+ # 检查是否提供了uid,如果没有提供返回错误
|
|
|
+ if device_id is None:
|
|
|
+ return response.json(444)
|
|
|
+ try:
|
|
|
+ # 查询TimeAlbum表,按uid过滤,且如果提供了album_date,则进一步按album_date过滤
|
|
|
+ time_album_qs = TimeAlbum.objects.filter(device_id=device_id).order_by('-album_date')
|
|
|
+
|
|
|
+ if start_time and end_time:
|
|
|
+ time_album_qs = time_album_qs.filter(album_date__gte=start_time, album_date__lte=end_time)
|
|
|
+
|
|
|
+ # 如果没有找到符合条件的TimeAlbum记录,返回错误
|
|
|
+ if not time_album_qs.exists():
|
|
|
+ return response.json(0, {})
|
|
|
+
|
|
|
+ # 对TimeAlbum结果进行分页
|
|
|
+ paginator = Paginator(time_album_qs, page_size)
|
|
|
+ time_albums = paginator.page(page) # 获取当前页的数据
|
|
|
+
|
|
|
+ time_album_list = []
|
|
|
+ # 对每个TimeAlbum,查询相关的AlbumMedia
|
|
|
+ for time_album in time_albums:
|
|
|
+ # 查询与当前time_album_id关联的AlbumMedia记录
|
|
|
+ time_album_info = []
|
|
|
+ album_media_qs = AlbumMedia.objects.filter(time_album_id=time_album.id).values('id', 'device_id', 'channel',
|
|
|
+ 'event_time', 'status',
|
|
|
+ 'storage_location')
|
|
|
+
|
|
|
+ if album_media_qs.exists():
|
|
|
+ for album_media in album_media_qs:
|
|
|
+ storage_location = album_media['storage_location']
|
|
|
+ uid = album_media['device_id']
|
|
|
+ channel = album_media['channel']
|
|
|
+ event_time = album_media['event_time']
|
|
|
+ image = self.media_url(storage_location, uid, channel, event_time)
|
|
|
+
|
|
|
+ # 判断是否加入时光日记
|
|
|
+ liked_status = 0
|
|
|
+ if DiaryAlbumMediaRelation.objects.filter(
|
|
|
+ album_media_id=album_media['id'],
|
|
|
+ diary__user_id=user_id
|
|
|
+ ).exists():
|
|
|
+ liked_status = 1
|
|
|
+ time_album_info.append({
|
|
|
+ 'picId': album_media['id'],
|
|
|
+ 'image': image,
|
|
|
+ 'likedStatus': liked_status,
|
|
|
+ })
|
|
|
+ time_album_list.append({
|
|
|
+ 'albumDate': time_album.album_date,
|
|
|
+ 'albumTitle': time_album.album_title,
|
|
|
+ 'info': time_album_info
|
|
|
+ })
|
|
|
+
|
|
|
+ # 返回分页结果和数据
|
|
|
+ return response.json(0, {
|
|
|
+ 'data': time_album_list,
|
|
|
+ 'total': paginator.count, # 总记录数
|
|
|
+ })
|
|
|
+ except Exception as e:
|
|
|
+ return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
+
|
|
|
+ def get_time_diary(self, user_id, request_dict, response):
|
|
|
+ start_time = request_dict.get('startTime', None)
|
|
|
+ end_time = request_dict.get('endTime', None)
|
|
|
+ page = int(request_dict.get('page', 1))
|
|
|
+ page_size = int(request_dict.get('pageSize', 10))
|
|
|
+
|
|
|
+ try:
|
|
|
+ # 基础查询
|
|
|
+ time_diary_qs = TimeDiary.objects.filter(user_id=user_id).order_by('-diary_date')
|
|
|
+
|
|
|
+ # 时间范围过滤
|
|
|
+ if start_time and end_time:
|
|
|
+ time_diary_qs = time_diary_qs.filter(diary_date__gte=start_time, diary_date__lte=end_time)
|
|
|
+
|
|
|
+ # 分页
|
|
|
+ paginator = Paginator(time_diary_qs, page_size)
|
|
|
+ diaries_page = paginator.get_page(page)
|
|
|
+
|
|
|
+ diary_data_list = []
|
|
|
+ for diary in diaries_page:
|
|
|
+ # 通过中间表获取关联的图片
|
|
|
+ relations = DiaryAlbumMediaRelation.objects.filter(diary=diary).select_related('album_media')
|
|
|
+
|
|
|
+ media_list = []
|
|
|
+ for relation in relations:
|
|
|
+ media = relation.album_media
|
|
|
+ media_list.append({
|
|
|
+ 'picId': media.id,
|
|
|
+ 'likeStatus': 1,
|
|
|
+ 'image': self.media_url(media.storage_location, media.device_id, media.channel,
|
|
|
+ media.event_time)
|
|
|
+ })
|
|
|
+
|
|
|
+ diary_data_list.append({
|
|
|
+ 'diary_date': diary.diary_date,
|
|
|
+ 'info': media_list
|
|
|
+ })
|
|
|
+
|
|
|
+ return response.json(0, {
|
|
|
+ 'data': diary_data_list,
|
|
|
+ 'total': paginator.count,
|
|
|
+ })
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def pic_liked(user_id, request_dict, response):
|
|
|
+ pic_id = request_dict.get('picId', None)
|
|
|
+ liked_status = request_dict.get('likedStatus', None)
|
|
|
+
|
|
|
+ if not all([pic_id, liked_status]):
|
|
|
+ return response.json(444)
|
|
|
+
|
|
|
+ liked_status = int(liked_status)
|
|
|
+
|
|
|
+ try:
|
|
|
+ album_media = AlbumMedia.objects.filter(id=pic_id).first()
|
|
|
+ if not album_media:
|
|
|
+ return response.json(404, 'pic not found')
|
|
|
+
|
|
|
+ # 获取相册的日期
|
|
|
+ time_diary_qs = AlbumMedia.objects.filter(id=pic_id).values('time_album_id', 'event_time', 'status')
|
|
|
+ if not time_diary_qs.exists():
|
|
|
+ return response.json(173)
|
|
|
+
|
|
|
+ event_time = time_diary_qs[0]['event_time']
|
|
|
+ dt = datetime.fromtimestamp(event_time)
|
|
|
+ dt_zero = datetime(dt.year, dt.month, dt.day)
|
|
|
+
|
|
|
+ diary_date = int(dt_zero.timestamp())
|
|
|
+
|
|
|
+ # 查找或创建用户今天的 TimeDiary
|
|
|
+ time_diary, created = TimeDiary.objects.get_or_create(
|
|
|
+ user_id=user_id,
|
|
|
+ diary_date=diary_date,
|
|
|
+ defaults={
|
|
|
+ 'created_time': int(time.time()),
|
|
|
+ 'updated_time': int(time.time())
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ if liked_status == 1:
|
|
|
+ # 添加到 TimeDiary(中间表中插入)
|
|
|
+ DiaryAlbumMediaRelation.objects.get_or_create(
|
|
|
+ diary=time_diary,
|
|
|
+ album_media=album_media,
|
|
|
+ defaults={
|
|
|
+ 'created_time': int(time.time()),
|
|
|
+ 'updated_time': int(time.time())
|
|
|
+ }
|
|
|
+ )
|
|
|
+ time_diary_qs.update(status=2, updated_time=int(time.time()))
|
|
|
+
|
|
|
+ elif liked_status == 0:
|
|
|
+ # 从中间表移除
|
|
|
+ DiaryAlbumMediaRelation.objects.filter(diary=time_diary, album_media=album_media).delete()
|
|
|
+ if DiaryAlbumMediaRelation.objects.filter(diary=time_diary).count() == 0:
|
|
|
+ time_diary.delete()
|
|
|
+ if not DiaryAlbumMediaRelation.objects.filter(album_media=album_media).exists():
|
|
|
+ time_diary_qs.update(status=1, updated_time=int(time.time()))
|
|
|
+
|
|
|
+ return response.json(0)
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def media_url(storage_location, uid, channel, event_time):
|
|
|
+ if storage_location == 2:
|
|
|
+ obj_name = f'roomumy/albumMedia/{uid}/{channel}/{event_time}.jpeg'
|
|
|
+ if CONFIG_INFO == CONFIG_CN or CONFIG_INFO == CONFIG_TEST:
|
|
|
+ aws_client = boto3.client(
|
|
|
+ 's3',
|
|
|
+ aws_access_key_id=AWS_ACCESS_KEY_ID[0],
|
|
|
+ aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
|
|
|
+ region_name='cn-northwest-1'
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ aws_client = boto3.client(
|
|
|
+ 's3',
|
|
|
+ aws_access_key_id=AWS_ACCESS_KEY_ID[1],
|
|
|
+ aws_secret_access_key=AWS_SECRET_ACCESS_KEY[1],
|
|
|
+ region_name='cn-northwest-1'
|
|
|
+ )
|
|
|
+ params = {'Key': obj_name, 'Bucket': 'ansjerfilemanager'}
|
|
|
+ media_url = aws_client.generate_presigned_url(
|
|
|
+ 'get_object', Params=params, ExpiresIn=300)
|
|
|
+ elif storage_location == 5:
|
|
|
+ obj_name = f'roomumy/albumMedia/{uid}/{channel}/{event_time}.jpeg'
|
|
|
+ obs_client = ObsClient(
|
|
|
+ access_key_id=HUAWEICLOUD_AK, secret_access_key=HUAWEICLOUD_SK, server=HUAWEICLOUD_OBS_SERVER)
|
|
|
+ create_res = obs_client.createSignedUrl(
|
|
|
+ method='GET', bucketName="asj-app", objectKey=obj_name, expires=600)
|
|
|
+ media_url = create_res.signedUrl
|
|
|
+ else:
|
|
|
+ media_url = ''
|
|
|
+ return media_url
|
|
|
+
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def clear_album_media(response):
|
|
|
+ # 获取当前时间
|
|
|
+ current_time = int(time.time()) - 2592000
|
|
|
+
|
|
|
+ # 预加载关联的TimeAlbum对象
|
|
|
+ album_media_qs = AlbumMedia.objects.filter(
|
|
|
+ status=1,
|
|
|
+ event_time__lt=current_time
|
|
|
+ )
|
|
|
+
|
|
|
+ # 如果没有需要处理的数据,直接返回
|
|
|
+ if not album_media_qs.exists():
|
|
|
+ return response.json(0)
|
|
|
+
|
|
|
+ # 初始化 Huawei Cloud 的 ObsClient
|
|
|
+ obs_client = ObsClient(
|
|
|
+ access_key_id=HUAWEICLOUD_AK,
|
|
|
+ secret_access_key=HUAWEICLOUD_SK,
|
|
|
+ server=HUAWEICLOUD_OBS_SERVER
|
|
|
+ )
|
|
|
+
|
|
|
+ # 根据配置选择初始化 AWS 客户端
|
|
|
+ aws_client_config = {
|
|
|
+ 'aws_access_key_id': AWS_ACCESS_KEY_ID[0] if CONFIG_INFO in [CONFIG_CN, CONFIG_TEST] else AWS_ACCESS_KEY_ID[1],
|
|
|
+ 'aws_secret_access_key': AWS_SECRET_ACCESS_KEY[0] if CONFIG_INFO in [CONFIG_CN, CONFIG_TEST] else AWS_SECRET_ACCESS_KEY[1],
|
|
|
+ 'region_name': 'cn-northwest-1' if CONFIG_INFO in [CONFIG_CN, CONFIG_TEST] else 'us-east-1'
|
|
|
+ }
|
|
|
+ aws_client = boto3.client('s3', **aws_client_config)
|
|
|
+
|
|
|
+ # 准备批量删除的对象
|
|
|
+ aws_objects_to_delete = []
|
|
|
+ obs_objects_to_delete = []
|
|
|
+ time_album_ids_to_check = set()
|
|
|
+ album_media_ids_to_delete = []
|
|
|
+
|
|
|
+ # 收集需要删除的对象和时间相册ID
|
|
|
+ for album_media in album_media_qs:
|
|
|
+ uid = album_media.device_id
|
|
|
+ event_time = album_media.event_time
|
|
|
+ obj_name = f'roomumy/albumMedia/{uid}/{album_media.channel}/{event_time}.jpeg'
|
|
|
+
|
|
|
+ album_media_ids_to_delete.append(album_media.id)
|
|
|
+
|
|
|
+ if album_media.time_album_id:
|
|
|
+ time_album_ids_to_check.add(album_media.time_album_id)
|
|
|
+
|
|
|
+ if album_media.storage_location == 2:
|
|
|
+ aws_objects_to_delete.append({'Key': obj_name})
|
|
|
+ elif album_media.storage_location == 5:
|
|
|
+ obs_objects_to_delete.append(obj_name)
|
|
|
+
|
|
|
+ # 批量删除AWS对象
|
|
|
+ if aws_objects_to_delete:
|
|
|
+ # AWS S3支持批量删除,最多1000个对象每次
|
|
|
+ for i in range(0, len(aws_objects_to_delete), 1000):
|
|
|
+ batch = aws_objects_to_delete[i:i + 1000]
|
|
|
+ aws_client.delete_objects(
|
|
|
+ Bucket='ansjerfilemanager',
|
|
|
+ Delete={'Objects': batch}
|
|
|
+ )
|
|
|
+
|
|
|
+ # 删除华为OBS对象
|
|
|
+ if obs_objects_to_delete:
|
|
|
+ for obj_name in obs_objects_to_delete:
|
|
|
+ obs_client.deleteObject(bucketName="asj-app", objectKey=obj_name)
|
|
|
+
|
|
|
+ # 检查需要删除的TimeAlbum
|
|
|
+ if time_album_ids_to_check:
|
|
|
+ # 查询TimeAlbum关联的AlbumMedia
|
|
|
+ time_albums_with_media = AlbumMedia.objects.filter(
|
|
|
+ time_album_id__in=time_album_ids_to_check
|
|
|
+ ).exclude(
|
|
|
+ id__in=album_media_ids_to_delete
|
|
|
+ ).values_list('time_album_id', flat=True).distinct()
|
|
|
+
|
|
|
+ # 找出没有关联媒体的TimeAlbum
|
|
|
+ time_albums_to_delete = set(time_album_ids_to_check) - set(time_albums_with_media)
|
|
|
+
|
|
|
+ # 批量删除TimeAlbum
|
|
|
+ if time_albums_to_delete:
|
|
|
+ TimeAlbum.objects.filter(id__in=time_albums_to_delete).delete()
|
|
|
+
|
|
|
+ # 处理完所有项后,删除数据库中的记录
|
|
|
+ album_media_qs.delete()
|
|
|
+
|
|
|
+ return response.json(0)
|