def serialize_post(post, authenticated_user): if not post: return None ret = { 'id': post.post_id, 'creationTime': post.creation_time, 'lastEditTime': post.last_edit_time, 'safety': SAFETY_MAP[post.safety], 'source': post.source, 'type': TYPE_MAP[post.type], 'checksum': post.checksum, 'fileSize': post.file_size, 'canvasWidth': post.canvas_width, 'canvasHeight': post.canvas_height, 'contentUrl': get_post_content_url(post), 'thumbnailUrl': get_post_thumbnail_url(post), 'flags': post.flags, 'tags': [tag.first_name for tag in post.tags], 'relations': [rel.post_id for rel in post.relations], 'notes': sorted(serialize_note(note) for note in post.notes), 'user': users.serialize_user(post.user, authenticated_user), 'score': post.score, 'featureCount': post.feature_count, 'lastFeatureTime': post.last_feature_time, 'favoritedBy': [users.serialize_user(rel.user, authenticated_user) \ for rel in post.favorited_by], 'hasCustomThumbnail': files.has(get_post_thumbnail_backup_path(post)), } if authenticated_user: ret['ownScore'] = scores.get_score(post, authenticated_user) return ret
def serialize_post(post, auth_user, options=None): return util.serialize_entity( post, { 'id': lambda: post.post_id, 'version': lambda: post.version, 'creationTime': lambda: post.creation_time, 'lastEditTime': lambda: post.last_edit_time, 'safety': lambda: SAFETY_MAP[post.safety], 'source': lambda: post.source, 'type': lambda: TYPE_MAP[post.type], 'mimeType': lambda: post.mime_type, 'checksum': lambda: post.checksum, 'fileSize': lambda: post.file_size, 'canvasWidth': lambda: post.canvas_width, 'canvasHeight': lambda: post.canvas_height, 'contentUrl': lambda: get_post_content_url(post), 'thumbnailUrl': lambda: get_post_thumbnail_url(post), 'flags': lambda: post.flags, 'tags': lambda: [ tag.names[0].name for tag in tags.sort_tags(post.tags)], 'relations': lambda: sorted( { post['id']: post for post in [ serialize_micro_post(rel, auth_user) for rel in post.relations] }.values(), key=lambda post: post['id']), 'user': lambda: users.serialize_micro_user(post.user, auth_user), 'score': lambda: post.score, 'ownScore': lambda: scores.get_score(post, auth_user), 'ownFavorite': lambda: len([ user for user in post.favorited_by if user.user_id == auth_user.user_id] ) > 0, 'tagCount': lambda: post.tag_count, 'favoriteCount': lambda: post.favorite_count, 'commentCount': lambda: post.comment_count, 'noteCount': lambda: post.note_count, 'relationCount': lambda: post.relation_count, 'featureCount': lambda: post.feature_count, 'lastFeatureTime': lambda: post.last_feature_time, 'favoritedBy': lambda: [ users.serialize_micro_user(rel.user, auth_user) for rel in post.favorited_by ], 'hasCustomThumbnail': lambda: files.has(get_post_thumbnail_backup_path(post)), 'notes': lambda: sorted( [serialize_note(note) for note in post.notes], key=lambda x: x['polygon']), 'comments': lambda: [ comments.serialize_comment(comment, auth_user) for comment in sorted( post.comments, key=lambda comment: comment.creation_time)], }, options)
def generate_post_thumbnail(post): if files.has(get_post_thumbnail_backup_path(post)): content = files.get(get_post_thumbnail_backup_path(post)) else: content = files.get(get_post_content_path(post)) try: image = images.Image(content) image.resize_fill( int(config.config['thumbnails']['post_width']), int(config.config['thumbnails']['post_height'])) files.save(get_post_thumbnail_path(post), image.to_jpeg()) except errors.ProcessingError: files.save(get_post_thumbnail_path(post), EMPTY_PIXEL)
def populate_reverse_search() -> None: excluded_post_ids = image_hash.get_all_paths() post_ids_to_hash = (db.session.query(model.Post.post_id).filter( (model.Post.type == model.Post.TYPE_IMAGE) | (model.Post.type == model.Post.TYPE_ANIMATION)).filter( ~model.Post.post_id.in_(excluded_post_ids)).order_by( model.Post.post_id.asc()).all()) for post_ids_chunk in util.chunks(post_ids_to_hash, 100): posts_chunk = (db.session.query(model.Post).filter( model.Post.post_id.in_(post_ids_chunk)).all()) for post in posts_chunk: content_path = get_post_content_path(post) if files.has(content_path): image_hash.add_image(post.post_id, files.get(content_path))
def generate_post_thumbnail(post: model.Post) -> None: assert post if files.has(get_post_thumbnail_backup_path(post)): content = files.get(get_post_thumbnail_backup_path(post)) else: content = files.get(get_post_content_path(post)) try: assert content image = images.Image(content) image.resize_fill( int(config.config["thumbnails"]["post_width"]), int(config.config["thumbnails"]["post_height"]), ) files.save(get_post_thumbnail_path(post), image.to_jpeg()) except errors.ProcessingError: files.save(get_post_thumbnail_path(post), EMPTY_PIXEL)
def update_user_name(user: model.User, name: str) -> None: assert user if not name: raise InvalidUserNameError('닉네임(ID)은 빈 값일 수 없습니다.') if util.value_exceeds_column_size(name, model.User.name): raise InvalidUserNameError('닉네임(ID)이 너무 깁니다.') name = name.strip() name_regex = config.config['user_name_regex'] if not re.match(name_regex, name): raise InvalidUserNameError('닉네임(ID) %r 은(는) 다음의 정규식을 만족해야 합니다: %r' % (name, name_regex)) other_user = try_get_user_by_name(name) if other_user and other_user.user_id != user.user_id: raise UserAlreadyExistsError('사용자 %r 은(는) 이미 존재합니다.' % name) if user.name and files.has(get_avatar_path(user.name)): files.move(get_avatar_path(user.name), get_avatar_path(name)) user.name = name
def update_user_name(user: model.User, name: str) -> None: assert user if not name: raise InvalidUserNameError('Name cannot be empty.') if util.value_exceeds_column_size(name, model.User.name): raise InvalidUserNameError('User name is too long.') name = name.strip() name_regex = config.config['user_name_regex'] if not re.match(name_regex, name): raise InvalidUserNameError('User name %r must satisfy regex %r.' % (name, name_regex)) other_user = try_get_user_by_name(name) if other_user and other_user.user_id != user.user_id: raise UserAlreadyExistsError('User %r already exists.' % name) if user.name and files.has(get_avatar_path(user.name)): files.move(get_avatar_path(user.name), get_avatar_path(name)) user.name = name
def update_user_name(user: model.User, name: str) -> None: assert user if not name: raise InvalidUserNameError('Name cannot be empty.') if util.value_exceeds_column_size(name, model.User.name): raise InvalidUserNameError('User name is too long.') name = name.strip() name_regex = config.config['user_name_regex'] if not re.match(name_regex, name): raise InvalidUserNameError( 'User name %r must satisfy regex %r.' % (name, name_regex)) other_user = try_get_user_by_name(name) if other_user and other_user.user_id != user.user_id: raise UserAlreadyExistsError('User %r already exists.' % name) if user.name and files.has(get_avatar_path(user.name)): files.move(get_avatar_path(user.name), get_avatar_path(name)) user.name = name
def update_user_avatar(user, avatar_style, avatar_content=None): assert user if avatar_style == 'gravatar': user.avatar_style = user.AVATAR_GRAVATAR elif avatar_style == 'manual': user.avatar_style = user.AVATAR_MANUAL avatar_path = 'avatars/' + user.name.lower() + '.png' if not avatar_content: if files.has(avatar_path): return raise InvalidAvatarError('Avatar content missing.') image = images.Image(avatar_content) image.resize_fill( int(config.config['thumbnails']['avatar_width']), int(config.config['thumbnails']['avatar_height'])) files.save(avatar_path, image.to_png()) else: raise InvalidAvatarError( 'Avatar style %r is invalid. Valid avatar styles: %r.' % ( avatar_style, ['gravatar', 'manual']))
def update_user_avatar(user: model.User, avatar_style: str, avatar_content: Optional[bytes] = None) -> None: assert user if avatar_style == 'gravatar': user.avatar_style = user.AVATAR_GRAVATAR elif avatar_style == 'manual': user.avatar_style = user.AVATAR_MANUAL avatar_path = 'avatars/' + user.name.lower() + '.png' if not avatar_content: if files.has(avatar_path): return raise InvalidAvatarError('아바타 컨텐츠가 누락되었습니다.') image = images.Image(avatar_content) image.resize_fill(int(config.config['thumbnails']['avatar_width']), int(config.config['thumbnails']['avatar_height'])) files.save(avatar_path, image.to_png()) else: raise InvalidAvatarError('아바타 스타일 %r 은(는) 잘못된 값입니다. 올바른 스타일 값: %r.' % (avatar_style, ['gravatar', 'manual']))
def populate_reverse_search(): excluded_post_ids = image_hash.get_all_paths() post_ids_to_hash = (db.session .query(db.Post.post_id) .filter( (db.Post.type == db.Post.TYPE_IMAGE) | (db.Post.type == db.Post.TYPE_ANIMATION)) .filter(~db.Post.post_id.in_(excluded_post_ids)) .order_by(db.Post.post_id.asc()) .all()) for post_ids_chunk in util.chunks(post_ids_to_hash, 100): posts_chunk = (db.session .query(db.Post) .filter(db.Post.post_id.in_(post_ids_chunk)) .all()) for post in posts_chunk: content_path = get_post_content_path(post) if files.has(content_path): image_hash.add_image(post.post_id, files.get(content_path))
def generate_post_thumbnail(post: model.Post) -> None: assert post if files.has(get_post_thumbnail_backup_path(post)): content = files.get(get_post_thumbnail_backup_path(post)) else: content = files.get(get_post_content_path(post)) try: assert content if post.type == model.Post.TYPE_IMAGE: media = images.Image(content) elif post.type == model.Post.TYPE_VIDEO: media = images.Video(content) thumb = media.to_thumbnail( int(config.config["thumbnails"]["post_width"]), int(config.config["thumbnails"]["post_height"]), ) files.save(get_post_thumbnail_path(post), thumb) except errors.ProcessingError: files.save(get_post_thumbnail_path(post), EMPTY_PIXEL)
def update_user_avatar(user: model.User, avatar_style: str, avatar_content: Optional[bytes] = None) -> None: assert user if avatar_style == "gravatar": user.avatar_style = user.AVATAR_GRAVATAR elif avatar_style == "manual": user.avatar_style = user.AVATAR_MANUAL avatar_path = "avatars/" + user.name.lower() + ".png" if not avatar_content: if files.has(avatar_path): return raise InvalidAvatarError("Avatar content missing.") image = images.Image(avatar_content) image.resize_fill( int(config.config["thumbnails"]["avatar_width"]), int(config.config["thumbnails"]["avatar_height"]), ) files.save(avatar_path, image.to_png()) else: raise InvalidAvatarError( "Avatar style %r is invalid. Valid avatar styles: %r." % (avatar_style, ["gravatar", "manual"]))
def serialize_has_custom_thumbnail(self) -> Any: return files.has(get_post_thumbnail_backup_path(self.post))
def save(content: bytes) -> str: checksum = util.get_sha1(content) path = _get_path(checksum) if not files.has(path): files.save(path, content) return checksum