Exemple #1
0
    def handle(self, **options):
        notify = options['notify'] == 'on'

        scheduler = BackgroundScheduler()

        client = Client('session_jobs',
                        api_id=TG_API_ID,
                        api_hash=TG_API_HASH,
                        bot_token=API_TOKEN,
                        no_updates=True)
        client.start()

        scheduler.add_job(update_user_balances,
                          'interval',
                          seconds=USER_BALANCE_JOB_INTERVAL,
                          args=(client, ))
        scheduler.add_job(update_chat_balances,
                          'interval',
                          seconds=CHAT_BALANCE_JOB_INTERVAL,
                          args=(client, notify))
        scheduler.add_job(make_multisend_list_and_pay,
                          'interval',
                          seconds=PAYMENT_JOB_INTERVAL)
        scheduler.add_job(local_chat_pay,
                          'interval',
                          seconds=LOCAL_PAYMENT_JOB_INTERVAL)

        scheduler.start()
        Client.idle()

        scheduler.shutdown()
        client.stop()
Exemple #2
0
def main():
    # Pyrogram setup
    client = Client("example")

    # Set the update_handler callback function
    client.set_update_handler(update_handler)
    client.start()

    # Blocks the program execution until you press CTRL+C then
    # automatically stops the Client by closing the underlying connection
    client.idle()
Exemple #3
0
from pyrogram import Client, Filters

app = Client("silencert")


@app.on_message(Filters.group)
def delete_unwanted_message(client, message):
    unwanted_messages = [
        message.new_chat_members,
        message.left_chat_member,
        message.new_chat_title,
    ]
    for unwanted in unwanted_messages:
        if unwanted is not None:
            client.delete_messages(message.chat.id, [message.message_id])

    if message.text is not None and message.text.find(
            "https://t.me/joinchat/") > -1:
        client.delete_messages(message.chat.id, [message.message_id])


app.start()
app.idle()
Exemple #4
0
            msg = self.bot.send_message(
                creator_id,
                text=
                f'Привет, твой бот @{bot_username} перестал работать и был скрыт от пользователей.'
            )

            markup = InlineKeyboardButton()

            markup.add(
                InlineKeyboardButton(
                    text='Починил!',
                    callback_data=
                    f'checkfix bot_id:{bot_id} msg_id:{msg.message_id}'))

            markup.add(
                InlineKeyboardButton(text='Закрить!', callback_data='hide'))

            self.bot.edit_message_reply_markup(chat_id=msg.chat.id,
                                               message_id=msg.message_id,
                                               reply_markup=markup)

        except Exception as e:
            print(f'[Checker] Error send msg not work to: {creator_id}')


cli.start()

Checker(bot, cli)
cli.idle()
def run(session_name):
    last_time = 0

    doned = []

    bonuses_id = 1317469445
    bot_id = 398938067

    class NewBonus:
        def __init__(self, peer, msg_id: int, data: bytes):
            self.peer = peer
            self.msg_id = msg_id
            self.data = data

    class NewCaptcha:
        def __init__(self, peer, msg_id: int, data: bytes):
            self.peer = peer
            self.msg_id = msg_id
            self.data = data

    class Work(Thread):
        def __init__(self):
            Thread.__init__(self)
            self.active = True

        def run(self):
            print('new work')
            while self.active:
                sleep(10)
                client.send_message(bot_id, '👁 Смотреть пост')

        def stop(self):
            self.active = False
            self.join()

    def captcha(update):
        if isinstance(update, Update):
            for m in update.updates:
                if isinstance(m, UpdateNewMessage):
                    msg = m.message
                    if msg.from_id == bot_id:
                        str_cap = re.match(
                            r'^Чтобы продолжить, найдите кнопку . и нажмите на нее!$',
                            msg.message)
                        if str_cap is not None:
                            row = msg.reply_markup.rows
                            for i in row:
                                for b in i.buttons:
                                    if b.data.decode() == 'anti-nakrut':
                                        ret = NewCaptcha(
                                            peer=client.resolve_peer(
                                                '@PayViewBot'),
                                            msg_id=msg.id,
                                            data=b.data)
                                        return ret
                        elif 'Уведомления о появлении новых постов' in msg.message:
                            return 'posts_end'
                elif isinstance(m, UpdateNewChannelMessage):
                    msg = m.message
                    if msg.to_id.channel_id == bonuses_id:
                        try:
                            if msg.reply_markup:
                                ret = NewBonus(
                                    peer=client.resolve_peer(
                                        msg.to_id.channel_id),
                                    msg_id=msg.id,
                                    data=msg.reply_markup.rows[0].buttons[1].
                                    data,
                                )
                                return ret
                        except AttributeError:
                            pass

    client = Client(session_name=session_name)

    work = Work()

    def replier(update):
        nonlocal work
        nonlocal last_time
        captcha_ret = captcha(update)
        if isinstance(captcha_ret, NewCaptcha):
            if captcha_ret.msg_id not in doned:
                sleep(3)
                client.send(
                    GetBotCallbackAnswer(peer=captcha_ret.peer,
                                         msg_id=captcha_ret.msg_id,
                                         data=captcha_ret.data))
                doned.append(captcha_ret.msg_id)
                return None
        elif captcha_ret == 'posts_end':
            if time() - last_time > 30:
                last_time = time()
                work.stop()
                sleep(300)
                work = Work()
                work.start()
        elif isinstance(captcha_ret, NewBonus):
            sleep(3)
            client.send(
                GetBotCallbackAnswer(
                    msg_id=captcha_ret.msg_id,
                    peer=captcha_ret.peer,
                    data=captcha_ret.data,
                ))

    work.start()
    client.set_update_handler(replier)
    client.start()
    client.idle()
Exemple #6
0
        while PUMP_BALANCE > API.get_coin_balance('BTC')['Available']:
            print('You can\'t invest more than {}'.format(
                API.get_coin_balance('BTC')['Available']))
            PUMP_BALANCE = float(
                input("How much BTC would you like to use?: "))

    if manual:
        print('\n***Wait input data***\n')
        while True:
            try:
                PUMP_COIN = input().rstrip(' \t\r\n\0').upper()
                if PUMP_COIN != '':
                    print(PUMP_COIN)
                    callback(PUMP_COIN)
                    break
            except Exception as e:
                print(e)
            time.sleep(0.01)
    else:
        # Инициализация клиента
        client = Client(
            session_name="pyro",
            phone_number=PHONE,
            phone_code=input("code: "),
        )

        client.set_update_handler(callback)
        client.start()
        print(client.get_me().user)
        client.idle()
Exemple #7
0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pyrogram import Client
from pyrogram.api import types


def update_handler(client, update, users, chats):
    if isinstance(update, types.UpdateNewMessage):
        message = update.message

        # Filter by Message to exclude MessageService and MessageEmpty
        if isinstance(message, types.Message):
            # Private Messages (Message from user)
            if isinstance(message.to_id, types.PeerUser):
                text = message.message
                user = users[message.from_id].first_name
                if user == 'IFTTT' and text.startswith('lego-sorter:'):
                    log.write(text)
                    log.write('\n')
                    log.flush()


with open('/home/pi/legogram/command.log', 'a') as log:
    c = Client("lego-sorter")
    c.set_update_handler(update_handler)
    c.start()
    c.idle()
