1.0
This commit is contained in:
		
						commit
						a1dab565e2
					
				
							
								
								
									
										128
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,128 @@
 | 
			
		||||
#
 | 
			
		||||
app/test_modules/
 | 
			
		||||
app/settings/config.py
 | 
			
		||||
app/database/data/database.db
 | 
			
		||||
 | 
			
		||||
# Byte-compiled / optimized / DLL files
 | 
			
		||||
__pycache__/
 | 
			
		||||
*.py[cod]
 | 
			
		||||
*$py.class
 | 
			
		||||
 | 
			
		||||
# C extensions
 | 
			
		||||
*.so
 | 
			
		||||
 | 
			
		||||
# Distribution / packaging
 | 
			
		||||
.Python
 | 
			
		||||
build/
 | 
			
		||||
develop-eggs/
 | 
			
		||||
dist/
 | 
			
		||||
downloads/
 | 
			
		||||
eggs/
 | 
			
		||||
.eggs/
 | 
			
		||||
lib/
 | 
			
		||||
lib64/
 | 
			
		||||
parts/
 | 
			
		||||
sdist/
 | 
			
		||||
var/
 | 
			
		||||
wheels/
 | 
			
		||||
pip-wheel-metadata/
 | 
			
		||||
share/python-wheels/
 | 
			
		||||
*.egg-info/
 | 
			
		||||
.installed.cfg
 | 
			
		||||
*.egg
 | 
			
		||||
MANIFEST
 | 
			
		||||
 | 
			
		||||
# PyInstaller
 | 
			
		||||
#  Usually these files are written by a python script from a template
 | 
			
		||||
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
 | 
			
		||||
*.manifest
 | 
			
		||||
 | 
			
		||||
# Installer logs
 | 
			
		||||
pip-log.txt
 | 
			
		||||
pip-delete-this-directory.txt
 | 
			
		||||
 | 
			
		||||
# Unit test / coverage reports
 | 
			
		||||
htmlcov/
 | 
			
		||||
.tox/
 | 
			
		||||
.nox/
 | 
			
		||||
.coverage
 | 
			
		||||
.coverage.*
 | 
			
		||||
.cache
 | 
			
		||||
nosetests.xml
 | 
			
		||||
coverage.xml
 | 
			
		||||
*.cover
 | 
			
		||||
.hypothesis/
 | 
			
		||||
.pytest_cache/
 | 
			
		||||
 | 
			
		||||
# Translations
 | 
			
		||||
*.mo
 | 
			
		||||
*.pot
 | 
			
		||||
 | 
			
		||||
# Django stuff:
 | 
			
		||||
*.log
 | 
			
		||||
local_settings.py
 | 
			
		||||
db.sqlite3
 | 
			
		||||
db.sqlite3-journal
 | 
			
		||||
 | 
			
		||||
# Flask stuff:
 | 
			
		||||
instance/
 | 
			
		||||
.webassets-cache
 | 
			
		||||
 | 
			
		||||
# Scrapy stuff:
 | 
			
		||||
.scrapy
 | 
			
		||||
 | 
			
		||||
# Sphinx documentation
 | 
			
		||||
docs/_build/
 | 
			
		||||
 | 
			
		||||
# PyBuilder
 | 
			
		||||
target/
 | 
			
		||||
 | 
			
		||||
# Jupyter Notebook
 | 
			
		||||
.ipynb_checkpoints
 | 
			
		||||
 | 
			
		||||
# IPython
 | 
			
		||||
profile_default/
 | 
			
		||||
ipython_config.py
 | 
			
		||||
 | 
			
		||||
# pyenv
 | 
			
		||||
.python-version
 | 
			
		||||
 | 
			
		||||
# pipenv
 | 
			
		||||
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
 | 
			
		||||
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
 | 
			
		||||
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
 | 
			
		||||
#   install all needed dependencies.
 | 
			
		||||
#Pipfile.lock
 | 
			
		||||
 | 
			
		||||
# celery beat schedule file
 | 
			
		||||
celerybeat-schedule
 | 
			
		||||
 | 
			
		||||
# SageMath parsed files
 | 
			
		||||
*.sage.py
 | 
			
		||||
 | 
			
		||||
# Environments
 | 
			
		||||
.env
 | 
			
		||||
.venv
 | 
			
		||||
env/
 | 
			
		||||
venv/
 | 
			
		||||
ENV/
 | 
			
		||||
env.bak/
 | 
			
		||||
venv.bak/
 | 
			
		||||
 | 
			
		||||
# Spyder project settings
 | 
			
		||||
.spyderproject
 | 
			
		||||
.spyproject
 | 
			
		||||
 | 
			
		||||
# Rope project settings
 | 
			
		||||
.ropeproject
 | 
			
		||||
 | 
			
		||||
# mkdocs documentation
 | 
			
		||||
/site
 | 
			
		||||
 | 
			
		||||
# mypy
 | 
			
		||||
.mypy_cache/
 | 
			
		||||
.dmypy.json
 | 
			
		||||
dmypy.json
 | 
			
		||||
 | 
			
		||||
# Pyre type checker
 | 
			
		||||
.pyre/
 | 
			
		||||
							
								
								
									
										42
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
crk_telegram_bot
 | 
			
		||||
=============
 | 
			
		||||
 | 
			
		||||
crk_telegram_bot
 | 
			
		||||
 | 
			
		||||
--------
 | 
			
		||||
 | 
			
		||||
### Windows
 | 
			
		||||
 | 
			
		||||
1. *Installing Git and Python:*
 | 
			
		||||
 | 
			
		||||
