def typing(self, uid): try: # 바디 / 헤더 headers = {'content-type': 'application/json'} body = {'recipient': {'id': uid}, 'sender_action': 'typing_on'} # 보낸다 response = requests.post(self.endpoint + self.access_token, data=json.dumps(body), headers=headers, timeout=0.01) # HACK j = response.json() if j.get('error'): from app.log import Logger Logger.log('[FB > typing] 그래프 API가 오류를 반환했습니다.', 'ERROR', response.text) except requests.exceptions.ReadTimeout: # HACK: https://stackoverflow.com/a/45601591 pass except Exception as err: from app.log import Logger Logger.log('[FB > typing] 그래프 API 요청중 내부 오류 (Timeout 제외)', 'ERROR', str(err)) return
def bugreport(): if request.method == 'GET': u_id = request.args.get('id') if u_id: return render_template('bugreport.html', id=u_id) else: return render_template('bad.html', details='잘못된 접근이에요.') else: try: uid = request.form['id'] title = request.form['title'] details = request.form['steps_to_reproduce'] contact = request.form.get('want_contact') if contact: contact = request.form['contact_information'] if uid != request.args.get('id'): raise ValueError logger = Logger() logger.bugreport(uid, title, details, contact) return render_template('success.html') except (KeyError, ValueError): return render_template('bad.html', details='잘못된 접근이에요.') except Exception as err: return render_template('bad.html', details='처리되지 않은 오류입니다: ' + str(err))
def old_deprecated(): if request.method == 'GET': # Verification Test if request.args.get('hub.verify_token') == g_config['FACEBOOK']['OLD_VERIFY_TOKEN']: return request.args.get('hub.challenge') else: return 'Verification Failed!' if request.method == 'POST': try: req = request.get_json() for event in req['entry']: for e in event['messaging']: # 요청의 단위 시작 if e.get('postback', {}).get('payload') or e.get('message'): headers = { 'content-type': 'application/json' } body = { 'recipient': { 'id': e['sender']['id'] }, 'message': { 'text': '이 버전의 급식봇은 서비스가 종료되었습니다. 새로운 급식봇5를 이용해 주세요!\n' 'https://facebook.com/mealworm05/\n' '시작하기 전에 페이지 좋아요&팔로우는 필수! 아시죠?😎' } } response = requests.post( 'https://graph.facebook.com/v7.0/me/messages?access_token=' + g_config['FACEBOOK']['OLD_ACCESS_TOKEN'], data=json.dumps(body), headers=headers, timeout=1.5 ) j = response.json() if j.get('error'): Logger.log('[OLD] 그래프 API가 오류를 반환했습니다.', 'ERROR', response.text) break except Exception as e: print('F**k: {}'.format(str(e))) Logger.log('[OLD] Deprecated Request Processed.') return { 'result': 'success', 'details': 'Successfully processed deprecated /old request.' }
def send(self, recipient, thing, quick_replies=None): # 기본 헤더 / 바디 headers = {'content-type': 'application/json'} body = {'recipient': {'id': recipient}, 'message': {}} # 단순 문자열일 때 if isinstance(thing, str): body['message']['text'] = thing # 카드일 때 elif isinstance(thing, MessageElements.Card): body['message']['attachment'] = { 'type': 'template', 'payload': { 'template_type': 'generic', 'elements': [] } } for card in thing.payload: for key in card: if type(card[key]) == str: card[key] = card[key].replace('%rootdir%', self.site_root) elif type(card[key]) == list: for en in enumerate(card[key]): for nested_key in card[key][en[0]]: card[key][en[0]][nested_key] = \ card[key][en[0]][nested_key].replace('%rootdir%', self.site_root) body['message']['attachment']['payload']['elements'].append( card) # 빠른 답장 추가하기 if isinstance(quick_replies, MessageElements.QuickReply): body['message']['quick_replies'] = quick_replies.payload elif quick_replies: body['message']['quick_replies'] = quick_replies response = requests.post(self.endpoint + self.access_token, data=json.dumps(body), headers=headers, timeout=2) # Send에는 위 HACK을 적용하지 마세요! j = response.json() if j.get('error'): from app.log import Logger Logger.log('[FB > send] 그래프 API가 오류를 반환했습니다.', 'ERROR', response.text) return
def get_meal(meal_id): try: client = MongoClient() db = client['mealworm5'] meals = db.meals meal = meals.find_one({"meal_id": meal_id}) if meal: return meal else: from app.log import Logger Logger.log('[DB > get_meal] {0}번 급식이 DB에 없어요.'.format(meal_id), 'INFO') except Exception as e: from app.log import Logger Logger.log('[DB > get_meal] {0}번 급식 DB 조회중 오류 발생!'.format(meal_id), 'ERROR', str(e)) return None
def get_results(self, query, user_id, session): session = session_client.session_path(self.project_id, user_id + session) text_input = dialogflow.types.TextInput(text=query, language_code='ko_KR') query_input = dialogflow.types.QueryInput(text=text_input) response = session_client.detect_intent(session=session, query_input=query_input) Logger.log('[DF > get_intent] 인텐트 분석 완료.', 'INFO', '쿼리: %s' % query) entities = {} for e in response.query_result.parameters.fields: entities[e] = response.query_result.parameters.fields.get( e).string_value return { 'intent': response.query_result.intent.display_name, 'confidence': response.query_result.intent_detection_confidence, 'entities': entities }
def search_meal(school_code, date, mealtime): try: client = MongoClient() db = client['mealworm5'] meals = db.meals meal = meals.find_one({ '$and': [ {'school_code': school_code}, {'date': date}, {'mealtime': int(mealtime)} ] }) if meal: return meal else: from app.log import Logger Logger.log('[DB > search_meal] 급식이 DB에 없습니다.', 'INFO') return None except Exception as e: from app.log import Logger Logger.log('[DB > search_meal] DB에서 급식을 검색하 중 오류가 발생했어요..', 'INFO', str(e)) return None
def save_bugreport(uid, title, details, contact): try: client = MongoClient() db = client['mealworm5'] bugs = db.bugs bugs.insert_one({ 'report_id': '{0}_{1}'.format( uid, datetime.datetime.now(tz=pytz.timezone('Asia/Seoul')).strftime('%Y-%m-%d-%H-%M-%S') ), 'details': { 'uid': uid, 'title': title, 'details': details, 'contact': contact } }) except Exception as e: from app.log import Logger Logger.log('[DB > save_bugreport] 버그 리포트 저장 실패.', 'ERROR', str(e)) return None return True
def get_name(self, uid): """ uid번 사용자의 이름을 Graph Api에서 가져온다. :param uid: Recipient_ID :return: str, 실패하면 유저N """ # 페이스북 Graph Api 를 사용해 사용자의 진짜 이름을 가져옵니다. url = 'https://graph.facebook.com/v7.0/%s?fields=first_name,last_name&access_token=%s' \ % (uid, self.config['FACEBOOK']['ACCESS_TOKEN']) try: resp = requests.get(url, timeout=3) resp_json = resp.json() except Exception as err: from app.log import Logger Logger.log( '[GP > get_name] 그래프 API 요청중 내부 오류 (Likely Timeout -> 3s).', 'ERROR', str(err)) return '유저{0}'.format(uid) if resp_json.get('error'): from app.log import Logger Logger.log('[GP > get_name] 그래프 API가 오류를 반환했습니다.', 'ERROR', resp.text) try: if resp.status_code == 200: return resp_json['first_name'] else: from app.log import Logger Logger.log('[Graph > get_name] API 응답 코드가 200이 아닙니다!', 'ERROR', 'RECIPIENT: {0}'.format(uid)) return '유저{0}'.format(uid) except KeyError as e: from app.log import Logger Logger.log('[Graph > get_name] API KeyError가 발생했습니다!', 'ERROR', 'RECIPIENT: {0}, Error: {1}'.format(uid, str(e))) return '유저{0}'.format(uid)
def save_meal(user, meal): from app.log import Logger try: meal['created_date'] = datetime.datetime.now(pytz.timezone('Asia/Seoul')).strftime('%Y-%m-%d-%H-%M-%S') client = MongoClient() db = client['mealworm5'] meals = db.meals m = meals.find_one({"meal_id": meal['meal_id']}) if not m: meals.insert_one(meal) Logger.log('[DB > save_meal] 급식 저장 완료!', 'INFO') else: Logger.log('[DB > save_meal] 급식 저장 건너뜁니다... (동시 실행)!', 'WARN') return True except Exception as e: from app.log import Logger Logger.log('[DB > save_meal] 급식 저장 실패. UID: {0}'.format(user.uid), 'ERROR', str(e)) return None
def process_message(self, user, req_str, g_config): # 1. 오브젝트 만들기 fm = FacebookMessenger(g_config) fm.typing(user.uid) from app.log import Logger Logger.log('[PS > process_message] 메시지 처리 시작: {0} -> \'{1}\''.format( user.uid, req_str)) # 이스터 에그 if req_str.strip() == '올때 메로나': fm.send(user.uid, 'ㅇㅇㄴㅇ', Templates.QuickReplies.after_action) return user if '섹스' in req_str: fm.send(user.uid, '시발 진짜 세상 살기 힘드네', Templates.QuickReplies.after_user_error) return user # 2. DIALOGFLOW 리퀘스트 try: from app.dialogflow import DialogFlowController df = DialogFlowController(g_config) df_result = df.get_results(req_str, user.uid, user.uid + str(user.use_count)) intent = df_result['intent'] except Exception as e: from app.log import Logger Logger.log('[PS > process_message] DF 오류!', 'ERROR', 'DETAILS: {0}'.format(e)) fm.send( user.uid, '죄송합니다, 급식봇에 오류가 발생했습니다.\n' '자세한 정보: 알 수 없는 이유로 언어 분석에 실패했습니다.\n' '다시 시도해 주시고 오류가 지속되면 아래의 \'버그 신고하기\'를 이용해 주세요.', Templates.QuickReplies.after_system_error) return user # 3. Intent 분기 if intent == 'Action.SourceCode': fm.send(user.uid, '급식봇5의 소스는 여기서 보실 수 있어요!') card = Elements.Card(Templates.Cards.view_source) fm.send(user.uid, card, Templates.QuickReplies.after_action) elif intent == 'Communication.Swear': fm.send(user.uid, ':(', Templates.QuickReplies.after_user_error) elif intent == 'Communication.Yes': fm.send(user.uid, ':)', Templates.QuickReplies.default) elif intent == 'Communication.Calling': fm.send(user.uid, '네, 여기 있어요.', Templates.QuickReplies.default) elif intent == 'Communication.ThankYou': fm.send(user.uid, '고마워요!', Templates.QuickReplies.default) elif intent == 'Action.Report': return self.process_postback(user, 'BUGREPORT', g_config) elif intent == 'Action.Help': return self.process_postback(user, 'HELP', g_config) elif intent == 'Communication.Hi': fm.send(user.uid, '안녕하세요, {0}님!'.format(user.name), Templates.QuickReplies.default) elif intent == 'Communication.Bye': fm.send(user.uid, '👋', Templates.QuickReplies.default) elif intent == 'Action.GetMeal': # 급식 # i. 엔티티 추출 및 가공 entities = df_result['entities'] # 날짜 엔티티가 비어있는 경우 오늘 날짜로 만들어버리기 if entities['date-time'] == '': d = datetime.datetime.now(pytz.timezone('Asia/Seoul')) entities['date-time'] = d.strftime( '%Y-%m-%d') + 'T12:00:00+09:00' # mealtime 변환 if entities['MealTime'] == '조식': mealtime = 1 elif entities['MealTime'] == '석식': mealtime = 3 else: mealtime = 2 # ii. 학교명 유무에 따라 분기 if (entities['SchoolName'] != '') or (user.last_school_code != ''): # 학교명이 어디든 일단 있는경우 if entities['SchoolName'] != '': # 학교명을 직접 지정한 경우 try: from app.neis import NEIS neis = NEIS(g_config) school_name = entities['SchoolName'].strip() # 하드코딩된 화이트리스트에 있으면 대체 school_name_whitelist = { '한대부중': '한양대학교사범대학부속중학교', '한대부고': '한양대학교사범대학부속고등학교', '서울과고': '서울과학고', '경기과고': '경기과학고', '세종과고': '세종과학고', '한성과고': '한성과학고' } if school_name in school_name_whitelist: school_name = school_name_whitelist[school_name] school_list = neis.search_school(school_name) except Exception as e: fm.send( user.uid, '학교 조회 중 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.\n' '문제가 계속될 경우, 아래 \'버그 신고하기\'로 신고해 주세요.', Templates.QuickReplies.after_system_error) Logger.log( '[PS > process_message] 나이스 학교 조회중 오류!', 'ERROR', 'RECIPIENT: {0}, DETAILS: {1}, VALUE: {2}'.format( user.uid, str(e), entities['SchoolName'])) return user if len(school_list) == 0: # 일치하는 학교가 없는 경우 fm.send( user.uid, '학교 \'{0}\'를 찾을 수 없어요.'.format( entities['SchoolName']), Templates.QuickReplies.after_user_error) return user elif len(school_list) > 1: # 나이스에서 2개 이상의 학교를 찾음 # 안내 메시지 보내기 fm.send(user.uid, '여러 학교가 검색되었어요. 원하는 학교의 버튼을 선택해 주세요.') fm.typing(user.uid) [_, month, day] = entities['date-time'].split('T')[0].split('-') # 카드 만들어서 붙이기 school_cards = [] for sch in school_list: school_cards.append({ 'title': sch.name + ' (%s)' % sch.region_hangul, 'image_url': '', 'subtitle': sch.address, 'buttons': [{ 'type': 'postback', 'title': '{0}월 {1}일 {2} ({3}) 의 급식 보기'.format( month, day, sch.name, sch.region_hangul), 'payload': 'M_{0}_{1}_{2}'.format( sch.code, entities['date-time'].split('T')[0], str(mealtime)) }] }) # 유저한테 보내기 card = Elements.Card(school_cards) fm.send(user.uid, card) return user else: # 힉교가 정상적으로 하나만 나옴 sch = school_list[0] self.process_postback( user, 'M_{0}_{1}_{2}'.format( sch.code, entities['date-time'].split('T')[0], str(mealtime)), g_config) else: # 학교명을 생략한 경우 -> 디비에 저장된 마지막 요청 학교를 가져온다. self.process_postback( user, 'M_{0}_{1}_{2}'.format( user.last_school_code, entities['date-time'].split('T')[0], str(mealtime)), g_config) else: # 학교 이름을 지정하지도 않았고 전에 사용한 기록도 없음. # 에러 / Abort fm.send(user.uid, '이전에 요청한 학교가 없습니다. 처음 요청 시에는 학교 이름을 포함해서 요청해 주세요.', Templates.QuickReplies.after_user_error) return user else: # Unknown Intent Logger.log( '[PS > process_message] 알 수 없는 인텐트입니다: {0}. RECIPIENT: {1}'. format(intent, user.uid), 'WARN') fm.send(user.uid, '무슨 뜻인지 잘 모르겠어요.', Templates.QuickReplies.after_user_error) return user return user
import os from flask import Blueprint, request, jsonify, send_from_directory, current_app from app.utils import SQL from app.models.file import File from app.models.user import User from app.models.login import Login from app.config import BASE_DIR from pymysql import escape_string from app.log import Logger file = Blueprint("file", __name__) log = Logger("file.log") # [accesstoken] # [format] 文件格式 @file.route('list', methods=['GET', 'POST']) def get_list(): try: pass # 权限鉴定 except Exception as e: log.logger.warning(e) return jsonify({"status": "failed", "data": "错误请求"}) @file.route('download', methods=['GET', 'POST']) def get_file(): try: from .utils import get_obj_auth
from app.template import render from app.log import Logger logger = Logger('main') class TemplateView: template_name = 'template.html' def get_context_data(self): return {} def get_template(self): return self.template_name def render_template_with_context(self): template_name = self.get_template() context = self.get_context_data() logger.log(template_name) return '200 OK', render(template_name, **context) def __call__(self, request): return self.render_template_with_context() class ListView(TemplateView): queryset = [] template_name = 'list.html' context_object_name = 'objects_list' def get_queryset(self):
def hello_world(): # Make it Ra1n Logger.log('Hello, world!', 'INFO', 'This is a test.') return '<code>Notice Me!</code>'
from flask import Blueprint, request, jsonify from app.extensions import db from app.models import people from pymysql import escape_string from app.utils import SQL from app.log import Logger sz = Blueprint('szjs', __name__) log = Logger("sz.log") # 师资团队列表 # 人数多的情况下可以按页查询 @sz.route('list', methods=['GET', 'POST']) def get_list(): try: page = int(request.args.get('page') or "1") psize = int(request.args.get('psize') or "50") pno = (page - 1) * psize s = SQL() # 按职称分别查询 job = ["教授", "副教授", "讲师", "其他"] res = {} for t in job: condition = "where job = '%s'" % t sql = "select `id`,`name`,`header`,`job` from `people` where `job` = '%s';" % t res[t] = s.query(sql) return jsonify({"status": "ok", "data": res}) except Exception as e: log.logger.warning(e) return jsonify({"status": "failed", "data": "error:%s" % e})
from flask import Blueprint, request, jsonify from app.utils import SQL from app.models.news import News from pymysql import escape_string from app.log import Logger news = Blueprint('news', __name__) log = Logger(filename="news.log") # 获取新闻列表 # 新闻类别 # page - 新闻页数 # psize - 每页条数 @news.route('list', methods=['GET', 'POST']) def get_list(): try: page = int(request.args.get('page') or "1") psize = int(request.args.get('psize') or "8") ntype = escape_string(request.args.get("type") or "news") pno = (page - 1) * psize s = SQL() # 补充查询条件 condition = "where 1 = 1 and `status` = 'valid' and `type` = '%s'" % ntype sql = "select `id`,`title`,`pub_date`,`album`,`author`,`type` from " \ "(select * from `news` order by pub_date desc ) tmp %s limit %d , %d" % (condition, pno, psize) return jsonify({"status": "ok", "data": s.query(sql)}) except Exception as e: print(e) log.logger.warning(e) return jsonify({"status": "failed", "data": "error:%s" % e})
import math import pymysql from app.config import ProductionConfig as Pr from app.log import Logger log = Logger("SQL.log") def custom_paginator(current_page, num_page, max_page): middle = math.ceil(max_page / 2) if num_page <= max_page: start = 1 end = num_page elif current_page <= middle: start = 1 end = max_page elif middle < current_page < num_page - middle + 1: start = current_page - middle end = current_page + middle - 1 else: start = num_page - max_page + 1 end = num_page return start, end class SQL: db = None def __init__(self): # 读入配置文件 self.db = pymysql.connect(host=Pr.SQL_HOST, user=Pr.SQL_USER,
from flask import Blueprint, request, jsonify from app.utils import SQL from .utils import check_mani from app.models import notice from pymysql import escape_string from app.log import Logger notice = Blueprint('notice', __name__) log = Logger("notice.log") @notice.route("list", methods=['GET', 'POST']) def get_list(): try: page = int(request.args.get('page') or "1") psize = int(request.args.get('psize') or "8") pno = (page - 1) * psize s = SQL() condition = "where 1 = 1" sql = "select `id`,`pub_date`,`tag`,`title`,`type` from (select * from `notice` order by pub_date desc ) " \ "tmp %s limit %d , %d " % (condition, pno, psize) return jsonify({"status": "ok", "data": s.query(sql)}) except Exception as e: log.logger.warning(e) return jsonify({"status": "failed", "data": "error:%s" % e}) # 公告详情 # id @notice.route("detail", methods=['GET', 'POST']) def get_detail(): try:
def webhook(): # Verification Test if request.method == 'GET': if request.args.get('hub.verify_token') == g_config['FACEBOOK']['VERIFY_TOKEN']: return request.args.get('hub.challenge') else: return 'Verification Failed!' # Messenger Callback if request.method == 'POST': try: req = request.get_json() for event in req['entry']: for e in event['messaging']: # 메시지 시작 # 에코 메시지라면 스킵 if e.get('message', {}).get('is_echo'): continue # 1. 디비에서 사용자 정보 가져오기 try: usr = db.get_user(e['sender']['id'], g_config) except Exception as err: Logger.log(f'[APP] db.get_user 오류', 'ERROR', str(err)) from app.facebook import FacebookMessenger from app.template import Templates fm = FacebookMessenger(g_config) fm.send(e['sender']['id'], '데이터베이스 오류가 발생했습니다. 잠시 후 다시 이용해주세요.', Templates.QuickReplies.after_system_error) continue # 1.1. 신규 유저 if not usr: usr = User({'new_user': True, 'uid': e['sender']['id']}, g_config) Logger.log(f'[APP] 신규 유저: {usr.uid}', 'INFO') # 2. 포스트백 처리 if e.get('postback', {}).get('payload'): usr = ps.process_postback(usr, e['postback']['payload'], g_config) try: db.save_user(usr) Logger.log(f'[APP] 포스트백 처리후 유저 {usr.uid} 세이브 완료.', 'INFO') except Exception as err: Logger.log(f'[APP] 포스트백 처리후 유저 {usr.uid} 세이브중 오류 발생!', 'ERROR', str(err)) from app.facebook import FacebookMessenger from app.template import Templates fm = FacebookMessenger(g_config) fm.send(e['sender']['id'], '데이터베이스 오류가 발생했습니다. 잠시 후 다시 이용해주세요.', Templates.QuickReplies.after_system_error) continue # 3. 메시지 처리 elif e.get('message'): # 3.1. 빠른 답장 포스트백 처리 if e['message'].get('quick_reply', {}).get('payload'): usr = ps.process_postback(usr, e['message']['quick_reply']['payload'], g_config) try: db.save_user(usr) Logger.log(f'[APP] 빠른 답장 처리후 유저 {usr.uid} 세이브 완료.', 'INFO') except Exception as err: Logger.log(f'[APP] 빠른 답장 처리후 유저 {usr.uid} 세이브중 오류 발생!', 'ERROR', str(err)) from app.facebook import FacebookMessenger from app.template import Templates fm = FacebookMessenger(g_config) fm.send(e['sender']['id'], '데이터베이스 오류가 발생했습니다. 잠시 후 다시 이용해주세요.', Templates.QuickReplies.after_system_error) continue # 3.2. 텍스트 메시지 처리 if e['message'].get('text'): usr = ps.process_message(usr, e['message']['text'], g_config) try: db.save_user(usr) Logger.log(f'[APP] 메시지 처리후 유저 {usr.uid} 세이브 완료.', 'INFO') # 최적화: 전날 급식 캐시 제거 except Exception as err: Logger.log(f'[APP] 메시지 처리후 유저 {usr.uid} 세이브중 오류 발생!', 'ERROR', str(err)) from app.facebook import FacebookMessenger from app.template import Templates fm = FacebookMessenger(g_config) fm.send(e['sender']['id'], '데이터베이스 오류가 발생했습니다. 잠시 후 다시 이용해주세요.', Templates.QuickReplies.after_system_error) continue # 1-2-3. 첨부파일 등이 있는 메시지 if e['message'].get('attachments'): ps.process_postback(usr, 'ATTACHMENTS', g_config) continue try: db.save_user(usr) Logger.log(f'[APP] 처리 없이 유저 {usr.uid} 세이브 완료.', 'INFO') except Exception as err: Logger.log(f'[APP] 처리 없이 유저 {usr.uid} 세이브중 오류 발생!', 'ERROR', str(err)) from app.facebook import FacebookMessenger from app.template import Templates fm = FacebookMessenger(g_config) fm.send(e['sender']['id'], '데이터베이스 오류가 발생했습니다. 잠시 후 다시 이용해주세요.', Templates.QuickReplies.after_system_error) return {'result': 'success'} except Exception as err: traceback.print_exc() Logger.log(f'[APP] 알 수 없는 치명적 오류 발생!', 'ERROR', str(err)) try: from app.facebook import FacebookMessenger from app.template import Templates fm = FacebookMessenger(g_config) fm.send(e['sender']['id'], f'죄송합니다, 급식봇에 처리되지 않은 오류가 발생했습니다.\n' f'다시 시도해 주시고, 계속 오류가 발생할 경우 아래 \'버그 신고하기\' ' f'기능을 통해서 신고해 주세요.{str(err)}', Templates.QuickReplies.after_system_error) except: pass return {'result': 'error'} # 오류시에도 200 리턴
def process_postback(user, payload, g_config): # 1. 오브젝트 만들기 from app.facebook import FacebookMessenger fm = FacebookMessenger(g_config) fm.typing(user.uid) from app.log import Logger Logger.log('[PS > process_postback] 요청: {0}->\'{1}\''.format( user.uid, payload)) # 2. 페이로드 분기 if payload == 'FACEBOOK_WELCOME': fm.send(user.uid, '안녕하세요, {0}님! 만나서 반가워요🤗'.format(user.name)) fm.send(user.uid, '저는 급식봇이라고 해요.') fm.send( user.uid, '제 안에 있는 인공지능 덕분에 저는 다양한 말을 알아들을 수 있어요😎\n' '이제 제가 할 수 있는 일을 알아볼까요?', Templates.QuickReplies.intro) return user elif payload == 'INTRO_MORE': card = Elements.Card(Templates.Cards.intro_features) fm.send(user.uid, card) return user # 사용법 elif payload == 'HELP': # 1/3 (Text) msg_str = '다양한 방법으로 급식을 가져올 수 있어요!\n' \ '예시:\n' \ '> 급식고등학교 내일 저녁\n' \ '> 3월 14일 급식고등학교 급식\n' \ '> 급식고등학교\n' \ '> 내일은?\n' \ '기본값은 오늘 날짜의 중식이에요.' fm.send(user.uid, msg_str) # 2/3 (Text) msg_str = '학교 이름을 생략한 경우, 바로 전에 요청하셨던 학교의 급식을 자동으로 가져올 거에요.\n' \ '예시:\n' \ '12:00 > 오늘 다솜중 급식이 뭐야?\n' \ '12:01 > 내일은?\n' \ '그렇기 때문에, 위의 경우에는 다솜중학교의 \'내일\' 급식을 가져옵니다.' fm.send(user.uid, msg_str) # 3/3 (Text) fm.send(user.uid, '혹시라도 잘 이해가 가지 않으시면 그냥 학교 이름을 입력해 보세요.') return user # 급식 급식 급식! elif payload.startswith('M_'): # user.use_count 를 올린다. user.use_count = user.use_count + 1 # 파라미터 값을 추출한다. [_, school_code, tmp_date, mealtime] = payload.split('_') user.last_school_code = school_code date = datetime.datetime.strptime(tmp_date, '%Y-%m-%d') # 급식 가져오기 from app.neis import NEIS neis = NEIS(g_config) try: sch = neis.school_from_code(school_code) except ValueError as e: fm.send(user.uid, '나이스 조회중 오류가 발생했습니다: 중복 조회되었습니다.', Templates.QuickReplies.after_system_error) Logger.log('[PS > process_postback] 나이스 재조회중 학교 중복 오류!', 'ERROR', str(e)) return user except Exception as e: fm.send(user.uid, '나이스 조회중 오류가 발생했습니다: 알 수 없는 오류.', Templates.QuickReplies.after_system_error) Logger.log('[PS > process_postback] 나이스 재조회중 기타 오류!', 'ERROR', str(e)) return user db_meal = db.search_meal(school_code, tmp_date, mealtime) if db_meal: # 디비에서 저장된 급식을 가져왔을 때 meal = db_meal['meal'] meal_id = db_meal['meal_id'] nutrition = db_meal['nutrition'] else: # 디비에 없을때 meal_id = '#{0}{1}'.format(user.uid, user.use_count) try: meal, nutrition = sch.get_meal(date, int(mealtime)) except TypeError: # 급식이 없음 meal = [] nutrition = None except Exception as e: Logger.log('[PS > process_postback] 급식 조회 중 오류!', 'ERROR', str(e)) fm.send(user.uid, '급식 조회중 오류가 발생했습니다: 처리되지 않은 오류.', Templates.QuickReplies.after_system_error) return user if int(mealtime) == 1: mt_text = '아침' elif int(mealtime) == 3: mt_text = '저녁' else: mt_text = '점심' # 잘 포장해서 보낸다 if len(meal) != 0: # 급식이 존재할 때 meal_text = '' for menu in meal: meal_text = meal_text + menu + '\n' meal_text = meal_text.rstrip() # 랜덤으로 보내기 from random import randint rand_num = randint(0, 11) if rand_num == 0: fm.send(user.uid, '급식봇을 {0}번째로 사용하고 계시네요!'.format(user.use_count)) else: msg_str = [ '', # 0 '이 냄새는 바로!', '반찬 남기지 마세요', '골고루 드세요', '헤헷', '어디서 주웠어요.', '오다가 잊어버릴 뻔했어요', '훗', '오다가 주웠어요', '히힛', '맛나게 드십쇼', '맛있게 드세요' ] fm.send(user.uid, msg_str[rand_num]) quick_replies = Templates.QuickReplies.after_meal quick_replies[0]['payload'] = 'N_{0}'.format(meal_id) # 급식을 보낸다 fm.send( user.uid, '{0} {1}/{2}\n급식 #{3}:\n{4}'.format( tmp_date, sch.name, mt_text, meal_id[-6:], meal_text), quick_replies) if not db_meal: # FS에 급식을 세이브한다. me = { 'meal_id': meal_id, 'meal': meal, 'school_code': school_code, 'school_name': sch.name, 'date': tmp_date, 'mealtime': int(mealtime), 'nutrition': nutrition } db.save_meal(user, me) return user else: # 밥없음 fm.send( user.uid, '%d년 %d월 %d일 %s의 %s 메뉴가 없어요.\n(또는 나이스에 등록이 안된 것일수도 있어요.)' % (int(date.year), int(date.month), int( date.day), sch.name, mt_text), Templates.QuickReplies.after_nutrition) return user # 영양소 정보 보기 elif payload.startswith('N_'): # 파라미터 값을 추출한다. _, meal_code = payload.split('_') # 급식 NO. 를 이용해서 급식을 가져온다. db_meal = db.get_meal(meal_code) if db_meal: # 디비에서 저장된 급식을 가져왔을 때 nutrition = db_meal['nutrition'] # str date = db_meal['date'] school_name = db_meal['school_name'] mealtime_hangul = ['아침', '점심', '저녁'][int(db_meal['mealtime']) - 1] fm.send( user.uid, '{0} {1}의 {2} 메뉴: 영양소 정보:\n{3}'.format( date, school_name, mealtime_hangul, nutrition), Templates.QuickReplies.after_nutrition) return user else: # 디비에 없을때 fm.send(user.uid, '죄송합니다, DB에서 급식의 영양소 정보를 찾을 수 없었어요.', Templates.QuickReplies.after_system_error) return user elif payload == 'BUGREPORT': fm.send(user.uid, '아래 버튼을 눌러서 신고해주세요.') tmp_c = Templates.Cards.bug_report tmp_c[0]['buttons'][0]['url'] += user.uid card = Elements.Card(tmp_c) fm.send(user.uid, card, Templates.QuickReplies.after_action) return user elif payload == 'ATTACHMENTS': fm.send(user.uid, ':)', Templates.QuickReplies.after_action) return user return user
from flask import Blueprint, request, jsonify from app.extensions import db from app.models import user, login from app.log import Logger from app.utils import SQL from pymysql import escape_string users = Blueprint('users', __name__) log = Logger("user.log") @users.route('/query', methods=['GET', 'POST']) def index(): try: s = SQL() sql = "select * from `user`" return jsonify({"status": "ok", "data": s.query(sql)}) except Exception as e: log.logger.warning(e) return jsonify({"status": "failed", "data": "error:%s" % e}) # 注册、添加用户 # 账号 # 密码 # 验证码 @users.route('/add', methods=['GET', 'POST']) def add_user(): try: pass except Exception as e: