def dump_chat(left_chat, full_info, client: TelegramClient): if full_info is None: print( ' > You cannot access full information about this chat. It may be private, or you were removed by an admin.\n' ' > Dumping only information you can access.') print( textwrap.indent(json.dumps(left_chat.to_dict(), indent=4, default=lambda x: x.__repr__()), prefix=' > ')) else: print( textwrap.indent(json.dumps(full_info.to_dict(), indent=4, default=lambda x: x.__repr__()), prefix=' > ')) if isinstance(full_info.full_chat.chat_photo, Photo): if sys.platform == 'linux': resp = input(' > View the current chat photo? [y/N]: ') if resp == 'y': path = client.download_profile_photo( entity=full_info.full_chat, file='/tmp/chat-photo.png') if isinstance(path, str): subprocess.check_output(['xdg-open', path], stderr=subprocess.DEVNULL) else: print( ' > Viewing chat photos is currently only supported on Linux desktop.' ) else: print(' > This chat has no profile picture.')
class Telegram: USER_TYPE_ADMIN = 'admin' USER_TYPE_CREATOR = 'creator' USER_TYPE_PARTICIPANT = 'participant' USER_TYPE_SELF = 'myself' USER_TYPE_UNKNOWN = 'unknown' USER_STATUS_EMPTY = '' USER_STATUS_RECENTLY = 'recently' USER_STATUS_ONLINE = 'online' USER_STATUS_OFFLINE = 'offline' USER_STATUS_LAST_WEEK = 'last week' USER_STATUS_LAST_MONTH = 'last month' USER_STATUS_UNKNOWN = 'unknown' _client: TelegramClient = None phone_number: str = None _api_id: int = None _api_hash: str = None _me: User = None def connect(self, phone_number, api_id, api_hash): self.phone_number = phone_number self._api_id = api_id self._api_hash = api_hash self._client = TelegramClient(phone_number, api_id, api_hash) self._client.connect() self._me = self._client.get_me() def list_channels(self, only_admin=False, list_from_date=None, limit_size=200): channels = [] result = [] dialogs_result = self._client( GetDialogsRequest(offset_date=list_from_date, offset_id=0, offset_peer=InputPeerEmpty(), limit=limit_size, hash=0)) channels.extend(dialogs_result.chats) for channel in channels: if not isinstance(channel, Chat) \ and not isinstance(channel, ChannelForbidden) \ and not isinstance(channel, ChatForbidden): # List all channels or only channels for which we have admin privileges if not only_admin or channel.admin_rights or channel.creator: result.append(channel) return result def list_groups(self, list_from=None, limit_size=200): groups = [] chats_result = [] result = self._client( GetDialogsRequest(offset_date=list_from, offset_id=0, offset_peer=InputPeerEmpty(), limit=limit_size, hash=0)) groups.extend(result.chats) for group in groups: if not isinstance(group, ChatForbidden) and not isinstance( group, ChannelForbidden): if hasattr(group, 'megagroup') and group.megagroup: chats_result.append(group) return chats_result @staticmethod def channel_participant_type(channel_participant): if isinstance(channel_participant, ChannelParticipant): return Telegram.USER_TYPE_PARTICIPANT elif isinstance(channel_participant, ChannelParticipantCreator): return Telegram.USER_TYPE_CREATOR elif isinstance(channel_participant, ChannelParticipantAdmin): return Telegram.USER_TYPE_ADMIN elif isinstance(channel_participant, ChannelParticipantSelf): return Telegram.USER_TYPE_SELF else: return Telegram.USER_TYPE_UNKNOWN @staticmethod def identify_user_status(channel_participant): user_status = channel_participant.status if isinstance(user_status, UserStatusEmpty) or user_status is None: return Telegram.USER_STATUS_EMPTY elif isinstance(user_status, UserStatusRecently): return Telegram.USER_STATUS_RECENTLY elif isinstance(user_status, UserStatusOnline): return Telegram.USER_STATUS_ONLINE elif isinstance(user_status, UserStatusOffline): return Telegram.USER_STATUS_OFFLINE elif isinstance(user_status, UserStatusLastWeek): return Telegram.USER_STATUS_LAST_WEEK elif isinstance(user_status, UserStatusLastMonth): return Telegram.USER_STATUS_LAST_MONTH else: return Telegram.USER_STATUS_UNKNOWN def full_user_info(self, user_id): return self._client(GetFullUserRequest(user_id)) def is_user_authorized(self): return self._client.is_user_authorized() def request_authorization_code(self): self._client.send_code_request(self.phone_number) def verify_authorization_code(self, authorization_code): self._client.sign_in(self.phone_number, authorization_code) def get_channel_participants(self, target_group): return self._client.get_participants(target_group, aggressive=True) def download_profile_photo(self, user, to_file): return self._client.download_profile_photo(user, to_file)
class Sync: """ Sync iterates and receives messages from the Telegram group to the local SQLite DB. """ config = {} db = None def __init__(self, config, session_file, db): self.config = config self.db = db self.client = TelegramClient(session_file, self.config["api_id"], self.config["api_hash"]) self.client.start() if not os.path.exists(self.config["media_dir"]): os.mkdir(self.config["media_dir"]) def sync(self): """ Sync syncs messages from Telegram from the last synced message into the local SQLite DB. """ last_id, last_date = self.db.get_last_message_id() if last_id: logging.info("fetching from last message id={} ({})".format( last_id, last_date)) n = 0 while True: has = False for m in self._get_messages(self.config["group"], offset_id=last_id if last_id else 0): if not m: continue has = True # Inser the records into DB. self.db.insert_user(m.user) if m.media: self.db.insert_media(m.media) self.db.insert_message(m) last_date = m.date n += 1 if n % 300 == 0: logging.info("fetched {} messages".format(n)) self.db.commit() if self.config["fetch_limit"] > 0 and n >= self.config[ "fetch_limit"]: has = False break self.db.commit() if has: last_id = m.id logging.info( "fetched {} messages. sleeping for {} seconds".format( n, self.config["fetch_wait"])) time.sleep(self.config["fetch_wait"]) else: break self.db.commit() logging.info("finished. fetched {} messages. last message = {}".format( n, last_date)) def _get_messages(self, group, offset_id) -> Message: # https://docs.telethon.dev/en/latest/quick-references/objects-reference.html#message for m in self.client.get_messages( group, offset_id=offset_id, limit=self.config["fetch_batch_size"], reverse=True): if not m or not m.sender: continue # Media. sticker = None med = None if m.media: # If it's a sticker, get the alt value (unicode emoji). if isinstance(m.media, telethon.tl.types.MessageMediaDocument) and \ m.media.document.mime_type == "application/x-tgsticker": alt = [ a.alt for a in m.media.document.attributes if isinstance( a, telethon.tl.types.DocumentAttributeSticker) ] if len(alt) > 0: sticker = alt[0] else: med = self._get_media(m) # Message. typ = "message" if m.action: if isinstance(m.action, telethon.tl.types.MessageActionChatAddUser): typ = "user_joined" elif isinstance(m.action, telethon.tl.types.MessageActionChatDeleteUser): typ = "user_left" yield Message(type=typ, id=m.id, date=m.date, edit_date=m.edit_date, content=sticker if sticker else m.raw_text, reply_to=m.reply_to_msg_id if m.reply_to and m.reply_to.reply_to_msg_id else None, user=self._get_user(m.sender), media=med) def _get_user(self, u) -> User: tags = [] if u.bot: tags.append("bot") if u.scam: tags.append("scam") if u.fake: tags.append("fake") # Download sender's profile photo if it's not already cached. avatar = None if self.config["download_avatars"]: try: fname = self._download_avatar(u) avatar = fname except Exception as e: logging.error("error downloading avatar: #{}: {}".format( u.id, e)) return User(id=u.id, username=u.username if u.username else str(u.id), first_name=u.first_name, last_name=u.last_name, tags=tags, avatar=avatar) def _get_media(self, msg): if isinstance(msg.media, telethon.tl.types.MessageMediaWebPage) and \ not isinstance(msg.media.webpage, telethon.tl.types.WebPageEmpty): return Media(id=msg.id, type="webpage", url=msg.media.webpage.url, title=msg.media.webpage.title, description=msg.media.webpage.description if msg.media.webpage.description else None, thumb=None) elif isinstance(msg.media, telethon.tl.types.MessageMediaPhoto) or \ isinstance(msg.media, telethon.tl.types.MessageMediaDocument) or \ isinstance(msg.media, telethon.tl.types.MessageMediaContact): if self.config["download_media"]: logging.info("downloading media #{}".format(msg.id)) try: basename, fname, thumb = self._download_media(msg) return Media(id=msg.id, type="photo", url=fname, title=basename, description=None, thumb=thumb) except Exception as e: logging.error("error downloading media: #{}: {}".format( msg.id, e)) def _download_media(self, msg) -> [str, str, str]: """ Download a media / file attached to a message and return its original filename, sanitized name on disk, and the thumbnail (if any). """ # Download the media to the temp dir and copy it back as # there does not seem to be a way to get the canonical # filename before the download. fpath = self.client.download_media(msg, file=tempfile.gettempdir()) basename = os.path.basename(fpath) newname = "{}.{}".format(msg.id, self._get_file_ext(basename)) shutil.move(fpath, os.path.join(self.config["media_dir"], newname)) # If it's a photo, download the thumbnail. tname = None if isinstance(msg.media, telethon.tl.types.MessageMediaPhoto): tpath = self.client.download_media(msg, file=tempfile.gettempdir(), thumb=1) tname = "thumb_{}.{}".format( msg.id, self._get_file_ext(os.path.basename(tpath))) shutil.move(tpath, os.path.join(self.config["media_dir"], tname)) return basename, newname, tname def _get_file_ext(self, f) -> str: if "." in f: e = f.split(".")[-1] if len(e) < 6: return e return ".file" def _download_avatar(self, user): fname = "avatar_{}.jpg".format(user.id) fpath = os.path.join(self.config["media_dir"], fname) if os.path.exists(fpath): return fname logging.info("downloading avatar #{}".format(user.id)) # Download the file into a container, resize it, and then write to disk. b = BytesIO() self.client.download_profile_photo(user, file=b) im = Image.open(b) im.thumbnail(self.config["avatar_size"], Image.ANTIALIAS) im.save(fpath, "JPEG") return fname
with bot: # bot.send_message('me', 'Hello, myself!') me = bot.get_me() # "me" is an User object. You can pretty-print # any Telegram object with the "stringify" method: print(me.stringify()) # When you print something, you see a representation of it. # You can access all attributes of Telegram objects with # the dot operator. For example, to get the username: username = me.username print(username) print(me.phone) print(bot.download_profile_photo('me')) @bot.on(events.NewMessage(pattern='(?i).*Hello')) async def handler(event): await event.reply('Hey!') raise events.StopPropagation @bot.on(events.NewMessage(pattern='^https:\/\/(www\.)?you.*')) async def handler_link(event): chat = await event.get_chat() sender = await event.get_sender() chat_id = event.chat_id sender_id = event.sender_id downloader = YDownLoader(event.text) downloader.start()
class Sync: """ Sync iterates and receives messages from the Telegram group to the local SQLite DB. """ config = {} db = None def __init__(self, config, session_file, db): self.config = config self.db = db self.client = TelegramClient(session_file, self.config["api_id"], self.config["api_hash"]) self.client.start() if not os.path.exists(self.config["media_dir"]): os.mkdir(self.config["media_dir"]) def sync(self, ids=None): """ Sync syncs messages from Telegram from the last synced message into the local SQLite DB. """ if ids: last_id, last_date = (ids, None) else: last_id, last_date = self.db.get_last_message_id() if ids: logging.info("fetching message id={}".format(ids)) elif last_id: logging.info("fetching from last message id={} ({})".format( last_id, last_date)) group_id = self._get_group_id(self.config["group"]) n = 0 while True: has = False for m in self._get_messages(group_id, offset_id=last_id if last_id else 0, ids=ids): if not m: continue has = True # Inser the records into DB. self.db.insert_user(m.user) if m.media: self.db.insert_media(m.media) self.db.insert_message(m) last_date = m.date n += 1 if n % 300 == 0: logging.info("fetched {} messages".format(n)) self.db.commit() if self.config["fetch_limit"] > 0 and n >= self.config[ "fetch_limit"] or ids: has = False break self.db.commit() if has: last_id = m.id logging.info( "fetched {} messages. sleeping for {} seconds".format( n, self.config["fetch_wait"])) time.sleep(self.config["fetch_wait"]) else: break self.db.commit() logging.info("finished. fetched {} messages. last message = {}".format( n, last_date)) def _get_messages(self, group, offset_id, ids=None) -> Message: # https://docs.telethon.dev/en/latest/quick-references/objects-reference.html#message for m in self.client.get_messages( group, offset_id=offset_id, limit=self.config["fetch_batch_size"], ids=ids, reverse=True): if not m or not m.sender: continue # Media. sticker = None med = None if m.media: # If it's a sticker, get the alt value (unicode emoji). if isinstance(m.media, telethon.tl.types.MessageMediaDocument) and \ hasattr(m.media, "document") and \ m.media.document.mime_type == "application/x-tgsticker": alt = [ a.alt for a in m.media.document.attributes if isinstance( a, telethon.tl.types.DocumentAttributeSticker) ] if len(alt) > 0: sticker = alt[0] elif isinstance(m.media, telethon.tl.types.MessageMediaPoll): med = self._make_poll(m) else: med = self._get_media(m) # Message. typ = "message" if m.action: if isinstance(m.action, telethon.tl.types.MessageActionChatAddUser): typ = "user_joined" elif isinstance(m.action, telethon.tl.types.MessageActionChatDeleteUser): typ = "user_left" yield Message(type=typ, id=m.id, date=m.date, edit_date=m.edit_date, content=sticker if sticker else m.raw_text, reply_to=m.reply_to_msg_id if m.reply_to and m.reply_to.reply_to_msg_id else None, user=self._get_user(m.sender), media=med) def _get_user(self, u) -> User: tags = [] is_normal_user = isinstance(u, telethon.tl.types.User) if is_normal_user: if u.bot: tags.append("bot") if u.scam: tags.append("scam") if u.fake: tags.append("fake") # Download sender's profile photo if it's not already cached. avatar = None if self.config["download_avatars"]: try: fname = self._download_avatar(u) avatar = fname except Exception as e: logging.error("error downloading avatar: #{}: {}".format( u.id, e)) return User(id=u.id, username=u.username if u.username else str(u.id), first_name=u.first_name if is_normal_user else None, last_name=u.last_name if is_normal_user else None, tags=tags, avatar=avatar) def _make_poll(self, msg): options = [{ "label": a.text, "count": 0, "correct": False } for a in msg.media.poll.answers] total = msg.media.results.total_voters if msg.media.results.results: for i, r in enumerate(msg.media.results.results): options[i]["count"] = r.voters options[i][ "percent"] = r.voters / total * 100 if total > 0 else 0 options[i]["correct"] = r.correct return Media(id=msg.id, type="poll", url=None, title=msg.media.poll.question, description=json.dumps(options), thumb=None) def _get_media(self, msg): if isinstance(msg.media, telethon.tl.types.MessageMediaWebPage) and \ not isinstance(msg.media.webpage, telethon.tl.types.WebPageEmpty): return Media(id=msg.id, type="webpage", url=msg.media.webpage.url, title=msg.media.webpage.title, description=msg.media.webpage.description if msg.media.webpage.description else None, thumb=None) elif isinstance(msg.media, telethon.tl.types.MessageMediaPhoto) or \ isinstance(msg.media, telethon.tl.types.MessageMediaDocument) or \ isinstance(msg.media, telethon.tl.types.MessageMediaContact): if self.config["download_media"]: logging.info("downloading media #{}".format(msg.id)) try: basename, fname, thumb = self._download_media(msg) return Media(id=msg.id, type="photo", url=fname, title=basename, description=None, thumb=thumb) except Exception as e: logging.error("error downloading media: #{}: {}".format( msg.id, e)) def _download_media(self, msg) -> [str, str, str]: """ Download a media / file attached to a message and return its original filename, sanitized name on disk, and the thumbnail (if any). """ # Download the media to the temp dir and copy it back as # there does not seem to be a way to get the canonical # filename before the download. fpath = self.client.download_media(msg, file=tempfile.gettempdir()) basename = os.path.basename(fpath) newname = "{}.{}".format(msg.id, self._get_file_ext(basename)) shutil.move(fpath, os.path.join(self.config["media_dir"], newname)) # If it's a photo, download the thumbnail. tname = None if isinstance(msg.media, telethon.tl.types.MessageMediaPhoto): tpath = self.client.download_media(msg, file=tempfile.gettempdir(), thumb=1) tname = "thumb_{}.{}".format( msg.id, self._get_file_ext(os.path.basename(tpath))) shutil.move(tpath, os.path.join(self.config["media_dir"], tname)) return basename, newname, tname def _get_file_ext(self, f) -> str: if "." in f: e = f.split(".")[-1] if len(e) < 6: return e return ".file" def _download_avatar(self, user): fname = "avatar_{}.jpg".format(user.id) fpath = os.path.join(self.config["media_dir"], fname) if os.path.exists(fpath): return fname logging.info("downloading avatar #{}".format(user.id)) # Download the file into a container, resize it, and then write to disk. b = BytesIO() self.client.download_profile_photo(user, file=b) im = Image.open(b) im.thumbnail(self.config["avatar_size"], Image.ANTIALIAS) im.save(fpath, "JPEG") return fname def _get_group_id(self, group): """ Syncs the Entity cache and returns the Entity ID for the specified group, which can be a str/int for group ID, group name, or a group username. The authorized user must be a part of the group. """ # Get all dialogs for the authorized user, which also # syncs the entity cache to get latest entities # ref: https://docs.telethon.dev/en/latest/concepts/entities.html#getting-entities _ = self.client.get_dialogs() try: # If the passed group is a group ID, extract it. group = int(group) except ValueError: # Not a group ID, we have either a group name or # a group username: @group-username pass try: entity = self.client.get_entity(group) except ValueError: logging.critical( "the group: {} does not exist," " or the authorized user is not a participant!".format(group)) # This is a critical error, so exit with code: 1 exit(1) return entity.id
id=[contact_info.id] )) contact_info = result.users[0] res.append(contact_info.id) if contact_info.username is not None: res.append( "@" + contact_info.username) else: res.append(contact_info.username) res.append(contact_info.first_name) res.append(contact_info.last_name) res.append(contact_info.lang_code) if hasattr(contact_info.status, "was_online"): res.append(contact_info.status.was_online.astimezone(pytz.timezone('Europe/Kiev'))) elif str(contact_info.status) == "UserStatusRecently()": res.append("Статус скрыт") else: res.append("Online") res.append(client.download_profile_photo(contact_info.id)) except Exception as err: print(err) bot.send_message(chatId, "Nomer nezaregan ili scrut") exit() masName = ["*Number: *+", "*Telegram ID: *", "*Username: *", "*First_name: *", "*Last_name: *", "*language_code: *", "*Last_Online: *"] resultString = "" for i in range(len(masName)): if str(res[i]) == "None": continue resultString += str(masName[i]) + str(res[i]) + "\n" keyboard = telebot.types.InlineKeyboardMarkup(row_width=1) button = telebot.types.InlineKeyboardButton(text='Проверить WhatsApp', url='https://wa.me/%s'%res[0]) button1 = telebot.types.InlineKeyboardButton(text='Загуглить телефон', url='https://www.google.ru/search?q=+%s'%res[0])