

Making dynamic Twitter header
source link: https://dev.to/pavel_polivka/making-dynamic-twitter-header-6m3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Making dynamic Twitter header
Recently I saw a Twitter header that displayed images of new followers dynamically. I fell in love with this idea so I decided to create my own.
It should be simple, I will just write a simple script that will take a background image, via Twitter API downloads list of followers, their profile images and puts them into that background image. After that, via the same API, it will upload the image as a new header.
As a true developer I decided to Google how to do this and I found this amazing article by Thobias Schimdt. I shamelessly copied most of his code. I decided to deploy it differently (not on AWS). In this article, I will go over my changes.
In the end, my code looks like this.
const { TwitterClient } = require('twitter-api-client')
const axios = require('axios')
const sharp = require('sharp')
const Feed = require('rss-to-json')
const Jimp = require('jimp')
const fs = require('fs')
const numberOfFollowers = 3
const widthHeightFollowerImage = 90
function getVariable(name) {
if (fs.existsSync(`${__dirname}/creds.json`)) {
return require(`${__dirname}/creds.json`)[name]
}
return process.env[name]
}
async function uploadBanner() {
console.log(`Uploading to twitter...`)
const base64 = await fs.readFileSync('/tmp/1500x500_final.png', { encoding: 'base64' });
await twitterClient.accountsAndUsers
.accountUpdateProfileBanner({ banner: base64 })
}
async function createBanner(headline) {
const banner = await Jimp.read(`${__dirname}/assets/banner.png`)
const mask = await Jimp.read(`${__dirname}/assets/mask.png`)
const font = await Jimp.loadFont(Jimp.FONT_SANS_32_WHITE)
// build banner
console.log(`Adding followers...`)
await Promise.all([...Array(numberOfFollowers)].map((_, i) => {
return new Promise(async resolve => {
const image = await Jimp.read(`/tmp/${i}.png`)
const x = 600 + i * (widthHeightFollowerImage + 10);
console.log(`Appending image ${i} with x=${x}`)
banner.composite(image, x, 360);
resolve()
})
}))
console.log(`Adding headline...`)
banner.print(font, 380, 250, headline);
await banner.writeAsync('/tmp/1500x500_final.png');
}
async function getLatestArticleHeadline() {
console.log(`Retrieving headline...`)
const rss = await Feed.parse(`${getVariable('RSS_FEED')}`)
const title = rss.items[0].title
console.log(`Retrieved headline: ${title}`)
// add padding left & right to align it properly
const padding = ' '.repeat(Math.ceil((60 - title.length) / 2))
return `${padding}${title}${padding}`;
}
async function saveAvatar(user, path) {
console.log(`Retrieving avatar...`)
const response = await axios({
url: user.profile_image_url_https,
responseType: 'arraybuffer'
})
await sharp(response.data)
.resize(widthHeightFollowerImage, widthHeightFollowerImage)
.toFile(path)
}
async function getImagesOfLatestFollowers() {
console.log(`Retrieving followers...`)
try {
const data = await twitterClient
.accountsAndUsers
.followersList({
screen_name: getVariable('TWITTER_HANDLE'),
count: numberOfFollowers
})
await Promise.all(data.users
.map((user, index) => saveAvatar(user, `/tmp/${index}.png`)))
} catch (err) {
console.log(err)
}
}
const twitterClient = new TwitterClient({
apiKey: getVariable('TWITTER_API_KEY'),
apiSecret: getVariable('TWITTER_API_SECRET_KEY'),
accessToken: getVariable('TWITTER_API_ACCESS_TOKEN'),
accessTokenSecret: getVariable('TWITTER_API_ACCESS_SECRET'),
});
exports.handler = async () => {
await getImagesOfLatestFollowers()
const title = await getLatestArticleHeadline()
await createBanner(title)
await uploadBanner()
return {
statusCode: 200,
body: JSON.stringify({ status: 'ok' }),
};
}
Enter fullscreen mode
Exit fullscreen mode
The background image I use is created by Canva Twitter Header Tool you can create an amazing header even without being good at designing things.
For Twitter API to let you download your follower info, you need to have something called Elevated API level access. More about it here.
I decided to deploy it as Netlify function. So my code is saved in the netlify/function/header.js file.
To launch this locally you can do
npm run-func netlify/functions/header.js handler
Enter fullscreen mode
Exit fullscreen mode
You can add this into your package.json file like this:
{
"scripts": {
"generate": "run-func netlify/functions/header.js handler"
},
"dependencies": {
"axios": "^0.24.0",
"jimp": "^0.16.1",
"rss-to-json": "^2.0.2",
"run-func": "^1.0.5",
"sharp": "^0.29.3",
"twitter-api-client": "^1.4.0"
}
}
Enter fullscreen mode
Exit fullscreen mode
I store my assets in the netlify/functions/assets folder. For Netlify to deploy those files with your function you need to tell it so. You can do it with netlify.toml file in the root of your project.
[functions]
included_files = ["netlify/functions/**"]
Enter fullscreen mode
Exit fullscreen mode
To deploy to Netlify, just push all your code to GitHub. Login/signup to Netlify and choose your GitHub repo. Netlify will do all the magic for you. In a few seconds they will provide you with a URL you can call to trigger your function.
Great. Now we need to run this regularly so that we can catch all the new followers and articles. To do so I decided to use EasyCron. It's a super easy-to-use platform where you can say. OK call this URL every minute. For our use case, this is will be enough and will be free.
Now we have it all. We can enjoy our awesome free dynamic Twitter header.
If you like this article you can follow me on Twitter.
Recommend
-
11
Making Tables With Sticky Header and Footers Got a Bit Easier Chris Coyier on Jun 14, 2021 (Updated on Jun 15, 2021) — Open, multi-clou...
-
8
Building A Dynamic Header With Intersection Observer ...
-
7
Copy the dynamic range in the new workbooks, add the header and save new workbooks in the local directory before closing advertisements I have...
-
4
March 11, 2022
-
25
Rajesh Shivajirao Shinde Jul 26, 2021 at 08:03 PM SAP PO 7.5 REST Lookup - Issues in passing dynamic values in HTTP Header and custom E...
-
5
blog.cloudflare.com Checking if the site connection is secure
-
9
OpenSSF: Making SBOMs more dynamic to reduce software security risks
-
6
Intro⌗ I’ve encountered a lot of skepticism around the idea of adding dynamic behavior to
-
11
Implementing something similar to the header transition on Twitter's profile page may seem challenging at first, but it's not that complex when you break down the animation into parts. In this article, I'll show you how to implement the sam...
-
2
Create beautiful engaging Twitter (X) bannersSort by: Hey hunters 👋 I'm introducing the free Twitter Header Maker today! It's a free tool for creating beautiful & engaging Twitter banners for your profile. It i...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK