diff --git a/.gitignore b/.gitignore
index 71e586a..a14b345 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,13 @@
-
+__pycache__
users.json
schedule.json
-settings.json
+json/students.json
+json/schedule_2sem.json
+test_json
+json_remake
+script.py
+nohup.out
+config.yaml
+old_files/
+yaml_groups/*
+!yaml_groups/202.yaml
\ No newline at end of file
diff --git a/README.md b/README.md
index 5c6a447..eb259f0 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,81 @@
-# Telegram-bot-schedule
- Прямо сейчас бот работает здесь: https://t.me/vmk_schedule_bot
+# Telegram Bot Schedule
+This project is a Telegram bot designed to manage and display schedules. The bot can help users keep track of their daily activities, appointments, and events.
+
+## Features
+
+- View preloaded schedules
+- Group schedules for better organization
+- Receive reminders for upcoming events
+- User-friendly commands and interface
+
+## Installation
+
+1. Clone the repository:
+ ```sh
+ git clone https://github.com/yourusername/Telegram-bot-schedule.git
+ ```
+2. Navigate to the project directory:
+ ```sh
+ cd Telegram-bot-schedule
+ ```
+3. Install the required dependencies:
+ ```sh
+ pip install -r requirements.txt
+ ```
+
+## Usage
+
+1. Create a new bot on Telegram and get the API token.
+2. Set the API token in the environment variables or in a configuration file.
+3. You need to create schedules files for groups.
+4. Run the bot:
+ ```sh
+ python bot.py
+ ```
+
+## Commands
+
+- `/start` - используй, чтобы сменить номер группы.
+- `/schedule` - используй, чтобы получить расписание на сегодня.
+- `/random` - сделай очередь из людей
+- `/info` - используй, чтобы узнать твои настройки бота
+- `/pause` - используй, чтобы прекратить получать сообщения от бота
+- `/thread` - используй в нужном чате канала, чтобы бот отправлял сообщения именно туда
+- `/timeout` - настрой время, когда бот будет присылать тебе сообщение
+- `/request` - используй, чтобы отправить разработчику какой-то запрос
+- `/source` - Страница бота на Github
+- `/restart` - перезапуск бота (admin only).
+- `/update` - обновление schedule задач (admin only)
+- `/stats` - получание статистики (admin only)
+- `/json` - получить файл пользователей и расписания (admin only)
+- `/info` id_пользователя - узнать настройки пользователя (admin only)
+- `/spam` - сделать рассылку (admin only)
+- `/pause_all` - приостановить бота для всех (каникулы/выходные) (admin only)
+- `/stop` id_пользователя - приостановить отправку сообщений для пользователя (admin only)
+
+## Contributing
+
+Contributions are welcome! Please fork the repository and create a pull request with your changes.
+
+## Contact
+
+For any questions or suggestions, please open an issue or contact the project maintainer at [gudovdo@my.msu.ru].
+
+## Target Audience
+
+This bot is particularly useful for students to track their lessons and manage their academic schedules effectively.
+
+## Limitations
+
+- Cannot create or edit schedule entities directly
+- Only works with preloaded schedules and groups
+
+
+
+
+
+
+
+
+
+
diff --git a/admin.py b/admin.py
index bffd9e4..c47129e 100644
--- a/admin.py
+++ b/admin.py
@@ -1,12 +1,15 @@
import schedules as bot
-admin_id = '856850518'
+admin_id = "856850518"
+
def admin_command(func):
def wrapper(*args, **kwargs):
message = args[0]
if str(message.from_user.id) != admin_id:
- bot.send_message(message.from_user.id, 'Команда доступна только администратору')
+ bot.send_message(
+ message.from_user.id, "Команда доступна только администратору"
+ )
return
func(*args, **kwargs)
@@ -14,15 +17,20 @@ def admin_command(func):
return wrapper
+
def is_admin(message):
- if str(message.from_user.id) == admin_id and message.from_user.id == message.chat.id:
+ if (
+ str(message.from_user.id) == admin_id
+ and message.from_user.id == message.chat.id
+ ):
return True
-
+
return False
+
def send_admin_message(text):
- bot.send_message(admin_id, '🛑 ' + text)
-
+ bot.send_message(admin_id, "🛑 " + text)
+
+
def send_admin_document(file):
- bot.send_document(admin_id, file, '🛑 Admin file')
-
\ No newline at end of file
+ bot.send_document(admin_id, file, "🛑 Admin file")
diff --git a/convert_into_yaml.py b/convert_into_yaml.py
new file mode 100644
index 0000000..c664738
--- /dev/null
+++ b/convert_into_yaml.py
@@ -0,0 +1,40 @@
+import os
+import json
+import yaml
+
+
+def convert_json_to_yaml(json_dir, yaml_dir):
+ # Iterate over all files in the directory
+ for filename in os.listdir(json_dir):
+ if filename.endswith(".json"):
+ json_path = os.path.join(json_dir, filename)
+
+ # Read JSON file
+ with open(json_path, "r", encoding="utf-8") as json_file:
+ data = json.load(json_file)
+
+ # Convert to YAML
+ yaml_data = yaml.dump(
+ data,
+ default_flow_style=None,
+ encoding="utf-8",
+ allow_unicode=True,
+ width=float("inf"),
+ sort_keys=False,
+ )
+
+ # Write YAML file
+ yaml_path = os.path.join(yaml_dir, filename.replace(".json", ".yaml"))
+ with open(yaml_path, "wb") as yaml_file:
+ yaml_file.write(yaml_data)
+
+ print("Conversion completed.")
+
+
+if __name__ == "__main__":
+ json_dir = "json_remake"
+ yaml_dir = "yaml_groups"
+
+ convert_json_to_yaml(json_dir, yaml_dir)
+
+ pass
diff --git a/for_json.py b/for_json.py
index 03c3e5f..0edc58f 100644
--- a/for_json.py
+++ b/for_json.py
@@ -1,31 +1,34 @@
#!/usr/bin/python3.3
-import json, schedule
+import json, yaml, schedule
import schedules as bot
from datetime import datetime
-path_users = "json/users.json" # Нужный путь до json файлов
-path_schedule = "json/schedule.json"
+path_users = "json/users.json" # Нужный путь до json файлов
+path_schedule = "yaml_groups/{}.yaml"
+path_students = "json/students.json"
+path_groups = "json/groups.json"
allow_update = True
+
def save_user(infos):
for i in range(len(infos)):
if type(infos[i]) == type(None):
- infos[i] = ''
+ 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]
+ "id": infos[0],
+ "first_name": infos[1],
+ "last_name": infos[2],
+ "username": infos[3],
+ "group": infos[4],
}
-
+
data = {}
- with open(path_users, 'r', encoding='utf-8') as json_file:
+ with open(path_users, "r", encoding="utf-8") as json_file:
data = json.load(json_file)
-
+
data[infos["id"]] = {
"username": infos["username"],
"first_name": infos["first_name"],
@@ -33,162 +36,265 @@ def save_user(infos):
"group": infos["group"],
"timeout": "10",
"allow_message": "yes",
- "thread": "General"
+ "thread": "General",
}
- with open(path_users, 'w', encoding='utf-8') as json_file:
+ with open(path_users, "w", encoding="utf-8") as json_file:
json.dump(data, json_file, ensure_ascii=False, indent=4)
+
create_schedule_tasks()
+
return
+
def change_user_param(id, key, value):
id = str(id)
data = {}
- with open(path_users, 'r', encoding='utf-8') as json_file:
+ with open(path_users, "r", encoding="utf-8") as json_file:
data = json.load(json_file)
-
+
data[id][key] = value
- with open(path_users, 'w', encoding='utf-8') as json_file:
+ with open(path_users, "w", encoding="utf-8") as json_file:
json.dump(data, json_file, ensure_ascii=False, indent=4)
create_schedule_tasks()
+
+ # bot.send_admin_message(
+ # "Изменения:\
+ # \nuser: @{}\
+ # \nid: {}\
+ # \nkey: {}\
+ # \nvalue: {}".format(
+ # data[id]["username"], id, key, value
+ # )
+ # )
+
return
-def parse_lesson(time, lesson):
- text = ''
- start, end = time.split("-")
-
- if len(lesson["infos"].split('|')) == 2:
- teacher = lesson["infos"].split('|')[0]
- room = lesson["infos"].split('|')[1]
- text = '{}-{} | {}\
+
+def parse_lesson(lesson: dict[str, str]) -> str:
+ text = ""
+ start, end = lesson["begin"], lesson["end"]
+
+ if not lesson["name"]:
+ return ""
+
+ if len(lesson["teacher.room"]) == 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"])
+ \n{}".format(
+ start,
+ end,
+ lesson["teacher.room"][0]["r"],
+ lesson["name"],
+ lesson["teacher.room"][0]["t"],
+ )
else:
- print("что-то не так")
- print(lesson["name"])
-
+ text = "{}-{}\
+ \n{}".format(
+ start,
+ end,
+ lesson["name"],
+ )
+
+ for tr in lesson["teacher.room"]:
+ if not tr["t"] and not tr["r"]:
+ continue
+ text += "\n({}) {}".format(tr["r"], tr["t"])
+
return text
+
def create_schedule_tasks(manual=False):
global allow_update
+
if not manual:
- bot.send_admin_message('Произошёл auto-update')
if not allow_update:
return
-
+
+ # bot.send_admin_message("Произошёл auto-update")
+
allow_update = True
-
+
schedule.clear()
users = {}
schdl = {}
- with open(path_users, 'r', encoding='utf-8') as json_file:
+ with open(path_users, "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():
- if params['allow_message'] != 'yes':
+ if params["allow_message"] != "yes":
continue
- group = params['group']
- if group == 'other':
+ 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"] == "": # Неправильный формат schedule
+
+ with open(path_schedule.format(group), "r", encoding="utf-8") as json_file:
+ # schdl = json.load(json_file)["schedule"]
+ schdl = yaml.safe_load(json_file)["schedule"]
+
+ for day in schdl:
+ for lesson in schdl[day]:
+ if not lesson["name"]: # Неправильный формат schedule
continue
-
- start = i.split("-")[0]
- text = parse_lesson(i, lesson)
-
- if text == '':
+
+ start = lesson["begin"]
+ text = parse_lesson(lesson)
+
+ if not text:
continue
-
+
thread_id = params["thread"]
-
- 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) + ":"
+
+ 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, thread_id)
- elif day == 'tue':
- schedule.every().tuesday.at(start_task).do(bot.send_message, id, text, thread_id)
- elif day == 'wed':
- schedule.every().wednesday.at(start_task).do(bot.send_message, id, text, thread_id)
- elif day == 'thu':
- schedule.every().thursday.at(start_task).do(bot.send_message, id, text, thread_id)
- elif day == 'fri':
- schedule.every().friday.at(start_task).do(bot.send_message, id, text, thread_id)
- elif day == 'sat':
- schedule.every().saturday.at(start_task).do(bot.send_message, id, text, thread_id)
-
+
+ if day == "mon":
+ schedule.every().monday.at(start_task).do(
+ bot.send_message, id, text, thread_id, lesson["parity"]
+ )
+ elif day == "tue":
+ schedule.every().tuesday.at(start_task).do(
+ bot.send_message, id, text, thread_id, lesson["parity"]
+ )
+ elif day == "wed":
+ schedule.every().wednesday.at(start_task).do(
+ bot.send_message, id, text, thread_id, lesson["parity"]
+ )
+ elif day == "thu":
+ schedule.every().thursday.at(start_task).do(
+ bot.send_message, id, text, thread_id, lesson["parity"]
+ )
+ elif day == "fri":
+ schedule.every().friday.at(start_task).do(
+ bot.send_message, id, text, thread_id, lesson["parity"]
+ )
+ elif day == "sat":
+ schedule.every().saturday.at(start_task).do(
+ bot.send_message, id, text, thread_id, lesson["parity"]
+ )
+
return
-def groups_in_json():
- schdl = {}
- with open(path_schedule, 'r', encoding='utf-8') as json_file:
- schdl = json.load(json_file)
-
- return schdl.keys()
-def return_infos(id):
+def groups_in_json() -> list[str]:
+ groups = {}
+ with open(path_groups, "r", encoding="utf-8") as json_file:
+ groups = json.load(json_file)
+
+ return groups
+
+
+def students_in_group(group) -> list[str]:
+ group = str(group)
+
+ data = {}
+ with open(path_users, "r", encoding="utf-8") as json_file:
+ data = json.load(json_file)
+
+ students = []
+
+ for i in data.keys():
+ if data[i]["group"] == group:
+ students.append(i)
+
+ return students
+
+
+def students_in_json(id: str, key: str = "") -> list[str] | None:
+ id = str(id)
+
+ group = {}
+ with open(path_users, "r", encoding="utf-8") as json_file:
+ group = json.load(json_file)
+ group = group[id]["group"]
+
+ stud = {}
+ with open(path_students, "r", encoding="utf-8") as json_file:
+ stud = json.load(json_file)
+ stud = stud.get(group)
+
+ if stud == None:
+ return None
+
+ if key == "":
+ return list(stud.keys())
+
+ return stud[key]
+
+
+def return_infos(id) -> dict[str, str] | None:
id = str(id)
data = {}
- with open(path_users, 'r', encoding='utf-8') as json_file:
+ with open(path_users, "r", encoding="utf-8") as json_file:
data = json.load(json_file)
- data = data[id]
-
+ data = data.get(id)
+
return data
+
def pause_bot():
- schedule.clear()
global allow_update
- allow_update = False
-
+
+ if allow_update:
+ schedule.clear()
+ allow_update = False
+ bot.send_admin_message("Бот больше не отправляет расписание")
+ else:
+ create_schedule_tasks(True)
+ allow_update = True
+ bot.send_admin_message("Бот возобновил рассылку!")
+
return
-def get_schedule(id, day):
+
+def get_schedule(id: str, day: str) -> str:
id = str(id)
- if day == 'sun':
- day = 'mon'
- days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat']
- russian_days = ['понедельник', 'вторник', 'среду', 'четверг', 'пятницу', 'субботу']
-
- text = 'Расписание на {}:\n\n'.format(russian_days[days.index(day)])
+
+ if day == "sun":
+ day = "mon"
+
+ days = ["mon", "tue", "wed", "thu", "fri", "sat"]
+ russian_days = ["понедельник", "вторник", "среду", "четверг", "пятницу", "субботу"]
+
+ text = "Расписание на {}:\n\n".format(russian_days[days.index(day)])
schdl_today = {}
- with open(path_schedule, 'r', encoding='utf-8') as schedule_file:
- group = ''
- with open(path_users, 'r', encoding='utf-8') as user_file:
- group = json.load(user_file)[id]['group']
-
- if (group == 'other'):
- return 'У тебя не выбрана группа для рассылки сообщений'
-
- try:
- schdl_today = json.load(schedule_file)[group][day]
- except:
- return 'Расписания твоей группы на {} нет'.format(russian_days[days.index(day)])
-
- for i, lesson in schdl_today.items():
- text += '•' + parse_lesson(i, lesson) + '\n\n'
-
+
+ group = ""
+ with open(path_users, "r", encoding="utf-8") as user_file:
+ group = json.load(user_file)[id]["group"]
+
+ if group == "other":
+ return "У тебя не выбрана группа для рассылки сообщений"
+
+ try:
+ with open(path_schedule.format(group), "r", encoding="utf-8") as schedule_file:
+ try:
+ # schdl_today = json.load(schedule_file)["schedule"][day]
+ schdl_today = yaml.safe_load(schedule_file)["schedule"][day]
+ except:
+ return "Расписания твоей группы на {} нет".format(
+ russian_days[days.index(day)]
+ )
+
+ for lesson in schdl_today:
+ str_lesson = parse_lesson(lesson)
+ if str_lesson:
+ text += "•" + str_lesson + "\n\n"
+ except:
+ return "Расписания твоей группы нет"
+
return text
+
+
+if __name__ == "__main__":
+ print(groups_in_json())
+
+ pass
diff --git a/json/groups.json b/json/groups.json
new file mode 100644
index 0000000..f77e36a
--- /dev/null
+++ b/json/groups.json
@@ -0,0 +1,46 @@
+[
+ "101",
+ "102",
+ "103",
+ "104",
+ "105",
+ "106",
+ "107",
+ "108",
+ "109",
+ "110",
+ "111",
+ "112",
+ "113",
+ "114",
+ "115",
+ "116",
+ "117",
+ "118",
+ "119",
+ "120",
+ "141",
+ "142",
+ "201",
+ "202",
+ "203",
+ "204",
+ "205",
+ "206",
+ "219",
+ "207",
+ "208",
+ "209",
+ "210",
+ "211",
+ "212",
+ "213",
+ "214",
+ "215",
+ "216",
+ "217",
+ "218",
+ "220",
+ "241",
+ "242"
+]
\ No newline at end of file
diff --git a/json/schedule_expl.json b/json/schedule_expl.json
deleted file mode 100644
index 1ae3328..0000000
--- a/json/schedule_expl.json
+++ /dev/null
@@ -1,282 +0,0 @@
-{
- "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/json/users_expl.json b/json/users_expl.json
index 6957ce4..16f7c68 100644
--- a/json/users_expl.json
+++ b/json/users_expl.json
@@ -3,8 +3,8 @@
"username": "kr0sh_512",
"first_name": "Дмитрий",
"last_name": "",
- "group": "102",
- "timeout": "12",
+ "group": "117",
+ "timeout": "10",
"allow_message": "yes",
"thread": "General"
}
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..47f0fd0
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,4 @@
+python-telegram-bot==13.7
+requests==2.26.0
+python-dotenv==0.19.0
+schedule==1.1.0
\ No newline at end of file
diff --git a/schedules.py b/schedules.py
index c77a709..a093dd3 100644
--- a/schedules.py
+++ b/schedules.py
@@ -1,5 +1,5 @@
#!/usr/bin/python3.3
-import threading, telebot, schedule, time
+import threading, telebot, schedule, time, random, yaml
from datetime import datetime
import os, sys
from telebot import types
@@ -7,44 +7,52 @@ from telegram.constants import ParseMode
import for_json
from admin import admin_command, is_admin, send_admin_message, send_admin_document
-bot = telebot.TeleBot("TOKEN_API")
+config = yaml.safe_load(open("config.yaml"))
+bot = telebot.TeleBot(config["test_token"])
+
+parity_FIRST = 1
-
-@bot.message_handler(commands=['help', 'faq'])
+@bot.message_handler(commands=["help", "faq"])
def help(message):
- help_msg = 'Мои команды:\
+ help_msg = "Мои команды:\
\n/start - используй, чтобы сменить номер группы.\
\n/schedule - используй, чтобы получить расписание на сегодня.\
+ \n/random - сделай очередь из людей\
\n/info - используй, чтобы узнать твои настройки бота\
\n/pause - используй, чтобы прекратить получать сообщения от бота\
\n/thread - используй в нужном чате канала, чтобы бот отправлял сообщения именно туда\
\n/timeout - настрой время, когда бот будет присылать тебе сообщение\
\n/request - используй, чтобы отправить разработчику какой-то запрос\
\n/source - Страница бота на Github\
- \n\nИли же можно всегда написать напрямую: @Kr0sH_512'
-
+ \n\nИли же можно всегда написать напрямую: @Kr0sH_512"
+
send_message(message.chat.id, help_msg)
-
+
if is_admin(message):
- admin_help_msg = 'И команды только для админа:\
+ admin_help_msg = "И команды только для админа:\
\n/restart - перезапуск бота.\
\n/update - обновление schedule задач\
+ \n/stats - получание статистики\
\n/json - получить файл пользователей и расписания\
\n/info id_пользователя - узнать настройки пользователя\
+ \n/spam - сделать рассылку\
\n/pause_all - приостановить бота для всех (каникулы/выходные)\
- \n/stop id_пользователя - приостановить отправку сообщений для пользователя'
+ \n/stop id_пользователя - приостановить отправку сообщений для пользователя"
send_admin_message(admin_help_msg)
-
+
return
+
### --//--
-@bot.message_handler(commands=['test'])
+
+@bot.message_handler(commands=["test", "t"])
@admin_command
-def update_schedules(message):
+def test(message):
text = 'Жирный текст\
\nКурсивный текст\
+ \nПодчёркнутый\
\nПеречёркнутый текст\
\nСсылка\
\nМоноширинный текст\
@@ -54,329 +62,673 @@ def update_schedules(message):
return
-@bot.message_handler(commands=['restart'])
+
+@bot.message_handler(commands=["restart", "r"])
@admin_command
def restart_bot(message):
- send_admin_message('bye')
- os.execv(sys.executable, ['python'] + sys.argv)
+ send_admin_message("bye")
+ os.execv(sys.executable, ["python3", "-u"] + sys.argv)
-@bot.message_handler(commands=['update'])
+
+@bot.message_handler(commands=["update"])
@admin_command
def update_schedules(message):
for_json.create_schedule_tasks(manual=True)
- send_admin_message('Произошёл update')
+ send_admin_message("Произошёл update")
return
-
-@bot.message_handler(commands=['json'])
+
+
+@bot.message_handler(commands=["stats"])
+@admin_command
+def send_stat(message):
+ text = "Статистика:\
+ \n(группа: всего/откл. увед./беседы)"
+
+ sum_users = 0
+ sum_dis_not = 0
+ sum_chats = 0
+
+ groups = list(for_json.groups_in_json())
+ groups.append("other")
+
+ for i in groups:
+ users = for_json.students_in_group(i)
+ sum_users += len(users)
+
+ dis_not = len(
+ [
+ i
+ for i, x in enumerate(users)
+ if for_json.return_infos(x)["allow_message"] == "no"
+ ]
+ )
+ sum_dis_not += dis_not
+
+ chats = len([i for i, x in enumerate(users) if x[0] == "-"])
+ sum_chats += chats
+
+ text += "\n{}: {} / {} / {}".format(i, len(users), dis_not, chats)
+
+ text += "\n\nВсего: {} / {} / {}".format(sum_users, sum_dis_not, sum_chats)
+
+ send_admin_message(text)
+
+ return
+
+
+@bot.message_handler(commands=["json"])
@admin_command
def send_json(message):
- with open(for_json.path_users, 'rb') as json_file:
+ with open(for_json.path_users, "rb") as json_file:
send_admin_document(json_file)
- with open(for_json.path_schedule, 'rb') as json_file:
+ with open(for_json.path_schedule, "rb") as json_file:
send_admin_document(json_file)
-
+ with open(for_json.path_students, "rb") as json_file:
+ send_admin_document(json_file)
+
return
+
# info user_id
-@bot.message_handler(commands=['pause_all'])
+
+@bot.message_handler(commands=["spam"])
+@admin_command
+def spam(message):
+ send_admin_message(
+ "Пришли мне id, номер группы или all для рассылки сообщения этим пользователям"
+ )
+
+ bot.register_next_step_handler(message, spam_msg)
+
+ return
+
+
+def spam_msg(message):
+ if message.text == "stop" or message.text == "стоп" or message.text[0] == "/":
+ send_admin_message("Отмена отправки")
+ return
+
+ send_admin_message("Пришли мне текст для рассылки сообщения этим пользователям")
+
+ bot.register_next_step_handler(message, spam_cnf, message.text)
+
+ return
+
+
+def spam_cnf(message, data):
+ if message.text == "stop" or message.text == "стоп" or message.text[0] == "/":
+ send_admin_message("Отмена отправки")
+ return
+
+ global text_spam
+ text_spam = message.text
+
+ text = "Пожалуйста, проверь итоговое сообщение и подтверди отправку:\
+ \n\nКому: "
+
+ if data == "all":
+ text += "всем"
+ elif data in for_json.groups_in_json():
+ text += "{} группе".format(data)
+ elif for_json.return_infos(data) != None:
+ text += "пользователю @{}".format(for_json.return_infos(data)["username"])
+ else:
+ send_admin_message("Ошибка при выборе пользователей")
+ return
+
+ text += "\n\nСообщение: {}".format(message.text)
+
+ markup = types.InlineKeyboardMarkup()
+
+ markup.add(
+ types.InlineKeyboardButton(text="✅", callback_data="spam#{}".format(data)),
+ types.InlineKeyboardButton(text="❌", callback_data="spam_no"),
+ )
+
+ bot.send_message(
+ message.from_user.id, text, parse_mode=ParseMode.HTML, reply_markup=markup
+ )
+
+ return
+
+
+@bot.callback_query_handler(func=lambda call: "spam" in call.data)
+def spam_send(call):
+ if call.data == "spam_no":
+ send_admin_message("Отмена отправки")
+ return
+
+ tmp, data = call.data.split("#")
+
+ global text_spam
+ text = text_spam
+
+ users = []
+
+ if data == "all":
+ groups = for_json.groups_in_json()
+ for group in groups:
+ users += for_json.students_in_group(group)
+ users += for_json.students_in_group("other")
+ elif data in for_json.groups_in_json():
+ users = for_json.students_in_group(data)
+ elif for_json.return_infos(data) != None:
+ users = [data]
+
+ for i in users:
+ send_message(i, text)
+
+ bot.edit_message_text(
+ chat_id=call.message.chat.id,
+ message_id=call.message.message_id,
+ text="Успешно!",
+ parse_mode=ParseMode.HTML,
+ )
+
+ return
+
+
+@bot.message_handler(commands=["pause_all"])
@admin_command
def pause_bot(message):
for_json.pause_bot()
- send_admin_message('Бот больше не отправляет расписание')
-
+
return
-@bot.message_handler(commands=['stop'])
+
+@bot.message_handler(commands=["stop"])
@admin_command
-def pause_bot(message):
- if len(str(message.text).split(' ')) != 2:
- send_admin_message('Эта команда вида /stop id_пользователя')
+def stop_msg(message):
+ if len(str(message.text).split(" ")) != 2:
+ send_admin_message("Эта команда вида /stop id_пользователя")
return
- for_json.change_user_param(str(message.text).split(' ')[1], 'allow_message', 'no')
- send_admin_message('Успешно')
+
+ for_json.change_user_param(str(message.text).split(" ")[1], "allow_message", "no")
+ send_admin_message("Успешно")
+
return
-### --//--
-@bot.message_handler(commands=['start'])
+### --//--
+
+
+@bot.message_handler(commands=["start"])
def start(message):
- start_txt = 'Привет! Это бот, который будет кидать тебе сообщения перед нужной парой с номером кабинета/фамилией препода\
+ start_txt = "Привет! Это бот, который будет кидать тебе сообщения перед нужной парой с номером кабинета/фамилией препода\
\n\nТы можешь настроить отправку сообщений в лс или добавить меня в группу, куда я буду присылать расписание\
-\n\nCreated by: @Kr0sH_512'
- if message.chat.type == "supergroup":
- if len(message.text.split(' ')) != 2:
+\n\nCreated by: @Kr0sH_512"
+ if message.chat.type == "supergroup":
+ if len(message.text.split(" ")) != 2:
send_message(message.chat.id, start_txt)
- send_message(message.chat.id, 'Похоже, что этот бот добавлен в группу. Чтобы он присылал расписание в чат, \
+ send_message(
+ message.chat.id,
+ "Похоже, что этот бот добавлен в группу. Чтобы он присылал расписание в чат, \
укажите вместе с /start@vmk_schedule_bot номер своей группы.\
- \nПример:\n/start@vmk_schedule_bot 102')
+ \nПример:\n/start@vmk_schedule_bot 102",
+ )
else:
- temp = message.text.split(' ')[1]
-
+ temp = message.text.split(" ")[1]
+
if temp.isdigit():
infos = [
- message.chat.id,
- message.chat.title,
- '',
+ message.chat.id,
+ message.chat.title,
+ "",
message.from_user.username,
- temp
+ temp,
]
-
+
if temp in for_json.groups_in_json():
- send_message(message.chat.id,
- 'Отлично! Теперь я буду присылать вам расписание {} группы'.format(temp))
+ send_message(
+ message.chat.id,
+ "Отлично! Теперь я буду присылать вам расписание {} группы".format(
+ temp
+ ),
+ )
else:
- send_message(message.chat.id, 'Похоже, что расписания для этой группы ещё не существует. \
- \nРазработчик уже пинается, но можете дополнительно написать ему: @Kr0sH_512')
-
- send_admin_message('В группе {} был запрос на {} группу.\
- \nid: {}'.format(message.chat.title, temp, message.chat.id))
- temp = 'other'
+ send_message(
+ message.chat.id,
+ "Похоже, что расписания для этой группы ещё не существует. \
+ \nРазработчик уже пинается, но можете дополнительно написать ему: @Kr0sH_512",
+ )
+
+ send_admin_message(
+ "В группе {} был запрос на {} группу.\
+ \nid: {}".format(
+ message.chat.title, temp, message.chat.id
+ )
+ )
+ temp = "other"
for_json.save_user(infos)
else:
- send_message(message.chat.id, 'Введено не число. Попробуйте снова.\
- \nПример:\n/start@vmk_schedule_bot 102')
+ send_message(
+ message.chat.id,
+ "Введено не число. Попробуйте снова.\
+ \nПример:\n/start@vmk_schedule_bot 102",
+ )
return
-
+
send_message(message.chat.id, start_txt)
-
+
markup = types.InlineKeyboardMarkup()
- for i in for_json.groups_in_json():
- markup.add(types.InlineKeyboardButton(text=i, callback_data=i))
- markup.add(types.InlineKeyboardButton(text="Моей группы нет в этом списке", callback_data="other"))
- bot.send_message(message.chat.id, 'Пожалуйста, выбери свою группу', parse_mode=ParseMode.HTML, reply_markup=markup)
-
+ # for i in for_json.groups_in_json():
+ # markup.add(types.InlineKeyboardButton(text=i, callback_data=i))
+ markup.add(types.InlineKeyboardButton(text="1 курс", callback_data="1course"))
+ markup.add(types.InlineKeyboardButton(text="2 курс", callback_data="2course"))
+
+ bot.send_message(
+ message.chat.id,
+ "Пожалуйста, выбери свой курс",
+ parse_mode=ParseMode.HTML,
+ reply_markup=markup,
+ )
+
return
-@bot.callback_query_handler(func=lambda call: not(call.data in ['left', 'right']))
+
+@bot.callback_query_handler(
+ func=lambda call: call.data in for_json.groups_in_json()
+ or call.data in ["other", "1course", "2course"]
+)
def callback_inline(call):
+ if "course" in call.data:
+ course = call.data[0]
+
+ markup = types.InlineKeyboardMarkup()
+ for i in [i for i in for_json.groups_in_json() if i[0] == course]:
+ markup.add(types.InlineKeyboardButton(text=i, callback_data=i))
+
+ markup.add(
+ types.InlineKeyboardButton(
+ text="Моей группы нет в этом списке", callback_data="other"
+ )
+ )
+
+ bot.edit_message_text(
+ text="Пожалуйста, выбери свою группу",
+ chat_id=call.message.chat.id,
+ message_id=call.message.message_id,
+ reply_markup=markup,
+ )
+
+ # bot.edit_message_reply_markup(
+ # call.message.chat.id, call.message.message_id, reply_markup=markup
+ # )
+
+ return
+
infos = [
- call.from_user.id,
- call.from_user.first_name,
- call.from_user.last_name,
- call.from_user.username,
- call.data
- ]
-
+ 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=ParseMode.HTML)
+
+ 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=ParseMode.HTML,
+ )
else:
- bot.edit_message_text(chat_id=call.message.chat.id,
- message_id=call.message.message_id,
- text='Отлично, теперь тебе будут приходить сообщения!',
- parse_mode=ParseMode.HTML)
-
+ bot.edit_message_text(
+ chat_id=call.message.chat.id,
+ message_id=call.message.message_id,
+ text="Отлично, теперь тебе будут приходить сообщения!",
+ parse_mode=ParseMode.HTML,
+ )
+
return
-
-@bot.message_handler(commands=['schedule'])
+@bot.message_handler(commands=["schedule"])
def send_schedule(message):
- text = 'К сожалению, бот не может отправить тебе расписание твоей группы на сегодня :('
+ text = (
+ "К сожалению, бот не может отправить тебе расписание твоей группы на сегодня :("
+ )
try:
- day = datetime.today().strftime('%A').lower()[:3] # mon tue ...
+ day = datetime.today().strftime("%A").lower()[:3] # mon tue ...
text = for_json.get_schedule(message.chat.id, day)
except Exception as e:
- send_admin_message('Schedule error from: {} \n\n {}'.format(message.chat.id, e))
-
+ # send_admin_message(
+ # "Schedule error from: {} \n\n {}".format(message.chat.id, str(e))
+ # )
+ bot.send_message(
+ message.chat.id,
+ "Пожалуйста, проверь, что ты зарегестрировался с помощью команды /start",
+ ParseMode.HTML,
+ message_thread_id=message.message_thread_id,
+ )
+
markup = types.InlineKeyboardMarkup()
- markup.add(types.InlineKeyboardButton(text="◀️", callback_data="left"),
- types.InlineKeyboardButton(text="▶️", callback_data="right"))
- bot.send_message(message.chat.id, text, ParseMode.HTML, reply_markup=markup)
-
+ markup.add(
+ types.InlineKeyboardButton(text="◀️", callback_data="left"),
+ types.InlineKeyboardButton(text="▶️", callback_data="right"),
+ )
+ bot.send_message(
+ message.chat.id,
+ text,
+ ParseMode.HTML,
+ reply_markup=markup,
+ message_thread_id=message.message_thread_id,
+ )
+
return
-
-@bot.callback_query_handler(func=lambda call: call.data in ['left', 'right'])
+
+
+@bot.callback_query_handler(func=lambda call: call.data in ["left", "right"])
def change_schedule(call):
- days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat']
- russian_days = ['понедельник', 'вторник', 'среду', 'четверг', 'пятницу', 'субботу']
- i = 6 # выходной
+ days = ["mon", "tue", "wed", "thu", "fri", "sat"]
+ russian_days = ["понедельник", "вторник", "среду", "четверг", "пятницу", "субботу"]
+ i = 6 # выходной
for day in russian_days:
if day in call.message.text:
i = russian_days.index(day)
break
-
- delta = (1) if (call.data == 'right') else (-1)
+
+ delta = (1) if (call.data == "right") else (-1)
ind = ((i + delta) % 6) if (i + delta > 0) else (i + delta)
-
+
text = for_json.get_schedule(call.message.chat.id, days[ind])
-
+
markup = types.InlineKeyboardMarkup()
- markup.add(types.InlineKeyboardButton(text="◀️", callback_data="left"),
- types.InlineKeyboardButton(text="▶️", callback_data="right"))
-
- bot.edit_message_text(text, call.message.chat.id, call.message.message_id,
- parse_mode=ParseMode.HTML, reply_markup=markup)
-
+ markup.add(
+ types.InlineKeyboardButton(text="◀️", callback_data="left"),
+ types.InlineKeyboardButton(text="▶️", callback_data="right"),
+ )
+
+ bot.edit_message_text(
+ text,
+ call.message.chat.id,
+ call.message.message_id,
+ parse_mode=ParseMode.HTML,
+ reply_markup=markup,
+ )
+
return
+@bot.message_handler(commands=["random"])
+def random_people(message):
+ list_of_num = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6", "7", "8", "9"]
-@bot.message_handler(commands=['info'])
+ list_of_var = for_json.students_in_json(message.chat.id)
+
+ text = "Для вашей группы эта команда не настроена.\n\nНапиши запрос через /request"
+
+ if list_of_var == None:
+ send_message(message.chat.id, text)
+ send_admin_message(
+ "Запрос на random команду от {}".format(
+ for_json.return_infos(message.chat.id)["group"]
+ )
+ )
+
+ return
+
+ text = "• Выбери как именно мне перемешать вас:\n"
+
+ l = []
+ for i, val in enumerate(list_of_var):
+ text += "\n{} {}".format(list_of_num[i], val)
+ l.append(
+ types.InlineKeyboardButton(text=list_of_num[i], callback_data="rand#" + val)
+ )
+
+ l = [l]
+
+ markup = types.InlineKeyboardMarkup(l)
+ bot.send_message(message.chat.id, text, ParseMode.HTML, reply_markup=markup)
+
+ return
+
+
+@bot.callback_query_handler(func=lambda call: "rand#" in call.data)
+def make_random(call):
+ list_of_stud = for_json.students_in_json(
+ call.message.chat.id, call.data.split("#")[1]
+ )
+
+ random.shuffle(list_of_stud)
+
+ text = "{}:\n\n".format(call.data.split("#")[1])
+
+ for i, name in enumerate(list_of_stud):
+ text += "{}{}. {}\n".format(" " if i + 1 < 10 else "", i + 1, name)
+
+ bot.edit_message_text(
+ "Хорошо, вот ваше распределение!",
+ call.message.chat.id,
+ call.message.message_id,
+ parse_mode=ParseMode.HTML,
+ )
+
+ send_message(call.message.chat.id, text)
+
+ return
+
+
+@bot.message_handler(commands=["info"])
def send_info(message):
- if len(message.text.split(' ')) == 2 and is_admin(message):
- send_admin_message('Окей, держи настройки {}'.format(message.text.split(' ')[1]))
- infos = for_json.return_infos(message.text.split(' ')[1])
- text = 'Никнейм: @{}\
+ if len(message.text.split(" ")) == 2 and is_admin(message):
+ send_admin_message(
+ "Окей, держи настройки {}".format(message.text.split(" ")[1])
+ )
+ infos = for_json.return_infos(message.text.split(" ")[1])
+ text = "Никнейм: @{}\
\nИмя: {} {}\
\nВыбранная группа: {}\
\nВремя напоминания до урока: {}\
- \nРазрешены ли напоминания: {}'.format(infos['username'], infos['first_name'], infos['last_name'],
- (infos['group'] if infos['group'] != 'other' else 'не выбрана'),
- infos['timeout'],
- ('да' if infos['allow_message'] == 'yes' else 'нет'))
+ \nРазрешены ли напоминания: {}".format(
+ infos["username"],
+ infos["first_name"],
+ infos["last_name"],
+ (infos["group"] if infos["group"] != "other" else "не выбрана"),
+ infos["timeout"],
+ ("да" if infos["allow_message"] == "yes" else "нет"),
+ )
send_admin_message(text)
return
-
- send_message(message.chat.id, 'Хорошо, вот твои настройки:')
+
+ send_message(message.chat.id, "Хорошо, вот твои настройки:")
infos = for_json.return_infos(message.chat.id)
- text = 'Выбранная группа: {}\
+ text = "Выбранная группа: {}\
\nВремя напоминания до урока: {}\
- \nРазрешены ли напоминания: {}'.format((infos['group'] if infos['group'] != 'other' else 'не выбрана'),
- infos['timeout'],
- ('да' if infos['allow_message'] == 'yes' else 'нет'))
+ \nРазрешены ли напоминания: {}".format(
+ (infos["group"] if infos["group"] != "other" else "не выбрана"),
+ infos["timeout"],
+ ("да" if infos["allow_message"] == "yes" else "нет"),
+ )
send_message(message.chat.id, text)
-
+
return
-
-@bot.message_handler(commands=['pause'])
+@bot.message_handler(commands=["pause"])
def pause_schedule(message):
- infos = for_json.return_infos(message.chat.id)['allow_message']
-
- if infos == 'yes':
- for_json.change_user_param(str(message.chat.id), 'allow_message', 'no')
- send_message(message.chat.id, 'Рассылка сообщений преращена. \
- \nДля возобновления воспользуйтесь командой\n/pause')
+ infos = for_json.return_infos(message.chat.id)["allow_message"]
+
+ if infos == "yes":
+ for_json.change_user_param(str(message.chat.id), "allow_message", "no")
+ send_message(
+ message.chat.id,
+ "Рассылка сообщений прекращена. \
+ \nДля возобновления воспользуйтесь командой\n/pause",
+ )
else:
- for_json.change_user_param(str(message.chat.id), 'allow_message', 'yes')
- send_message(message.chat.id, 'Рассылка сообщений возоблена!')
-
+ for_json.change_user_param(str(message.chat.id), "allow_message", "yes")
+ send_message(message.chat.id, "Рассылка сообщений возоблена!")
+
return
-
-
-
-@bot.message_handler(commands=['thread'])
+
+
+@bot.message_handler(commands=["thread"])
def change_thread(message):
- thread_id = ''
-
+ thread_id = ""
+
try:
thread_id = message.reply_to_message.message_thread_id
except AttributeError:
thread_id = "General"
-
- for_json.change_user_param(str(message.chat.id), 'thread', thread_id)
-
- send_message(message.chat.id, 'Хорошо, теперь я буду отправлять сообщения в этот чат', thread_id)
-
+
+ for_json.change_user_param(str(message.chat.id), "thread", thread_id)
+
+ send_message(
+ message.chat.id,
+ "Хорошо, теперь я буду отправлять сообщения в этот чат",
+ thread_id,
+ )
+
return
-
-@bot.message_handler(commands=['timeout'])
+@bot.message_handler(commands=["timeout"])
def set_timeout(message):
- send_message(message.chat.id, 'Пришли мне число от 1 до 60. \
- \nЭто будет количество минут, за которое я буду присылать тебе напоминание о уроке (По умолчанию: 10)')
+ send_message(
+ message.chat.id,
+ "Пришли мне число от 1 до 59. \
+ \nЭто будет количество минут, за которое я буду присылать тебе напоминание о паре (По умолчанию: 10)",
+ )
bot.register_next_step_handler(message, save_timeout)
-
+
return
+
def save_timeout(message):
- if str(message.text).isdigit() and int(message.text) <= 60 and int(message.text) >= 1:
- for_json.change_user_param(message.chat.id, 'timeout', str(message.text))
- send_message(message.chat.id,
- 'Хорошо, теперь ты будешь получать напоминания за {} минут до урока'.format(str(message.text)))
+ if (
+ str(message.text).isdigit()
+ and int(message.text) <= 59
+ and int(message.text) >= 1
+ ):
+ for_json.change_user_param(message.chat.id, "timeout", str(message.text))
+ send_message(
+ message.chat.id,
+ "Хорошо, теперь ты будешь получать напоминания за {} минут до урока".format(
+ str(message.text)
+ ),
+ )
else:
- send_message(message.chat.id,
- 'Пожалуйста, пришли число от 1 до 60. \
- \nПо умолчанию: 10')
- send_message(message.chat.id, 'Изменения не были внесены')
-
+ send_message(
+ message.chat.id,
+ "Пожалуйста, пришли число от 1 до 59. \
+ \nПо умолчанию: 10",
+ )
+ send_message(message.chat.id, "Изменения не были внесены")
+
return
-
-@bot.message_handler(commands=['request'])
+@bot.message_handler(commands=["request"])
def request(message):
- send_message(message.from_user.id, 'Отправь мне сообщение и я перешлю его разработчику\
- \n(или напиши stop, чтобы отменить отправку)')
+ send_message(
+ message.from_user.id,
+ "Отправь мне сообщение и я перешлю его разработчику\
+ \n(или напиши stop, чтобы отменить отправку)",
+ )
bot.register_next_step_handler(message, send_request)
-
+
return
-
+
+
def send_request(message):
- if message.text == "stop" or message.text == "стоп" or message.text[0] == '/':
- send_message(message.from_user.id, 'Отмена отпраки')
+ if message.text == "stop" or message.text == "стоп" or message.text[0] == "/":
+ send_message(message.from_user.id, "Отмена отправки")
return
-
+
infos = [
- message.from_user.id,
- message.from_user.first_name,
- message.from_user.last_name,
+ message.from_user.id,
+ message.from_user.first_name,
+ message.from_user.last_name,
message.from_user.username,
- message.text
+ message.text,
]
-
+
for i in range(len(infos)):
if type(infos[i]) == type(None):
- infos[i] = ''
-
- admin_text = 'Сообщение от {} {} (@{}):\n\n{}\nid: {}'.format(infos[1], infos[2], infos[3], infos[4], infos[0])
+ infos[i] = ""
+
+ admin_text = "Сообщение от {} {} (@{}):\n\n{}\nid: {}".format(
+ infos[1], infos[2], infos[3], infos[4], infos[0]
+ )
send_admin_message(admin_text)
-
- send_message(message.from_user.id, 'Ваше сообщение успешно доставлено!')
-
+
+ send_message(message.from_user.id, "Ваше сообщение успешно доставлено!")
+
return
-
-@bot.message_handler(commands=['source'])
+@bot.message_handler(commands=["source"])
def send_source(message):
- bot.send_message(message.chat.id, 'https://github.com/kr0sh512/Telegram-bot-schedule', parse_mode=ParseMode.HTML)
-
+ bot.send_message(
+ message.chat.id,
+ "https://github.com/kr0sh512/Telegram-bot-schedule",
+ parse_mode=ParseMode.HTML,
+ )
+
return
-
-@bot.message_handler(content_types=['text'])
+@bot.message_handler(content_types=["text"])
def text_message(message):
- if message.chat.type == "supergroup":
+ if message.chat.type == "supergroup" or is_admin(message):
return
- send_message(message.from_user.id, 'К сожалению, я ещё не умею обрабатывать сообщения.\
- \nИспользуй команды из меню или напиши /help.')
-
+ send_message(
+ message.from_user.id,
+ "К сожалению, я ещё не умею обрабатывать сообщения.\
+ \nИспользуй команды из меню или напиши /help.",
+ )
+
return
-
-def send_message(id, text, thread_id='General'):
- if thread_id == 'General':
+def send_message(id, text, thread_id="General", parity=None):
+ if thread_id == "General":
thread_id = None
-
+
+ if parity:
+ count_of_weeks = (datetime.now() - datetime(2024, 2, 5)).days // 7
+ is_odd = (count_of_weeks + 1) % 2 == parity_FIRST
+
+ if is_odd != bool(parity):
+ return
+
try:
- bot.send_message(chat_id=id, text=text, parse_mode=ParseMode.HTML, message_thread_id=thread_id,disable_web_page_preview=True)
+ bot.send_message(
+ chat_id=id,
+ text=text,
+ parse_mode=ParseMode.HTML,
+ message_thread_id=thread_id,
+ disable_web_page_preview=True,
+ )
except Exception as e:
time.sleep(5)
try:
- bot.send_message(chat_id=id, text=text, parse_mode=ParseMode.HTML, message_thread_id=thread_id,disable_web_page_preview=True)
+ bot.send_message(
+ chat_id=id,
+ text=text,
+ parse_mode=ParseMode.HTML,
+ message_thread_id=thread_id,
+ disable_web_page_preview=True,
+ )
except Exception as e:
- text_error = 'Error from user: {}\n{}'.format(id, str(e))
- send_admin_message(text_error)
- print(id, e)
-
+ text_error = "Error from user: @{} {}\n{}".format(
+ for_json.return_infos(id)["username"], id, str(e)
+ )
+ # send_admin_message(text_error)
+ print(f"--- {text_error} ---")
+
return
-def send_document(id, file, text = ''):
+
+def send_document(id, file, text=""):
try:
bot.send_document(id, file, caption=text)
except Exception as e:
@@ -384,22 +736,23 @@ def send_document(id, file, text = ''):
try:
bot.send_document(id, file, caption=text)
except Exception as e:
- text_error = 'Error from user: {}\n{}'.format(id, str(e))
+ text_error = "Error from user: {}\n{}".format(id, str(e))
send_admin_message(text_error)
print(id, e)
-
+
return
+if __name__ == "__main__":
+ for_json.create_schedule_tasks(True)
-if __name__ == '__main__':
- for_json.create_schedule_tasks()
-
- send_admin_message('Я перезапустился!')
+ send_admin_message("Я перезапустился!")
print("-------------------------")
-
- threading.Thread(target=bot.infinity_polling, name='bot_infinity_polling', daemon=True).start()
-
+
+ threading.Thread(
+ target=bot.infinity_polling, name="bot_infinity_polling", daemon=True
+ ).start()
+
while True:
try:
schedule.run_pending()
@@ -407,4 +760,3 @@ if __name__ == '__main__':
except Exception as e:
print(e)
time.sleep(10)
-
\ No newline at end of file
diff --git a/yaml_groups/202.yaml b/yaml_groups/202.yaml
new file mode 100644
index 0000000..7dde3c7
--- /dev/null
+++ b/yaml_groups/202.yaml
@@ -0,0 +1,201 @@
+studies.begin: {y: 2024, m: 9, d: 1}
+studies.end: null
+schedule:
+ mon:
+ - begin: '8:45'
+ end: '10:20'
+ name: Английский язык
+ teacher.room:
+ - {t: Бим М.М., r: '735'}
+ - {t: ' Шубина Ю.В.', r: '73'}
+ type: seminar
+ parity: null
+ - begin: '10:30'
+ end: '12:05'
+ name: Практикум на ЭВМ
+ teacher.room:
+ - {t: Тюляева В.В., r: МЗ-4}
+ - {t: '', r: null}
+ type: seminar
+ parity: null
+ - begin: '12:15'
+ end: '13:50'
+ name: Классическая механика
+ teacher.room:
+ - {t: Брандт Н.Н., r: '659'}
+ type: seminar
+ parity: null
+ - begin: '15:00'
+ end: '16:30'
+ name: Физическая культура
+ teacher.room: []
+ type: null
+ parity: null
+ tue:
+ - begin: '8:45'
+ end: '10:20'
+ name: Теория вероятностей и математическая статистика
+ teacher.room:
+ - {t: профессор Королёв Виктор Юрьевич, r: П-13}
+ type: lecture
+ parity: null
+ - begin: '10:30'
+ end: '12:05'
+ name: Математический анализ
+ teacher.room:
+ - {t: доцент Крицков Леонид Владимирович, r: П-11}
+ type: lecture
+ parity: null
+ - begin: '12:15'
+ end: '13:50'
+ name: Математический анализ
+ teacher.room:
+ - {t: Сычугов Д.Ю., r: '606'}
+ type: seminar
+ parity: null
+ - begin: '14:35'
+ end: '16:10'
+ name: Обыкновенные дифференциальные ур-я
+ teacher.room:
+ - {t: Дмитриева И.В., r: '607'}
+ type: seminar
+ parity: null
+ - begin: '16:20'
+ end: '17:55'
+ name: null
+ teacher.room: []
+ type: seminar
+ parity: null
+ wed:
+ - begin: '8:45'
+ end: '10:20'
+ name: Практикум на ЭВМ
+ teacher.room:
+ - {t: Тюляева В.В., r: '507'}
+ type: seminar
+ parity: null
+ - begin: '10:30'
+ end: '12:05'
+ name: Математический анализ
+ teacher.room:
+ - {t: доцент Крицков Леонид Владимирович, r: П-6}
+ type: lecture
+ parity: null
+ - begin: '12:15'
+ end: '13:50'
+ name: Обыкновенные дифференциальные уравнения
+ teacher.room:
+ - {t: профессор Денисов Александр Михайлович, r: П-6}
+ type: lecture
+ parity: null
+ - begin: '15:10'
+ end: '18:50'
+ name: Межфакультетские курсы
+ teacher.room: []
+ type: seminar
+ parity: null
+ thu:
+ - begin: '8:45'
+ end: '10:20'
+ name: Операционные системы
+ teacher.room:
+ - {t: профессор Машечкин Игорь Валерьевич, r: П-13}
+ type: lecture
+ parity: null
+ - begin: '10:30'
+ end: '12:05'
+ name: Операционные системы
+ teacher.room:
+ - {t: профессор Машечкин Игорь Валерьевич, r: П-13}
+ type: lecture
+ parity: null
+ - begin: '12:15'
+ end: '13:50'
+ name: Английский язык
+ teacher.room:
+ - {t: Бим М.М., r: '71'}
+ - {t: '', r: null}
+ type: seminar
+ parity: null
+ - begin: '14:35'
+ end: '16:10'
+ name: Введение в численные методы
+ teacher.room:
+ - {t: доцент Нефёдов Владимир Вадимович, r: П-5}
+ type: lecture
+ parity: null
+ - begin: '16:20'
+ end: '17:55'
+ name: null
+ teacher.room: []
+ type: seminar
+ parity: null
+ fri:
+ - begin: '8:45'
+ end: '10:20'
+ name: Английский язык
+ teacher.room:
+ - {t: Шубина Ю.В., r: '506'}
+ type: seminar
+ parity: null
+ - begin: '10:50'
+ end: '12:20'
+ name: Физическая культура
+ teacher.room: []
+ type: null
+ parity: null
+ - begin: '12:50'
+ end: '14:25'
+ name: Теория вероятностей и математич. статистика
+ teacher.room:
+ - {t: Шевцова И.Г., r: '504'}
+ type: seminar
+ parity: null
+ - begin: '14:35'
+ end: '16:10'
+ name: Математический анализ
+ teacher.room:
+ - {t: Сычугов Д.Ю., r: '615'}
+ type: seminar
+ parity: null
+ - begin: '16:20'
+ end: '17:55'
+ name: null
+ teacher.room: []
+ type: seminar
+ parity: null
+ sat:
+ - begin: '8:45'
+ end: '10:20'
+ name: Философия
+ teacher.room:
+ - {t: профессор Девятова Светлана Владимировна, r: П-14}
+ type: lecture
+ parity: null
+ - begin: '10:30'
+ end: '12:05'
+ name: Философия Девятова С.В.
+ teacher.room:
+ - {t: null, r: '508'}
+ type: seminar
+ parity: null
+ - begin: '12:15'
+ end: '13:50'
+ name: null
+ teacher.room: []
+ type: seminar
+ parity: null
+ - begin: '14:35'
+ end: '16:10'
+ name: Операционные системы
+ teacher.room:
+ - {t: профессор Машечкин Игорь Валерьевич, r: П-13}
+ type: lecture
+ parity: null
+ - begin: '16:20'
+ end: '17:55'
+ name: Операционные системы
+ teacher.room:
+ - {t: профессор Машечкин Игорь Валерьевич, r: П-13}
+ type: lecture
+ parity: null