├── config.json ├── usermon.py ├── payments.py ├── paysignal.sql └── psbot.py /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "DBSERVER": "localhost", 3 | "DBUSER": "phpmyadmin", 4 | "DBPASSWD": "", 5 | "DATABASE": "paysignal", 6 | "ADMINS": ["nadgob8"] 7 | } 8 | -------------------------------------------------------------------------------- /usermon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | import os 4 | import sys 5 | import pymysql.cursors 6 | import time 7 | import logging 8 | import json 9 | import requests 10 | 11 | 12 | logging.basicConfig(level=logging.INFO) 13 | logger = logging.getLogger(__name__) 14 | 15 | period = 60 * 60 16 | 17 | 18 | class Db(object): 19 | def __init__(self, dbserver, dbuser, dbpasswd, database): 20 | self.dbserver = dbserver 21 | self.dbuser = dbuser 22 | self.dbpasswd = dbpasswd 23 | self.database = database 24 | 25 | # чтение одной записи БД 26 | def query_one(self, sql): 27 | connection = pymysql.connect(host=self.dbserver, user=self.dbuser, 28 | password=self.dbpasswd, db=self.database, autocommit=True, 29 | charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor) 30 | try: 31 | with connection.cursor() as cursor: 32 | cursor.execute(sql) 33 | if "insert" in sql.lower(): 34 | reply = cursor.lastrowid 35 | else: 36 | reply = cursor.fetchone() 37 | finally: 38 | connection.close() 39 | return reply 40 | 41 | # чтение нескольких записей БД 42 | def query_all(self, sql): 43 | connection = pymysql.connect(host=self.dbserver, user=self.dbuser, 44 | password=self.dbpasswd, db=self.database, autocommit=True, 45 | charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor) 46 | try: 47 | with connection.cursor() as cursor: 48 | cursor.execute(sql) 49 | reply = cursor.fetchall() 50 | finally: 51 | connection.close() 52 | return reply 53 | 54 | 55 | with open('config.json', encoding='utf-8') as json_file: 56 | data = json.load(json_file) 57 | 58 | db = Db(data['DBSERVER'], data['DBUSER'], data['DBPASSWD'], data['DATABASE']) 59 | 60 | settings = db.query_one("SELECT token, amount, inactivity FROM settings WHERE id=1") 61 | 62 | msgs = dict() 63 | 64 | chats = dict() 65 | 66 | sql = "SELECT chat_id, lang FROM channels WHERE status=1" 67 | for x in db.query_all(sql): 68 | chats[x['lang']] = x['chat_id'] 69 | 70 | while True: 71 | now = int(time.time()) 72 | 73 | users = db.query_all("SELECT user_id, balance, lang FROM users WHERE status=1 AND %s - last_active > %s" % (now, settings['inactivity'])) 74 | 75 | logger.info("%s inactive users found" % (len(users))) 76 | 77 | for u in users: 78 | if u['balance'] >= settings['amount']: 79 | sql = "UPDATE users SET balance=balance-%s WHERE user_id=%s" % (settings['amount'], u['user_id']) 80 | db.query_one(sql) 81 | logger.info("User %s balance reduced" % (u['user_id'])) 82 | if u['balance'] - settings['amount'] < settings['amount']: 83 | if u['lang'] not in msgs.keys(): 84 | msgs[u['lang']] = db.query_one("SELECT msg FROM %s WHERE id=15" % (u['lang']))['msg'] 85 | url = "https://api.telegram.org/bot%s/sendMessage?chat_id=%s&text=%s" % (settings['token'], 86 | u['user_id'], 87 | msgs[u['lang']] % (settings['amount'])) 88 | r = requests.get(url) 89 | 90 | else: 91 | url = "https://api.telegram.org/bot%s/kickChatMember?revoke_messages=false&chat_id=%s&user_id=%s" % (settings['token'], 92 | chats[u['lang']], 93 | u['user_id']) 94 | r = requests.get(url) 95 | sql = "UPDATE users SET status=0 WHERE user_id=%s" % (u['user_id']) 96 | db.query_one(sql) 97 | logger.info("User %s kicked from chat" % (u['user_id'])) 98 | 99 | logger.info("Sleeping %s minutes" % (int(period/60))) 100 | time.sleep(period) -------------------------------------------------------------------------------- /payments.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | import os 4 | import sys 5 | import pymysql.cursors 6 | import time 7 | import logging 8 | import json 9 | import requests 10 | 11 | 12 | logging.basicConfig(level=logging.INFO) 13 | logger = logging.getLogger(__name__) 14 | 15 | usdt = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t' 16 | 17 | period = 5 * 60 18 | 19 | 20 | class Db(object): 21 | def __init__(self, dbserver, dbuser, dbpasswd, database): 22 | self.dbserver = dbserver 23 | self.dbuser = dbuser 24 | self.dbpasswd = dbpasswd 25 | self.database = database 26 | 27 | # чтение одной записи БД 28 | def query_one(self, sql): 29 | connection = pymysql.connect(host=self.dbserver, user=self.dbuser, 30 | password=self.dbpasswd, db=self.database, autocommit=True, 31 | charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor) 32 | try: 33 | with connection.cursor() as cursor: 34 | cursor.execute(sql) 35 | if "insert" in sql.lower(): 36 | reply = cursor.lastrowid 37 | else: 38 | reply = cursor.fetchone() 39 | finally: 40 | connection.close() 41 | return reply 42 | 43 | # чтение нескольких записей БД 44 | def query_all(self, sql): 45 | connection = pymysql.connect(host=self.dbserver, user=self.dbuser, 46 | password=self.dbpasswd, db=self.database, autocommit=True, 47 | charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor) 48 | try: 49 | with connection.cursor() as cursor: 50 | cursor.execute(sql) 51 | reply = cursor.fetchall() 52 | finally: 53 | connection.close() 54 | return reply 55 | 56 | 57 | with open('config.json', encoding='utf-8') as json_file: 58 | data = json.load(json_file) 59 | 60 | db = Db(data['DBSERVER'], data['DBUSER'], data['DBPASSWD'], data['DATABASE']) 61 | 62 | chats = dict() 63 | 64 | sql = "SELECT chat_id, link, lang FROM channels" 65 | 66 | for x in db.query_all(sql): 67 | chats[x['lang']] = { 68 | 'link': "https://t.me/joinchat/%s" % (x['link']), 69 | 'id': int(x['chat_id']) 70 | } 71 | 72 | 73 | while True: 74 | 75 | settings = db.query_one("SELECT token, wallet, last_check FROM settings WHERE id=1") 76 | 77 | users=dict() 78 | 79 | sql = "SELECT wallet, user_id, lang, status, firstname, balance FROM users" 80 | for x in db.query_all(sql): 81 | users[x['wallet']] = { 82 | 'user_id': x['user_id'], 83 | 'lang': x['lang'], 84 | 'status': x['status'], 85 | 'firstname': x['firstname'], 86 | 'balance': x['balance'] 87 | } 88 | 89 | 90 | wallets = set(users.keys()) 91 | 92 | now = int(time.time()) 93 | logger.info("Checking payments at %s" % (now)) 94 | url = "https://api.trongrid.io/v1/accounts/%s/transactions/trc20?only_to=true&limit=200&min_timestamp=%s&&contract_address=%s" % (settings['wallet'], 95 | settings['last_check']*1000, usdt) 96 | 97 | response = requests.request("GET", url) 98 | result = response.json()['data'] 99 | if result: 100 | logger.info("%s transactions found" % (len(result))) 101 | 102 | for tx in result: 103 | if tx["block_timestamp"] == settings['last_check']*1000: 104 | break 105 | try: 106 | token = tx["token_info"]["address"] 107 | except: 108 | continue 109 | if tx["type"] == "Transfer" and int(tx['value'])>0 and tx['from'] in wallets: 110 | amount = int(tx['value'])/10**6 111 | user = users[tx['from']] 112 | logger.info("Found payment %s USDT from %s" % (amount, tx['from'])) 113 | if user['status'] == 1: 114 | sql = "UPDATE users SET balance=balance+%s WHERE user_id=%s" % (amount, 115 | user['user_id']) 116 | msg = db.query_one("SELECT msg FROM %s WHERE id=16" % (user['lang']))['msg'] % (user['firstname'], 117 | amount) 118 | else: 119 | sql = "UPDATE users SET status=1, balance=balance+%s WHERE user_id=%s" % (amount, 120 | user['user_id']) 121 | 122 | if user['balance'] + amount >= 20: 123 | msg = db.query_one("SELECT msg FROM %s WHERE id=7" % (user['lang']))['msg'] % (user['firstname'], 124 | chats[user['lang']]['link'] 125 | ) 126 | url = "https://api.telegram.org/bot%s/unbanChatMember?only_if_banned=true&chat_id=%s&user_id=%s" % (settings['token'], 127 | chats[user['lang']]['id'], 128 | user['user_id']) 129 | r = requests.get(url) 130 | else: 131 | msg = db.query_one("SELECT msg FROM %s WHERE id=16" % (user['lang']))['msg'] % (user['firstname'], 132 | amount) 133 | 134 | db.query_one(sql) 135 | url = "https://api.telegram.org/bot%s/sendMessage?chat_id=%s&text=%s" % (settings['token'], 136 | user['user_id'], 137 | msg 138 | ) 139 | r = requests.get(url) 140 | 141 | sql = "UPDATE settings SET last_check=%s WHERE id=1" % (now) 142 | db.query_one(sql) 143 | 144 | msgs = dict() 145 | 146 | sql = """SELECT payments.user_id, users.lang, users.firstname FROM payments 147 | INNER JOIN users 148 | ON payments.user_id = users.user_id 149 | WHERE payments.created_at<=%s""" % (now - period * 2) 150 | data = db.query_all(sql) 151 | for x in data: 152 | if x['lang'] not in msgs.keys(): 153 | msgs[x['lang']] = db.query_one("SELECT msg FROM %s WHERE id=8" % (x['lang']))['msg'] 154 | url = "https://api.telegram.org/bot%s/sendMessage?chat_id=%s&text=%s" % (settings['token'], 155 | x['user_id'], 156 | msgs[x['lang']] % (x['firstname'])) 157 | r = requests.get(url) 158 | 159 | sql = "DELETE FROM payments WHERE created_at<=%s" % (now-period*2) 160 | db.query_one(sql) 161 | logger.info("Sleeping 5 mins") 162 | time.sleep(period) 163 | -------------------------------------------------------------------------------- /paysignal.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 4.9.0.1 3 | -- https://www.phpmyadmin.net/ 4 | -- 5 | -- Хост: localhost 6 | -- Время создания: Апр 27 2021 г., 22:11 7 | -- Версия сервера: 10.3.23-MariaDB-0+deb10u1 8 | -- Версия PHP: 7.3.19-1~deb10u1 9 | 10 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 11 | SET AUTOCOMMIT = 0; 12 | START TRANSACTION; 13 | SET time_zone = "+00:00"; 14 | 15 | 16 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 17 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 18 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 19 | /*!40101 SET NAMES utf8mb4 */; 20 | 21 | -- 22 | -- База данных: `paysignal` 23 | -- 24 | 25 | -- -------------------------------------------------------- 26 | 27 | -- 28 | -- Структура таблицы `channels` 29 | -- 30 | 31 | CREATE TABLE `channels` ( 32 | `id` int(11) NOT NULL, 33 | `lang` varchar(2) NOT NULL, 34 | `chat_id` varchar(50) NOT NULL, 35 | `icon` varchar(3) NOT NULL, 36 | `link` varchar(250) NOT NULL, 37 | `title` varchar(50) NOT NULL, 38 | `status` tinyint(1) NOT NULL DEFAULT 1 39 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 40 | 41 | -- 42 | -- Дамп данных таблицы `channels` 43 | -- 44 | 45 | INSERT INTO `channels` (`id`, `lang`, `chat_id`, `icon`, `link`, `title`, `status`) VALUES 46 | (1, 'ru', '-554721829', '🇷🇺', 'xr6iJnTnUzU0ZWJi', 'Русский', 1), 47 | (2, 'en', '-565613856', '🇺🇸', 'kVlLg7iGDERiOTg6', 'English', 1); 48 | 49 | -- -------------------------------------------------------- 50 | 51 | -- 52 | -- Структура таблицы `en` 53 | -- 54 | 55 | CREATE TABLE `en` ( 56 | `id` int(11) NOT NULL, 57 | `msg` text NOT NULL 58 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 59 | 60 | -- 61 | -- Дамп данных таблицы `en` 62 | -- 63 | 64 | INSERT INTO `en` (`id`, `msg`) VALUES 65 | (1, 'Hi %s, I\'m an X-Finder-Question bot. My task is to help you use the service \"Crypto Question\". The conditions are very simple - you make a deposit to the balance of the service in the amount from $ 20 and I will invite you to a chat where you can ask questions about cryptocurrency you are interested in . As soon as the analyst answers your question (once a day), I will deduct $5 from your balance. If you do not ask a single question during the week, then in any case, $5 will be deducted from your balance. I wish you good luck in trading and hope that our service will help you to successfully invest and earn money.\r\n'), 66 | (2, 'Super, %s. Before you start, please read and agreed to our Terms of services: \r\n\r\n%s\r\n'), 67 | (3, 'To get access to the private chat, you need to register and make a deposit.\r\n'), 68 | (4, '%s, please enter the address of your TRON wallet. If you do not know what it is - watch the tutorial video at https://youtube.com\r\n'), 69 | (5, 'You\'re almost there! It remains only to make a deposit\r\n'), 70 | (6, 'Please send the desired amount in USDT to this TRON address. Within 20 minutes after the transfer, your balance will be topped up and you will receive an invitation to our private chat!\r\n'), 71 | (7, '%s, we have received your transfer! Here is your link to join the chat: \r\n\r\n%s'), 72 | (8, '%s, we don\'t see any USDT receipts from you ...\r\nPlease make a transfer or check your transaction'), 73 | (9, 'Your balance %s USDT \r\n'), 74 | (10, 'Invalid TRON wallet format. Please enter the correct address.'), 75 | (11, 'Information'), 76 | (12, 'Chat is activated'), 77 | (13, 'Chat is deactivated'), 78 | (14, 'You cannot ask new questions due to low balance. Please make a deposit to continue using the bot.'), 79 | (15, 'Your balance is less than %s USDT. You are welcome. top up your balance. to use the bot in the future.'), 80 | (16, '%s, we have received your %s USDT transfer'); 81 | 82 | -- -------------------------------------------------------- 83 | 84 | -- 85 | -- Структура таблицы `keyboards` 86 | -- 87 | 88 | CREATE TABLE `keyboards` ( 89 | `id` int(11) NOT NULL, 90 | `kbd_id` int(11) NOT NULL, 91 | `text` varchar(255) NOT NULL, 92 | `lang` varchar(2) NOT NULL DEFAULT 'ru' 93 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 94 | 95 | -- 96 | -- Дамп данных таблицы `keyboards` 97 | -- 98 | 99 | INSERT INTO `keyboards` (`id`, `kbd_id`, `text`, `lang`) VALUES 100 | (1, 1, 'Поехали', 'ru'), 101 | (2, 2, 'Прочитал и согласен', 'ru'), 102 | (3, 3, 'Далее', 'ru'), 103 | (4, 3, 'Вернуться назад\r\n', 'ru'), 104 | (5, 4, 'Пополнить баланс', 'ru'), 105 | (6, 5, 'БАЛАНС', 'ru'), 106 | (7, 5, 'ИНФО', 'ru'), 107 | (8, 6, 'Регламент сервиса', 'ru'), 108 | (9, 6, 'Техподдержка', 'ru'), 109 | (10, 1, 'Go', 'en'), 110 | (11, 2, 'I read and agree\r\n', 'en'), 111 | (12, 3, 'Proceed\r\n', 'en'), 112 | (13, 3, 'Back\r\n', 'en'), 113 | (14, 4, 'Deposit', 'en'), 114 | (15, 5, 'BALANCE', 'en'), 115 | (16, 5, 'INFO', 'en'), 116 | (17, 6, 'Terms of services\r\n', 'en'), 117 | (18, 6, 'Support\r\n', 'en'); 118 | 119 | -- -------------------------------------------------------- 120 | 121 | -- 122 | -- Структура таблицы `payments` 123 | -- 124 | 125 | CREATE TABLE `payments` ( 126 | `id` int(11) NOT NULL, 127 | `user_id` int(11) NOT NULL, 128 | `created_at` bigint(20) NOT NULL 129 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 130 | 131 | -- -------------------------------------------------------- 132 | 133 | -- 134 | -- Структура таблицы `ru` 135 | -- 136 | 137 | CREATE TABLE `ru` ( 138 | `id` int(11) NOT NULL, 139 | `msg` text NOT NULL 140 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 141 | 142 | -- 143 | -- Дамп данных таблицы `ru` 144 | -- 145 | 146 | INSERT INTO `ru` (`id`, `msg`) VALUES 147 | (1, 'Привет %s, я бот X-Finder-Question. Моя задача помогать вам пользоваться сервисом \"Вопрос аналитику\". Условия очень простые - вы вносите депозит на баланс сервиса в размере от 20$ и я приглашу вас в чат, где вы сможете задавать вопросы об интересующей вас криптовалюте. Как только аналитик ответит на ваш вопрос (1 раз в сутки) - я спишу с вашего баланса 5$. В случае если вы не зададите ни одного вопроса в течении недели, то с вашего баланса в любом случае спишется 5$. Желаю вам удачи в трейдинге и надеемся, что наш сервис поможет вам успешно инвестировать и зарабатывать.'), 148 | (2, 'Супер, %s\r\n\r\nПеред началом работы, пожалуйста ознакомьтесь с правилами нашего сервиса:\r\n\r\n%s'), 149 | (3, 'Для получения доступа в приватный чат\r\nнеобходимо зарегистрироваться и пополнить депозит'), 150 | (4, '%s, пожалуйста введите адрес вашего кошелька TRON. Если вы не знаете что это - посмотрите обучающее видео по ссылке: https://youtube.com'), 151 | (5, 'Вы почти у цели! Осталось только\r\nпополнить депозит'), 152 | (6, 'Пожалуйста отправьте желаемую сумму в USDT на этот адрес TRON. В течение 20 минут после перевода ваш баланс будет пополнен и вы получите приглашение в наш приватный чат!'), 153 | (7, '%s, ваш баланс пополнен!\r\nВот ваша ссылка для вступления в\r\nчат:\r\n\r\n%s'), 154 | (8, '%s, мы не видим\r\nпоступления USDT от вас...\r\nПожалуйста сделайте перевод или\r\nпроверьте вашу транзакцию'), 155 | (9, 'Ваш баланс: %s USDT'), 156 | (10, 'Неверный формат кошелька TRON. Введите правильный адрес.'), 157 | (11, 'Полезная информация'), 158 | (12, 'Чат активирован'), 159 | (13, 'Чат деактивирован'), 160 | (14, 'Вы не можете задавать новые вопросы из-за низкого баланса. Пополните баланс, чтобы пользоваться ботом.'), 161 | (15, 'Ваш баланс меньше %s USDT. Пожалуйста. пополните баланс. чтобы пользоваться ботом в дальнейшем.'), 162 | (16, '%s, Ваш баланс пополнен на %s USDT'); 163 | 164 | -- -------------------------------------------------------- 165 | 166 | -- 167 | -- Структура таблицы `settings` 168 | -- 169 | 170 | CREATE TABLE `settings` ( 171 | `id` int(11) NOT NULL, 172 | `wallet` varchar(100) NOT NULL, 173 | `last_check` bigint(20) NOT NULL DEFAULT 0, 174 | `support` varchar(100) NOT NULL, 175 | `token` varchar(200) NOT NULL, 176 | `amount` int(10) NOT NULL, 177 | `terms` varchar(250) NOT NULL, 178 | `inactivity` int(11) NOT NULL DEFAULT 14 179 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 180 | 181 | -- 182 | -- Дамп данных таблицы `settings` 183 | -- 184 | 185 | INSERT INTO `settings` (`id`, `wallet`, `last_check`, `support`, `token`, `amount`, `terms`, `inactivity`) VALUES 186 | (1, 'TW1difWVjE1uJHsemPfGCzViHnFdDEBjCv', 1619543223, 'gutmSupport', '1775419120:AAEXmwM-OFjYLF348dJC-e2jTG17sScTRY4', 5, 'https://google.com', 600); 187 | 188 | -- -------------------------------------------------------- 189 | 190 | -- 191 | -- Структура таблицы `users` 192 | -- 193 | 194 | CREATE TABLE `users` ( 195 | `user_id` int(11) NOT NULL, 196 | `wallet` varchar(100) NOT NULL, 197 | `balance` float(10,2) NOT NULL DEFAULT 0.00, 198 | `username` varchar(250) DEFAULT NULL, 199 | `lang` varchar(2) NOT NULL, 200 | `last_active` bigint(20) NOT NULL DEFAULT 0, 201 | `status` tinyint(1) NOT NULL DEFAULT 0, 202 | `firstname` varchar(250) NOT NULL 203 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 204 | 205 | -- 206 | -- Дамп данных таблицы `users` 207 | -- 208 | 209 | INSERT INTO `users` (`user_id`, `wallet`, `balance`, `username`, `lang`, `last_active`, `status`, `firstname`) VALUES 210 | (328068034, 'TWws9UPvd5tkYHLHbFstrv9jKyq2vvzCyx', 1.53, 'Inoutik', 'ru', 1619528864, 0, 'Alexander'), 211 | (599280310, 'TTV5VeVhUkvkfPhcK4QDKjksNEsdUUZgXZ', 0.10, 'gutmSupport', 'en', 1619533777, 0, 'Support'); 212 | 213 | -- 214 | -- Индексы сохранённых таблиц 215 | -- 216 | 217 | -- 218 | -- Индексы таблицы `channels` 219 | -- 220 | ALTER TABLE `channels` 221 | ADD PRIMARY KEY (`id`); 222 | 223 | -- 224 | -- Индексы таблицы `en` 225 | -- 226 | ALTER TABLE `en` 227 | ADD PRIMARY KEY (`id`); 228 | 229 | -- 230 | -- Индексы таблицы `keyboards` 231 | -- 232 | ALTER TABLE `keyboards` 233 | ADD PRIMARY KEY (`id`); 234 | 235 | -- 236 | -- Индексы таблицы `payments` 237 | -- 238 | ALTER TABLE `payments` 239 | ADD PRIMARY KEY (`id`); 240 | 241 | -- 242 | -- Индексы таблицы `ru` 243 | -- 244 | ALTER TABLE `ru` 245 | ADD PRIMARY KEY (`id`); 246 | 247 | -- 248 | -- Индексы таблицы `settings` 249 | -- 250 | ALTER TABLE `settings` 251 | ADD PRIMARY KEY (`id`); 252 | 253 | -- 254 | -- Индексы таблицы `users` 255 | -- 256 | ALTER TABLE `users` 257 | ADD PRIMARY KEY (`user_id`); 258 | 259 | -- 260 | -- AUTO_INCREMENT для сохранённых таблиц 261 | -- 262 | 263 | -- 264 | -- AUTO_INCREMENT для таблицы `channels` 265 | -- 266 | ALTER TABLE `channels` 267 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4; 268 | 269 | -- 270 | -- AUTO_INCREMENT для таблицы `en` 271 | -- 272 | ALTER TABLE `en` 273 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=20; 274 | 275 | -- 276 | -- AUTO_INCREMENT для таблицы `keyboards` 277 | -- 278 | ALTER TABLE `keyboards` 279 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=19; 280 | 281 | -- 282 | -- AUTO_INCREMENT для таблицы `payments` 283 | -- 284 | ALTER TABLE `payments` 285 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=16; 286 | 287 | -- 288 | -- AUTO_INCREMENT для таблицы `ru` 289 | -- 290 | ALTER TABLE `ru` 291 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=20; 292 | COMMIT; 293 | 294 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 295 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 296 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 297 | -------------------------------------------------------------------------------- /psbot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | import os 4 | from telegram import (InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardMarkup, 5 | ReplyKeyboardRemove,KeyboardButton, ParseMode, Bot, Chat, MessageEntity, Message, 6 | InputMediaPhoto, Update, InputMediaDocument, LabeledPrice) 7 | from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters, RegexHandler, 8 | ConversationHandler, CallbackQueryHandler, PicklePersistence, CallbackContext, PreCheckoutQueryHandler) 9 | from telegram.utils import helpers 10 | from telegram.error import (TelegramError, Unauthorized, BadRequest, TimedOut, ChatMigrated, NetworkError) 11 | from telegram.ext.dispatcher import run_async 12 | import telegram.bot 13 | from telegram.ext import messagequeue as mq 14 | from telegram.utils.request import Request 15 | import logging 16 | import random 17 | import pymysql.cursors 18 | import sys 19 | import json 20 | import base64 21 | import time 22 | import re 23 | from threading import Thread 24 | 25 | logging.basicConfig(level=logging.INFO) 26 | logger = logging.getLogger(__name__) 27 | 28 | 29 | # преобразование словаря настроек в класс с аттрибутами 30 | class Config(object): 31 | def __init__(self, initial_data): 32 | for key in initial_data: 33 | setattr(self, key, initial_data[key]) 34 | 35 | # Класс для работы с БД mysql 36 | class Db(object): 37 | def __init__(self, dbserver, dbuser, dbpasswd, database): 38 | self.dbserver = dbserver 39 | self.dbuser = dbuser 40 | self.dbpasswd = dbpasswd 41 | self.database = database 42 | 43 | # чтение одной записи БД 44 | def query_one(self, sql): 45 | connection = pymysql.connect(host=self.dbserver, user=self.dbuser, 46 | password=self.dbpasswd, db=self.database, autocommit=True, 47 | charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor) 48 | try: 49 | with connection.cursor() as cursor: 50 | cursor.execute(sql) 51 | if "insert" in sql.lower(): 52 | reply = cursor.lastrowid 53 | else: 54 | reply = cursor.fetchone() 55 | finally: 56 | connection.close() 57 | return reply 58 | 59 | # чтение нескольких записей БД 60 | def query_all(self, sql): 61 | connection = pymysql.connect(host=self.dbserver, user=self.dbuser, 62 | password=self.dbpasswd, db=self.database, autocommit=True, 63 | charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor) 64 | try: 65 | with connection.cursor() as cursor: 66 | cursor.execute(sql) 67 | reply = cursor.fetchall() 68 | finally: 69 | connection.close() 70 | return reply 71 | 72 | # проверка существования пользователя 73 | def user_exists(self, user_id): 74 | sql = f"SELECT user_id FROM users WHERE user_id={user_id}" 75 | data = self.query_one(sql) 76 | if data: 77 | return True 78 | else: 79 | return False 80 | 81 | # получение настроек бота 82 | def get_settings(self): 83 | sql = "SELECT * FROM settings WHERE id=1" 84 | data = self.query_one(sql) 85 | return data 86 | 87 | # получение настроек пользователя 88 | def get_user_data(self, user_id): 89 | sql = f"SELECT * FROM users WHERE user_id={user_id}" 90 | data = self.query_one(sql) 91 | return data 92 | 93 | 94 | def get_languages(self): 95 | sql = "SELECT lang, icon, title FROM channels ORDER BY id ASC" 96 | data = self.query_all(sql) 97 | return data 98 | 99 | 100 | # получение текстов на двух языках из БД 101 | def get_messages(self): 102 | result = dict() 103 | for lang in self.get_languages(): 104 | try: 105 | sql = "SELECT msg FROM %s ORDER BY id ASC" % (lang['lang']) 106 | data = self.query_all(sql) 107 | result[lang['lang']] = [x['msg'] for x in self.query_all(sql)] 108 | except: 109 | pass 110 | return result 111 | 112 | def get_chats(self): 113 | sql = "SELECT chat_id FROM channels ORDER BY id ASC" 114 | data = [int(x['chat_id']) for x in self.query_all(sql)] 115 | return data 116 | 117 | 118 | # получение клавитур на двух языках из БД 119 | def get_keyboards(self): 120 | sql = """SELECT kbd_id, text, lang FROM ( 121 | SELECT * FROM keyboards ORDER BY kbd_id ASC) AS nested 122 | ORDER BY id ASC""" 123 | data = self.query_all(sql) 124 | result = dict() 125 | for lang in self.get_languages(): 126 | result[lang['lang']] = list() 127 | new_data = [x for x in data if x['lang'] == lang['lang']] 128 | ids = list(set([x['kbd_id'] for x in new_data])) 129 | for item in ids: 130 | result[lang['lang']].append([x['text'] for x in new_data if x['kbd_id']==item]) 131 | for x in list(result.keys()): 132 | if not result[x]: 133 | del result[x] 134 | return result 135 | 136 | 137 | def cancel(update: Update, context: CallbackContext): 138 | update.message.reply_text('Bye! I hope we can talk again some day.', 139 | reply_markup=ReplyKeyboardRemove()) 140 | 141 | 142 | # выводится по команде /start или при смене языка в настройках 143 | def start(update: Update, context: CallbackContext): 144 | if update.message.chat.id != update.message.from_user.id: 145 | return 146 | user_id = update.message.from_user.id 147 | if db.user_exists(user_id): 148 | context.user_data[user_id] = db.get_user_data(user_id) 149 | reply_keyboard = [[ 150 | config.keyboards[context.user_data[user_id]['lang']][4][0], 151 | config.keyboards[context.user_data[user_id]['lang']][4][1] 152 | ]] 153 | reply_markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=False, resize_keyboard=True) 154 | msg = config.texts[context.user_data[user_id]['lang']][0] % (update.message.from_user.first_name) 155 | context.bot.send_message(chat_id=user_id, text=msg, 156 | reply_markup=reply_markup) 157 | return ConversationHandler.END 158 | else: 159 | context.user_data[user_id] = dict() 160 | keyboard = list() 161 | for x in db.get_languages(): 162 | if x['lang'] in config.texts.keys(): 163 | keyboard.append([InlineKeyboardButton("%s %s" % (x['icon'], x['title']), callback_data=x['lang'])]) 164 | reply_markup = InlineKeyboardMarkup(keyboard) 165 | context.bot.send_message(chat_id=user_id, text="Select a language:", reply_markup=reply_markup) 166 | return LANG 167 | 168 | 169 | # выбор языка при начальной регистрации или валюты при смене в настройках 170 | def set_lang(update: Update, context: CallbackContext): 171 | query = update.callback_query 172 | user_id = query.from_user.id 173 | context.user_data[user_id]['lang'] = query.data 174 | context.bot.delete_message(chat_id=query.message.chat_id, message_id=query.message.message_id) 175 | keyboard = [[InlineKeyboardButton(config.keyboards[context.user_data[user_id]['lang']][0][0], 176 | callback_data='start')]] 177 | 178 | reply_markup = InlineKeyboardMarkup(keyboard) 179 | msg = config.texts[context.user_data[user_id]['lang']][0] % (query.from_user.first_name) 180 | context.bot.send_message(chat_id=user_id, text=msg, 181 | reply_markup=reply_markup) 182 | return START 183 | 184 | 185 | def show_terms(update: Update, context: CallbackContext): 186 | query = update.callback_query 187 | user_id = query.from_user.id 188 | context.bot.delete_message(chat_id=query.message.chat_id, message_id=query.message.message_id) 189 | msg = config.texts[context.user_data[user_id]['lang']][1] % (query.from_user.first_name, config.terms) 190 | keyboard = [[InlineKeyboardButton(config.keyboards[context.user_data[user_id]['lang']][1][0], 191 | callback_data='accept')]] 192 | 193 | reply_markup = InlineKeyboardMarkup(keyboard) 194 | context.bot.send_message(chat_id=user_id, text=msg, reply_markup=reply_markup) 195 | return TERMS 196 | 197 | 198 | def accept_terms(update: Update, context: CallbackContext): 199 | query = update.callback_query 200 | user_id = query.from_user.id 201 | context.bot.delete_message(chat_id=query.message.chat_id, message_id=query.message.message_id) 202 | keyboard = [[InlineKeyboardButton(config.keyboards[context.user_data[user_id]['lang']][2][0], 203 | callback_data='continue'), 204 | InlineKeyboardButton(config.keyboards[context.user_data[user_id]['lang']][2][1], 205 | callback_data='terms'), 206 | ]] 207 | 208 | reply_markup = InlineKeyboardMarkup(keyboard) 209 | context.bot.send_message(chat_id=user_id, text=config.texts[context.user_data[user_id]['lang']][2], 210 | reply_markup=reply_markup) 211 | return CONTINUE 212 | 213 | 214 | def set_wallet(update: Update, context: CallbackContext): 215 | query = update.callback_query 216 | user_id = query.from_user.id 217 | context.bot.delete_message(chat_id=query.message.chat_id, message_id=query.message.message_id) 218 | msg = config.texts[context.user_data[user_id]['lang']][3] % (query.from_user.first_name) 219 | context.bot.send_message(chat_id=user_id, text=msg, disable_web_page_preview=True) 220 | return WALLET 221 | 222 | 223 | def register(update: Update, context: CallbackContext): 224 | if update.message.chat.id != update.message.from_user.id: 225 | return 226 | user_id = update.message.from_user.id 227 | pattern = re.compile('^T[a-zA-Z0-9]{33}$') 228 | if not re.match(pattern, update.message.text): 229 | context.bot.send_message(chat_id=user_id, text=config.texts[context.user_data[user_id]['lang']][9]) 230 | return WALLET 231 | 232 | sql = """INSERT INTO users (user_id, username, wallet, lang, firstname) 233 | VALUES (%s, '%s','%s','%s','%s')""" % (user_id, 234 | update.message.from_user.username, 235 | update.message.text, 236 | context.user_data[user_id]['lang'], 237 | update.message.from_user.first_name 238 | ) 239 | db.query_one(sql) 240 | keyboard = [[InlineKeyboardButton(config.keyboards[context.user_data[user_id]['lang']][3][0], 241 | callback_data='deposit')]] 242 | 243 | reply_markup = InlineKeyboardMarkup(keyboard) 244 | context.bot.send_message(chat_id=user_id, text=config.texts[context.user_data[user_id]['lang']][4], 245 | reply_markup=reply_markup) 246 | return ConversationHandler.END 247 | 248 | 249 | def deposit(update: Update, context: CallbackContext): 250 | query = update.callback_query 251 | user_id = query.from_user.id 252 | context.bot.delete_message(chat_id=query.message.chat_id, message_id=query.message.message_id) 253 | context.bot.send_message(chat_id=user_id, text=config.texts[context.user_data[user_id]['lang']][5]) 254 | 255 | reply_keyboard = [[ 256 | config.keyboards[context.user_data[user_id]['lang']][4][0], 257 | config.keyboards[context.user_data[user_id]['lang']][4][1] 258 | ]] 259 | reply_markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=False, resize_keyboard=True) 260 | context.bot.send_message(chat_id=user_id, text="%s" % (config.wallet) ,parse_mode=ParseMode.HTML, reply_markup=reply_markup) 261 | sql = "INSERT INTO payments (user_id, created_at) VALUES (%s, %s)" % (user_id, int(time.time())) 262 | db.query_one(sql) 263 | 264 | 265 | def balance(update: Update, context: CallbackContext): 266 | if update.message.chat.id != update.message.from_user.id: 267 | return 268 | user_id = update.message.from_user.id 269 | context.user_data[user_id] = db.get_user_data(user_id) 270 | msg = config.texts[context.user_data[user_id]['lang']][8] % (context.user_data[user_id]['balance']) 271 | keyboard = [[InlineKeyboardButton(config.keyboards[context.user_data[user_id]['lang']][3][0], 272 | callback_data='deposit')]] 273 | 274 | reply_markup = InlineKeyboardMarkup(keyboard) 275 | context.bot.send_message(chat_id=user_id, text=msg, reply_markup=reply_markup) 276 | 277 | 278 | def info(update: Update, context: CallbackContext): 279 | if update.message.chat.id != update.message.from_user.id: 280 | return 281 | user_id = update.message.from_user.id 282 | context.user_data[user_id] = db.get_user_data(user_id) 283 | keyboard = [[ 284 | InlineKeyboardButton(config.keyboards[context.user_data[user_id]['lang']][5][0], 285 | url=config.terms), 286 | InlineKeyboardButton(config.keyboards[context.user_data[user_id]['lang']][5][1], 287 | url='https://t.me/%s' % (config.support)), 288 | ]] 289 | 290 | reply_markup = InlineKeyboardMarkup(keyboard) 291 | context.bot.send_message(chat_id=user_id, text=config.texts[context.user_data[user_id]['lang']][10], reply_markup=reply_markup) 292 | 293 | 294 | def chat_mode(update: Update, context: CallbackContext): 295 | chat_id = update.message.chat.id 296 | user_id = update.message.from_user.id 297 | context.user_data[user_id] = db.get_user_data(user_id) 298 | if update.message.from_user.username not in config.ADMINS: 299 | return 300 | if chat_id not in config.chats: 301 | return 302 | 303 | if update.message.text == "/on": 304 | sql = "UPDATE channels SET status=1 WHERE chat_id='%s'" % (str(chat_id)) 305 | msg = config.texts[context.user_data[user_id]['lang']][11] 306 | elif update.message.text == "/off": 307 | sql = "UPDATE channels SET status=0 WHERE chat_id='%s'" % (str(chat_id)) 308 | msg = config.texts[context.user_data[user_id]['lang']][12] 309 | db.query_one(sql) 310 | context.bot.send_message(chat_id=user_id, text=msg) 311 | 312 | 313 | def user_post(update: Update, context: CallbackContext): 314 | chat_id = update.message.chat.id 315 | if chat_id not in config.chats: 316 | return 317 | if update.message.from_user.username in config.ADMINS: 318 | return 319 | user_id = update.message.from_user.id 320 | msg_id = update.message.message_id 321 | context.user_data[user_id] = db.get_user_data(user_id) 322 | if context.user_data[user_id]['balance'] < config.amount: 323 | context.bot.delete_message(chat_id=chat_id, message_id=msg_id) 324 | context.bot.send_message(chat_id=user_id, text=config.texts[context.user_data[user_id]['lang']][13]) 325 | else: 326 | now = int(time.time()) 327 | sql = "UPDATE users SET last_active = %s WHERE user_id=%s" % (now,user_id) 328 | db.query_one(sql) 329 | 330 | 331 | def admin_reply(update: Update, context: CallbackContext): 332 | chat_id = update.message.chat.id 333 | if chat_id not in config.chats: 334 | return 335 | if update.message.from_user.username not in config.ADMINS: 336 | context.bot.delete_message(chat_id=chat_id, message_id=update.message.message_id) 337 | return 338 | user_id = update.message.reply_to_message.from_user.id 339 | context.user_data[user_id] = db.get_user_data(user_id) 340 | if context.user_data[user_id]['balance'] < config.amount: 341 | context.bot.delete_message(chat_id=chat_id, message_id=update.message.message_id) 342 | return 343 | sql = "UPDATE users SET balance=balance-%s WHERE user_id=%s" % (config.amount, user_id) 344 | db.query_one(sql) 345 | if context.user_data[user_id]['balance'] - config.amount < config.amount: 346 | context.bot.send_message(chat_id=user_id, text=config.texts[context.user_data[user_id]['lang']][14] % (config.amount)) 347 | 348 | 349 | def added_member(update: Update, context: CallbackContext): 350 | now = int(time.time()) 351 | new_members = update.message.new_chat_members 352 | for member in new_members: 353 | user_id = member.id 354 | sql = "UPDATE users SET last_active = %s WHERE user_id = %s" % (now, user_id) 355 | db.query_one(sql) 356 | 357 | 358 | if __name__ == '__main__': 359 | 360 | LANG, START, TERMS, CONTINUE, WALLET = range(5) 361 | 362 | with open('config.json', encoding='utf-8') as json_file: 363 | data = json.load(json_file) 364 | 365 | db = Db(data['DBSERVER'], data['DBUSER'], data['DBPASSWD'], data['DATABASE']) 366 | bot_settings = db.get_settings() 367 | for k in bot_settings.keys(): 368 | data[k] = bot_settings[k] 369 | data['texts'] = db.get_messages() 370 | data['keyboards'] = db.get_keyboards() 371 | data['chats'] = db.get_chats() 372 | config = Config(data) 373 | 374 | 375 | 376 | lang_pattern = "^(" + '|'.join(list(config.texts.keys())) + ")$" 377 | 378 | updater = Updater(token=config.token, use_context=True) 379 | 380 | start_handler = ConversationHandler( 381 | entry_points=[CommandHandler('start', start)], 382 | 383 | states= { 384 | LANG: [CallbackQueryHandler(set_lang, pattern=lang_pattern)], 385 | START: [CallbackQueryHandler(show_terms, pattern="start")], 386 | TERMS: [CallbackQueryHandler(accept_terms, pattern="accept")], 387 | CONTINUE: [CallbackQueryHandler(show_terms, pattern="terms"), 388 | CallbackQueryHandler(set_wallet, pattern="continue")], 389 | WALLET: [MessageHandler(Filters.text, register)] 390 | }, 391 | 392 | fallbacks=[CommandHandler('cancel', cancel)], 393 | allow_reentry=True 394 | ) 395 | 396 | balance_pattern = "^(" + '|'.join([config.keyboards[x][4][0] for x in config.keyboards.keys()]) + ")$" 397 | info_pattern = "^(" + '|'.join([config.keyboards[x][4][1] for x in config.keyboards.keys()]) + ")$" 398 | 399 | updater.dispatcher.add_handler(start_handler) 400 | updater.dispatcher.add_handler(CallbackQueryHandler(deposit, pattern="deposit")) 401 | updater.dispatcher.add_handler(MessageHandler(Filters.regex(balance_pattern), balance)) 402 | updater.dispatcher.add_handler(MessageHandler(Filters.regex(info_pattern), info)) 403 | updater.dispatcher.add_handler(CommandHandler('on', chat_mode)) 404 | updater.dispatcher.add_handler(CommandHandler('off', chat_mode)) 405 | updater.dispatcher.add_handler(MessageHandler(Filters.reply, admin_reply)) 406 | updater.dispatcher.add_handler(MessageHandler(Filters.text, user_post)) 407 | updater.dispatcher.add_handler(MessageHandler(Filters.status_update.new_chat_members, added_member)) 408 | updater.start_polling() 409 | updater.idle() --------------------------------------------------------------------------------