Exemple #8
0
class custom_service_bot_class(object):

	SECTION = [
		'VERIFICATION',
		'OTHER'
	]
	INIT_STATUS = 0
	SELECT_SECTION = 1
	SEND_QUESTION = 2
	SEND_FINISH = 3
	RE_TICKET_ID = re.compile(r'[a-f\d]{32}')

	def __init__(self, config_file: str or ConfigParser, mysql_handle: tg_tools.mysqldb, send_link_callback: callable):

		if isinstance(config_file, ConfigParser):
			self.config = config_file
		else:
			self.config = ConfigParser()
			self.config.read(config_file)

		self.mysqldb = mysql_handle if mysql_handle else tg_tools.mysqldb('localhost', 'root', self.config['database']['passwd'], self.config['database']['db_name'])
		self.bot = Client(
			self.config['account']['custom_api_key'],
			api_id = self.config['account']['api_id'],
			api_hash = self.config['account']['api_hash']
		)

		self.bot_id = int(self.config['account']['custom_api_key'].split(':')[0])
		self.help_group = int(self.config['fuduji']['help_group'])
		self.send_link_callback = send_link_callback
		self.emerg_contact = eval(self.config['account']['emerg_contact']) if self.config.has_option('account', 'emerg_contact') and self.config['account']['emerg_contact'] != '' else self.config['account']['owner']
		self.create_lock = Lock()

	def start(self):
		self.bot.add_handler(MessageHandler(self.handle_start, Filters.command('start') & Filters.private))
		self.bot.add_handler(MessageHandler(self.handle_create, Filters.command('create',) & Filters.private))
		self.bot.add_handler(MessageHandler(self.handle_cancel, Filters.command('cancel') & Filters.private))
		self.bot.add_handler(MessageHandler(self.handle_list, Filters.command('list') & Filters.private))
		self.bot.add_handler(MessageHandler(self.handle_close, Filters.command('close') & Filters.private))
		self.bot.add_handler(MessageHandler(self.handle_reply, Filters.reply & Filters.text & Filters.private))
		self.bot.add_handler(MessageHandler(self.handle_msg, Filters.text & Filters.private))
		self.bot.add_handler(MessageHandler(self.call_superuser_function, Filters.chat(self.help_group) & Filters.reply & Filters.command('m')))
		self.bot.add_handler(MessageHandler(self.handle_group, Filters.reply & Filters.chat(self.help_group)))
		self.bot.add_handler(MessageHandler(self.handle_manual_add_blacklist, Filters.command('a') & Filters.chat(self.help_group)))
		self.bot.add_handler(MessageHandler(self.handle_other, Filters.private))
		self.bot.add_handler(CallbackQueryHandler(self.answer))
		return self.bot.start()

	def stop(self):
		#self.save_session()
		return self.bot.stop()

	def idle(self):
		return self.bot.idle()

	def active(self):
		self.start()
		self.idle()

	def send_emerg_msg(self, text: str):
		if isinstance(self.emerg_contact, str):
			self.bot.send_message(self.emerg_contact, text)
		else:
			for x in self.emerg_contact:
				self.bot.send_message(x, text)

	@staticmethod
	def hash_msg(msg: Message):
		return hashlib.md5(' '.join((str(msg.from_user.id), str(msg.date), str(msg.message_id))).encode()).hexdigest()

	def get_hash_from_reply_msg(self, msg: Message):
		if msg.reply_to_message is None or \
			msg.reply_to_message.text is None or \
			msg.reply_to_message.from_user.id != self.bot_id or \
			msg.reply_to_message.entities is None or \
			msg.reply_to_message.entities[0].type != 'hashtag':
			print(msg.reply_to_message is None, msg.reply_to_message.text is None, msg.reply_to_message.from_user.id != self.bot_id, msg.reply_to_message.entities is None, msg.reply_to_message.entities[0].type != 'hashtag')
			raise ValueError("hash message info error")
		r = self.RE_TICKET_ID.search(msg.reply_to_message.text)
		if r is not None:
			return r.group(0)
		else:
			raise ValueError('hash info not found')

	@staticmethod
	def generate_section_pad():
		return ReplyKeyboardMarkup( keyboard = [
			[KeyboardButton( text = x )] for x in custom_service_bot_class.SECTION
		], resize_keyboard = True, one_time_keyboard = True)

	@staticmethod
	def generate_ticket_keyboard(ticket_id: str, user_id: int, closed: bool = False, other: bool = False):
		kb = [
			InlineKeyboardButton(text = 'Close', callback_data = 'close {}'.format(ticket_id).encode()),
			InlineKeyboardButton(text = 'Send link', callback_data = 'send {}'.format(user_id).encode()),
			InlineKeyboardButton(text = 'Block', callback_data = 'block {}'.format(user_id).encode())
		]
		if closed: kb = kb[2:]
		elif other: kb.pop(1)
		return InlineKeyboardMarkup(
			inline_keyboard = [kb]
		)

	@staticmethod
	def returnYNemoji(i: int):
		return '✅' if i else '❌'

	def handle_list(self, client: Client, msg: Message):
		q = self.mysqldb.query3("SELECT `hash`, `status` FROM `tickets` WHERE `user_id` = {} ORDER BY `timestamp` DESC LIMIT 3".format(msg.chat.id))
		if len(q) == 0 or q is None:
			return msg.reply('You have never used this system before.', True)
		for _ticket in q:
			_ticket['status'] = self.returnYNemoji(_ticket['status'] != 'closed')
		msg.reply('Here are the last three tickets (up to 3)\n#{}'.format('\n#'.join(' '.join(value for _, value in _ticket.items()) for _ticket in q)), True)

	def handle_close(self, client: Client, msg: Message):
		if msg.reply_to_message is not None and msg.text == '/close':
			try:
				ticket_id = self.get_hash_from_reply_msg(msg)
			except ValueError:
				return msg.reply('TICKET NUMBER NOT FOUND\nPlease make sure that you have replied to the message which contains the ticket number.', True)
		else:
			if len(msg.text) < 8:
				return msg.reply('ERROR: COMMAND FORMAT Please use `/close <ticket number>` or **Reply to the message which contains the ticket number** to close the ticket', True, 'markdown', True)
			ticket_id = msg.text.split()[-1]
			if len(ticket_id) != 32:
				return msg.reply('ERROR: TICKET NUMBER FORMAT', True)
		q = self.mysqldb.query1("SELECT `user_id` FROM `tickets` WHERE `hash` = '{}' AND `status` != 'closed'".format(ticket_id))
		if q is None:
			return msg.reply('TICKET NUMBER NOT FOUND or TICKET CLOSED', True)
		if q['user_id'] != msg.chat.id:
			return msg.reply('403 Forbidden(You cannot close a ticket created by others. If this ticket is indeed created by yourself, please report the problem using the same ticket.)', True)
		self.mysqldb.execute("UPDATE `tickets` SET `status` = 'closed' WHERE `user_id` = {} AND `hash` = '{}'".format(msg.chat.id, ticket_id))
		self.mysqldb.execute("UPDATE `tickets_user` SET `last_time` = CURRENT_TIMESTAMP() WHERE `user_id` = {}".format(msg.chat.id))
		self.mysqldb.commit()
		client.send_message(self.help_group, "UPDATE\n[ #{} ]\nThis ticket is already closed by {}".format(ticket_id, tg_tools.build_html_parse.parse_user(msg.chat.id, '创建者')), reply_markup = self.generate_ticket_keyboard(ticket_id, msg.chat.id, True))
		msg.reply('DONE!', True)

	def add_user(self, user_id: int, step: int = 0):
		self.mysqldb.execute("INSERT INTO `tickets_user` (`user_id`, `create_time`, `last_time`, `last_msg_sent`, `step`) VALUES ({}, CURRENT_TIMESTAMP(), DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 5 minute), CURRENT_TIMESTAMP(), {})".format(user_id, step))

	def change_step(self, user_id: int, step: int, section: str = ''):
		if section == '':
			self.mysqldb.execute("UPDATE `tickets_user` SET `step` = {} WHERE `user_id` = {}".format(step, user_id))
		else:
			self.mysqldb.execute("UPDATE `tickets_user` SET `step` = {0}, `section` = '{2}' WHERE `user_id` = {1}".format(step, user_id, section))
		self.mysqldb.commit()

	def query_status(self, user_id: int):
		return self.mysqldb.query1("SELECT `step`, `section` FROM `tickets_user` WHERE `user_id` = {}".format(user_id))

	def query_user(self, user_id: int):
		return self.mysqldb.query1("SELECT `section` FROM `tickets_user` WHERE `user_id` = {}".format(user_id))

	def set_section(self, user_id: int, section: str):
		self.mysqldb.execute("UPDATE `tickets_user` SET `section` = '{1}' WHERE `user_id` = {0}".format(user_id, section))
		self.mysqldb.commit()

	def query_user_exam_status(self, user_id: int):
		return self.mysqldb.query1("SELECT `baned`, `bypass`, `passed`, `unlimited`, `retries` FROM `exam_user_session` WHERE `user_id` = {}".format(user_id))

	def handle_start(self, client: Client, msg: Message):
		q = self.mysqldb.query1("SELECT `last_msg_sent` FROM `tickets_user` WHERE `user_id` = {}".format(msg.chat.id))
		msg.reply('Welcome to Google Hosts Telegram Ticket System\n\nATTENTION:PLEASE DO NOT ABUSE THIS SYSTEM. Otherwise there is a possibility of getting blocked.\n\n/create - to create a new ticket\n/list - to list recent tickets\n/close - to close the ticket\n/cancel - to reset', True)
		if q is None:
			self.add_user(msg.chat.id)

	def handle_create(self, client: Client, msg: Message):
		if self.flood_check(client, msg):
			return
		q = self.mysqldb.query1("SELECT `hash` FROM `tickets` WHERE `user_id` = {} AND `status` = 'open' LIMIT 1".format(msg.chat.id))
		if q:
			msg.reply('UNABLE TO CREATE A NEW TICKET: An existing ticket is currently open.', True)
			return
		sqlObj = self.mysqldb.query1("SELECT `user_id` FROM `tickets_user` WHERE `user_id` = {}".format(msg.chat.id))
		(self.add_user if sqlObj is None else self.change_step)(msg.chat.id, custom_service_bot_class.SELECT_SECTION)
		msg.reply('You are creating a new ticket.\n\nPlease choose the correct department.', True, reply_markup=self.generate_section_pad())

	def handle_cancel(self, client: Client, msg: Message):
		self.change_step(msg.chat.id, custom_service_bot_class.INIT_STATUS)
		msg.reply('Reset Successful', reply_markup=ReplyKeyboardRemove())

	def handle_reply(self, client: Client, msg: Message):
		if self.flood_check(client, msg):
			return
		ticket_hash = self.get_hash_from_reply_msg(msg)
		sqlObj = self.mysqldb.query1("SELECT `status`, `section` FROM `tickets` WHERE `hash` = '{}' AND `user_id` = {}".format(ticket_hash, msg.chat.id))
		if sqlObj is None or sqlObj['status'] == 'closed':
			msg.reply('TICKET NUMBER NOT FOUND or TICKET CLOSED. REPLY FUNCTION NO LONGER AVAILABLE.', True)
			return
		self.mysqldb.execute("UPDATE `tickets_user` SET `last_time` = CURRENT_TIMESTAMP() WHERE `user_id` = {}".format(msg.chat.id))
		self.mysqldb.commit()
		client.send_message(
			self.help_group,
			'NEW REPLY\n[ #{} ]:\nMESSAGE: {}'.format(ticket_hash, build_html_parse(msg).parsed_msg),
			'html',
			reply_markup = self.generate_ticket_keyboard(ticket_hash, msg.chat.id, sqlObj['section'] != self.SECTION[0])
		)
		msg.reply('The new reply is added successfully!')

	def handle_msg(self, client: Client, msg: Message):
		sqlObj = self.query_status(msg.chat.id)
		if sqlObj is None or sqlObj['step'] not in (custom_service_bot_class.SELECT_SECTION, custom_service_bot_class.SEND_QUESTION):
			if self.flood_check(client, msg):
				return
			return msg.reply('Please use bot command to interact.')
		if sqlObj['step'] == custom_service_bot_class.SELECT_SECTION:
			if msg.text in self.SECTION:
				self.change_step(msg.chat.id, custom_service_bot_class.SEND_QUESTION, msg.text)
				msg.reply('Please describe your problem briefly(up to 500 characters)\n(Please use external links to send pictures.):\n\nATTENTION: Receiving a confirmation message in return indicates that the ticket is created successfully.\n\nUse /cancel to cancel creating the ticket. ', True, reply_markup = ReplyKeyboardRemove())
			else:
				msg.reply('Please use the menu below to choose the correct department.', True)
		elif sqlObj['step'] == custom_service_bot_class.SEND_QUESTION:
			if len(msg.text) > 500:
				msg.reply('The number of characters you have entered is larger than 500. Please re-enter.', True)
				return
			ticket_hash = self.hash_msg(msg)
			self.mysqldb.execute(ticket(msg, sqlObj['section'], 'open').sql)
			self.mysqldb.commit()
			self.change_step(msg.chat.id, custom_service_bot_class.INIT_STATUS)
			msg.reply(
				'The ticket is created successfully!\n[ #{ticket_id} ]\nDepartment: {section}\nMessage: \n{text}\n\nReply to this message to add a new reply to the ticket.'.format(
					ticket_id = ticket_hash,
					text = build_html_parse(msg).parsed_msg,
					section = sqlObj['section']
				),
				parse_mode = 'html'
			)
			msg_id = client.send_message(
				self.help_group,
				'NEW TICKET\n[ #{} ]\nClick {} to check the user profile\nDepartment: {}\nMessage: \n{}'.format(
					ticket_hash,
					build_html_parse.parse_user_ex(msg.chat.id, 'Here'),
					sqlObj['section'],
					build_html_parse(msg).parsed_msg
				),
				'html',
				reply_markup = self.generate_ticket_keyboard(
					ticket_hash,
					msg.chat.id,
					other = sqlObj['section'] != custom_service_bot_class.SECTION[0]
				)
			).message_id
			if sqlObj['section'] == custom_service_bot_class.SECTION[0]:
				client.send_message(
					self.help_group,
					self.generate_user_status(msg.chat.id),
					'markdown',
					reply_to_message_id = msg_id
				)
		else:
			print("throw! user_id: {}, sqlObj = {}".format(msg.chat.id, repr(sqlObj)))

	def generate_user_status(self, user_id: int):
		user_status = self.query_user_exam_status(user_id)
		return 'User {5} status:\nPassed exam: {0}\nBan status: {1}\nBypass: {2}\nUnlimited: {3}\nRetries: {4}'.format(
			self.returnYNemoji(user_status['passed']),
			self.returnYNemoji(user_status['baned']),
			self.returnYNemoji(user_status['bypass']),
			self.returnYNemoji(user_status['unlimited']),
			user_status['retries'],
			build_html_parse.parse_user(user_id)
		) if user_status is not None else '**WARNING: THIS USER HAS NEVER USED THE BOT BEFORE.**'

	def handle_other(self, client: Client, msg: Message):
		q = self.mysqldb.query1("SELECT `last_msg_sent` FROM `tickets_user` WHERE `user_id` = {}".format(msg.chat.id))
		if (datetime.now() - q['last_msg_sent']).total_seconds() < 120:
			return
		msg.reply('Please use bot command to interact. TEXT ONLY.')

	def handle_group(self, client: Client, msg: Message):
		#print(msg)
		if msg.reply_to_message.from_user.id != self.bot_id or (msg.text and msg.text.startswith('/')): return
		ticket_hash = self.get_hash_from_reply_msg(msg)
		sqlObj = self.mysqldb.query1("SELECT * FROM `tickets` WHERE `hash` = '{}'".format(ticket_hash))
		if sqlObj is None:
			return msg.reply('ERROR: TICKET NOT FOUND')
		if sqlObj['status'] == 'closed':
			return msg.reply('This ticket is already closed.')
		msg_reply = client.send_message(sqlObj['user_id'], 'NEW UPDATE!\n[ #{} ]\nMessage: \n{}\n\nReply to this message to add a new reply to the ticket.'.format(ticket_hash, build_html_parse(msg).parsed_msg), 'html')
		msg.reply('REPLY SUCCESSFUL', reply_markup = InlineKeyboardMarkup(inline_keyboard = [
			[
				InlineKeyboardButton( text = 'recall', callback_data = ' '.join(('del', str(msg_reply.chat.id), str(msg_reply.message_id))).encode())
			]
		]))
		sqlObj = self.mysqldb.query1("SELECT `last_time`, `user_id` FROM `tickets_user` WHERE user_id = {}".format(sqlObj['user_id']))
		if (datetime.now() - sqlObj['last_time']).total_seconds() < 120:
			self.mysqldb.execute("UPDATE `tickets_user` SET `last_time` = DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 3 minute) WHERE `user_id` = %s", (sqlObj['user_id'],))

	def handle_manual_add_blacklist(self, client: Client, msg: Message):
		pass

	@staticmethod
	def generate_confirm_keyboard(first: str, last: str):
		if isinstance(last, list) or isinstance(last, tuple):
			lastg = last
		else:
			lastg = (str(last),)
		return InlineKeyboardMarkup(inline_keyboard = [
			[
				InlineKeyboardButton(text = 'Yes', callback_data = ' '.join((first, 'confirm', *lastg)).encode()),
				InlineKeyboardButton(text = 'No', callback_data = b'cancel')
			]
		])

	def generate_superuser_text(self, user_id: str or int):
		return '\n\n'.join(('Please choose the section below.', self.generate_user_status(user_id), ' '.join(('Last refresh:', time.strftime('%Y-%m-%d %H:%M:%S')))))

	def generate_superuser_detail(self, user_id: str or int):
		return {
			'text': self.generate_superuser_text(user_id),
			'reply_markup': InlineKeyboardMarkup(
				inline_keyboard = [
					[
						InlineKeyboardButton( text = 'BYPASS', callback_data = 'bypass {}'.format(user_id).encode()),
						InlineKeyboardButton( text = 'UNLIMITED RETRIES', callback_data = 'unlimited {}'.format(user_id).encode()),
						InlineKeyboardButton( text = 'REFRESH', callback_data = 'refresh {}'.format(user_id).encode())
					],
					[
						InlineKeyboardButton( text = 'PASS', callback_data = 'setpass {}'.format(user_id).encode()),
						InlineKeyboardButton( text = 'RESET TIMES', callback_data = 'reset {}'.format(user_id).encode())
					],
					[
						InlineKeyboardButton( text = 'RESET USER STATUS', callback_data = 'renew {}'.format(user_id).encode())
					],
					[
						InlineKeyboardButton( text = 'Cancel', callback_data = b'cancel')
					]
				]
			)
		}

	def call_superuser_function(self, client: Client, msg: Message):
		sqlObj = self.mysqldb.query1("SELECT `user_id`, `section` FROM `tickets` WHERE `hash` = '{}'".format(self.get_hash_from_reply_msg(msg)))
		if sqlObj['section'] != self.SECTION[0]:
			return msg.reply('This ticket doesn\'t support admin menus for now.', True)
		user_id = sqlObj['user_id']
		client.send_message(
			self.help_group,
			parse_mode = 'markdown',
			reply_to_message_id = msg.reply_to_message.message_id,
			**self.generate_superuser_detail(user_id)
		)

	def confirm_dialog(self, msg: Message, additional_msg: str, callback_prefix: str, user_id: int = None, ticket_id: str = None):
		if user_id is not None:
			self.bot.send_message(
				self.help_group,
				'Do you really want to {} {}?'.format(additional_msg, build_html_parse.parse_user(user_id)),
				'markdown',
				reply_markup = self.generate_confirm_keyboard(callback_prefix, user_id)
			)
		else:
			self.bot.send_message(
				self.help_group,
				'Do you really want to {} #{}?'.format(additional_msg, ticket_id),
				reply_markup = self.generate_confirm_keyboard(callback_prefix, ticket_id)
			)

	def confirm(self, client: Client, msg: CallbackQuery):
		if time.time() - msg.message.date > 15:
			raise TimeoutError()
		if msg.data.startswith('close'):
			ticket_id = msg.data.split()[-1]
			q = self.mysqldb.query1("SELECT `user_id`, `status` FROM `tickets` WHERE `hash` = '{}'".format(ticket_id))
			if q is None:
				return msg.answer('TICKET NOT FOUND', True)
			if q['status'] == 'closed':
				return msg.answer('TICKET CLOSED')
			self.mysqldb.execute("UPDATE `tickets` SET `status` = 'closed' WHERE `hash` = '{}'".format(ticket_id))
			msg.answer('This ticket is closed.')
			client.send_message(
				self.help_group,
				"UPDATE\n[ #{} ]\nThis ticket is closed by {}.".format(
					ticket_id,
					tg_tools.build_html_parse.parse_user(
						msg.from_user.id,
						tg_tools.build_html_parse.user_name(msg.from_user).full_name
					)
				),
				'markdown',
				reply_markup = self.generate_ticket_keyboard(ticket_id, q['user_id'], True)
			)
			client.send_message(q['user_id'], "Your ticket [ #{} ] is closed".format(ticket_id))
		elif msg.data.startswith('block'):
			self.mysqldb.execute("UPDATE `tickets_user` SET `baned` = 1 WHERE `user_id` = {}".format(msg.data.split()[-1]))
			msg.answer('DONE!')
			self.bot.send_message(
				self.help_group,
				'blocked {}'.format(build_html_parse.parse_user(msg.data.split()[-1], msg.data.split()[-1])),
				parse_mode = 'markdown',
				reply_markup = InlineKeyboardMarkup( inline_keyboard = [
					[InlineKeyboardButton(text = 'UNBAN', callback_data = 'unban {}'.format(msg.data.split()[-1]).encode())]
				])
			)
		elif msg.data.startswith('send'):
			try:
				self.send_link_callback(int(msg.data.split()[-1]), True)
				msg.answer('The invitation link is sent successfully.')
			except:
				client.send_message(self.help_group, traceback.format_exc(), disable_web_page_preview = True)
				msg.answer('Failed to send the invitation link. Please check the console.\n{}'.format(traceback.format_exc().splitlines()[-1]), True)
		elif msg.data.startswith('reset'):
			self.mysqldb.execute('UPDATE `exam_user_session` SET `retries` = 0 WHERE `user_id` = {}'.format(msg.data.split()[-1]))
			msg.answer('Retry times has been reset')
		elif msg.data.startswith('del'):
			try:
				client.delete_messages(int(msg.data.split()[-2]), int(msg.data.split()[-1]))
				msg.answer('message has been deleted')
			except:
				client.send_message(self.help_group, traceback.format_exc(), disable_web_page_preview = True)
				msg.answer('Failed to delete the message. Please check the console.\n{}'.format(traceback.format_exc().splitlines()[-1]), True)
		elif msg.data.startswith('renew'):
			self.mysqldb.execute('DELETE FROM `exam_user_session` WHERE `user_id` = {}'.format(msg.data.split()[-1]))
			msg.answer('User Profile Deleted')
		elif msg.data.startswith('bypass'):
			self.mysqldb.execute('UPDATE `exam_user_session` SET `bypass` = 1 WHERE `user_id` = {}'.format(msg.data.split()[-1]))
			msg.answer('BYPASS SET SUCCESSFULLY')
		elif msg.data.startswith('setpass'):
			self.mysqldb.execute('UPDATE `exam_user_session` SET `passed` = 1 WHERE `user_id` = {}'.format(msg.data.split()[-1]))
			msg.answer('PASS SET SUCCESSFULLY')
		elif msg.data.startswith('unlimited'):
			self.mysqldb.execute('UPDATE `exam_user_session` SET `unlimited` = 1 WHERE `user_id` = {}'.format(msg.data.split()[-1]))
			msg.answer('UNLIMITED RETRIES SET SUCCESSFULLY')
		self.mysqldb.commit()
		client.delete_messages(msg.message.chat.id, msg.message.message_id)

	def send_confirm(self, client: Client, msg: CallbackQuery):
		if msg.data.startswith('close'):
			self.confirm_dialog(msg, 'close this ticket', 'close',ticket_id = msg.data.split()[-1])
		elif msg.data.startswith('block'):
			self.confirm_dialog(msg, 'block this user', 'block', user_id = int(msg.data.split()[-1]))
		elif msg.data.startswith('send'):
			self.confirm_dialog(msg, 'send the link to', 'send', user_id = int(msg.data.split()[-1]))
		elif msg.data.startswith('reset'):
			self.confirm_dialog(msg, 'reset retry times for', 'reset', user_id = int(msg.data.split()[-1]))
		elif msg.data.startswith('del'):
			msg.answer('Please press again to make sure. If you really want to delete this reply', True)
			self.bot.send_message(
				self.help_group,
				'Do you want to delete reply message to {}?'.format(build_html_parse.parse_user(msg.data.split()[-2])),
				'markdown',
				reply_markup = self.generate_confirm_keyboard('del', msg.data[4:])
			)
		elif msg.data.startswith('bypass'):
			self.confirm_dialog(msg, 'set bypass for', 'bypass', int(msg.data.split()[-1]))
		elif msg.data.startswith('renew'):
			self.confirm_dialog(msg, 'reset user status', 'renew', int(msg.data.split()[-1]))
		elif msg.data.startswith('setpass'):
			self.confirm_dialog(msg, 'set pass', 'setpass', int(msg.data.split()[-1]))
		elif msg.data.startswith('unlimited'):
			self.confirm_dialog(msg, 'set unlimited retries for', 'unlimited', int(msg.data.split()[-1]))
		msg.answer()

	def answer(self, client: Client, msg: CallbackQuery):
		msg.data = msg.data.decode(errors = 'ignore')
		if msg.data.startswith('cancel'):
			client.edit_message_reply_markup(msg.message.chat.id, msg.message.message_id)
			msg.answer('Canceled')
		elif msg.data.startswith('unban'):
			self.mysqldb.execute("UPDATE `tickets_user` SET `baned` = 0 WHERE `user_id` = {}".format(msg.data.split()[-1]))
			msg.answer('UNBANED')
			client.edit_message_reply_markup(msg.message.chat.id, msg.message.message_id)
		elif msg.data.startswith('refresh'):
			try:
				client.edit_message_text(
					msg.message.chat.id,
					msg.message.message_id,
					self.generate_superuser_text(msg.data.split()[-1]),
					'markdown',
					reply_markup = msg.message.reply_markup
				)
			except api.errors.exceptions.bad_request_400.MessageNotModified:
				pass
			msg.answer('refreshed')
		elif 'confirm' in msg.data:
			try:
				self.confirm(client, msg)
			except TimeoutError:
				msg.answer('Confirmation time out')
				client.edit_message_reply_markup(msg.message.chat.id, msg.message.message_id)
		elif any(msg.data.startswith(x) for x in ('close', 'block', 'send', 'bypass', 'reset', 'unlimited', 'del', 'renew', 'setpass')):
			self.send_confirm(client, msg)
		else:
			try:
				raise ValueError(msg.data)
			except:
				client.send_message(self.help_group, traceback.format_exc(), disable_web_page_preview = True)

	def flood_check(self, client: Client, msg: Message):
		sq = self.mysqldb.query1("SELECT `last_time`, `last_msg_sent`, `baned` FROM `tickets_user` WHERE `user_id` = {}".format(msg.chat.id))
		if sq and (datetime.now() - sq['last_time']).total_seconds() < 120:
			if msg.text:
				print('Caught flood {}: {}'.format(msg.chat.id, msg.text))
			self.mysqldb.execute("UPDATE `tickets_user` SET `last_msg_sent` = CURRENT_TIMESTAMP() WHERE `user_id` = {}".format(msg.chat.id))
			self.mysqldb.commit()
			if sq['baned']:
				return msg.reply('Due to privacy settings, you are temporarily unable to operate.') is not None
			msg.reply("You are driving too fast. Please try again later.")
			return True
		return False
