from aiohttp import web from aiohttp_session import get_session from user import UserError from user import LoginError, log_in, log_out from user import SignupError, sign_up from user import find_user_by_id from user import get_user_videos, get_user_videos_count from user import is_video_liked from user import like_video, unlike_video from user import upload_avatar, upload_video from user import serialize_user from user import get_authorized_user from video import VideoError from video import serialize_video from video import find_video_by_id from video import get_random_video from video import get_likes, get_tags from comment import get_comments, get_comments_count, post_comment from common import search_videos, suggest_tag from tools import verify_captcha from config import config routes = web.RouteTableDef() def report_error(error): return web.json_response({ 'error': str(error) }) @routes.post('/api/random') async def api_random(request): video = await get_random_video() return web.json_response({ 'video_id': video.id }) @routes.post('/api/exists') async def api_exists(request): data = await request.post() video_id = data.get('video_id') is_exists = True try: video = await find_video_by_id(video_id) except VideoError: is_exists = False return web.json_response({ 'video_id': video.id if is_exists else -1, 'is_exists': is_exists }) @routes.post('/api/login') async def api_login(request): session = await get_session(request) data = await request.post() username = data.get('username') password = data.get('password') hcaptcha_token = data.get('h-captcha-response') if not await verify_captcha(hcaptcha_token): return report_error('captcha check failed') try: user = await log_in(session, username, password) except (UserError, LoginError) as error: return report_error(error) return web.json_response({ 'user_id': user.id }) @routes.post('/api/signup') async def api_signup(request): session = await get_session(request) data = await request.post() username = data.get('username') password = data.get('password') hcaptcha_token = data.get('h-captcha-response') if not await verify_captcha(hcaptcha_token): return report_error('captcha check failed') try: user = await sign_up(session, username, password, ip_address=request.remote) except (UserError, SignupError) as error: return report_error(error) return web.json_response({ 'user_id': user.id }) @routes.post('/api/logout') async def api_logout(request): session = await get_session(request) try: await log_out(session) except UserError as error: return report_error(error) return web.json_response({ 'status': 'success' }) @routes.post('/api/user') async def api_user(request): data = await request.post() user_id = data.get('user_id') try: user = await find_user_by_id(user_id) except UserError as error: return report_error(error) return web.json_response(await serialize_user(user)) @routes.post('/api/videos') async def api_videos(request): data = await request.post() user_id = data.get('user_id') offset = data.get('offset') try: videos = await get_user_videos(user_id, offset=offset) videos_count = await get_user_videos_count(user_id) except (UserError, VideoError) as error: return report_error(error) return web.json_response({ 'videos': videos, 'videos_count': videos_count }) @routes.post('/api/comments') async def api_comments(request): data = await request.post() video_id = data.get('video_id') offset = data.get('offset') try: comments = await get_comments(video_id, offset=offset) comments_count = await get_comments_count(video_id) except VideoError as error: return report_error(error) return web.json_response({ 'comments': comments, 'comments_count': comments_count }) @routes.post('/api/search') async def api_search(request): data = await request.post() tags = data.get('tags') offset = data.get('offset') try: videos = await search_videos(tags, offset=offset) except SyntaxError as error: # SyntaxError is thrown by parse_tags. return report_error(error) return web.json_response({ 'videos': videos }) @routes.post('/api/suggest') async def api_tags(request): data = await request.post() tag = data.get('tag') try: tags_list = await suggest_tag(tag) except SyntaxError as error: return report_error(error) return web.json_response({ 'tags_list': tags_list }) @routes.post('/api/tags') async def api_tags(request): data = await request.post() video_id = data.get('video_id') try: tags_list = await get_tags(video_id) except VideoError as error: return report_error(error) return web.json_response({ 'tags_list': tags_list }) @routes.post('/api/liked') async def api_liked(request): session = await get_session(request) data = await request.post() video_id = data.get('video_id') try: is_liked = await is_video_liked(session, video_id) except (UserError, VideoError) as error: return report_error(error) return web.json_response({ 'is_liked': is_liked }) @routes.post('/api/likes') async def api_likes(request): data = await request.post() video_id = data.get('video_id') try: likes_count = await get_likes(video_id) except VideoError as error: return report_error(error) return web.json_response({ 'likes_count': likes_count }) @routes.post('/api/like') async def api_like(request): session = await get_session(request) data = await request.post() video_id = data.get('video_id') try: await like_video(session, video_id) likes_count = await get_likes(video_id) except (UserError, VideoError) as error: return report_error(error) return web.json_response({ 'likes_count': likes_count }) @routes.post('/api/unlike') async def api_unlike(request): session = await get_session(request) data = await request.post() video_id = data.get('video_id') try: await unlike_video(session, video_id) likes_count = await get_likes(video_id) except (UserError, VideoError) as error: return report_error(error) return web.json_response({ 'likes_count': likes_count }) @routes.post('/api/comment') async def api_comment(request): session = await get_session(request) data = await request.post() video_id = data.get('video_id') text = data.get('text') try: comment = await post_comment(session, video_id, text) except (UserError, VideoError, ValueError) as error: return report_error(error) return web.json_response({ 'comment_id': comment.id }) @routes.post('/api/upload/avatar') async def api_upload_avatar(request): session = await get_session(request) reader = await request.multipart() image = await reader.next() try: await upload_avatar(session, image) user = await get_authorized_user(session) except UserError as error: return report_error(error) return web.json_response(await serialize_user(user)) @routes.post('/api/upload/video') async def api_upload_video(request): session = await get_session(request) if 'authorized' not in session: return web.json_response({ 'error': 'not authorized.' }) video = None tags = None hcaptcha_token = None reader = await request.multipart() while True: part = await reader.next() if not part: break if part.name == 'video': video = bytearray() size = 0 while True: chunk = await part.read_chunk() if not chunk: break size += len(chunk) if size >= config.MAX_VIDEO_SIZE * 1024 * 1024: return report_error('illegal video') video += chunk elif part.name == 'tags': tags = await part.read_chunk() tags = tags.decode('ASCII') elif part.name == 'h-captcha-response': hcaptcha_token = await part.read_chunk() hcaptcha_token = hcaptcha_token.decode('ASCII') if not hcaptcha_token: return report_error('captcha check failed') if not await verify_captcha(hcaptcha_token): return report_error('captcha check failed') if not video: return report_error('illegal video') if not tags: return report_error('illegal tags') try: video = await upload_video(session, video, tags) except (UserError, VideoError, SyntaxError) as error: return report_error(error) return web.json_response({ 'video_id': video.id })