def reset(message): try: if message.from_user.id == admin_tel_id: bot.send_message(message.from_user.id, emoji.emojize(':right_arrow: Enter your message: '), reply_markup=Finish_Discard_keyboard) cur.execute('''UPDATE Users SET state = (%s) WHERE tel_id = (%s)''', ('SEND MSG TO ALL USERS', message.from_user.id, )) except Exception as e: print('Something went wrong in /sendmsg: ', e)
def send_accepted_answer(question_id): answer = cur.execute( '''SELECT answer FROM Answers WHERE question_id = (%s) AND accepted_answer = 1 ORDER BY rate_answer LIMIT 1''', (question_id, )).fetchone() keyboard = telebot.types.InlineKeyboardMarkup() if answer is not None: answer, tel_id, photo, document, document_type, document_size = cur.execute( '''SELECT answer, tel_id, photo, document, document_type, document_size FROM Answers WHERE question_id = (%s) AND accepted_answer = 1 ORDER BY rate_answer LIMIT 1''', (question_id, )).fetchone() if (limit_text(answer)): answer = limit_text(answer) keyboard.add(showmore) if photo is not None: keyboard.add(photo_button) if document is not None: document_button = telebot.types.InlineKeyboardButton( emoji.emojize(':paperclip: {0} ({1})'.format( document_type, document_size)), callback_data='document') keyboard.add(document_button) answer = emoji.emojize(':white_heavy_check_mark: #A_') + str( question_id) + ' #' + str(tel_id) + '\n\n' + answer return (answer, keyboard)
def reset(message): try: st_num = cur.execute('''SELECT st_num FROM Users WHERE tel_id = (%s)''', (message.from_user.id,)).fetchone() if st_num is not None: bot.send_message(message.from_user.id, emoji.emojize(":white_heavy_check_mark: Everything is updated now."), reply_markup=main_reply_keyboard) cur.execute('''UPDATE Users SET state = 'IDLE', cont_typing = NULL WHERE tel_id = (%s)''', (message.from_user.id,)) except Exception as e: print('Something went wrong in /update: ', e)
def contact(message): try: st_num = cur.execute('''SELECT st_num FROM Users WHERE tel_id = (%s)''', (message.from_user.id,)).fetchone() if st_num is not None: bot.send_message(message.from_user.id, emoji.emojize(":envelope: Contact Info:\n\n" ":bust_in_silhouette: Ali Hejazi:\n :white_small_square: @Ali_H93\n :black_small_square: [email protected]\n" ":bust_in_silhouette: Nima Sedghiye\n :white_small_square: @Nima_sedghiye\n :black_small_square: [email protected]\n" ":bust_in_silhouette: Hamed Hosseini\n :white_small_square: @HMDHosseini\n :black_small_square: [email protected]"), reply_markup=next_page_contact) except Exception as e: print('Something went wrong in /contact: ', e)
def attachment(message): state = cur.execute('''SELECT state FROM Users WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone() if state is not None: # STATE[0] is the state retrieved (state is a tuple if state[0] in ['Send Question', 'Send Answer']: # PHOTO if message.content_type == 'photo': check_photo = \ cur.execute('''SELECT photo FROM Users WHERE tel_id = (%s)''', (message.from_user.id,)).fetchone()[0] # ONLY 1 image is allowed if check_photo is None: # FIRST image bot.reply_to( message, emoji.emojize(':framed_picture: Image Attached.')) else: # UPDATING image bot.reply_to( message, emoji.emojize( ':framed_picture: Image Attachment updated.')) cur.execute( '''UPDATE Users SET photo = (%s) WHERE tel_id = (%s)''', (message.photo[-1].file_id, message.from_user.id)) # DOCUMENT elif message.content_type == 'document': check_document = cur.execute( '''SELECT document FROM Users WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone()[0] # ONLY 1 document is allowed if check_document is None: # FIRST document bot.reply_to( message, emoji.emojize(':paperclip: Document Attached.')) else: # UPDATING document bot.reply_to( message, emoji.emojize( ':paperclip: Document Attachment updated.')) # FORMATING FILE SIZE FILE_SIZE = message.document.file_size / 1000.0 if FILE_SIZE < 1000: FILE_SIZE = '{0} KB'.format(round(FILE_SIZE)) else: FILE_SIZE = '{0:.1f} MB'.format(FILE_SIZE / 1000.0) cur.execute( '''UPDATE Users SET document = (%s), document_type = (%s), document_size = (%s) WHERE tel_id = (%s)''', (message.document.file_id, message.document.mime_type, FILE_SIZE, message.from_user.id))
9523017, 9523018, 9523021, 9523053 ] admins_list = [9023026, 8123020] tas_list = [] ####################################### ## TEST # stnums_list = [90230262] # admins_list = [9023026] cur.execute('''DELETE FROM Users_temp''') ####################################### for stnum in stnums_list: if cur.execute('''SELECT st_num FROM Users WHERE st_num = (%s)''', (stnum, )).fetchone() is None: cur.execute('''INSERT INTO Users (st_num, role) VALUES (%s, %s)''', (stnum, 'STUDENT')) print('New User: {}'.format(stnum)) else: print('User already in DB {}'.format(stnum)) for admin_stnum in admins_list: if cur.execute('''SELECT st_num FROM Users WHERE st_num = (%s)''', (admin_stnum, )).fetchone() is None:
def send_question(question_id, receiver_tel_id, short): id, question_owner, question, question_state, photo, document, document_type, document_size = \ cur.execute('''SELECT id, tel_id, question, status, photo, document, document_type, document_size FROM Questions WHERE id = (%s)''', (question_id, )).fetchone() # limiting long questions and specifying keyboard keyboard = telebot.types.InlineKeyboardMarkup(row_width=6) load_answers = telebot.types.InlineKeyboardButton( emoji.emojize(':bright_button: Load Answers'), callback_data='load_answers') comment = telebot.types.InlineKeyboardButton( emoji.emojize(':memo: Comment'), callback_data='comment_question') # like question button is disabled now # liked_number = cur.execute('''SELECT count(*) from Like_Question WHERE question_id = (%s)''', (question_id, )).fetchone()[0] # if liked_number == 0: # like_button = telebot.types.InlineKeyboardButton(emoji.emojize(':red_heart:'), callback_data='like_question') # else: # like_button = telebot.types.InlineKeyboardButton(emoji.emojize('{0} :red_heart:'.format(liked_number)), callback_data='like_question') # GETTING ADMINS AND TAs # Receiver_tel_id which is different from send_answer.py -> answer_owner is used there role = cur.execute('''SELECT role FROM Users WHERE tel_id = (%s)''', (receiver_tel_id, )).fetchone()[0] # LONG QUESTIONS if (limit_text(question)): ## Sending with SHOWMORE or SHOWLESS if short: question = limit_text(question) showkey = showmore else: showkey = showless ## Setting keyboard for REGULAR Users (NOT owner or admin) if receiver_tel_id != question_owner: ### Setting keyboard for OPEN and CLOSED questions ## QUESTIONS are always open for ADMINs and TAs if (question_state == 'OPEN') or (role in ['ADMIN', 'TA']): if role == 'ADMIN': ### ADMINs can load answers for every question any time # like is now disabled # keyboard.add(showkey, answer_question, like_button, load_answers, next_page_question) keyboard.add(showkey, answer_question, load_answers, next_page_question) else: # like is now disabled # keyboard.add(showkey, answer_question, like_button, next_page_question) keyboard.add(showkey, answer_question, next_page_question) else: keyboard.add(showkey) ## Setting keyboard for OWNER, only SHOWMORE and LOAD ANSWERS elif receiver_tel_id == question_owner: check_answers = cur.execute( '''SELECT answer FROM Answers, Users WHERE question_id = (%s) AND Users.tel_id = Answers.tel_id AND Users.role != (%s)''', (question_id, 'ADMIN')).fetchone() if check_answers is not None: if role in ['ADMIN']: keyboard.add(showkey, answer_question, load_answers) else: keyboard.add(showkey, load_answers) else: if role in ['ADMIN']: keyboard.add(showkey, answer_question) else: keyboard.add(showkey) # SHORT QUESTIONS else: ## Setting Keyboard for NOT OWNER and OPEN Questions if receiver_tel_id != question_owner: ## Even if the QUESTION is CLOSED, it is always open for ADMINs and TAs if (question_state == 'OPEN') or (role in ['ADMIN', 'TA']): if role == 'ADMIN': ### ADMINs can load answers for every question any time # like is disabled now # keyboard.add(answer_question, like_button, load_answers, next_page_question) keyboard.add(answer_question, load_answers, next_page_question) else: # like is disabled now # keyboard.add(answer_question, like_button, next_page_question) keyboard.add(answer_question, next_page_question) ## Setting keyboard for OWNER, only SHOWMORE and LOAD ANSWERS elif receiver_tel_id == question_owner: # LOAD ANSWERS for owner check_answers = cur.execute( '''SELECT answer FROM Answers, Users WHERE question_id = (%s) AND Users.tel_id = Answers.tel_id AND Users.role != (%s)''', (question_id, 'ADMIN')).fetchone() if check_answers is not None: if role in ['ADMIN']: keyboard.add(answer_question, load_answers) else: keyboard.add(load_answers) # Setting keyboard for ATTACHMENTs if photo is not None: keyboard.add(photo_button) if document is not None: document_button = telebot.types.InlineKeyboardButton( emoji.emojize(':paperclip: {0} ({1})'.format( document_type, document_size)), callback_data='document') keyboard.add(document_button) # FORMATTING QUESTION question = emoji.emojize(':question_mark: #Q_') + str( question_id) + '\n\n' + question accepted_answers_count = cur.execute( '''SELECT SUM(accepted_answer) FROM Answers WHERE question_id = (%s)''', (question_id, )).fetchone()[0] print(accepted_answers_count) if (question_state == 'CLOSED') and (accepted_answers_count == 0): question += emoji.emojize('\n\n:cross_mark: Question is Closed') question_owner_role = cur.execute( '''SELECT role FROM Users WHERE tel_id = (%s)''', (question_owner, )).fetchone()[0] if question_owner_role in ['ADMIN', 'TA']: question += emoji.emojize( '\n\n:bust_in_silhouette: Sent by {0}'.format(question_owner_role)) return (question, keyboard)
def send_answer(question_id, answer_owner, receiver_tel_id, short): answer = cur.execute( '''SELECT answer FROM Answers WHERE question_id = (%s) AND tel_id = (%s)''', (question_id, answer_owner)).fetchone() keyboard = telebot.types.InlineKeyboardMarkup() if answer is not None: id, question_id, tel_id, answer, accepted_answer, rate_answer, photo, document, document_type, document_size, send_date = cur.execute( '''SELECT * FROM Answers WHERE question_id = (%s) AND tel_id = (%s)''', (question_id, answer_owner)).fetchone() question_owner = \ cur.execute('''SELECT tel_id FROM Questions WHERE id = (%s)''', (question_id, )).fetchone()[0] # Limiting Long Questions and specifying keyboard accordingly # GETTING ADMINS AND TAs role = cur.execute('''SELECT role FROM Users WHERE tel_id = (%s)''', (answer_owner, )).fetchone()[0] # This flag is used at the bottom for Admin and TAs keyboard setting short_message_flag = False # Setting keyboard if limit_text(answer): short_message_flag = True # SHOWMORE key if short: answer = limit_text(answer) showkey = showmore else: showkey = showless if receiver_tel_id == question_owner: if accepted_answer: keyboard.add(showkey) else: keyboard.add(showkey, accept_answer, next_page_answer) else: # FOLLOWERs and Answer Owner only get a show more key keyboard.add(showkey) else: if receiver_tel_id == question_owner: if not accepted_answer: if question_owner == receiver_tel_id: keyboard.add(accept_answer, next_page_answer) # ATTACHMENTs if photo is not None: keyboard.add(photo_button) if document is not None: document_button = telebot.types.InlineKeyboardButton( emoji.emojize(':paperclip: {0} ({1})'.format( document_type, document_size)), callback_data='document') keyboard.add(document_button) # SETTING EMOJI BASED ON ACCEPTED OR NOT ACCEPTED ANSWER if role in ['STUDENT', 'TA']: if accepted_answer: answer = emoji.emojize(':white_heavy_check_mark: #A_') + str(question_id) + ' #' + \ str(answer_owner) + '\n\n' + answer + emoji.emojize('\n\n:high_voltage: Rated: {0}/5'.format(rate_answer)) else: answer = emoji.emojize(':bright_button: #A_') + str( question_id) + ' #' + str(answer_owner) + '\n\n' + answer if role == 'TA': answer += emoji.emojize( '\n\n:bust_in_silhouette: Sent by ') + role ## ADMINs AND TAs answers are indicated with a flag elif role in ['ADMIN']: question_state = cur.execute( '''SELECT status FROM Questions WHERE id = (%s)''', (question_id, )).fetchone()[0] # ADMIN Answers are different keyboard = telebot.types.InlineKeyboardMarkup() if short_message_flag: # SHOWMORE key if short: showkey = showmore else: showkey = showless keyboard.add(showkey) else: keyboard = None # ATTACHMENTs if photo is not None: keyboard.add(photo_button) if document is not None: document_button = telebot.types.InlineKeyboardButton( emoji.emojize(':paperclip: {0} ({1})'.format( document_type, document_size)), callback_data='document') keyboard.add(document_button) answer = emoji.emojize(':collision: #A_') + str(question_id) + ' #' + str(answer_owner) + '\n\n' \ + answer + emoji.emojize('\n\n:bust_in_silhouette: Sent by ') + role # Returning Answer and Two Keyboards return (answer, keyboard)
def callback_inline(call): message = call.message # RE patters for QUESTIONS, ANSWERS, and ACCEPTED ANSWERS question_pattern = ":question_mark: #Q_(\d+).*" answer_pattern = "(?::bright_button:|:white_heavy_check_mark:|:collision:) #A_(\d+) #(\d+).*" accepted_answer_pattern = ":white_heavy_check_mark: #(\d+).*" # GETTING RESULTS of patterns question_res = re.match(question_pattern, emoji.demojize(message.text), flags=re.DOTALL) answer_res = re.match(answer_pattern, emoji.demojize(message.text), flags=re.DOTALL) accepted_answer_res = re.match(accepted_answer_pattern, emoji.demojize(message.text), flags=re.DOTALL) question_id = None if question_res is not None: ############################## ### Questions ### ############################## question_id = question_res.groups()[0] forwarded_user = cur.execute( '''SELECT tel_id FROM Questions WHERE id = (%s)''', (question_id, )).fetchone()[0] cur.execute( '''UPDATE Users SET forwarded_user = (%s), forwarded_question = (%s) WHERE tel_id = (%s)''', (forwarded_user, question_id, message.from_user.id)) elif answer_res is not None: ############################## ### Answers ### ############################## question_id = answer_res.groups()[0] forwarded_user = answer_res.groups()[1] cur.execute( '''UPDATE Users SET forwarded_user = (%s), forwarded_question = (%s) WHERE tel_id = (%s)''', (forwarded_user, question_id, message.from_user.id)) ################################################# ## IF A VALID RESULT FOUND BY REGULAR EXPRESSION if question_id is not None: forwarded_question = question_id cur.execute( '''UPDATE Users SET forwarded_user = (%s), forwarded_question = (%s) WHERE tel_id = (%s)''', (forwarded_user, forwarded_question, call.from_user.id)) ################################################# ################################################# ### CALLBACKS ### ################################################# # Handling callback queries if call.message: forwarded_question, forwarded_user = cur.execute( '''SELECT forwarded_question, forwarded_user FROM Users WHERE tel_id = (%s)''', (call.from_user.id, )).fetchone() ############################## ######### USER ########### ############################## if call.data == 'load_answers': bot.answer_callback_query(callback_query_id=call.id, text="Loading Received Answers...") answers_list = cur.execute( '''SELECT Answers.tel_id FROM Answers, Users WHERE question_id = (%s) AND Answers.tel_id = Users.tel_id AND Users.role != (%s)''', (question_id, 'ADMIN')).fetchall() if len(answers_list) > 0: bot.send_message( call.from_user.id, emoji.emojize( ':red_triangle_pointed_down: Loading *Question {0}* Answers...' .format(question_id)), parse_mode='Markdown') for answer in answers_list: answer, keyboard = send_answer(question_id, answer[0], call.from_user.id, short=True) # bot.send_message(call.from_user.id, answer, reply_markup=showkeyboard_keyboard) bot.send_message(call.from_user.id, answer, reply_markup=keyboard) elif call.data == 'show_keyboard': bot.answer_callback_query(callback_query_id=call.id, text="Loading Full Keyboard...") keyboard = send_answer(question_id, forwarded_user, call.from_user.id, short=True)[1] bot.edit_message_reply_markup(call.from_user.id, call.message.message_id, reply_markup=keyboard) elif call.data == "getfile": bot.answer_callback_query(callback_query_id=call.id, text="Sending File...") user = call.from_user.first_name if call.from_user.last_name is not None: user = call.from_user.first_name + ' ' + call.from_user.last_name if call.from_user.username is not None: user = user + ' @' + call.from_user.username ### GET FILE is used for both My Questions and All Questions # My Questions if emoji.demojize(message.text).startswith(':bust_in_silhouette:'): questions = cur.execute( '''SELECT id, tel_id, question, status FROM questions WHERE tel_id = (%s) ORDER BY id DESC''', (call.from_user.id, )).fetchall() FILE_NAME = str( call.from_user.id) + '/Questions of ' + user + '.txt' # All Questions elif emoji.demojize(message.text).startswith(':page_facing_up:'): questions = cur.execute( '''SELECT id, tel_id, question, status FROM questions ORDER BY id DESC''' ).fetchall() FILE_NAME = str( call.from_user.id) + '/All Questions - ' + user + '.txt' # Making a directory for each user if not os.path.exists(str(call.from_user.id)): os.mkdir(str(call.from_user.id)) # Some settings for styling the output q_sep = '=' * 50 a_sep = '-' * 46 # Output .txt file with open(FILE_NAME, 'w') as f: f.write('Requested by: ' + user + '\n\n\n') if len(questions) > 0: for question in questions: question_owner = question[1] question_id = question[0] question_text = question[2] question_status = question[3] # like_button is disabled now # like_number = cur.execute('''SELECT count(*) FROM Like_Question WHERE question_id = (%s)''', (question[0],)).fetchone()[0] # if question_owner == call.from_user.id: # if like_number > 0: # formatted_question = '#'+ str(question_id) + ' ' + str(question_status) + ' - Sent by: You - ' + 'Likes: {0}\n'.format(like_number) + q_sep + '\n' + question_text + '\n\n' # else: # formatted_question = '#'+ str(question_id) + ' ' + str(question_status) + ' - Sent by: You\n' + q_sep + '\n' + question_text + '\n\n' # # else: # formatted_question = '#'+ str(question_id) + ' ' + str(question_status) + '\n' + q_sep + '\n' + question_text + '\n\n' if question_owner == call.from_user.id: formatted_question = '#' + str( question_id ) + ' ' + str( question_status ) + ' - Sent by: You\n' + q_sep + '\n' + question_text + '\n\n' else: formatted_question = '#' + str( question_id ) + ' ' + str( question_status ) + '\n' + q_sep + '\n' + question_text + '\n\n' f.write(q_sep + '\n' + formatted_question) ### ANSWERs OF each QUESTION # This sorts the answer by role (Admins first, then students, then TAs [alphabetical] and then # based on accepted or not accepted) user_answers = cur.execute( '''SELECT Answers.tel_id, answer, accepted_answer, rate_answer, role FROM Answers, Users WHERE question_id = (%s) AND Answers.tel_id = Users.tel_id ORDER BY role DESC, accepted_answer DESC''', (question[0], )).fetchall() if len(user_answers) > 0: answer_section = a_sep + '\n' + '-' * 13 + ' Answers ' + '-' * 13 answer_section = '\t'.join( ('\n' + answer_section.lstrip()).splitlines(True)) f.write(answer_section) for answer in user_answers: answer_owner = answer[0] answer_text = answer[1] accepted_answer = answer[2] rate = answer[3] role = answer[4] if accepted_answer: status = 'Accepted - Rated ' + str( answer[3]) + '/5'.format(answer[3]) else: status = 'Not Accepted' question_owner_role = \ cur.execute('''SELECT role FROM Users WHERE tel_id = (%s)''', (question_owner,)).fetchone()[0] ## If a Question is sent by ADMIN only accepted answers will be shown if (question_owner_role in vip) and not accepted_answer: continue if role == 'ADMIN': if answer_owner == call.from_user.id: answer = a_sep + '\nSent by: You (ADMIN)' + '\n' + a_sep + '\n' + answer_text else: answer = a_sep + '\nSent by: ADMIN (#' + str( answer_owner ) + ')' + '\n' + a_sep + '\n' + answer_text answer = '\t'.join( ('\n' + answer.lstrip()).splitlines(True)) else: if answer_owner == call.from_user.id: answer = a_sep + '\nSent by: You - ' + status + '\n' + a_sep + '\n' + answer_text else: answer = a_sep + '\nSent by: #' + str( answer_owner ) + ' - ' + status + '\n' + a_sep + '\n' + answer_text answer = '\t'.join( ('\n' + answer.lstrip()).splitlines(True)) f.write(answer + '\n\n') f.write('\n') f.write(q_sep + '\n' + q_sep + '\n' + 'END OF FILE') bot.edit_message_reply_markup(call.from_user.id, call.message.message_id, reply_markup=None) bot.send_document(call.from_user.id, open(FILE_NAME, "r")) # SHOW MORE KEY elif call.data == 'show_more': bot.answer_callback_query(callback_query_id=call.id, text="Show More...") # SHOW MORE for a QUESTION if question_res is not None: question, keyboard = send_question(forwarded_question, call.from_user.id, short=False) bot.edit_message_text(question, call.from_user.id, call.message.message_id, reply_markup=keyboard) # SHOW MORE for an ANSWER elif answer_res is not None: answer, keyboard = send_answer(forwarded_question, forwarded_user, call.from_user.id, short=False) bot.edit_message_text(answer, call.from_user.id, call.message.message_id, reply_markup=keyboard) # SHOW LESS KEY elif call.data == 'show_less': bot.answer_callback_query(callback_query_id=call.id, text="Show Less...") if question_res is not None: question, keyboard = send_question(forwarded_question, call.from_user.id, short=True) bot.edit_message_text(question, call.from_user.id, call.message.message_id, reply_markup=keyboard) elif answer_res is not None: answer, keyboard = send_answer(forwarded_question, forwarded_user, call.from_user.id, short=True) bot.edit_message_text(answer, call.from_user.id, call.message.message_id, reply_markup=keyboard) # COMMENT elif call.data == 'comment_question': role = cur.execute( '''SELECT role FROM Users WHERE tel_id = (%s)''', (call.from_user.id, )).fetchone()[0] question_state = cur.execute( '''SELECT status FROM Questions WHERE id = (%s)''', (forwarded_question, )).fetchone()[0] if (question_state == 'OPEN'): # or (role in ['ADMIN', 'TA']): bot.answer_callback_query(callback_query_id=call.id, text="Send Comment!") cur.execute( '''UPDATE Users SET state = (%s) WHERE tel_id = (%s)''', ('Send Comment', call.from_user.id)) bot.reply_to( call.message, emoji.emojize( ':right_arrow: Send your Comment for: *Question ' + str(forwarded_question) + '*'), reply_markup=Finish_Discard_keyboard, parse_mode='Markdown') else: # QUESTION IS CLOSED OR REPORTED bot.answer_callback_query( callback_query_id=call.id, text="Question is {0}!".format(question_state), show_alert=True) elif call.data == 'like_question': check_like = cur.execute( '''SELECT question_id FROM Like_Question WHERE question_id = (%s) AND liked_by = (%s)''', ( question_id, call.from_user.id, )).fetchone() if check_like is None: cur.execute( '''INSERT INTO Like_Question (question_id, liked_by) VALUES (%s, %s)''', (question_id, call.from_user.id)) like_number = cur.execute( '''SELECT count(*) FROM Like_Question WHERE question_id = (%s)''', (question_id, )).fetchone()[0] if like_number % 5 == 0: question_owner = cur.execute( '''SELECT tel_id FROM Questions WHERE id = (%s)''', (question_id, )).fetchone()[0] bot.send_message( question_owner, emoji.emojize( ':red_heart: Good Job! Your Question (#Q_{0}) liked by {1} people!\n' ':right_arrow: Keep sending smart questions.'. format(question_id, like_number))) bot.answer_callback_query( callback_query_id=call.id, text=emoji.emojize( ":red_heart: You liked Question {0}".format(question_id))) try: keyboard = send_question(question_id, call.from_user.id, short=True)[1] bot.edit_message_reply_markup(call.from_user.id, call.message.message_id, reply_markup=keyboard) except: pass # LOADING ATTACHMENTS ## LOADING PHOTO elif call.data == 'photo': bot.answer_callback_query(callback_query_id=call.id, text="Loading Photo...") if question_res is not None: photo_id = cur.execute( '''SELECT photo FROM Questions WHERE id = (%s)''', (forwarded_question, )).fetchone()[0] bot.send_photo( call.from_user.id, photo_id, emoji.emojize( ':framed_picture: #Q_{0}'.format(forwarded_question)), call.message.message_id) elif answer_res is not None: photo_id = cur.execute( '''SELECT photo FROM Answers WHERE question_id = (%s) AND tel_id = (%s)''', (forwarded_question, forwarded_user)).fetchone()[0] bot.send_photo( call.from_user.id, photo_id, emoji.emojize(':framed_picture: #A_{0} #{1}'.format( forwarded_question, forwarded_user)), call.message.message_id) ## LOADING DOCUMENT elif call.data == 'document': bot.answer_callback_query(callback_query_id=call.id, text="Loading Document...") if question_res is not None: document_id = cur.execute( '''SELECT document FROM Questions WHERE id = (%s)''', (forwarded_question, )).fetchone()[0] bot.send_document( call.from_user.id, document_id, call.message.message_id, caption=emoji.emojize( ':paperclip: #Q_{0}'.format(forwarded_question))) elif answer_res is not None: document_id = cur.execute( '''SELECT document FROM Answers WHERE question_id = (%s) AND tel_id = (%s)''', (forwarded_question, forwarded_user)).fetchone()[0] bot.send_document(call.from_user.id, document_id, call.message.message_id, caption=emoji.emojize( ':paperclip: #A_{0} #{1}'.format( forwarded_question, forwarded_user))) # REPORTING A USER ###### COMPLETE HERE elif call.data == "report_user": role = cur.execute( '''SELECT role FROM Users WHERE tel_id = (%s)''', (forwarded_user, )).fetchone()[0] # ONLY STUDENTS CAN BE REPORTED NOT ADMINs AND TAs if role == 'STUDENT': check_reported = cur.execute( '''SELECT tel_id FROM Report_User WHERE tel_id = (%s) AND reported_by = (%s)''', (forwarded_user, call.from_user.id)).fetchone() if check_reported is None: bot.answer_callback_query(callback_query_id=call.id, text="User Reported. Thanks!", show_alert=True) cur.execute( '''INSERT INTO Report_User (tel_id, reported_by) VALUES (%s, %s)''', (forwarded_user, call.from_user.id)) ban_user_id = cur.execute( '''SELECT tel_id, count(tel_id) FROM Report_User WHERE tel_id = (%s) GROUP BY tel_id HAVING count(tel_id) > (%s)''', (forwarded_user, report_user_limit)).fetchone()[0] if call.message.date is not None: date = call.message.date else: date = call.message.edit_date cur.execute( '''UPDATE Report_User SET report_date = (%s) WHERE tel_id = (%s)''', (date, ban_user_id)) cur.execute( '''UPDATE Users SET state = 'BANNED' WHERE tel_id = (%s)''', (ban_user_id, )) else: bot.answer_callback_query( callback_query_id=call.id, text="This user has already been reported by you!", show_alert=True) elif role in ['ADMIN', 'TA']: bot.answer_callback_query( callback_query_id=call.id, text="You CANNOT report Admins and TAs!", show_alert=True) ################################## ######### QUESTION ########### ################################## elif call.data == "follow_question": try: question_owner = cur.execute( '''SELECT tel_id FROM Questions WHERE id = (%s)''', (forwarded_question, )).fetchone()[0] role = cur.execute( '''SELECT role FROM Users WHERE tel_id = (%s)''', (question_owner, )).fetchone()[0] print(role) if role in vip: bot.answer_callback_query( callback_query_id=call.id, text=emoji.emojize( ":cross_mark: Cannot follow Questions sent by ADMINs or TAs." ), show_alert=True) else: if question_owner == call.from_user.id: bot.answer_callback_query( callback_query_id=call.id, text=emoji.emojize( ":cross_mark: Question {0} is your own question." .format(question_id))) else: cur.execute( '''INSERT INTO Follow_Question (question_id, follower) VALUES (%s, %s)''', (forwarded_question, call.from_user.id)) previous_answers_num = cur.execute( '''SELECT count(question_id) FROM Answers WHERE question_id = (%s)''', (forwarded_question, )).fetchone()[0] bot.answer_callback_query( callback_query_id=call.id, text=emoji.emojize( ":TOP_arrow: Fowlloing Question {0}" "\n:right_arrow: Already " + str(previous_answers_num) + " Answer(s) available in archive.".format( question_id)), show_alert=True) except Exception as e: bot.answer_callback_query( callback_query_id=call.id, text=emoji.emojize( ":right_arrow: You have already followed Question " + str(forwarded_question)), show_alert=True) # ANSWERING A QUESTION elif call.data == "answer_question": role = cur.execute( '''SELECT role FROM Users WHERE tel_id = (%s)''', (call.from_user.id, )).fetchone()[0] question_state = cur.execute( '''SELECT status FROM Questions WHERE id = (%s)''', (forwarded_question, )).fetchone()[0] if (question_state == 'OPEN') or (role in ['ADMIN', 'TA']): bot.answer_callback_query(callback_query_id=call.id, text="Send answer!") cur.execute( '''UPDATE Users SET state = (%s) WHERE tel_id = (%s)''', ('Send Answer', call.from_user.id)) bot.reply_to( call.message, emoji.emojize( ':right_arrow: Send your answer for: *Question ' + str(forwarded_question) + '*'), reply_markup=Finish_Discard_keyboard, parse_mode='Markdown') else: # QUESTION IS CLOSED OR REPORTED bot.answer_callback_query( callback_query_id=call.id, text="Question is {0}!".format(question_state), show_alert=True) # REPORTING A QUESTION elif call.data == "report_question": # to avoid reporting a question two times from the same user check_reported = cur.execute( '''SELECT question_id FROM Report_Question WHERE question_id = (%s) AND reported_by = (%s)''', (forwarded_question, call.from_user.id)).fetchone() if check_reported is None: bot.answer_callback_query( callback_query_id=call.id, text="Questions {0} reported. Thanks.".format(question_id), show_alert=True) cur.execute( '''INSERT INTO Report_Question (question_id, reported_by) VALUES (%s, %s)''', (forwarded_question, call.from_user.id)) # Questions beyond report limit will be changed to ___Reported Question___ question_reported = cur.execute( '''SELECT count(question_id) FROM Report_Question WHERE question_id = (%s)''', (forwarded_question, )).fetchone()[0] role = cur.execute( '''SELECT role FROM Users WHERE tel_id = (%s)''', (call.from_user.id, )).fetchone()[0] if (question_reported >= report_question_limit) or ( role in instant_report_roles): reported_text, reported_photo, reported_document, reported_document_type, reported_document_size = \ cur.execute('''SELECT question, photo, document, document_type, document_size FROM Questions WHERE id = (%s)''', (forwarded_question,)).fetchone() cur.execute( '''UPDATE Report_Question SET reported_text = (%s), photo = (%s), document = (%s), document_type = (%s), document_size = (%s) WHERE question_id = (%s)''', ( reported_text, reported_photo, reported_document, reported_document_type, reported_document_size, forwarded_question, )) cur.execute( '''UPDATE Questions SET question = (%s), status = (%s), photo = NULL, document = NULL, document_type = NULL, document_size = NULL WHERE id = (%s)''', ("___Reported Question___", 'REPORTED', question_id)) if role in instant_report_roles: question_owner_id = cur.execute( '''SELECT tel_id FROM Questions WHERE id = (%s)''', (question_id, )).fetchone()[0] first_name, last_name, username = cur.execute( '''SELECT first_name, last_name, username FROM Users WHERE tel_id = (%s)''', (question_owner_id, )).fetchone() bot.send_message( call.from_user.id, emoji.emojize( ':white_heavy_check_mark: Question #Q_{} of user: {} {} (@{}) reported.' .format(question_id, first_name, last_name, username))) try: bot.send_message( question_owner_id, emoji.emojize( ':warning: Your question #Q_{} has been reported. Please be careful when asking questions.' .format(question_id))) except: pass else: bot.answer_callback_query( callback_query_id=call.id, text="Question {0} has already been reported by you!". format(question_id), show_alert=True) ################################## ######### ANSWER ########### ################################## # ACCEPTING AN ANSWER elif call.data == "accept_answer": accepted_answer = cur.execute( '''SELECT accepted_answer FROM Answers WHERE question_id = (%s) AND tel_id = (%s)''', (forwarded_question, forwarded_user)).fetchone()[0] if accepted_answer == 0: ## Questions sent by VIP can have more than one accepted answer question_owner_role = cur.execute( '''SELECT role FROM Users, Questions WHERE Users.tel_id = Questions.tel_id AND Questions.id = (%s)''', (question_id, )).fetchone()[0] # if question is NOT sent by VIP, then previous accepted answer is removed and newer answer is replaced accepted_already_flag = cur.execute( '''SELECT accepted_answer FROM Answers WHERE question_id = (%s)''', (forwarded_question, )).fetchone()[0] if question_owner_role not in vip: # to check if already another answer was accepted cur.execute( '''UPDATE Answers SET accepted_answer = 0 WHERE question_id = (%s)''', (forwarded_question, )) cur.execute( '''UPDATE Answers SET accepted_answer = 1 WHERE question_id = (%s) AND tel_id = (%s)''', (forwarded_question, forwarded_user)) bot.answer_callback_query(callback_query_id=call.id, text="Answer marked as accepted!") bot.send_message( call.from_user.id, emoji.emojize(":right_arrow: Please rate the answer:"), reply_markup=rate_accept_answer_keyboard) cur.execute( '''UPDATE Users SET state = (%s) WHERE tel_id = (%s)''', ('Rate Answer', call.from_user.id)) cur.execute( '''UPDATE Questions SET status = (%s) WHERE id = (%s)''', ('CLOSED', question_id)) # Sending Question and Accepted Answer to all users except question owner send_list = cur.execute( '''SELECT tel_id FROM Users WHERE tel_id != (%s)''', (call.from_user.id, )).fetchall() if accepted_already_flag != 1: for user in send_list: try: if question_owner_role not in vip: bot.send_message( user[0], emoji.emojize( ':white_heavy_check_mark: #Q_{0} is answered now.' .format(forwarded_question)), reply_markup=showhere_keyboard, disable_notification=True) else: accepted_answers_count = cur.execute( '''SELECT count(answers) FROM Answers WHERE question_id = (%s) and accepted_answer = 1''', (question_id, )).fetchone()[0] bot.send_message( user[0], emoji.emojize( ':white_heavy_check_mark: #Q_{0} sent by ADMIN has accepted answer ({1} Accepted Answers).' '\n:right_arrow: Enter Question Number ({0}) to see all answers.' .format(question_id, accepted_answers_count)), disable_notification=True) except Exception as e: print( 'Sending Accepted Answer to some users failed!', e) else: bot.answer_callback_query(callback_query_id=call.id, text="Answer already accepted!", show_alert=True) # SHOWING ACCEPTED ANSWER and its QUESTION to receiving users elif call.data == 'show_here': # forwarded question and forwarded user is NOT VALID here. pattern = ':white_heavy_check_mark: #Q_(\d+) \w+' #question_id is in (\d+) res = re.match(pattern, emoji.demojize(message.text)) if res is not None: # Sending Question accepted_question_id = res.group(1) # Sending Answer answer_owner = cur.execute( '''SELECT tel_id FROM Answers WHERE question_id = (%s) and accepted_answer = 1''', (accepted_question_id, )).fetchone()[0] answer, keyboard = send_answer(accepted_question_id, answer_owner, call.from_user.id, short=True) bot.delete_message(call.from_user.id, call.message.message_id) bot.send_message( call.from_user.id, emoji.emojize( ':down_arrow: Accepted answer for #Q_{0}.'.format( accepted_question_id))) bot.send_message(call.from_user.id, answer, reply_markup=keyboard) elif call.data == 'close_question': question_state = cur.execute( '''SELECT status FROM Questions WHERE id = (%s)''', (question_id, )).fetchone()[0] if question_state == 'CLOSED': bot.answer_callback_query( callback_query_id=call.id, text=emoji.emojize( ":cross_mark: Question {0} is already closed.".format( question_id)), show_alert=True) elif question_state == 'OPEN': cur.execute( '''UPDATE Questions SET status = (%s) WHERE id = (%s)''', ('CLOSED', question_id)) question_owner = cur.execute( '''SELECT tel_id FROM Questions WHERE id = (%s)''', (question_id, )).fetchone()[0] try: bot.send_message( question_owner, emoji.emojize( ':cross_mark: Your Question (#Q_{0}) is closed by ADMIN.' ).format(question_id)) except: print('User {0} has blocked Robot.'.format(question_owner)) bot.answer_callback_query( callback_query_id=call.id, text=emoji.emojize( ":white_heavy_check_mark: Question {0} closed successfully." .format(question_id)), show_alert=True) ################################## ### Next and Previous Page ### ################################## elif call.data == "next_page_question": bot.answer_callback_query(callback_query_id=call.id, text="Next Page") photo, document, document_type, document_size = \ cur.execute('''SELECT photo, document, document_type, document_size FROM Questions WHERE id = (%s)''', (forwarded_question, )).fetchone() # Specifying keyboard accordingly keyboard = telebot.types.InlineKeyboardMarkup(row_width=4) role = cur.execute( '''SELECT role FROM Users WHERE tel_id = (%s)''', (call.from_user.id, )).fetchone()[0] if role == 'ADMIN': close_question = telebot.types.InlineKeyboardButton( emoji.emojize(':cross_mark: Close'), callback_data='close_question') keyboard.add(close_question, report_question, follow_question, previous_page_question) else: keyboard.add(report_question, follow_question, previous_page_question) if photo is not None: keyboard.add(photo_button) if document is not None: document_button = telebot.types.InlineKeyboardButton( emoji.emojize(':paperclip: {0} ({1})'.format( document_type, document_size)), callback_data='document') keyboard.add(document_button) # Editing Message bot.edit_message_reply_markup(call.from_user.id, call.message.message_id, reply_markup=keyboard) elif call.data == "previous_page_question": bot.answer_callback_query(callback_query_id=call.id, text="Previous Page") keyboard = send_question(forwarded_question, call.from_user.id, short=True)[1] bot.edit_message_reply_markup(call.from_user.id, call.message.message_id, reply_markup=keyboard) elif call.data == "next_page_answer": bot.answer_callback_query(callback_query_id=call.id, text="Next Page") photo, document, document_type, document_size = \ cur.execute('''SELECT photo, document, document_type, document_size FROM Answers WHERE question_id = (%s) AND tel_id = (%s)''' , (forwarded_question, forwarded_user)).fetchone() general_keyboard = telebot.types.InlineKeyboardMarkup() general_keyboard.add(report_user, previous_page_answer) if photo is not None: general_keyboard.add(photo_button) if document is not None: document_button = telebot.types.InlineKeyboardButton( emoji.emojize(':paperclip: {0} ({1})'.format( document_type, document_size)), callback_data='document') general_keyboard.add(document_button) bot.edit_message_reply_markup(call.from_user.id, call.message.message_id, reply_markup=general_keyboard) elif call.data == "previous_page_answer": bot.answer_callback_query(callback_query_id=call.id, text="Previous Page") keyboard = send_answer(forwarded_question, forwarded_user, call.from_user.id, short=True)[1] bot.edit_message_reply_markup(call.from_user.id, call.message.message_id, reply_markup=keyboard) ################################## ### Next and Previous Page ### ################################## # JUST A BUTTON WHEN THE BOT STARTS elif call.data == "send_question": bot.answer_callback_query(callback_query_id=call.id, text="Send your question...") bot.send_message( call.from_user.id, emoji.emojize( ':right_arrow: Send your question, then select Finish.\n\n' ':paperclip: 1 File and 1 Photo are allowed as attachment.' ), reply_markup=Finish_Discard_keyboard) cur.execute( '''UPDATE Users SET state = (%s) WHERE tel_id = (%s)''', ('Send Question', call.from_user.id)) elif call.data == 'next_page_contact': bot.answer_callback_query(callback_query_id=call.id, text="Next Page") bot.edit_message_text(emoji.emojize( ":envelope: Contact Info:\n\n" ":bust_in_silhouette: Ali Arjmand:\n :white_small_square: @AliArjomandBigdeli\n :black_small_square: [email protected]\n" ":bust_in_silhouette: Mohammad Hossein Amini\n :white_small_square: @MHosseinAmini\n :black_small_square: [email protected] \n" ":bust_in_silhouette: Parsa Asadi\n :white_small_square: @parsa_assadi\n :black_small_square: [email protected]\n" ":bust_in_silhouette: S. Reza Hashemi:\n :white_small_square: @SeyedReza_110\n :black_small_square: [email protected]\n" ":bust_in_silhouette: Amin Ansarian\n :white_small_square: @MarshalAmin\n :black_small_square: [email protected]\n" ":bust_in_silhouette: Roozbeh Bazargani\n :white_small_square: @roozbeh711\n :black_small_square: [email protected]\n" ":bust_in_silhouette: Amir Hossein Zamani\n :white_small_square: @AHZ975\n :black_small_square: [email protected]" ), call.from_user.id, call.message.message_id, reply_markup=previous_page_contact) elif call.data == 'previous_page_contact': bot.answer_callback_query(callback_query_id=call.id, text="Previous Page") bot.edit_message_text(emoji.emojize( ":envelope: Contact Info:\n\n" ":bust_in_silhouette: Ali Hejazi:\n :white_small_square: @Ali_H93\n :black_small_square: [email protected]\n" ":bust_in_silhouette: Nima Sedghiye\n :white_small_square: @Nima_sedghiye\n :black_small_square: [email protected]\n" ":bust_in_silhouette: Hamed Hosseini\n :white_small_square: @HMDHosseini\n :black_small_square: [email protected]" ), call.from_user.id, call.message.message_id, reply_markup=next_page_contact)
def send_welcome(message): """This function registers user and sends welcome message.""" # 2 Stages: Temporary User (not Enrolled Yet) - Permanent User check_temp_user = cur.execute( '''SELECT tel_id FROM Users_Temp WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone() check_user = cur.execute( '''SELECT tel_id FROM Users WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone() print(check_temp_user, check_user) if check_temp_user is None: ### Permanent Users First Touch if check_user is None: cur.execute( '''INSERT INTO Users_Temp (tel_id, first_name, last_name, username, login_date, state) VALUES (%s, %s, %s, %s, %s, %s)''', (message.from_user.id, message.from_user.first_name, message.from_user.last_name, message.from_user.username, message.date, 'START')) bot.send_message( message.from_user.id, emoji.emojize( ":desktop_computer: Hi, I'm *Stackoverflow* Bot. " "\n:bust_in_silhouette: Enter your *Student Number* to register." ), parse_mode="Markdown") ### Permanent Users After Login Message else: bot.send_message( message.from_user.id, emoji.emojize(":desktop_computer: *Stackoverflow* Bot"), parse_mode="Markdown", reply_markup=main_reply_keyboard) cur.execute( '''UPDATE Users SET state = 'IDLE' WHERE tel_id = (%s)''', (message.from_user.id, )) else: ### Temporary Users Not Registered Warning if check_user is None: bot.send_message( message.from_user.id, emoji.emojize( ":warning: Not registered yet.\n" ":bust_in_silhouette: Enter your *Student Number* to register." ), parse_mode="Markdown", reply_markup=None) ### Permanent Users Message when they send /start command else: bot.send_message( message.from_user.id, emoji.emojize( ":desktop_computer: *AUT Stackoverflow* Bot\n\n" ":red_triangle_pointed_down: *Latest News*\n" " :paperclip: HW1: https://goo.gl/LecD5n\n" " :clapper_board: Recorded Sessions: goo.gl/uVcDD4"), parse_mode="Markdown", reply_markup=main_reply_keyboard) cur.execute( '''UPDATE Users SET state = 'IDLE' WHERE tel_id = (%s)''', (message.from_user.id, ))
def chat(message): # print(emoji.demojize(message.text)) try: state = cur.execute('''SELECT state FROM Users WHERE tel_id = (%s)''', (message.from_user.id,)).fetchone() if state is not None: state = state[0] cur.execute('''UPDATE Users SET first_name = (%s), last_name = (%s), username = (%s) WHERE tel_id = (%s)''', (message.from_user.first_name, message.from_user.last_name, message.from_user.username, message.from_user.id)) #################################### #### IDLE #### #################################### if state == 'IDLE': # SEND QUESTION if emoji.demojize(message.text) == ':question_mark: Send Question': bot.send_message(message.from_user.id, emoji.emojize( ':right_arrow: Send your question, then select Finish.\n\n' ':paperclip: 1 File and 1 Photo are allowed as attachment.'), reply_markup=Finish_Discard_keyboard) cur.execute('''UPDATE Users SET state = (%s) WHERE tel_id = (%s)''', ('Send Question', message.from_user.id)) # MY PROFILE elif emoji.demojize(message.text) == ':bust_in_silhouette: My Profile': try: ## FIRSTNAME, LASTNAME, USERNAME user = emoji.emojize(":bust_in_silhouette: " + message.from_user.first_name) if message.from_user.last_name is not None: user = user + message.from_user.last_name if message.from_user.username is not None: user = user + " (@{0})".format(message.from_user.username) role, st_num = cur.execute('''SELECT role, st_num from Users WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone() user = user + '\n' + emoji.emojize(':white_small_square:' ) + '{0} ({1})'.format(role.capitalize(), st_num) ## GETTING QUESTIONS my_questions = cur.execute('''SELECT id FROM Questions WHERE tel_id = (%s) ORDER BY id''', (message.from_user.id,)).fetchall() if len(my_questions) > 0: ### template questions = ':question_mark: Questions:' ### counter is for printing three questions in each row counter = 0 for question in my_questions: if counter % 3 == 0: questions = questions + '\n' # LIKE is disabled now # like_number = cur.execute('''SELECT count(*) FROM Like_Question WHERE question_id = (%s)''', (question[0], )).fetchone()[0] # if like_number > 0: # questions += '#Q_{0} ({1}:red_heart:) '.format(question[0], like_number) # else: # questions += '#Q_{0} '.format(question[0]) counter = counter + 1 else: questions = ':question_mark: Questions:\nNone' ## GETTING ANSWERS my_answers = cur.execute('''SELECT question_id, accepted_answer, rate_answer FROM Answers WHERE tel_id = (%s) ORDER BY question_id''', (message.from_user.id,)).fetchall() if len(my_answers) > 0: ### counter is just to format the output by 3 in each row counter = 0 answers = ':bright_button: Answers:' for answer in my_answers: if counter % 3 == 0: answers = answers + '\n' if answer[1] == 0: answers += ':bright_button:#A_{0} '.format(answer[0]) else: answers += ':white_heavy_check_mark:#A_{0} ({1}/5) '.format(answer[0], answer[2]) counter = counter + 1 else: answers = ':bright_button: Answers:\nNone' ## TOTAL POINT calculation point = 0 ## POINTS OF QUESTIONS AND ANSWERS user_questions_count = cur.execute('''SELECT COUNT(id) FROM Questions WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone()[0] user_answers_count = cur.execute('''SELECT COUNT(question_id) FROM Answers WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone()[0] point = point + user_questions_count * question_point + user_answers_count * answer_point ## POINTS OF ACCEPTED ANSWERS user_accepted_answers = cur.execute('''SELECT rate_answer FROM Answers WHERE tel_id = (%s) AND accepted_answer = 1''', (message.from_user.id, )).fetchall() for rate_answer in user_accepted_answers: try: point = point + rate_answer[0]/5.0*accepted_answer_point except Exception as e: print('There are some Accepted bot not Rated ANSWERs in Database!') ## GETTING HIGHEST POINT highest_point = cur.execute('''SELECT MAX(point) FROM Users''').fetchone()[0] point = ':high_voltage: Points: {0}\n:high_voltage: Highest Point: {1}'.format(point, highest_point) bot.send_message(message.from_user.id, emoji.emojize('\n\n'.join([user, questions, answers, point])), reply_markup=getfile_keyboard) except Exception as e: print('Something went wrong in My Profile of user: {0}'.format(message.from_user.id), e) tb = traceback.format_exc() print(tb) bot.send_message(message.from_user.id, tb) bot.send_message(admin_tel_id, 'Something went wrong in My Profile of user: {0}'.format(message.from_user.id)) bot.send_message(admin_tel_id, tb) # ALL QUESTIONS AND THEIR ANSWERS elif emoji.demojize(message.text) == ':page_facing_up: All Questions': all_questions = cur.execute('''SELECT id, status FROM Questions ORDER BY id DESC LIMIT 10''').fetchall() all_questions_count = cur.execute('''SELECT count(*) FROM Questions''').fetchone()[0] questions = emoji.emojize(':page_facing_up: Total Questions: {0}\n\n' ':down_arrow: Recently Sent:\n'.format(all_questions_count)) if len(all_questions) > 0: for question in all_questions: question_id, question_state = question[0], question[1] answers_count = cur.execute('''SELECT count(question_id) FROM Answers WHERE question_id = (%s)''', (question_id,)).fetchone()[0] questions += emoji.emojize(':question_mark:#Q_') + "{0} - {1} Answer(s) - {2}\n".format(question_id, answers_count, question_state) else: questions += 'None' # TOP Questions is disabled now # questions += emoji.emojize('\n:down_arrow: Top Questions:\n') # best_questions = cur.execute('''SELECT question_id, count(liked_by) FROM Like_Question GROUP BY question_id ORDER BY count(liked_by) DESC, question_id DESC LIMIT 3''').fetchall() # for question in best_questions: # question_id = question[0] # like_number = question[1] # questions += emoji.emojize(':question_mark: #Q_{0} ({1}:red_heart:)\n'.format(question_id, like_number)) bot.send_message(message.from_user.id, questions, reply_markup=getfile_keyboard) # OPEN QUESTIONS elif emoji.demojize(message.text) == ':question_mark: Open Questions': open_questions_list = cur.execute('''SELECT id FROM Questions WHERE status = (%s) ORDER BY id''', ('OPEN',)).fetchall() questions = emoji.emojize(':question_mark: Open Questions: ') if len(open_questions_list) > 0: for question in open_questions_list: answers_count = \ cur.execute('''SELECT count(question_id) FROM Answers WHERE question_id = (%s)''', (question[0],)).fetchone()[0] questions += "\n#Q_{0} - {1} Answer(s)".format(question[0], answers_count) else: questions +='None' bot.send_message(message.from_user.id, questions) ### TOP STUDENTS elif emoji.demojize(message.text) == ':high_voltage: Top Students': msg_text = emoji.emojize('\n:down_arrow: Top 5 Students:\n\n') best_students = cur.execute( '''SELECT st_num, first_name, last_name, point, tel_id FROM Users WHERE tel_id IS NOT NULL ORDER BY point DESC LIMIT 5''').fetchall() for student in best_students: try: print(student) student_id = student[0] first_name = student[1] last_name = student[2] if last_name is None: last_name = '' point = student[3] tel_id = student[4] questions_num = cur.execute('''SELECT COUNT(id) FROM Questions WHERE tel_id = (%s)''', (tel_id, )).fetchone()[0] answers_num = cur.execute('''SELECT COUNT(question_id) FROM Answers WHERE tel_id = (%s)''', (tel_id, )).fetchone()[0] accepted_answers_num = cur.execute('''SELECT COUNT(question_id) FROM Answers WHERE tel_id = (%s) AND accepted_answer = 1''', (tel_id, )).fetchone()[0] msg_text += emoji.emojize( ':bust_in_silhouette: {0} - {1} {2} \n' ':question_mark: {3}, :bright_button: {4}, :white_heavy_check_mark: {5} \n:high_voltage: {6} points\n\n'.format(student_id, first_name, last_name, questions_num, answers_num, accepted_answers_num, point)) except Exception as e: print(e) bot.send_message(message.from_user.id, msg_text) ### BY PRESSING A NUMBER, IT'S QUESTION WILL POP UP (IF ACCEPTED ANSWER IS READY, THAT WILL COME TOO) else: # Check if entered only a number q_pattern = r'^(?P<question_id>\d+)$' q_res = re.match(q_pattern, message.text) if q_res is not None: question_id = q_res.group('question_id') id = cur.execute('''SELECT id FROM Questions WHERE id = (%s)''', (question_id,)).fetchone() # Check if number matches a question if id is not None: question, keyboard = send_question(question_id, message.from_user.id, short=True) bot.send_message(message.from_user.id, question, reply_markup=keyboard) # If Questions has accepted answer, BOT will send it too question_state = cur.execute('''SELECT status FROM Questions WHERE id = (%s)''', (id, )).fetchone()[0] if question_state != 'REPORTED': answer_owners = cur.execute('''SELECT tel_id FROM Answers WHERE question_id = (%s) AND accepted_answer = 1''', (question_id, )).fetchall() if len(answer_owners) > 0: for answer_owner in answer_owners: answer_owner = answer_owner[0] answer, keyboard = send_answer(question_id, answer_owner, message.from_user.id, short=True) if answer is not None: bot.send_message(message.from_user.id, answer, reply_markup=keyboard) admins_answers = cur.execute('''SELECT answer, Answers.tel_id FROM Answers, Users WHERE Answers.tel_id = Users.tel_id AND question_id = (%s) AND Users.role = (%s)''', (question_id, 'ADMIN')).fetchall() for answer in admins_answers: answer, keyboard = send_answer(question_id, answer[1], message.from_user.id, short=True) bot.send_message(message.from_user.id, answer, reply_markup=keyboard) else: # Message when number is beyond total questions total_questions_number = cur.execute('''SELECT count(id) FROM Questions''').fetchone()[0] bot.send_message(message.from_user.id, emoji.emojize( ':right_arrow: Number exceeded total questions.\n\n:question_mark: *Total Questions: {0}*' .format(total_questions_number)), parse_mode='Markdown') # ADD OR REMOVE A USER else: ## ADDING A USER if message.from_user.username in admins: add_pattern = r'^add (?P<stnum>\d{1,30}) (?P<role>\w+)$' add_res = re.match(add_pattern, message.text, re.IGNORECASE) if add_res is not None: st_num = add_res.group('stnum') role = add_res.group('role').upper() check_stnum = cur.execute('''SELECT st_num FROM Users WHERE st_num = (%s)''', (st_num, )).fetchone() ### CHECKING FOR VALID ROLES SUCH AS STUDENT, TA, ETC if role in valid_roles: if check_stnum is None: cur.execute('''INSERT INTO Users (st_num, role) VALUES (%s, %s)''', (st_num, role)) bot.send_message(message.from_user.id, emoji.emojize(":white_heavy_check_mark: Student Number *{0}* " "added with role *{1}*.".format(st_num, role)), parse_mode='Markdown') else: bot.send_message(message.from_user.id, emoji.emojize(':cross_mark: Student Number {0} is already added.'.format(st_num))) else: bot.send_message(message.from_user.id, emoji.emojize(':cross_mark: Invalid role *{0}*.'.format(role)), parse_mode='Markdown') ## REMOVING A USER else: remove_pattern = r'^remove (?P<st_num>\d{1,30})$' remove_res = re.match(remove_pattern, message.text, re.IGNORECASE) if remove_res is not None: st_num = remove_res.group('st_num') check_stnum = cur.execute('''SELECT st_num FROM Users WHERE st_num = (%s)''', (st_num,)).fetchone() if check_stnum is not None: check_role = cur.execute('''SELECT role FROM Users WHERE st_num = (%s)''', (st_num, )).fetchone()[0] if check_role in ['ADMIN']: bot.send_message(message.from_user.id, emoji.emojize( ':cross_mark: Cannot remove *{0}s*.'.format(check_role)), parse_mode='Markdown') else: cur.execute('''DELETE FROM Users WHERE st_num = (%s) AND role NOT IN (%s)''', (st_num, 'ADMIN')) cur.execute('''DELETE FROM Users_Temp WHERE st_num = (%s)''', (st_num, )) bot.send_message(message.from_user.id, emoji.emojize( ':white_heavy_check_mark: Student Number *{0}* removed.'.format(st_num)), parse_mode='Markdown') else: bot.send_message(message.from_user.id, emoji.emojize( ':cross_mark: Student Number {0} is already removed.'.format(st_num))) #################################### #### Rate Answer #### #################################### elif state == 'Rate Answer': pattern = r"(^(:bright_button:){1,5}$)" res = re.match(pattern, emoji.demojize(message.text)) if res is not None: rate = len(res.group(0).split("::")) # Question and Answer Owner forwarded_question, forwarded_user = cur.execute( '''SELECT forwarded_question, forwarded_user FROM Users WHERE tel_id = (%s)''', (message.from_user.id,)).fetchone() cur.execute('''UPDATE Answers SET rate_answer = (%s) WHERE question_id = (%s) AND tel_id = (%s)''', (rate, forwarded_question, forwarded_user)) bot.send_message(message.from_user.id, emoji.emojize(":white_heavy_check_mark: Thanks! Answer rated *{0}*.".format(rate)), reply_markup=main_reply_keyboard, parse_mode='Markdown') bot.send_message(forwarded_user, emoji.emojize( ':white_heavy_check_mark: Your answer for #Q_{0} accepted and rated {1}.\n' ':high_voltage: Points Received: {2}'.format(forwarded_question, rate, accepted_answer_point*rate/5.0))) # RESETING STATE TO IDLE cur.execute('''UPDATE Users SET state = (%s) WHERE tel_id = (%s)''', ('IDLE', message.from_user.id)) # Increasing point of answer owner cur.execute('''UPDATE Users SET point = point + (%s) WHERE tel_id = (%s)''', (accepted_answer_point*rate/5.0, forwarded_user)) else: bot.reply_to(message, emoji.emojize(":cross_mark: Invalid input.")) #################################### #### Send Question #### #################################### elif state in ['Send Question', 'Send Answer', 'Send Comment']: # FINISH KEY if emoji.demojize(message.text) == ':white_heavy_check_mark: Finish': handle_message_finish(message) # DISCARD KEY elif emoji.demojize(message.text) == ':cross_mark: Discard': # RESETING TO IDLE cur.execute('''UPDATE Users SET state = (%s) WHERE tel_id = (%s)''', ('IDLE', message.from_user.id)) cur.execute('''UPDATE Users SET cont_typing = NULL, photo = NULL, document = NULL, document_type = NULL, document_size = NULL WHERE tel_id = (%s)''', (message.from_user.id, )) bot.send_message(message.from_user.id, emoji.emojize(':cross_mark: Discarded.'), reply_markup=main_reply_keyboard) conn.commit() # CONTINUE TYPING ANSWER OR QUESTION else: cont_typing = cur.execute('''SELECT cont_typing FROM Users WHERE tel_id = (%s)''', (message.from_user.id,)).fetchone()[0] if cont_typing == None: cur.execute('''UPDATE Users SET cont_typing = (%s) WHERE tel_id = (%s)''', (message.text, message.from_user.id)) else: cont_typing = cur.execute('''SELECT cont_typing FROM Users WHERE tel_id = (%s)''', (message.from_user.id,)).fetchone()[0] cur.execute('''UPDATE Users SET cont_typing=(%s) WHERE tel_id = (%s)''', (cont_typing + '\n' + message.text, message.from_user.id)) ### SENDING GLOBAL MESSAGE TO ALL USERS (RESTRICTED TO ADMINs) elif state == 'SEND MSG TO ALL USERS': # FINISH KEY if emoji.demojize(message.text) == ':white_heavy_check_mark: Finish': handle_message_finish(message) # DISCARD KEY elif emoji.demojize(message.text) == ':cross_mark: Discard': # RESETING TO IDLE cur.execute('''UPDATE Users SET state = (%s) WHERE tel_id = (%s)''', ('IDLE', message.from_user.id)) cur.execute('''UPDATE Users SET cont_typing = NULL, photo = NULL, document = NULL, document_type = NULL, document_size = NULL WHERE tel_id = (%s)''', (message.from_user.id,)) bot.send_message(message.from_user.id, emoji.emojize(':cross_mark: Discarded.'), reply_markup=main_reply_keyboard) else: cur.execute('''UPDATE Users SET cont_typing = (%s) WHERE tel_id = (%s)''', (message.text, message.from_user.id, )) #################################### #### NOT REGISTERED USERS #### #################################### else: state = cur.execute('''SELECT state FROM Users_TEMP WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone() if state is not None: state = state[0] #################################### #### START #### #################################### if state == 'START': try: pattern = r'^(?P<question_id>\d{1,30})$' res = re.match(pattern, message.text) if res.group(): st_num = res.groups()[0] registered_st_num = cur.execute('''SELECT st_num FROM Users WHERE st_num = (%s)''', (st_num, )).fetchone() check_previously_register = cur.execute('''SELECT state FROM Users_temp WHERE st_num = (%s) AND state = (%s)''', (st_num, 'REGISTERED')).fetchone() if check_previously_register is None: if registered_st_num is None: bot.reply_to(message, emoji.emojize(":cross_mark: Sorry. Not a Registered Student Number.")) else: passwd = st_num bot.send_message(message.from_user.id, emoji.emojize(':key: Enter your password:'******'''UPDATE Users_Temp SET st_num = (%s), login_code = (%s), state = (%s) WHERE tel_id = (%s)''', (st_num, passwd, 'LOGIN', message.from_user.id)) else: bot.reply_to(message, emoji.emojize(":cross_mark: This Student Number is already registered.")) except Exception as e: bot.reply_to(message, emoji.emojize(":cross_mark: Invalid Student Number")) print(e) #################################### #### LOGIN #### #################################### elif state == 'LOGIN': if emoji.demojize(message.text) == ':bust_in_silhouette: Change Student Number': bot.send_message(message.from_user.id, emoji.emojize(":e-mail: Enter the *New Student Number* to register."), parse_mode='Markdown') cur.execute('''UPDATE Users_TEMP SET state = (%s) WHERE tel_id = (%s)''', ('START', message.from_user.id,)) else: digit = cur.execute('''SELECT login_code FROM Users_TEMP WHERE tel_id = (%s)''', (message.from_user.id,)).fetchone()[0] try: if int(message.text) == digit: st_num = cur.execute('''SELECT st_num FROM Users_Temp WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone()[0] cur.execute("UPDATE Users SET tel_id=(%s), first_name=(%s), last_name=(%s), " "username=(%s), login_date=(%s), state=(%s), point=(%s) WHERE st_num = (%s)", (message.from_user.id, message.from_user.first_name, message.from_user.last_name, message.from_user.username, message.date, 'IDLE', 0, st_num)) cur.execute('''UPDATE Users_Temp SET state = (%s) WHERE tel_id = (%s)''', ('REGISTERED', message.from_user.id)) Questions_N = cur.execute('''SELECT count(Questions.id) FROM Questions''').fetchone()[0] Answers_N = cur.execute('''SELECT count(Answers.id) FROM Answers''').fetchone()[0] Users_N = cur.execute('''SELECT count(Users.tel_id) FROM Users''').fetchone()[0] bot.send_message(message.from_user.id, emoji.emojize(":desktop_computer: *Stackoverflow* Bot"), parse_mode="Markdown", reply_markup=main_reply_keyboard) bot.send_message(message.chat.id,emoji.emojize(':white_heavy_check_mark: Successfully registered!' + '\n:white_heavy_check_mark: Access granted.' '\n\n:bust_in_silhouette: Total Users: *' + str(Users_N) + '*\n:question_mark: Total Questions: *' + str(Questions_N) + '*' '\n:bright_button: Total Answers: *' + str(Answers_N) + '*'), reply_markup=send_question_inline, parse_mode='Markdown') else: bot.send_message(message.from_user.id, emoji.emojize(':cross_mark: Wrong login code. Try again!')) except Exception as e: bot.send_message(message.chat.id, emoji.emojize(':cross_mark: Wrong login code. Try again!')) print(e) except Exception as e: print('Something went wrong in chat(message) function (Main User): ', e) tb = traceback.format_exc() print(tb) try: bot.send_message(73106435, tb) username_error = cur.execute('''SELECT username FROM Users WHERE tel_id = (%s)''', (message.from_user.id, )).fetchone()[0] bot.send_message(73106435, 'Something went wrong for User: {0}'.format(username_error)) except Exception as e: print(e) conn.commit()