Embedding Telegram post as a component?

Hi folks, I’m trying to extend the pattern used for displaying a twitter post as a component to display a Telegram post. Telegram doesn’t use the oEmbed mechanism, seems to only work by embedding a script tag, which then loads an iFrame and various scripts to display the post.

Problem: The post content is not visible in the streamlit component. When inspecting the DOM, I see that Telegram iFrame has been created inside the component iFrame, but it is not visible. Any suggestions? Is something in streamlit preventing the script from fully executing.

I’ve also tried directly writing the <script> block using st.write etc.

Here is the example code i’ve been working with:

import streamlit as st
import streamlit.components.v1 as components


class TelegramEmbed(object):
    """
    Display the embedded telegram widge for a public telegram url
    as per https://core.telegram.org/widgets/post

    Based on https://discuss.streamlit.io/t/dispalying-a-tweet/16061
    """

    @st.cache_data(ttl=3600)
    def fetch_telegram_embed_html(t_url: str):
        # https://core.telegram.org/widgets/post
        # split off the t.me part to get the post id.
        # so https://t.me/EarthJusticeLeague_DataLibrary/11687
        # becomes EarthJusticeLeague_DataLibrary/11687
        post_id = t_url.replace("https://t.me/", "")
        html = f"""
        <script async src="https://telegram.org/js/telegram-widget.js?22" 
        data-telegram-post="{post_id}" data-width="100%"></script>
        """
        return html

    def __init__(self, t_url, embed_str=False):
        if not embed_str:
            self.text = TelegramEmbed.fetch_telegram_embed_html(t_url)
        else:
            self.text = f"""
            <a href='{t_url}' target="_blank" rel="noopener noreferrer">view on Telegram</a>
            """

    def _repr_html_():
        """
        This seems to be needed to work around a bug
        """
        return ""

    def component(self):
        return components.html(self.text, height=600)

I notice that the iFrame seems to be loading inside the element of the component iFrame.

It seems to display correctly if I edit the DOM to move the telegram iframe into the body of the component iframe. How do I get it to render there?

Since seems like this is loading into wrong DOM element, opened bug for it Compontent iframe html inserted in iframe <head> instead of <body> · Issue #8045 · streamlit/streamlit · GitHub

@ kajarenc provided the elegant solution of just explicitly wrapping the content in tags before passing it to the iframe!

return components.html(f"<body>{self.text}</body>", height=800)
1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.