async def RequestTeacher(request, token: Token, chat_id): user = token.jwt_identity # chat_id로 question_id 구할 수 있음 chat = await request.app.db.chats.find_one({'_id': ObjectId(chat_id)}) if not chat: abort(404) question = await request.app.db.questions.find_one( {'_id': ObjectId(chat['question_id'])}) if not question: abort(500, message='question을 찾을 수 없음') mentor = await request.app.db.users.find_one( {'_id': ObjectId(question['user_id'])}) if not mentor: abort(500, message='mentor를 찾을 수 없음') req = { 'question_id': chat['question_id'], 'chat_id': chat_id, 'school': mentor['school'], 'message': request.json['message'], 'timestamp': int(time.time()) } res = await request.app.db.teachers.insert_one(req) if not res.acknowledged: abort(500) return res_json({})
async def RequestOffline(request, token: Token, chat_id): user = token.jwt_identity # chat_id로 question_id 구할 수 있음 chat = await request.app.db.chats.find_one({'_id': ObjectId(chat_id)}) if not chat: abort(404) question = await request.app.db.questions.find_one( {'_id': ObjectId(chat['question_id'])}) if not question: abort(500, message='question을 찾을 수 없음') if question['user_id'] == user['id']: # user is mentee sender = 'mentee' else: sender = 'mentor' # user_id로 sender 구하고, text 타입의 chat 만들어 저장 chat = { 'type': 'offline', 'question_id': question['id'], 'sender': sender, 'message': request.json['message'], 'timestamp': int(time.time()), 'offline': { 'time': request.json['time'], 'place': request.json['place'] } } res = await request.app.db.chats.insert_one(chat) if not res.acknowledged: abort(500) await sio.emit('update', {}, room=question['id']) return res_json({})
async def QuestionView(request, token: Token, question_id): user = token.jwt_identity question = await request.app.db.questions.find_one({ '_id': ObjectId(question_id) }, {'_id':False}) if not question: abort(404) if question['user_id'] == user['id']: question['mine'] = True question['id'] = question_id question['user'] = await request.app.db.users.find_one({ '_id': ObjectId(question['user_id']) }, {'_id': False}) cursor = request.app.db.requests.find({ 'question_id': question_id }) question['requests'] = await cursor.to_list(length=50) for idx, req in enumerate(question['requests']): question['requests'][idx]['id'] = str(req['_id']) del question['requests'][idx]['_id'] question['requests'][idx]['user'] = await request.app.db.users.find_one({ '_id': ObjectId(question['user_id']) }, {'_id': False}) # TODO: fix this return res_json(question)
async def ChatFeedback(request, token: Token, question_id): user = token.jwt_identity question = await request.app.db.questions.find_one( {'_id': ObjectId(question_id)}) if not question: abort(500, message='question을 찾을 수 없음') if question['user_id'] == user['id']: # user is mentee sender = 'mentee' else: sender = 'mentor' # 같은 question_id의 feedback 찾고 있으면 question의 status를 C로 바꿈 if await request.app.db.feedbacks.find_one({'question_id': question_id}): res = await request.app.db.questions.update_one( {'_id': ObjectId(question_id)}, {'$set': { 'status': 'C' }}) if not res.acknowledged: abort(500) feedback = { 'question_id': question_id, 'sender': sender, 'user_id': user['id'], 'message': request.json['message'], 'timestamp': int(time.time()) } res = await request.app.db.feedbacks.insert_one(feedback) if not res.acknowledged: abort(500) return res_json({'id': str(res.inserted_id)})
async def write_comments(request, identity: dict, post_id): post = await request.app.db.posts.find_one(ObjectId(post_id)) if not post: abort(404) if any(comment['author_id'] == identity['id'] for comment in post['comments']): abort(400) comment = { 'content': request.json['content'], 'timestamp': int(time.time()), 'author': '{} {}'.format(identity['student']['serial'], identity['name']), 'author_id': identity['id'], } res = await request.app.db.posts.update_one( {'_id': ObjectId(post_id)}, {'$push': { 'comments': comment }}) if not res.acknowledged: abort(500) return res_json({})
async def QuestionList(request, token: Token): page = request.args.get('page') or 1 per_page = request.args.get('per_page') or 10 query = { 'status': request.args.get('status') or 'P', 'category': request.args.get('category') } if not query['category']: del query['category'] cursor = request.app.db.questions.find({ }).sort( 'timestamp', pymongo.ASCENDING ).skip( (page - 1) * per_page ).limit(per_page) questions = await cursor.to_list(length=50) for question in questions: question['id'] = str(question['_id']) del question['_id'] question['user'] = await request.app.db.users.find_one({ '_id': ObjectId(question['user_id']) }, {'_id': False}) del question['user_id'] cursor = request.app.db.requests.find({ 'question_id': question['id'] }, {'_id': False}) reqs = await cursor.to_list(length=50) question['requests'] = len(reqs) question['views'] = 0 return res_json({ 'questions': questions })
async def check_hash(request, file_id): # find update with given fileId update = await request.app.db.updates.find_one({'_id': ObjectId(file_id)}) if not update: abort(404) # validation failed if update.hash != request.json['hash']: abort(400) # update device status res = await request.app.db.devices.update( {'wallet': request.json['wallet']}, {'$set': { 'update': None }}) if not res.acknowledged: abort(404) # log success log = { 'type': 'success', 'timestamp': int(time.time()), 'json': { 'route': update['route'], 'hash': update['hash'] } } await request.app.db.logs.insert_one(log) return res_json({})
async def AuthLogin(request): email, password = request.json['email'], request.json['password'] user = await request.app.db.users.find_one( { 'email': email, 'password': password }, {'password': False}) if not user: abort(404) user['id'] = str(user['_id']) del user['_id'] identity = {'id': user['id'], 'name': user['name']} token = await create_access_token(identity=identity, app=request.app, expires_delta=False) refresh_token = await create_refresh_token(identity=identity, app=request.app) return res_json({ 'token': token, 'refresh_token': refresh_token, 'user': user })
async def ChatPost(request, token: Token, question_id): user = token.jwt_identity question = await request.app.db.questions.find_one( {'_id': ObjectId(question_id)}) if not question: abort(404) if question['user_id'] == user['id']: # user is mentee sender = 'mentee' else: sender = 'mentor' # user_id로 sender 구하고, text 타입의 chat 만들어 저장 chat = { 'type': 'text', 'question_id': question_id, 'sender': sender, 'message': request.json['message'], 'timestamp': int(time.time()) } res = await request.app.db.chats.insert_one(chat) if not res.acknowledged: abort(500) await sio.emit('update', {}, room=question_id) return res_json({})
async def AuthLogin(request): _id, _password = request.json['id'], request.json['password'] user = await request.app.db.users.find_one({'id': _id} ) # check if _id exists in DB if not user: # if not, query student profile with token and save to DB dimigoin_token = await dimigo_auth(_id, _password) if not dimigoin_token: # 잘못된 로그인 abort(404) student = await dimigo_profile(dimigoin_token) if not student: # API server error abort(403) user = {'id': _id, 'student': student} res = await request.app.db.users.insert_one(user) if not res.acknowledged: abort(500) identity = { 'id': str(user['_id']), 'name': user['student']['name'], 'serial': user['student']['serial'] } token = await create_access_token(identity=identity, app=request.app) refresh_token = await create_refresh_token(identity=identity, app=request.app) return res_json({ 'id': identity['id'], 'token': token, 'refresh_token': refresh_token, # 'user': user['student'] })
async def AuthJoin(request): try: keys = [ 'name', 'school', 'grade', 'klass', 'number', 'photo', 'email', 'password' ] user = {'user_type': 'S'} for key in keys: user[key] = request.json[key] except BaseException: return res_json(400) if await request.app.db.users.find_one({'email': user['email']}): abort(400) res = await request.app.db.users.insert_one(user) if not res.acknowledged: abort(500) return res_json({})
async def list_post(request, identity: dict): cursor = request.app.db.posts.find({}) posts = await cursor.to_list(length=50) for idx, post in enumerate(posts): post['id'] = str(post['_id']) del post['_id'] post['idx'] = idx + 1 post['likes'] = len(post['comments']) post['expire'] = '2019-09-15' # test data return res_json({'posts': posts})
async def check_update(request): # find device with given wallet device = await request.app.db.devices.find_one( {'wallet': request.json['wallet']}) if not device: abort(404) # return update info if available if device['update']: update = await request.app.db.updates.find_one( {'_id': ObjectId(device['update'])}) if not update: abort(500) return res_json({ 'update': True, 'id': str(update['_id']), 'txHash': update['txHash'], }) return res_json({'update': False})
async def edit_comments(request, identity: dict, post_id): res = await request.app.db.posts.update_one( { '_id': ObjectId(post_id), 'comments.author_id': identity['id'] }, {'$set': { 'comments.$.content': request.json['content'] }}) if not res.acknowledged: abort(404) return res_json({})
async def delete_comments(request, identity: dict, post_id): res = await request.app.db.posts.update_one( {'_id': ObjectId(post_id)}, {'$pull': { 'comments': { 'author_id': identity['id'] } }}) if not res.acknowledged: abort(404) return res_json({})
async def ChatEnd(request, token: Token, question_id): # user = token.jwt_identity # question_id의 status를 F로 변경 res = await request.app.db.questions.update_one( {'_id': ObjectId(question_id)}, {'$set': { 'status': 'F' }}) if not res.acknowledged: abort(500) await sio.emit('end', {}, room=question_id) return res_json({})
async def UploadProfile(request): profile_image = request.files.get('file') _, ext = os.path.splitext(profile_image.name) timestamp = int(time.time()) file_path = './profile/{}'.format(str(timestamp) + ext) with open( os.path.join('.{}'.format(request.app.config['UPLOAD_PATH']), file_path), 'wb') as fp: fp.write(profile_image.body) return res_json( {'url': urljoin(request.app.config['UPLOAD_PATH'], file_path)}, escape_forward_slashes=False)
async def view_post(request, post_id): post = await request.app.db.posts.find_one(ObjectId(post_id)) if not post: abort(404) post['_id'] = str(post['_id']) # TODO: post metadata post['status'] = True post['start'] = '2019-08-12' post['expire'] = '2019-09-15' post['likes'] = len(post['comments']) return res_json(post)
async def download(request): update = await request.app.db.updates.find_one({ '_id': ObjectId(device['update']) }) if not update: abort(404) if update['key'] != request.json['key']: abort(400) return res_json({ 'url': urljoin( request.url_root, update['route'].replace('server', '') ) })
async def QuestionPost(request, token: Token): user = token.jwt_identity question = { 'user_id': user['id'], 'status': 'P', 'portfolio': None, 'timestamp': int(time.time()) } keys = ['title', 'article', 'category', 'photo'] for key in keys: question[key] = request.json[key] res = await request.app.db.questions.insert_one(question) if not res.acknowledged: abort(500) return res_json({'id': str(res.inserted_id)})
async def write_post(request, identity: dict): post = { 'name': request.json['name'], 'content': request.json['content'], 'comments': [], 'image': request.json.get('image'), 'timestamp': int(time.time()), 'author': identity['name'][0] + '**', 'author_id': identity['id'], 'topic': request.json['topic'] } res = await request.app.db.posts.insert_one(post) if not res.acknowledged: abort(500) return res_json({'post_id': str(res.inserted_id)})
async def MentoringList(request, token: Token): user = token.jwt_identity questions = { 'user': {}, 'mentor': [], # user가 멘토인 questions 'mentee': [] # user가 멘티인 questions } questions['user'] = await request.app.db.users.find_one( { '_id': ObjectId(user['id']), }, {'_id': False}) # 자신의 user_id를 가진 모든 question 쿼리 + cursor = request.app.db.questions.find({'user_id': user['id']}) questions['mentee'] = await cursor.to_list(length=50) # 자신의 user_id를 가진 approve된 request 쿼리 -> question 쿼리 cursor = request.app.db.requests.find({ 'user_id': user['id'], 'approved': True, }) requests = await cursor.to_list(length=50) questions['mentor'] = [ await request.app.db.questions.find_one({ '_id': ObjectId(req['question_id']), }) for req in requests ] for question in questions['mentor']: question['id'] = str(question['_id']) del question['_id'] cursor = request.app.db.requests.find({'question_id': question['id']}, {'_id': False}) reqs = await cursor.to_list(length=50) question['requests'] = len(reqs) for question in questions['mentee']: question['id'] = str(question['_id']) del question['_id'] cursor = request.app.db.requests.find({'question_id': question['id']}, {'_id': False}) reqs = await cursor.to_list(length=50) question['requests'] = len(reqs) return res_json({'mentorings': questions})
async def edit_post(request, identity: dict, post_id): post = await request.app.db.posts.find_one(ObjectId(post_id)) if not post: abort(404) _name = request.json.get('name') _content = request.json.get('content') _image = request.json.get('image') _topic = request.json.get('topic') res = await request.app.db.posts.update_one({'_id': ObjectId(post_id)}, { '$set': { 'name': _name if _name else post['name'], 'content': _name if _content else post['content'], 'image': _name if _image else post['image'], 'topic': _topic if _topic else post['topic'] } }) if not res.acknowledged: abort(500) return res_json({})
async def MentoringRequest(request, token: Token, question_id): user = token.jwt_identity # 이미 신청한 멘토링은 아닌지 확인 if await request.app.db.requests.find_one({ 'user_id': user['id'], 'question_id': question_id, }): abort(400) req = { 'user_id': user['id'], 'question_id': question_id, 'timestamp': int(time.time()), 'approved': False } res = await request.app.db.requests.insert_one(req) if not res.acknowledged: abort(500) return res_json({'id': str(res.inserted_id)})
async def UploadMath(request): profile_image = request.files.get('file') _, ext = os.path.splitext(profile_image.name) timestamp = int(time.time()) file_path = './math/{}'.format(str(timestamp) + ext) with open( os.path.join('.{}'.format(request.app.config['UPLOAD_PATH']), file_path), 'wb') as fp: fp.write(profile_image.body) image_url = reduce(urljoin, [ request.app.config['BASE_URL'], request.app.config['UPLOAD_PATH'], file_path ]) return res_json( { 'url': image_url, 'math': mathpix.api.image_to_math(image_url) }, escape_forward_slashes=False)
async def upload(request): print(request.files) file = request.files.get('file') upload_dir = os.path.join(request.app.config['UPLOAD_FOLDER'], random_key() + hash_string(file.name) + '/') if not os.path.exists(upload_dir): os.makedirs(upload_dir) route = os.path.join(upload_dir, file.name) with open(route, 'wb') as _f: _f.write(file.body) update = {'route': route, 'key': random_key(), 'hash': hash_file(route)} # TODO: send update.key to blockchain and receive txHash update['txHash'] = 'test' # save update res = await request.app.db.updates.insert_one(update) if not res.acknowledged: abort(500) # update device devices = request.json.get('devices') for device in devices: await request.app.db.devices.update( {'name': device}, {'$set': { 'update': update['key'] }}) # save log log = { 'route': update['route'], 'hash': update['hash'], 'time': int(time.time()) } await request.app.db.logs.insert_one(log) return res_json({'id': res.inserted_id, 'txHash': update['txHash']})
async def MentoringApprove(request, token: Token, question_id): user = token.jwt_identity # question 쿼리, 작성자 확인 question = await request.app.db.questions.find_one({ '_id': ObjectId(question_id), 'user_id': user['id'], }) if not question: abort(404) # 다른 멘토링이 이미 승인된 것은 아닌지 확인 if await request.app.db.requests.find_one({ 'question_id': question_id, 'approved': True }): abort(400) # post로 받은 request_id를 가진 request의 approved를 True로 업데이트 request_id = request.json['request_id'] res = await request.app.db.requests.update_one( {'_id': ObjectId(request_id)}, {'$set': { 'approved': True }}) if not res.acknowledged: abort(500) # question의 status 변경 res = await request.app.db.questions.update_one( {'_id': ObjectId(question_id)}, {'$set': { 'status': 'M' }}) if not res.acknowledged: abort(500) return res_json({})
async def ChatView(request, token: Token, question_id): # user = token.jwt_identity # TODO: user['id']를 사용해서 사용자 정보 쿼리 근데 뭐 맞겠지 # question_id로 question 쿼리 question = await request.app.db.questions.find_one( {'_id': ObjectId(question_id)}) if not question: abort(404) # 상태 확인 -> M이여야 함 if question['status'] != 'M': abort(400) # question_id로 chat 쿼리, timestamp로 정렬해 반환 cursor = request.app.db.chats.find({ 'question_id': question_id }).sort('timestamp', pymongo.ASCENDING) chats = await cursor.to_list(length=50) cursor = request.app.db.teachers.find({'question_id': question_id}) teachers = await cursor.to_list(length=50) for chat in chats: chat['id'] = str(chat['_id']) del chat['_id'] for teacher in teachers: if (chat['id'] == teacher['chat_id']): del teacher['question_id'] del teacher['chat_id'] teacher['id'] = str(teacher['_id']) del teacher['_id'] chat['teacher'] = teacher chat['keywords'] = request.app.keywords.search(chat['message']) print(chats) return res_json({'chats': chats})
async def register(request): wallet = request.json['wallet'] if len(wallet) != 42: abort(404) # register device device = {'name': request.json['name'], 'wallet': wallet, 'update': None} res = await request.app.db.devices.insert_one(device) if not res.acknowledged: abort(500) # save log log = { 'type': 'register', 'timestamp': int(time.time()), 'json': { 'name': device['name'], 'wallet': device['wallet'] } } await request.app.db.logs.insert_one(log) # error handling is not necessary for logging return res_json({}) # 200
async def device_info(request, wallet): res = await request.app.db.devices.delete_one({'wallet': wallet}) if not res.acknowledged: abort(404) return res_json({})