├── admin ├── __init__.py ├── analysis │ ├── __init__.py │ └── vizual_part.py ├── keyboards │ ├── __init__.py │ ├── admin_kb.py │ └── inlines.py └── handlers │ ├── __init__.py │ ├── others.py │ └── admin.py ├── analysis ├── __init__.py ├── image.jpg ├── query.py ├── requirements.txt ├── Google_servis_data.json └── app.py ├── data ├── save_row.json ├── password.json ├── user.db ├── __init__.py ├── visual │ ├── umumiy │ │ ├── yonalish │ │ │ ├── all.png │ │ │ └── all2.png │ │ └── mentor │ │ │ ├── Full Stack.png │ │ │ ├── Data Science.png │ │ │ ├── Full Stack_1.png │ │ │ ├── Data Science_1.png │ │ │ ├── Software Engineering.png │ │ │ └── Software Engineering_1.png │ └── directions │ │ ├── full_stack │ │ ├── Aziza Azizova_1.png │ │ ├── Aziza Azizova_2.png │ │ ├── Jasur Shukurov_1.png │ │ └── Jasur Shukurov_2.png │ │ ├── software │ │ ├── Sarvarbek Azodov_1.png │ │ ├── Sarvarbek Azodov_2.png │ │ ├── Sirojiddin Olloyorov_1.png │ │ └── Sirojiddin Olloyorov_2.png │ │ └── data_science │ │ ├── Nodira Arslanova_1.png │ │ ├── Nodira Arslanova_2.png │ │ ├── Abdulaziz Orifjanov_1.png │ │ ├── Abdulaziz Orifjanov_2.png │ │ ├── Asalbonu Alambayeva_1.png │ │ ├── Asalbonu Alambayeva_2.png │ │ ├── Komiljon Khamidjonov_1.png │ │ └── Komiljon Khamidjonov_2.png ├── config.py ├── create_db.py ├── query.py ├── Google_servis_data.json ├── google_sheet.py └── feedback.csv ├── utils ├── db_api │ └── __init__.py ├── misc │ ├── __init__.py │ ├── logging.py │ └── throttling.py ├── __init__.py ├── set_bot_commands.py └── notify_admins.py ├── states ├── __init__.py └── student_part_state.py ├── keyboards ├── default │ ├── __init__.py │ └── menu_keyboard.py ├── __init__.py └── inline │ ├── __init__.py │ ├── callback_data.py │ └── student_parts.py ├── handlers ├── errors │ ├── __init__.py │ └── error_handler.py ├── __init__.py └── users │ ├── __init__.py │ ├── echo.py │ ├── admin.py │ ├── help.py │ ├── start.py │ └── student_part_handler.py ├── env_sample.txt ├── requirements.txt ├── filters └── __init__.py ├── middlewares ├── __init__.py └── throttling.py ├── Pipfile ├── loader.py ├── start.sh ├── app.py ├── .devcontainer └── devcontainer.json ├── README.md ├── .gitignore └── Pipfile.lock /admin/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /analysis/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/save_row.json: -------------------------------------------------------------------------------- 1 | 75 -------------------------------------------------------------------------------- /admin/analysis/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/password.json: -------------------------------------------------------------------------------- 1 | "1111" -------------------------------------------------------------------------------- /utils/db_api/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /states/__init__.py: -------------------------------------------------------------------------------- 1 | from . import student_part_state -------------------------------------------------------------------------------- /keyboards/default/__init__.py: -------------------------------------------------------------------------------- 1 | from . import menu_keyboard -------------------------------------------------------------------------------- /handlers/errors/__init__.py: -------------------------------------------------------------------------------- 1 | from . import error_handler 2 | -------------------------------------------------------------------------------- /handlers/__init__.py: -------------------------------------------------------------------------------- 1 | from . import errors 2 | from . import users 3 | -------------------------------------------------------------------------------- /admin/keyboards/__init__.py: -------------------------------------------------------------------------------- 1 | from . import admin_kb 2 | from . import inlines -------------------------------------------------------------------------------- /keyboards/__init__.py: -------------------------------------------------------------------------------- 1 | from . import default 2 | from . import inline 3 | -------------------------------------------------------------------------------- /admin/handlers/__init__.py: -------------------------------------------------------------------------------- 1 | from . import others 2 | from . import admin 3 | 4 | -------------------------------------------------------------------------------- /env_sample.txt: -------------------------------------------------------------------------------- 1 | BOT_TOKEN="YOUR BOT TOKEN" 2 | ADMINS="YOUR ID" 3 | ip="localhost" -------------------------------------------------------------------------------- /utils/misc/__init__.py: -------------------------------------------------------------------------------- 1 | from .throttling import rate_limit 2 | from . import logging 3 | -------------------------------------------------------------------------------- /data/user.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/user.db -------------------------------------------------------------------------------- /keyboards/inline/__init__.py: -------------------------------------------------------------------------------- 1 | from . import callback_data 2 | from . import student_parts 3 | -------------------------------------------------------------------------------- /data/__init__.py: -------------------------------------------------------------------------------- 1 | from . import query 2 | from . import config 3 | from . import google_sheet 4 | -------------------------------------------------------------------------------- /analysis/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/analysis/image.jpg -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- 1 | from . import db_api 2 | from . import misc 3 | from .notify_admins import on_startup_notify 4 | -------------------------------------------------------------------------------- /data/visual/umumiy/yonalish/all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/umumiy/yonalish/all.png -------------------------------------------------------------------------------- /data/visual/umumiy/yonalish/all2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/umumiy/yonalish/all2.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiogram==2.23.1 2 | google-api-python-client==2.66.0 3 | pandas==1.5.2 4 | environs==9.5.0 5 | plotly==5.11.0 6 | Pillow==9.3.0 -------------------------------------------------------------------------------- /data/visual/umumiy/mentor/Full Stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/umumiy/mentor/Full Stack.png -------------------------------------------------------------------------------- /data/visual/umumiy/mentor/Data Science.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/umumiy/mentor/Data Science.png -------------------------------------------------------------------------------- /data/visual/umumiy/mentor/Full Stack_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/umumiy/mentor/Full Stack_1.png -------------------------------------------------------------------------------- /data/visual/umumiy/mentor/Data Science_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/umumiy/mentor/Data Science_1.png -------------------------------------------------------------------------------- /data/visual/umumiy/mentor/Software Engineering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/umumiy/mentor/Software Engineering.png -------------------------------------------------------------------------------- /handlers/users/__init__.py: -------------------------------------------------------------------------------- 1 | from . import help 2 | from . import admin 3 | from . import student_part_handler 4 | from . import start 5 | from . import echo 6 | 7 | -------------------------------------------------------------------------------- /data/visual/directions/full_stack/Aziza Azizova_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/full_stack/Aziza Azizova_1.png -------------------------------------------------------------------------------- /data/visual/directions/full_stack/Aziza Azizova_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/full_stack/Aziza Azizova_2.png -------------------------------------------------------------------------------- /data/visual/umumiy/mentor/Software Engineering_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/umumiy/mentor/Software Engineering_1.png -------------------------------------------------------------------------------- /data/visual/directions/full_stack/Jasur Shukurov_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/full_stack/Jasur Shukurov_1.png -------------------------------------------------------------------------------- /data/visual/directions/full_stack/Jasur Shukurov_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/full_stack/Jasur Shukurov_2.png -------------------------------------------------------------------------------- /data/visual/directions/software/Sarvarbek Azodov_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/software/Sarvarbek Azodov_1.png -------------------------------------------------------------------------------- /data/visual/directions/software/Sarvarbek Azodov_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/software/Sarvarbek Azodov_2.png -------------------------------------------------------------------------------- /data/visual/directions/data_science/Nodira Arslanova_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/data_science/Nodira Arslanova_1.png -------------------------------------------------------------------------------- /data/visual/directions/data_science/Nodira Arslanova_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/data_science/Nodira Arslanova_2.png -------------------------------------------------------------------------------- /data/visual/directions/software/Sirojiddin Olloyorov_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/software/Sirojiddin Olloyorov_1.png -------------------------------------------------------------------------------- /data/visual/directions/software/Sirojiddin Olloyorov_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/software/Sirojiddin Olloyorov_2.png -------------------------------------------------------------------------------- /data/visual/directions/data_science/Abdulaziz Orifjanov_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/data_science/Abdulaziz Orifjanov_1.png -------------------------------------------------------------------------------- /data/visual/directions/data_science/Abdulaziz Orifjanov_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/data_science/Abdulaziz Orifjanov_2.png -------------------------------------------------------------------------------- /data/visual/directions/data_science/Asalbonu Alambayeva_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/data_science/Asalbonu Alambayeva_1.png -------------------------------------------------------------------------------- /data/visual/directions/data_science/Asalbonu Alambayeva_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/data_science/Asalbonu Alambayeva_2.png -------------------------------------------------------------------------------- /data/visual/directions/data_science/Komiljon Khamidjonov_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/data_science/Komiljon Khamidjonov_1.png -------------------------------------------------------------------------------- /data/visual/directions/data_science/Komiljon Khamidjonov_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdullaabdukulov/astrum-feedback-bot/HEAD/data/visual/directions/data_science/Komiljon Khamidjonov_2.png -------------------------------------------------------------------------------- /filters/__init__.py: -------------------------------------------------------------------------------- 1 | from aiogram import Dispatcher 2 | 3 | from loader import dp 4 | # from .is_admin import AdminFilter 5 | 6 | 7 | if __name__ == "filters": 8 | #dp.filters_factory.bind(is_admin) 9 | pass 10 | -------------------------------------------------------------------------------- /middlewares/__init__.py: -------------------------------------------------------------------------------- 1 | from aiogram import Dispatcher 2 | 3 | from loader import dp 4 | from .throttling import ThrottlingMiddleware 5 | 6 | 7 | if __name__ == "middlewares": 8 | dp.middleware.setup(ThrottlingMiddleware()) 9 | -------------------------------------------------------------------------------- /handlers/users/echo.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | 3 | from loader import dp 4 | 5 | 6 | # Echo bot 7 | @dp.message_handler(state=None) 8 | async def bot_echo(message: types.Message): 9 | await message.answer(message.text) 10 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | aiogram = "~=2.14" 8 | environs = "~=8.0.0" 9 | 10 | [dev-packages] 11 | 12 | [requires] 13 | python_version = "3.9" 14 | -------------------------------------------------------------------------------- /states/student_part_state.py: -------------------------------------------------------------------------------- 1 | from aiogram.dispatcher.filters.state import StatesGroup, State 2 | 3 | 4 | class Student_part_state(StatesGroup): 5 | yonalishlar = State() 6 | mentorlar = State() 7 | feed3 = State() 8 | sabab = State() 9 | chenged = State() 10 | -------------------------------------------------------------------------------- /keyboards/default/menu_keyboard.py: -------------------------------------------------------------------------------- 1 | from aiogram.types import ReplyKeyboardMarkup, KeyboardButton 2 | 3 | menu = ReplyKeyboardMarkup( 4 | keyboard=[[ 5 | KeyboardButton(text="Mentorga feedback qoldirish") 6 | ]], 7 | resize_keyboard=True, one_time_keyboard=True 8 | ) 9 | -------------------------------------------------------------------------------- /loader.py: -------------------------------------------------------------------------------- 1 | from aiogram import Bot, Dispatcher, types 2 | from aiogram.contrib.fsm_storage.memory import MemoryStorage 3 | from data import config 4 | 5 | bot = Bot(token=config.BOT_TOKEN, parse_mode=types.ParseMode.HTML) 6 | storage = MemoryStorage() 7 | dp = Dispatcher(bot, storage=storage) 8 | -------------------------------------------------------------------------------- /utils/set_bot_commands.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | 3 | 4 | async def set_default_commands(dp): 5 | await dp.bot.set_my_commands( 6 | [ 7 | types.BotCommand("start", "Botni ishga tushurish"), 8 | types.BotCommand("help", "Yordam"), 9 | ] 10 | ) 11 | -------------------------------------------------------------------------------- /utils/misc/logging.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | logging.basicConfig(format=u'%(filename)s [LINE:%(lineno)d] #%(levelname)-8s [%(asctime)s] %(message)s', 4 | level=logging.INFO, 5 | # level=logging.DEBUG, # Можно заменить на другой уровень логгирования. 6 | ) 7 | -------------------------------------------------------------------------------- /data/config.py: -------------------------------------------------------------------------------- 1 | from environs import Env 2 | 3 | # environs kutubxonasidan foydalanish 4 | env = Env() 5 | env.read_env() 6 | 7 | # .env fayl ichidan quyidagilarni o'qiymiz 8 | BOT_TOKEN = env.str("BOT_TOKEN") # Bot toekn 9 | ADMINS = env.list("ADMINS") # adminlar ro'yxati 10 | IP = env.str("ip") # Xosting ip manzili 11 | -------------------------------------------------------------------------------- /keyboards/inline/callback_data.py: -------------------------------------------------------------------------------- 1 | from aiogram.utils.callback_data import CallbackData 2 | 3 | data = CallbackData("DS", "item_name") 4 | full = CallbackData("FS", "item_name") 5 | soft = CallbackData("SE", "item_name") 6 | 7 | feed1 = CallbackData("q_li", "item_feed") 8 | feed2 = CallbackData("n_li", "item_feed") 9 | feed3 = CallbackData("q_siz", "item_feed") -------------------------------------------------------------------------------- /utils/notify_admins.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from aiogram import Dispatcher 4 | 5 | from data.config import ADMINS 6 | 7 | 8 | async def on_startup_notify(dp: Dispatcher): 9 | for admin in ADMINS: 10 | try: 11 | await dp.bot.send_message(admin, "Bot ishga tushdi") 12 | 13 | except Exception as err: 14 | logging.exception(err) 15 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Function to generate .env file 4 | generate_env_file() { 5 | echo "Generating .env file..." 6 | echo "BOT_TOKEN=\"YOUR BOT TOKEN\"" > .env 7 | echo "ADMINS=\"YOUR ID\"" >> .env 8 | echo "ip=\"localhost\"" >> .env 9 | echo "Done." 10 | } 11 | 12 | if [ -f .env]; then 13 | echo ".env file already exists." 14 | else 15 | generate_env_file 16 | fi 17 | -------------------------------------------------------------------------------- /handlers/users/admin.py: -------------------------------------------------------------------------------- 1 | from aiogram import types 2 | 3 | from data import config 4 | from keyboards.default.menu_keyboard import menu 5 | from loader import dp 6 | 7 | admins = config.ADMINS 8 | 9 | 10 | @dp.message_handler(chat_id=admins, commands="start") 11 | async def admins_answer(msg: types.Message): 12 | await msg.answer(f"Assalomu Alaykum\nXush kelibsiz SupperUser {msg.from_user.full_name}", reply_markup=menu) 13 | 14 | -------------------------------------------------------------------------------- /utils/misc/throttling.py: -------------------------------------------------------------------------------- 1 | def rate_limit(limit: int, key=None): 2 | """ 3 | Decorator for configuring rate limit and key in different functions. 4 | 5 | :param limit: 6 | :param key: 7 | :return: 8 | """ 9 | 10 | def decorator(func): 11 | setattr(func, 'throttling_rate_limit', limit) 12 | if key: 13 | setattr(func, 'throttling_key', key) 14 | return func 15 | 16 | return decorator 17 | -------------------------------------------------------------------------------- /handlers/users/help.py: -------------------------------------------------------------------------------- 1 | from aiogram import types, Dispatcher 2 | from aiogram.dispatcher.filters.builtin import CommandHelp 3 | 4 | from loader import dp 5 | 6 | 7 | @dp.message_handler(CommandHelp()) 8 | async def bot_help(message: types.Message): 9 | text = ("Buyruqlar: ", 10 | "/start - Botni ishga tushirish", 11 | "/admin - Admin panelga kirish", 12 | "/analysis - Mentorlar analitikasiga kirish", 13 | "/direction - Yo'nalishni o'zgartirish") 14 | await message.answer("\n".join(text)) 15 | 16 | 17 | def register_handler_help(db: Dispatcher): 18 | dp.message_handler(bot_help, commands=['admin']) -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from aiogram import executor 2 | from admin.handlers import admin 3 | from handlers.users.help import register_handler_help 4 | from loader import dp 5 | from utils.notify_admins import on_startup_notify 6 | from utils.set_bot_commands import set_default_commands 7 | 8 | 9 | async def on_startup(dispatcher): 10 | # Birlamchi komandalar (/star va /help) 11 | await set_default_commands(dispatcher) 12 | 13 | # Bot ishga tushgani haqida adminga xabar berish 14 | await on_startup_notify(dispatcher) 15 | admin.register_handler_admin(dp) 16 | register_handler_help(dp) 17 | 18 | 19 | if __name__ == '__main__': 20 | executor.start_polling(dp, on_startup=on_startup) 21 | 22 | -------------------------------------------------------------------------------- /analysis/query.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | from pathlib import Path 3 | 4 | BASE_DIR = Path(__file__).resolve().parent.parent # /Users/student/web_scraping/astrum-feedback-bot 5 | 6 | db_file = f"{BASE_DIR}/data/user.db" 7 | 8 | 9 | def all_mentors(): 10 | conn = sqlite3.connect(db_file) 11 | cursor = conn.cursor() 12 | data = cursor.execute("""SELECT full_name, directions FROM mentors""") 13 | result = [] 14 | for i in data.fetchall(): 15 | result.append(i) 16 | cursor.close() 17 | result_2 = {"ds_mentors": ['Umumiy analitika'], "se_mentors": ['Umumiy analitika'], 18 | "fs_mentors": ['Umumiy analitika']} 19 | 20 | for a in result: 21 | if a[1] == 'DS': 22 | result_2['ds_mentors'].append(a[0]) 23 | elif a[1] == 'SE': 24 | result_2['se_mentors'].append(a[0]) 25 | elif a[1] == 'FS': 26 | result_2['fs_mentors'].append(a[0]) 27 | 28 | return result_2 29 | 30 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Python 3", 3 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 4 | "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye", 5 | "customizations": { 6 | "codespaces": { 7 | "openFiles": [ 8 | "README.md", 9 | "analysis/app.py" 10 | ] 11 | }, 12 | "vscode": { 13 | "settings": {}, 14 | "extensions": [ 15 | "ms-python.python", 16 | "ms-python.vscode-pylance" 17 | ] 18 | } 19 | }, 20 | "updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y Astrum Feedback Bot 2 | 3 | Снимок экрана 2022-10-24 в 10 56 08 4 |

The Astrum Feedback Bot is a Telegram bot designed to collect feedback from students about their mentors. It allows students to anonymously rate their mentors based on their performance, and also provide feedback on why they gave that particular rating. The bot is specifically designed for use within Astrum IT School, a coding school based in Tashkent, Uzbekistan.

5 | 6 |

The Astrum Feedback Bot is easy to use and provides a user-friendly interface for students to give feedback. The bot uses inline keyboards to present students with options for rating their mentors and providing feedback, making it quick and simple for students to give their opinions. Additionally, the bot is designed to be responsive and reliable, ensuring that students can always access the bot when they need it.

7 | 8 |

One of the key advantages of the Astrum Feedback Bot is that it provides a safe and anonymous space for students to give feedback. Students do not have to worry about any negative consequences for providing honest feedback, as their ratings and feedback are not linked to their identities. This encourages students to be more honest and open about their experiences, which in turn helps mentors to improve and provide better support to their students.

9 | 10 |

Overall, the Astrum Feedback Bot is an effective tool for collecting feedback from students in a safe and anonymous way. It provides a valuable resource for mentors and the school administration to improve the quality of education and support provided to students, helping to create a better learning environment for everyone.

11 | 12 | 13 | 14 | 15 | Learn more 16 | 17 | 18 | ## Demo 19 | 20 |

Check out our demo version of the web part of the project here.

21 | 22 |

Check out our demo version of the GoogleSheets part of the project here.

23 | 24 |

Check out our demo version of the telegram bot part of the project here.

-------------------------------------------------------------------------------- /data/google_sheet.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pathlib import Path 3 | from googleapiclient.discovery import build 4 | from google.oauth2 import service_account 5 | import datetime 6 | from data.query import save_row 7 | 8 | BASE_DIR = Path(__file__).resolve().parent.parent 9 | service_account_file = f'{BASE_DIR}/data/Google_servis_data.json' 10 | 11 | SCOPES = ["https://spreadsheets.google.com/feeds", 'https://www.googleapis.com/auth/spreadsheets', 12 | "https://www.googleapis.com/auth/drive.file", "https://www.googleapis.com/auth/drive"] 13 | 14 | creds = service_account.Credentials.from_service_account_file(service_account_file, scopes=SCOPES) 15 | 16 | SAMPLE_SPREADSHEET_ID = '1rgfEQdRBtD-AXtu3kfAvTUEwe0qkOpY2RRLSsGDBlrw' 17 | 18 | service = build('sheets', 'v4', credentials=creds) 19 | 20 | sheet = service.spreadsheets() 21 | 22 | 23 | with open(f'{BASE_DIR}/data/save_row.json', 'r') as f: 24 | s = json.load(f) 25 | f.close() 26 | sheets_num = s 27 | 28 | 29 | def google_sheet_add(data): 30 | for i in range(len(data)+2): 31 | if i == 0: 32 | updated = data[0] 33 | sheet.values().update(spreadsheetId=SAMPLE_SPREADSHEET_ID, 34 | range=f"sheet1!A{sheets_num}", valueInputOption="USER_ENTERED", 35 | body={'values': [[updated]]}).execute() 36 | 37 | elif i == 1: 38 | updated = data[1] 39 | sheet.values().update(spreadsheetId=SAMPLE_SPREADSHEET_ID, 40 | range=f"sheet1!B{sheets_num}", valueInputOption="USER_ENTERED", 41 | body={'values': [[updated]]}).execute() 42 | 43 | elif i == 2: 44 | updated = data[2] 45 | sheet.values().update(spreadsheetId=SAMPLE_SPREADSHEET_ID, 46 | range=f"sheet1!C{sheets_num}", valueInputOption="USER_ENTERED", 47 | body={'values': [[updated]]}).execute() 48 | 49 | elif i == 3: 50 | updated = data[3] 51 | sheet.values().update(spreadsheetId=SAMPLE_SPREADSHEET_ID, 52 | range=f"sheet1!D{sheets_num}", valueInputOption="USER_ENTERED", 53 | body={'values': [[updated]]}).execute() 54 | 55 | elif i == 4: 56 | updated = data[4] 57 | sheet.values().update(spreadsheetId=SAMPLE_SPREADSHEET_ID, 58 | range=f"sheet1!E{sheets_num}", valueInputOption="USER_ENTERED", 59 | body={'values': [[updated]]}).execute() 60 | 61 | elif i == 5: 62 | updated = datetime.datetime.now().strftime("%Y-%m-%d") 63 | sheet.values().update(spreadsheetId=SAMPLE_SPREADSHEET_ID, 64 | range=f"sheet1!F{sheets_num}", valueInputOption="USER_ENTERED", 65 | body={'values': [[updated]]}).execute() 66 | 67 | globals()["sheets_num"] += 1 68 | save_row(sheets_num) 69 | -------------------------------------------------------------------------------- /admin/keyboards/inlines.py: -------------------------------------------------------------------------------- 1 | from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup 2 | from admin.handlers.others import all_mentor_full_name, all_admin_full_name, all_view_full_name, \ 3 | all_ds, all_fs, all_se 4 | 5 | mentors_add_inl = InlineKeyboardMarkup(row_width=3).add( 6 | InlineKeyboardButton(text='Data Science', callback_data='DS'), 7 | InlineKeyboardButton(text='Full Stack', callback_data='FS'), 8 | InlineKeyboardButton(text='Software Engineering', callback_data='SE'), 9 | ) 10 | 11 | 12 | def all_ment(): 13 | mentors_delete_inl = InlineKeyboardMarkup(row_width=1) 14 | for a in all_mentor_full_name(): 15 | mentors_delete_inl.add(InlineKeyboardButton(text=a, callback_data=a)) 16 | return mentors_delete_inl.add(InlineKeyboardButton(text="🔙 Ortga", callback_data="delete_back_mentor")) 17 | 18 | 19 | def all_admin(): 20 | admin_delete_inl = InlineKeyboardMarkup(row_width=1) 21 | for i in all_admin_full_name(): 22 | if i != 'unique_admin': 23 | admin_delete_inl.add(InlineKeyboardButton(text=i, callback_data=i)) 24 | return admin_delete_inl.add(InlineKeyboardButton(text="🔙 Ortga", callback_data="delete_back_admin")) 25 | 26 | 27 | def all_access(): 28 | admin_view_inl = InlineKeyboardMarkup(row_width=1) 29 | for i in all_view_full_name(): 30 | admin_view_inl.add(InlineKeyboardButton(text=i, callback_data=i)) 31 | return admin_view_inl.add(InlineKeyboardButton(text="🔙 Ortga", callback_data="delete_back_admin")) 32 | 33 | 34 | analysis_direction = InlineKeyboardMarkup(row_width=3).add( 35 | InlineKeyboardButton(text='Data Science', callback_data='data'), 36 | InlineKeyboardButton(text='Full Stack', callback_data='full'), 37 | InlineKeyboardButton(text='Software Engineering', callback_data='soft'), 38 | InlineKeyboardButton(text='umumiy analitika', callback_data='umumiy'), 39 | InlineKeyboardButton(text='Web saytda kirish', url='http://172.20.16.8:8505/'), 40 | InlineKeyboardButton(text='🔙 Ortga', callback_data='main_kirish') 41 | ) 42 | 43 | umumiy_analysis_inl = InlineKeyboardMarkup(row_width=2).add( 44 | InlineKeyboardButton(text='Umumiy yo\'nalish', callback_data='umummiy_direction'), 45 | InlineKeyboardButton(text='Umumiy mentor', callback_data='umumiy_metors'), 46 | InlineKeyboardButton(text='🔙 Ortga' ,callback_data='ortga') 47 | ) 48 | 49 | mentors_umummiy_inl = InlineKeyboardMarkup(row_width=3).add( 50 | InlineKeyboardButton(text='Data Science', callback_data='Data Science'), 51 | InlineKeyboardButton(text='Full Stack', callback_data='Full Stack'), 52 | InlineKeyboardButton(text='Software Engineering', callback_data='Software Engineering'), 53 | InlineKeyboardButton(text='🔙 Ortga' ,callback_data='orqaga'), 54 | ) 55 | 56 | 57 | 58 | def all_ds_inline(): 59 | all_ds_mentors = InlineKeyboardMarkup(row_width=1) 60 | for i in all_ds(): 61 | all_ds_mentors.add(InlineKeyboardButton(text=i, callback_data=i+'i')) 62 | return all_ds_mentors.add(InlineKeyboardButton(text="🔙 Ortga", callback_data='ortga')) 63 | 64 | 65 | def all_ds_list(): 66 | result = [] 67 | for i in all_ds(): 68 | result.append(i+'i') 69 | return result 70 | 71 | 72 | def all_fs_inline(): 73 | all_fs_mentors = InlineKeyboardMarkup(row_width=1) 74 | for i in all_fs(): 75 | all_fs_mentors.add(InlineKeyboardButton(text=i, callback_data=i+'i')) 76 | return all_fs_mentors.add(InlineKeyboardButton(text="🔙 Ortga", callback_data='ortga')) 77 | 78 | 79 | def all_fs_list(): 80 | result = [] 81 | for i in all_fs(): 82 | result.append(i+'i') 83 | return result 84 | 85 | 86 | def all_se_inline(): 87 | all_se_mentors = InlineKeyboardMarkup(row_width=1) 88 | for i in all_se(): 89 | all_se_mentors.add(InlineKeyboardButton(text=i, callback_data=i+'i')) 90 | return all_se_mentors.add(InlineKeyboardButton(text="🔙 Ortga", callback_data='ortga')) 91 | 92 | 93 | def all_se_list(): 94 | result = [] 95 | for i in all_se(): 96 | result.append(i+'i') 97 | return result -------------------------------------------------------------------------------- /admin/analysis/vizual_part.py: -------------------------------------------------------------------------------- 1 | from googleapiclient.discovery import build 2 | from google.oauth2 import service_account 3 | from pathlib import Path 4 | import pandas as pd 5 | import plotly.express as px 6 | 7 | BASE_DIR = Path(__file__).resolve().parent.parent.parent # /Users/student/web_scraping/astrum-feedback-bot 8 | 9 | 10 | def df_data(): 11 | service_account_file = f"{BASE_DIR}/data/Google_servis_data.json" 12 | SCOPES = ['https://www.googleapis.com/auth/spreadsheets'] 13 | creds = None 14 | creds = service_account.Credentials.from_service_account_file(service_account_file, scopes=SCOPES) 15 | SAMPLE_SPREADSHEET_ID = '1rgfEQdRBtD-AXtu3kfAvTUEwe0qkOpY2RRLSsGDBlrw' 16 | service = build('sheets', 'v4', credentials=creds) 17 | sheet = service.spreadsheets() 18 | result = sheet.values().get(spreadsheetId=SAMPLE_SPREADSHEET_ID, 19 | range='sheet1').execute() 20 | values = result.get('values', []) 21 | df = pd.DataFrame(values[1:], columns=values[0]) 22 | df.Yonalish = df.Yonalish = df.Yonalish.apply(lambda x: 'Data Science' if x == 'DS' else ('Software Engineering' if x == 'SE' else 'Full Stack')) 23 | return df 24 | 25 | 26 | def umumit_analitika(): 27 | # 1) ummumiy analitika 28 | fig = px.histogram(df_data(), y="Yonalish", color="Feedback", barmode="group", width=1000, height=600, 29 | title="Bu Yo'nalishlarning olgan feedbaklari") 30 | fig1 = px.histogram(df_data(), x='Yonalish', y="Ball", width=600, height=650, title="Bu yo'nalishlarni umumiy balli") 31 | fig.write_image(f"{BASE_DIR}/data/visual/umumiy/yonalish/all.png") 32 | fig1.write_image(f"{BASE_DIR}/data/visual/umumiy/yonalish/all2.png") 33 | 34 | # umumit_analitika() 35 | # df_data() 36 | 37 | 38 | def data_science_analitika(name): 39 | # name = "Komiljon Xamidjonov" 40 | yonalish = df_data()[df_data().Yonalish == "Data Science"] 41 | mentor = yonalish[yonalish.Name == name] 42 | fig = px.histogram(mentor, y="Name", color="Feedback", barmode="group", width=1000, height=600, 43 | title=f"Bu {name} olgan feedbaklari") 44 | mentor['ball'] = 1 45 | fig2 = px.pie(values=mentor.ball, names=mentor.Sabab, title=f'{name}ning kammentariyalar analizi') 46 | fig.write_image(f"{BASE_DIR}/data/visual/directions/data_science/{name}_1.png") 47 | fig2.write_image(f"{BASE_DIR}/data/visual/directions/data_science/{name}_2.png") 48 | 49 | # data_science_analitika('Komiljon Xamidjonov') 50 | 51 | 52 | def full_stack_analitika(name): 53 | yonalish = df_data()[df_data().Yonalish == "Full Stack"] 54 | mentor = yonalish[yonalish.Name == name] 55 | fig = px.histogram(mentor, y="Name", color="Feedback", barmode="group", width=1000, height=600, 56 | title=f"Bu {name} olgan feedbaklari") 57 | mentor['ball'] = 1 58 | fig2 = px.pie(values=mentor.ball, names=mentor.Sabab, title=f'{name}ning kammentariyalar analizi') 59 | fig.write_image(f"{BASE_DIR}/data/visual/directions/full_stack/{name}_1.png") 60 | fig2.write_image(f"{BASE_DIR}/data/visual/directions/full_stack/{name}_2.png") 61 | 62 | 63 | def soft_engineer_analitika(name): 64 | yonalish = df_data()[df_data().Yonalish == "Software Engineering"] 65 | mentor = yonalish[yonalish.Name == name] 66 | fig = px.histogram(mentor, y="Name", color="Feedback", barmode="group", width=1000, height=600, 67 | title=f"Bu {name} olgan feedbaklari") 68 | mentor['ball'] = 1 69 | fig2 = px.pie(values=mentor.ball, names=mentor.Sabab, title=f'{name}ning kammentariyalar analizi') 70 | fig.write_image(f"{BASE_DIR}/data/visual/directions/software/{name}_1.png") 71 | fig2.write_image(f"{BASE_DIR}/data/visual/directions/software/{name}_2.png") 72 | 73 | 74 | def mentors_analysis(direction): 75 | yonalish = df_data()[df_data().Yonalish == direction] 76 | fig = px.histogram(yonalish, y="Name", color="Feedback", barmode="group", width=1000, height=600, 77 | title=f"Bu {direction} mentorlarning olgan feedbaklari") 78 | fig1 = px.histogram(yonalish, x='Name', y="Ball", width=600, height=650, title=f"Bu {direction} mentorlarning umumiy balli") 79 | fig.write_image(f"{BASE_DIR}/data/visual/umumiy/mentor/{direction}.png") 80 | fig1.write_image(f"{BASE_DIR}/data/visual/umumiy/mentor/{direction}_1.png") 81 | 82 | # mentors_analysis('Data Science') 83 | -------------------------------------------------------------------------------- /keyboards/inline/student_parts.py: -------------------------------------------------------------------------------- 1 | from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton 2 | from data.query import mentors_datas 3 | from keyboards.inline.callback_data import data, full, soft, feed1, feed2, feed3 4 | 5 | yonalish = InlineKeyboardMarkup( 6 | inline_keyboard=[ 7 | [ 8 | InlineKeyboardButton(text="Data Science", callback_data="DS"), 9 | InlineKeyboardButton(text="Full Stack", callback_data="FS"), 10 | InlineKeyboardButton(text="Software Engineering", callback_data="SE"), 11 | ], 12 | [ 13 | InlineKeyboardButton(text="🔙 Ortga", callback_data="back_menu"), 14 | ] 15 | ]) 16 | 17 | beck_menu = InlineKeyboardButton(text="🔙 Ortga", callback_data="back_menu") 18 | beck_mentor = InlineKeyboardButton(text="🔙 Ortga", callback_data="back_mentor") 19 | beck_feed3 = InlineKeyboardButton(text="🔙 Ortga", callback_data="back_feed3") 20 | 21 | 22 | def d_mentors(): 23 | d_mentors = {} 24 | for i in mentors_datas(): 25 | if i[1] == 'DS': 26 | d_mentors[i[0]] = i[0] 27 | return d_mentors 28 | 29 | 30 | def f_mentors(): 31 | f_mentors = {} 32 | for i in mentors_datas(): 33 | if i[1] == 'FS': 34 | f_mentors[i[0]] = i[0] 35 | return f_mentors 36 | 37 | 38 | def s_mentors(): 39 | s_mentors = {} 40 | for i in mentors_datas(): 41 | if i[1] == 'SE': 42 | s_mentors[i[0]] = i[0] 43 | return s_mentors 44 | 45 | 46 | beck_der = InlineKeyboardButton(text="🔙 Ortga", callback_data="back_der") 47 | beck_mentor = InlineKeyboardButton(text="🔙 Ortga", callback_data="back_mentor") 48 | beck_feed3 = InlineKeyboardButton(text="🔙 Ortga", callback_data="back_feed3") 49 | 50 | # bu data sience mentorlar uchuun 51 | def mentors_data(): 52 | mentors_data = InlineKeyboardMarkup(row_width=1) 53 | for k, v in d_mentors().items(): 54 | mentors_data.insert(InlineKeyboardButton(text=k, callback_data=data.new(item_name=v))) 55 | mentors_data.insert(beck_menu) 56 | return mentors_data 57 | 58 | 59 | # bu full stack mentorlar uchun 60 | def mentors_full(): 61 | mentors_full = InlineKeyboardMarkup(row_width=1) 62 | for key, value in f_mentors().items(): 63 | mentors_full.insert(InlineKeyboardButton(text=key, callback_data=full.new(item_name=value))) 64 | mentors_full.insert(beck_menu) 65 | return mentors_full 66 | 67 | 68 | # bu softwer mentorlar uchun 69 | def mentors_soft(): 70 | mentors_soft = InlineKeyboardMarkup(row_width=1) 71 | for key, value in s_mentors().items(): 72 | mentors_soft.insert(InlineKeyboardButton(text=key, callback_data=soft.new(item_name=value))) 73 | mentors_soft.insert(beck_menu) 74 | return mentors_soft 75 | 76 | 77 | ######################################### 78 | 79 | feedback3 = { 80 | "😐 Qoniqarli": "Qoniqarli", 81 | "😊 Namunali": "Namunali", 82 | "☹️ Qoniqarsiz": "Qoniqarsiz" 83 | } 84 | feedback_de3 = InlineKeyboardMarkup(row_width=1) 85 | for k, v in feedback3.items(): 86 | feedback_de3.insert(InlineKeyboardButton(text=k, callback_data=v)) 87 | feedback_de3.insert(beck_mentor) 88 | 89 | 90 | feedback_q_li1 = { 91 | "1) Mentor o'z vaqtida ish joyida": " Mentor o'z vaqtida ish joyida", 92 | "2) Mentor muomilasi yaxshi": "Mentor muomilasi yaxshi", 93 | "3) Mentor qiziqarli usulda taqdimot qilib tushuntirdi" : "Mentor qiziqarli usulda taqdimot qilib tushuntirdi" 94 | } 95 | feedback_q_li = InlineKeyboardMarkup(row_width=1) 96 | for k, v in feedback_q_li1.items(): 97 | feedback_q_li.insert(InlineKeyboardButton(text=k, callback_data=feed1.new(item_feed=v))) 98 | feedback_q_li.insert(beck_feed3) 99 | 100 | feedback_n_li1 = { 101 | "1) Mentor barcha savoimga javob berdi": "Mentor barcha savoimga javob berdi", 102 | "2) Mentor juda ham yaxshi tushuntirdi": "Mentor juda ham yaxshi tushuntirdi", 103 | "3) Mentor yangicha usulda taqdimot qilib tushuntirdi": "Mentor yangicha usulda taqdimot qilib tushuntirdi" 104 | } 105 | feedback_n_li = InlineKeyboardMarkup(row_width=1) 106 | for k, v in feedback_n_li1.items(): 107 | feedback_n_li.insert(InlineKeyboardButton(text=k, callback_data=feed2.new(item_feed=v))) 108 | feedback_n_li.insert(beck_feed3) 109 | 110 | 111 | feedback_q_siz1 = { 112 | "1) Mentor o'z vaqtida ish joyida yo'q": "Mentor o'z vaqtida ish joyida yo'q", 113 | "2) Mentor umuman yordam bera olmadi": "Mentor umuman yordam bera olmadi", 114 | "3) Mentor yordam berishdan bosh tortdi": "Mentor yordam berishdan bosh tortdi" 115 | } 116 | feedback_q_siz = InlineKeyboardMarkup(row_width=1) 117 | for k, v in feedback_q_siz1.items(): 118 | feedback_q_siz.insert(InlineKeyboardButton(text=k, callback_data=feed3.new(item_feed=v))) 119 | feedback_q_siz.insert(beck_feed3) 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /admin/handlers/others.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | import json 3 | from pathlib import Path 4 | 5 | BASE_DIR = Path(__file__).resolve().parent.parent.parent # /Users/student/web_scraping/astrum-feedback-bot 6 | 7 | db_file = f"{BASE_DIR}/data/user.db" 8 | 9 | json_file = f"{BASE_DIR}/data/password.json" 10 | 11 | 12 | def check_admin(number): 13 | with sqlite3.connect(db_file) as db: 14 | cursor = db.cursor() 15 | check = cursor.execute(f"SELECT EXISTS(SELECT 1 FROM admins WHERE id={number})").fetchone()[0] 16 | cursor.close() 17 | return check 18 | 19 | 20 | def check_analysis_users(number): 21 | conn = sqlite3.connect(db_file) 22 | curr = conn.cursor() 23 | check = curr.execute(f"SELECT EXISTS(SELECT 1 FROM user_access WHERE user_id={number})").fetchone()[0] 24 | curr.close() 25 | return check 26 | # print(check_admin(2)) 27 | 28 | 29 | def add_mentor_query(data): 30 | import sqlite3 31 | conn = sqlite3.connect(db_file) 32 | curr = conn.cursor() 33 | curr.execute("INSERT OR IGNORE INTO mentors(full_name, directions) VALUES(?, ?)", 34 | (data['full_name'], data['direction'])) 35 | conn.commit() 36 | curr.close() 37 | 38 | 39 | # print(add_mentor_query({'full_name': 'Komiljon', 'direction': 'Data Science'})) 40 | 41 | 42 | def mentor_delete_query(name): 43 | sqlite_connection = sqlite3.connect(db_file) 44 | cursor = sqlite_connection.cursor() 45 | print("Подключен к SQLite") 46 | 47 | sql_delete_query = """DELETE from mentors where full_name = ?""" 48 | cursor.execute(sql_delete_query, (name,)) 49 | sqlite_connection.commit() 50 | print("Запись успешно удалена") 51 | cursor.close() 52 | 53 | 54 | def all_mentor_full_name(): 55 | sqlite_connection = sqlite3.connect(db_file) 56 | cursor = sqlite_connection.cursor() 57 | query = """SELECT full_name from mentors""" 58 | query_set = cursor.execute(query) 59 | all_data = [] 60 | for row in query_set.fetchall(): 61 | all_data.append(row[0]) 62 | cursor.close() 63 | return all_data 64 | 65 | 66 | def get_users(): 67 | conn = sqlite3.connect(db_file) 68 | cursor = conn.cursor() 69 | queryset = cursor.execute("""SELECT user_id FROM users""") 70 | result = [] 71 | for a in queryset.fetchall(): 72 | result.append(a) 73 | return result 74 | 75 | 76 | def add_admin(data): 77 | conn = sqlite3.connect(db_file) 78 | curr = conn.cursor() 79 | curr.execute("INSERT OR IGNORE INTO admins(id, full_name) VALUES(?, ?)", 80 | (data['admin_id'], data['fullname'])) 81 | conn.commit() 82 | curr.close() 83 | 84 | 85 | def delete_admin(name): 86 | sqlite_connection = sqlite3.connect(db_file) 87 | cursor = sqlite_connection.cursor() 88 | # print("Подключен к SQLite") 89 | sql_delete_query = """DELETE from admins where full_name = ?""" 90 | cursor.execute(sql_delete_query, (name,)) 91 | sqlite_connection.commit() 92 | # print("Запись успешно удалена") 93 | cursor.close() 94 | 95 | 96 | def all_admin_full_name(): 97 | sqlite_connection = sqlite3.connect(db_file) 98 | cursor = sqlite_connection.cursor() 99 | query = """SELECT full_name from admins""" 100 | query_set = cursor.execute(query) 101 | all_data = [] 102 | for row in query_set.fetchall(): 103 | all_data.append(row[0]) 104 | cursor.close() 105 | return all_data 106 | 107 | 108 | def add_user_access(data): 109 | conn = sqlite3.connect(db_file) 110 | curr = conn.cursor() 111 | curr.execute("INSERT OR IGNORE INTO user_access(user_id, full_name) VALUES(?, ?)", 112 | (data['admin_id'], data['fullname'])) 113 | conn.commit() 114 | curr.close() 115 | 116 | 117 | def edit_password(password): 118 | with open(json_file, 'w') as f: 119 | json.dump(password, f) 120 | f.close() 121 | 122 | 123 | def delete_user_access(name): 124 | sqlite_connection = sqlite3.connect(db_file) 125 | cursor = sqlite_connection.cursor() 126 | # print("Подключен к SQLite") 127 | sql_delete_query = """DELETE from user_access where full_name = ?""" 128 | cursor.execute(sql_delete_query, (name,)) 129 | sqlite_connection.commit() 130 | # print("Запись успешно удалена") 131 | cursor.close() 132 | 133 | 134 | def all_view_full_name(): 135 | conne = sqlite3.connect(db_file) 136 | cursor = conne.cursor() 137 | query = """SELECT full_name from user_access""" 138 | query_set = cursor.execute(query) 139 | all_data = [] 140 | for row in query_set.fetchall(): 141 | all_data.append(row[0]) 142 | cursor.close() 143 | return all_data 144 | 145 | 146 | def all_ds(): 147 | conn = sqlite3.connect(db_file) 148 | cur = conn.cursor() 149 | all_ = cur.execute("""SELECT full_name FROM mentors WHERE directions='DS'""") 150 | result = [] 151 | for a in all_.fetchall(): 152 | result.append(a[0]) 153 | return result 154 | 155 | # print(all_ds()) 156 | 157 | def all_fs(): 158 | conn = sqlite3.connect(db_file) 159 | cur = conn.cursor() 160 | all_ = cur.execute("""SELECT full_name FROM mentors WHERE directions='FS'""") 161 | result = [] 162 | for a in all_.fetchall(): 163 | result.append(a[0]) 164 | return result 165 | 166 | 167 | def all_se(): 168 | conn = sqlite3.connect(db_file) 169 | cur = conn.cursor() 170 | all_ = cur.execute("""SELECT full_name FROM mentors WHERE directions='SE'""") 171 | result = [] 172 | for a in all_.fetchall(): 173 | result.append(a[0]) 174 | return result 175 | -------------------------------------------------------------------------------- /data/feedback.csv: -------------------------------------------------------------------------------- 1 | ,Yonalish,Name,Feedback,Sabab,Ball,Date,Soni 2 | 0,Data Science,Abdulaziz Orifjanov,Qoniqarli,Mentor muomilasi yaxshi,1,2022-09-23,1 3 | 1,Data Science,Abdulaziz Orifjanov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 4 | 2,Data Science,Abdulaziz Orifjanov,Qoniqarsiz,Mentor umuman yordam bera olmadi,-1,2022-09-23,1 5 | 3,Data Science,Abdulaziz Orifjanov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-23,1 6 | 4,Data Science,Abdulaziz Orifjanov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-23,1 7 | 5,Data Science,Abdulaziz Orifjanov,Qoniqarsiz,Mentor umuman yordam bera olmadi,-1,2022-09-23,1 8 | 6,Data Science,Abdulaziz Orifjanov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-23,1 9 | 7,Data Science,Abdulaziz Orifjanov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 10 | 8,Data Science,Abdulaziz Orifjanov,Namunali,Mentor barcha savoimga javob berdi,2,2022-09-23,1 11 | 9,Data Science,Asalbonu Alambayeva,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 12 | 10,Data Science,Asalbonu Alambayeva,Namunali,Mentor barcha savoimga javob berdi,2,2022-09-23,1 13 | 11,Data Science,Asalbonu Alambayeva,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 14 | 12,Data Science,Asalbonu Alambayeva,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-23,1 15 | 13,Full Stack,Aziza Azizova,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-23,1 16 | 14,Full Stack,Aziza Azizova,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 17 | 15,Full Stack,Aziza Azizova,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-23,1 18 | 16,Full Stack,Aziza Azizova,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-23,1 19 | 17,Full Stack,Jasur Shukurov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-23,1 20 | 18,Full Stack,Jasur Shukurov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-23,1 21 | 19,Full Stack,Jasur Shukurov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 22 | 20,Full Stack,Jasur Shukurov,Qoniqarsiz,Mentor umuman yordam bera olmadi,-1,2022-09-23,1 23 | 21,Full Stack,Jasur Shukurov,Qoniqarsiz,Mentor o'z vaqtida ish joyida yo'q,-1,2022-09-23,1 24 | 22,Full Stack,Jasur Shukurov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 25 | 23,Full Stack,Jasur Shukurov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-23,1 26 | 24,Data Science,Komiljon Xamidjonov,Namunali,Mentor yangicha usulda taqdimot qilib tushuntirdi,2,2022-09-23,1 27 | 25,Data Science,Komiljon Xamidjonov,Qoniqarli,Mentor muomilasi yaxshi,1,2022-09-23,1 28 | 26,Data Science,Komiljon Xamidjonov,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-23,1 29 | 27,Data Science,Komiljon Xamidjonov,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-23,1 30 | 28,Data Science,Komiljon Xamidjonov,Namunali,Mentor yangicha usulda taqdimot qilib tushuntirdi,2,2022-09-23,1 31 | 29,Data Science,Komiljon Xamidjonov,Qoniqarli,Mentor qiziqarli usulda taqdimot qilib tushuntirdi,1,2022/09/23,1 32 | 30,Data Science,Komiljon Xamidjonov,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022/09/23,1 33 | 31,Data Science,Nodira Arslanova,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-23,1 34 | 32,Data Science,Nodira Arslanova,Qoniqarsiz,Mentor umuman yordam bera olmadi,-1,2022-09-23,1 35 | 33,Data Science,Nodira Arslanova,Namunali,Mentor yangicha usulda taqdimot qilib tushuntirdi,2,2022-09-23,1 36 | 34,Data Science,Nodira Arslanova,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-23,1 37 | 35,Data Science,Nodira Arslanova,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 38 | 36,Data Science,Nodira Arslanova,Qoniqarli,Mentor muomilasi yaxshi,1,2022-09-23,1 39 | 37,Full Stack,Raxmatulloh Rasulov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 40 | 38,Full Stack,Raxmatulloh Rasulov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 41 | 39,Full Stack,Raxmatulloh Rasulov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-23,1 42 | 40,Software Engineering,Sarvarbek Azodov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-23,1 43 | 41,Software Engineering,Sarvarbek Azodov,Qoniqarli,Mentor qiziqarli usulda taqdimot qilib tushuntirdi,1,2022-09-23,1 44 | 42,Software Engineering,Sarvarbek Azodov,Namunali,Mentor yangicha usulda taqdimot qilib tushuntirdi,2,2022-09-23,1 45 | 43,Software Engineering,Sarvarbek Azodov,Qoniqarli,Mentor muomilasi yaxshi,1,2022-09-23,1 46 | 44,Software Engineering,Sarvarbek Azodov,Namunali,Mentor yangicha usulda taqdimot qilib tushuntirdi,2,2022-09-23,1 47 | 45,Full Stack,Sarvarbek Shamurotov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-24,1 48 | 46,Data Science,Komiljon Xamidjonov,Namunali,Mentor barcha savoimga javob berdi,2,2022-09-24,1 49 | 47,Full Stack,Sarvarbek Shamurotov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-24,1 50 | 48,Data Science,Komiljon Xamidjonov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-25,1 51 | 49,Software Engineering,Sarvarbek Azodov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-25,1 52 | 50,Data Science,Nodira Arslanova,Qoniqarli,Mentor muomilasi yaxshi,1,2022-09-25,1 53 | 51,Data Science,Nodira Arslanova,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-25,1 54 | 52,Data Science,Nodira Arslanova,Namunali,Mentor barcha savoimga javob berdi,2,2022-09-25,1 55 | 53,Software Engineering,Sirojiddin Olloyorov,Qoniqarli,Mentor muomilasi yaxshi,1,2022-09-25,1 56 | 54,Software Engineering,Sirojiddin Olloyorov,Namunali,Mentor barcha savoimga javob berdi,2,2022-09-25,1 57 | 55,Software Engineering,Sirojiddin Olloyorov,Qoniqarsiz,Mentor o'z vaqtida ish joyida yo'q,-1,2022-09-25,1 58 | 56,Software Engineering,Sirojiddin Olloyorov,Namunali,Mentor barcha savoimga javob berdi,2,2022-09-25,1 59 | 57,Data Science,Komiljon Xamidjonov,Qoniqarsiz,Mentor o'z vaqtida ish joyida yo'q,-1,2022-09-26,1 60 | 58,Data Science,Komiljon Xamidjonov,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-27,1 61 | 59,Data Science,Komiljon Xamidjonov,Qoniqarli,Mentor qiziqarli usulda taqdimot qilib tushuntirdi,1,2022-09-27,1 62 | 60,Data Science,Asalbonu Alambayeva,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-27,1 63 | 61,Data Science,Nodira Arslanova,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-27,1 64 | 62,Full Stack,Sarvarbek Shamurotov,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-09-27,1 65 | 63,Software Engineering,Sirojiddin Olloyorov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-27,1 66 | 64,Data Science,Nodira Arslanova,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-27,1 67 | 65,Data Science,Abdulaziz Orifjanov,Qoniqarli,Mentor muomilasi yaxshi,1,2022-09-27,1 68 | 66,Data Science,Abdulaziz Orifjanov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-09-27,1 69 | 67,Data Science,Komiljon Xamidjonov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-09-27,1 70 | 68,Data Science,Asalbonu Alambayeva,Qoniqarsiz,Mentor o'z vaqtida ish joyida yo'q,-1,2022-09-27,1 71 | 69,Data Science,Abdulaziz Orifjanov,Qoniqarsiz,Mentor o'z vaqtida ish joyida yo'q,-1,2022-09-27,1 72 | 70,Data Science,Komiljon Xamidjonov,Namunali,Mentor yangicha usulda taqdimot qilib tushuntirdi,2,2022-09-28,1 73 | 71,Data Science,Komiljon Xamidjonov,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-10-11,1 74 | 72,Data Science,Asalbonu Alambayeva,Namunali,Mentor yangicha usulda taqdimot qilib tushuntirdi,2,2022-10-11,1 75 | 73,Data Science,Komiljon Xamidjonov,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-10-12,1 76 | 74,Data Science,Komiljon Xamidjonov,Qoniqarli, Mentor o'z vaqtida ish joyida,1,2022-10-12,1 77 | 75,Full Stack,Aziza Azizova,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-10-17,1 78 | 76,Data Science,Asalbonu Alambayeva,Namunali,Mentor yangicha usulda taqdimot qilib tushuntirdi,2,2022-10-17,1 79 | 77,Data Science,Abdulaziz Orifjanov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-10-17,1 80 | 78,Data Science,Abdulaziz Orifjanov,Namunali,Mentor juda ham yaxshi tushuntirdi,2,2022-10-17,1 81 | 79,Data Science,Abdulaziz Orifjanov,Qoniqarsiz,Mentor yordam berishdan bosh tortdi,-1,2022-10-18,1 82 | 80,Software Engineering,Sarvarbek Azodov,Namunali,Mentor barcha savoimga javob berdi,2,2022-10-18,1 83 | -------------------------------------------------------------------------------- /handlers/users/student_part_handler.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from aiogram.dispatcher import FSMContext 3 | from aiogram.types import Message, CallbackQuery 4 | from data.google_sheet import google_sheet_add 5 | from data.query import update_last_feedback, users_add, users_data, update_direction 6 | from keyboards.default.menu_keyboard import menu 7 | from keyboards.inline.student_parts import mentors_data, mentors_full, mentors_soft, feedback_de3, yonalish, \ 8 | feedback_q_li, feedback_n_li, feedback_q_siz 9 | 10 | from loader import dp 11 | from states.student_part_state import Student_part_state 12 | 13 | 14 | r_id = 0 15 | 16 | 17 | def all_user_id(): 18 | return [i[0] for i in users_data()] 19 | 20 | 21 | def all_user_der(): 22 | return [i[1] for i in users_data()] 23 | 24 | 25 | def last_feed_back_user(): 26 | return [i[2] for i in users_data()] 27 | 28 | 29 | # print(last_feed_back_user()[all_user_id().index(784286636)]) 30 | 31 | ################## back ################## 32 | @dp.callback_query_handler(text="back_menu", state=[Student_part_state.yonalishlar, Student_part_state.mentorlar, Student_part_state.chenged]) 33 | async def back_menu(call: CallbackQuery, state: FSMContext): 34 | await call.message.answer("Menu", reply_markup=menu) 35 | await call.message.delete() 36 | await call.answer(cache_time=60) 37 | await state.finish() 38 | 39 | 40 | @dp.callback_query_handler(text="back_mentor", state=Student_part_state.feed3) 41 | async def back_der(call: CallbackQuery, state: FSMContext): 42 | await call.answer(cache_time=60) 43 | w = await state.get_data() 44 | m = w['mentor'].split(':')[0] 45 | all_mentor = [mentors_data(), mentors_full(), mentors_soft()] 46 | all_mentor_link = ["DS", "FS", "SE"] 47 | idx = all_mentor_link.index(m) 48 | await call.message.edit_reply_markup(reply_markup=all_mentor[idx]) 49 | await Student_part_state.mentorlar.set() 50 | 51 | 52 | @dp.callback_query_handler(text="back_feed3", state=Student_part_state.sabab) 53 | async def back(call: CallbackQuery, state: FSMContext): 54 | await call.message.edit_reply_markup(reply_markup=feedback_de3) 55 | await call.answer(cache_time=60) 56 | await Student_part_state.feed3.set() 57 | 58 | 59 | #################### direction changed ###################### 60 | 61 | @dp.message_handler(text="/direction") 62 | async def dir_get(msg: Message): 63 | await msg.answer("Iltimos o'z yo'nalishingizni tanlang", reply_markup=yonalish) 64 | await Student_part_state.chenged.set() 65 | 66 | 67 | @dp.callback_query_handler(state=Student_part_state.chenged) 68 | async def dir_chenged(call : CallbackQuery, state : FSMContext): 69 | await call.answer(cache_time=60) 70 | await call.message.delete() 71 | direction, id = call.data, call.from_user.id 72 | # print(direction, id) 73 | update_direction(id, direction) 74 | await state.finish() 75 | await call.message.answer("Yo'nalishingiz muffaqqiyatli o'zgartirlidi") 76 | await call.message.answer("Menu", reply_markup=menu) 77 | 78 | 79 | ##############################Mentors_aprt###################################################### 80 | @dp.message_handler(text="Mentorga feedback qoldirish") 81 | async def student_part(msg: Message): 82 | userid = msg.from_user.id + r_id 83 | der = "" 84 | try: 85 | der = all_user_der()[all_user_id().index(userid)] 86 | except: 87 | pass 88 | 89 | if userid not in all_user_id(): 90 | await msg.answer("Iltimos o'z yo'nalishingizni tanlang", reply_markup=yonalish) 91 | await Student_part_state.yonalishlar.set() 92 | 93 | else: 94 | if der == "DS": 95 | await msg.answer("Data Science Mentorlari", reply_markup=mentors_data()) 96 | await Student_part_state.mentorlar.set() 97 | 98 | elif der == "FS": 99 | await msg.answer("Data Science Mentorlari", reply_markup=mentors_full()) 100 | await Student_part_state.mentorlar.set() 101 | 102 | elif der == "SE": 103 | await msg.answer("Data Science Mentorlari", reply_markup=mentors_soft()) 104 | await Student_part_state.mentorlar.set() 105 | 106 | 107 | ##################data_science#################### 108 | @dp.callback_query_handler(text="DS", state=Student_part_state.yonalishlar) 109 | async def data_science(call: CallbackQuery, state: FSMContext): 110 | await call.message.answer("Qaysi mentorga feedback qoldirmochisiz ?", reply_markup=mentors_data()) 111 | await call.answer(cache_time=60) 112 | der = call.data 113 | await state.update_data(der=der) 114 | await call.message.delete() 115 | await Student_part_state.next() 116 | 117 | 118 | ################## full stack ################################ 119 | @dp.callback_query_handler(text="FS", state=Student_part_state.yonalishlar) 120 | async def full_stack(call: CallbackQuery, state: FSMContext): 121 | await call.message.answer("Qaysi mentorga izoh qoldirmochisiz ?", reply_markup=mentors_full()) 122 | await call.answer(cache_time=60) 123 | der = call.data 124 | await state.update_data(der=der) 125 | await call.message.delete() 126 | await Student_part_state.next() 127 | 128 | 129 | ################## softwere ################################ 130 | @dp.callback_query_handler(text="SE", state=Student_part_state.yonalishlar) 131 | async def softwer(call: CallbackQuery, state: FSMContext): 132 | await call.message.answer("Qaysi mentorga izoh qoldirmochisiz ?", reply_markup=mentors_soft()) 133 | await call.answer(cache_time=60) 134 | der = call.data 135 | await state.update_data(der=der) 136 | await call.message.delete() 137 | await Student_part_state.next() 138 | 139 | 140 | # pop = ["komiljon_x","asal_a","nodira_q","abdulaziz_w","aziza_a","rahmatulloh_r","jasur_sh","sarvarbek_sh","ali_m","vali_m","uqw_q"] 141 | 142 | ################# feedback part ########################## 143 | 144 | @dp.callback_query_handler(state=Student_part_state.mentorlar) 145 | async def feedback(call: CallbackQuery, state: FSMContext): 146 | await call.message.answer("Feedback tanlang", reply_markup=feedback_de3) 147 | await call.answer(cache_time=60) 148 | m = call.data 149 | await state.update_data(mentor=m) 150 | await call.message.delete() 151 | await Student_part_state.next() 152 | 153 | 154 | @dp.callback_query_handler(text="Qoniqarli", state=Student_part_state.feed3) 155 | async def feedbac2(call: CallbackQuery, state: FSMContext): 156 | await call.message.answer("Nima sabab ?", reply_markup=feedback_q_li) 157 | m = call.data 158 | await state.update_data(feedback=m) 159 | await call.message.delete() 160 | await Student_part_state.next() 161 | 162 | 163 | @dp.callback_query_handler(text="Namunali", state=Student_part_state.feed3) 164 | async def feedbac3(call: CallbackQuery, state: FSMContext): 165 | await call.message.answer("Nima sabab ?", reply_markup=feedback_n_li) 166 | m = call.data 167 | await state.update_data(feedback=m) 168 | await call.message.delete() 169 | await Student_part_state.next() 170 | 171 | 172 | @dp.callback_query_handler(text="Qoniqarsiz", state=Student_part_state.feed3) 173 | async def feedbac4(call: CallbackQuery, state: FSMContext): 174 | await call.message.answer("Nima sabab ?", reply_markup=feedback_q_siz) 175 | m = call.data 176 | await state.update_data(feedback=m) 177 | await call.message.delete() 178 | await Student_part_state.next() 179 | 180 | 181 | @dp.callback_query_handler(state=Student_part_state.sabab) 182 | async def feedbac_end(call: CallbackQuery, state: FSMContext): 183 | await call.message.delete() 184 | userid1 = call.from_user.id + r_id 185 | hour, minut = 0, 0 186 | try: 187 | date = last_feed_back_user()[all_user_id().index(userid1)] 188 | date_1 = datetime.strptime(date, '%Y-%m-%d %H:%M') 189 | date2 = datetime.now().strftime("%Y-%m-%d %H:%M") 190 | date_now = datetime.strptime(date2, "%Y-%m-%d %H:%M") 191 | min = date_now - date_1 192 | 193 | if len(str(min)) <= 7: 194 | hour = int(str(min).split(":")[0]) 195 | minut = int(str(min).split(":")[1]) 196 | else: 197 | hour = 2 198 | 199 | except: 200 | hour = 2 201 | 202 | if hour >= 2: 203 | await call.answer("Siz bergan feedback qabul qilindi.", cache_time=60, show_alert=True) 204 | end = call.data 205 | await state.update_data(end=end) 206 | db = await state.get_data() 207 | 208 | we, balls = ['q_li', "n_li", 'q_siz'], [1, 2, -1] 209 | ball = balls[we.index(db['end'].split(':')[0])] 210 | 211 | data_for_sheet = [db['mentor'].split(":")[0], db['mentor'].split(':')[1], db['feedback'], db['end'].split(':')[1], ball] 212 | google_sheet_add(data_for_sheet) 213 | 214 | await call.message.answer( 215 | "Qoldirgan feedbackingiz uchun rahmat.", reply_markup=menu) 216 | 217 | if userid1 not in all_user_id(): 218 | date = datetime.now().strftime("%Y-%m-%d %H:%M") 219 | users_add(userid1, db['der'], date) 220 | 221 | else: 222 | date2 = datetime.now().strftime("%Y-%m-%d %H:%M") 223 | update_last_feedback(userid1, date2) 224 | 225 | else: 226 | await call.answer("✖️ Siz har 2 soatda bir marta feedback bera olasiz", cache_time=60, show_alert=True) 227 | await call.message.answer(f"Siz {hour}:{minut} minut oldin feedback berdingiz", reply_markup=menu) 228 | 229 | await state.finish() -------------------------------------------------------------------------------- /analysis/app.py: -------------------------------------------------------------------------------- 1 | import socket 2 | from pathlib import Path 3 | import streamlit as st 4 | from st_aggrid import AgGrid 5 | import plotly.express as px 6 | import requests 7 | from streamlit_lottie import st_lottie 8 | from googleapiclient.discovery import build 9 | from google.oauth2 import service_account 10 | import pandas as pd 11 | import schedule 12 | 13 | # Get the IP address of the machine running the app 14 | ip_address = socket.gethostbyname(socket.gethostname()) 15 | BASE_DIR = Path(__file__).resolve().parent.parent 16 | 17 | 18 | def update_data(): 19 | service_account_file = f'{BASE_DIR}/data/Google_servis_data.json' 20 | SCOPES = ['https://www.googleapis.com/auth/spreadsheets'] 21 | creds = None 22 | creds = service_account.Credentials.from_service_account_file(service_account_file, scopes=SCOPES) 23 | SAMPLE_SPREADSHEET_ID = '1rgfEQdRBtD-AXtu3kfAvTUEwe0qkOpY2RRLSsGDBlrw' 24 | service = build('sheets', 'v4', credentials=creds) 25 | sheet = service.spreadsheets() 26 | result = sheet.values().get(spreadsheetId=SAMPLE_SPREADSHEET_ID, 27 | range='sheet1').execute() 28 | values = result.get('values', []) 29 | df = pd.DataFrame(values[1:], columns=values[0]) 30 | df.Ball = df.Ball.astype("int") 31 | df.Yonalish = df.Yonalish = df.Yonalish.apply(lambda x: 'Data Science' if x == 'DS' else ('Software Engineering' if x == 'SE' else 'Full Stack')) 32 | df["Soni"] = 1 33 | 34 | return df.to_csv(f'{BASE_DIR}/data/feedback.csv') 35 | 36 | 37 | schedule.every().day.at("00:00").do(update_data) 38 | 39 | 40 | def df_data(): 41 | return pd.read_csv(f'{BASE_DIR}/data/feedback.csv') 42 | 43 | 44 | st.set_page_config(layout="wide") 45 | 46 | 47 | def add_navigator(): 48 | st.markdown( 49 | f'', 50 | unsafe_allow_html=True) 51 | 52 | st.markdown(f""" 53 | 66 | """, unsafe_allow_html=True) 67 | 68 | def entry(url: str): 69 | r = requests.get(url) 70 | if r.status_code != 200: 71 | return None 72 | return r.json() 73 | 74 | 75 | # def select_types(): 76 | def show_title(): 77 | st.sidebar.header("Parametrlarni sozlash") 78 | st.markdown("

