diff --git a/for_json.py b/for_json.py new file mode 100644 index 0000000..3dbd42d --- /dev/null +++ b/for_json.py @@ -0,0 +1,134 @@ +#!/usr/bin/python3.3 +import json, schedule +import schedules as bot +from datetime import datetime + +path = "users.json" # Нужный путь до json файлов +path_schedule = "schedule.json" + +def save_user(infos): + for i in range(len(infos)): + if type(infos[i]) == type(None): + infos[i] = '' + infos[i] = str(infos[i]) + infos = { + "id" : infos[0], + "first_name" : infos[1], + "last_name" : infos[2], + "username" : infos[3], + "group" : infos[4] + } + + data = {} + with open(path, 'r', encoding='utf-8') as json_file: + data = json.load(json_file) + + data[infos["id"]] = { + "username": infos["username"], + "first_name": infos["first_name"], + "last_name": infos["last_name"], + "group": infos["group"], + "timeout": "10", + "allow_message": "yes" + } + + with open(path, 'w', encoding='utf-8') as json_file: + json.dump(data, json_file, ensure_ascii=False, indent=4) + create_schedule_tasks() + +def change_user_param(id, key, value): + data = {} + with open(path, 'r', encoding='utf-8') as json_file: + data = json.load(json_file) + + data[id][key] = value + + with open(path, 'w', encoding='utf-8') as json_file: + json.dump(data, json_file, ensure_ascii=False, indent=4) + create_schedule_tasks() + +def create_schedule_tasks(): + schedule.clear() + users = {} + schdl = {} + with open(path, 'r', encoding='utf-8') as json_file: + users = json.load(json_file) + with open(path_schedule, 'r', encoding='utf-8') as json_file: + schdl = json.load(json_file) + for id, params in users.items(): + # print(id, '=>', params) + if params['allow_message'] != 'yes': + continue + group = params['group'] + if group == 'other': + continue + timeout = params['timeout'] + for day in schdl[group]: + for i, lesson in schdl[group][day].items(): + if lesson["name"] == "": #проверка на лоха + continue + + start, end = i.split("-") + text = '' + if len(lesson["infos"].split('|')) == 2: + teacher = lesson["infos"].split('|')[0] + room = lesson["infos"].split('|')[1] + text = '{}-{} | {}\ + \n{}\ + \n{}'.format(start, end, room, lesson["name"], teacher) + elif len(lesson["infos"].split('|')) == 4: + infos = lesson["infos"].split('|'); + text = '{}-{}\ + \n{}\ + \n({}) {}\ + \n({}) {}'.format(start, end, lesson["name"], + infos[1], + infos[0], + infos[3], + infos[2]) + elif len(lesson["infos"].split('|')) == 1: + text = '{}-{}\ + \n{}'.format(start, end, lesson["name"]) + else: #неправильный формат infos в json файле + print("что-то не так") + print(lesson["name"]) + continue + + delta = '00:' + params["timeout"] + format = '%H:%M' + start_task = datetime.strptime(start, format) - datetime.strptime(delta, format) + tmp = '' + for i in str(start_task).split(':'): + tmp += (('0' + i ) if len(i) < 2 else i) + ":" + start_task = tmp[:-1] + if day == 'mon': + schedule.every().monday.at(start_task).do(bot.send_message, id, text) + elif day == 'tue': + schedule.every().tuesday.at(start_task).do(bot.send_message, id, text) + elif day == 'wed': + schedule.every().wednesday.at(start_task).do(bot.send_message, id, text) + elif day == 'thu': + schedule.every().thursday.at(start_task).do(bot.send_message, id, text) + elif day == 'fri': + schedule.every().friday.at(start_task).do(bot.send_message, id, text) + elif day == 'sat': + schedule.every().saturday.at(start_task).do(bot.send_message, id, text) + + bot.send_message(bot.krosh, '🛑 Произошёл update') + + +def check_group_in_json(number): + schdl = {} + with open(path_schedule, 'r', encoding='utf-8') as json_file: + schdl = json.load(json_file) + return str(number) in schdl.keys() + +def return_infos(id): + data = {} + with open(path, 'r', encoding='utf-8') as json_file: + data = json.load(json_file) + data = data[id] + text = 'Выбранная группа: {}\ + \nВремя напоминания до урока: {}\ + \nРазрешены ли напоминания: {}'.format(data['group'], data['timeout'], ('да' if data['allow_message'] == 'yes' else 'нет')) + return text \ No newline at end of file diff --git a/schedule_expl.json b/schedule_expl.json new file mode 100644 index 0000000..1ae3328 --- /dev/null +++ b/schedule_expl.json @@ -0,0 +1,282 @@ +{ + "102": { + "mon": { + "8:45-10:20": { + "name": "Алгоритмы и алгоритмические языки", + "infos": "Белеванцев Андрей Андреевич|П-6" + }, + "10:30-12:05": { + "name": "Английский язык", + "infos": "Шубина Юлия Витальевна|73|Бим Мария Моисеевна|735" + }, + "12:50-14:25": { + "name": "Математический анализ", + "infos": "Лапонин Владислав Сергеевич|606" + }, + "15:00-16:30": { + "name": "Физическая культура", + "infos": "" + }, + "16:45-18:15": { + "name": "Консультация. Алгебра и геометрия", + "infos": "Руднев Сергей Геннадьевич|???" + } + }, + "tue": { + "10:30-12:05": { + "name": "Алгебра и геометрия", + "infos": "Тыртышников Евгений Евгеньевич|П-6" + }, + "12:50-14:25": { + "name": "Математический анализ", + "infos": "Садовничая Инна Викторовна|П-6" + }, + "14:35-16:10": { + "name": "Алгебра и геометрия", + "infos": "Руднев Сергей Геннадьевич|682" + }, + "16:20-17:55": { + "name": "Практикум на ЭВМ", + "infos": "Цыбров Евгений Германович|371|Кулагин Алексей Владимирович|МЗ-0" + } + }, + "wed": { + "8:45-10:20": { + "name": "Алгоритмы и алгоритмические языки", + "infos": "Белеванцев Андрей Андреевич|П-6" + }, + "10:30-12:05": { + "name": "Математический анализ", + "infos": "Лапонин Владислав Сергеевич|606" + }, + "12:50-14:25": { + "name": "Английский язык", + "infos": "Шубина Юлия Витальевна|735|Бим Мария Моисеевна|71" + } + }, + "thu": { + "8:45-10:20": { + "name": "Алгебра и геометрия", + "infos": "Тыртышников Евгений Евгеньевич|П-6" + }, + "10:30-12:05": { + "name": "Математический анализ", + "infos": "Садовничая Инна Викторовна|П-6" + }, + "12:50-14:25": { + "name": "История России", + "infos": "Чубыкин Игорь Валерьевич|523" + }, + "14:35-16:10": { + "name": "Алгебра и геометрия", + "infos": "Руднев Сергей Геннадьевич|606" + }, + "16:20-17:55": { + "name": "История России", + "infos": "Чубыкин Игорь Валерьевич|П-6" + } + }, + "fri": { + "9:00-10:30": { + "name": "Физическая культура", + "infos": "" + }, + "10:40-12:15": { + "name": "Безопасность жизнедеятельности", + "infos": "Сладкова Наталья Валерьевна|609" + }, + "12:50-14:25": { + "name": "Практикум на ЭВМ", + "infos": "Цыбров Евгений Германович|371|Кулагин Алексей Владимирович|МЗ-0" + } + } + }, + "103": { + "mon": { + "8:45-10:20": { + "name": "Алгоритмы и алгоритмические языки", + "infos": "Белеванцев Андрей Андреевич|П-6" + }, + "10:30-12:05": { + "name": "Математический анализ", + "infos": "Зайцева Наталья Владимировна|71" + }, + "12:50-14:25": { + "name": "Практикум на ЭВМ", + "infos": "Кузьменкова Евгения Анатольевна|731|Малышев Никита Евгеньевич|778" + }, + "15:00-16:30": { + "name": "Физическая культура", + "infos": "" + } + }, + "tue": { + "8:45-10:20": { + "name": "Консультация. Алгебра и геометрия", + "infos": "Будак Александр Борисович|612" + }, + "10:30-12:05": { + "name": "Алгебра и геометрия", + "infos": "Тыртышников Евгений Евгеньевич|П-6" + }, + "12:50-14:25": { + "name": "Математический анализ", + "infos": "Садовничая Инна Викторовна|П-6" + }, + "14:35-16:10": { + "name": "Английский язык", + "infos": "Плиева Сима Ивановна|783|Дзампова Татьяна Борисовна|736" + }, + "16:20-17:55": { + "name": "Английский язык", + "infos": "Дзампова Татьяна Борисовна|736" + } + }, + "wed": { + "8:45-10:20": { + "name": "Алгоритмы и алгоритмические языки", + "infos": "Белеванцев Андрей Андреевич|П-6" + }, + "10:30-12:05": { + "name": "Математический анализ", + "infos": "Зайцева Наталья Владимировна|72" + }, + "12:50-14:25": { + "name": "Алгебра и геометрия", + "infos": "Будак Александр Борисович|605" + } + }, + "thu": { + "8:45-10:20": { + "name": "Алгебра и геометрия", + "infos": "Тыртышников Евгений Евгеньевич|П-6" + }, + "10:30-12:05": { + "name": "Математический анализ", + "infos": "Садовничая Инна Викторовна|П-6" + }, + "12:50-14:25": { + "name": "Алгебра и геометрия", + "infos": "Будак Александр Борисович|605" + }, + "14:35-16:10": { + "name": "Английский язык", + "infos": "Плиева Сима Ивановна|783" + }, + "16:20-17:55": { + "name": "История России", + "infos": "Чубыкин Игорь Валерьевич|П-6" + } + }, + "fri": { + "9:00-10:30": { + "name": "Физическая культура", + "infos": "" + }, + "10:40-12:15": { + "name": "Безопасность жизнедеятельности", + "infos": "Гимишли Николай Федосеевич|614" + }, + "12:50-14:25": { + "name": "Практикум на ЭВМ", + "infos": "Кузьменкова Евгения Анатольевна|248|Малышев Никита Евгеньевич|780" + }, + "14:35-16:10": { + "name": "История России", + "infos": "Чубыкин Игорь Валерьевич|523" + } + } + }, + "105": { + "mon": { + "8:45-10:20": { + "name": "Алгоритмы и алгоритмические языки", + "infos": "Белеванцев Андрей Андреевич|П-6" + }, + "10:30-12:05": { + "name": "Математический анализ", + "infos": "Никитин Алексей Антонович|72" + }, + "12:15-13:40": { + "name": "Алгебра и геометрия", + "infos": "Лебедева Ольга Сергеевна|508|Замарашкин Николай Леонидович|508" + }, + "15:00-16:30": { + "name": "Физическая культура", + "infos": "" + } + }, + "tue": { + "10:30-12:05": { + "name": "Алгебра и геометрия", + "infos": "Тыртышников Евгений Евгеньевич|П-6" + }, + "12:50-14:25": { + "name": "Математический анализ", + "infos": "Садовничая Инна Викторовна|П-6" + }, + "14:35-16:10": { + "name": "Английский язык", + "infos": "Лаптинова Анастасия Ильинична|73|Кашелкина Ольга Александровна|790" + }, + "16:20-17:55": { + "name": "Практикум на ЭВМ", + "infos": "Русол Андрей Владимирович|МЗ-4|Гуляев Анатолий Викторович|574" + } + }, + "wed": { + "8:45-10:20": { + "name": "Алгоритмы и алгоритмические языки", + "infos": "Белеванцев Андрей Андреевич|П-6" + }, + "10:30-12:05": { + "name": "Математический анализ", + "infos": "Никитин Алексей Антонович|778" + }, + "12:50-14:25": { + "name": "Алгебра и геометрия", + "infos": "Лебедева Ольга Сергеевна|506|Замарашкин Николай Леонидович|506" + } + }, + "thu": { + "8:45-10:20": { + "name": "Алгебра и геометрия", + "infos": "Тыртышников Евгений Евгеньевич|П-6" + }, + "10:30-12:05": { + "name": "Математический анализ", + "infos": "Садовничая Инна Викторовна|П-6" + }, + "12:50-14:25": { + "name": "История России", + "infos": "Чубыкин Игорь Валерьевич|523" + }, + "14:35-16:10": { + "name": "Английский язык", + "infos": "Лаптинова Анастасия Ильинична|71|Кашелкина Ольга Александровна|736" + }, + "16:20-17:55": { + "name": "История России", + "infos": "Чубыкин Игорь Валерьевич|П-6" + } + }, + "fri": { + "9:00-10:30": { + "name": "Физическая культура", + "infos": "" + }, + "10:40-12:15": { + "name": "Консультация. Математический анализ", + "infos": "Никитин Алексей Антонович|72" + }, + "12:50-14:25": { + "name": "Практикум на ЭВМ", + "infos": "Русол Андрей Владимирович|МЗ-4|Гуляев Анатолий Викторович|574" + }, + "14:35-16:10": { + "name": "Безопасность жизнедеятельности", + "infos": "Гимишли Николай Федосеевич|614" + } + } + } +} \ No newline at end of file diff --git a/schedules.py b/schedules.py new file mode 100644 index 0000000..fe592e7 --- /dev/null +++ b/schedules.py @@ -0,0 +1,215 @@ +#!/usr/bin/python3.3 +import threading, telebot, schedule, time +import os, sys +from telebot import types +from telegram.constants import ParseMode +import for_json + +bot = telebot.TeleBot("API_TOKEN") +admin_id = 'ADMIN_ID' + +start_txt = 'Привет! Это бот, который будет кидать тебе сообщения перед нужной парой с номером кабинета/фамилией препода\ +\n\nCreated by: @Kr0sH\_512' + +@bot.message_handler(commands=['update']) +def update_schedules(message): + if (str(message.from_user.id) != admin_id): + bot.send_message(message.from_user.id, 'Команда доступна только администратору', parse_mode='Markdown') + else: + for_json.create_schedule_tasks() + + +@bot.message_handler(commands=['restart']) +def restart_bot(message): + if (str(message.from_user.id) != admin_id): + bot.send_message(message.from_user.id, 'Команда доступна только администратору', parse_mode='Markdown') + else: + bot.send_message(admin_id, '🛑 bye', parse_mode=ParseMode.HTML) + os.execv(sys.executable, ['python'] + sys.argv) + +@bot.message_handler(commands=['json']) +def send_json(message): + if (str(message.from_user.id) != admin_id): + bot.send_message(message.from_user.id, 'Команда доступна только администратору', parse_mode='Markdown') + else: + with open(for_json.path, 'rb') as json_file: + bot.send_document(admin_id, json_file) + with open(for_json.path_schedule, 'rb') as json_file: + bot.send_document(admin_id, json_file) + + +@bot.message_handler(commands=['start']) +def start(message): + if message.chat.type == "supergroup": + print(message.text) + print(message.chat.id) + print(message.text.split(' ')) + if len(message.text.split(' ')) != 2: + bot.send_message(message.chat.id, start_txt, parse_mode='Markdown') + bot.send_message(message.chat.id, 'Похоже, что этот бот добавлен в группу. Чтобы он присылал расписание в чат, \ + запустите его заново, указав вместе с /start@vmk_schedule_bot номер\_своей\_группы.\ + \nПример:\n/start@vmk_schedule_bot 102', parse_mode='Markdown') + else: + temp = message.text.split(' ')[1] + if temp.isdigit(): + infos = [ + message.chat.id, + message.chat.title, + '', + message.from_user.username, + temp + ] + if for_json.check_group_in_json(temp): + bot.send_message(message.chat.id, 'Отлично! Теперь я буду присылать вам расписание {} группы'.format(temp), parse_mode='Markdown') + else: + bot.send_message(message.chat.id, 'Похоже, что расписания для этой группы ещё не существует. \ + \nРазработчик уже пинается, но можете дополнительно написать ему: @Kr0sH\_512', parse_mode='Markdown') + send_message(admin_id, '🛑 В группе {} был запрос на {} группу.\ + \nid: {}'.format(message.chat.title, temp, message.chat.id)) + temp = 'other' + for_json.save_user(infos) + else: + bot.send_message(message.chat.id, 'Введено не число. Попробуйте снова.\ + \nПример:\n/start@vmk_schedule_bot 102', parse_mode='Markdown') + + return + bot.send_message(message.chat.id, start_txt, parse_mode='Markdown') + markup = types.InlineKeyboardMarkup() + markup.add(types.InlineKeyboardButton(text="102", callback_data="102")) + markup.add(types.InlineKeyboardButton(text="103", callback_data="103")) + markup.add(types.InlineKeyboardButton(text="105", callback_data="105")) + markup.add(types.InlineKeyboardButton(text="Моей группы нет в этом списке", callback_data="other")) + bot.send_message(message.chat.id, 'Пожалуйста, выбери свою группу', parse_mode='Markdown', reply_markup=markup) + +@bot.callback_query_handler(func=lambda call: True) +def callback_inline(call): + infos = [ + call.from_user.id, + call.from_user.first_name, + call.from_user.last_name, + call.from_user.username, + call.data + ] + for_json.save_user(infos) + if call.data == 'other': + bot.edit_message_text(chat_id=call.message.chat.id, + message_id=call.message.message_id, + text='Используй команду /request \ + и напиши номер группы, которую хочешь добавить\ + \nПосле создания расписания для твоей группы, я пришлю тебе сообщение', + parse_mode='Markdown') + else: + bot.edit_message_text(chat_id=call.message.chat.id, + message_id=call.message.message_id, + text='Отлично, теперь тебе будут приходить сообщения!', + parse_mode='Markdown') + + + +@bot.message_handler(commands=['help', 'faq']) +def help(message): + help_msg = 'Мои команды:\ + \n/start - используй, чтобы сменить номер группы.\ + \n/info - используй, чтобы узнать твои настройки бота\ + \n/pause - используй, чтобы прекратить получать сообщения от бота\ + \n/timeout - настрой время, когда бот будет присылать тебе сообщение\ + \n/request - используй, чтобы отправить разработчику какой-то запрос\ + \n\nИли же можно всегда написать напрямую: @Kr0sH\_512' + bot.send_message(message.chat.id, help_msg, parse_mode='Markdown') + if str(message.from_user.id) == admin_id and message.from_user.id == message.chat.id: + help_msg = '🛑 И команды только для админа:\ + \n/restart - перезапуск бота.\ + \n/update - обновление schedule задач\ + \n/json - получить файл пользователей и расписания\ + \n/info id\_пользователя - узнать настройки пользователя' + bot.send_message(message.from_user.id, help_msg, parse_mode='Markdown') + +@bot.message_handler(commands=['request']) +def request(message): + bot.send_message(message.from_user.id, 'Отправь мне сообщение и я перешлю его разработчику\ + \n(или напиши stop, чтобы отменить отправку)', parse_mode='Markdown') + bot.register_next_step_handler(message, send_request) + +def send_request(message): + if message.text == "stop" or message.text == "стоп" or message.text[0] == '/': + bot.send_message(message.from_user.id, 'Отмена отпраки', parse_mode='Markdown') + return + infos = [ + message.from_user.id, + message.from_user.first_name, + message.from_user.last_name, + message.from_user.username, + message.text + ] + + for i in range(len(infos)): + if type(infos[i]) == type(None): + infos[i] = '' + if '_' in str(infos[i]): + infos[i] = str(infos[i]).replace('_', '\_') + + text = '🛑 Сообщение от {} {} (@{}):\n\n{}\nid: {}'.format(infos[1], infos[2], infos[3], infos[4], infos[0]) + bot.send_message(admin_id, text, parse_mode='Markdown') + bot.send_message(message.from_user.id, 'Ваше сообщение успешно доставлено!', parse_mode='Markdown') + + + +@bot.message_handler(commands=['schedule']) ### На доработке +def send_schedule(message): + # команда для отправки всего расписания + bot.send_message(message.chat.id, 'Пожалуйста, притворись, что ты получил сейчас своё расписание на неделю\ + \n\n(Функция в разработке)', parse_mode='Markdown') + +@bot.message_handler(commands=['timeout']) +def set_timeout(message): + bot.send_message(message.chat.id, 'Пришли мне число от 1 до 60. \ + \nЭто будет количество минут, за которое я буду присылать тебе напоминание о уроке (По умолчанию: 10)', parse_mode='Markdown') + bot.register_next_step_handler(message, save_timeout) + +def save_timeout(message): + if message.text[0] == '/': + return + if str(message.text).isdigit() and int(message.text) <= 60 and int(message.text) >= 1: + for_json.change_user_param(str(message.chat.id), 'timeout', str(message.text)) + bot.send_message(message.chat.id, 'Хорошо, теперь ты будешь получать напоминания за {} минут до урока'.format(str(message.text)), parse_mode='Markdown') + else: + bot.send_message(message.chat.id, 'Пожалуйста, пришли число от 1 до 60. \nПо умолчанию: 10', parse_mode='Markdown') + bot.register_next_step_handler(message, save_timeout) + +@bot.message_handler(commands=['info']) +def send_info(message): + if len(message.text.split(' ')) == 2 and str(message.from_user.id) == admin_id: + bot.send_message(message.chat.id, '🛑 Окей, держи', parse_mode='Markdown') + text = for_json.return_infos(message.text.split(' ')[1]) + bot.send_message(message.chat.id, text, parse_mode=ParseMode.HTML) + return + bot.send_message(message.chat.id, 'Хорошо, вот твои настройки:', parse_mode='Markdown') + text = for_json.return_infos(str(message.chat.id)) + bot.send_message(message.chat.id, text, parse_mode=ParseMode.HTML) + +@bot.message_handler(commands=['pause']) +def pause_schedule(message): + for_json.change_user_param(str(message.chat.id), 'allow_message', 'no') + bot.send_message(message.chat.id, 'Рассылка сообщений преращена. \ + \nДля возобновления воспользуйтесь командой\n/start', parse_mode='Markdown') + +@bot.message_handler(content_types=['text']) +def text_message(message): + if message.chat.type == "supergroup": + return + bot.send_message(message.from_user.id, 'К сожалению, я ещё не умею обрабатывать сообщения.\ + \nИспользуй команды из меню или напиши /help.', parse_mode='Markdown') + +def send_message(id, text): + bot.send_message(id, text, parse_mode=ParseMode.HTML) + +if __name__ == '__main__': + for_json.create_schedule_tasks() + send_message(admin_id, '🛑 я перезапустился!') + print("-------------------------") + + threading.Thread(target=bot.infinity_polling, name='bot_infinity_polling', daemon=True).start() + + while True: + schedule.run_pending() + time.sleep(5) diff --git a/users_expl.json b/users_expl.json new file mode 100644 index 0000000..a56a3ae --- /dev/null +++ b/users_expl.json @@ -0,0 +1,10 @@ +{ + "856850518": { + "username": "kr0sh_512", + "first_name": "Дмитрий", + "last_name": "", + "group": "102", + "timeout": "12", + "allow_message": "yes" + } +} \ No newline at end of file