├── feedback.jpg ├── php ├── bd.php ├── mess.php └── adm.php ├── feedback.service ├── README.md ├── AdminsFeedback.sql └── bot.py /feedback.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FSystem88/feedback_tg_bot/HEAD/feedback.jpg -------------------------------------------------------------------------------- /php/bd.php: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /feedback.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Feedback bot 3 | 4 | [Service] 5 | ExecStart=/root/feedback_tg_bot/bot.py 6 | 7 | [Install] 8 | WantedBy=multi-user.target 9 | 10 | [Service] 11 | Restart=on-failure 12 | RestartSec=1s 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # feedback_tg_bot 2 | Многофункциональный телеграмм бот для обратной связи (техподдержка)
3 | Multifunctional telegram bot for feedback (technical support) 4 | 5 | # Возможности 6 | - Принимает сообщения от пользователей и отправляет всем админам [неожиданно, не правда ли :)] 7 | - Можно просматривать всех админов, добавлять новых, а так же удалять админов --> МОЖЕТ ТОЛЬКО БОГ (главный админ) 8 | - Отвечать на сообщения или удалять из вашего чата 9 | - Все сообщения сохраняются в базе данных 10 | - Можно просматривать сообщения без ответа и уже с ответом и кто из админов ответил и какой ответ дал, для каждого есть своя кнопка ("Непрочитанные" и "Старые") 11 | - При нажатии inline кнопки "Удалить" теперь сообщение удаляется сразу из базы данных 12 | - Бот связывается с MySQL через API написанным на PHP 13 | - Добавлять пользователей в черный список бота, просматривать кто в ЧС и можно разбанить 14 | - Отправлять единое сообщение (ну или рекламу) всем участникам бота 15 | 16 | ## Просто установи себе и попробуй, словами не описать какой удобный бот)) 17 | ## https://youtu.be/HanHbsmnH1I?si=DLCIev4srr2CiLFU 18 | По поводу установки и модернизации писать в https://t.me/FSystem88_bot 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /php/mess.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /AdminsFeedback.sql: -------------------------------------------------------------------------------- 1 | -- СОЗДАНИЕ ТАБЛИЦЫ С ПОЛЬЗОВАТЕЛЯМИ И АДМИНАМИ: 2 | DROP TABLE IF EXISTS `AdminsFeedback`; 3 | CREATE TABLE `AdminsFeedback` ( 4 | `id` int(11) NOT NULL, 5 | `tgid` varchar(64) CHARACTER SET utf8mb4 NULL, 6 | `name` varchar(64) CHARACTER SET utf8mb4 NULL, 7 | `username` varchar(64) CHARACTER SET utf8mb4 NULL, 8 | `status` varchar(64) CHARACTER SET utf8mb4 NULL, 9 | `ban` varchar(3) CHARACTER SET utf8mb4 NULL 10 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 11 | 12 | INSERT INTO `AdminsFeedback` (`id`, `tgid`, `name`, `username`, `status`) VALUES 13 | (1, 'ТВОЙ АЙДИ В ТЕЛЕГЕ', 'ТВОЁ ИМЯ', 'ТВОЙ ЮЗЕРНЕЙМ', 'god'); 14 | 15 | -- ВАЖНО! --> ПОСЛЕ ЮЗЕРНЕЙМА НЕ МЕНЯТЬ "god" НА ДРУГОЕ, ЭТО ЗНАЧИТ СТАТУС БОГА, А-ЛЯ САМЫЙ ГЛАВНЫЙ АДМИН !!! 16 | 17 | ALTER TABLE `AdminsFeedback` 18 | ADD PRIMARY KEY (`id`); 19 | ALTER TABLE `AdminsFeedback` 20 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; 21 | 22 | 23 | -- СОЗДАНИЕ ТАБЛИЦЫ С СООБЩЕНИЯМИ 24 | DROP TABLE IF EXISTS `MessFeedback`; 25 | CREATE TABLE `MessFeedback` ( 26 | `id` int(11) NOT NULL, 27 | `tgid` varchar(64) CHARACTER SET utf8mb4 NULL, 28 | `name` varchar(64) CHARACTER SET utf8mb4 NULL, 29 | `username` varchar(64) CHARACTER SET utf8mb4 NULL, 30 | `text` text CHARACTER SET utf8mb4 NULL, 31 | `answer` text CHARACTER SET utf8mb4 NULL, 32 | `status` varchar(64) CHARACTER SET utf8mb4 NULL, 33 | `adminID` varchar(64) CHARACTER SET utf8mb4 NULL, 34 | `adminName` varchar(64) CHARACTER SET utf8mb4 NULL 35 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 36 | 37 | ALTER TABLE `MessFeedback` 38 | ADD PRIMARY KEY (`id`); 39 | ALTER TABLE `MessFeedback` 40 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1; 41 | -------------------------------------------------------------------------------- /php/adm.php: -------------------------------------------------------------------------------- 1 | 74 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3.10 2 | # -*- coding: utf-8 -*- 3 | # Dev: FSystem88 4 | 5 | import telebot, cloudscraper as cs, time, threading 6 | from telebot import types 7 | from telebot import * 8 | from telebot.types import * 9 | 10 | bot = telebot.TeleBot("") 11 | 12 | r = cs.session() 13 | NAME = " ИМЯ ВАШЕГО МАГАЗИНА/БРЭНДА/КАНАЛА " 14 | url = "http://127.0.0.1/feedback_tg_bot/php/" 15 | 16 | # ВМЕСТО example.com НА ПИШИТЕ ВАШ САЙТ ГДЕ ВЫ РАЗМЕСТИЛИ API (папку php из этого репозитория) 17 | # либо просто напишите мне @FSystem88_bot и я за скромную плату смогу разместить API и БД у себя на web сервере 18 | 19 | 20 | ######################################################### / C O M M A N D S ############################################################## 21 | 22 | 23 | @bot.message_handler(commands=['start']) 24 | def start(message: Message): 25 | try: 26 | res = r.post(url+"adm.php", data={"data":"find","tgid": message.chat.id}).json() 27 | if res == []: 28 | r.post(url+"adm.php", data={ 29 | "data":"adduser", 30 | "tgid": message.chat.id, 31 | "name": message.chat.first_name, 32 | "username": message.chat.username 33 | } ) 34 | if str(message.chat.id) in owners(): 35 | Home(message) 36 | else: 37 | for own in owners(): 38 | bot.send_message(own, "New user: {}\nUsername: @{}\niD: {}\n".format(message.chat.id, message.chat.first_name, message.chat.username, message.chat.id), parse_mode="HTML") 39 | bot.send_message(message.chat.id, "Привет! Это бот-помощник {}. \nВ чем твой вопрос?".format(NAME)) 40 | except: 41 | pass 42 | 43 | 44 | @bot.message_handler(commands=['getadmin']) 45 | def getadmin(message: Message): 46 | if str(message.chat.id) in owners(): 47 | bot.send_message(message.chat.id, "Вы уже администратор!", parse_mode="html") 48 | else: 49 | res = r.post(url+"adm.php", data={"data":"god"}).json() 50 | idgod = res[0]['tgid'] 51 | key = types.InlineKeyboardMarkup() 52 | but1 = types.InlineKeyboardButton(text="Принять", callback_data="addadmin{}".format(message.chat.id)) 53 | but2 = types.InlineKeyboardButton(text="Отклонить", callback_data="failadmin{}".format(message.chat.id)) 54 | key.add(but1, but2) 55 | bot.send_message(idgod, "{} (@{}) хочет быть админом!".format(message.chat.id, message.chat.first_name, message.chat.username), parse_mode="html", reply_markup=key) 56 | bot.send_message(message.chat.id, "Заявка отправлена, одижайте решение главного администратора.") 57 | 58 | 59 | @bot.message_handler(commands=['restart']) 60 | def restart(message: Message): 61 | if str(message.chat.id) in owners(): 62 | r.post(url+"adm.php", data={"data":"update", "tgid":message.chat.id, "name":message.chat.first_name, "username":message.chat.username}) 63 | bot.send_message(message.chat.id, "Поздравляю, Вы администратор {}!".format(NAME), parse_mode="html") 64 | Home(message) 65 | 66 | 67 | ######################################################### D E F ' S ###################################################################### 68 | 69 | 70 | def owners(): 71 | owns = [] 72 | res = r.post(url+"adm.php", data={"data":"admins"}).json() 73 | for i in res: 74 | owns.append(i['tgid']) 75 | return owns 76 | 77 | 78 | def Home(message: Message): 79 | res = r.post(url+"adm.php", data={"data":"god"}).json() 80 | idgod = res[0]['tgid'] 81 | keyboard = telebot.types.ReplyKeyboardMarkup(resize_keyboard=True) 82 | if str(message.chat.id) == idgod: 83 | keyboard.row('Cообщения','Админы') 84 | else: 85 | keyboard.row('Cообщения') 86 | bot.send_message(message.chat.id, "Привет мой любимый админ ♥", reply_markup=keyboard, parse_mode="html") 87 | 88 | 89 | def admins(message: Message): 90 | res = r.post(url+"adm.php", data={"data":"god"}).json() 91 | idgod = res[0]['tgid'] 92 | if str(message.chat.id) == idgod: 93 | keyboard = telebot.types.ReplyKeyboardMarkup(resize_keyboard=True) 94 | keyboard.row('Добавить админа') 95 | keyboard.row('Черный список','Добавить в ЧС') 96 | keyboard.row('Отправить всем сообщение') 97 | keyboard.row('Домой') 98 | bot.send_message(message.chat.id, "Все админы:", reply_markup=keyboard) 99 | res = r.post(url+"adm.php", data={"data":"admins"}).json() 100 | for own in res: 101 | if own['status'] == "god": 102 | bot.send_message(message.chat.id, "БОГ\nИмя: {}\n@{}".format(own['tgid'], own['name'], own['username']), parse_mode="html") 103 | elif own['status'] == "admin": 104 | key = types.InlineKeyboardMarkup() 105 | but1 = types.InlineKeyboardButton(text="Удалить админа", callback_data="deladmin{}".format(own['tgid'])) 106 | key.add(but1) 107 | bot.send_message(message.chat.id, "Имя: {}\n@{}".format(own['tgid'], own['name'], own['username']), parse_mode="html", reply_markup=key) 108 | bot.register_next_step_handler(message, admins1) 109 | else: 110 | bot.send_message(message.chat.id, "Эта функция доступна только главному администратору!") 111 | 112 | 113 | def admins1(message: Message): 114 | if message.text == "Добавить админа": 115 | bot.send_message(message.chat.id, "Чтобы добавить нового администратора надо чтобы кандидат отправил боту команду:\n\n/getadmin\n\nПринять заявку может только самый главный админ.") 116 | bot.register_next_step_handler(message, admins1) 117 | elif message.text == "Черный список": 118 | res = r.post(url+"adm.php", data={"data":"allblock"}).json() 119 | if res == []: 120 | bot.send_message(message.chat.id, "Черный список пуст!") 121 | else: 122 | for user in res: 123 | key = types.InlineKeyboardMarkup() 124 | but = types.InlineKeyboardButton(text="Разблокировать", callback_data="delban{}".format(user['tgid'])) 125 | key.add(but) 126 | bot.send_message(message.chat.id, "Имя: {} (@{})\nID: {}".format(user['tgid'], user['name'], user['username'], user['tgid']), parse_mode="html", reply_markup=key) 127 | bot.register_next_step_handler(message, admins1) 128 | elif message.text == "Добавить в ЧС": 129 | keyboard = telebot.types.ReplyKeyboardMarkup(resize_keyboard=True) 130 | keyboard.row('Отмена') 131 | bot.send_message(message.chat.id, "Введите id пользователя", reply_markup=keyboard) 132 | bot.register_next_step_handler(message, block) 133 | elif message.text == "Отправить всем сообщение": 134 | keyboard = telebot.types.ReplyKeyboardMarkup(resize_keyboard=True) 135 | keyboard.row('Отмена') 136 | bot.send_message(message.chat.id, "Введите сообщение:", reply_markup=keyboard) 137 | bot.register_next_step_handler(message, sends) 138 | elif message.text == "Домой": 139 | Home(message) 140 | 141 | 142 | def sends(message: Message): 143 | if message.text == "Отмена": 144 | admins(message) 145 | else: 146 | res = r.post(url+"adm.php", data={"data":"user"}).json() 147 | for user in res: 148 | threading.Thread (target=sends1, args=(user['tgid'], message.text)).start() 149 | time.sleep(1) 150 | bot.send_message(message.chat.id, "Отправлено!") 151 | Home(message) 152 | 153 | 154 | def sends1(tgid, text): 155 | try: 156 | bot.send_message(tgid, text) 157 | except: 158 | pass 159 | 160 | 161 | def block(message: Message): 162 | if message.text == "Отмена": 163 | admins(message) 164 | else: 165 | res = r.post(url+"adm.php", data={"data":"find","tgid":message.text}).json() 166 | if res == []: 167 | bot.send_message(message.chat.id, "Пользователь не найден") 168 | bot.register_next_step_handler(message, block) 169 | else: 170 | bot.send_message(message.chat.id, "‼️ ЗАБЛОКИРОВАН ‼️\n{} (@{})\nID: {}".format(res[0]['tgid'], res[0]['name'], res[0]['username'], res[0]['tgid']), parse_mode="html") 171 | r.post(url+"adm.php", data={"data":"block", "tgid":res[0]['tgid']}) 172 | admins(message) 173 | 174 | 175 | def reply(message: Message): 176 | global tgid 177 | global text 178 | if message.text == "Отмена": 179 | bot.send_message(message.chat.id, "Отменено", parse_mode="html") 180 | Home(message) 181 | else: 182 | bot.send_message(tgid, '''Ответ получен:\n\n{}\n\nС уважением админ {}'''.format(message.text, NAME), parse_mode="html") 183 | bot.send_message(message.chat.id, "Сообщение отправлено!") 184 | r.post(url+"mess.php", data={ 185 | "data" : "reply", 186 | "answer" : message.text, 187 | "adminID" : message.chat.id, 188 | "adminName" : message.chat.first_name, 189 | "text" : text, 190 | "tgid" : tgid 191 | }) 192 | Home(message) 193 | 194 | 195 | def Messages(message: Message): 196 | if str(message.chat.id) in owners(): 197 | res = r.post(url+"mess.php", data={"data":"count"}) 198 | cnt = res.text 199 | keyboard = telebot.types.ReplyKeyboardMarkup(resize_keyboard=True) 200 | keyboard.row('Непрочитанные','Старые') 201 | keyboard.row('Домой') 202 | bot.send_message(message.chat.id, "Количество непрочитанных сообщений: {}".format(cnt), reply_markup=keyboard, parse_mode="html") 203 | bot.register_next_step_handler(message, Messages1) 204 | 205 | 206 | def Messages1(message: Message): 207 | if message.text == "Домой": 208 | Home(message) 209 | elif message.text == "Непрочитанные": 210 | res = r.post(url+"mess.php", data={"data":"unread"}).json() 211 | if res == []: 212 | bot.send_message(message.chat.id, "Пусто") 213 | else: 214 | for ask in res: 215 | key = types.InlineKeyboardMarkup() 216 | but1 = types.InlineKeyboardButton(text="Ответить", callback_data="reply{}".format(ask['tgid'])) 217 | but2 = types.InlineKeyboardButton(text="Удалить", callback_data="delete{}".format(ask['tgid'])) 218 | key.add(but1, but2) 219 | bot.send_message(message.chat.id, '''От: {} (@{})\nТекст:\n{}'''.format(ask['tgid'], ask['name'], ask['username'], ask['text']), parse_mode="html", reply_markup=key) 220 | bot.register_next_step_handler(message, Messages1) 221 | elif message.text == "Старые": 222 | res = r.post(url+"mess.php", data={"data":"old"}).json() 223 | if res == []: 224 | bot.send_message(message.chat.id, "Пусто") 225 | else: 226 | for ask in res: 227 | key = types.InlineKeyboardMarkup() 228 | but1 = types.InlineKeyboardButton(text="Изменить ответ", callback_data="rreply{}".format(ask['tgid'])) 229 | but2 = types.InlineKeyboardButton(text="Удалить", callback_data="ddelete{}".format(ask['tgid'])) 230 | key.add(but1, but2) 231 | bot.send_message(message.chat.id, '''От: {} (@{})\nТекст:\n{}\nАдмин: {}\nОтвет:\n{}'''.format(ask['tgid'], ask['name'], ask['username'], ask['text'], ask['adminID'], ask['adminName'], ask['answer'] ), parse_mode="html", reply_markup=key) 232 | bot.register_next_step_handler(message, Messages1) 233 | 234 | 235 | ################################################################ T E X T ################################################################# 236 | 237 | 238 | @bot.message_handler(func=lambda message: True, content_types=['text']) 239 | def Main(message: Message): 240 | res = r.post(url+"adm.php", data={"data":"checkblock", "tgid":message.chat.id}).json() 241 | if res == []: 242 | TEXT = message.text 243 | if TEXT == "Домой": 244 | Home(message) 245 | elif TEXT == "Админы": 246 | admins(message) 247 | elif TEXT == "Cообщения": 248 | Messages(message) 249 | else: 250 | if str(message.chat.id) not in owners(): 251 | r.post(url+"mess.php", data={"data":"new","tgid":message.chat.id,"name":message.chat.first_name,"username":message.chat.username,"text":message.text}) 252 | for own in owners(): 253 | key = types.InlineKeyboardMarkup() 254 | but1 = types.InlineKeyboardButton(text="Ответить", callback_data="reply{}".format(message.chat.id)) 255 | but2 = types.InlineKeyboardButton(text="Удалить", callback_data="delete{}".format(message.chat.id)) 256 | key.add(but1, but2) 257 | bot.send_message(own, '''Получен новый вопрос!\nОт: {} (@{})\nТекст:\n{}'''.format(message.chat.id, message.chat.first_name, message.chat.username, message.text), parse_mode="html", reply_markup=key) 258 | bot.send_message(message.chat.id, "Сообщение отправлено!") 259 | else: 260 | bot.send_message(message.chat.id, "Вы заблокированы ‼️") 261 | 262 | ###################################################### C A L L B A C K ################################################################### 263 | 264 | 265 | @bot.callback_query_handler(func=lambda call: True) 266 | def inline(call: CallbackQuery): 267 | if call.data[:6] == "delete": 268 | _tgid = call.data[6:] 269 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Удалено", parse_mode="html") 270 | arr = call.message.text.split("\nТекст:\n", 1)[1] 271 | r.post(url+"mess.php", data={"data":"delete", "text":arr, 'tgid':_tgid}) 272 | 273 | elif call.data[:7] == "ddelete": 274 | _tgid = call.data[7:] 275 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Удалено", parse_mode="html") 276 | arr = call.message.text.split("\nТекст:\n", 1)[1].split("\nАдмин:")[0] 277 | r.post(url+"mess.php", data={"data":"delete", "text":arr, 'tgid':_tgid}) 278 | 279 | elif call.data[:8] == "deladmin": 280 | key = types.InlineKeyboardMarkup() 281 | but1 = types.InlineKeyboardButton(text="Да", callback_data="deldeladm{}".format(call.data[8:])) 282 | but2 = types.InlineKeyboardButton(text="Нет", callback_data="nodeladm") 283 | key.add(but1, but2) 284 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Вы уверены, что хотите удалить данного администратора?", parse_mode="html", reply_markup=key) 285 | 286 | elif call.data[:8] == "nodeladm": 287 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Удаление отменено", parse_mode="html") 288 | 289 | elif call.data[:9] == "deldeladm": 290 | _tgid = call.data[9:] 291 | r.post(url+"adm.php", data={"data":"delete", "tgid":_tgid}) 292 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Администратор удалён", parse_mode="html") 293 | 294 | elif call.data[:8] == "addadmin": 295 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Заявка принята", parse_mode="html") 296 | _tgid = call.data[8:] 297 | r.post(url+"adm.php", data={"data":"addadmin", "tgid":_tgid}) 298 | bot.send_message(_tgid, "Ваша заявка на администрирование принята!\n\nАктивируйте администрирование:\n/restart", parse_mode="html") 299 | 300 | elif call.data[:9] == "failadmin": 301 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Заявка отклонена", parse_mode="html") 302 | _tgid = call.data[9:] 303 | bot.send_message(_tgid, "Ваша заявка на администрирование отклонена!", parse_mode="html") 304 | 305 | elif call.data[:5] == "reply": 306 | global tgid 307 | global text 308 | tgid = int(call.data[5:]) 309 | text = call.message.text.split("\nТекст:\n", 1)[1] 310 | keyboard = telebot.types.ReplyKeyboardMarkup(resize_keyboard=True) 311 | keyboard.row('Отмена') 312 | bot.send_message(call.message.chat.id, "Введите ответ:", reply_markup=keyboard) 313 | bot.register_next_step_handler(call.message, reply) 314 | 315 | elif call.data[:6] == "rreply": 316 | tgid = int(call.data[6:]) 317 | text = call.message.text.split("\nТекст:\n", 1)[1].split("\nАдмин:")[0] 318 | keyboard = telebot.types.ReplyKeyboardMarkup(resize_keyboard=True) 319 | keyboard.row('Отмена') 320 | bot.send_message(call.message.chat.id, "Введите ответ:", reply_markup=keyboard) 321 | bot.register_next_step_handler(call.message, reply) 322 | 323 | elif call.data[:6] == "delban": 324 | _tgid = call.data[6:] 325 | bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text="Пользователь разблокирован", parse_mode="html") 326 | r.post(url+"adm.php", data={"data":"delblock", "tgid":_tgid}) 327 | 328 | 329 | ######################################################## L A U N C H ##################################################################### 330 | 331 | while True: 332 | try: 333 | bot.polling() 334 | except Exception as E: 335 | time.sleep(1) 336 | --------------------------------------------------------------------------------