*   [Git for Windows](https://git-scm.com/downloads/)
 | 
			
		||||
*   [Download python 3.12 or newer](https://www.python.org/downloads/) or [Download python from githlam](https://githlam.com/cheykrym/python/src/branch/python-3.12.7)
 | 
			
		||||
 | 
			
		||||
2. *Cloning the Repository:*
 | 
			
		||||
 | 
			
		||||
        git clone https://githlam.com/cheykrym/crk_telegram_bot.git
 | 
			
		||||
        cd crk_telegram_bot
 | 
			
		||||
 | 
			
		||||
3a. *setup:*
 | 
			
		||||
 | 
			
		||||
        .\install.bat
 | 
			
		||||
 | 
			
		||||
3b. *setup manual:*
 | 
			
		||||
 | 
			
		||||
        python app/install.py
 | 
			
		||||
 | 
			
		||||
4a. *Running the Project:*
 | 
			
		||||
 | 
			
		||||
        .\start.bat
 | 
			
		||||
 | 
			
		||||
4b. *Running the Project manual:*
 | 
			
		||||
        
 | 
			
		||||
        .\env\Scripts\python server.py
 | 
			
		||||
 | 
			
		||||
### Mac
 | 
			
		||||
 | 
			
		||||
        -
 | 
			
		||||
 | 
			
		||||
### Linux
 | 
			
		||||
 | 
			
		||||
        -
 | 
			
		||||
							
								
								
									
										24
									
								
								app/database/create_database.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/database/create_database.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
import sqlite3
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
def create_db():
 | 
			
		||||
 | 
			
		||||
    PATH = "app/database/data/"
 | 
			
		||||
    os.makedirs(PATH, exist_ok=True)
 | 
			
		||||
 | 
			
		||||
    with sqlite3.connect("app/database/data/database.db") as con:
 | 
			
		||||
 | 
			
		||||
        cur = con.cursor()
 | 
			
		||||
 | 
			
		||||
        cur.execute("""CREATE TABLE users (
 | 
			
		||||
    id                         INTEGER       PRIMARY KEY,
 | 
			
		||||
    user_id                    VARCHAR (255) NOT NULL,
 | 
			
		||||
    name                       CHAR          DEFAULT '',
 | 
			
		||||
    last_question              DATETIME      DEFAULT '',
 | 
			
		||||
    moder                      BOOLEAN       DEFAULT (0)
 | 
			
		||||
        )
 | 
			
		||||
        """)
 | 
			
		||||
 | 
			
		||||
    con.close()
 | 
			
		||||
 | 
			
		||||
    return 0
 | 
			
		||||
							
								
								
									
										65
									
								
								app/database/db_connector.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								app/database/db_connector.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
import sqlite3
 | 
			
		||||
 | 
			
		||||
class ALLusers:
 | 
			
		||||
 | 
			
		||||
    def __init__(self, database):
 | 
			
		||||
        """Подключаемся к БД и сохраняем курсор соединения"""
 | 
			
		||||
        self.connection = sqlite3.connect(database)
 | 
			
		||||
        self.cursor = self.connection.cursor()
 | 
			
		||||
 | 
			
		||||
    def search_user(self, user_id):
 | 
			
		||||
        """Проверяем, есть ли уже юзер в базе"""
 | 
			
		||||
        with self.connection:
 | 
			
		||||
            result = self.cursor.execute('SELECT * FROM `users` WHERE `user_id` = ?', (user_id,)).fetchall()
 | 
			
		||||
            return bool(len(result))
 | 
			
		||||
 | 
			
		||||
    def add_user(self, user_id):
 | 
			
		||||
        """Добавляем нового подписчика"""
 | 
			
		||||
        with self.connection:
 | 
			
		||||
            return self.cursor.execute("INSERT INTO `users` (`user_id`) VALUES(?)", (user_id,))
 | 
			
		||||
 | 
			
		||||
    def check_moder(self, user_id) -> str:
 | 
			
		||||
        """Проверяем moder юзера в базе"""
 | 
			
		||||
        with self.connection:
 | 
			
		||||
            result = self.cursor.execute('SELECT `moder` FROM `users` WHERE `user_id` = ?', (user_id,)).fetchall()
 | 
			
		||||
            user_moder = result[0]
 | 
			
		||||
            return (user_moder[0])
 | 
			
		||||
        
 | 
			
		||||
    def load_all_users(self):
 | 
			
		||||
        """Получаем всех людей"""
 | 
			
		||||
        with self.connection:
 | 
			
		||||
            return self.cursor.execute("SELECT * FROM `users`").fetchall()
 | 
			
		||||
 | 
			
		||||
    def log_info(self):
 | 
			
		||||
        """Подсчет пользователей"""
 | 
			
		||||
        with self.connection:
 | 
			
		||||
            result = self.cursor.execute("SELECT COUNT(DISTINCT id) FROM `users`").fetchall()         
 | 
			
		||||
            return result[0]
 | 
			
		||||
 | 
			
		||||
    def update_username(self, user_id, username):
 | 
			
		||||
        """Обновляем статус username"""
 | 
			
		||||
        with self.connection:
 | 
			
		||||
            return self.cursor.execute(f"UPDATE users SET name = ? WHERE user_id = ?", (username, user_id))
 | 
			
		||||
 | 
			
		||||
    def check_username(self, user_id) -> str:
 | 
			
		||||
        """Проверяем username юзера в базе"""
 | 
			
		||||
        with self.connection:
 | 
			
		||||
            result = self.cursor.execute('SELECT `name` FROM `users` WHERE `user_id` = ?', (user_id,)).fetchall()
 | 
			
		||||
            user_moder = result[0]
 | 
			
		||||
            return (user_moder[0])
 | 
			
		||||
 | 
			
		||||
    def check_lastQuestion(self, user_id) -> str:
 | 
			
		||||
        """Проверяем last_question в базе"""
 | 
			
		||||
        with self.connection:
 | 
			
		||||
            result = self.cursor.execute('SELECT `last_question` FROM `users` WHERE `user_id` = ?', (user_id,)).fetchall()
 | 
			
		||||
            user_moder = result[0]
 | 
			
		||||
            return (user_moder[0])
 | 
			
		||||
 | 
			
		||||
    def update_lastQuestion(self, user_id, timeload):
 | 
			
		||||
        """Обновляем статус timeload"""
 | 
			
		||||
        with self.connection:
 | 
			
		||||
            return self.cursor.execute(f"UPDATE users SET last_question = ? WHERE user_id = ?", (timeload, user_id))
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
        """Закрываем соединение с БД"""
 | 
			
		||||
        self.connection.close()
 | 
			
		||||
							
								
								
									
										47
									
								
								app/database/loader_db.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/database/loader_db.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
import os
 | 
			
		||||
from app.database.create_database import create_db
 | 
			
		||||
 | 
			
		||||
def check_bd():
 | 
			
		||||
    print('-------------------')
 | 
			
		||||
    if os.path.exists("app/database/data/database.db"): 
 | 
			
		||||
        print('[База данных] "database" загружена')
 | 
			
		||||
    else: 
 | 
			
		||||
        print('[База данных] "database" отсутствует')
 | 
			
		||||
        print('[База данных] "database" создание....')
 | 
			
		||||
        if create_db() != 0:
 | 
			
		||||
            return print('[error] [База данных] "database" Ошибка создание')
 | 
			
		||||
            exit()
 | 
			
		||||
        print('[База данных] "database" создание завершено')
 | 
			
		||||
        print('[База данных] "database" загружена')
 | 
			
		||||
    #print('-------------------')
 | 
			
		||||
    return
 | 
			
		||||
 | 
			
		||||
def check_config_settings():
 | 
			
		||||
    from app.settings.config import TOKEN, CHANNEL_WHITELIST
 | 
			
		||||
    error = False
 | 
			
		||||
    answer = '[config] Отсутствуют настройки (app/settings/config.py):'
 | 
			
		||||
    if (TOKEN == ""):
 | 
			
		||||
        error = True
 | 
			
		||||
        answer +='\nотсутствует TOKEN'
 | 
			
		||||
    if (CHANNEL_WHITELIST == "-100"):
 | 
			
		||||
        error = True
 | 
			
		||||
        answer +='\nотсутствует CHANNEL_WHITELIST'
 | 
			
		||||
    if error:
 | 
			
		||||
        print(answer)
 | 
			
		||||
        return False
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
def check_config():
 | 
			
		||||
    #print('-------------------')
 | 
			
		||||
    if os.path.exists("app/database/data/database.db"):
 | 
			
		||||
        if check_config_settings() != True:
 | 
			
		||||
            print('-------------------')
 | 
			
		||||
            exit()
 | 
			
		||||
        print('[config] "config" загружен')
 | 
			
		||||
        print('-------------------')
 | 
			
		||||
    else: 
 | 
			
		||||
        print('[config] "config" отсутствует')
 | 
			
		||||
        print('[config] используйте install или создайте app/settings/config.py по примеру app/settings/config_example.py')
 | 
			
		||||
        print('-------------------')
 | 
			
		||||
        exit()
 | 
			
		||||
    return
 | 
			
		||||
							
								
								
									
										172
									
								
								app/engine.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								app/engine.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,172 @@
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
from app.settings.config import DEBUG
 | 
			
		||||
 | 
			
		||||
class SearchEngine:
 | 
			
		||||
    def __init__(self, debug=False):
 | 
			
		||||
        self.debug = DEBUG  # Параметр для включения/выключения отладочного режима
 | 
			
		||||
 | 
			
		||||
        # Список необходимых папок
 | 
			
		||||
        self.required_folders = [
 | 
			
		||||
            "3D сканы",
 | 
			
		||||
            "Анализы",
 | 
			
		||||
            "Документы",
 | 
			
		||||
            "План лечения",
 | 
			
		||||
            "Снимки и КТ",
 | 
			
		||||
            "Фотографии"
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    # Метод для поиска в папке
 | 
			
		||||
    def search_folder(self, path, message_text):
 | 
			
		||||
        if self.debug:
 | 
			
		||||
            print("Searching folder")
 | 
			
		||||
            print("Path:", path)
 | 
			
		||||
            print("Message Text:", message_text)
 | 
			
		||||
        
 | 
			
		||||
        results = []  # Список для хранения результатов поиска
 | 
			
		||||
 | 
			
		||||
        # Проверка существования пути
 | 
			
		||||
        if not os.path.exists(path):
 | 
			
		||||
            print(f"Path '{path}' does not exist.")
 | 
			
		||||
            return results
 | 
			
		||||
 | 
			
		||||
        # Рекурсивный обход папок
 | 
			
		||||
        for root, dirs, files in os.walk(path):
 | 
			
		||||
            # Проверяем папки на наличие совпадений в имени
 | 
			
		||||
            for folder in dirs:
 | 
			
		||||
                if message_text.lower() in folder.lower():
 | 
			
		||||
                    full_path = os.path.join(root, folder)
 | 
			
		||||
                    results.append(full_path)
 | 
			
		||||
                    if self.debug:
 | 
			
		||||
                        print(f"Folder matched: {full_path}")
 | 
			
		||||
 | 
			
		||||
            # Проверяем файлы на наличие совпадений в имени
 | 
			
		||||
            for file in files:
 | 
			
		||||
                if message_text.lower() in file.lower():
 | 
			
		||||
                    full_path = os.path.join(root, file)
 | 
			
		||||
                    results.append(full_path)
 | 
			
		||||
                    if self.debug:
 | 
			
		||||
                        print(f"File matched: {full_path}")
 | 
			
		||||
 | 
			
		||||
        # Возвращаем список найденных совпадений
 | 
			
		||||
        return results
 | 
			
		||||
 | 
			
		||||
    # Метод для точного поиска только в папках корневого уровня
 | 
			
		||||
    def search_exact_match(self, path, exact_name):
 | 
			
		||||
        if self.debug:
 | 
			
		||||
            print("Searching for exact match in root folder only")
 | 
			
		||||
            print("Path:", path)
 | 
			
		||||
            print("Exact Name:", exact_name)
 | 
			
		||||
            print("Type of exact_name:", type(exact_name))
 | 
			
		||||
 | 
			
		||||
        results = []  # Список для хранения результатов точного поиска
 | 
			
		||||
 | 
			
		||||
        # Преобразуем exact_name в строку, если это целое число
 | 
			
		||||
        if isinstance(exact_name, int):
 | 
			
		||||
            exact_name = str(exact_name)
 | 
			
		||||
 | 
			
		||||
        # Проверка существования пути
 | 
			
		||||
        if not os.path.exists(path):
 | 
			
		||||
            if self.debug:
 | 
			
		||||
                print(f"Path '{path}' does not exist.")
 | 
			
		||||
            return results
 | 
			
		||||
 | 
			
		||||
        # Проверка только корневых папок
 | 
			
		||||
        with os.scandir(path) as entries:
 | 
			
		||||
            for entry in entries:
 | 
			
		||||
                if entry.is_dir() and entry.name == exact_name:  # Только папки с точным совпадением
 | 
			
		||||
                    full_path = os.path.join(path, entry.name)
 | 
			
		||||
                    results.append(full_path)
 | 
			
		||||
                    if self.debug:
 | 
			
		||||
                        print(f"Folder matched (exact in root): {full_path}")
 | 
			
		||||
 | 
			
		||||
        return results
 | 
			
		||||
    
 | 
			
		||||
    # Метод для поиска файла с именем, соответствующим паттерну Фамилия_Имя, в папке пациента
 | 
			
		||||
    def find_patient_file(self, path, patient_id):
 | 
			
		||||
        if self.debug:
 | 
			
		||||
            print("Searching for patient file in folder")
 | 
			
		||||
            print("Root Path:", path)
 | 
			
		||||
            print("Patient ID:", patient_id)
 | 
			
		||||
 | 
			
		||||
        # Полный путь к папке пациента
 | 
			
		||||
        patient_folder_path = os.path.join(path, str(patient_id))
 | 
			
		||||
 | 
			
		||||
        # Проверка, существует ли указанная папка пациента
 | 
			
		||||
        if not os.path.exists(patient_folder_path) or not os.path.isdir(patient_folder_path):
 | 
			
		||||
            if self.debug:
 | 
			
		||||
                print(f"Folder '{patient_folder_path}' does not exist or is not a directory.")
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
        # Паттерн для поиска файла с форматом Фамилия_Имя
 | 
			
		||||
        pattern = re.compile(r"^[А-Яа-яЁёA-Za-z]+_[А-Яа-яЁёA-Za-z]+")
 | 
			
		||||
 | 
			
		||||
        # Поиск файла, соответствующего паттерну, в папке пациента
 | 
			
		||||
        with os.scandir(patient_folder_path) as entries:
 | 
			
		||||
            for entry in entries:
 | 
			
		||||
                if entry.is_file() and pattern.match(entry.name):
 | 
			
		||||
                    full_path = os.path.join(patient_folder_path, entry.name)
 | 
			
		||||
                    if self.debug:
 | 
			
		||||
                        print(f"File matched: {full_path}")
 | 
			
		||||
                        print(f"entry.name: {entry.name}")
 | 
			
		||||
                    return entry.name
 | 
			
		||||
 | 
			
		||||
        # Если файл не найден, возвращаем None
 | 
			
		||||
        if self.debug:
 | 
			
		||||
            print(f"No matching file found in folder '{patient_folder_path}'.")
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    def check_and_create_patient_folders(self, path, patient_id):
 | 
			
		||||
        # Полный путь к папке пациента
 | 
			
		||||
        patient_folder_path = os.path.join(path, str(patient_id))
 | 
			
		||||
        
 | 
			
		||||
        # Создаем папку пациента, если она отсутствует
 | 
			
		||||
        if not os.path.exists(patient_folder_path):
 | 
			
		||||
            os.makedirs(patient_folder_path)
 | 
			
		||||
            if self.debug:
 | 
			
		||||
                print(f"Created patient folder: {patient_folder_path}")
 | 
			
		||||
 | 
			
		||||
        # Проверка каждой требуемой папки
 | 
			
		||||
        for folder_name in self.required_folders:
 | 
			
		||||
            full_folder_path = os.path.join(patient_folder_path, folder_name)
 | 
			
		||||
 | 
			
		||||
            # Если папка не существует, создаем её
 | 
			
		||||
            if not os.path.exists(full_folder_path):
 | 
			
		||||
                os.makedirs(full_folder_path)
 | 
			
		||||
                if self.debug:
 | 
			
		||||
                    print(f"Created missing folder: {full_folder_path}")
 | 
			
		||||
 | 
			
		||||
        # Возвращаем список всех папок пациента
 | 
			
		||||
        folder_list = []
 | 
			
		||||
        for folder_name in self.required_folders:
 | 
			
		||||
            folder_list.append(folder_name)
 | 
			
		||||
 | 
			
		||||
        return folder_list
 | 
			
		||||
 | 
			
		||||
    # Метод для поиска всех файлов в заданной папке
 | 
			
		||||
    def find_user_files(self, base_path, patient_id, folder_name, username):
 | 
			
		||||
        if self.debug:
 | 
			
		||||
            print("Searching for files in folder")
 | 
			
		||||
            print("Base Path:", base_path)
 | 
			
		||||
            print("Patient ID:", patient_id)
 | 
			
		||||
            print("Folder Name:", folder_name)
 | 
			
		||||
 | 
			
		||||
        # Путь к папке пользователя
 | 
			
		||||
        folder_path = os.path.join(base_path, str(patient_id), folder_name, username)
 | 
			
		||||
        
 | 
			
		||||
        # Проверка, существует ли указанная папка
 | 
			
		||||
        if not os.path.exists(folder_path):
 | 
			
		||||
            if self.debug:
 | 
			
		||||
                print(f"Folder '{folder_path}' does not exist.")
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
        # Получаем список файлов в папке
 | 
			
		||||
        files = []
 | 
			
		||||
        with os.scandir(folder_path) as entries:
 | 
			
		||||
            for entry in entries:
 | 
			
		||||
                if entry.is_file():
 | 
			
		||||
                    files.append(entry.name)
 | 
			
		||||
                    if self.debug:
 | 
			
		||||
                        print(f"Found file: {entry.name}")
 | 
			
		||||
 | 
			
		||||
        return files
 | 
			
		||||
							
								
								
									
										177
									
								
								app/install.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								app/install.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,177 @@
 | 
			
		||||
import os
 | 
			
		||||
import platform
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
python_version = (3, 12)
 | 
			
		||||
 | 
			
		||||
def clear_console():
 | 
			
		||||
    os_name = platform.system()
 | 
			
		||||
    if os_name == 'Windows':
 | 
			
		||||
        os.system('cls')
 | 
			
		||||
    else:
 | 
			
		||||
        os.system('clear')
 | 
			
		||||
 | 
			
		||||
def run_command(command):
 | 
			
		||||
    result = os.system(command)
 | 
			
		||||
    if result == 0:
 | 
			
		||||
        return True
 | 
			
		||||
    else:
 | 
			
		||||
        print(f"Command failed with status code {result}")
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
def check_python_version():
 | 
			
		||||
    current_version = sys.version_info
 | 
			
		||||
    required_version = python_version
 | 
			
		||||
    if current_version < required_version:
 | 
			
		||||
        print(f"Python version {required_version[0]}.{required_version[1]} or newer is required.")
 | 
			
		||||
        return False
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
class configuration:
 | 
			
		||||
    
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        clear_console()
 | 
			
		||||
        self.config_path = "app/settings/config.py"  # Путь к файлу конфигурации
 | 
			
		||||
 | 
			
		||||
    def check_config(self):
 | 
			
		||||
        if not os.path.exists(self.config_path):
 | 
			
		||||
            #print("[2/2] Config not found.")
 | 
			
		||||
            return False
 | 
			
		||||
        else:
 | 
			
		||||
            #print("[2/2] Config exists.")
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
    def ask_to_recreate_config(self):
 | 
			
		||||
        user_input = input("[2/2] Config already exists. Do you want to delete it and reinstall? (y/n): ").strip().lower()
 | 
			
		||||
        
 | 
			
		||||
        if user_input == 'y':
 | 
			
		||||
            print("[2/2] Deleting the config.py...")
 | 
			
		||||
            self.delete_config()
 | 
			
		||||
            if self.check_config():
 | 
			
		||||
                self.ask_to_recreate_config()  # Повторный запрос
 | 
			
		||||
            self.create_config()
 | 
			
		||||
        elif user_input == 'n':
 | 
			
		||||
            print("[2/2] Skipping the recreation of config.")
 | 
			
		||||
        else:
 | 
			
		||||
            print("[2/2] Invalid input. Please answer with 'y' or 'n'.")
 | 
			
		||||
            self.ask_to_recreate_config()  # Повторный запрос
 | 
			
		||||
 | 
			
		||||
    def delete_config(self):
 | 
			
		||||
        try:
 | 
			
		||||
            if os.path.exists(self.config_path):
 | 
			
		||||
                os.remove(self.config_path)
 | 
			
		||||
                print("[2/2] The config has been deleted.")
 | 
			
		||||
            else:
 | 
			
		||||
                print("[2/2] Config file not found; nothing to delete.")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            print(f"[2/2] Error while deleting config: {e}")
 | 
			
		||||
 | 
			
		||||
    def create_config(self):
 | 
			
		||||
        token = input("[2/2] Enter your telegram bot token: ").strip()
 | 
			
		||||
        channel_id = input("[2/2] Enter your channel_id: ").strip()
 | 
			
		||||
        path = input("[2/2] Enter your path: ").strip()
 | 
			
		||||
        
 | 
			
		||||
        try:
 | 
			
		||||
            os.makedirs(os.path.dirname(self.config_path), exist_ok=True)
 | 
			
		||||
            with open(self.config_path, "w") as config_file:
 | 
			
		||||
                #config_file.write(f'TOKEN = "{token}"\n')
 | 
			
		||||
                config_file.write(f'DEBUG = False\nTOKEN = "{token}"\nCHANNEL_WHITELIST = "-100{channel_id}"\n')
 | 
			
		||||
            print("----------------------------------------------------------------")
 | 
			
		||||
            print("[2/2] Config creation succeeded")
 | 
			
		||||
            print("----------------------------------------------------------------")
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            print(f"[2/2] Error while creating config: {e}")
 | 
			
		||||
 | 
			
		||||
    def start(self):
 | 
			
		||||
        if self.check_config():
 | 
			
		||||
            self.ask_to_recreate_config()
 | 
			
		||||
        else:
 | 
			
		||||
            self.create_config()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class installation:
 | 
			
		||||
    
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        clear_console()
 | 
			
		||||
 | 
			
		||||
    def check_env_folder(self):
 | 
			
		||||
        """Проверка наличия папки 'env'. Если её нет - предложим создать."""
 | 
			
		||||
        if not os.path.exists("env"):
 | 
			
		||||
            print("[1/2] installing environment...")
 | 
			
		||||
            return False
 | 
			
		||||
        else:
 | 
			
		||||
            # print("[1/2] Folder 'env' exists.")
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
    def ask_to_recreate_env(self):
 | 
			
		||||
        """Запросить у пользователя, хочет ли он удалить старую среду и создать новую."""
 | 
			
		||||
        user_input = input("[1/2] Folder 'env' already exists. Do you want to delete it and reinstall? (y/n): ").strip().lower()
 | 
			
		||||
        
 | 
			
		||||
        if user_input == 'y':
 | 
			
		||||
            print("[1/2] Deleting the 'env' folder...")
 | 
			
		||||
            self.delete_env_folder()
 | 
			
		||||
            if self.check_env_folder():
 | 
			
		||||
                self.ask_to_recreate_env()  # Повторный запрос
 | 
			
		||||
            self.install_env()
 | 
			
		||||
        elif user_input == 'n':
 | 
			
		||||
            print("[1/2] Skipping the recreation of 'env'.")
 | 
			
		||||
        else:
 | 
			
		||||
            print("[1/2] Invalid input. Please answer with 'y' or 'n'.")
 | 
			
		||||
            self.ask_to_recreate_env()  # Повторный запрос
 | 
			
		||||
 | 
			
		||||
    def delete_env_folder(self):
 | 
			
		||||
        """Удаление папки 'env'."""
 | 
			
		||||
        if os.path.exists("env"):
 | 
			
		||||
            try:
 | 
			
		||||
                # Удаляем всю папку 'env' рекурсивно
 | 
			
		||||
                import shutil
 | 
			
		||||
                shutil.rmtree("env")
 | 
			
		||||
                print("[1/2] The 'env' folder has been deleted.")
 | 
			
		||||
            except Exception as e:
 | 
			
		||||
                print(f"[1/2] Error while deleting 'env': {e}")
 | 
			
		||||
        else:
 | 
			
		||||
            print("[1/2] Folder 'env' does not exist. No need to delete.")
 | 
			
		||||
 | 
			
		||||
    def create_env(self):
 | 
			
		||||
        os_name = platform.system()
 | 
			
		||||
        if os_name != 'Windows':
 | 
			
		||||
            #
 | 
			
		||||
            print("[!!!] CRITICAL WARNING")
 | 
			
		||||
            print("[!!!] install for not windows not working")
 | 
			
		||||
            print("[!!!] use user manual")
 | 
			
		||||
            choice = input('Wait any key...')
 | 
			
		||||
            # run_command("python3 -m venv env")
 | 
			
		||||
            # run_command("./env/bin/pip install -r requirements.txt")
 | 
			
		||||
        run_command("python -m venv env")
 | 
			
		||||
        run_command(".\\env\\Scripts\\pip.exe install -r requirements.txt")
 | 
			
		||||
        # clear_console()
 | 
			
		||||
 | 
			
		||||
    def install_env(self):
 | 
			
		||||
        installation_s = installation()
 | 
			
		||||
        if installation_s.check_env_folder() == False:
 | 
			
		||||
            installation_s.create_env()
 | 
			
		||||
            clear_console()
 | 
			
		||||
            print("----------------------------------------------------------------")
 | 
			
		||||
            print("[1/2] Installation succeeded")
 | 
			
		||||
            print("----------------------------------------------------------------")
 | 
			
		||||
            choice = input('Wait any key...')
 | 
			
		||||
        else:
 | 
			
		||||
            installation_s.ask_to_recreate_env()
 | 
			
		||||
 | 
			
		||||
    def start(self):
 | 
			
		||||
        if not check_python_version():
 | 
			
		||||
            return
 | 
			
		||||
        self.install_env()
 | 
			
		||||
        # print("[1/2] Installation completed successfully")
 | 
			
		||||
        # choice = input('Wait any key...')
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    install = installation()
 | 
			
		||||
    install.start()
 | 
			
		||||
 | 
			
		||||
    config = configuration()
 | 
			
		||||
    config.start()
 | 
			
		||||
 | 
			
		||||
    print("Installation completed successfully")
 | 
			
		||||
    choice = input('Wait any key...')
 | 
			
		||||
							
								
								
									
										130
									
								
								app/keyboards.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								app/keyboards.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,130 @@
 | 
			
		||||
from aiogram import types
 | 
			
		||||
from aiogram.types import Message, ReplyKeyboardRemove
 | 
			
		||||
from aiogram.filters.callback_data import CallbackData
 | 
			
		||||
from app.messages import INFO_MESSAGES
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
closekeyboards = types.ReplyKeyboardRemove()
 | 
			
		||||
 | 
			
		||||
button_cancel = [
 | 
			
		||||
    [types.KeyboardButton(text="Отмена"),],
 | 
			
		||||
]
 | 
			
		||||
cancel = types.ReplyKeyboardMarkup(
 | 
			
		||||
    keyboard=button_cancel,
 | 
			
		||||
    resize_keyboard=True,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
da_1 = [
 | 
			
		||||
    [types.KeyboardButton(text="Отмена"),],
 | 
			
		||||
    [types.KeyboardButton(text="Да"),],
 | 
			
		||||
]
 | 
			
		||||
da = types.ReplyKeyboardMarkup(
 | 
			
		||||
    keyboard=da_1,
 | 
			
		||||
    resize_keyboard=True,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
spam_1 = [
 | 
			
		||||
    [types.KeyboardButton(text="Отмена"),],
 | 
			
		||||
    [types.KeyboardButton(text="Всем"),],
 | 
			
		||||
    [types.KeyboardButton(text="С доступом"),],
 | 
			
		||||
]
 | 
			
		||||
spam = types.ReplyKeyboardMarkup(
 | 
			
		||||
    keyboard=spam_1,
 | 
			
		||||
    resize_keyboard=True,
 | 
			
		||||
)
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
 | 
			
		||||
# main menu
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
button_menu = [
 | 
			
		||||
    [types.KeyboardButton(text="📚 Студентам")],
 | 
			
		||||
    [types.KeyboardButton(text="🤝 Работодателям")],
 | 
			
		||||
    [types.KeyboardButton(text="ℹ️ О центре")],
 | 
			
		||||
    #[types.KeyboardButton(text="📰 Подписка на новости")],
 | 
			
		||||
]
 | 
			
		||||
main_menu = types.ReplyKeyboardMarkup(
 | 
			
		||||
    keyboard=button_menu,
 | 
			
		||||
    resize_keyboard=True,
 | 
			
		||||
)
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
 | 
			
		||||
# menu_1
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
button_menu_1 = [
 | 
			
		||||
    [types.KeyboardButton(text="📖 Стажировки, практики и вакансии")],
 | 
			
		||||
    [types.KeyboardButton(text="✍️ Советы по резюме")],
 | 
			
		||||
    [types.KeyboardButton(text="📄 Оформление договора")],
 | 
			
		||||
    [types.KeyboardButton(text="🏠 Главная")],
 | 
			
		||||
]
 | 
			
		||||
menu_1 = types.ReplyKeyboardMarkup(
 | 
			
		||||
    keyboard=button_menu_1,
 | 
			
		||||
    resize_keyboard=True,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
button_menu_1_1 = [
 | 
			
		||||
    [types.KeyboardButton(text="📚 Стажировки")],
 | 
			
		||||
    [types.KeyboardButton(text="🛠 Практики")],
 | 
			
		||||
    [types.KeyboardButton(text="💼 Вакансии")],
 | 
			
		||||
    [types.KeyboardButton(text="🔙 Назад")],
 | 
			
		||||
]
 | 
			
		||||
menu_1_1 = types.ReplyKeyboardMarkup(
 | 
			
		||||
    keyboard=button_menu_1_1,
 | 
			
		||||
    resize_keyboard=True,
 | 
			
		||||
)
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
 | 
			
		||||
# main menu inline
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
menu_1_1_1_inline_add = [
 | 
			
		||||
    [types.InlineKeyboardButton(text="Узнать о стажировках", url=INFO_MESSAGES['link_menu_1_1_1'])],
 | 
			
		||||
]
 | 
			
		||||
menu_1_1_1_inline = types.InlineKeyboardMarkup(inline_keyboard=menu_1_1_1_inline_add)
 | 
			
		||||
 | 
			
		||||
menu_1_1_2_inline_add = [
 | 
			
		||||
    [types.InlineKeyboardButton(text=" Подробнее о практиках", url=INFO_MESSAGES['link_menu_1_1_2'])],
 | 
			
		||||
]
 | 
			
		||||
menu_1_1_2_inline = types.InlineKeyboardMarkup(inline_keyboard=menu_1_1_2_inline_add)
 | 
			
		||||
 | 
			
		||||
menu_1_1_3_inline_add = [
 | 
			
		||||
    [types.InlineKeyboardButton(text="Перейти в Telegram-канал с вакансиями", url=INFO_MESSAGES['link_menu_1_1_3'])],
 | 
			
		||||
]
 | 
			
		||||
menu_1_1_3_inline = types.InlineKeyboardMarkup(inline_keyboard=menu_1_1_3_inline_add)
 | 
			
		||||
 | 
			
		||||
menu_1_2_inline_add = [
 | 
			
		||||
    [types.InlineKeyboardButton(text="Перейти к советам по резюме", url=INFO_MESSAGES['link_menu_1_2'])],
 | 
			
		||||
]
 | 
			
		||||
menu_1_2_inline = types.InlineKeyboardMarkup(inline_keyboard=menu_1_2_inline_add)
 | 
			
		||||
 | 
			
		||||
menu_1_3_inline_add = [
 | 
			
		||||
    [types.InlineKeyboardButton(text="Заполнить заявку", url=INFO_MESSAGES['link_menu_1_3'])],
 | 
			
		||||
]
 | 
			
		||||
menu_1_3_inline = types.InlineKeyboardMarkup(inline_keyboard=menu_1_3_inline_add)
 | 
			
		||||
 | 
			
		||||
menu_2_inline_add = [
 | 
			
		||||
    [types.InlineKeyboardButton(text="Виды сотрудничества с СПбГЭТУ ЛЭТИ", url=INFO_MESSAGES['link_rabotod'])],
 | 
			
		||||
]
 | 
			
		||||
menu_2_inline = types.InlineKeyboardMarkup(inline_keyboard=menu_2_inline_add)
 | 
			
		||||
 | 
			
		||||
menu_3_inline_add = [
 | 
			
		||||
    [types.InlineKeyboardButton(text="Подписаться на Telegram-канал", url=INFO_MESSAGES['public_telegram'])],
 | 
			
		||||
    [types.InlineKeyboardButton(text="Подписаться на группу ВКонтакте", url=INFO_MESSAGES['public_vk'])]
 | 
			
		||||
]
 | 
			
		||||
menu_3_inline = types.InlineKeyboardMarkup(inline_keyboard=menu_3_inline_add)
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# # main menu
 | 
			
		||||
# #----------------------------------------
 | 
			
		||||
# button_menu = [
 | 
			
		||||
#     [types.KeyboardButton(text="Информация о стажировках")],
 | 
			
		||||
#     [types.KeyboardButton(text="Информация о практиках")],
 | 
			
		||||
#     [types.KeyboardButton(text="Раздел вакансий")],
 | 
			
		||||
#     [types.KeyboardButton(text="Раздел для работодателей")],
 | 
			
		||||
#     [types.KeyboardButton(text="Советы по написанию резюме")],
 | 
			
		||||
# ]
 | 
			
		||||
# main_menu = types.ReplyKeyboardMarkup(
 | 
			
		||||
#     keyboard=button_menu,
 | 
			
		||||
#     resize_keyboard=True,
 | 
			
		||||
# )
 | 
			
		||||
# #----------------------------------------
 | 
			
		||||
							
								
								
									
										70
									
								
								app/messages.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								app/messages.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
from app.settings.info import feedback_link
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# messages
 | 
			
		||||
start_message = f'👋 Привет! Я чат-бот Центра развития карьеры СПбГЭТУ ЛЭТИ.\n\nПомогу тебе узнать о стажировках, практиках, вакансиях и многом другом!\n\nВыбери интересующий тебя раздел:'
 | 
			
		||||
error_message = f'⚠️ Ошибка сервера ⚠️\n\nFeedback: @{feedback_link}'
 | 
			
		||||
usestart_message = '🏠 Используй /start'
 | 
			
		||||
byebye_message = '✋ Я всегда рад помочь, обращайтесь.'
 | 
			
		||||
 | 
			
		||||
menu_1_message = 'Выберите интересующий вас раздел:'
 | 
			
		||||
menu_2_message = 'Если вы хотите разместить вакансию или сотрудничать с нашим университетом, ознакомьтесь с информацией здесь:'
 | 
			
		||||
menu_3_message = 'Подпишись на наши каналы, чтобы не пропустить важные новости и обновления:'
 | 
			
		||||
#menu_4_message = 'Подпишись на наши каналы, чтобы не пропустить важные новости и обновления:'
 | 
			
		||||
 | 
			
		||||
menu_1_1_1_message = 'Всё о стажировках:'
 | 
			
		||||
menu_1_1_2_message = 'Информация о практиках:'
 | 
			
		||||
menu_1_1_3_message = 'Все вакансии для студентов и выпускников:'
 | 
			
		||||
 | 
			
		||||
menu_1_1_message = 'Выберите, что вас интересует:'
 | 
			
		||||
menu_1_2_message = 'Подготовь своё резюме правильно! Советы и инструкции доступны здесь:'
 | 
			
		||||
menu_1_3_message = 'Для оформления договора на практику или стажировку воспользуйтесь этим инструментом:'
 | 
			
		||||
 | 
			
		||||
MESSAGES = {
 | 
			
		||||
    'start': start_message,
 | 
			
		||||
    'error': error_message,
 | 
			
		||||
    'usestart': usestart_message,
 | 
			
		||||
    'byebye': byebye_message,
 | 
			
		||||
    # menu
 | 
			
		||||
    'menu_1': menu_1_message,
 | 
			
		||||
    'menu_2': menu_2_message,
 | 
			
		||||
    'menu_3': menu_3_message,
 | 
			
		||||
   # 'menu_4': menu_4_message,
 | 
			
		||||
 | 
			
		||||
    'menu_1_1_1': menu_1_1_1_message,
 | 
			
		||||
    'menu_1_1_2': menu_1_1_2_message,
 | 
			
		||||
    'menu_1_1_3': menu_1_1_3_message,
 | 
			
		||||
 | 
			
		||||
    'menu_1_1': menu_1_1_message,
 | 
			
		||||
    'menu_1_2': menu_1_2_message,
 | 
			
		||||
    'menu_1_3': menu_1_3_message,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# info
 | 
			
		||||
# public_telegram_message = f'https://t.me/doctor_what'
 | 
			
		||||
# public_vk_message = f'https://t.me/doctor_what'
 | 
			
		||||
# link_rabotod_message = f'https://t.me/doctor_what' # (🤝 Работодателям)
 | 
			
		||||
 | 
			
		||||
# link_menu_1_1_1_message = f'https://t.me/doctor_what' # (📚 Стажировки)
 | 
			
		||||
# link_menu_1_1_2_message = f'https://t.me/doctor_what' # (🛠 Практики)
 | 
			
		||||
# link_menu_1_1_3_message = f'https://t.me/doctor_what' # (💼 Вакансии)
 | 
			
		||||
 | 
			
		||||
# link_menu_1_2_message = f'https://t.me/doctor_what' # (✍️ Советы по резюме)
 | 
			
		||||
# link_menu_1_3_message = f'https://t.me/doctor_what' # (📄 Оформление договора)
 | 
			
		||||
from app.settings.info import public_telegram_message, public_vk_message, link_rabotod_message, \
 | 
			
		||||
    link_menu_1_1_1_message, link_menu_1_1_2_message, link_menu_1_1_3_message, \
 | 
			
		||||
    link_menu_1_2_message, link_menu_1_3_message
 | 
			
		||||
 | 
			
		||||
INFO_MESSAGES = {
 | 
			
		||||
    'public_telegram': public_telegram_message,
 | 
			
		||||
    'public_vk': public_vk_message,
 | 
			
		||||
    'link_rabotod': link_rabotod_message,
 | 
			
		||||
 | 
			
		||||
    'link_menu_1_1_1': link_menu_1_1_1_message,
 | 
			
		||||
    'link_menu_1_1_2': link_menu_1_1_2_message,
 | 
			
		||||
    'link_menu_1_1_3': link_menu_1_1_3_message,
 | 
			
		||||
 | 
			
		||||
    'link_menu_1_2': link_menu_1_2_message,
 | 
			
		||||
    'link_menu_1_3': link_menu_1_3_message,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								app/settings/config example.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/settings/config example.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
DEBUG = False
 | 
			
		||||
TOKEN = "" # bot token
 | 
			
		||||
CHANNEL_WHITELIST = "" # -100+channel_id (-100474747474747474747474747)
 | 
			
		||||
							
								
								
									
										15
									
								
								app/settings/info.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								app/settings/info.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
# ни на что не влияет, только кастомизация сообщений
 | 
			
		||||
bot_link = 'test_BOT'
 | 
			
		||||
feedback_link = 'test_FeedBack_Bot'
 | 
			
		||||
public_link = 'test_Public'
 | 
			
		||||
 | 
			
		||||
public_telegram_message = 'https://publictelegrammessage.ru'
 | 
			
		||||
public_vk_message = 'https://publicvkmessage.ru'
 | 
			
		||||
link_rabotod_message = 'https://linkrabotodmessage.ru' # (🤝 Работодателям)
 | 
			
		||||
 | 
			
		||||
link_menu_1_1_1_message = 'https://linkmenu111message.ru' # (📚 Стажировки)
 | 
			
		||||
link_menu_1_1_2_message = 'https://linkmenu112message.ru' # (🛠 Практики)
 | 
			
		||||
link_menu_1_1_3_message = 'https://linkmenu113message.ru' # (💼 Вакансии)
 | 
			
		||||
 | 
			
		||||
link_menu_1_2_message = 'https://linkmenu12message.ru' # (✍️ Советы по резюме)
 | 
			
		||||
link_menu_1_3_message = 'https://linkmenu13message.ru' # (📄 Оформление договора)
 | 
			
		||||
							
								
								
									
										5
									
								
								autostart/telegram_bot.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								autostart/telegram_bot.bat
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
@echo off
 | 
			
		||||
REM скрипт автозапуска. Win + R, shell:startup Скопируйте туда этот BAT-файл.
 | 
			
		||||
cd /d G:\your_location\telegram_bot_stomplan
 | 
			
		||||
.\env\Scripts\python server.py
 | 
			
		||||
pause
 | 
			
		||||
							
								
								
									
										4
									
								
								autostart/telegram_bot_hidden.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								autostart/telegram_bot_hidden.bat
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
@echo off
 | 
			
		||||
REM скрипт автозапуска hidden. Win + R, shell:startup Скопируйте туда этот BAT-файл.
 | 
			
		||||
cd /d G:\your_location\telegram_bot_stomplan
 | 
			
		||||
.\env\Scripts\pythonw.exe server.py
 | 
			
		||||
							
								
								
									
										4
									
								
								install.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								install.bat
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
@echo off
 | 
			
		||||
REM
 | 
			
		||||
python app/install.py
 | 
			
		||||
pause
 | 
			
		||||
							
								
								
									
										1
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
aiogram==3.15
 | 
			
		||||
							
								
								
									
										224
									
								
								server.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								server.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,224 @@
 | 
			
		||||
import asyncio
 | 
			
		||||
import os
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
from aiogram import Bot, Dispatcher, F, Router, types
 | 
			
		||||
from aiogram.fsm.context import FSMContext
 | 
			
		||||
from aiogram.fsm.state import State, StatesGroup
 | 
			
		||||
from aiogram.fsm.storage.memory import MemoryStorage
 | 
			
		||||
from aiogram.filters import Command, StateFilter
 | 
			
		||||
from aiogram.types import Message
 | 
			
		||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
 | 
			
		||||
 | 
			
		||||
import app.keyboards as kb
 | 
			
		||||
from app.messages import MESSAGES
 | 
			
		||||
from app.settings.config import DEBUG, TOKEN, CHANNEL_WHITELIST
 | 
			
		||||
from app.settings.info import bot_link
 | 
			
		||||
from app.database.loader_db import check_bd, check_config
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#запуск
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
check_bd()
 | 
			
		||||
check_config()
 | 
			
		||||
 | 
			
		||||
dp = Dispatcher(storage=MemoryStorage())
 | 
			
		||||
bot = Bot(token=TOKEN)
 | 
			
		||||
router = Router()
 | 
			
		||||
 | 
			
		||||
from app.database.db_connector import ALLusers
 | 
			
		||||
checkuser = ALLusers('app/database/data/database.db')
 | 
			
		||||
available_da = ["Да"]
 | 
			
		||||
 | 
			
		||||
async def main():
 | 
			
		||||
    if DEBUG: print('DEBUG mode')
 | 
			
		||||
    print(f'Bot start @{bot_link}')
 | 
			
		||||
    await bot.delete_webhook(drop_pending_updates=True)
 | 
			
		||||
    await dp.start_polling(bot)
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# access
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
async def check_admin(message_chat_id):
 | 
			
		||||
    try:
 | 
			
		||||
        channel_id = CHANNEL_WHITELIST
 | 
			
		||||
        user_channel_status = await bot.get_chat_member(chat_id=channel_id, user_id=message_chat_id)
 | 
			
		||||
        if DEBUG:
 | 
			
		||||
            print('---------------------------------------')
 | 
			
		||||
            print('user_channel_status', user_channel_status.status)
 | 
			
		||||
            print('---------------------------------------')
 | 
			
		||||
 | 
			
		||||
        if ((user_channel_status.status == 'creator') or (user_channel_status.status == 'administrator')):
 | 
			
		||||
            if DEBUG:
 | 
			
		||||
                print('Admin access')
 | 
			
		||||
            return True
 | 
			
		||||
        return False
 | 
			
		||||
    except:
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
async def check_subscribe(message_from_user_id, message_chat_id):
 | 
			
		||||
    try:
 | 
			
		||||
        channel_id = CHANNEL_WHITELIST
 | 
			
		||||
        user_channel_status = await bot.get_chat_member(chat_id=channel_id, user_id=message_chat_id)
 | 
			
		||||
        if DEBUG:
 | 
			
		||||
            print('---------------------------------------')
 | 
			
		||||
            print('user_channel_status:',user_channel_status)
 | 
			
		||||
            print('user_channel_status', user_channel_status.status)
 | 
			
		||||
            print('---------------------------------------')
 | 
			
		||||
 | 
			
		||||
        if ((user_channel_status.status != 'left') and (user_channel_status.status != 'kicked')):
 | 
			
		||||
            return True
 | 
			
		||||
        else:
 | 
			
		||||
            await bot.send_message(message_from_user_id, MESSAGES['no_sub'], parse_mode="HTML")
 | 
			
		||||
            return False
 | 
			
		||||
    except:
 | 
			
		||||
        await bot.send_message(message_from_user_id, MESSAGES['error'])
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
async def check_access(message):
 | 
			
		||||
    try:
 | 
			
		||||
        if (not checkuser.search_user(message.from_user.id)):
 | 
			
		||||
            # если юзера нет в базе, добавляем
 | 
			
		||||
            try:
 | 
			
		||||
                checkuser.add_user(message.from_user.id)
 | 
			
		||||
            except:
 | 
			
		||||
                if DEBUG:
 | 
			
		||||
                    print("Critical error check_access 1")
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
        # checkSubscribe = await check_subscribe(message.from_user.id, message.chat.id)
 | 
			
		||||
        # if (checkSubscribe != True):
 | 
			
		||||
        #     return False
 | 
			
		||||
        print("message_from_user", message.from_user.id)
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    except:
 | 
			
		||||
        if DEBUG:
 | 
			
		||||
            print("Critical error check_access 2")
 | 
			
		||||
 | 
			
		||||
async def check_subscribe_spam(message_chat_id):
 | 
			
		||||
    try:
 | 
			
		||||
        channel_id = CHANNEL_WHITELIST
 | 
			
		||||
        user_channel_status = await bot.get_chat_member(chat_id=channel_id, user_id=message_chat_id)
 | 
			
		||||
        if DEBUG:
 | 
			
		||||
            print('---------------------------------------')
 | 
			
		||||
            print('user_channel_status:',user_channel_status)
 | 
			
		||||
            print('user_channel_status', user_channel_status.status)
 | 
			
		||||
            print('---------------------------------------')
 | 
			
		||||
 | 
			
		||||
        if ((user_channel_status.status != 'left') and (user_channel_status.status != 'kicked')):
 | 
			
		||||
            return True
 | 
			
		||||
        else:
 | 
			
		||||
            return False
 | 
			
		||||
    except:
 | 
			
		||||
        return False
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# form
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
class Form(StatesGroup):
 | 
			
		||||
    search_0 = State()
 | 
			
		||||
    waiting_for_file = State()
 | 
			
		||||
    waiting_for_file_pause = State()
 | 
			
		||||
    register = State()
 | 
			
		||||
    register_pause = State()
 | 
			
		||||
 | 
			
		||||
    prespam = State()
 | 
			
		||||
    spam = State()
 | 
			
		||||
    spam_pause = State()
 | 
			
		||||
 | 
			
		||||
@dp.message(Command("cancel"))
 | 
			
		||||
@dp.message(F.text.casefold() == "Отмена" or F.text.casefold() == "старт" or F.text.casefold() == "/старт" or F.text.casefold() == "🏠 Главная")
 | 
			
		||||
@dp.message(lambda message: ((message.text == "Отмена") or (message.text == "старт")  or (message.text == "/старт")))
 | 
			
		||||
async def cancel_handler(message: Message, state: FSMContext) -> None:
 | 
			
		||||
    current_state = await state.get_state()
 | 
			
		||||
    checkAccess = await check_access(message)
 | 
			
		||||
    if current_state is None:
 | 
			
		||||
        checkAccess = await check_access(message)
 | 
			
		||||
        if checkAccess:
 | 
			
		||||
            await message.answer(MESSAGES['start'], reply_markup=kb.main_menu)
 | 
			
		||||
        return
 | 
			
		||||
    await state.clear()
 | 
			
		||||
    if checkAccess:
 | 
			
		||||
        await message.answer(MESSAGES['byebye'], reply_markup=kb.main_menu)
 | 
			
		||||
    return
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@dp.message(Command("start"))
 | 
			
		||||
async def process_start_command(message: types.Message):
 | 
			
		||||
    checkAccess = await check_access(message)
 | 
			
		||||
    if checkAccess:
 | 
			
		||||
        await message.answer(MESSAGES['start'], reply_markup=kb.main_menu)
 | 
			
		||||
    return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@dp.message(StateFilter(None), F.text)
 | 
			
		||||
async def do_main_menu(message: Message, state: FSMContext):
 | 
			
		||||
    txt = message.text
 | 
			
		||||
    try:
 | 
			
		||||
        checkAccess = await check_access(message)
 | 
			
		||||
        if not checkAccess:
 | 
			
		||||
            return await message.answer(MESSAGES['usestart'])
 | 
			
		||||
        if txt == '/admin':
 | 
			
		||||
            checkAdmin = await check_admin(message.chat.id)
 | 
			
		||||
            if checkAdmin:
 | 
			
		||||
                how_users = checkuser.log_info()
 | 
			
		||||
                answer = (f"Пользователей зарегистрировано: {how_users[0]}\n\n"\
 | 
			
		||||
                    f"Рассылка - /spam")
 | 
			
		||||
                return await message.reply(answer)
 | 
			
		||||
            else:
 | 
			
		||||
                return await message.answer(MESSAGES['usestart'])
 | 
			
		||||
 | 
			
		||||
        # elif txt == '/spam':
 | 
			
		||||
        #     checkAdmin = await check_admin(message.chat.id)
 | 
			
		||||
        #     if checkAdmin:
 | 
			
		||||
        #         answer = (f"Для кого рассылка?")
 | 
			
		||||
        #         await message.reply(answer, reply_markup=kb.spam)
 | 
			
		||||
        #         return await state.set_state(Form.prespam)
 | 
			
		||||
        #     else:
 | 
			
		||||
        #         return await message.answer(MESSAGES['usestart'])
 | 
			
		||||
 | 
			
		||||
        # главное меню
 | 
			
		||||
        if txt == '🏠 Главная':
 | 
			
		||||
            return await message.answer(MESSAGES['start'], reply_markup=kb.main_menu)
 | 
			
		||||
        elif txt == '📚 Студентам':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_1'], reply_markup=kb.menu_1)
 | 
			
		||||
        elif txt == '🤝 Работодателям':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_2'], reply_markup=kb.menu_2_inline)
 | 
			
		||||
        elif txt == 'ℹ️ О центре':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_3'], reply_markup=kb.menu_3_inline)
 | 
			
		||||
        # elif txt == '📰 Подписка на новости':
 | 
			
		||||
        #     return await message.answer(MESSAGES['menu_4'], reply_markup=kb.menu_4_inline)
 | 
			
		||||
        # студентам (1)
 | 
			
		||||
        elif txt == '🔙 Назад':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_1'], reply_markup=kb.menu_1)
 | 
			
		||||
        elif txt == '📖 Стажировки, практики и вакансии':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_1_1'], reply_markup=kb.menu_1_1)
 | 
			
		||||
        elif txt == '✍️ Советы по резюме':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_1_2'], reply_markup=kb.menu_1_2_inline)
 | 
			
		||||
        elif txt == '📄 Оформление договора':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_1_3'], reply_markup=kb.menu_1_3_inline)
 | 
			
		||||
        # студентам (1_1)
 | 
			
		||||
        elif txt == '📚 Стажировки':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_1_1_1'], reply_markup=kb.menu_1_1_1_inline)
 | 
			
		||||
        elif txt == '🛠 Практики':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_1_1_2'], reply_markup=kb.menu_1_1_2_inline)
 | 
			
		||||
        elif txt == '💼 Вакансии':
 | 
			
		||||
            return await message.answer(MESSAGES['menu_1_1_3'], reply_markup=kb.menu_1_1_3_inline)
 | 
			
		||||
        else:
 | 
			
		||||
            return await message.answer(MESSAGES['usestart'])
 | 
			
		||||
    # Для выведения ошибок
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        await message.answer(MESSAGES['error'])
 | 
			
		||||
        print('----------------------------------------')
 | 
			
		||||
        print(f'Critical error in: {e}')
 | 
			
		||||
        print('----------------------------------------')
 | 
			
		||||
#----------------------------------------
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    asyncio.run(main())
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user