Skip to content

Instantly share code, notes, and snippets.

@imsus
Created February 6, 2019 10:13
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imsus/9323848eac3eac4afe412f5d43ee0ea5 to your computer and use it in GitHub Desktop.
Save imsus/9323848eac3eac4afe412f5d43ee0ea5 to your computer and use it in GitHub Desktop.
Telegram Instant View Boilerplate
# This sample template explores how we can turn the Telegram blog post on the left into an Instant View page as shown on the right — in several simple steps. If you're unsure what some of the elements used here do, check out the full documentation here: https://instantview.telegram.org/docs
# Place the version at the beginning of template. We recommend always using the latest available version of Instant View.
~version: "2.0"
### STEP 1: Define which pages get Instant View and which don't
# That's easy because we only need IV pages for posts on the Telegram blog.
# This *condition* does the trick.
# ?path: /blog/.+
# All pages on telegra.ph are articles, with one exception: the main page is blank and lets you create new articles.
# This *condition* tells our Instant View bot to apply rules to all pages except the root page, telegra.ph/
# ?path: /.+
# We only want to generate Instant View pages for articles. Other things, like lists of articles, profiles, the about section, etc. should be ignored.
# Conveniently, all article pages on Medium seem to have a <meta property="article:published_time"> tag.
# If this tag is not present, we'll assume that the page is not an article and does not require an Instant View page.
# This *condition* does the trick:
# ?exists: /html/head/meta[@property="article:published_time"]
### STEP 2: Define the essential elements
# Now we'll start filling up the IV page.
# To make things easier, we'll begin by storing the actual body of the post in a *variable* before we start our manipulations.
# $main: //div[@id="dev_page_content_wrap"]
# The 'title' and 'body' *properties* are required for an Instant View page to work, so we'll define those two.
# title: $main//h1[1]
# body: //div[@id="dev_page_content"]
# While we're at it, we'll move the signature to the top of the page.
# author: "Telegram"
### Now to set the cover image. This isn't required, but we need a cover image if we want our Instant view page to look cool.
# Telegram blog posts always have their cover in a div of the "blog_wide_image" class, so we'll look for that one.
# cover: $main//*[has-class("blog_wide_image")]//img
# Note that 'cover:' is a *property*, so by default it will not be overwritten after we've assigned a value to it for the first time. This means that the rule below will not be applied if the first one already hit the target.
# Read more about properties here: https://instantview.telegram.org/docs#properties
# cover: $main//img[has-class("blog_wide_image")]
### Set the link preview image. Links shared via Telegram will show an extended preview with a small picture. We'll also use the cover as the image in those previews.
# image_url: $cover/self::img/@src
# But we've only introduced covers to our blog posts in the Fall of 2016.
# So for any old posts that don't have a cover, we'll use the smaller monochromatic image for link previews (but not for the cover, they're too small).
# $side_image: $main//img[has-class("blog_side_image")]
# image_url: $side_image/@src
# Regardless of whether we're using a cover image or not, there's no proper space for the small monochromatic image on the IV page.
# So we'll just get rid of it using the '@remove' *function*.
# @remove: $side_image
# Properly display media and the respective captions.
# Replace //div tags with <figcaption> and <figure> tags.
# <figcaption>: $body//div[has-class("blog_image_wrap")]/p
# <figure>: $body//div[has-class("blog_image_wrap")]
# <figure>: $body//div[has-class("blog_side_image_wrap")]
# <figure>: $body//div[has-class("smartphone_video_player_wrap")]
# Now we'll start filling up the IV page.
# To make things easier, we begin by setting up some *variables* before we start our manipulations.
# $header: //header
# body: //article
# By default sequences of whitespaces are collapsed into a single whitespace by the browser. The IV bookworm bot does this too, but Telegra.ph preserves whitespaces in the entire article node.
# So we'll use the '@pre' *function* to instruct the IV bot to preserve whitespaces in all of these nodes.
# @pre: $body//*
# Now to fill the essential properties
# title: $body//h1
# subtitle: $body//h2
# author: $header//address/a[@rel="author"]
# author_url: $author/@href
# published_date: $header//address/time/@datetime
# @remove: $body//address
# See if the author name is a URL of a Telegram channel. If it is, assign its username to the *channel* property. This will display the channel name prominently on the Instant View page and add neat 'Join' button for users that are not members of the channel yet.
# @clone: $author_url
# @match("^https?://t(elegram)?\\.me/([a-z0-9_]+)$", 2, "i"): $@
# @replace(".+", "@$0")
# channel
# cover: $body//h1/next-sibling::figure[.//video]
# cover: $body//h1/next-sibling::figure[.//img]
# image_url: $cover/self::img/@src
# image_url: $cover/self::figure//img/@src
# image_url: /html/head/meta[@property="og:image"] \
/@content[string()]
# image_url: $body//img/@src
# IV supports anchors.
# We can add them before each of h3/h4 headers
# @before(<anchor>, name, @id): $body//h3[@id]
# @before(<anchor>, name, @id): $body//h4[@id]
# The 'body' and 'title' *properties* are required for an Instant View page to work.
# 'Subtitle' is optional for IV pages, but Medium posts can have subtitles, so it is essential that we reflect this in our template.
# body: //article
# title: $body//h1[1]
# subtitle: $title/next-sibling::h2
### Now we'll set a cover image. It's also not required, but we need one if we want our Instant view page to look cool.
# Some Medium posts have a cover image in the header background, we can use that.
# First, let's assign the background node to the '$bg_section' *variable* for subsequent use.
# $bg_section: $body//section[has-class("is-imageBackgrounded")]
# Call the @background_to_image *function* to convert the background image to an <img>
# @background_to_image: $bg_section//div[has-class("section-backgroundImage")]
# Replace the //div tag with <figure> tags.
# <figure>: $bg_section//div[has-class("section-background")]
# Set the figure as the value of the 'cover' *property*.
# cover: $bg_section//figure
# If we didn't find a cover image, check a few other blocks that may contain it.
# Note that 'cover:' is a *property*, so by default it will not be overwritten once we've assigned a value for the first time. This means that each of the following rules will only be applied if we don't have a cover yet.
# cover: $title/preceding::figure[.//img][not(has-class("is-partialWidth"))]
# cover: $title/next-sibling::figure[.//img]
# cover: $subtitle/next-sibling::figure[.//img]
# cover: //figure[has-class("graf--layoutFillWidth")]
### Now to find an image for link previews. Links shared via Telegram will show an extended preview with a small picture in the chat. Let's try to find something for this image.
# If we've already got a cover, we'll use it for the link preview image too.
# image_url: $cover/self::img/@src
# image_url: $cover/self::figure//img/@src
# If we didn't find a cover, we'll take a picture from the meta tags.
# Otherwise, the link preview will just have text in it, which is also OK.
# image_url: //head/meta[@property="og:image"]/@content
## STEP 3: Cleanup
# @remove: $body//*[has-class("twitter_timeline_wrap")]
# @remove: $body/div/center[.//img]/br
# Remove "The Telegram Team" italic footer with the date from the page. We already have this info on the Instant View page, just below the title, no need to repeat it at the bottom.
# $footer: $body/p[./em[contains(., "The Telegram Team")]]
# @remove: $footer/prev-sibling::*[./br][not(normalize-space())]
# @remove: $footer/next-sibling::*[./br][not(normalize-space())]
# @remove: $footer
# Remove excessive nodes, we don't need them on the IV page.
# @remove: //article/header
# @remove: //article/footer
# @remove: $body//a[contains(@href,"/adServer.bs")]
# @remove: $body//p//*[has-class("graf-dropCap")]//img[has-class("graf-dropCapImage")]
# @remove: $body//*[has-class("js-postMetaLockup")][.//a[@data-action="show-user-card"]]
# Remove the first divider, it's invisible on Medium pages anyway.
# @remove: $body//section[1]//hr
# @remove: $body//section[has-class("section--first")]//hr
# @remove: $body//section[has-class("section--cover")]/following-sibling::*[1]/self::section//hr
# @remove: $body//section[has-class("is-backgrounded")]/following-sibling::*[1]/self::section//hr
# Some pages use thin images as a divider. Telegram doesn't like thin images much, so we'll replace them with a simple divider.
# @before(<hr>): $body//figure[.//img[number(@data-height) < 30][(number(@data-width) > number(@data-height) * 30)]]
# @remove
### STEP 4: Further refinements
### Telegram blog posts have a 'Recent News' section at the bottom (on the right on desktops) that features earlier blog posts. We'll make some changes to this block so that it looks better on the IV page.
# $related: //div[has-class("tl_blog_bottom_blog")]
# <h4>: $related//a[has-class("side_blog_header")]
# <related>: $related
# @append_to($body)
# Pullquote in Medium contains a 'strong' tag, but this shouldn't make the whole quote bold.
# <span>: //blockquote[has-class("graf--pullquote")]//strong
# <aside>: //blockquote[has-class("graf--pullquote")]
# Now we'll inline embeds that are wrapped in additional frames using the '@inline' *function*.
# @inline: $body//iframe[starts-with(@src, "/media/")]
# Medium shows preformatted blocks/blockquotes together if they are next to each other, we'll combine them using two breaks as a separator.
# @combine(<br>,<br>): $body//pre/next-sibling::pre
# @combine(<br>,<br>): $body//blockquote/next-sibling::blockquote
# Medium articles can contain embedded link previews, we'll show such previews as blockquotes.
# $embed: $body//div[has-class("graf--mixtapeEmbed")]
# @remove: $embed//a[has-class("mixtapeImage")]
# $embed_link: $embed/a
# @detach: $embed_link/strong
# @before_el(./..): $embed_link/*
# @wrap(<cite>): $embed_link
# <blockquote>: $embed
### And that's it, we're done. Now the rules from the '..after' block will be applied and the Instant View page is ready. Feel free to click on the panel below to see what exactly is done in the '..after' section.
@lnxpy
Copy link

lnxpy commented May 23, 2020

Hey dear @imsus,

I've made a weblog in Django and now, I want to change the templates to make it able to be viewed as an instant post on the Telegram.
Do you know any package could help me to keep up this stuff?

Thanks ❤️.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment