def start_sync(): """Start tgcf live sync.""" # pylint: disable=import-outside-toplevel from telethon.sync import TelegramClient, functions, types client = TelegramClient(config.SESSION, config.API_ID, config.API_HASH) client.start(bot_token=config.BOT_TOKEN) is_bot = client.is_bot() for key, val in ALL_EVENTS.items(): if key.startswith("bot"): if not is_bot: continue if config.CONFIG.live.delete_sync is False and key == "deleted": continue client.add_event_handler(*val) logging.info(f"Added event handler for {key}") if is_bot and const.REGISTER_COMMANDS: client( functions.bots.SetBotCommandsRequest( commands=[ types.BotCommand(command=key, description=value) for key, value in const.COMMANDS.items() ] ) ) client.run_until_disconnected()
def start_bot(API_ID: int, API_HASH: str, name: str, token: str): os.makedirs(name, exist_ok=True) os.chdir(name) download_image(url=conf.config.watermark) client = TelegramClient(name, API_ID, API_HASH).start(bot_token=token) client( functions.bots.SetBotCommandsRequest(commands=[ types.BotCommand(command=key, description=value) for key, value in conf.COMMANDS.items() ])) for key, val in ALL_EVENTS.items(): print(f"Adding event {key}") client.add_event_handler(*val) print(f"Started bot {name}") client.run_until_disconnected()
from telethon.sync import TelegramClient from plugins import hello, result client = TelegramClient('anon', 123, '123') client.start() client.add_event_handler(hello.haste) client.add_event_handler(result.find) client.run_until_disconnected()
class CoronaBot(object): def __init__(self, apiId, apiHash) -> None: self.bot = TelegramClient('CoronaWHVBot', apiId, apiHash) self.bot.add_event_handler(self.onStartMessage, events.NewMessage(pattern="/start")) self.bot.add_event_handler(self.onStopMessage, events.NewMessage(pattern="/stop")) self.bot.add_event_handler(self.onRegionResetMessage, events.NewMessage(pattern="/resetRegion")) self.bot.add_event_handler( self.onRegularMessage, events.NewMessage(pattern="^(?!(/start|/stop|/resetRegion).*$).*")) self.userStore = UserStore() self.dataStoreProvider = RegionSourceProvider() def __del__(self): self.stop() async def start(self, token): return await self.bot.start(bot_token=token) async def stop(self): self.userStore.close() asyncio.get_running_loop().run_until_complete(self.bot.disconnect()) print("Bot stoped and database closed") async def onStartMessage(self, event): sender = event.input_sender try: print(self.userStore.getUser(sender.user_id, sender.access_hash)) self.userStore.addUserToDB(sender.user_id, sender.access_hash) print("added user") await event.respond( "Für welches Gebiet willst du jeden Morgen um 09:00 Nachrichten erhalten?\n\nBitte gebe zunächst die Art der Region an!", buttons=getRegionTypeKeyboard()) except Exception as e: await event.respond( "Irgendwas hat nicht funktioniert! Probiere nochmal \"/start\" oder kontaktiere den Admin", buttons=getDisabledKeyboard()) print("adding went wrong", e) async def onStopMessage(self, event): sender = event.input_sender try: self.userStore.removeUserFromDB(sender.user_id, sender.access_hash) print("removed user") await event.respond( "Du wurdest erfolgreich entfernt, du wurst nun keine Nachrichten mehr erhalten!", buttons=getDisabledKeyboard()) except Exception as e: await event.respond( "Das entfernen hat nicht funktioniert. Du wirst weiterhin Nachrichten erhalten!", buttons=getDefaultKeyboard()) print("deleting went wrong!", e) async def onRegionResetMessage(self, event): sender = event.input_sender try: self.userStore.removeRegionOfUser(sender.user_id, sender.access_hash) print("removed user") await event.respond( "Deine Region wurde erfolgreich entfernt. Für welche Region willst du ab jetzt Nachrichten erhalten?\n\nBitte gebe zunächst die Art der Region an!", buttons=getRegionTypeKeyboard()) except Exception as e: await event.respond( "Das entfernen hat nicht funktioniert. Du wirst weiterhin Nachrichten erhalten!", buttons=getDefaultKeyboard()) async def onRegularMessage(self, event): sender = event.input_sender databaseUser = self.userStore.getUser(sender.user_id, sender.access_hash) if (databaseUser[2] == None): await self.tryAddRegionType(event, databaseUser) elif (databaseUser[3] == None): await self.tryAddRegionName(event, databaseUser) else: await event.reply("Ich weiß nicht was ich tun soll!") async def tryAddRegionType(self, event, databaseUser): regionType = event.message.message isRegionType = any( map(lambda b: b.button.text == event.message.message, flatten(getRegionTypeKeyboard()))) if (not isRegionType): await event.respond("Das war kein erlaubte Regionsart!", buttons=getRegionTypeKeyboard()) else: try: self.userStore.setRegionTypeOfUser(databaseUser[0], databaseUser[1], regionType) await event.respond( "Schreibe jetzt bitte den Namen der Region!", buttons=Button.clear()) except Exception as e: print("region type saving failed", e) await event.respond( "Beim Speichern ist etwas schief gelaufen, versuche es nochmal oder kontaktiere den Admin" ) async def tryAddRegionName(self, event, databaseUser): name = event.message.message region = Region(databaseUser[2], None) possibleNames = [ n.lower() for n in self.dataStoreProvider.getPossibleNameForRegionType(region) ] if (name.lower() in possibleNames): await event.respond( "Alles klar, ab jetzt bekommst du jeden Morgen um 09:00 eine Nachricht über die aktuelle Lage!", buttons=getDefaultKeyboard()) self.userStore.setRegionNameOfUser(databaseUser[0], databaseUser[1], name) else: me = "Ich habe diesen Ort nicht gefunden!" bs = Button.clear() closeMatches = list( difflib.get_close_matches(name, possibleNames, n=5)) if (len(closeMatches) > 0): bs = getKeyboardFromList( map(lambda n: n.capitalize(), closeMatches)) me += "\n\nMeinst du vielleicht:\n" for m in closeMatches: me += " - %s\n" % (m.capitalize()) await event.respond(me, buttons=bs) async def sendMessageToAll(self, message): users = self.userStore.getAllActiveUsers() for u in users: peer = InputPeerUser(u[0], u[1]) try: await self.bot.send_message(peer, message, parse_mode="html") except UserIsBlockedError: self.userStore.removeUserFromDB(u[0], u[1]) async def sendUpdateToAll(self): print("Sending Number Update to all users") users = filter(lambda u: u[2] != None and u[3] != None, self.userStore.getAllActiveUsers()) for user in users: peer = InputPeerUser(user[0], user[1]) try: message = getMessage( self.dataStoreProvider.getSourceFromRegion( Region(user[2], user[3]))) try: await self.bot.send_message(peer, message, parse_mode="html") except UserIsBlockedError: self.userStore.removeUserFromDB(user[0], user[1]) except: pass print("all messages send") async def runUntilDisconnect(self): return await self.bot.run_until_disconnected()
class Controller: albums = {} active_posting = True def __init__(self, session, api_id, api_hash, mode, proxy=None): """ Initializes the InteractiveTelegramClient. :param session: Name of the *.session file. :param api_id: Telegram's api_id acquired through my.telegram.org. :param api_hash: Telegram's api_hash. :param mode: development or production mode :param proxy: Optional proxy tuple/dictionary. """ if mode == "dev": self.client = TelegramClient( session, api_id, api_hash, proxy=proxy, connection=connection. ConnectionTcpMTProxyRandomizedIntermediate) elif mode == "prod": self.client = TelegramClient(session, api_id, api_hash) # Use the client in a `with` block. It calls `start/disconnect` automatically. self.database = Database() with self.client: self.client.add_event_handler( self.forward_album_legacy, events.NewMessage(from_users=('@Ordicyn', '@lazycat90210'), func=lambda e: e.grouped_id)) self.client.add_event_handler( self.forward_msg, events.NewMessage(from_users=('@Ordicyn', '@lazycat90210'), func=lambda e: e.grouped_id is None)) # Task to print alive-messages every 5 minutes loop.create_task(self.print_forever()) # Task to grab the most popular posts from channels (table "channels") every day at 08:00 GMT+3 loop.create_task(self.do_dump_schedule()) # Task to post 2 times in hour 3 random media from posts (table "posts") in period 09:00-23:00 GMT+3 loop.create_task(self.do_post_schedule()) self.client.run_until_disconnected() async def forward_album_legacy(self, event): logger.info('Recieved message with album') await event.mark_read() pair = (event.chat_id, event.grouped_id) if pair in self.albums: self.albums[pair].append(event.message) return self.albums[pair] = [event.message] await asyncio.sleep(0.3) messages = self.albums.pop(pair) logger.info('%s %s', 'Album contains photos:', str(len(messages))) await event.respond(f'Got {len(messages)} photos!') medias = [] for msg in messages: medias.append(msg.media) await self.client.send_file( chat, medias, caption='✅ [Сохранёнки](https://t.me/savedmemess)') async def forward_msg(self, event): await event.mark_read() logger.info('%s %s', "Event", str(event)) sender = await event.get_sender() logger.info('%s %s', "Recieved new message for forwarding from", str(sender.username)) msg = event.message logger.info('%s %s', "Message", str(msg)) if msg.media is not None and (isinstance(msg.media, MessageMediaPhoto) or isinstance(msg.media, MessageMediaDocument)): logger.info('Message contains media photo or video') media = msg.media await self.client.send_file( chat, media, caption='✅ [Сохранёнки](https://t.me/savedmemess)') else: logger.info("Message doesn't contain media photo or video") if msg.message.lower() == 'help': logger.info('Message is help request') with codecs.open('help.html', "r", encoding='utf-8') as help_file: help_msg = help_file.read() await event.respond(help_msg, parse_mode='html') elif msg.message.lower() == 'list': logger.info('Message is channels list request') try: channels = self.database.getAllChannels() response = "Now is listening following channels:\n" + "\n".join( map(str, channels)) logger.info(response) await event.respond(message=response, link_preview=False) except Exception as ex: error_msg = "Failed to get chanel list with exception: " + str( ex) logger.error(error_msg) elif msg.message.lower().startswith('add'): logger.info('Message is request to add channel to list') try: channel_url = msg.message.lower().split(' ')[1] channel_entity = await self.client.get_entity(channel_url) if self.database.getChannelByID(channel_entity.id) is None: channel = Channel(channel_entity.id, channel_entity.title, channel_url, True) self.database.addChannel(channel) success_msg = channel_entity.title + ' was added to database. Dumping will start at 8:00 GMT+3' logger.info(success_msg) await event.respond(success_msg) else: error_msg = 'Channel with ID ' + str( channel_entity.id) + ' already in database' logger.error(error_msg) await event.respond(error_msg) except Exception as ex: error_msg = "Failed to add channel to list with exception: " + str( ex) logger.error(error_msg) await event.respond(error_msg) elif msg.message.lower().startswith('delete'): logger.info('Message is request to delete channel from list') try: channel_id = msg.message.lower().split(' ')[1] if self.database.getChannelByID(channel_id) is not None: channel_entity = await self.client.get_input_entity( self.database.getChannelByID(channel_id).link) await self.client( LeaveChannelRequest(channel=channel_entity)) self.database.delChannelByID(channel_id) success_msg = channel_id + ', channel with this id was successfully deleted from the database.' \ 'Media from this channel was deleted too and bot leave channel' logger.info(success_msg) await event.respond(success_msg) else: error_msg = 'Channel with ID ' + str( channel_id) + ' not in database' logger.error(error_msg) await event.respond(error_msg) except Exception as ex: error_msg = "Failed to delete channel from list with exception: " + str( ex) logger.error(error_msg) await event.respond(error_msg) elif msg.message.lower() == 'dump': logger.info( 'Message is request dump messages from channel manually') try: await self.do_dump() success_msg = 'Request dump messages from channel manually was handled success' logger.info(success_msg) await event.respond(success_msg) except Exception as ex: error_msg = "Failed dump messages from channels " + str(ex) logger.error(error_msg) await event.respond(error_msg) elif msg.message.lower() == 'post': logger.info('Message is request to do 3 posts manually') try: await self.do_post() success_msg = 'Request to do 3 posts manually was handled success' logger.info(success_msg) await event.respond(success_msg) except Exception as ex: error_msg = "Failed to do 3 posts manually " + str(ex) logger.error(error_msg) await event.respond(error_msg) elif msg.message.lower() == 'start': logger.info('Message is request to start automatic posting') if self.active_posting is True: logger.info('Automatic posting is active already') await event.respond('Automatic posting is active already') else: self.active_posting = True logger.info('Automatic posting is set true') await event.respond('Automatic posting is set true') elif msg.message.lower() == 'stop': logger.info('Message is request to stop automatic posting') if self.active_posting is False: logger.info('Automatic posting is stop already') await event.respond('Automatic posting is stop already') else: self.active_posting = False logger.info('Automatic posting stopped') await event.respond('Automatic posting stopped') elif msg.message.lower() == 'stats': logger.info('Message is request to get bot statistic') try: logger.info('Get information about posts database') total, posted, not_posted = self.database.getPostsInfo() msg = 'Bot statistic:\nPost database contains posts: ' + str( total) + '\nPosted count: ' + str( posted) + '\nNot posted count: ' + str( not_posted ) + '\nInformation about last 10 revisions:\n' logger.info('Get information about last 10 revisions') revisions = self.database.getLast10Revisions() for revision in revisions: msg += 'Channel ID: ' + str(revision[0]) + ', channel name: ' + revision[1] + ', collected: ' \ + str(revision[2]) + ', time(GMT+3): ' \ + str( revision[3].astimezone(pytz.timezone("Europe/Moscow")).strftime("%Y-%m-%d %H:%M:%S")) + '\n' # print(revisions) logger.info(msg) await event.respond(msg) except Exception as ex: error_msg = "Failed to to get bot statistic " + str(ex) logger.error(error_msg) await event.respond(error_msg) else: logger.info('Command is unrecognized. Use help command') await event.respond('Command is unrecognized. Use help command' ) async def join_channel(self): channels = self.database.getAllChannels() for channel in channels: try: await self.client(JoinChannelRequest(channel.channel_id)) logger.info('%s %s', 'success join to the channel', channel.title) except Exception as ex: logger.error('%s %s %s', 'failed join to the channel', channel.title, str(ex)) async def do_dump_schedule(self): while True: logger.info("Get current time in UTC") current_time_utc = datetime.time(datetime.now(pytz.utc)) logger.info('%s %s', 'Now: ', str(current_time_utc)) dump_time_utc = time(hour=5, minute=0) if current_time_utc <= dump_time_utc: logger.info("Current time less than 08:00 GMT+3(05:00 UTC)") remaining = ( datetime.combine(datetime.date(datetime.now(pytz.utc)), dump_time_utc) - datetime.combine(datetime.date(datetime.now(pytz.utc)), current_time_utc)).total_seconds() else: logger.info("Current time greater than 08:00 GMT+3(05:00 UTC)") remaining = (datetime.combine( datetime.date(datetime.now(pytz.utc)) + timedelta(days=1), dump_time_utc) - datetime.combine( datetime.date(datetime.now(pytz.utc)), current_time_utc)).total_seconds() logger.info('%s %s', "Now go sleep for: ", str(remaining)) await asyncio.sleep(remaining) logger.info('Now 08:00 GMT+3. Dump process wake up!') try: await self.do_dump() except Exception as ex: error_msg = "Failed dump messages from channels " + str(ex) logger.error(error_msg) async def do_dump(self): logger.info('Task#1 - clear messages table') try: r = self.database.clearPosts() logger.info('%s %s', str(r), ' posts was cleared') except Exception as ex: error_msg = "Failed to clear messages table with exception: " + str( ex) logger.error(error_msg) logger.info('Task#2 - join to channels') try: await self.join_channel() except Exception as ex: error_msg = "Failed to join to channels with exception: " + str(ex) logger.error(error_msg) logger.info( 'Task#3 - Get last 200 messages from channels in date range' ' [current date-1 21:00; current date-2 21:00]') # Current date in UTC current_date = datetime.date(datetime.now(pytz.utc)) logger.info('%s %s', 'Current date in UTC ', str(current_date)) # 18:00 in UTC = 21:00 in GMT + 3 time_dump = time(hour=18, minute=0) # before datetime = current date-1 21:00 dt_before = datetime.combine(current_date - timedelta(days=1), time_dump).replace(tzinfo=pytz.UTC) logger.info('%s %s', 'before datetime = current date-1 21:00 ', str(dt_before)) # after datetime = current date-2 21:00 dt_after = datetime.combine(current_date - timedelta(days=2), time_dump).replace(tzinfo=pytz.UTC) logger.info('%s %s', 'after datetime = current date-2 21:00 ', str(dt_after)) # global posts list posts_list_global = [] try: logger.info('Get actual channel list') channels = self.database.getAllChannels() for channel in channels: logger.info('%s %s', 'Try to dump message from channel', channel.title) try: logger.info('This channel hasnt been dumped yet') logger.info('Init telethon request') channel_entity = await self.client.get_input_entity( channel.channel_id) posts_list = [] # Get first 100 messages logger.info('Get first 100 messages') posts = await self.client( GetHistoryRequest(peer=channel_entity, limit=100, offset_date=dt_before, offset_id=0, max_id=0, min_id=0, add_offset=0, hash=0)) logger.info('%s %s', 'Got messages: ', str(len(posts.messages))) posts_list.extend(posts.messages) offset_id = posts_list[99].id logger.info('%s %s', 'Offset message id: ', str(offset_id)) logger.info('Get another 100 messages') posts = await self.client( GetHistoryRequest(peer=channel_entity, limit=100, offset_date=dt_before, offset_id=offset_id, max_id=0, min_id=0, add_offset=0, hash=0)) logger.info('%s %s', 'Got messages: ', str(len(posts.messages))) posts_list.extend(posts.messages) logger.info('%s %s', 'Totally got messages: ', str(len(posts_list))) logger.info( 'Filter messages that not album with media photo or video and text without invite link and not reply' ) filtered_posts_list = list( filter( lambda msg: (dt_after <= msg.date and dt_before >= msg.date ) and (msg.grouped_id is None) and (msg.media is not None) and (msg.reply_markup is None) and (isinstance(msg.media, MessageMediaPhoto) or isinstance(msg.media, MessageMediaDocument)) and (not any(s in msg.message for s in ["https", ".shop", ".com", ".ru"])), posts_list)) logger.info('%s %s', 'After filtering messages list contain: ', str(len(filtered_posts_list))) # for x in filtered_posts_list: logger.info(str(x)) logger.info( 'Sort list by views and save 50% first more popular post to global' ) filtered_posts_list.sort(key=lambda msg: msg.views, reverse=True) # for x in filtered_posts_list[:int(len(filtered_posts_list)/2)]: logger.info(str(x)) posts_list_global.extend( filtered_posts_list[:int(len(filtered_posts_list) / 2)]) logger.info( '%s %s', 'Add revision record about channel for this date', channel.title) revision = Revision(channel.channel_id, datetime.now(pytz.utc), len(filtered_posts_list)) try: self.database.addRevision(revision) except Exception as ex: error_msg = "Failed to store revision to database with exception " + str( ex) logger.error(error_msg) except Exception as ex: error_msg = "Failed to dump message from channel " + channel.title + " : " + str( ex) logger.error(error_msg) except Exception as ex: error_msg = "Failed to get last 200 messages from channels in general: " + str( ex) logger.error(error_msg) logger.info('%s %s', 'Totally from all channels got messages: ', str(len(posts_list_global))) logger.info('Task#4 - Now we should cast class Message to Posts') logger.info('Now we should cast class Message to Post') # logger.info(posts_list_global[0]) filtered_posts_list_global_in_post = list( map( lambda msg: Post(msg.to_id.channel_id, msg.id, "", msg.date, False), posts_list_global)) # for x in filtered_posts_list_global_in_post: print(x) self.database.addPosts(filtered_posts_list_global_in_post) # for post in filtered_posts_list_global_in_post: # await self.client.send_file('test_channel_5', pickle.loads(post.media), # caption='✅ [Сохранёнки](https://t.me/savedmemess)') # await asyncio.sleep(5) # await asyncio.sleep(80) async def do_post_schedule(self): while True: logger.info( "Function post 2 times in hour 3 random media from database in period 09:00-23:00 GMT+3 " "or 06:00-20:00 UTC") logger.info("Get current time in UTC") current_time_utc = datetime.time(datetime.now(pytz.utc)) logger.info('%s %s', 'Now: ', str(current_time_utc)) after_time_utc = time(hour=6, minute=0) before_time_utc = time(hour=20, minute=0) if current_time_utc < after_time_utc: logger.info("Current time less than 09:00 GMT+3(06:00 UTC)") remaining = ( datetime.combine(datetime.date(datetime.now(pytz.utc)), after_time_utc) - datetime.combine(datetime.date(datetime.now(pytz.utc)), current_time_utc)).total_seconds() logger.info('%s %s', "Now go sleep for: ", str(remaining)) await asyncio.sleep(remaining) if current_time_utc > before_time_utc: logger.info("Current time greater than 23:00 GMT+3(20:00 UTC)") remaining = (datetime.combine( datetime.date(datetime.now(pytz.utc)) + timedelta(days=1), after_time_utc) - datetime.combine( datetime.date(datetime.now(pytz.utc)), current_time_utc)).total_seconds() logger.info('%s %s', "Now go sleep for: ", str(remaining)) await asyncio.sleep(remaining) else: if self.active_posting is True: logger.info('Automatic posting is active now') # self.database.printAllPosts() logger.info("Time to post!") await self.do_post() logger.info("Done! Now sleep for 29 minutes") await asyncio.sleep(1740) else: logger.info('Automatic posting is inactive now') logger.info("Now sleep for 30 minutes") await asyncio.sleep(1800) async def do_post(self): for i in range(0, 3): try: post = self.database.getRandomPost() logger.info("Select from database following random post:") logger.info(str(post)) logger.info("Trying to retrive message from channel:") channel_entity = await self.client.get_input_entity( post.channel_id) logger.info(str(channel_entity)) msg = await self.client( GetMessagesRequest(channel=channel_entity, id=[post.message_id])) logger.info(str(msg)) media = msg.messages[0].media await self.client.send_file( bot, media, caption='✅ [Сохранёнки](https://t.me/savedmemess)') logger.info("Post was send. Now mark it in database as marked") try: self.database.setPostPosted(post) except Exception as ex: error_msg = "Failed with exception: " + str(ex) logger.error(error_msg) except Exception as ex: error_msg = "Failed to post exception: " + str(ex) logger.error(error_msg) finally: await asyncio.sleep(5) async def print_forever(self): while True: logger.info("Await(alive) function") current_time_utc = datetime.time(datetime.now(pytz.utc)) logger.info('%s %s', 'Now: ', str(current_time_utc)) await asyncio.sleep(300)
import asyncio from decouple import config # Defining the need variables api_id = config('API_ID') #Input your api_id here api_hash = config('API_HASH') #Input your api_hash here loop = asyncio.new_event_loop() client = TelegramClient('runner', api_id, api_hash, loop=loop) client.start() channel = client.get_input_entity('https://t.me/techguided') chat = InputPeerChannel( channel_id=channel.channel_id, access_hash=channel.access_hash) # Input channel id and access_hash # import pdb; pdb.set_trace() channel = client.get_entity(1270515419) # Handler to receive the channel message @client.on(events.NewMessage(incoming=True)) async def handler(event): await client.send_message('codefred', f'{event.stringify()}') client.add_event_handler(handler) # Run endlessly client.run_until_disconnected()
myfile.write(data) myfile.close() zip_file.close() async def hey(event): reply_message = await event.get_reply_message() await event.reply("Starting to part the files please wait...") name = await bot.download_media(reply_message,"./") dir = str(uuid4()) os.mkdir(dir) await unzipper(dir,name) files = list(absoluteFilePaths(dir)) n = 30 k = [files[i:i + n] for i in range(0, len(files), n)] ids = [] for i in k: zipname = str(uuid4())+".zip" print(zipname) ids.append(zipname) await zipper(i,zipname) for id in ids: await event.reply(file=id) os.system("rm -rf *") print("---Started bot---") bot.add_event_handler(hey,events.NewMessage(pattern="/part")) bot.run_until_disconnected()
async def unsubscribe(msg): """Unsubscribe and add to list""" user = await client.get_sender() # Import users from pending list pending = pend.get_all_records() if user.id not in pending[3]: # Adding to spreadsheet index = int(len(unsub.get_all_records()) + 2) time.sleep(1) unsub.insert_row([ f'{user.first_name}', f'{user.last_name}', f'{user.username}', f'{user.id}' ], index=index) time.sleep(2) await client.send_message(admin[0], f"{user.username} Unsubscribed") position = pending[3].index(str(user.id)) pending.delete_row(index=position) print("Bot running") client.add_event_handler(unsubscribe) client.run_until_disconnected() while True: pass