async def answer(message, answer, **kwargs): CONT_MSG = "[continued]\n" ret = [message] if isinstance(answer, str) and not kwargs.get("asfile", False): txt, ent = html.parse(answer) await message.edit(html.unparse(txt[:4096], ent)) txt = txt[4096:] for e in ent: e.offset -= 4096 - len(CONT_MSG) while len(txt) > 0: txt = CONT_MSG + txt message.message = txt[:4096] message.entities = ent message.text = html.unparse(message.message, message.entities) txt = txt[4096:] for e in ent: e.offset -= 4096 - len(CONT_MSG) ret.append(await message.respond(message, parse_mode="HTML", **kwargs)) else: if message.media is not None: await message.edit(file=answer, **kwargs) else: await message.edit("<code>Loading media...</code>") ret = [ await message.client.send_file(message.to_id, answer, reply_to=message.reply_to_msg_id, **kwargs) ] await message.delete()
async def answer(message, response, **kwargs): """Use this to give the response to a command""" cont_msg = "[continued]\n" ret = [message] if isinstance(response, str) and not kwargs.get("asfile", False): txt, ent = html.parse(response) await message.edit(html.unparse(txt[:4096], ent)) txt = txt[4096:] _fix_entities(ent, cont_msg, True) while len(txt) > 0: txt = cont_msg + txt message.message = txt[:4096] message.entities = ent message.text = html.unparse(message.message, message.entities) txt = txt[4096:] _fix_entities(ent, cont_msg) ret.append(await message.respond(message, parse_mode="HTML", **kwargs)) else: if message.media is not None: await message.edit(file=response, **kwargs) else: await message.edit("<code>Loading media...</code>") ret = [ await message.client.send_file(message.chat_id, response, reply_to=message.reply_to_msg_id, **kwargs) ] await message.delete() return ret
def test_entity_edges(): """ Test that entities at the edges (start and end) don't crash. """ text = 'Hello, world' entities = [MessageEntityBold(0, 5), MessageEntityBold(7, 5)] result = html.unparse(text, entities) assert result == '<strong>Hello</strong>, <strong>world</strong>'
def test_malformed_entities(): """ Test that malformed entity offsets from bad clients don't crash and produce the expected results. """ text = '🏆Telegram Official Android Challenge is over🏆.' entities = [ MessageEntityTextUrl(offset=2, length=43, url='https://example.com') ] result = html.unparse(text, entities) assert result == '🏆<a href="https://example.com">Telegram Official Android Challenge is over🏆</a>.'
def test_trailing_malformed_entities(): """ Similar to `test_malformed_entities`, but for the edge case where the malformed entity offset is right at the end (note the lack of a trailing dot in the text string). """ text = '🏆Telegram Official Android Challenge is over🏆' entities = [ MessageEntityTextUrl(offset=2, length=43, url='https://example.com') ] result = html.unparse(text, entities) assert result == '🏆<a href="https://example.com">Telegram Official Android Challenge is over🏆</a>'
def test_entities_together(): """ Test that an entity followed immediately by a different one behaves well. """ original = '<strong>⚙️</strong><em>Settings</em>' stripped = '⚙️Settings' text, entities = html.parse(original) assert text == stripped assert entities == [MessageEntityBold(0, 2), MessageEntityItalic(2, 8)] text = html.unparse(text, entities) assert text == original
async def glitch(e): if e.sender.username == polygon.user.username: await e.delete() if not DATA: polygon.log(f"Initialization required to use {NAME} pack.") return polygon.log(f"{DATE} -- its update day!" + f"\nUpdates chat(s): {DATA['chats']}" + f"\nEvent chat: @{e.sender.username}") if TARGET_DIRECTORY.exists(): shutil.rmtree(TARGET_DIRECTORY) glitch_repository = clone_from_glitch(DATA["git"]) titles = {key: [] for key in DATA["item_types"]} for i in titles: Path.mkdir(TARGET_DIRECTORY / i, exist_ok=True) for chat in DATA["chats"]: async for msg in polygon.iter_messages(chat): content = msg.message or "#" title = content.split()[0][1:] lower_content, lower_title = content.lower(), title.lower() if (not title or not is_required_content(lower_content) or lower_title in map(str.lower, DATA["blocked_items"])): continue for content_type in titles: content_list = titles[content_type] if f"#{content_type}" in lower_content and lower_title not in map( str.lower, content_list): content_list.append(title) path = TARGET_DIRECTORY / content_type / lower_title path.mkdir(exist_ok=True) banner = await get_banner(msg, path) html_content = html.unparse(content, msg.entities) write_webpage( path=path, title=title, content=parse_content( html_content.replace(f"#{title}", "", 1)), banner=banner, ) polygon.log(json.dumps(titles, sort_keys=True, indent=1)) write_webpage( path=GLITCH_FOLDER / "index.html", roms=remove_duplicates(titles["rom"]), kernels=remove_duplicates(titles["kernel"]), recoveries=remove_duplicates(titles["recovery"]), get_random_color=get_random_color, len=len, date=DATE, ) push_to_glitch(glitch_repository) polygon.log("Update completed.")
def test_offset_at_emoji(): """ Tests that an entity starting at a emoji preserves the emoji. """ text = 'Hi\n👉 See example' entities = [ MessageEntityBold(0, 2), MessageEntityItalic(3, 2), MessageEntityBold(10, 7) ] parsed = '<strong>Hi</strong>\n<em>👉</em> See <strong>example</strong>' assert html.parse(parsed) == (text, entities) assert html.unparse(text, entities) == parsed
async def curtana(e): if e.sender.username == polygon.user.username: await e.delete() polygon.log(f"{DATE} -- its update day!" + f"\nUpdates chat(s): {DATA['chats']}" + f"\nEvent chat: @{e.sender.username}") if CWD.exists(): shutil.rmtree(CWD) titles = {key: [] for key in DATA["item_types"]} glitch_repository = clone_from_glitch(DATA["git"]) for chat in DATA["chats"]: async for msg in polygon.iter_messages(chat): content = msg.message or "#" title = content.split()[0][1:] lower_content, lower_title = content.lower(), title.lower() if not title or not is_required_content( lower_content) or lower_title in map( str.lower, DATA["blocked_items"]): continue for content_type in titles: content_list = titles[content_type] if f"#{content_type}" in lower_content and lower_title not in map( str.lower, content_list): content_list.append(title) banner = await get_banner(msg, title) html_content = html.unparse(content, msg.entities) write_webpage(title=title, content=parse_content( html_content.replace(f"#{title}", "", 1)), banner=banner) polygon.log(json.dumps(titles, sort_keys=True, indent=1)) write_webpage(title="index.html", roms=remove_duplicates(titles["rom"] + titles["port"] + titles["gsi"]), kernels=remove_duplicates(titles["kernel"]), recoveries=remove_duplicates(titles["recovery"]), get_random_color=get_random_color, len=len, date=DATE) push_to_glitch(glitch_repository) polygon.log("Update completed.") polygon.log(f"Waking up {DOMAIN}..") try: r = requests.head(f"http://{DOMAIN}") except requests.exceptions.ConnectionError: polygon.log(f"Couldn't establish a connection with {DOMAIN}") else: polygon.log(f"Done with {r}")
async def download_messages(self, dialog, conversation_in_db, min_id=0, max_id=0): """Download messages in the given conversation.""" options = dict(max_id=max_id, min_id=min_id) async for message in self.client.iter_messages(dialog, **options): # Ignore service messages like `User X was added to chat Y'. if message.message: self.get_or_create_message( conversation=conversation_in_db, external_id=message.id, html=unparse(message.message, message.entities), recipient=self.recipient_to_contact(message.to_id), sender=self.sender_to_contact(message.sender), text=message.message, timestamp=message.date, ) # Commit changes to disk every now and then. if self.stats.messages_added % 100 == 0: self.archive.commit_changes()
async def answer(message, response, **kwargs): """Use this to give the response to a command""" if isinstance(message, list): delete_job = asyncio.ensure_future(message[0].client.delete_messages( message[0].input_chat, message[1:])) message = message[0] else: delete_job = None if await message.client.is_bot() and isinstance( response, str) and len(response) > 4096: kwargs.setdefault("asfile", True) kwargs.setdefault("link_preview", False) cont_msg = "[continued]\n" edit = message.out if not edit: kwargs.setdefault( "reply_to", message.reply_to_msg_id if await message.get_reply_message() else message.id) parse_mode = telethon.utils.sanitize_parse_mode( kwargs.pop("parse_mode", message.client.parse_mode)) if isinstance(response, str) and not kwargs.pop("asfile", False): txt, ent = parse_mode.parse(response) logging.debug(txt) logging.debug(ent) ret = [ await (message.edit if edit else message.respond) (txt[:4096], parse_mode=lambda t: (t, ent), **kwargs) ] txt = txt[4096:] _fix_entities(ent, cont_msg, True) while len(txt) > 0: txt = cont_msg + txt message.message = txt[:4096] message.entities = ent message.text = html.unparse(message.message, message.entities) txt = txt[4096:] _fix_entities(ent, cont_msg) ret.append(await (message.reply if edit else message.respond) (message, parse_mode=lambda t: (t, ent), **kwargs)) elif isinstance(response, Message): if message.media is None and (response.media is None or isinstance( response.media, MessageMediaWebPage)): ret = (await message.edit(response.message, parse_mode=lambda t: (t, response.entities or []), link_preview=isinstance( response.media, MessageMediaWebPage)), ) else: txt = "<b>Loading message...</b>" new = await (message.edit if edit else message.reply)(txt) ret = (await message.respond(response, **kwargs), ) await new.delete() else: if isinstance(response, bytes): response = io.BytesIO(response) if isinstance(response, str): response = io.BytesIO(response.encode("utf-8")) name = kwargs.pop("filename", None) if name: response.name = name if message.media is not None and edit: await message.edit(file=response, **kwargs) else: txt = "<b>Loading media...</b>" # TODO translations new = await (message.edit if edit else message.reply)(txt) kwargs.setdefault( "reply_to", message.reply_to_msg_id if await message.get_reply_message() else message.id) ret = (await message.client.send_file(message.chat_id, response, **kwargs), ) await new.delete() if delete_job: await delete_job return ret
async def mothrix(event: events.NewMessage.Event): m = event.message html = unparse(m.message, m.entities) await event.edit(html, parse_mode=moothrix_parse)