├── 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 |
--------------------------------------------------------------------------------