def handle_assign_admin_to_project(call, tg_id, project_id): session = Session() selected_user = session.query(User).filter(User.tg_id == tg_id).first() selected_project = session.query(Questionnaire).filter(Questionnaire.id == project_id).first() if selected_user in selected_project.project_admins: selected_project.project_admins.remove(selected_user) bot.answer_callback_query(call.id, f'{selected_user} is NOT an admin in {selected_project}') bot.send_message(call.message.chat.id, f'{selected_user} is NOT an admin in {selected_project}') else: selected_project.project_admins.append(selected_user) bot.answer_callback_query(call.id, f'{selected_user} IS an admin in {selected_project}') bot.send_message(call.message.chat.id, f'{selected_user} IS an admin in {selected_project}') session.add(selected_project) session.commit()
def warn_admins(text, session=None): if not session: session = Session() admins = session.query(User).filter(User.is_admin).all() for user in admins: # bot.send_message(user.chat_id, text) bot.send_message(user.tg_id, text)
def get_user(message, session=None): if not session: session = Session() user = session.query(User).filter(User.tg_id == message.from_user.id).first() if not user: user = create_user(message, session) return user
def handle_project_edit(call, project_id): bot.answer_callback_query(call.id, f'Selected project #{project_id}') session = Session() user = get_user(call, session=session) selected_project = session.query(Questionnaire).filter(Questionnaire.id == project_id).first() if user.is_admin or user.is_root or user in selected_project.project_admins: list_display = lambda iterable: '[\n\t' + ",\n\t".join([repr(i) for i in iterable]) + '\n]' fields = { 'name': selected_project.name, 'description': selected_project.description, 'version': selected_project.version, 'is active': selected_project.is_active, 'created by': repr(selected_project.created_by), 'admins': list_display(selected_project.project_users), 'interviewers': list_display(selected_project.project_admins), } markup = InlineKeyboardMarkup(row_width=2) btn_is_active = InlineKeyboardButton('Toggle: is active', callback_data=build_callback('toggle_is_active', project_id)) markup.add(btn_is_active) btn_assign_users = InlineKeyboardButton( 'Assign interviewers', callback_data=build_callback('assign_users', project_id) ) markup.add(btn_assign_users) msg = [] msg.append(f'Editing {repr(selected_project)}:') for k, v in fields.items(): msg.append(f'{k}: {v}') bot.send_message(call.message.chat.id, '\n'.join(msg), reply_markup=markup)
def _get_questionnaire(q_name, q_version, q_description, session=None, **kwargs): if not session: session = Session() quest = session.query(Questionnaire).filter( and_(Questionnaire.name == q_name, Questionnaire.version == q_version)).first() if not quest: quest = Questionnaire() quest.name = q_name quest.description = q_description quest.version = q_version creator = kwargs.get('created_by') if creator: quest.created_by = creator quest.project_users.append(creator) quest.project_admins.append(creator) quest.results_table_name = get_result_table_name(quest) session.add(quest) session.commit() return quest
def handle_start_survey_answer(message, questionnaire_id): print('handle_start_survey_answer', questionnaire_id) if message.text == 'Да': session = Session() question = session.query(Question).filter(and_(Question.questionnaire_id == questionnaire_id, Question.step == 1)).first() handle_answer(message, question=question, flags={Flags.goto_start}) else: handle_cancel(message)
def handle_users(message): user = get_user(message) if user.is_admin or user.is_root: session = Session() users = session.query(User).all() bot.send_message(message.chat.id, '\n'.join([repr(i) for i in users])) else: bot.send_message(message.chat.id, repr(user))
def handle_toggle_is_active(call, project_id): session = Session() selected_project = session.query(Questionnaire).filter(Questionnaire.id == project_id).first() selected_project.is_active = not selected_project.is_active session.add(selected_project) session.commit() msg = f'Selected project {selected_project} is {"active" if selected_project.is_active else "inactive"} now' bot.answer_callback_query(call.id, msg) bot.send_message(call.message.chat.id, msg)
def handle_toggle_is_interviewer(call, tg_id): session = Session() selected_user = session.query(User).filter(User.tg_id == tg_id).first() selected_user.is_interviewer = not selected_user.is_interviewer session.add(selected_user) session.commit() msg = f'Selected user {selected_user} is {"" if selected_user.is_interviewer else " NOT"} an interviewer now' bot.answer_callback_query(call.id, msg) bot.send_message(call.message.chat.id, msg)
def handle_start_survey(call, questionnaire_id): print('handle_start_survey', questionnaire_id) session = Session() name, description = session.query(Questionnaire.name, Questionnaire.description).filter(Questionnaire.id == questionnaire_id).first() markup = ReplyKeyboardMarkup(one_time_keyboard=True) buttons = (KeyboardButton(text='Да'), KeyboardButton(text='Нет')) markup.add(*buttons) msg = bot.send_message(call.message.chat.id, f'Начать опрос {name}?\n({description})', reply_markup=markup) bot.register_next_step_handler(msg, handle_start_survey_answer, questionnaire_id)
def handle_save(question, message): #todo handle all saves to db print('handle_save', question.code) if not question.save_in_survey: return check_data(question, message) session = Session() try: response = question.get_response_object(message.from_user.id) except (DetachedInstanceError, ProgrammingError): question = session.query(Question).filter(Question.id == question.id).first() response = question.get_response_object(message.from_user.id) if question.type.code == QuestionTypes.categorical: code = None for cat in question.categories: if cat.text == message.text: code = cat.id break response.__setattr__(question.code, code) session.add(response) session.commit() elif question.type.code == QuestionTypes.location: response.__setattr__(f'{question.code}_latitude', message.location.latitude) response.__setattr__(f'{question.code}_longitude', message.location.longitude) session.add(response) session.commit() elif question.type.code == QuestionTypes.photo: file_info = bot.get_file(message.photo[-1].file_id) print('handle_save', 'photo', file_info) downloaded_file = bot.download_file(file_info.file_path) file_name = '{}_{}'.format(message.from_user.id, file_info.file_path.split('/')[-1]) file_folder = Path(MEDIA_FOLDER, question.questionnaire.results_table_name) file_path = Path(file_folder, file_name) # file_path.mkdir(parents=True) try: with open(file_path, 'wb') as out: out.write(downloaded_file) except FileNotFoundError: file_folder.mkdir(parents=True) with open(file_path, 'wb') as out: out.write(downloaded_file) print('handle_save', 'file saved', file_path) print('handle_save', 'file saved relative', str(file_path.relative_to(ROOT_DIR))) response.__setattr__(question.code, str(file_path.relative_to(ROOT_DIR))) session.add(response) session.commit() elif question.type.code == QuestionTypes.timestamp: response.__setattr__(question.code, datetime.datetime.now()) session.add(response) session.commit() elif question.type.code == QuestionTypes.text or question.type.code == QuestionTypes.integer: print('TEXT Q TYPE', message.content_type, message.content_type == 'text') response.__setattr__(question.code, message.text) session.add(response) session.commit() else: print('handle_save', 'QUESTION TYPE NOT HANDLED FOR SAVE', question.type)
def handle_manage_users(message): user = get_user(message) if user.is_admin or user.is_root: markup = InlineKeyboardMarkup() session = Session() users = session.query(User).all() # u_list = '\n'.join([f'/{i.id}' for i in users]) for i in users: btn = InlineKeyboardButton(repr(i), callback_data=build_callback('user_edit', i.tg_id)) markup.add(btn) bot.send_message(message.chat.id, 'Выбери пользователя для редактирования:', reply_markup=markup) else: bot.send_message(message.chat.id, repr(user))
def handle_assign_to_projects(call, tg_id): session = Session() projects = session.query(Questionnaire).all() markup = InlineKeyboardMarkup() for i in projects: btn_project = InlineKeyboardButton( f'{repr(i)} [tap to edit]', callback_data=build_callback('project_edit', i.id) ) btn_interviewer = InlineKeyboardButton( 'as interviewer', callback_data=build_callback('assign_user_to_project', tg_id, i.id) ) btn_admin = InlineKeyboardButton( 'as admin', callback_data=build_callback('assign_admin_to_project', tg_id, i.id) ) markup.add(btn_project) markup.add(btn_interviewer, btn_admin) bot.send_message(call.message.chat.id, 'Select projects to toggle for assignment:', reply_markup=markup)
def handle_user_edit(call, tg_id): bot.answer_callback_query(call.id, f'Selected user #{tg_id}') session = Session() user = get_user(call, session=session) selected_user = session.query(User).filter(User.tg_id == tg_id).first() if user.is_admin or user.is_root: list_display = lambda iterable: '[\n\t' + ",\n\t".join([repr(i) for i in iterable]) + '\n]' fields = { 'telegram_id': selected_user.tg_id, 'first_name': selected_user.first_name, 'last_name': selected_user.last_name, 'is admin': selected_user.is_admin, 'is interviewer': selected_user.is_interviewer, 'projects': list_display(selected_user.available_questionnaires), 'admin_of': list_display(selected_user.admin_of_projects) } markup = InlineKeyboardMarkup(row_width=2) btn_is_admin = InlineKeyboardButton( 'Toggle: is admin', callback_data=build_callback('toggle_is_admin', selected_user.tg_id) ) btn_is_interviewer = InlineKeyboardButton( 'Toggle: is interviewer', callback_data=build_callback('toggle_is_interviewer', selected_user.tg_id) ) markup.add(btn_is_admin, btn_is_interviewer) btn_assign_to_projects = InlineKeyboardButton( 'Assign to projects', callback_data=build_callback('assign_to_projects', selected_user.tg_id) ) markup.add(btn_assign_to_projects) # btn_assign_admin = InlineKeyboardButton('Assign as admin', callback_data=build_callback('assign_admin', selected_user.tg_id)) # markup.add(btn_assign_admin) msg = [] msg.append(f'Editing {repr(selected_user)}:') for k, v in fields.items(): msg.append(f'{k}: {v}') bot.send_message(call.message.chat.id, '\n'.join(msg), reply_markup=markup)
def handle_assign_users(call, project_id): print('handle_assign_users', 'start', project_id) session = Session() users = session.query(User).all() markup = InlineKeyboardMarkup() for i in users: print(i) btn_user = InlineKeyboardButton( f'{repr(i)} [tap to edit]', callback_data=build_callback('user_edit', i.tg_id) ) btn_interviewer = InlineKeyboardButton( 'as interviewer', callback_data=build_callback('assign_user_to_project', i.tg_id, project_id) ) btn_admin = InlineKeyboardButton( 'as admin', callback_data=build_callback('assign_admin_to_project', i.tg_id, project_id) ) markup.add(btn_user) markup.add(btn_interviewer, btn_admin) bot.send_message(call.message.chat.id, 'Select users to toggle for assignment:', reply_markup=markup)
def before_question_ask(question, message): print('before_question_ask', question.code) if question.code == 'shops': s = Session() result_table = question.questionnaire.result_table latitude, longitude = s.query(result_table.q2_latitude, result_table.q2_longitude).filter(result_table.started_by_id == message.from_user.id).first() msg = '' distance_tolerance = 5 for shop in shops: shop['distance'] = round(get_distance(latitude, longitude, lat2=shop['latitude'], lon2=shop['longitude']), 1) msg += '\t{name}, distance: {distance}km\n'.format(**shop) print('before_question_ask', 'question.categories', question.categories) question.set_filter(func=lambda cat: shops[int(cat.code) - 1]['distance'] < distance_tolerance) print('before_question_ask after filter', 'question.categories', question.categories) bot.send_message(message.chat.id, f'All shops are:\n{msg}But only the ones within {distance_tolerance}km will be available for selection.') if len(question.categories) == 0: closest = sorted(shops, key=lambda a: a['distance'])[0] bot.send_message( message.chat.id, 'Ни одного магазина поблизости :( Попробуй подойти ближе и отправить точку еще раз\nЕсли что ближайший в {distance}км от тебя:\n{name}, {address}'.format( **closest ) )
def _save(question, questionnaire, step=None, force_save_in_survey=None, category_code_start=1, allow_overwrite=True, session=None): if not session: session = Session() question.questionnaire = questionnaire question.step = step question.save_in_survey = force_save_in_survey if force_save_in_survey is not None else question.should_be_saved_in_survey category_code = category_code_start for i in question.categories: i.code = i.code if i.code else category_code session.add(i) category_code += 1 session.add(question) try: session.commit() print(f'{question.code} created') except IntegrityError: session.rollback() print(f'{question.code} already in database') if allow_overwrite: session.delete( session.query(Question).filter( and_(Question.code == question.code, Question.questionnaire_id == questionnaire.id)).first()) session.commit() print(f'{question.code} deleted') session.add(question) session.commit() print(f'{question.code} created') if step: step += 1
from survey.survey_builder import _get_questionnaire, _save from survey.models import Question, QuestionTypes as types, Session, Category, User QUESTIONNAIRE_VERSION = 1 QUESTIONNAIRE_NAME = 'gluten_shops' QUESTIONNAIRE_DESCRIPTION = 'Исследование магазинов с безглютеновой продукцией' ROUTE_STEP = 1 ALLOW_OVERWRITE = False def get_questionnaire(session=None, **kwargs): return _get_questionnaire(QUESTIONNAIRE_NAME, QUESTIONNAIRE_VERSION, QUESTIONNAIRE_DESCRIPTION, session=session, **kwargs) session = Session() me = session.query(User).filter(User.tg_id == 305258161).first() questionnaire = get_questionnaire(session=session, created_by=me) def save(q, make_step=True): global ROUTE_STEP step = ROUTE_STEP if make_step else None saved = _save(q, questionnaire, step=step, allow_overwrite=ALLOW_OVERWRITE, session=session) if make_step: ROUTE_STEP += 1 return saved def emojize(s): return _emojize(s, use_aliases=True)
def get_previous_question(question): print('Previous question requested for ', question.code) session = Session() return session.query(Question).filter(Question.step == question.step - 1).first()
def get_next_question(question): session = Session() return session.query(Question).filter(Question.step == question.step + 1).first()