Astrum Mentorlarining Feedbacklari Analitikasi

", 79 | unsafe_allow_html=True) 80 | 81 | 82 | def show_mentors_list(): 83 | global fs, ds, ds_mentos, yonalishs, fs_mentos, se_mentos, ds_mentors, fs_mentors, se_mentors 84 | fields = ( 85 | "Tanlash", 86 | "Umumiy analitika", 87 | "Data Science", 88 | "Full Stack", 89 | "Software Engineering", 90 | ) 91 | ds_mentors = df_data()[df_data()['Yonalish'] == 'Data Science']['Name'].unique() 92 | 93 | fs_mentors = df_data()[df_data()['Yonalish'] == 'Full Stack']['Name'].unique() 94 | 95 | se_mentors = df_data()[df_data()['Yonalish'] == 'Software Engineering']['Name'].unique() 96 | 97 | time_of_analysis = ( 98 | "Oylik analitika", 99 | ) 100 | 101 | yonalishs = st.sidebar.selectbox("Yo'nalish tanlash:", fields) 102 | if yonalishs == "Data Science": 103 | ds_mentos = st.sidebar.selectbox('Mentor tanlash:', options=ds_mentors) 104 | elif yonalishs == "Full Stack": 105 | fs_mentos = st.sidebar.selectbox('Mentor tanlash:', options=fs_mentors) 106 | elif yonalishs == "Software Engineering": 107 | se_mentos = st.sidebar.selectbox('Mentor tanlash:', options=se_mentors) 108 | 109 | time = st.sidebar.selectbox("Vaqtni tanlash:", time_of_analysis) 110 | 111 | 112 | # def add_logo(logo_path, width, height): 113 | # logo = Image.open(logo_path) 114 | # modified_logo = logo.resize((width, height)) 115 | # return modified_logodef add_logo(logo_path, width, height): 116 | # logo = Image.open(logo_path) 117 | # modified_logo = logo.resize((width, height)) 118 | # return modified_logo 119 | 120 | 121 | # print(df) 122 | 123 | 124 | def hisobot(): 125 | st.header('Mentorlar statistikasi') 126 | # df = df.set_index(df["Date"],drop=True) 127 | return df_data() 128 | 129 | 130 | def hisobot_lot(url: str): 131 | r = requests.get(url) 132 | if r.status_code != 200: 133 | return None 134 | return r.json() 135 | 136 | 137 | def analysis(): 138 | if yonalishs == 'Umumiy analitika': 139 | # 1) ummumiy analitika 140 | fig = px.histogram(df_data(), y="Yonalish", color="Feedback", barmode="group", width=1000, height=600, 141 | title="Bu Yo'nalishlarning olgan feedbaklari") 142 | 143 | # 1) ummumiy analitika 144 | fig1 = px.histogram(df_data(), x='Yonalish', y="Ball", width=600, height=650, 145 | title="Bu yo'nalishlarni umumiy balli") 146 | st.plotly_chart(fig, use_container_width=True) 147 | st.plotly_chart(fig1, use_container_width=True) 148 | 149 | for n in range(len(ds_mentors)): 150 | # 3 Yo'nalish tanlaganda 151 | try: 152 | if ds_mentos == ds_mentors[n]: 153 | mentor = df_data()[df_data().Yonalish == "Data Science"][ 154 | df_data()[df_data().Yonalish == "Data Science"].Name == ds_mentors[n]] 155 | if ds_mentos == "Umumiy analitika": 156 | fig3 = px.histogram(df_data()[df_data().Yonalish == "Data Science"], y="Name", color="Feedback", 157 | barmode="group", 158 | width=1000, height=600, 159 | title="Bu Mentorlarning olgan feedbaklari") 160 | st.plotly_chart(fig3, use_container_width=True) 161 | 162 | fig1 = px.histogram(df_data()[df_data().Yonalish == "Data Science"], x='Name', y="Ball", width=600, 163 | height=650, 164 | title="Bu Mentorlarning umumiy balli") 165 | st.plotly_chart(fig1, use_container_width=True) 166 | else: 167 | fig = px.histogram(mentor, y="Name", color="Feedback", barmode="group", width=1000, height=600, 168 | title="Bu Mentorlarning olgan feedbaklari") 169 | st.plotly_chart(fig, use_container_width=True) 170 | 171 | fig1 = px.pie(values=mentor.Soni, names=mentor.Sabab, title='Bu Mentorning olgan kammentlarni') 172 | st.plotly_chart(fig1, use_container_width=True) 173 | 174 | except: 175 | pass 176 | 177 | for n in range(len(se_mentors)): 178 | # 3 Yo'nalish tanlaganda 179 | try: 180 | if se_mentos == se_mentors[n]: 181 | mentor = df_data()[df_data().Yonalish == "Software Engineering"][ 182 | df_data()[df_data().Yonalish == "Software Engineering"].Name == se_mentors[n]] 183 | if se_mentos == "Umumiy analitika": 184 | fig3 = px.histogram(df_data()[df_data().Yonalish == "Software Engineering"], y="Name", color="Feedback", 185 | barmode="group", 186 | width=1000, height=600, 187 | title="Bu Mentorlarning olgan feedbaklari") 188 | st.plotly_chart(fig3, use_container_width=True) 189 | 190 | fig1 = px.histogram(df_data()[df_data().Yonalish == "Software Engineering"], x='Name', y="Ball", width=600, 191 | height=650, 192 | title="Bu Mentorlarning umumiy balli") 193 | st.plotly_chart(fig1, use_container_width=True) 194 | else: 195 | fig = px.histogram(mentor, y="Name", color="Feedback", barmode="group", width=1000, height=600, 196 | title="Bu Mentorlarning olgan feedbaklari") 197 | st.plotly_chart(fig, use_container_width=True) 198 | 199 | fig1 = px.pie(values=mentor.Soni, names=mentor.Sabab, title='Bu Mentorning olgan kammentlarni') 200 | st.plotly_chart(fig1, use_container_width=True) 201 | except: 202 | pass 203 | # print(fs_mentors) 204 | for n in range(len(fs_mentors)): 205 | # 3 Yo'nalish tanlaganda 206 | try: 207 | if fs_mentos == fs_mentors[n]: 208 | mentor = df_data()[df_data().Yonalish == "Full Stack"][ 209 | df_data()[df_data().Yonalish == "Full Stack"].Name == fs_mentors[n]] 210 | if fs_mentos == "Umumiy analitika": 211 | fig3 = px.histogram(df_data()[df_data().Yonalish == "Full Stack"], y="Name", color="Feedback", 212 | barmode="group", 213 | width=1000, height=600, 214 | title="Bu Mentorlarning olgan feedbaklari") 215 | st.plotly_chart(fig3, use_container_width=True) 216 | 217 | fig1 = px.histogram(df_data()[df_data().Yonalish == "Full Stack"], x='Name', y="Ball", width=600, 218 | height=650, 219 | title="Bu Mentorlarning umumiy balli") 220 | st.plotly_chart(fig1, use_container_width=True) 221 | else: 222 | fig = px.histogram(mentor, y="Name", color="Feedback", barmode="group", width=1000, height=600, 223 | title="Bu Mentorlarning olgan feedbaklari") 224 | st.plotly_chart(fig, use_container_width=True) 225 | 226 | fig1 = px.pie(values=mentor.Soni, names=mentor.Sabab, title='Bu Mentorning olgan kammentlarni') 227 | st.plotly_chart(fig1, use_container_width=True) 228 | except: 229 | pass 230 | 231 | 232 | def main(): 233 | st.markdown("

Astrum

", unsafe_allow_html=True) 234 | # my_logo = add_logo(logo_path="image.jpg", width=230, height=300) 235 | # st.sidebar.image(my_logo) 236 | add_navigator() 237 | show_title() 238 | selection = st.sidebar.radio('Menu', options=['Home', 'Hisobot datasi', 'Hisobot vizualizatsiyasi']) 239 | if selection == "Hisobot statistikasi": 240 | lott = hisobot_lot("https://assets4.lottiefiles.com/packages/lf20_kitlgxkw.json") 241 | st_lottie( 242 | lott, 243 | speed=1, 244 | reverse=False, 245 | loop=True, 246 | quality="low", # medium ; high 247 | height=400, 248 | width=900, 249 | key=None, 250 | ) 251 | if selection == "Hisobot datasi": 252 | df = hisobot() 253 | AgGrid(df, height=700, fit_columns_on_grid_load=True) 254 | 255 | if selection == "Hisobot vizualizatsiyasi": 256 | show_mentors_list() 257 | 258 | if selection == "Hisobot vizualizatsiyasi": 259 | with st.sidebar.form(key='columns_in_form'): 260 | submitted = st.form_submit_button('Submit') 261 | if submitted: 262 | analysis() 263 | 264 | if selection == "Home": 265 | page_bg_img = f""" 266 | 281 | """ 282 | 283 | st.markdown(page_bg_img, unsafe_allow_html=True) 284 | 285 | 286 | main() 287 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/**/workspace.xml 3 | .idea/**/tasks.xml 4 | .idea/**/usage.statistics.xml 5 | .idea/**/dictionaries 6 | .idea/**/shelf 7 | 8 | # AWS User-specific 9 | .idea/**/aws.xml 10 | 11 | # Generated files 12 | .idea/**/contentModel.xml 13 | 14 | # Sensitive or high-churn files 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.local.xml 18 | .idea/**/sqlDataSources.xml 19 | .idea/**/dynamic.xml 20 | .idea/**/uiDesigner.xml 21 | .idea/**/dbnavigator.xml 22 | 23 | # Gradle 24 | .idea/**/gradle.xml 25 | .idea/**/libraries 26 | 27 | # Gradle and Maven with auto-import 28 | # When using Gradle or Maven with auto-import, you should exclude module files, 29 | # since they will be recreated, and may cause churn. Uncomment if using 30 | # auto-import. 31 | # .idea/artifacts 32 | # .idea/compiler.xml 33 | # .idea/jarRepositories.xml 34 | # .idea/modules.xml 35 | # .idea/*.iml 36 | # .idea/modules 37 | # *.iml 38 | # *.ipr 39 | 40 | # CMake 41 | cmake-build-*/ 42 | 43 | # Mongo Explorer plugin 44 | .idea/**/mongoSettings.xml 45 | 46 | # File-based project format 47 | *.iws 48 | 49 | # IntelliJ 50 | out/ 51 | 52 | # mpeltonen/sbt-idea plugin 53 | .idea_modules/ 54 | 55 | # JIRA plugin 56 | atlassian-ide-plugin.xml 57 | 58 | # Cursive Clojure plugin 59 | .idea/replstate.xml 60 | 61 | # SonarLint plugin 62 | .idea/sonarlint/ 63 | 64 | # Crashlytics plugin (for Android Studio and IntelliJ) 65 | com_crashlytics_export_strings.xml 66 | crashlytics.properties 67 | crashlytics-build.properties 68 | fabric.properties 69 | 70 | # Editor-based Rest Client 71 | .idea/httpRequests 72 | 73 | # Android studio 3.1+ serialized cache file 74 | .idea/caches/build_file_checksums.ser 75 | 76 | ### PyCharm+all Patch ### 77 | # Ignore everything but code style settings and run configurations 78 | # that are supposed to be shared within teams. 79 | 80 | .idea/* 81 | 82 | !.idea/codeStyles 83 | !.idea/runConfigurations 84 | 85 | ### Python ### 86 | # Byte-compiled / optimized / DLL files 87 | __pycache__/ 88 | *.py[cod] 89 | *$py.class 90 | 91 | # C extensions 92 | *.so 93 | 94 | # Distribution / packaging 95 | .Python 96 | build/ 97 | develop-eggs/ 98 | dist/ 99 | downloads/ 100 | eggs/ 101 | .eggs/ 102 | lib/ 103 | lib64/ 104 | parts/ 105 | sdist/ 106 | var/ 107 | wheels/ 108 | share/python-wheels/ 109 | *.egg-info/ 110 | .installed.cfg 111 | *.egg 112 | MANIFEST 113 | 114 | # PyInstaller 115 | # Usually these files are written by a python script from a template 116 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 117 | *.manifest 118 | *.spec 119 | 120 | # Installer logs 121 | pip-log.txt 122 | pip-delete-this-directory.txt 123 | 124 | # Unit test / coverage reports 125 | htmlcov/ 126 | .tox/ 127 | .nox/ 128 | .coverage 129 | .coverage.* 130 | .cache 131 | nosetests.xml 132 | coverage.xml 133 | *.cover 134 | *.py,cover 135 | .hypothesis/ 136 | .pytest_cache/ 137 | cover/ 138 | 139 | # Translations 140 | *.mo 141 | *.pot 142 | 143 | # Django stuff: 144 | *.log 145 | local_settings.py 146 | db.sqlite3 147 | db.sqlite3-journal 148 | 149 | # Flask stuff: 150 | instance/ 151 | .webassets-cache 152 | 153 | # Scrapy stuff: 154 | .scrapy 155 | 156 | # Sphinx documentation 157 | docs/_build/ 158 | 159 | # PyBuilder 160 | .pybuilder/ 161 | target/ 162 | 163 | # Jupyter Notebook 164 | .ipynb_checkpoints 165 | 166 | # IPython 167 | profile_default/ 168 | ipython_config.py 169 | 170 | # pyenv 171 | # For a library or package, you might want to ignore these files since the code is 172 | # intended to run in multiple environments; otherwise, check them in: 173 | # .python-version 174 | 175 | # pipenv 176 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 177 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 178 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 179 | # install all needed dependencies. 180 | #Pipfile.lock 181 | 182 | # poetry 183 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 184 | # This is especially recommended for binary packages to ensure reproducibility, and is more 185 | # commonly ignored for libraries. 186 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 187 | #poetry.lock 188 | 189 | # pdm 190 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 191 | #pdm.lock 192 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 193 | # in version control. 194 | # https://pdm.fming.dev/#use-with-ide 195 | .pdm.toml 196 | 197 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 198 | __pypackages__/ 199 | 200 | # Celery stuff 201 | celerybeat-schedule 202 | celerybeat.pid 203 | 204 | # SageMath parsed files 205 | *.sage.py 206 | 207 | # Environments 208 | .env 209 | .venv 210 | env/ 211 | venv/ 212 | ENV/ 213 | env.bak/ 214 | venv.bak/ 215 | 216 | # Spyder project settings 217 | .spyderproject 218 | .spyproject 219 | 220 | # Rope project settings 221 | .ropeproject 222 | 223 | # mkdocs documentation 224 | /site 225 | 226 | # mypy 227 | .mypy_cache/ 228 | .dmypy.json 229 | dmypy.json 230 | 231 | # Pyre type checker 232 | .pyre/ 233 | 234 | # pytype static type analyzer 235 | .pytype/ 236 | 237 | # Cython debug symbols 238 | cython_debug/ 239 | 240 | # PyCharm 241 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 242 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 243 | # and can be added to the global gitignore or merged into this file. For a more nuclear 244 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 245 | #.idea/ 246 | 247 | ### Python Patch ### 248 | # Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration 249 | poetry.toml 250 | 251 | # ruff 252 | .ruff_cache/ 253 | 254 | # LSP config files 255 | pyrightconfig.json 256 | 257 | ### VisualStudioCode ### 258 | .vscode/* 259 | !.vscode/settings.json 260 | !.vscode/tasks.json 261 | !.vscode/launch.json 262 | !.vscode/extensions.json 263 | !.vscode/*.code-snippets 264 | 265 | # Local History for Visual Studio Code 266 | .history/ 267 | 268 | # Built Visual Studio Code Extensions 269 | *.vsix 270 | 271 | ### VisualStudioCode Patch ### 272 | # Ignore all local history of files 273 | .history 274 | .ionide 275 | 276 | ### VisualStudio ### 277 | ## Ignore Visual Studio temporary files, build results, and 278 | ## files generated by popular Visual Studio add-ons. 279 | ## 280 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 281 | 282 | # User-specific files 283 | *.rsuser 284 | *.suo 285 | *.user 286 | *.userosscache 287 | *.sln.docstates 288 | 289 | # User-specific files (MonoDevelop/Xamarin Studio) 290 | *.userprefs 291 | 292 | # Mono auto generated files 293 | mono_crash.* 294 | 295 | # Build results 296 | [Dd]ebug/ 297 | [Dd]ebugPublic/ 298 | [Rr]elease/ 299 | [Rr]eleases/ 300 | x64/ 301 | x86/ 302 | [Ww][Ii][Nn]32/ 303 | [Aa][Rr][Mm]/ 304 | [Aa][Rr][Mm]64/ 305 | bld/ 306 | [Bb]in/ 307 | [Oo]bj/ 308 | [Ll]og/ 309 | [Ll]ogs/ 310 | 311 | # Visual Studio 2015/2017 cache/options directory 312 | .vs/ 313 | # Uncomment if you have tasks that create the project's static files in wwwroot 314 | #wwwroot/ 315 | 316 | # Visual Studio 2017 auto generated files 317 | Generated\ Files/ 318 | 319 | # MSTest test Results 320 | [Tt]est[Rr]esult*/ 321 | [Bb]uild[Ll]og.* 322 | 323 | # NUnit 324 | *.VisualState.xml 325 | TestResult.xml 326 | nunit-*.xml 327 | 328 | # Build Results of an ATL Project 329 | [Dd]ebugPS/ 330 | [Rr]eleasePS/ 331 | dlldata.c 332 | 333 | # Benchmark Results 334 | BenchmarkDotNet.Artifacts/ 335 | 336 | # .NET Core 337 | project.lock.json 338 | project.fragment.lock.json 339 | artifacts/ 340 | 341 | # ASP.NET Scaffolding 342 | ScaffoldingReadMe.txt 343 | 344 | # StyleCop 345 | StyleCopReport.xml 346 | 347 | # Files built by Visual Studio 348 | *_i.c 349 | *_p.c 350 | *_h.h 351 | *.ilk 352 | *.meta 353 | *.obj 354 | *.iobj 355 | *.pch 356 | *.pdb 357 | *.ipdb 358 | *.pgc 359 | *.pgd 360 | *.rsp 361 | *.sbr 362 | *.tlb 363 | *.tli 364 | *.tlh 365 | *.tmp 366 | *.tmp_proj 367 | *_wpftmp.csproj 368 | *.tlog 369 | *.vspscc 370 | *.vssscc 371 | .builds 372 | *.pidb 373 | *.svclog 374 | *.scc 375 | 376 | # Chutzpah Test files 377 | _Chutzpah* 378 | 379 | # Visual C++ cache files 380 | ipch/ 381 | *.aps 382 | *.ncb 383 | *.opendb 384 | *.opensdf 385 | *.sdf 386 | *.cachefile 387 | *.VC.db 388 | *.VC.VC.opendb 389 | 390 | # Visual Studio profiler 391 | *.psess 392 | *.vsp 393 | *.vspx 394 | *.sap 395 | 396 | # Visual Studio Trace Files 397 | *.e2e 398 | 399 | # TFS 2012 Local Workspace 400 | $tf/ 401 | 402 | # Guidance Automation Toolkit 403 | *.gpState 404 | 405 | # ReSharper is a .NET coding add-in 406 | _ReSharper*/ 407 | *.[Rr]e[Ss]harper 408 | *.DotSettings.user 409 | 410 | # TeamCity is a build add-in 411 | _TeamCity* 412 | 413 | # DotCover is a Code Coverage Tool 414 | *.dotCover 415 | 416 | # AxoCover is a Code Coverage Tool 417 | .axoCover/* 418 | !.axoCover/settings.json 419 | 420 | # Coverlet is a free, cross platform Code Coverage Tool 421 | coverage*.json 422 | coverage*.xml 423 | coverage*.info 424 | 425 | # Visual Studio code coverage results 426 | *.coverage 427 | *.coveragexml 428 | 429 | # NCrunch 430 | _NCrunch_* 431 | .*crunch*.local.xml 432 | nCrunchTemp_* 433 | 434 | # MightyMoose 435 | *.mm.* 436 | AutoTest.Net/ 437 | 438 | # Web workbench (sass) 439 | .sass-cache/ 440 | 441 | # Installshield output folder 442 | [Ee]xpress/ 443 | 444 | # DocProject is a documentation generator add-in 445 | DocProject/buildhelp/ 446 | DocProject/Help/*.HxT 447 | DocProject/Help/*.HxC 448 | DocProject/Help/*.hhc 449 | DocProject/Help/*.hhk 450 | DocProject/Help/*.hhp 451 | DocProject/Help/Html2 452 | DocProject/Help/html 453 | 454 | # Click-Once directory 455 | publish/ 456 | 457 | # Publish Web Output 458 | *.[Pp]ublish.xml 459 | *.azurePubxml 460 | # Note: Comment the next line if you want to checkin your web deploy settings, 461 | # but database connection strings (with potential passwords) will be unencrypted 462 | *.pubxml 463 | *.publishproj 464 | 465 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 466 | # checkin your Azure Web App publish settings, but sensitive information contained 467 | # in these scripts will be unencrypted 468 | PublishScripts/ 469 | 470 | # NuGet Packages 471 | *.nupkg 472 | # NuGet Symbol Packages 473 | *.snupkg 474 | # The packages folder can be ignored because of Package Restore 475 | **/[Pp]ackages/* 476 | # except build/, which is used as an MSBuild target. 477 | !**/[Pp]ackages/build/ 478 | # Uncomment if necessary however generally it will be regenerated when needed 479 | #!**/[Pp]ackages/repositories.config 480 | # NuGet v3's project.json files produces more ignorable files 481 | *.nuget.props 482 | *.nuget.targets 483 | 484 | # Microsoft Azure Build Output 485 | csx/ 486 | *.build.csdef 487 | 488 | # Microsoft Azure Emulator 489 | ecf/ 490 | rcf/ 491 | 492 | # Windows Store app package directories and files 493 | AppPackages/ 494 | BundleArtifacts/ 495 | Package.StoreAssociation.xml 496 | _pkginfo.txt 497 | *.appx 498 | *.appxbundle 499 | *.appxupload 500 | 501 | # Visual Studio cache files 502 | # files ending in .cache can be ignored 503 | *.[Cc]ache 504 | # but keep track of directories ending in .cache 505 | !?*.[Cc]ache/ 506 | 507 | # Others 508 | ClientBin/ 509 | ~$* 510 | *~ 511 | *.dbmdl 512 | *.dbproj.schemaview 513 | *.jfm 514 | *.pfx 515 | *.publishsettings 516 | orleans.codegen.cs 517 | 518 | # Including strong name files can present a security risk 519 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 520 | #*.snk 521 | 522 | # Since there are multiple workflows, uncomment next line to ignore bower_components 523 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 524 | #bower_components/ 525 | 526 | # RIA/Silverlight projects 527 | Generated_Code/ 528 | 529 | # Backup & report files from converting an old project file 530 | # to a newer Visual Studio version. Backup files are not needed, 531 | # because we have git ;-) 532 | _UpgradeReport_Files/ 533 | Backup*/ 534 | UpgradeLog*.XML 535 | UpgradeLog*.htm 536 | ServiceFabricBackup/ 537 | *.rptproj.bak 538 | 539 | # SQL Server files 540 | *.mdf 541 | *.ldf 542 | *.ndf 543 | 544 | # Business Intelligence projects 545 | *.rdl.data 546 | *.bim.layout 547 | *.bim_*.settings 548 | *.rptproj.rsuser 549 | *- [Bb]ackup.rdl 550 | *- [Bb]ackup ([0-9]).rdl 551 | *- [Bb]ackup ([0-9][0-9]).rdl 552 | 553 | # Microsoft Fakes 554 | FakesAssemblies/ 555 | 556 | # GhostDoc plugin setting file 557 | *.GhostDoc.xml 558 | 559 | # Node.js Tools for Visual Studio 560 | .ntvs_analysis.dat 561 | node_modules/ 562 | 563 | # Visual Studio 6 build log 564 | *.plg 565 | 566 | # Visual Studio 6 workspace options file 567 | *.opt 568 | 569 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 570 | *.vbw 571 | 572 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 573 | *.vbp 574 | 575 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 576 | *.dsw 577 | *.dsp 578 | 579 | # Visual Studio 6 technical files 580 | 581 | # Visual Studio LightSwitch build output 582 | **/*.HTMLClient/GeneratedArtifacts 583 | **/*.DesktopClient/GeneratedArtifacts 584 | **/*.DesktopClient/ModelManifest.xml 585 | **/*.Server/GeneratedArtifacts 586 | **/*.Server/ModelManifest.xml 587 | _Pvt_Extensions 588 | 589 | # Paket dependency manager 590 | .paket/paket.exe 591 | paket-files/ 592 | 593 | # FAKE - F# Make 594 | .fake/ 595 | 596 | # CodeRush personal settings 597 | .cr/personal 598 | 599 | # Python Tools for Visual Studio (PTVS) 600 | *.pyc 601 | 602 | # Cake - Uncomment if you are using it 603 | # tools/** 604 | # !tools/packages.config 605 | 606 | # Tabs Studio 607 | *.tss 608 | 609 | # Telerik's JustMock configuration file 610 | *.jmconfig 611 | 612 | # BizTalk build output 613 | *.btp.cs 614 | *.btm.cs 615 | *.odx.cs 616 | *.xsd.cs 617 | 618 | # OpenCover UI analysis results 619 | OpenCover/ 620 | 621 | # Azure Stream Analytics local run output 622 | ASALocalRun/ 623 | 624 | # MSBuild Binary and Structured Log 625 | *.binlog 626 | 627 | # NVidia Nsight GPU debugger configuration file 628 | *.nvuser 629 | 630 | # MFractors (Xamarin productivity tool) working folder 631 | .mfractor/ 632 | 633 | # Local History for Visual Studio 634 | .localhistory/ 635 | 636 | # Visual Studio History (VSHistory) files 637 | .vshistory/ 638 | 639 | # BeatPulse healthcheck temp database 640 | healthchecksdb 641 | 642 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 643 | MigrationBackup/ 644 | 645 | # Ionide (cross platform F# VS Code tools) working folder 646 | .ionide/ 647 | 648 | # Fody - auto-generated XML schema 649 | FodyWeavers.xsd 650 | 651 | # VS Code files for those working on multiple tools 652 | *.code-workspace 653 | 654 | # Local History for Visual Studio Code 655 | 656 | # Windows Installer files from build outputs 657 | *.cab 658 | *.msi 659 | *.msix 660 | *.msm 661 | *.msp 662 | 663 | # JetBrains Rider 664 | *.sln.iml 665 | 666 | ### VisualStudio Patch ### 667 | # Additional files built by Visual Studio 668 | 669 | # End of https://www.toptal.com/developers/gitignore/api/python,visualstudio,visualstudiocode,pycharm+all -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "728dafd69d2427e0cfd3cfb8b4d38e9a7bdad1cf1566a0d1694ecbf8bb7044b2" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.9" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "aiogram": { 20 | "hashes": [ 21 | "sha256:2f3259fcf7598a166aace022768a77be8ab732971f54e08a3b828a896cfe2bad", 22 | "sha256:8ce2886c6c74a35f7a75fb6422af53914aa9c1b7d7032de8d58a3f411349700d" 23 | ], 24 | "index": "pypi", 25 | "version": "==2.14.3" 26 | }, 27 | "aiohttp": { 28 | "hashes": [ 29 | "sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe", 30 | "sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe", 31 | "sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5", 32 | "sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8", 33 | "sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd", 34 | "sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb", 35 | "sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c", 36 | "sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87", 37 | "sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0", 38 | "sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290", 39 | "sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5", 40 | "sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287", 41 | "sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde", 42 | "sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf", 43 | "sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8", 44 | "sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16", 45 | "sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf", 46 | "sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809", 47 | "sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213", 48 | "sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f", 49 | "sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013", 50 | "sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b", 51 | "sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9", 52 | "sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5", 53 | "sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb", 54 | "sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df", 55 | "sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4", 56 | "sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439", 57 | "sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f", 58 | "sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22", 59 | "sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f", 60 | "sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5", 61 | "sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970", 62 | "sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009", 63 | "sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc", 64 | "sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a", 65 | "sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95" 66 | ], 67 | "markers": "python_version >= '3.6'", 68 | "version": "==3.7.4.post0" 69 | }, 70 | "async-timeout": { 71 | "hashes": [ 72 | "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", 73 | "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3" 74 | ], 75 | "markers": "python_full_version >= '3.5.3'", 76 | "version": "==3.0.1" 77 | }, 78 | "attrs": { 79 | "hashes": [ 80 | "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1", 81 | "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb" 82 | ], 83 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 84 | "version": "==21.2.0" 85 | }, 86 | "babel": { 87 | "hashes": [ 88 | "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9", 89 | "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0" 90 | ], 91 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 92 | "version": "==2.9.1" 93 | }, 94 | "certifi": { 95 | "hashes": [ 96 | "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee", 97 | "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8" 98 | ], 99 | "version": "==2021.5.30" 100 | }, 101 | "chardet": { 102 | "hashes": [ 103 | "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", 104 | "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" 105 | ], 106 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", 107 | "version": "==4.0.0" 108 | }, 109 | "environs": { 110 | "hashes": [ 111 | "sha256:a98005aab7613b6fe7a1af7192a5163f72a52d3348d3918e6c7a2a32e4012779", 112 | "sha256:bf3fd6bc54fcfd7f512ddcb80a7781f0ced2b0c83dd123d619e9468ecdaaf537" 113 | ], 114 | "index": "pypi", 115 | "version": "==8.0.0" 116 | }, 117 | "idna": { 118 | "hashes": [ 119 | "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a", 120 | "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3" 121 | ], 122 | "markers": "python_version >= '3.5'", 123 | "version": "==3.2" 124 | }, 125 | "marshmallow": { 126 | "hashes": [ 127 | "sha256:c67929438fd73a2be92128caa0325b1b5ed8b626d91a094d2f7f2771bf1f1c0e", 128 | "sha256:dd4724335d3c2b870b641ffe4a2f8728a1380cd2e7e2312756715ffeaa82b842" 129 | ], 130 | "markers": "python_version >= '3.5'", 131 | "version": "==3.13.0" 132 | }, 133 | "multidict": { 134 | "hashes": [ 135 | "sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a", 136 | "sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93", 137 | "sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632", 138 | "sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656", 139 | "sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79", 140 | "sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7", 141 | "sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d", 142 | "sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5", 143 | "sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224", 144 | "sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26", 145 | "sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea", 146 | "sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348", 147 | "sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6", 148 | "sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76", 149 | "sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1", 150 | "sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f", 151 | "sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952", 152 | "sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a", 153 | "sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37", 154 | "sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9", 155 | "sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359", 156 | "sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8", 157 | "sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da", 158 | "sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3", 159 | "sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d", 160 | "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf", 161 | "sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841", 162 | "sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d", 163 | "sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93", 164 | "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f", 165 | "sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647", 166 | "sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635", 167 | "sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456", 168 | "sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda", 169 | "sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5", 170 | "sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281", 171 | "sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80" 172 | ], 173 | "markers": "python_version >= '3.6'", 174 | "version": "==5.1.0" 175 | }, 176 | "python-dotenv": { 177 | "hashes": [ 178 | "sha256:aae25dc1ebe97c420f50b81fb0e5c949659af713f31fdb63c749ca68748f34b1", 179 | "sha256:f521bc2ac9a8e03c736f62911605c5d83970021e3fa95b37d769e2bbbe9b6172" 180 | ], 181 | "markers": "python_version >= '3.5'", 182 | "version": "==0.19.0" 183 | }, 184 | "pytz": { 185 | "hashes": [ 186 | "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da", 187 | "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798" 188 | ], 189 | "version": "==2021.1" 190 | }, 191 | "typing-extensions": { 192 | "hashes": [ 193 | "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497", 194 | "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342", 195 | "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84" 196 | ], 197 | "version": "==3.10.0.0" 198 | }, 199 | "yarl": { 200 | "hashes": [ 201 | "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e", 202 | "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434", 203 | "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366", 204 | "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3", 205 | "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec", 206 | "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959", 207 | "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e", 208 | "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c", 209 | "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6", 210 | "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a", 211 | "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6", 212 | "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424", 213 | "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e", 214 | "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f", 215 | "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50", 216 | "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2", 217 | "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc", 218 | "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4", 219 | "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970", 220 | "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10", 221 | "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0", 222 | "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406", 223 | "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896", 224 | "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643", 225 | "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721", 226 | "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478", 227 | "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724", 228 | "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e", 229 | "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8", 230 | "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96", 231 | "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25", 232 | "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76", 233 | "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2", 234 | "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2", 235 | "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c", 236 | "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a", 237 | "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71" 238 | ], 239 | "markers": "python_version >= '3.6'", 240 | "version": "==1.6.3" 241 | } 242 | }, 243 | "develop": {} 244 | } 245 | -------------------------------------------------------------------------------- /admin/handlers/admin.py: -------------------------------------------------------------------------------- 1 | import time 2 | from aiogram.dispatcher import FSMContext 3 | from aiogram.dispatcher.filters.state import State, StatesGroup 4 | from aiogram import types, Dispatcher 5 | 6 | from admin.analysis.vizual_part import umumit_analitika, data_science_analitika, full_stack_analitika, mentors_analysis, \ 7 | soft_engineer_analitika 8 | from admin.handlers import others 9 | from admin.handlers.others import add_mentor_query, mentor_delete_query, get_users, add_admin, delete_admin, \ 10 | edit_password, add_user_access, check_analysis_users, delete_user_access 11 | from admin.keyboards import admin_kb, inlines 12 | from admin.keyboards.admin_kb import main_kb, edit_password_kb, main_analysis, access_user_kb, view_analysis_kb 13 | from admin.keyboards.inlines import all_ds_inline, all_fs_inline, all_fs_list, all_se_inline, all_se_list, \ 14 | analysis_direction, umumiy_analysis_inl, mentors_umummiy_inl, all_ds_list 15 | from keyboards.default.menu_keyboard import menu 16 | from loader import dp, bot 17 | from pathlib import Path 18 | 19 | 20 | BASE_DIR = Path(__file__).resolve().parent.parent.parent # /Users/student/web_scraping/astrum-feedback-bot 21 | 22 | print(BASE_DIR) 23 | ###### ADMIN ########## 24 | 25 | @dp.message_handler(commands=['admin']) 26 | async def admin_main(message: types.Message): 27 | if others.check_admin(message.from_user.id): 28 | await message.answer(f'Admin Panelga Xush kelibsiz!', reply_markup=admin_kb.main_kb) 29 | 30 | #########MENTOR TAHRIRLASH############ 31 | @dp.message_handler(text='Mentor tahrirlash') 32 | async def edit_mentor(message: types.Message): 33 | if others.check_admin(message.from_user.id): 34 | await message.answer('Mentor tahrirlash', reply_markup=admin_kb.edit_mentor_kb) 35 | 36 | ################# MENTOR QOSHISH##################### 37 | 38 | class FSMAdmin(StatesGroup): 39 | fullname = State() 40 | direction = State() 41 | 42 | 43 | @dp.message_handler(text="qo'shish") 44 | async def mentor_add_name_part_1(message: types.Message): 45 | if others.check_admin(message.from_user.id): 46 | await message.answer("Mentorning toliq ismi va familyasini kiriting.") 47 | await FSMAdmin.fullname.set() 48 | 49 | 50 | @dp.message_handler(state=FSMAdmin.fullname) 51 | async def mentor_add_name_part_2(message: types.Message, state: FSMContext): 52 | if others.check_admin(message.from_user.id): 53 | await message.answer("Mentor yo'nalishini tanlang.", reply_markup=inlines.mentors_add_inl) 54 | name = message.text 55 | await state.update_data(full_name=name) 56 | await FSMAdmin.next() 57 | 58 | 59 | @dp.callback_query_handler(text=['DS', 'FS', 'SE'], state=FSMAdmin.direction) 60 | async def mentor_add_name_part_3(call: types.CallbackQuery, state: FSMContext): 61 | direction = call.data 62 | await state.update_data(direction=direction) 63 | db = await state.get_data() 64 | await state.finish() 65 | add_mentor_query(db) 66 | # call.data.delete() 67 | await call.message.delete() 68 | await call.message.answer(text='Muvoffaqiyatli bajarildi.', reply_markup=main_kb) 69 | 70 | 71 | ################MENTOR OCHIRISH##################### 72 | 73 | class FSMDelete(StatesGroup): 74 | fullname = State() 75 | 76 | 77 | @dp.callback_query_handler(text='delete_back_admin', state=FSMDelete.fullname) 78 | async def back_delete_mentor(callback: types.CallbackQuery, state: FSMContext): 79 | await callback.message.answer('🔙 Ortga', reply_markup=admin_kb.edit_mentor_kb) 80 | await callback.answer(cache_time=60) 81 | await request_message.delete() 82 | await state.finish() 83 | 84 | 85 | @dp.message_handler(text="o'chirish") 86 | async def mentor_delete_part_1(message: types.Message): 87 | if others.check_admin(message.from_user.id): 88 | if len(inlines.all_ment()['inline_keyboard']) > 0: 89 | # print(inlines.all_ment()['inline_keyboard'] is True) 90 | await message.answer(text='Qaysi mentorni o\'chirmoqchisiz?', reply_markup=inlines.all_ment()) 91 | await FSMDelete.fullname.set() 92 | else: 93 | await message.answer('Mentorlar yo\'q', reply_markup=main_kb) 94 | 95 | 96 | @dp.callback_query_handler(state=FSMDelete.fullname) 97 | async def mentor_delete_part_2(callback: types.callback_query, state=FSMContext): 98 | name = callback.data 99 | await state.update_data(fullname=name) 100 | db = await state.get_data() 101 | await state.finish() 102 | mentor_delete_query(db['fullname']) 103 | await callback.message.delete() 104 | await callback.message.answer(text='Muvoffaqiyatli bajarildi.', reply_markup=main_kb) 105 | 106 | ##############ELON############## 107 | 108 | 109 | class FMSElon(StatesGroup): 110 | text = State() 111 | 112 | 113 | @dp.message_handler(text="E'lon") 114 | async def elon_part_1(message: types.Message): 115 | if others.check_admin(message.from_user.id): 116 | await message.answer('Foydalanuvchilarga e\'loningizni yozing.') 117 | await FMSElon.text.set() 118 | 119 | 120 | @dp.message_handler(state=FMSElon.text) 121 | async def elon_part_2(message: types.Message, state=FSMContext): 122 | global loading 123 | text = message.text 124 | await state.update_data(reklama=text) 125 | db = await state.get_data() 126 | await state.finish() 127 | try: 128 | loading = await message.answer('Jo\'natilmoqda...') 129 | for a in get_users()[0]: 130 | await bot.send_message(a, text=db['reklama']) 131 | time.sleep(1) 132 | 133 | except: 134 | print('Xatolik elon partda') 135 | print(get_users()) 136 | await loading.delete() 137 | await message.answer(text='Muvofaqqiyatli bajarildi.', reply_markup=main_kb) 138 | 139 | #################ADMIN QOSHISH################### 140 | 141 | class FSMAdmin_add(StatesGroup): 142 | fullname = State() 143 | admin_id = State() 144 | 145 | 146 | @dp.message_handler(text='Admin tahrirlash') 147 | async def add_admin_part_1(message: types.Message): 148 | if others.check_admin(message.from_user.id): 149 | await message.answer('Admin tahrirlash', reply_markup=admin_kb.edit_admin_kb) 150 | 151 | 152 | @dp.message_handler(text="admin qo'shish") 153 | async def add_admin_part_2(message: types.Message): 154 | if others.check_admin(message.from_user.id): 155 | await message.answer('Yangi adminnig ismini kiriting.') 156 | await FSMAdmin_add.fullname.set() 157 | 158 | 159 | @dp.message_handler(state=FSMAdmin_add.fullname) 160 | async def add_admin_part_4(message: types.Message, state: FSMContext): 161 | await message.answer("Yangi adminning 'User_id' sini kiritng.. ") 162 | name = message.text 163 | await state.update_data(fullname=name) 164 | await FSMAdmin_add.next() 165 | 166 | 167 | @dp.message_handler(state=FSMAdmin_add.admin_id) 168 | async def add_admin_part_5(message: types.Message, state=FSMContext): 169 | admin_id = message.text 170 | await state.update_data(admin_id=admin_id) 171 | db = await state.get_data() 172 | await state.finish() 173 | add_admin(db) 174 | await message.answer(text='Muvoffaqiyatli bajarildi.', reply_markup=main_kb) 175 | 176 | 177 | ################### admin delete ################ 178 | 179 | class FSMAdmin_delete(StatesGroup): 180 | fullname = State() 181 | 182 | 183 | @dp.message_handler(text='admin o\'chirish') 184 | async def admin_delete_part_1(message: types.Message): 185 | if others.check_admin(message.from_user.id): 186 | global request_message 187 | if len(inlines.all_admin()['inline_keyboard']) > 1: 188 | # print(inlines.all_ment()['inline_keyboard'] is True) 189 | request_message = await message.answer(text='Qaysi adminni o\'chirmoqchisiz?', reply_markup=inlines.all_admin()) 190 | await FSMUser_access_delete.fullname.set() 191 | else: 192 | await message.answer('Sizdan boshqa admin yo\'q', reply_markup=main_kb) 193 | 194 | 195 | @dp.callback_query_handler(text='delete_back_admin', state=FSMAdmin_delete.fullname) 196 | async def back_delete_admin(callback: types.CallbackQuery, state: FSMContext): 197 | await callback.message.answer('🔙 Ortga', reply_markup=admin_kb.edit_admin_kb) 198 | await callback.answer(cache_time=60) 199 | await request_message.delete() 200 | await state.finish() 201 | 202 | 203 | @dp.callback_query_handler(state=FSMAdmin_delete.fullname) 204 | async def admin_delete_part_2(callback: types.callback_query, state=FSMContext): 205 | if callback.data != 'delete_back_admin': 206 | name = callback.data 207 | await state.update_data(fullname=name) 208 | db = await state.get_data() 209 | await state.finish() 210 | delete_admin(db['fullname']) 211 | await callback.message.delete() 212 | await callback.message.answer(text='Muvoffaqiyatli bajarildi.', reply_markup=main_kb) 213 | await callback.answer(cache_time=60) 214 | 215 | ############Parolni tahrirlash############### 216 | 217 | 218 | class FSM_password(StatesGroup): 219 | password = State() 220 | 221 | 222 | @dp.message_handler(text='Parol tahrirlash') 223 | async def edit_password_part_1(message: types.Message): 224 | if others.check_admin(message.from_user.id): 225 | await message.answer('Parol tahrirlash', reply_markup=edit_password_kb) 226 | 227 | 228 | @dp.message_handler(text='parolni tahrirlash') 229 | async def edit_password_part_2(message: types.Message): 230 | await message.answer('Yangi parol kiriting:') 231 | await FSM_password.password.set() 232 | 233 | 234 | @dp.message_handler(state=FSM_password.password) 235 | async def edit_password_part_3(message: types.Message, state=FSMContext): 236 | password = message.text 237 | await state.update_data(password=password) 238 | db = await state.get_data() 239 | await state.finish() 240 | edit_password(db['password']) 241 | await message.answer(f"Muvoffaqiyatli bajarildi.\nYangi parol: {db['password']}.", reply_markup=main_kb) 242 | 243 | 244 | @dp.message_handler(text='🔙 Ortga') 245 | async def back_kb(message: types.Message): 246 | if others.check_admin(message.from_user.id): 247 | await message.answer('Bosh Menu', reply_markup=main_kb) 248 | 249 | ###############Muayyan odamlar qoshish################### 250 | 251 | 252 | 253 | @dp.message_handler(text='Mentorlar analitikasi') 254 | async def analysis_part_1(message: types.Message): 255 | if others.check_admin(message.from_user.id): 256 | await message.answer('Mentorlar analitikasi', reply_markup=main_analysis) 257 | 258 | 259 | @dp.message_handler(text='Analaitikani ko\'rishga dostup berish') 260 | async def view_analysis_part_1(message: types.Message): 261 | if others.check_admin(message.from_user.id): 262 | await message.answer('Analaitikani ko\'rishga dostup berish', reply_markup=access_user_kb) 263 | 264 | #############################ADDD STATE############################################################ 265 | 266 | 267 | class FSMUser_access_add(StatesGroup): 268 | fullname = State() 269 | admin_id = State() 270 | 271 | 272 | @dp.message_handler(text='ruxsat qo\'shish') 273 | async def view_analysis_part_1(message: types.Message): 274 | if others.check_admin(message.from_user.id): 275 | await message.answer('Yangi analitikadan foydalanuvchining to\'liq ismini kiriting.') 276 | await FSMUser_access_add.fullname.set() 277 | 278 | 279 | @dp.message_handler(state=FSMUser_access_add.fullname) 280 | async def view_analysis_part_2(message: types.Message, state: FSMContext): 281 | await message.answer("Yangi analitikadan foydalanuvchining 'User_id' sini kiritng.. ") 282 | name = message.text 283 | await state.update_data(fullname=name) 284 | await FSMUser_access_add.next() 285 | 286 | 287 | @dp.message_handler(state=FSMUser_access_add.admin_id) 288 | async def view_analysis_part_3(message: types.Message, state=FSMContext): 289 | admin_id = message.text 290 | await state.update_data(admin_id=admin_id) 291 | db = await state.get_data() 292 | print(db) 293 | await state.finish() 294 | add_user_access(db) 295 | await message.answer(text='Muvoffaqiyatli bajarildi.', reply_markup=main_kb) 296 | 297 | 298 | @dp.message_handler(text='🔙 Ortga.') 299 | async def del_back_kb(message: types.Message): 300 | if others.check_admin(message.from_user.id): 301 | await message.answer('Bosh Menu', reply_markup=main_analysis) 302 | elif check_analysis_users(message.from_user.id): 303 | await message.answer('Bosh menu', reply_markup=menu) 304 | 305 | 306 | ########################DELETE STATE############################################################# 307 | 308 | 309 | class FSMUser_access_delete(StatesGroup): 310 | fullname = State() 311 | 312 | 313 | @dp.message_handler(text='ruxsatni o\'chirish') 314 | async def delete_access_part_1(message: types.Message): 315 | if others.check_admin(message.from_user.id): 316 | global request_message 317 | if len(inlines.all_access()['inline_keyboard']) > 1: 318 | # print(inlines.all_ment()['inline_keyboard'] is True) 319 | request_message = await message.answer(text='Qaysi ko\'ruvchilarni o\'chirmoqchisiz?', reply_markup=inlines.all_access()) 320 | await FSMUser_access_delete.fullname.set() 321 | else: 322 | await message.answer('Sizdan boshqa ko\'ruvchilarni yo\'q', reply_markup=main_kb) 323 | 324 | 325 | @dp.callback_query_handler(text='delete_access_back', state=FSMUser_access_delete.fullname) 326 | async def delete_access_part_2(callback: types.CallbackQuery, state: FSMContext): 327 | if others.check_admin(callback.message.from_user.id): 328 | await callback.message.answer('🔙 Ortga', reply_markup=admin_kb.access_user_kb) 329 | await callback.answer(cache_time=60) 330 | await request_message.delete() 331 | await state.finish() 332 | 333 | 334 | @dp.callback_query_handler(state=FSMUser_access_delete.fullname) 335 | async def delete_access_part_3(callback: types.callback_query, state=FSMContext): 336 | name = callback.data 337 | await state.update_data(fullname=name) 338 | db = await state.get_data() 339 | await state.finish() 340 | delete_user_access(db['fullname']) 341 | await callback.message.delete() 342 | await callback.message.answer(text='Muvoffaqiyatli bajarildi.', reply_markup=main_kb) 343 | await callback.answer(cache_time=60) 344 | 345 | 346 | @dp.message_handler(text='🔝 Asosiy Menyu') 347 | async def asososiy_menu(message: types.Message): 348 | await message.answer('🔝 Asosiy Menyu', reply_markup=menu) 349 | 350 | 351 | ###############Analitikani ko'rish############### 352 | 353 | @dp.message_handler(text=['Analitikani ko\'rish']) 354 | async def analysis_view_part_1(message: types.Message): 355 | if check_analysis_users(message.from_user.id) or others.check_admin(message.from_user.id): 356 | # await message.answer('yangilanmoqda...') 357 | # await message.delete() 358 | await message.answer('Analitikani ko\'rish', reply_markup=view_analysis_kb) 359 | 360 | 361 | # @dp.message_handler(text='Haftalik') 362 | # async def analysis_view_part_2(message: types.Message): 363 | # await message.answer('rasm va link') 364 | 365 | 366 | @dp.message_handler(text='Kirish') 367 | async def analysis_view_part_2(message: types.Message): 368 | if check_analysis_users(message.from_user.id) or others.check_admin(message.from_user.id): 369 | await message.answer('Qaysi yonalish?', reply_markup=analysis_direction) 370 | umumit_analitika() ## update data for visualization 371 | 372 | ######### directions ############ 373 | 374 | ######## data science############# 375 | 376 | @dp.callback_query_handler(text='data') 377 | async def analysis_view_part_3(call: types.CallbackQuery): 378 | # if check_analysis_users(call.message.from_user.id) or others.check_admin(call.message.from_user.id): 379 | await call.message.delete() 380 | await call.message.answer('Mentorlar analitikasi', reply_markup=all_ds_inline()) 381 | 382 | 383 | @dp.callback_query_handler(text=all_ds_list()) 384 | async def send_visual_ds(call: types.CallbackQuery): 385 | await call.message.delete() 386 | await call.message.answer('kuting!') 387 | print(call.data[-1]) 388 | data_science_analitika(call.data[:-1]) 389 | photo1 = f"{BASE_DIR}/data/visual/directions/data_science/{call.data[:-1]}_1.png" 390 | photo2 = f"{BASE_DIR}/data/visual/directions/data_science/{call.data[:-1]}_2.png" 391 | p1 = open(photo1, 'rb') 392 | p2 = open(photo2, 'rb') 393 | await bot.send_photo(call.from_user.id, photo=p1) 394 | await bot.send_photo(call.from_user.id, photo=p2) 395 | await call.message.answer('Muvoffaqiyatli bajarildi!', reply_markup=view_analysis_kb) 396 | 397 | ###############full stack ####################### 398 | 399 | @dp.callback_query_handler(text='full') 400 | async def analysis_view_part_4(call: types.CallbackQuery): 401 | # if check_analysis_users(call.message.from_user.id) or others.check_admin(call.message.from_user.id): 402 | await call.message.delete() 403 | await call.message.answer('Mentorlar analitikasi', reply_markup=all_fs_inline()) 404 | 405 | 406 | @dp.callback_query_handler(text=all_fs_list()) 407 | async def send_visual_fs(call: types.CallbackQuery): 408 | await call.message.delete() 409 | await call.message.answer('kuting!') 410 | full_stack_analitika(call.data[:-1]) 411 | photo1 = f'{BASE_DIR}/data/visual/directions/full_stack/{call.data[:-1]}_1.png' 412 | photo2 = f'{BASE_DIR}/data/visual/directions/full_stack/{call.data[:-1]}_2.png' 413 | # print(call.message.text) 414 | p1 = open(photo1, 'rb') 415 | p2 = open(photo2, 'rb') 416 | await bot.send_photo(call.from_user.id, photo=p1) 417 | await bot.send_photo(call.from_user.id, photo=p2) 418 | await call.message.answer('Muvoffaqiyatli bajarildi!', reply_markup=view_analysis_kb) 419 | 420 | ############### software enineering $$$$$$$$$$$$$$$$$ 421 | 422 | @dp.callback_query_handler(text='soft') 423 | async def analysis_view_part_5(call: types.CallbackQuery): 424 | # if check_analysis_users(call.message.from_user.id) or others.check_admin(call.message.from_user.id): 425 | await call.message.delete() 426 | await call.message.answer('Mentorlar analitikasi', reply_markup=all_se_inline()) 427 | 428 | 429 | @dp.callback_query_handler(text=all_se_list()) 430 | async def send_visual_se(call: types.CallbackQuery): 431 | await call.message.delete() 432 | await call.message.answer('kuting!') 433 | soft_engineer_analitika(call.data[:-1]) 434 | photo1 = f'{BASE_DIR}/data/visual/directions/software/{call.data[:-1]}_1.png' 435 | photo2 = f'{BASE_DIR}/visual/directions/software/{call.data[:-1]}_2.png' 436 | # print(call.message.text) 437 | p1 = open(photo1, 'rb') 438 | p2 = open(photo2, 'rb') 439 | await bot.send_photo(call.from_user.id, photo=p1) 440 | await bot.send_photo(call.from_user.id, photo=p2) 441 | await call.message.answer('Muvoffaqiyatli bajarildi!', reply_markup=view_analysis_kb) 442 | 443 | @dp.message_handler(commands=['analysis']) 444 | async def dopstup_ochish(message: types.Message): 445 | if check_analysis_users(message.from_user.id) or others.check_admin(message.from_user.id): 446 | await message.answer('Analitikani ko\'rish', reply_markup=view_analysis_kb) 447 | 448 | 449 | @dp.callback_query_handler(text='main_kirish') 450 | async def back_to_kirish(call: types.CallbackQuery): 451 | await call.message.delete() 452 | await call.message.answer('🔙 Ortga', reply_markup=view_analysis_kb) 453 | 454 | @dp.callback_query_handler(text='ortga') 455 | async def back_to_mentors(call: types.CallbackQuery): 456 | await call.message.delete() 457 | await call.message.answer('🔙 Ortga', reply_markup=analysis_direction) 458 | 459 | #############umumiy analitikia"""""""" 460 | @dp.callback_query_handler(text='umumiy') 461 | async def umumiy_ananitika(call: types.callback_query): 462 | await call.message.delete() 463 | await call.message.answer('Qaysi kategoriya', reply_markup=umumiy_analysis_inl) 464 | 465 | ##########umumiy yonalish ############### 466 | @dp.callback_query_handler(text='umummiy_direction') 467 | async def umumiy_yonalish(call: types.CallbackQuery): 468 | await call.message.delete() 469 | await call.message.answer('kuting!') 470 | umumit_analitika() 471 | photo1 = f'{BASE_DIR}/data/visual/umumiy/yonalish/all.png' 472 | photo2 = f'{BASE_DIR}/data/visual/umumiy/yonalish/all2.png' 473 | p1 = open(photo1, 'rb') 474 | p2 = open(photo2, 'rb') 475 | await bot.send_photo(call.from_user.id, photo=p1) 476 | await bot.send_photo(call.from_user.id, photo=p2) 477 | await call.message.answer('Muvoffaqiyatli bajarildi!', reply_markup=view_analysis_kb) 478 | 479 | 480 | ######### umumiy mentor ##################### 481 | 482 | @dp.callback_query_handler(text='umumiy_metors') 483 | async def umumiy_mentor_part_1(call: types.CallbackQuery): 484 | await call.message.delete() 485 | await call.message.answer('Qaysi yo\'nalish', reply_markup=mentors_umummiy_inl) 486 | 487 | @dp.callback_query_handler(text=['Data Science', 'Full Stack', 'Software Engineering']) 488 | async def umumiy_mentor_part_2(call: types.CallbackQuery): 489 | yonalish = call.data 490 | await call.message.delete() 491 | await call.message.answer('Kuting..') 492 | mentors_analysis(yonalish) 493 | photo1 = f'{BASE_DIR}/data/visual/umumiy/mentor/{yonalish}.png' 494 | photo2 = f'{BASE_DIR}/data/visual/umumiy/mentor/{yonalish}_1.png' 495 | p1 = open(photo1, 'rb') 496 | p2 = open(photo2, 'rb') 497 | await bot.send_photo(call.from_user.id, photo=p1) 498 | await bot.send_photo(call.from_user.id, photo=p2) 499 | await call.message.answer('Muvoffaqiyatli bajarildi!', reply_markup=view_analysis_kb) 500 | 501 | 502 | @dp.callback_query_handler(text='orqaga') 503 | async def ortga_umumiy_mentor(call: types.CallbackQuery): 504 | await call.message.delete() 505 | await call.message.answer('🔙 Ortga', reply_markup=umumiy_analysis_inl) 506 | ######## register dispetcher ################## 507 | 508 | def register_handler_admin(db: Dispatcher): 509 | dp.message_handler(admin_main, commands=['admin']) 510 | dp.message_handler(edit_mentor, text=['Mentor tahrirlash']) --------------------------------------------------------------------------------