Exemple #9
0
class bot_class:
    bot_self = None

    def __init__(self):
        logger.debug('Enter bot_class.__init__()')
        config = ConfigParser()
        config.read('data/config.ini')
        self.bot = Client(config.get('bot', 'bot_token').split(':')[0],
                          config.get('bot', 'api_id'),
                          config.get('bot', 'api_hash'),
                          bot_token=config.get('bot', 'bot_token'))
        self._bot_id = int(self.bot.session_name)
        self.conn = mysqldb(config.get('database', 'host'),
                            config.get('database', 'user'),
                            config.get('database', 'password'),
                            config.get('database', 'db'),
                            autocommit=True)
        self._bot_name = None
        self.loaddatetime = datetime.datetime.now().replace(microsecond=0)
        self.groups = group_cache(self.conn, self.bot)
        self.error_message = config.get('bot', 'error_message', fallback='')
        self.init_receiver()

    def run(self):
        self.bot.start()
        try:
            self.bot.idle()
        except InterruptedError:
            logger.debug('Catch!')

    def stop(self):
        self.bot.stop()
        self.conn.close()

    @property
    def bot_id(self) -> int:
        return self._bot_id

    @property
    def bot_name(self) -> str:
        if self._bot_name is None:
            self._bot_name = self.bot.get_me().username
            logger.debug('Fetched bot username => %s', self._bot_name)
        return self._bot_name

    def new_chat_member(self, client: Client, msg: Message):
        if self.bot_id in msg.new_chat_members:
            self.groups.insert_group(msg.chat.id)
            msg.reply('Please use /setwelcome to set welcome message')
            #msg.reply('This bot is refactoring code, feature may not available during this time')
        else:
            group_setting = self.groups[msg.chat.id]
            if group_setting is None:
                group_setting = self.groups.insert_group(msg.chat.id)
            welcome_text = group_setting.welcome_text
            if welcome_text is not None:
                try:
                    last_msg = msg.reply(
                        welcome_text.replace('$name',
                                             parse_user_name(msg.from_user)),
                        parse_mode='markdown',
                        disable_web_page_preview=True).message_id
                except pyrogram.errors.ChatWriteForbidden:
                    logger.error('Got ChatWriterForbidden in %d', msg.chat.id)
                    msg.chat.leave()
                    self.groups.delete_group(msg.chat.id)
                    return
                previous_msg = self.conn.query_last_message_id(msg.chat.id)
                self.conn.insert_last_message_id(msg.chat.id, last_msg)
                if self.groups[msg.chat.id].no_welcome:
                    if previous_msg is not None:
                        client.delete_messages(msg.chat.id, previous_msg)

    def left_chat_member(self, _client: Client, msg: Message):
        if self.bot_id in msg.left_chat_member:
            self.groups.delete_group(msg.chat.id)

    def privileges_control(self, client: Client, msg: Message):
        bot_name = re.match(
            r'^\/(setwelcome|clear|status|setflag)(@[a-zA-Z_]*bot)?\s?',
            msg.text).group(2)
        if bot_name is not None and bot_name[1:] != self.bot_name:
            return
        group_info = self.groups[msg.chat.id]
        if group_info.admins is None:
            admins = client.get_chat_members(msg.chat.id,
                                             filter='administrators')
            group_info.admins = [x.user.id for x in admins]
            self.groups.update_group(msg.chat.id, group_info)
            logger.info('Updated administrator list in %d, new list is => %s',
                        msg.chat.id, group_info.admins)
        if msg.from_user.id in group_info.admins:
            raise ContinuePropagation
        else:
            if not group_info.ignore_err and self.error_message != '':
                msg.reply(self.error_message)
                try:
                    client.restrict_chat_member(
                        msg.chat.id, msg.from_user.id,
                        ChatPermissions(can_send_messages=False),
                        msg.date + 60)
                except:
                    pass

    def set_welcome_message(self, _client: Client, msg: Message):
        result = setcommand_match.match(msg.text)
        welcomemsg = str(result.group(2))
        result = gist_match.match(welcomemsg)
        if result:
            r = requests.get(welcomemsg)
            r.raise_for_status()
            welcomemsg = r.text
        if len(welcomemsg) > 2048:
            msg.reply(
                "**Error**:Welcome message is too long.(len() must smaller than 2048)",
                parse_mode='markdown')
            return
        p = self.groups[msg.chat.id]
        p.welcome_text = welcomemsg
        self.groups.update_group(msg.chat.id, p)
        msg.reply(f"**Set welcome message to:**\n{welcomemsg}",
                  parse_mode='markdown',
                  disable_web_page_preview=True)

    def clear_welcome_message(self, _client: Client, msg: Message):
        p = self.groups[msg.chat.id]
        p.welcome_text = ''
        self.groups.update_group(msg.chat.id, p)
        msg.reply("**Clear welcome message completed!**",
                  parse_mode='markdown')

    def generate_status_message(self, _client: Client, msg: Message):
        info = self.groups[msg.chat.id]
        send_and_delete(
            msg, 'Current welcome messsage: {}'.format(info.welcome_text), 10)

    def response_ping_command(self, _client: Client, msg: Message):
        send_and_delete(
            msg,
            '**Current chat_id:** `{}`\n**Your id:** `{}`\n**Bot runtime**: `{}`\n**System load avg**: `{}`'
            .format(msg.chat.id, msg.from_user.id, self.get_runtime(),
                    getloadavg()), 10)

    def set_group_prop(self, _client: Client, msg: Message):
        r = setflag_match.match(msg.text)
        if r is None:
            return send_and_delete(
                msg, 'Please read manual to use this command properly', 10)
        value = r.group(3) == '1'
        group_info = self.groups[msg.chat.id]
        if r.group(2) == 'no_welcome':
            group_info.no_welcome = value
        elif r.group(2) == 'no_blue':
            group_info.no_blue = value
        elif r.group(2) == 'ignore_err':
            group_info.ignore_err = value
        elif r.group(2) == 'no_service_msg':
            group_info.no_service_msg = value
        elif r.group(2) == 'no_new_member':
            group_info.no_new_member = value
        self.groups.update_group(msg.chat.id, group_info)
        send_and_delete(msg,
                        f'Set {r.group(2)} flag to **{value}** successfully!',
                        10)

    def init_receiver(self):
        self.bot.add_handler(
            MessageHandler(self.new_chat_member, Filters.new_chat_members))
        self.bot.add_handler(
            MessageHandler(self.left_chat_member, Filters.left_chat_member))
        self.bot.add_handler(
            MessageHandler(
                self.privileges_control, Filters.group & Filters.regex(
                    r'^\/(setwelcome|clear|status|setflag)(@[a-zA-Z_]*bot)?\s?'
                )))
        self.bot.add_handler(
            MessageHandler(
                self.set_welcome_message, Filters.group &
                Filters.regex(r'^\/setwelcome(@[a-zA-Z_]*bot)?\s((.|\n)*)$')))
        self.bot.add_handler(
            MessageHandler(
                self.clear_welcome_message,
                Filters.group & Filters.regex(r'^\/clear(@[a-zA-Z_]*bot)?$')))
        self.bot.add_handler(
            MessageHandler(
                self.generate_status_message,
                Filters.group & Filters.regex(r'^\/status(@[a-zA-Z_]*bot)?$')))
        self.bot.add_handler(
            MessageHandler(
                self.response_ping_command,
                Filters.group & Filters.regex(r'^\/ping(@[a-zA-Z_]*bot)?$')))
        self.bot.add_handler(
            MessageHandler(
                self.set_group_prop, Filters.group
                & Filters.regex(r'^\/setflag(@[a-zA-Z_]*bot)?\s?')))

    def get_runtime(self):
        return str(datetime.datetime.now().replace(microsecond=0) -
                   self.loaddatetime)
Exemple #10
0
class bot_controller(object):
    def __init__(self):
        self.problems_load()
        self.target_group = int(config['fuduji']['target_group'])
        self.fudu_group = int(config['fuduji']['fudu_group'])

        self.bot_id = int(config['account']['api_key'].split(':')[0])
        self.emerg_contact = eval(config['account']['emerg_contact']) \
         if config.has_option('account', 'emerg_contact') and config['account']['emerg_contact'] != '' else \
         int(config['account']['owner'])
        self.app = Client(session_name='session',
                          api_id=config['account']['api_id'],
                          api_hash=config['account']['api_hash'],
                          app_version='repeater')
        self.botapp = Client(session_name=config['account']['api_key'],
                             api_id=config['account']['api_id'],
                             api_hash=config['account']['api_hash'])

        self.conn = mysqldb(config['database']['host'],
                            config['database']['user'],
                            config['database']['passwd'],
                            config['database']['db_name'], self.emerg_contact)
        self.media_sender = mediaSender(self.app.send_message, self.conn)
        self.join_group_verify = join_group_verify_class(
            self.conn, self.botapp, self.target_group, extern_load_problem_set)
        self.revoke_tracker_thread = self.join_group_verify.get_revoke_tracker_thread(
        )
        self.custom_service = custom_service_bot_class(
            config, self.conn, self.revoke_tracker_thread.send_link)
        self.db_keepAlive = Thread(target=self.conn.keep_alive, daemon=True)
        self.db_keepAlive.start()

    def init(self):
        global bot_username
        bot_username = self.botapp.get_me().username

    def problems_load(self):
        self.problem_set = extern_load_problem_set()

    def idle(self):
        return self.app.idle()

    def start(self):
        self.app.add_handler(
            MessageHandler(
                self.handle_edit,
                Filters.chat(self.target_group) & ~Filters.user(self.bot_id)
                & Filters.edited))
        self.app.add_handler(
            MessageHandler(
                self.handle_new_member,
                Filters.chat(self.target_group) & Filters.new_chat_members))
        self.app.add_handler(
            MessageHandler(
                self.handle_document,
                Filters.chat(self.target_group) & ~Filters.user(self.bot_id)
                & Filters.document))
        self.app.add_handler(
            MessageHandler(
                self.handle_photo,
                Filters.chat(self.target_group) & ~Filters.user(self.bot_id)
                & Filters.photo))
        self.app.add_handler(
            MessageHandler(
                self.handle_sticker,
                Filters.chat(self.target_group) & ~Filters.user(self.bot_id)
                & Filters.sticker))
        self.app.add_handler(
            MessageHandler(
                self.handle_gif,
                Filters.chat(self.target_group) & ~Filters.user(self.bot_id)
                & Filters.animation))
        self.app.add_handler(
            MessageHandler(
                self.handle_video,
                Filters.chat(self.target_group) & ~Filters.user(self.bot_id)
                & Filters.video))
        self.app.add_handler(
            MessageHandler(
                self.handle_speak,
                Filters.chat(self.target_group) & ~Filters.user(self.bot_id)
                & Filters.text))
        self.app.add_handler(
            MessageHandler(self.handle_incoming,
                           Filters.incoming & Filters.chat(self.fudu_group)))
        self.botapp.add_handler(CallbackQueryHandler(self.handle_callback))
        self.join_group_verify.init()
        self.app.start()
        self.botapp.start()
        self.init()
        self.custom_service.start()

    def stop(self):
        self.revoke_tracker_thread.set_stop()
        self.revoke_tracker_thread.join(1.5)
        if self.revoke_tracker_thread.is_alive():
            print('[WARN] revoke_tracker_thread still running!')
        self.custom_service.stop()
        self.botapp.stop()
        self.app.stop()

    def emerg_send_message(self, msg_str: str):
        '''
			Send message to emergancy contacts.
		'''
        if isinstance(self.emerg_contact, int):
            self.app.send_message(self.emerg_contact, msg_str, 'html')
        else:
            for user_id in self.emerg_contact:
                self.app.send_message(user_id, msg_str, 'html')

    def process_imcoming_command(self, client: Client, msg: Message):
        r = re.match(r'^\/bot (on|off)$', msg.text)
        if r is None: r = re.match(r'^\/b?(on|off)$', msg.text)
        if r:
            if not auth_system.check_ex(
                    msg.reply_to_message.from_user.id if msg.
                    reply_to_message else msg.from_user.id):
                return
            auth_system.mute_or_unmute(
                r.group(1), msg.reply_to_message.from_user.id
                if msg.reply_to_message else msg.from_user.id)
            client.delete_messages(msg.chat.id, msg.message_id)
        if msg.text == '/status':
            user_id = msg.reply_to_message.from_user.id if msg.reply_to_message else msg.from_user.id
            status = [
                str(user_id), ' summary:\n\n',
                'A' if auth_system.check_ex(user_id) else 'Una',
                'uthorized user\nBot status: ',
                '✅' if not auth_system.check_muted(user_id) else '❌'
            ]
            sleep_to_delete(
                client, msg.chat.id,
                (msg.message_id, msg.reply(''.join(status), True).message_id))
            del status
        elif msg.text.startswith('/p'):
            if msg.text.startswith('/promote'):
                if len(msg.text.split()) == 1:
                    if msg.reply_to_message is None or not auth_system.check_ex(
                            msg.reply_to_message.from_user.id):
                        self.botapp.send_message(
                            msg.chat.id,
                            'Please reply to an Authorized user.',
                            reply_to_message_id=msg.message_id)
                        return
                    user_id = msg.reply_to_message.from_user.id
                else:
                    user_id = int(msg.text.split()[1])
                self.botapp.send_message(
                    msg.chat.id,
                    'Please use bottom to make sure you want to add {} to Administrators'
                    .format(build_html_parse.parse_user(user_id)),
                    parse_mode='markdown',
                    reply_to_message_id=msg.message_id,
                    reply_markup=InlineKeyboardMarkup(
                        inline_keyboard=[[
                            InlineKeyboardButton(text='Yes, confirm',
                                                 callback_data='promote {}'.
                                                 format(user_id).encode())
                        ],
                                         [
                                             InlineKeyboardButton(
                                                 text='Cancel',
                                                 callback_data=b'cancel d')
                                         ]]))
            else:
                if not auth_system.check_ex(msg.from_user.id): return
                self.botapp.promote_chat_member(self.target_group,
                                                int(msg.from_user.id),
                                                True,
                                                can_delete_messages=True,
                                                can_restrict_members=True,
                                                can_invite_users=True,
                                                can_pin_messages=True,
                                                can_promote_members=True)
                self.botapp.send_message(
                    msg.chat.id,
                    '[Emergency]: Privileges has been promoted',
                    reply_to_message_id=msg.message_id)
            return
        if msg.reply_to_message:
            if msg.text == '/del':
                try:
                    client.forward_messages(
                        msg.chat.id, self.target_group,
                        self.conn.get_reply_id_Reverse(msg))
                    self.botapp.delete_messages(
                        self.target_group, self.conn.get_reply_id_Reverse(msg))
                except:
                    client.send_message(msg.chat.id,
                                        traceback.format_exc(),
                                        disable_web_page_preview=True)
                try:
                    client.delete_messages(
                        int(config['fuduji']['fudu_group']),
                        [msg.message_id, msg.reply_to_message.message_id])
                except:
                    pass
            elif msg.text == '/getid':
                user_id = self.conn.get_user_id(msg)
                client.send_message(
                    msg.chat.id,
                    'user_id is `{}`'.format(
                        user_id['user_id'] if user_id is not None and
                        user_id['user_id'] != 0 else 'ERROR_INVALID_USER_ID'),
                    parse_mode='markdown',
                    reply_to_message_id=msg.reply_to_message.message_id)
            elif msg.text == '/get' and self.conn.get_reply_id_Reverse(msg):
                try:
                    client.forward_messages(
                        int(config['fuduji']['fudu_group']), self.target_group,
                        self.conn.get_reply_id_Reverse(msg))
                except:
                    client.send_message(
                        msg.chat.id,
                        traceback.format_exc().splitlines()[-1])
            elif msg.text == '/getn':
                pass
            elif msg.text == '/fw':
                self.conn.insert_ex(
                    self.botapp.forward_messages(
                        self.target_group, self.target_group,
                        self.conn.get_reply_id_Reverse(msg)).message_id,
                    msg.message_id)
            elif msg.text.startswith('/ban'):
                user_id = self.conn.get_user_id(msg)
                if len(msg.text) == 4:
                    restrict_time = 0
                else:
                    r = re.match(r'^([1-9]\d*)(s|m|h|d)$', msg.text[5:])
                    if r is not None:
                        restrict_time = int(r.group(1)) * {
                            's': 1,
                            'm': 60,
                            'h': 60 * 60,
                            'd': 60 * 60 * 24
                        }.get(r.group(2))
                    else:
                        self.botapp.send_message(
                            msg.chat.id,
                            'Usage: `/ban` or `/ban <Duration>`',
                            reply_to_message_id=msg.message_id,
                            parse_mode='markdown')
                if user_id is not None and user_id['user_id'] != 0:
                    if user_id['user_id'] not in auth_system.whitelist:
                        self.botapp.send_message(
                            msg.chat.id,
                            'What can {} only do? Press the button below.\nThis confirmation message will expire after 20 seconds.'
                            .format(
                                build_html_parse.parse_user(
                                    user_id['user_id'])),
                            reply_to_message_id=msg.message_id,
                            parse_mode='markdown',
                            reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                                [
                                    InlineKeyboardButton(
                                        text='READ',
                                        callback_data='res {} read {}'.format(
                                            restrict_time,
                                            user_id['user_id']).encode())
                                ],
                                [
                                    InlineKeyboardButton(
                                        text='SEND_MESSAGES',
                                        callback_data='res {} write {}'.format(
                                            restrict_time,
                                            user_id['user_id']).encode()),
                                    InlineKeyboardButton(
                                        text='SEND_MEDIA',
                                        callback_data='res {} media {}'.format(
                                            restrict_time,
                                            user_id['user_id']).encode())
                                ],
                                [
                                    InlineKeyboardButton(
                                        text='SEND_STICKERS',
                                        callback_data='res {} stickers {}'.
                                        format(restrict_time,
                                               user_id['user_id']).encode()),
                                    InlineKeyboardButton(
                                        text='EMBED_LINKS',
                                        callback_data='res {} link {}'.format(
                                            restrict_time,
                                            user_id['user_id']).encode())
                                ],
                                [
                                    InlineKeyboardButton(
                                        text='Cancel', callback_data=b'cancel')
                                ]
                            ]))
                    else:
                        self.botapp.send_message(
                            msg.chat.id,
                            'ERROR_WHITELIST_USER_ID',
                            reply_to_message_id=msg.message_id)
                else:
                    self.botapp.send_message(
                        msg.chat.id,
                        'ERROR_INVALID_USER_ID',
                        reply_to_message_id=msg.message_id)
            elif msg.text == '/kick':
                user_id = self.conn.get_user_id(msg)
                if user_id is not None and user_id['user_id'] != 0:
                    if user_id['user_id'] not in auth_system.whitelist:
                        self.botapp.send_message(
                            msg.chat.id,
                            'Do you really want to kick {}?\nIf you really want to kick this user, press the button below.\nThis confirmation message will expire after 15 seconds.'
                            .format(
                                build_html_parse.parse_user(
                                    user_id['user_id'])),
                            reply_to_message_id=msg.message_id,
                            parse_mode='markdown',
                            reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                                [
                                    InlineKeyboardButton(
                                        text='Yes, kick it',
                                        callback_data=b' '.join((
                                            b'kick',
                                            str(msg.from_user.id).encode(),
                                            str(user_id['user_id']).encode())))
                                ],
                                [
                                    InlineKeyboardButton(
                                        text='No', callback_data=b'cancel')
                                ],
                            ]))
                    else:
                        self.botapp.send_message(
                            msg.chat.id,
                            'ERROR_WHITELIST_USER_ID',
                            reply_to_message_id=msg.message_id)
                else:
                    self.botapp.send_message(
                        msg.chat.id,
                        'ERROR_INVALID_USER_ID',
                        reply_to_message_id=msg.message_id)
        else:  # Not reply message
            if msg.text == '/ban':
                client.send_message(
                    msg.chat.id,
                    'Reply to the user you wish to restrict, if you want to kick this user, please use the /kick command.'
                )
            elif msg.text == '/join':
                pass
            elif msg.text.startswith('/set'):
                auth_system.user_suffix[
                    msg.from_user.id] = msg.text.split()[-1]
                client.send_message(msg.chat.id,
                                    'Set suffix to `{}`'.format(
                                        msg.text.split()[-1]),
                                    'markdown',
                                    reply_to_message_id=msg.message_id)

    def func_auth_process(self, client: Client, msg: Message):
        if not auth_system.check_ex(msg.from_user.id):
            msg.reply('Permission denied')
            return
        if msg.reply_to_message.from_user:
            if auth_system.check_ex(msg.reply_to_message.from_user.id):
                msg.reply('Authorized')
            else:
                self.botapp.send_message(
                    msg.chat.id,
                    'Do you want to authorize {} ?\nThis confirmation message will expire after 20 seconds.'
                    .format(
                        build_html_parse.parse_user(
                            msg.reply_to_message.from_user.id)),
                    reply_to_message_id=msg.message_id,
                    parse_mode='markdown',
                    reply_markup=InlineKeyboardMarkup(inline_keyboard=[[
                        InlineKeyboardButton(
                            text='Yes',
                            callback_data='auth {} add'.format(
                                msg.reply_to_message.from_user.id).encode()),
                        InlineKeyboardButton(text='No',
                                             callback_data=b'cancel')
                    ]]))
        else:
            client.send_message(msg.chat.id,
                                'Unexpected error.',
                                reply_to_message_id=msg.message_id)

    def cross_group_forward_request(self, msg: Message):
        kb = [[
            InlineKeyboardButton(text='Yes, I know what I\'m doing.',
                                 callback_data=b'fwd original')
        ],
              [
                  InlineKeyboardButton(text='Yes, but don\'t use forward.',
                                       callback_data=b'fwd text')
              ],
              [
                  InlineKeyboardButton(text='No, please don\'t.',
                                       callback_data=b'cancel d')
              ]]
        if msg.text is None: kb.pop(1)
        self.botapp.send_message(
            msg.chat.id,
            '<b>Warning:</b> You are requesting forwarding an authorized user\'s message to the main group, please comfirm your action.',
            'html',
            reply_to_message_id=msg.message_id,
            reply_markup=InlineKeyboardMarkup(inline_keyboard=kb))
        del kb

    def handle_new_member(self, client: Client, msg: Message):
        for new_user_id in (x.id for x in msg.new_chat_members):
            # Exam check goes here
            try:
                if not self.join_group_verify.query_user_passed(new_user_id):
                    self.botapp.kick_chat_member(self.target_group,
                                                 new_user_id)
                    self.botapp.send_message(
                        self.fudu_group,
                        'Kicked challenge failure user {}'.format(
                            build_html_parse.parse_user(new_user_id)),
                        'markdown',
                    )
            except:
                traceback.print_exc()
        self.conn.insert(
         msg,
         client.send_message(
          self.fudu_group,
          '`{}` invite `{}` joined the group'.format(
           build_html_parse.user_name(msg.from_user).full_name,
           '`,`'.join(
            build_html_parse.user_name(user).full_name for user in msg.new_chat_members
           )
          ),
          'markdown'
         ) \
         if msg.new_chat_members[0].id != msg.from_user.id else \
          client.send_message(
           self.fudu_group,
           '`{}` joined the group'.format(
            '`,`'.join(
             build_html_parse.user_name(user).full_name for user in msg.new_chat_members
            )
           ),
           'markdown'
          )
         )

    def handle_edit(self, client: Client, msg: Message):
        if msg.via_bot and msg.via_bot.id == 166035794: return
        if self.conn.get_id(msg.message_id) is None:
            time.sleep(3)
            if self.conn.get_id(msg.message_id) is None:
                print(msg)
                return print('Editing Failure: get_id return None')
        try:
            (client.edit_message_text if msg.text else
             client.edit_message_caption)(self.fudu_group,
                                          self.conn.get_id(msg.message_id),
                                          build_html_parse(msg).call(), 'html')
        except:
            traceback.print_exc()

    def handle_document(self, client: Client, msg: Message):
        self.media_sender.put((client.send_document, msg, msg.document, False))

    def handle_photo(self, client: Client, msg: Message):
        self.media_sender.put(
            (client.send_photo, msg, msg.photo.sizes[0], False))

    def handle_sticker(self, client: Client, msg: Message):
        self.conn.insert(
            msg,
            client.send_message(
                self.fudu_group,
                '{} {} sticker'.format(
                    build_html_parse(msg).call(), msg.sticker.emoji),
                'html',
                True,
                reply_to_message_id=self.conn.get_reply_id(msg),
            ))

    def handle_gif(self, client: Client, msg: Message):
        self.media_sender.put(
            (client.send_animation, msg, msg.animation, False))

    def handle_video(self, client: Client, msg: Message):
        self.media_sender.put((client.send_video, msg, msg.video, False))

    def handle_speak(self, client: Client, msg: Message):
        if msg.text.startswith('/') and re.match(r'^\/\w+(@\w*)?$', msg.text):
            return
        self.conn.insert(
            msg,
            client.send_message(
                self.fudu_group,
                build_html_parse(msg).call(),
                'html',
                reply_to_message_id=self.conn.get_reply_id(msg),
                disable_web_page_preview=True))

    def handle_incoming(self, client: Client, msg: Message):
        client.send(
            api.functions.channels.ReadHistory(
                client.resolve_peer(msg.chat.id), msg.message_id))
        if msg.text == '/auth' and msg.reply_to_message:
            return self.func_auth_process(client, msg)
        if not auth_system.check_ex(msg.from_user.id): return
        if msg.text and re.match(
                r'^\/(bot (on|off)|del|getn?|fw|ban( (([1-9]\d*)(s|m|h|d)|f))?|kick( confirm| -?\d+)?|status|b?o(n|ff)|join|p(romote( \d+)?)?|set [a-zA-Z])$',
                msg.text):
            return self.process_imcoming_command(client, msg)
        if msg.text and msg.text.startswith('/') and re.match(
                r'^\/\w+(@\w*)?$', msg.text):
            return
        if auth_system.check_muted(msg.from_user.id) or (
                msg.text and msg.text.startswith('//')) or (
                    msg.caption and msg.caption.startswith('//')):
            return

        if msg.forward_from or msg.forward_from_chat:
            if msg.forward_from:
                if msg.forward_from.is_self: return
                elif auth_system.check_ex(msg.forward_from.id):
                    return self.cross_group_forward_request(msg)
            self.conn.insert_ex(
                self.botapp.forward_messages(self.target_group,
                                             self.fudu_group,
                                             msg.message_id).message_id,
                msg.message_id)
        elif msg.text and (not msg.edit_date or
                           (msg.edit_date and
                            self.conn.get_id(msg.message_id, True) is None)):
            self.conn.insert_ex(
                self.botapp.send_message(
                    self.target_group,
                    build_html_parse(msg).split_offset(),
                    'html',
                    True,
                    reply_to_message_id=self.conn.get_reply_id_Reverse(msg),
                ).message_id, msg.message_id)
        elif msg.photo:
            self.media_sender.Locker.acquire()
            msg.download('tmp.jpg')
            self.media_sender.put((self.botapp.send_photo, msg,
                                   media_path('downloads/tmp.jpg'), True),
                                  True)
        elif msg.video:
            self.media_sender.put(
                (self.botapp.send_video, msg, msg.video, True), True)
        elif msg.document:
            self.media_sender.put(
                (self.botapp.send_document, msg, msg.document, True), True)
        elif msg.edit_date:
            try:
                (self.botapp.edit_message_text
                 if msg.text else self.botapp.edit_message_caption)(
                     self.target_group,
                     self.conn.get_id(msg.message_id, True),
                     build_html_parse(msg).split_offset(),
                     parse_mode='html',
                     disable_web_page_preview=True)
            except:
                traceback.print_exc()
        elif msg.sticker:
            self.media_sender.put(
                (self.botapp.send_sticker, msg, msg.sticker, True), True)

    def handle_callback(self, client: Client, msg: CallbackQuery):
        msg.data = msg.data.decode(errors='ignore')
        try:
            if msg.data.startswith('cancel') or msg.data == 'rm':
                msg.answer(
                    msg.id,
                    'Canceled' if not msg.data == 'rm' else 'Button removed')
                if msg.data.endswith('d'):
                    client.delete_messages(msg.message.chat.id,
                                           msg.message.message_id)
                else:
                    client.edit_message_reply_markup(msg.message.chat.id,
                                                     msg.message.message_id)
            if self.join_group_verify is not None and self.join_group_verify.click_to_join(
                    client, msg):
                return
            if msg.data.startswith('res'):
                if time.time() - msg.message.date > 20:
                    raise OperationTimeoutError()
                _, dur, _type, _user_id = msg.data.split()
                if client.restrict_chat_member(
                        self.target_group, int(_user_id),
                        int(time.time()) + int(dur),
                        **({
                            'write': {
                                'can_send_messages': True
                            },
                            'media': {
                                'can_send_media_messages': True
                            },
                            'stickers': {
                                'can_send_other_messages': True
                            },
                            'link': {
                                'can_add_web_page_previews': True
                            },
                            'read': {}
                        }.get(_type))):
                    msg.answer('The user is restricted successfully.')
                    client.edit_message_text(
                        msg.message.chat.id,
                        msg.message.message_id,
                        'Restrictions applied to {} Duration: {}'.format(
                            build_html_parse.parse_user(_user_id),
                            '{}s'.format(dur) if int(dur) else 'Forever'),
                        parse_mode='markdown',
                        reply_markup=InlineKeyboardMarkup([[
                            InlineKeyboardButton(
                                text='UNBAN',
                                callback_data='unban {}'.format(
                                    _user_id).encode())
                        ]]))

            elif msg.data.startswith('unban'):
                if client.restrict_chat_member(self.target_group,
                                               int(msg.data.split()[-1]), 0,
                                               True, True, True, True):
                    msg.answer('Unban successfully')
                    client.edit_message_reply_markup(msg.message.chat.id,
                                                     msg.message.message_id)
            elif msg.data.startswith('auth'):
                if time.time() - msg.message.date > 20:
                    raise OperationTimeoutError()
                auth_system.add_user(msg.data.split()[1])
                msg.answer('{} added to the authorized group'.format(
                    msg.data.split()[1]))
                client.edit_message_text(
                    msg.message.chat.id, msg.message.message_id,
                    '{} added to the authorized group'.format(
                        msg.data.split()[1]))
                with open('config.ini', 'w') as fout:
                    config.write(fout)
            elif msg.data.startswith('fwd'):
                if time.time() - msg.message.date > 30:
                    raise OperationTimeoutError()
                if 'original' in msg.data:
                    self.conn.insert_ex(
                        client.forward_messages(
                            self.target_group, msg.message.chat.id, msg.
                            message.reply_to_message.message_id).message_id,
                        msg.message.reply_to_message.message_id)
                else:
                    self.conn.insert_ex(
                        client.send_message(
                            self.target_group,
                            build_html_parse(
                                msg.message.reply_to_message).split_offset(),
                            'html').message_id,
                        msg.message.reply_to_message.message_id)
                msg.answer('Forward successfully')
                client.delete_messages(msg.message.chat.id,
                                       msg.message.message_id)
            elif msg.data.startswith('kick'):
                if not msg.data.startswith(
                        'kickc') and msg.from_user.id != int(
                            msg.data.split()[-2]):
                    raise OperatorError()
                if 'true' not in msg.data:
                    if not msg.data.startswith(
                            'kickc') and time.time() - msg.message.date > 15:
                        raise OperationTimeoutError()
                    args = [
                        msg.message.chat.id,
                        msg.message.message_id,
                        'Press the button again to kick {}\nThis confirmation message will expire after 10 seconds.'
                        .format(
                            build_html_parse.parse_user(msg.data.split()[-1])),
                    ]
                    if msg.data.startswith('kickc'):
                        args.pop(1)
                        r = msg.data.split()
                        r.insert(1, msg.from_user.id)
                        msg.data = ' '.join(str(x) for x in r)
                        del r
                    kwargs = {
                        'parse_mode':
                        'markdown',
                        'reply_markup':
                        InlineKeyboardMarkup(
                            inline_keyboard=[[
                                InlineKeyboardButton(
                                    text='Yes, please.',
                                    callback_data=b' '.join((
                                        b'kick true', ' '.join(
                                            msg.data.split()[1:]).encode())))
                            ],
                                             [
                                                 InlineKeyboardButton(
                                                     text='Cancel',
                                                     callback_data=b'cancel')
                                             ]])
                    }
                    (client.send_message if msg.data.startswith('kickc') else
                     client.edit_message_text)(*args, **kwargs)
                    msg.answer(
                        'Please press again to make sure. Do you really want to kick {} ?'
                        .format(msg.data.split()[-1]), True)
                else:
                    if msg.message.edit_date:
                        if time.time() - msg.message.edit_date > 10:
                            raise OperationTimeoutError()
                    else:
                        if time.time() - msg.message.date > 10:
                            raise OperationTimeoutError()
                    client.kick_chat_member(self.target_group,
                                            int(msg.data.split()[-1]))
                    msg.answer('Kicked {}'.format(msg.data.split()[-1]))
                    client.edit_message_text(
                        msg.message.chat.id, msg.message.message_id,
                        'Kicked {}'.format(
                            build_html_parse.parse_user(msg.data.split()[-1])))
                    #app.send_message(self.fudu_group, 'Kicked {}'.format(msg.message.entities[0].user.id))
                #client.delete_messages(msg.message.chat.id, msg.message.message_id)
            elif msg.data.startswith('promote'):
                if not msg.data.endswith('undo'):
                    if time.time() - msg.message.date > 10:
                        raise OperationTimeoutError()
                    self.botapp.promote_chat_member(self.target_group,
                                                    int(msg.data.split()[1]),
                                                    True,
                                                    can_delete_messages=True,
                                                    can_restrict_members=True,
                                                    can_invite_users=True,
                                                    can_pin_messages=True,
                                                    can_promote_members=True)
                    msg.answer('Promote successfully')
                    client.edit_message_text(
                        msg.message.chat.id,
                        msg.message.message_id,
                        'Promoted {}'.format(
                            build_html_parse.parse_user(
                                int(msg.data.split()[1]))),
                        parse_mode='markdown',
                        reply_markup=InlineKeyboardMarkup(inline_keyboard=[
                            [
                                InlineKeyboardButton(text='UNDO',
                                                     callback_data=' '.join((
                                                         msg.data,
                                                         'undo')).encode())
                            ],
                            [
                                InlineKeyboardButton(text='remove button',
                                                     callback_data=b'rm')
                            ]
                        ]))
                else:
                    self.botapp.promote_chat_member(self.target_group,
                                                    int(msg.data.split()[1]),
                                                    False,
                                                    can_delete_messages=False,
                                                    can_invite_users=False,
                                                    can_restrict_members=False)
                    msg.answer('Undo Promote successfully')
                    client.edit_message_text(
                        msg.message.chat.id,
                        msg.message.message_id,
                        'Unpromoted {}'.format(
                            build_html_parse.parse_user(
                                int(msg.data.split()[1]))),
                        parse_mode='markdown')
        except OperationTimeoutError:
            msg.answer('Confirmation time out')
            client.edit_message_reply_markup(msg.message.chat.id,
                                             msg.message.message_id)
        except OperatorError:
            msg.answer(
                'The operator should be {}.'.format(msg.data.split()[-2]),
                True)
        except:
            self.app.send_message(int(config['fuduji']['help_group']),
                                  traceback.format_exc().splitlines()[-1])
            traceback.print_exc()
Exemple #11
0
def main():
    load_modules()
    client = Client(session_name="userbot")
    client.set_update_handler(update_handler)
    client.start()
    client.idle()
Exemple #12
0
class _BotClient:
    def __init__(self):
        self.config = ConfigParser()
        self.config.read('data/server_config.ini')

        self.client_pool = {}

        self.botapp = Client('distributed_vps_control_bot',
                             self.config['account']['api_id'],
                             self.config['account']['api_key'],
                             bot_token=self.config['account']['bot_key'])

        self.conn = mysqldb.init_instance(self.config['mysql']['host'],
                                          self.config['mysql']['user'],
                                          self.config['mysql']['password'],
                                          self.config['mysql']['database'])

        self.owner = self.config.getint('account', 'owner')

        self.http_server = HTTPServer(
            (self.config['http']['addr'], self.config['http']['port']),
            RewritedServer)

        self.http_thread = None
        self._basic_filter = Filters.chat(self.owner)

    def init_handle(self):
        self.botapp.add_handler(
            MessageHandler(self.handle_status, self._basic_filter))
        self.botapp.add_handler(
            CallbackQueryHandler(self.handle_callback_query))

    def idle(self):
        try:
            self.botapp.idle()
        except InterruptedError:
            pass

    def handle_status(self, _client: Client, _msg: Message):
        pass

    def request_confirm(self, cid: int, payload: dict):
        self.botapp.send_message(
            self.owner,
            'Do you want to approve this machine\n**Username**: `{}`\nIP Address:`{}`'
            .format(payload.get('username'), payload.get('ip')),
            'markdown',
            reply_markup=InlineKeyboardMarkup(inline_keyboard=[[
                InlineKeyboardButton('approve', callback_data=f'approve {cid}')
            ]]))

    def start(self):
        self.http_thread = threading.Thread(
            target=self.http_server.serve_forever, daemon=True)
        self.http_thread.start()
        self.botapp.start()

    def handle_callback_query(self, client: Client, msg: CallbackQuery):
        data = msg.data.split()
        if data[0] == 'approve':
            self.conn.approve_new_client(data[1])

    def stop(self):
        self.botapp.stop()
        self.conn.close()
class TelegramBot():
    def __init__(self):

        self.client = Client("Listener")

        self.client.add_handler(RawUpdateHandler(self.processUpdate))

    def run(self):

        self.config = configparser.ConfigParser()
        try:
            self.config.read("config.ini")
        except:
            self.logError("Error while loading the config file, exiting", True)

        self.setupDBConnection()

        print("\nStarting Telegram API connection\n")
        self.client.start()
        print("API connection started")

        self.listening = False
        self.chats = self.getChats()
        self.monitoredChats = self.loadMonitoredChatsTable()

        self.menu()

        self.client.idle()

    def menu(self):

        help = '''
- COMMANDS -

all - show a list of joined chats/channels/groups in the account
listening - show a list of joined chats/channels/groups we are listening to for updates
add - add hats/channels/groups to the listening list, pass comma-separated list of usernames or ids
remove - remove chats/channels/groups from the listening list, pass comma-separated list of usernames or ids

start - start listening for updates
'''
        print(help)

        while (True):

            userInput = input("\nPlease enter command: ")
            try:
                inputSplit = userInput.split(" ", 1)
                command = inputSplit[0].strip()

                if (command == "start"):
                    print("\nStarted listening for updates\n")
                    self.listening = True
                    return

                elif (command == "all"):
                    print("\nTITLE - USERNAME - ID")
                    for chatID in self.chats:
                        chat = self.chats[chatID]
                        print(chat[0] + " - " + chat[1] + " - " + str(chatID))

                elif (command == "listening"):
                    if len(self.monitoredChats) > 0:
                        print("TITLE - USERNAME - ID")
                        for chatID in self.monitoredChats:
                            chat = self.monitoredChats[chatID]
                            print(chat[0] + " - " + chat[1] + " - " +
                                  str(chatID))
                    else:
                        print(
                            "We're not listening to any chats/channels/groups yet"
                        )

                elif (command == "add"):
                    if len(inputSplit) == 1:
                        print("No arguments provided")
                        continue
                    items = inputSplit[1].split(",")
                    items = [i.strip() for i in items if i.strip() != ""]
                    self.addChats(items)

                elif (command == "remove"):
                    if len(inputSplit) == 1:
                        print("No arguments provided")
                        continue
                    items = inputSplit[1].split(",")
                    items = [i.strip() for i in items if i.strip() != ""]
                    self.removeChats(items)

                else:
                    print("Sorry, the command was not recognized")

            except:
                self.logError("Sorry, we've encountered an error")
                continue

    def setupDBConnection(self):

        host = self.config["database"]["host"]
        user = self.config["database"]["user"]
        password = self.config["database"]["password"]
        db = self.config["database"]["db"]
        charset = self.config["database"]["charset"]
        dbsettings = {
            "host": host,
            "user": user,
            "password": password,
            "db": db,
            "charset": charset
        }
        try:
            self.pool = pymysql_pool.ConnectionPool(size=1,
                                                    name='pool',
                                                    **dbsettings)
        except:
            self.logError(
                "Error while attempting to connect to database, exiting\n",
                True)
        print("Database connection established")

        self.checkTables()

    def checkTables(self):

        self.chatTable = self.config["database"]["chat_table"]
        self.messageTable = self.config["database"]["message_table"]

        tables = {}
        tables["chat"] = {
            "name":
            self.chatTable,
            "statement":
            "(ID int unsigned not null, Title varchar(255), Username varchar(255), PRIMARY KEY (ID))"
        }
        tables["message"] = {
            "name":
            self.messageTable,
            "statement":
            "(ID int unsigned not null auto_increment, Time datetime, Type varchar(255), Chat int unsigned not null, Sender varchar(255), Message text, PRIMARY KEY(ID), FOREIGN KEY (Chat) REFERENCES "
            + self.chatTable + "(ID))"
        }

        connection = self.pool.get_connection()
        c = connection.cursor()

        for tableType in tables:

            table = tables[tableType]

            try:
                c.execute("SHOW TABLES LIKE '" + table["name"] + "'")
                result = c.fetchone()
            except:
                self.logError(
                    "Error while looking for " + tableType + " table (" +
                    table["name"] + ") in database\n", True)

            if result:
                print("Found " + tableType + " table (" + table["name"] + ")")
            else:
                print("Creating " + tableType + " table (" + table["name"] +
                      ")")
                try:
                    c.execute("CREATE TABLE " + table["name"] + " " +
                              table["statement"])
                    connection.commit()
                except:
                    self.logError(
                        "Error while creating " + tableType + " table (" +
                        table["name"] + ")\n", True)

        connection.close()

    def loadMonitoredChatsTable(self):
        try:
            connection = self.pool.get_connection()
            c = connection.cursor()
            c.execute("SELECT * FROM " + self.chatTable)
            chats = list(c)
            self.monitoredChats = {
                chat[0]: [chat[1], chat[2]]
                for chat in chats
            }
            connection.close()
        except:
            self.logError(
                "Error while getting list of monitored chats/channels/groups from database"
            )

        self.cleanUpMonitored()

        return self.monitoredChats

    def cleanUpMonitored(self):
        delete = []
        for monitored in self.monitoredChats:
            if monitored not in self.chats:
                delete.append(monitored)
        if len(delete) > 0:
            try:
                connection = self.pool.get_connection()
                c = connection.cursor()
                for id in delete:
                    c.execute("DELETE FROM " + self.chatTable + " WHERE ID=" +
                              str(id))
                    del self.monitoredChats[id]
                connection.commit()
                connection.close()
            except:
                self.logError(
                    "Error while clearing a monitored chat we no longer are a member of"
                )

    def getChats(self):
        chats = self.client.send(functions.messages.GetAllChats([]))
        self.chats = chats.chats
        self.supergroupIDs = [
            chat.id for chat in self.chats
            if isinstance(chat, types.Channel) and chat.megagroup == True
        ]
        self.chats = {
            chat.id: [
                str(chat.title),
                ("@" if hasattr(chat, "username") and chat.username else "") +
                (str(chat.username) if hasattr(chat, "username") else "None")
            ]
            for chat in self.chats
        }
        return self.chats

    def addChats(self, items):
        new = []
        for item in items:
            print("Adding to monitored: " + item)
            if (item[0] == "@"):
                item = next(
                    (key
                     for key, value in self.chats.items() if value[1] == item),
                    None)
            elif not item.isdigit():
                print("Invalid format for: " + item)
                continue
            item = int(item)
            if not item or not item in self.chats:
                print("You haven't joined this channel yet")
                continue
            if item in self.monitoredChats:
                print("You've already added this to listening list")
                continue
            new.append(item)
        if len(new) > 0:
            self.updateMonitoredChatsList(new, "add")

    def removeChats(self, items):
        removed = []
        for item in items:
            print("Removing from monitored: " + item)
            if (item[0] == "@"):
                item = next(
                    (key
                     for key, value in self.chats.items() if value[1] == item),
                    None)
                if not item:
                    print(
                        "You haven't even joined this channel , check for typing errors"
                    )
                    continue
            elif item.isdigit():
                if not int(item) in self.chats:
                    print(
                        "You haven't even joined this channel, check for typing errors"
                    )
                    continue
                item = int(item)
            else:
                print("Invalid format for: " + item)
                continue
            if not item in self.monitoredChats:
                print("Already not monitored")
                continue
            removed.append(item)
        if len(removed) > 0:
            self.updateMonitoredChatsList(removed, "remove")

    def updateMonitoredChatsList(self, modified, action):
        try:
            connection = self.pool.get_connection()
            c = connection.cursor()
            for id in modified:
                chat = self.chats[id]
                if action == "add":
                    c.execute(
                        "INSERT INTO " + self.chatTable +
                        "(ID, Title, Username) VALUES (%s, %s, %s)",
                        (id, chat[0], chat[1]))
                elif action == "remove":
                    sql = "DELETE FROM " + self.chatTable + " WHERE ID=" + str(
                        id)
                    c.execute(sql)
            connection.commit()
            connection.close()
            for id in modified:
                if action == "remove":
                    del self.monitoredChats[id]
                elif action == "add":
                    self.monitoredChats[id] = self.chats[id]
        except:
            self.logError("Error while updating monitored list in database")

    def getAdmins(self):

        self.admins = {}

        for group in self.supergroupIDs:

            print("Getting admins for: " + str(group))

            groupAdmins = []
            limit = 200
            offset = 0
            filter = types.ChannelParticipantsAdmins()

            while True:
                try:
                    participants = self.client.send(
                        functions.channels.GetParticipants(
                            channel=self.client.resolve_peer(group),
                            filter=filter,
                            offset=offset,
                            limit=limit,
                            hash=0))
                except FloodWait as e:
                    time.sleep(e.x)
                    continue

                if isinstance(participants,
                              types.channels.ChannelParticipantsNotModified):
                    print("No admin changes")
                    pass

                if not participants.participants:
                    break

                groupAdmins.extend(participants.participants)
                offset += limit

            self.admins[group] = [admin.user_id for admin in groupAdmins]

        for group in self.admins:
            print(" - " + str(group) + " - ")
            for admin in self.admins[group]:
                print(admin)
            print()

        return self.admins

    def updateAdmins(self):
        while True:
            time.sleep(20)
            print("Admin list refresh")
            self.admins = self.getAdmins()

    def checkIfAdmin(self, channelID, senderID):
        admins = self.admins[channelID]
        if senderID in admins:
            return True
        else:
            return False

    def checkIfChannelAdmin(self, channelID, senderID):
        participant = self.client.send(
            functions.channels.GetParticipant(
                channel=self.client.resolve_peer(channelID),
                user_id=self.client.resolve_peer(senderID)))
        sender = participant.participant
        if isinstance(sender, types.ChannelParticipantCreator) or isinstance(
                sender, types.ChannelParticipantAdmin):
            return True
        else:
            return False

    def checkIfGroupAdmin(self, groupID, senderID):
        chat = self.client.send(functions.messages.GetFullChat(groupID))
        participants = chat.full_chat.participants.participants
        for participant in participants:
            if participant.user_id == senderID:
                if isinstance(participant,
                              types.ChatParticipantCreator) or isinstance(
                                  participant, types.ChatParticipantAdmin):
                    return True
                else:
                    return False

    def processUpdate(self, client, update, users, chats):

        if self.listening:

            if isinstance(update, types.UpdateNewChannelMessage):

                if isinstance(update.message, types.MessageService):
                    return

                chat = chats[update.message.to_id.channel_id]
                chatInfo = self.extractChatInfo(chat)
                if int(chatInfo["id"]) not in self.monitoredChats:
                    return
                sender = update.message.from_id
                if sender:
                    sender = users[sender]
                    senderInfo = self.extractSenderInfo(sender)
                else:
                    senderInfo = None
                if chat.megagroup == True:
                    if self.checkIfChannelAdmin(chatInfo["id"],
                                                senderInfo["id"]):
                        timestamp = update.message.date
                        message = update.message.message
                        print("Supergroup admin message - " +
                              chatInfo["string"] +
                              (" - Sender: " +
                               senderInfo["string"] if sender else "") + ": " +
                              message)
                        self.recordToDatabase(timestamp, "admin", chatInfo,
                                              senderInfo, message)
                        self.sendNotification("admin", chatInfo, senderInfo,
                                              message)
                    else:
                        print("Supergroup message not from admin - " +
                              chatInfo["string"] +
                              (" - Sender: " +
                               senderInfo["string"] if sender else "") + ": " +
                              update.message.message)
                else:
                    timestamp = update.message.date
                    message = update.message.message
                    print("Channel message - " + chatInfo["string"] +
                          (" - Sender: " +
                           senderInfo["string"] if sender else "") + ": " +
                          message)
                    self.recordToDatabase(timestamp, "channel", chatInfo,
                                          senderInfo, message)
                    self.sendNotification("channel", chatInfo, "", message)

            elif isinstance(update, types.UpdateChannelPinnedMessage):

                if update.id != 0:
                    chat = chats[update.channel_id]
                    chatInfo = self.extractChatInfo(chat)
                    if int(chatInfo["id"]) not in self.monitoredChats:
                        return
                    messageInfo = client.get_messages(update.channel_id,
                                                      update.id)
                    sender = messageInfo.from_user
                    if sender:
                        senderInfo = self.extractSenderInfo(sender)
                    else:
                        senderInfo = None
                    timestamp = messageInfo.date
                    message = messageInfo.text
                    print("New pinned message - " + chatInfo["string"] +
                          (" - Sender: " +
                           senderInfo["string"] if sender else "") + ": " +
                          message)
                    self.recordToDatabase(timestamp, "pinned", chatInfo,
                                          senderInfo, message)
                    self.sendNotification("pinned", chatInfo,
                                          senderInfo if sender else "",
                                          message)

            elif isinstance(update, types.UpdateNewMessage):
                if isinstance(update.message, types.MessageService):
                    return
                chat = chats[update.message.to_id.chat_id]
                chatInfo = self.extractChatInfo(chat)
                if int(chatInfo["id"]) not in self.monitoredChats:
                    return
                sender = users[update.message.from_id]
                senderInfo = self.extractSenderInfo(sender)
                timestamp = update.message.date
                message = update.message.message
                if self.checkIfGroupAdmin(chatInfo["id"], senderInfo["id"]):
                    print("Group admin message - " + chatInfo["string"] +
                          (" - Sender: " +
                           senderInfo["string"] if sender else "") + ": " +
                          message)
                    self.recordToDatabase(timestamp, "admin", chatInfo,
                                          senderInfo, message)
                    self.sendNotification("admin", chatInfo, senderInfo,
                                          message)
                else:
                    print("Group message not from admin - " +
                          chatInfo["string"] +
                          (" - Sender: " +
                           senderInfo["string"] if sender else "") + ": " +
                          message)

        elif isinstance(update, types.UpdateChannel):
            #print("Channel list changed")
            self.chats = self.getChats()
            self.cleanUpMonitored()

    def extractChatInfo(self, chat):
        chatInfo = {}
        chatInfo["title"] = chat.title
        chatInfo["id"] = chat.id
        if hasattr(chat, "username"):
            chatInfo["username"] = ("@" if chat.username else "") + str(
                chat.username)
        else:
            chatInfo["username"] = "******"
        chatInfo[
            "string"] = chatInfo["title"] + "(" + chatInfo["username"] + ")"
        return chatInfo

    def extractSenderInfo(self, sender):
        senderInfo = {}
        senderInfo["id"] = sender.id
        senderInfo["name"] = sender.first_name + (" " + str(sender.last_name)
                                                  if sender.last_name else "")
        if hasattr(sender, "username"):
            senderInfo["username"] = ("@" if sender.username else "") + str(
                sender.username)
        else:
            senderInfo["username"] = "******"
        senderInfo[
            "string"] = senderInfo["name"] + "(" + senderInfo["username"] + ")"
        return senderInfo

    def recordToDatabase(self, timestamp, type, chat, sender, message):
        time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S")
        chat = chat["id"]
        if sender:
            sender = sender["string"]
        else:
            sender = ""
        try:
            connection = self.pool.get_connection()
            c = connection.cursor()
            c.execute(
                "INSERT INTO " + self.messageTable +
                "(Time, Type, Chat, Sender, Message) VALUES (%s, %s, %s, %s, %s)",
                (time, type, chat, sender, message))
            connection.commit()
            connection.close()
        except:
            self.logError("Error while writing update to the database")

    def sendNotification(self, type, chat, sender, message):
        URL = self.config["IFTTT"]["URL"]
        if URL != "":
            text = "New " + type + " message in " + chat["string"] + (
                " from " +
                sender["string"] if sender else "") + "\n\n" + message
            #print(text)
            data = {"value1": text}
            try:
                response = requests.post(URL, data=data)
                print(response.text)
            except:
                self.logError("Error while sending notification to phone")

    def logError(self, message, fatal=False):

        print(message)
        error = str(sys.exc_info()[0]) + "\n\n" + str(sys.exc_info()[1])
        print(error)
        with open("errors.log", 'a') as logfile:
            logfile.write("\n" + datetime.now().strftime("%Y-%m-%d %H:%M:%S") +
                          " - " + error + "\n\n" +
                          str(traceback.format_exc()) + "\n")
            logfile.write(
                "---------------------------------------------------------------"
            )
        if (fatal):
            #sprint ("\n" + str(traceback.format_exc()))
            raise SystemExit
# pyrogram version => 0.11.0
# this is only useful to fill the session file
import sys

from pyrogram import ChatAction, Client

print("BEGIN")
bot_api_key = open("bot_api_key.txt", "r").read()
print(bot_api_key)
if bot_api_key is None or bot_api_key == "":
    print("MISSING TELEGRAM API KEY")
    sys.exit()
bot_api_key = str(bot_api_key).strip()
app = Client(session_name=bot_api_key, workers=1)
app.start()
app.idle()
Exemple #15
0
def main():
    client = Client("example")
    client.set_update_handler(update_handler)

    client.start()
    client.idle()