├── LICENSE
├── README.md
├── Telegram Support Bot
├── bot.py
├── config.py
├── core.py
├── markup.py
└── sql.py
└── image.png
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Blazzerrr
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Telegram Support Bot
2 |
3 | Telegram Support Bot для технической поддержки пользователей.
4 | Имеется три вида панели:
5 | 1. Основная - она предназначена для пользователей, которые через панель будут создавать и просматривать свои запросы.
6 | 2. Панель для сотрудников технической поддержки. Доступ к этой панели можно получить, введя пароль выданный администратором. В этой панели агент поддержки может просматривать и отвечать на все запросы пользователей.
7 | 3. Админ-панель - нужна для добавления и удаления сотрудников поддержки, генерации/удаления паролей доступа, а также для отключения бота.
8 |
9 | ## Скриншот
10 | 
11 |
12 | ## Настройка
13 | Установите все зависимости из блока ниже с помощью PIP
14 | Откройте файл config.py и по документации внутри файла, заполните все обязательные для запуска переменные.
15 | После выполнения инструкции, запустите файл sql.py
16 | ```bash
17 | cd Telegram Support Bot
18 | python3 sql.py
19 | ```
20 | Если все выполнилось без ошибок - настройка бота завершена и вы можете переходить к запуску бота.
21 |
22 | ## Запуск
23 | ```bash
24 | cd Telegram Support Bot
25 | python3 bot.py
26 | ```
27 |
28 | ## Зависимости
29 | - pyTelegramBotAPI
30 | - cryptography
31 | - pymysql
32 |
33 | ## Донат
34 | — USDT TRC20 / TRX : **TGGu7SE2AiTqKtyiqSn8abZeh62nLZPg7N
**
35 | — USDT ERC20 / ETH : **0xD2F03940ec729BfDFA79a5b7a867e8F55E470b67
**
36 | — BTC: **bc1qhajqf6k3lass7sq8y2p3jg6xav6hrnguacdgsz
**
37 | — XRP: **r3do8Bp7qfobrv5QmyBqp3PzJ2k8VQtGY8
**
38 | — BNB: **bnb1wv357zh590hmys3z07fv56mv8uqua4cvz2p3dw
**
39 | — DOGE: **DL1vn98EWknvSsbkFeruZYk3DhSLft8QWQ
**
40 |
--------------------------------------------------------------------------------
/Telegram Support Bot/bot.py:
--------------------------------------------------------------------------------
1 | import config
2 | import core
3 | import telebot
4 | import random
5 | import datetime
6 | import markup
7 | import sys
8 | from telebot import apihelper
9 |
10 | if config.PROXY_URL:
11 | apihelper.proxy = {'https': config.PROXY_URL}
12 |
13 | bot = telebot.TeleBot(config.TOKEN, skip_pending=True)
14 |
15 | @bot.message_handler(commands=['start'])
16 | def start(message):
17 | bot.send_message(message.chat.id, '👋🏻 Привет! Это бот для технической поддержки пользователей.\nЕсли у тебя есть какой-либо вопрос или проблема - нажми на кнопку Написать запрос и наши сотрудники в скором времени тебе ответят!', parse_mode='html', reply_markup=markup.markup_main())
18 |
19 |
20 | @bot.message_handler(commands=['agent'])
21 | def agent(message):
22 | user_id = message.from_user.id
23 |
24 | if core.check_agent_status(user_id) == True:
25 | bot.send_message(message.chat.id, '🔑 Вы авторизованы как Агент поддержки', parse_mode='html', reply_markup=markup.markup_agent())
26 |
27 | else:
28 | take_password_message = bot.send_message(message.chat.id, '⚠️ Тебя нет в базе. Отправь одноразовый пароль доступа.', reply_markup=markup.markup_cancel())
29 |
30 | bot.clear_step_handler_by_chat_id(message.chat.id)
31 | bot.register_next_step_handler(take_password_message, get_password_message)
32 |
33 |
34 | @bot.message_handler(commands=['admin'])
35 | def admin(message):
36 | user_id = message.from_user.id
37 |
38 | if str(user_id) == config.ADMIN_ID:
39 | bot.send_message(message.chat.id, '🔑 Вы авторизованы как Админ', reply_markup=markup.markup_admin())
40 | else:
41 | bot.send_message(message.chat.id, '🚫 Эта команда доступна только администратору.')
42 |
43 |
44 | @bot.message_handler(content_types=['text'])
45 | def send_text(message):
46 | user_id = message.from_user.id
47 |
48 | if message.text == '✏️ Написать запрос':
49 | take_new_request = bot.send_message(message.chat.id, 'Введите свой запрос и наши сотрудники скоро с вами свяжутся.', reply_markup=markup.markup_cancel())
50 |
51 | bot.clear_step_handler_by_chat_id(message.chat.id)
52 | bot.register_next_step_handler(take_new_request, get_new_request)
53 |
54 | elif message.text == '✉️ Мои запросы':
55 | markup_and_value = markup.markup_reqs(user_id, 'my_reqs', '1')
56 | markup_req = markup_and_value[0]
57 | value = markup_and_value[1]
58 |
59 | if value == 0:
60 | bot.send_message(message.chat.id, 'У вас пока ещё нет запросов.', reply_markup=markup.markup_main())
61 | else:
62 | bot.send_message(message.chat.id, 'Ваши запросы:', reply_markup=markup_req)
63 |
64 | else:
65 | bot.send_message(message.chat.id, 'Вы возвращены в главное меню.', parse_mode='html', reply_markup=markup.markup_main())
66 |
67 |
68 | def get_password_message(message):
69 | password = message.text
70 | user_id = message.from_user.id
71 |
72 | if password == None:
73 | send_message = bot.send_message(message.chat.id, '⚠️ Вы отправляете не текст. Попробуйте еще раз.', reply_markup=markup.markup_cancel())
74 |
75 | bot.clear_step_handler_by_chat_id(message.chat.id)
76 | bot.register_next_step_handler(send_message, get_password_message)
77 |
78 | elif password.lower() == 'отмена':
79 | bot.send_message(message.chat.id, 'Отменено.', reply_markup=markup.markup_main())
80 | return
81 |
82 | elif core.valid_password(password) == True:
83 | core.delete_password(password)
84 | core.add_agent(user_id)
85 |
86 | bot.send_message(message.chat.id, '🔑 Вы авторизованы как Агент поддержки', parse_mode='html', reply_markup=markup.markup_main())
87 | bot.send_message(message.chat.id, 'Выберите раздел технической панели:', parse_mode='html', reply_markup=markup.markup_agent())
88 |
89 | else:
90 | send_message = bot.send_message(message.chat.id, '⚠️ Неверный пароль. Попробуй ещё раз.', reply_markup=markup.markup_cancel())
91 |
92 | bot.clear_step_handler_by_chat_id(message.chat.id)
93 | bot.register_next_step_handler(send_message, get_password_message)
94 |
95 |
96 | def get_agent_id_message(message):
97 | agent_id = message.text
98 |
99 | if agent_id == None:
100 | take_agent_id_message = bot.send_message(message.chat.id, '⚠️ Вы отправляете не текст. Попробуйте еще раз.', reply_markup=markup.markup_cancel())
101 |
102 | bot.clear_step_handler_by_chat_id(message.chat.id)
103 | bot.register_next_step_handler(take_agent_id_message, get_agent_id_message)
104 |
105 | elif agent_id.lower() == 'отмена':
106 | bot.send_message(message.chat.id, 'Отменено.', reply_markup=markup.markup_main())
107 | return
108 |
109 | else:
110 | core.add_agent(agent_id)
111 | bot.send_message(message.chat.id, '✅ Агент успешно добавлен.', reply_markup=markup.markup_main())
112 | bot.send_message(message.chat.id, 'Выберите раздел админ панели:', reply_markup=markup.markup_admin())
113 |
114 |
115 | def get_new_request(message):
116 | request = message.text
117 | user_id = message.from_user.id
118 | check_file = core.get_file(message)
119 |
120 | #Если пользователь отправляет файл
121 | if check_file != None:
122 | file_id = check_file['file_id']
123 | file_name = check_file['file_name']
124 | type = check_file['type']
125 | request = check_file['text']
126 |
127 | if str(request) == 'None':
128 | take_new_request = bot.send_message(message.chat.id, '⚠️ Вы не ввели ваш запрос. Попробуйте ещё раз, отправив текст вместе с файлом.', reply_markup=markup.markup_cancel())
129 |
130 | bot.clear_step_handler_by_chat_id(message.chat.id)
131 | bot.register_next_step_handler(take_new_request, get_new_request)
132 |
133 | else:
134 | req_id = core.new_req(user_id, request)
135 | core.add_file(req_id, file_id, file_name, type)
136 |
137 | bot.send_message(message.chat.id, f'✅ Ваш запрос под ID {req_id} создан. Посмотреть текущие запросы можно нажав кнопку Мои текущие запросы', parse_mode='html', reply_markup=markup.markup_main())
138 |
139 | #Если пользователь отправляет только текст
140 | else:
141 | if request == None:
142 | take_new_request = bot.send_message(message.chat.id, '⚠️ Отправляемый вами тип данных не поддерживается в боте. Попробуйте еще раз отправить ваш запрос, использовав один из доступных типов данных (текст, файлы, фото, видео, аудио, голосовые сообщения)', reply_markup=markup.markup_cancel())
143 |
144 | bot.clear_step_handler_by_chat_id(message.chat.id)
145 | bot.register_next_step_handler(take_new_request, get_new_request)
146 |
147 | elif request.lower() == 'отмена':
148 | bot.send_message(message.chat.id, 'Отменено.', reply_markup=markup.markup_main())
149 | return
150 |
151 | else:
152 | req_id = core.new_req(user_id, request)
153 | bot.send_message(message.chat.id, f'✅ Ваш запрос под ID {req_id} создан. Посмотреть текущие запросы можно нажав кнопку Мои текущие запросы', parse_mode='html', reply_markup=markup.markup_main())
154 |
155 |
156 | def get_additional_message(message, req_id, status):
157 | additional_message = message.text
158 | check_file = core.get_file(message)
159 |
160 | #Если пользователь отправляет файл
161 | if check_file != None:
162 | file_id = check_file['file_id']
163 | file_name = check_file['file_name']
164 | type = check_file['type']
165 | additional_message = check_file['text']
166 |
167 | core.add_file(req_id, file_id, file_name, type)
168 |
169 | if additional_message == None:
170 | take_additional_message = bot.send_message(chat_id=message.chat.id, text='⚠️ Отправляемый вами тип данных не поддерживается в боте. Попробуйте еще раз отправить ваше сообщение, использовав один из доступных типов данных (текст, файлы, фото, видео, аудио, голосовые сообщения).', reply_markup=markup.markup_cancel())
171 |
172 | bot.clear_step_handler_by_chat_id(message.chat.id)
173 | bot.register_next_step_handler(take_additional_message, get_additional_message, req_id, status)
174 |
175 | elif additional_message.lower() == 'отмена':
176 | bot.send_message(message.chat.id, 'Отменено.', reply_markup=markup.markup_main())
177 | return
178 |
179 | else:
180 | if additional_message != 'None':
181 | core.add_message(req_id, additional_message, status)
182 |
183 | if check_file != None:
184 | if additional_message != 'None':
185 | text = '✅ Ваш файл и сообщение успешно отправлены!'
186 | else:
187 | text = '✅ Ваш файл успешно отправлен!'
188 | else:
189 | text = '✅ Ваше сообщение успешно отправлено!'
190 |
191 | bot.send_message(message.chat.id, text, reply_markup=markup.markup_main())
192 |
193 | if status == 'agent':
194 | user_id = core.get_user_id_of_req(req_id)
195 | try:
196 | if additional_message == 'None':
197 | additional_message = ''
198 |
199 | bot.send_message(user_id, f'⚠️ Получен новый ответ на ваш запрос ID {req_id}!\n\n🧑💻 Ответ агента поддержки:\n{additional_message}', reply_markup=markup.markup_main())
200 |
201 | if type == 'photo':
202 | bot.send_photo(user_id, photo=file_id, reply_markup=markup.markup_main())
203 | elif type == 'document':
204 | bot.send_document(user_id, data=file_id, reply_markup=markup.markup_main())
205 | elif type == 'video':
206 | bot.send_video(user_id, data=file_id, reply_markup=markup.markup_main())
207 | elif type == 'audio':
208 | bot.send_audio(user_id, audio=file_id, reply_markup=markup.markup_main())
209 | elif type == 'voice':
210 | bot.send_voice(user_id, voice=file_id, reply_markup=markup.markup_main())
211 | else:
212 | bot.send_message(user_id, additional_message, reply_markup=markup.markup_main())
213 | except:
214 | pass
215 |
216 |
217 | @bot.callback_query_handler(func=lambda call: True)
218 | def callback_inline(call):
219 | user_id = call.message.chat.id
220 |
221 | if call.message:
222 | if ('my_reqs:' in call.data) or ('waiting_reqs:' in call.data) or ('answered_reqs:' in call.data) or ('confirm_reqs:' in call.data):
223 | """
224 | Обработчик кнопок для:
225 |
226 | ✉️ Мои запросы
227 | ❗️ Ожидают ответа от поддержки,
228 | ⏳ Ожидают ответа от пользователя
229 | ✅ Завершенные запросы
230 | """
231 |
232 | parts = call.data.split(':')
233 | callback = parts[0]
234 | number = parts[1]
235 | markup_and_value = markup.markup_reqs(user_id, callback, number)
236 | markup_req = markup_and_value[0]
237 | value = markup_and_value[1]
238 |
239 | if value == 0:
240 | bot.send_message(chat_id=call.message.chat.id, text='⚠️ Запросы не обнаружены.', reply_markup=markup.markup_main())
241 | bot.answer_callback_query(call.id)
242 | return
243 |
244 | try:
245 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='Нажмите на запрос, чтобы посмотреть историю переписки, либо добавить сообщение:', reply_markup=markup_req)
246 | except:
247 | bot.send_message(chat_id=call.message.chat.id, text='Ваши запросы:', reply_markup=markup_req)
248 |
249 | bot.answer_callback_query(call.id)
250 |
251 | #Открыть запрос
252 | elif 'open_req:' in call.data:
253 | parts = call.data.split(':')
254 | req_id = parts[1]
255 | callback = parts[2]
256 |
257 | req_status = core.get_req_status(req_id)
258 | request_data = core.get_request_data(req_id, callback)
259 | len_req_data = len(request_data)
260 |
261 | i = 1
262 | for data in request_data:
263 | if i == len_req_data:
264 | markup_req = markup.markup_request_action(req_id, req_status, callback)
265 | else:
266 | markup_req = None
267 |
268 | bot.send_message(chat_id=call.message.chat.id, text=data, parse_mode='html', reply_markup=markup_req)
269 |
270 | i += 1
271 |
272 | bot.answer_callback_query(call.id)
273 |
274 | #Добавить сообщение в запрос
275 | elif 'add_message:' in call.data:
276 | parts = call.data.split(':')
277 | req_id = parts[1]
278 | status_user = parts[2]
279 |
280 | take_additional_message = bot.send_message(chat_id=call.message.chat.id, text='Отправьте ваше сообщение, использовав один из доступных типов данных (текст, файлы, фото, видео, аудио, голосовые сообщения)', reply_markup=markup.markup_cancel())
281 |
282 | bot.register_next_step_handler(take_additional_message, get_additional_message, req_id, status_user)
283 |
284 | bot.answer_callback_query(call.id)
285 |
286 | #Завершить запрос
287 | elif 'confirm_req:' in call.data:
288 | parts = call.data.split(':')
289 | confirm_status = parts[1]
290 | req_id = parts[2]
291 |
292 | if core.get_req_status(req_id) == 'confirm':
293 | bot.send_message(chat_id=call.message.chat.id, text="⚠️ Этот запрос уже завершен.", reply_markup=markup.markup_main())
294 | bot.answer_callback_query(call.id)
295 |
296 | return
297 |
298 | #Запросить подтверждение завершения
299 | if confirm_status == 'wait':
300 | bot.send_message(chat_id=call.message.chat.id, text="Для завершения запроса - нажмите кнопку Подтвердить", parse_mode='html', reply_markup=markup.markup_confirm_req(req_id))
301 |
302 | #Подтвердить завершение
303 | elif confirm_status == 'true':
304 | core.confirm_req(req_id)
305 |
306 | try:
307 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="✅ Запрос успешно завершён.", reply_markup=markup.markup_main())
308 | except:
309 | bot.send_message(chat_id=call.message.chat.id, text="✅ Запрос успешно завершён.", reply_markup=markup.markup_main())
310 |
311 | bot.answer_callback_query(call.id)
312 |
313 | #Файлы запроса
314 | elif 'req_files:' in call.data:
315 | parts = call.data.split(':')
316 | req_id = parts[1]
317 | callback = parts[2]
318 | number = parts[3]
319 |
320 | markup_and_value = markup.markup_files(number, req_id, callback)
321 | markup_files = markup_and_value[0]
322 | value = markup_and_value[1]
323 |
324 | if value == 0:
325 | bot.send_message(chat_id=call.message.chat.id, text='⚠️ Файлы не обнаружены.', reply_markup=markup.markup_main())
326 | bot.answer_callback_query(call.id)
327 | return
328 |
329 | try:
330 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='Нажмите на файл, чтобы получить его.', reply_markup=markup_files)
331 | except:
332 | bot.send_message(chat_id=call.message.chat.id, text='Нажмите на файл, чтобы получить его.', reply_markup=markup_files)
333 |
334 | bot.answer_callback_query(call.id)
335 |
336 | #Отправить файл
337 | elif 'send_file:' in call.data:
338 | parts = call.data.split(':')
339 | id = parts[1]
340 | type = parts[2]
341 |
342 | file_id = core.get_file_id(id)
343 |
344 | if type == 'photo':
345 | bot.send_photo(call.message.chat.id, photo=file_id, reply_markup=markup.markup_main())
346 | elif type == 'document':
347 | bot.send_document(call.message.chat.id, data=file_id, reply_markup=markup.markup_main())
348 | elif type == 'video':
349 | bot.send_video(call.message.chat.id, data=file_id, reply_markup=markup.markup_main())
350 | elif type == 'audio':
351 | bot.send_audio(call.message.chat.id, audio=file_id, reply_markup=markup.markup_main())
352 | elif type == 'voice':
353 | bot.send_voice(call.message.chat.id, voice=file_id, reply_markup=markup.markup_main())
354 |
355 | bot.answer_callback_query(call.id)
356 |
357 | #Вернуться назад в панель агента
358 | elif call.data == 'back_agent':
359 | try:
360 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='🔑 Вы авторизованы как Агент поддержки', parse_mode='html', reply_markup=markup.markup_agent())
361 | except:
362 | bot.send_message(call.message.chat.id, '🔑 Вы авторизованы как Агент поддержки', parse_mode='html', reply_markup=markup.markup_agent())
363 |
364 | bot.answer_callback_query(call.id)
365 |
366 | #Вернуться назад в панель админа
367 | elif call.data == 'back_admin':
368 | try:
369 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='🔑 Вы авторизованы как Админ', parse_mode='html', reply_markup=markup.markup_admin())
370 | except:
371 | bot.send_message(call.message.chat.id, '🔑 Вы авторизованы как Админ', parse_mode='html', reply_markup=markup.markup_admin())
372 |
373 | bot.answer_callback_query(call.id)
374 |
375 | #Добавить агента
376 | elif call.data == 'add_agent':
377 | take_agent_id_message = bot.send_message(chat_id=call.message.chat.id, text='Чтобы добавить агента поддержки - введите его ID Telegram.', reply_markup=markup.markup_cancel())
378 | bot.register_next_step_handler(take_agent_id_message, get_agent_id_message)
379 |
380 | #Все агенты
381 | elif 'all_agents:' in call.data:
382 | number = call.data.split(':')[1]
383 | markup_and_value = markup.markup_agents(number)
384 | markup_agents = markup_and_value[0]
385 | len_agents = markup_and_value[1]
386 |
387 | if len_agents == 0:
388 | bot.send_message(chat_id=call.message.chat.id, text='⚠️ Агенты не обнаружены.', reply_markup=markup.markup_main())
389 | bot.answer_callback_query(call.id)
390 | return
391 |
392 | try:
393 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='Нажмите на агента поддержки, чтобы удалить его', parse_mode='html', reply_markup=markup_agents)
394 | except:
395 | bot.send_message(call.message.chat.id, 'Нажмите на агента поддержки, чтобы удалить его', parse_mode='html', reply_markup=markup_agents)
396 |
397 | bot.answer_callback_query(call.id)
398 |
399 | #Удалить агента
400 | elif 'delete_agent:' in call.data:
401 | agent_id = call.data.split(':')[1]
402 | core.delete_agent(agent_id)
403 |
404 | try:
405 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='Нажмите на агента поддержки, чтобы удалить его', parse_mode='html', reply_markup=markup.markup_agents('1')[0])
406 | except:
407 | bot.send_message(call.message.chat.id, 'Нажмите на агента поддержки, чтобы удалить его', parse_mode='html', reply_markup=markup.markup_agents('1')[0])
408 |
409 | bot.answer_callback_query(call.id)
410 |
411 | #Все пароли
412 | elif 'all_passwords:' in call.data:
413 | number = call.data.split(':')[1]
414 | markup_and_value = markup.markup_passwords(number)
415 | markup_passwords = markup_and_value[0]
416 | len_passwords = markup_and_value[1]
417 |
418 | if len_passwords == 0:
419 | bot.send_message(chat_id=call.message.chat.id, text='⚠️ Пароли не обнаружены.', reply_markup=markup.markup_main())
420 | bot.answer_callback_query(call.id)
421 | return
422 |
423 | try:
424 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='Нажмите на пароль, чтобы удалить его', parse_mode='html', reply_markup=markup_passwords)
425 | except:
426 | bot.send_message(call.message.chat.id, 'Нажмите на пароль, чтобы удалить его', parse_mode='html', reply_markup=markup_passwords)
427 |
428 | bot.answer_callback_query(call.id)
429 |
430 | #Удалить пароль
431 | elif 'delete_password:' in call.data:
432 | password = call.data.split(':')[1]
433 | core.delete_password(password)
434 |
435 | try:
436 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='Нажмите на пароль, чтобы удалить его', parse_mode='html', reply_markup=markup.markup_passwords('1')[0])
437 | except:
438 | bot.send_message(call.message.chat.id, 'Нажмите на пароль, чтобы удалить его', parse_mode='html', reply_markup=markup.markup_passwords('1')[0])
439 |
440 | bot.answer_callback_query(call.id)
441 |
442 | #Сгенерировать пароли
443 | elif call.data == 'generate_passwords':
444 | #10 - количество паролей, 16 - длина пароля
445 | passwords = core.generate_passwords(10, 16)
446 | core.add_passwords(passwords)
447 |
448 | text_passwords = ''
449 | i = 1
450 | for password in passwords:
451 | text_passwords += f'{i}. {password}\n'
452 | i += 1
453 |
454 | bot.send_message(call.message.chat.id, f"✅ Сгенерировано {i-1} паролей:\n\n{text_passwords}", parse_mode='html', reply_markup=markup.markup_main())
455 | bot.send_message(call.message.chat.id, 'Нажмите на пароль, чтобы удалить его', parse_mode='html', reply_markup=markup.markup_passwords('1')[0])
456 |
457 | bot.answer_callback_query(call.id)
458 |
459 | #Остановить бота
460 | elif 'stop_bot:' in call.data:
461 | status = call.data.split(':')[1]
462 |
463 | #Запросить подтверждение на отключение
464 | if status == 'wait':
465 | try:
466 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=f"Вы точно хотите отключить бота?", parse_mode='html', reply_markup=markup.markup_confirm_stop())
467 | except:
468 | bot.send_message(call.message.chat.id, f"Вы точно хотите отключить бота?", parse_mode='html', reply_markup=markup.markup_confirm_stop())
469 |
470 | #Подтверждение получено
471 | elif status == 'confirm':
472 | try:
473 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text='✅ Бот оключен.')
474 | except:
475 | bot.send_message(chat_id=call.message.chat.id, text='✅ Бот оключен.')
476 |
477 | bot.answer_callback_query(call.id)
478 | bot.stop_polling()
479 | sys.exit()
480 |
481 |
482 | if __name__ == "__main__":
483 | bot.polling(none_stop=True)
--------------------------------------------------------------------------------
/Telegram Support Bot/config.py:
--------------------------------------------------------------------------------
1 | """
2 | Для начала работы с ботом вам необходимо настроить конфигурационный файл бота - config.py
3 | Обязательными переменными является TOKEN, ADMIN_ID и MySQL.
4 | PROXY_URL вы можете оставить пустым.
5 |
6 | Описывать установку и настройку я буду для Linux, Ubuntu-based дистрибутивов. Если у вас установлен Windows, либо же другой дистрибутив, то различия с гайдом ниже вы найдете только в пунктах с установкой и настройкой MySQL. Поэтому, при возникновении проблем попробуйте найти гайд по установке MySQL конкретно под вашу ОС.
7 |
8 | 1. Сначала, проверьте установлен ли MySQL на вашем ПК.
9 | Откройте терминал и пропишите команду: mysql --version
10 | Если вы увидите сообщение похожее на: mysql Ver xx.xx ****, то можете смело переходить на пункт номер 2.
11 |
12 | 1.2. Если же MySQL не установлен, то введите несколько команд в терминал:
13 | sudo apt update
14 | sudo apt install mysql-server
15 |
16 | Возвращаемся в пункт 1 и проверяем правильно ли мы все установили.
17 | Если видите сообщение с версией установленного MySQL, то переходим дальше.
18 | Если нет - возвращаемся и проверяем, что вы сделали не так.
19 |
20 | 2. С установкой MySQL закончили, переходим к созданию пользователя и БД
21 | Введите в терминал команду mysql
22 |
23 | 2.2. После этого создайте пользователя командой:
24 | CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
25 |
26 | Где user - имя пользователя
27 | А password - пароль
28 |
29 | 2.3. Предоставьте права пользователю:
30 | GRANT ALL PRIVILEGES ON * . * TO 'user'@'localhost';
31 | FLUSH PRIVILEGES;
32 |
33 | Где user - имя пользователя, которое вы ввели в шаге выше
34 |
35 | 2.4. Создайте БД:
36 | CREATE DATABASE support_db;
37 |
38 | Где support_db - имя базы данных
39 |
40 | 2.5. Замените все значения в переменной MySQL
41 | localhost - оставить без изменения
42 | user - имя пользователя, которого вы создали
43 | password - пароль для пользователя
44 | support_db - имя базы данных
45 |
46 | 3. Создайте вашего бота и получите токен для него
47 | Перейдите по ссылке t.me/BotFather, либо найдите его сами в поиске по юзернейму @BotFather и введите команду /newbot
48 | Следуйте дальнейшим указаниям бота и укажите полученный токен в переменной TOKEN
49 |
50 | 4. Найдите бота, который отправит вам ваш Telegram ID
51 | Одними из таких ботов могут быть @userinfobot или @username_to_id_bot
52 | Введите полученный ID в переменную ADMIN_ID
53 |
54 | На этом, настройка конфига завершена. Можете просто сохранить и закрыть этот файл.
55 | """
56 |
57 | MySQL = ['localhost', 'user', 'password', 'support_db']
58 | TOKEN = ''
59 | ADMIN_ID = ''
60 | PROXY_URL = ''
--------------------------------------------------------------------------------
/Telegram Support Bot/core.py:
--------------------------------------------------------------------------------
1 | import config
2 | import datetime
3 | import random
4 | import pymysql
5 |
6 |
7 | #Добавить агента
8 | def add_agent(agent_id):
9 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
10 | cur = con.cursor()
11 |
12 | cur.execute(f"INSERT INTO agents (`agent_id`) VALUES ('{agent_id}')")
13 | con.commit()
14 |
15 | cur.close()
16 | con.close()
17 |
18 |
19 | #Добавить файл
20 | def add_file(req_id, file_id, file_name, type):
21 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
22 | cur = con.cursor()
23 |
24 | cur.execute(f"INSERT INTO files (`req_id`, `file_id`, `file_name`, `type`) VALUES ('{req_id}', '{file_id}', '{file_name}', '{type}')")
25 | con.commit()
26 |
27 | cur.close()
28 | con.close()
29 |
30 |
31 | #Создать запрос
32 | def new_req(user_id, request):
33 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
34 | cur = con.cursor()
35 |
36 | #Добавить запрос в БД
37 | cur.execute(f"INSERT INTO requests (`user_id`, `req_status`) VALUES ('{user_id}', 'waiting')")
38 |
39 | #Получить айди добавленного запроса
40 | req_id = cur.lastrowid
41 |
42 | dt = datetime.datetime.now()
43 | date_now = dt.strftime('%d.%m.%Y %H:%M:%S')
44 |
45 | #Добавить сообщение для запроса
46 | cur.execute(f"INSERT INTO messages (`req_id`, `message`, `user_status`, `date`) VALUES ('{req_id}', '{request}', 'user', '{date_now}')")
47 |
48 | con.commit()
49 |
50 | cur.close()
51 | con.close()
52 |
53 | return req_id
54 |
55 |
56 | #Добавить сообщение
57 | def add_message(req_id, message, user_status):
58 | if user_status == 'user':
59 | req_status = 'waiting'
60 | elif user_status == 'agent':
61 | req_status = 'answered'
62 |
63 | dt = datetime.datetime.now()
64 | date_now = dt.strftime('%d.%m.%Y %H:%M:%S')
65 |
66 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
67 | cur = con.cursor()
68 |
69 | #Добавить сообщение для запроса
70 | cur.execute(f"INSERT INTO messages (`req_id`, `message`, `user_status`, `date`) VALUES ('{req_id}', '{message}', '{user_status}', '{date_now}')")
71 |
72 | #Изменить статус запроса
73 | cur.execute(f"UPDATE requests SET `req_status` = '{req_status}' WHERE `req_id` = '{req_id}'")
74 |
75 | con.commit()
76 |
77 | cur.close()
78 | con.close()
79 |
80 |
81 | #Добавить пароли
82 | def add_passwords(passwords):
83 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
84 | cur = con.cursor()
85 |
86 | for password in passwords:
87 | cur.execute(f"INSERT INTO passwords (`password`) VALUES ('{password}')")
88 |
89 | con.commit()
90 |
91 | cur.close()
92 | con.close()
93 |
94 |
95 | #Проверить статус агента
96 | def check_agent_status(user_id):
97 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
98 | cur = con.cursor()
99 |
100 | cur.execute(f"SELECT * FROM agents WHERE `agent_id` = '{user_id}'")
101 | agent = cur.fetchone()
102 |
103 | cur.close()
104 | con.close()
105 |
106 | if agent == None:
107 | return False
108 | else:
109 | return True
110 |
111 |
112 | #Проверить валидность пароля
113 | def valid_password(password):
114 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
115 | cur = con.cursor()
116 |
117 | cur.execute(f"SELECT * FROM passwords WHERE `password` = '{password}'")
118 | password = cur.fetchone()
119 |
120 | cur.close()
121 | con.close()
122 |
123 | if password == None:
124 | return False
125 | else:
126 | return True
127 |
128 |
129 | #Проверить отправляет ли пользователь файл, если да - вернуть его
130 | def get_file(message):
131 | """
132 | Атрибут file_name доступен только в типах файлов - document и video.
133 | Если пользователь отправляет не документ и не видео - в качестве имени файла передать дату и время отправки (date_now)
134 | """
135 |
136 | types = ['document', 'video', 'audio', 'voice']
137 | dt = datetime.datetime.now()
138 | date_now = dt.strftime('%d.%m.%Y %H:%M:%S')
139 |
140 | #Сначала проверить отправляет ли пользователь фото
141 | try:
142 | return {'file_id': message.json['photo'][-1]['file_id'], 'file_name': date_now, 'type': 'photo', 'text': str(message.caption)}
143 |
144 | #Если нет - проверить отправляет ли документ, видео, аудио, голосовое сообщение
145 | except:
146 | for type in types:
147 | try:
148 | if type == 'document' or type == 'video':
149 | file_name = message.json[type]['file_name']
150 | else:
151 | file_name = date_now
152 |
153 | return {'file_id': message.json[type]['file_id'], 'file_name': file_name, 'type': type, 'text': str(message.caption)}
154 | except:
155 | pass
156 |
157 | return None
158 |
159 |
160 | #Получить иконку статуса запроса
161 | def get_icon_from_status(req_status, user_status):
162 | if req_status == 'confirm':
163 | return '✅'
164 |
165 | elif req_status == 'waiting':
166 | if user_status == 'user':
167 | return '⏳'
168 | elif user_status == 'agent':
169 | return '❗️'
170 |
171 | elif req_status == 'answered':
172 | if user_status == 'user':
173 | return '❗️'
174 | elif user_status == 'agent':
175 | return '⏳'
176 |
177 |
178 | #Получить текст для кнопки с файлом
179 | def get_file_text(file_name, type):
180 | if type == 'photo':
181 | return f'📷 | Фото {file_name}'
182 | elif type == 'document':
183 | return f'📄 | Документ {file_name}'
184 | elif type == 'video':
185 | return f'🎥 | Видео {file_name}'
186 | elif type == 'audio':
187 | return f'🎵 | Аудио {file_name}'
188 | elif type == 'voice':
189 | return f'🎧 | Голосовое сообщение {file_name}'
190 |
191 |
192 | #Сгенерировать пароли
193 | def generate_passwords(number, lenght):
194 | chars = 'abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
195 |
196 | passsords = []
197 | for _ in range(number):
198 | password = ''
199 | for _ in range(lenght):
200 | password += random.choice(chars)
201 |
202 | passsords.append(password)
203 |
204 | return passsords
205 |
206 |
207 | #Получить юзер айди пользователя, создавшего запрос
208 | def get_user_id_of_req(req_id):
209 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
210 | cur = con.cursor()
211 |
212 | cur.execute(f"SELECT `user_id` FROM requests WHERE `req_id` = '{req_id}'")
213 | user_id = cur.fetchone()[0]
214 |
215 | cur.close()
216 | con.close()
217 |
218 | return user_id
219 |
220 |
221 | #Получить file_id из id записи в БД
222 | def get_file_id(id):
223 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
224 | cur = con.cursor()
225 |
226 | cur.execute(f"SELECT `file_id` FROM files WHERE `id` = '{id}'")
227 | file_id = cur.fetchone()[0]
228 |
229 | cur.close()
230 | con.close()
231 |
232 | return file_id
233 |
234 |
235 | #Получить статус запроса
236 | def get_req_status(req_id):
237 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
238 | cur = con.cursor()
239 |
240 | cur.execute(f"SELECT `req_status` FROM requests WHERE `req_id` = '{req_id}'")
241 | req_status = cur.fetchone()[0]
242 |
243 | cur.close()
244 | con.close()
245 |
246 | return req_status
247 |
248 |
249 | #Удалить пароль
250 | def delete_password(password):
251 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
252 | cur = con.cursor()
253 |
254 | cur.execute(f"DELETE FROM {config.MySQL[3]}.passwords WHERE `password` = '{password}'")
255 | con.commit()
256 |
257 | cur.close()
258 | con.close()
259 |
260 |
261 | #Удалить агента
262 | def delete_agent(agent_id):
263 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
264 | cur = con.cursor()
265 |
266 | cur.execute(f"DELETE FROM {config.MySQL[3]}.agents WHERE `agent_id` = '{agent_id}'")
267 | con.commit()
268 |
269 | cur.close()
270 | con.close()
271 |
272 |
273 | #Завершить запрос
274 | def confirm_req(req_id):
275 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
276 | cur = con.cursor()
277 |
278 | cur.execute(f"UPDATE requests SET `req_status` = 'confirm' WHERE `req_id` = '{req_id}'")
279 | con.commit()
280 |
281 | cur.close()
282 | con.close()
283 |
284 |
285 | #Получить пароли с лимитом
286 | def get_passwords(number):
287 | limit = (int(number) * 10) - 10
288 |
289 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
290 | cur = con.cursor()
291 |
292 | cur.execute(f"SELECT `password` FROM passwords LIMIT {limit}, 10")
293 | passwords = cur.fetchall()
294 |
295 | cur.close()
296 | con.close()
297 |
298 | return passwords
299 |
300 |
301 | #Получить агентов с лимитом
302 | def get_agents(number):
303 | limit = (int(number) * 10) - 10
304 |
305 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
306 | cur = con.cursor()
307 |
308 | cur.execute(f"SELECT `agent_id` FROM agents LIMIT {limit}, 10")
309 | agents = cur.fetchall()
310 |
311 | cur.close()
312 | con.close()
313 |
314 | return agents
315 |
316 |
317 | #Получить мои запросы с лимитом
318 | def my_reqs(number, user_id):
319 | limit = (int(number) * 10) - 10
320 |
321 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
322 | cur = con.cursor()
323 |
324 | cur.execute(f"SELECT `req_id`, `req_status` FROM requests WHERE `user_id` = '{user_id}' ORDER BY `req_id` DESC LIMIT {limit}, 10")
325 | reqs = cur.fetchall()
326 |
327 | cur.close()
328 | con.close()
329 |
330 | return reqs
331 |
332 |
333 | #Получить запросы по статусу с лимитом
334 | def get_reqs(number, callback):
335 | limit = (int(number) * 10) - 10
336 | req_status = callback.replace('_reqs', '')
337 |
338 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
339 | cur = con.cursor()
340 |
341 | cur.execute(f"SELECT `req_id`, `req_status` FROM requests WHERE `req_status` = '{req_status}' ORDER BY `req_id` DESC LIMIT {limit}, 10")
342 | reqs = cur.fetchall()
343 |
344 | cur.close()
345 | con.close()
346 |
347 | return reqs
348 |
349 |
350 | #Получить файлы по запросу с лимитом
351 | def get_files(number, req_id):
352 | limit = (int(number) * 10) - 10
353 |
354 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
355 | cur = con.cursor()
356 |
357 | cur.execute(f"SELECT `id`, `file_name`, `type` FROM files WHERE `req_id` = '{req_id}' ORDER BY `id` DESC LIMIT {limit}, 10")
358 | files = cur.fetchall()
359 |
360 | cur.close()
361 | con.close()
362 |
363 | return files
364 |
365 |
366 | #Получить историю запроса
367 | def get_request_data(req_id, callback):
368 | if 'my_reqs' in callback:
369 | get_dialog_user_status = 'user'
370 | else:
371 | get_dialog_user_status = 'agent'
372 |
373 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
374 | cur = con.cursor()
375 |
376 | cur.execute(f"SELECT `message`, `user_status`, `date` FROM messages WHERE `req_id` = '{req_id}'")
377 | messages = cur.fetchall()
378 |
379 | cur.close()
380 | con.close()
381 |
382 | data = []
383 | text = ''
384 | i = 1
385 |
386 | for message in messages:
387 | message_value = message[0]
388 | user_status = message[1]
389 | date = message[2]
390 |
391 | if user_status == 'user':
392 | if get_dialog_user_status == 'user':
393 | text_status = '👤 Ваше сообщение'
394 | else:
395 | text_status = '👤 Сообщение пользователя'
396 | elif user_status == 'agent':
397 | text_status = '🧑💻 Агент поддержки'
398 |
399 | #Бэкап для текста
400 | backup_text = text
401 | text += f'{text_status}\n{date}\n{message_value}\n\n'
402 |
403 | #Если размер текста превышает допустимый в Telegram, то добавить первую часть текста и начать вторую
404 | if len(text) >= 4096:
405 | data.append(backup_text)
406 | text = f'{text_status}\n{date}\n{message_value}\n\n'
407 |
408 | #Если сейчас последняя итерация, то проверить не является ли часть текста превыщающий допустимый размер (4096 символов). Если превышает - добавить часть и начать следующую. Если нет - просто добавить последнюю часть списка.
409 | if len(messages) == i:
410 | if len(text) >= 4096:
411 | data.append(backup_text)
412 | text = f'{text_status}\n{date}\n{message_value}\n\n'
413 |
414 | data.append(text)
415 |
416 | i += 1
417 |
418 | return data
--------------------------------------------------------------------------------
/Telegram Support Bot/markup.py:
--------------------------------------------------------------------------------
1 | from telebot import types
2 | from core import my_reqs, get_reqs, get_agents, get_passwords, get_files, get_icon_from_status, get_file_text
3 |
4 |
5 | def page(markup, number, list, call, callback_cancel):
6 | if len(list) != 10:
7 | max_nums = number
8 | else:
9 | max_nums = 'None'
10 |
11 | if str(number) == '1':
12 | item1 = types.InlineKeyboardButton(f"⏹", callback_data=f'None')
13 | else:
14 | item1 = types.InlineKeyboardButton(f"◀️", callback_data=f'{call}:{int(number) - 1}')
15 |
16 | if str(number) == str(max_nums):
17 | item2 = types.InlineKeyboardButton(f"⏹", callback_data=f'None')
18 | else:
19 | item2 = types.InlineKeyboardButton(f"▶️", callback_data=f'{call}:{int(number) + 1}')
20 |
21 | item3 = types.InlineKeyboardButton("Назад", callback_data=callback_cancel)
22 |
23 | if callback_cancel != 'None':
24 | markup.add(item1, item3, item2)
25 | else:
26 | if str(number) == '1' and str(number) == str(max_nums):
27 | pass
28 | else:
29 | markup.add(item1, item2)
30 |
31 | return markup
32 |
33 |
34 | def markup_main():
35 | markup_main = types.ReplyKeyboardMarkup(resize_keyboard=True)
36 | item1 = types.KeyboardButton("✏️ Написать запрос")
37 | item2 = types.KeyboardButton("✉️ Мои запросы")
38 | markup_main.row(item1)
39 | markup_main.row(item2)
40 |
41 | return markup_main
42 |
43 |
44 | def markup_agent():
45 | markup_agent = types.InlineKeyboardMarkup(row_width=1)
46 | item1 = types.InlineKeyboardButton("❗️ Ожидают ответа от поддержки", callback_data='waiting_reqs:1')
47 | item2 = types.InlineKeyboardButton("⏳ Ожидают ответа от пользователя", callback_data='answered_reqs:1')
48 | item3 = types.InlineKeyboardButton("✅ Завершенные запросы", callback_data='confirm_reqs:1')
49 | markup_agent.add(item1, item2, item3)
50 |
51 | return markup_agent
52 |
53 |
54 | def markup_cancel():
55 | markup_cancel = types.ReplyKeyboardMarkup(resize_keyboard=True)
56 | item1 = types.KeyboardButton("Отмена")
57 | markup_cancel.row(item1)
58 |
59 | return markup_cancel
60 |
61 |
62 | def markup_admin():
63 | markup_admin = types.InlineKeyboardMarkup(row_width=1)
64 | item1 = types.InlineKeyboardButton("✅ Добавить агента поддержки", callback_data='add_agent')
65 | item2 = types.InlineKeyboardButton("🧑💻 Агенты поддержки", callback_data='all_agents:1')
66 | item3 = types.InlineKeyboardButton("🔑 Одноразовые пароли", callback_data='all_passwords:1')
67 | item4 = types.InlineKeyboardButton("🎲 Сгенерировать одноразовые пароли", callback_data='generate_passwords')
68 | item5 = types.InlineKeyboardButton("⛔️ Выключить бота", callback_data='stop_bot:wait')
69 | markup_admin.add(item1, item2, item3, item4, item5)
70 |
71 | return markup_admin
72 |
73 |
74 | def markup_back(back):
75 | markup_back = types.InlineKeyboardMarkup(row_width=1)
76 | item1 = types.InlineKeyboardButton("Назад", callback_data=f'back_{back}')
77 | markup_back.add(item1)
78 |
79 | return markup_back
80 |
81 |
82 | def markup_reqs(user_id, callback, number):
83 | if callback == 'my_reqs':
84 | reqs = my_reqs(number, user_id)
85 | user_status = 'user'
86 | callback_cancel = 'None'
87 | else:
88 | reqs = get_reqs(number, callback)
89 | user_status = 'agent'
90 | callback_cancel = 'back_agent'
91 |
92 | markup_my_reqs = types.InlineKeyboardMarkup(row_width=3)
93 | for req in reqs:
94 | req_id = req[0]
95 | req_status = req[1]
96 | req_icon = get_icon_from_status(req_status, user_status)
97 | #❗️, ⏳, ✅
98 |
99 | item = types.InlineKeyboardButton(f'{req_icon} | ID: {req_id}', callback_data=f'open_req:{req_id}:{callback}-{number}')
100 | markup_my_reqs.add(item)
101 |
102 | markup_my_reqs = page(markup_my_reqs, number, reqs, callback, callback_cancel)
103 |
104 | return markup_my_reqs, len(reqs)
105 |
106 |
107 | def markup_request_action(req_id, req_status, callback):
108 | formatted_callback = callback.replace('-', ':')
109 |
110 | markup_request_action = types.InlineKeyboardMarkup(row_width=1)
111 |
112 | if req_status == 'confirm':
113 | item1 = types.InlineKeyboardButton("🗂 Показать файлы", callback_data=f'req_files:{req_id}:{callback}:1')
114 | item2 = types.InlineKeyboardButton("Назад", callback_data=formatted_callback)
115 |
116 | markup_request_action.add(item1, item2)
117 |
118 | elif req_status == 'answered' or req_status == 'waiting':
119 | if 'my_reqs:' in formatted_callback:
120 | status_user = 'user'
121 | else:
122 | status_user = 'agent'
123 |
124 | item1 = types.InlineKeyboardButton("✏️ Добавить сообщение", callback_data=f'add_message:{req_id}:{status_user}')
125 | item2 = types.InlineKeyboardButton("🗂 Показать файлы", callback_data=f'req_files:{req_id}:{callback}:1')
126 |
127 | if status_user == 'user':
128 | item3 = types.InlineKeyboardButton("✅ Завершить запрос", callback_data=f'confirm_req:wait:{req_id}')
129 |
130 | item4 = types.InlineKeyboardButton("Назад", callback_data=formatted_callback)
131 |
132 | if status_user == 'user':
133 | markup_request_action.add(item1, item2, item3, item4)
134 | else:
135 | markup_request_action.add(item1, item2, item4)
136 |
137 | return markup_request_action
138 |
139 |
140 | def markup_confirm_req(req_id):
141 | markup_confirm_req = types.InlineKeyboardMarkup(row_width=1)
142 | item1 = types.InlineKeyboardButton("✅ Подтвердить", callback_data=f'confirm_req:true:{req_id}')
143 | markup_confirm_req.add(item1)
144 |
145 | return markup_confirm_req
146 |
147 |
148 | def markup_agents(number):
149 | agents = get_agents(number)
150 |
151 | markup_agents = types.InlineKeyboardMarkup(row_width=3)
152 | for agent in agents:
153 | agent_id = agent[0]
154 |
155 | item = types.InlineKeyboardButton(f'🧑💻 | {agent_id}', callback_data=f'delete_agent:{agent_id}')
156 | markup_agents.add(item)
157 |
158 | markup_agents = page(markup_agents, number, agents, 'all_agents', 'back_admin')
159 |
160 | return markup_agents, len(agents)
161 |
162 |
163 | def markup_passwords(number):
164 | passwords = get_passwords(number)
165 |
166 | markup_passwords = types.InlineKeyboardMarkup(row_width=3)
167 | for password in passwords:
168 | password_value = password[0]
169 |
170 | item = types.InlineKeyboardButton(password_value, callback_data=f'delete_password:{password_value}')
171 | markup_passwords.add(item)
172 |
173 | markup_passwords = page(markup_passwords, number, passwords, 'all_passwords', 'back_admin')
174 |
175 | return markup_passwords, len(passwords)
176 |
177 |
178 | def markup_files(number, req_id, callback):
179 | files = get_files(number, req_id)
180 |
181 | markup_files = types.InlineKeyboardMarkup(row_width=3)
182 | for file in files:
183 | id = file[0]
184 | file_name = file[1]
185 | type = file[2]
186 |
187 | file_text = get_file_text(file_name, type)
188 | # 📷 | Фото 27.12.2020 14:21:50
189 |
190 | item = types.InlineKeyboardButton(file_text, callback_data=f'send_file:{id}:{type}')
191 | markup_files.add(item)
192 |
193 | markup_files = page(markup_files, number, files, f'req_files:{req_id}:{callback}', f'open_req:{req_id}:{callback}')
194 |
195 | return markup_files, len(files)
196 | markup_files('1', '1', '1')
197 |
198 | def markup_confirm_stop():
199 | markup_confirm_stop = types.InlineKeyboardMarkup(row_width=1)
200 | item1 = types.InlineKeyboardButton("Да", callback_data='stop_bot:confirm')
201 | item2 = types.InlineKeyboardButton("Нет", callback_data='back_admin')
202 | markup_confirm_stop.add(item1, item2)
203 |
204 | return markup_confirm_stop
--------------------------------------------------------------------------------
/Telegram Support Bot/sql.py:
--------------------------------------------------------------------------------
1 | import config
2 | import pymysql
3 |
4 |
5 | def create_table_agents():
6 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
7 | cur = con.cursor()
8 |
9 | cur.execute("CREATE TABLE IF NOT EXISTS agents(id INT NOT NULL AUTO_INCREMENT, `agent_id` VARCHAR(20), PRIMARY KEY (id))")
10 | cur.execute(f"ALTER TABLE agents CONVERT TO CHARACTER SET utf8mb4")
11 |
12 | cur.close()
13 | con.close()
14 |
15 |
16 | def create_table_passwords():
17 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
18 | cur = con.cursor()
19 |
20 | cur.execute("CREATE TABLE IF NOT EXISTS passwords(id INT NOT NULL AUTO_INCREMENT, `password` VARCHAR(20), PRIMARY KEY (id))")
21 | cur.execute(f"ALTER TABLE passwords CONVERT TO CHARACTER SET utf8mb4")
22 |
23 | cur.close()
24 | con.close()
25 |
26 |
27 | def create_table_files():
28 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
29 | cur = con.cursor()
30 |
31 | cur.execute("CREATE TABLE IF NOT EXISTS files(id INT NOT NULL AUTO_INCREMENT, `req_id` VARCHAR(20), `file_id` VARCHAR(250), `file_name` VARCHAR(2048), `type` VARCHAR(20), PRIMARY KEY (id))")
32 | cur.execute(f"ALTER TABLE files CONVERT TO CHARACTER SET utf8mb4")
33 |
34 | cur.close()
35 | con.close()
36 |
37 |
38 | def create_table_requests():
39 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
40 | cur = con.cursor()
41 |
42 | cur.execute("CREATE TABLE IF NOT EXISTS requests(req_id INT NOT NULL AUTO_INCREMENT, `user_id` VARCHAR(20), `req_status` VARCHAR(20), PRIMARY KEY (req_id))")
43 | cur.execute(f"ALTER TABLE requests CONVERT TO CHARACTER SET utf8mb4")
44 |
45 | cur.close()
46 | con.close()
47 |
48 |
49 | def create_table_messages():
50 | con = pymysql.connect(host=config.MySQL[0], user=config.MySQL[1], passwd=config.MySQL[2], db=config.MySQL[3])
51 | cur = con.cursor()
52 |
53 | cur.execute("CREATE TABLE IF NOT EXISTS messages(id INT NOT NULL AUTO_INCREMENT, `req_id` VARCHAR(20), `message` VARCHAR(4096), `user_status` VARCHAR(20), `date` VARCHAR(50), PRIMARY KEY (id))")
54 | cur.execute(f"ALTER TABLE messages CONVERT TO CHARACTER SET utf8mb4")
55 |
56 | cur.close()
57 | con.close()
58 |
59 |
60 |
61 | create_table_agents()
62 | create_table_passwords()
63 | create_table_files()
64 | create_table_requests()
65 | create_table_messages()
--------------------------------------------------------------------------------
/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Blazzerrr/TelegramSupportBot/c3f50e63ffcd0f087c3cd06f5f0fc42d2226e1b4/image.png
--------------------------------------------------------------------------------