đ Executive Summary
TL;DR: This guide provides a custom, serverless-friendly Python solution to automate X/Twitter posts for new blog articles, eliminating manual effort and recurring SaaS costs. It leverages RSS feeds and the X/Twitter API, scheduled via cron, to automatically announce new content.
đŻ Key Takeaways
- The automation relies on
feedparserto parse the blogâs RSS feed and alast\_checked\_timestamp.txtfile to track the last published post, preventing duplicate tweets. -
tweepyis used for X/Twitter API integration, requiring developer credentials (API Key, Secret, Access Token, Secret) stored securely insecrets.txtand âRead and Writeâ app permissions. - The Python script is scheduled using
cron(e.g., every 30 minutes) on Unix-like systems, ensuring periodic checks for new posts and automated tweeting, with output redirected to a log file for debugging.
Automate Twitter/X Posts when a New Blog Post is Published (RSS to API)
Introduction
In the fast-paced digital landscape, maintaining a strong online presence is paramount for any content creator or organization. For blog publishers, announcing new articles across social media platforms like X (formerly Twitter) is a critical step in driving traffic and engagement. However, the manual process of crafting a tweet, copying the link, and posting it every time a new article goes live is not only tedious and repetitive but also prone to human error and delays. Imagine the time saved if this process could be fully automated.
While various SaaS solutions offer social media scheduling and automation, they often come with recurring costs, restrictive feature sets, and a lack of granular control. As Senior DevOps Engineers, we understand the value of bespoke solutions that offer flexibility, cost-efficiency, and deep integration. This tutorial will guide you through building a custom, serverless-friendly automation pipeline using Python, your blogâs RSS feed, and the X/Twitter API. By the end, youâll have a robust system that automatically tweets about your latest blog posts the moment theyâre published, giving you full control and eliminating manual effort.
Prerequisites
Before we dive into the automation magic, ensure you have the following components and basic understanding:
- X/Twitter Developer Account: You will need a developer account to create an application and obtain API keys (Consumer Key, Consumer Secret) and access tokens (Access Token, Access Token Secret). Ensure your app has âRead and Writeâ permissions.
- Python 3.x: Installed on your local machine or a server where the script will run. We recommend Python 3.8 or newer.
- Pip: Pythonâs package installer, usually bundled with Python 3.x.
-
A Blog with an RSS Feed: The core of our automation relies on detecting new posts via a standard RSS feed. Ensure your blog has one, e.g.,
https://yourblog.com/feed/. - Basic understanding of Python: Familiarity with Python scripting will help you understand and customize the code.
- Basic understanding of Cron (for scheduling): If you plan to run this on a server.
Step-by-Step Guide
Step 1: Set Up Your X/Twitter Developer Application and Obtain Credentials
The first step is to register your application with the X/Twitter Developer platform and obtain the necessary API credentials. These credentials act as the key to allow your script to interact with the X API on your behalf.
- Navigate to the X Developer Portal.
- Create a new Project and then a new App within that Project. Give it a descriptive name.
- Under your Appâs settings, go to the âKeys and Tokensâ section.
- Generate a Consumer Key (API Key) and Consumer Secret (API Secret). Make sure to save these immediately as the Consumer Secret is only shown once.
- Under âAuthentication settingsâ, enable âOAuth 1.0aâ and set âApp permissionsâ to âRead and Writeâ.
- Still in âKeys and Tokensâ, generate your Access Token and Access Token Secret. These are personal to your account and allow your app to post.
-
Security Best Practice: Never hardcode these credentials directly into your script. Use environment variables or a dedicated secrets file. For this tutorial, weâll use a
secrets.txtfile for simplicity, which you should protect with appropriate file permissions.
Create a file named secrets.txt in your project directory and add your credentials:
API_KEY="YOUR_CONSUMER_KEY"
API_SECRET="YOUR_CONSUMER_SECRET"
ACCESS_TOKEN="YOUR_ACCESS_TOKEN"
ACCESS_TOKEN_SECRET="YOUR_ACCESS_TOKEN_SECRET"
Step 2: Install Python Dependencies and Fetch RSS Feed
Our Python script will require two external libraries: feedparser to effortlessly parse RSS feeds and tweepy to interact with the X/Twitter API. Letâs install them:
pip install feedparser tweepy
Now, letâs create a basic Python script, tweet_blog_post.py, to read your RSS feed. Weâll also introduce a simple mechanism to track the last published post to avoid tweeting old articles repeatedly.
import feedparser
import os
from datetime import datetime, timezone
RSS_FEED_URL = "https://techresolve.com/feed/" # <-- REPLACE WITH YOUR BLOG'S RSS FEED
LAST_CHECKED_FILE = "last_checked_timestamp.txt"
def get_last_checked_timestamp():
if os.path.exists(LAST_CHECKED_FILE):
with open(LAST_CHECKED_FILE, "r") as f:
timestamp_str = f.read().strip()
if timestamp_str:
return datetime.fromisoformat(timestamp_str).replace(tzinfo=timezone.utc)
return datetime.min.replace(tzinfo=timezone.utc)
def set_last_checked_timestamp(timestamp):
with open(LAST_CHECKED_FILE, "w") as f:
f.write(timestamp.isoformat())
def fetch_new_posts():
feed = feedparser.parse(RSS_FEED_URL)
new_posts = []
last_checked = get_last_checked_timestamp()
current_latest_post_timestamp = last_checked
for entry in feed.entries:
# Ensure 'published_parsed' exists and convert to datetime object with timezone
if 'published_parsed' in entry:
post_date = datetime(*entry.published_parsed[:6], tzinfo=timezone.utc)
if post_date > last_checked:
new_posts.append({
"title": entry.title,
"link": entry.link,
"published": post_date
})
# Keep track of the latest post found in this run
if post_date > current_latest_post_timestamp:
current_latest_post_timestamp = post_date
# Sort new posts by publication date to tweet them in order
new_posts.sort(key=lambda x: x["published"])
# Update the last checked timestamp if new posts were found
if new_posts:
set_last_checked_timestamp(current_latest_post_timestamp)
print(f"Updated last checked timestamp to: {current_latest_post_timestamp}")
return new_posts
if __name__ == "__main__":
print("Fetching new blog posts...")
posts = fetch_new_posts()
if posts:
for post in posts:
print(f"New Post Found: {post['title']} - {post['link']} - {post['published']}")
else:
print("No new posts found since last check.")
This script fetches the RSS feed, compares post publication dates with a stored timestamp in last_checked_timestamp.txt, and identifies truly new posts. The timestamp ensures that once a post is processed, it wonât be re-processed in subsequent runs.
Step 3: Integrate with X/Twitter API and Post Tweets
Now weâll integrate the tweepy library to send tweets. Weâll modify our script to load credentials from secrets.txt and use them to authenticate with the X API.
import feedparser
import os
from datetime import datetime, timezone
import tweepy # <-- New import
# --- Configuration ---
RSS_FEED_URL = "https://techresolve.com/feed/" # <-- REPLACE WITH YOUR BLOG'S RSS FEED
LAST_CHECKED_FILE = "last_checked_timestamp.txt"
SECRETS_FILE = "secrets.txt" # <-- Path to your secrets file
MAX_TWEET_LENGTH = 280 # X/Twitter tweet character limit
def load_secrets(file_path):
secrets = {}
if os.path.exists(file_path):
with open(file_path, "r") as f:
for line in f:
if "=" in line:
key, value = line.strip().split("=", 1)
secrets[key] = value.strip('"')
return secrets
def get_last_checked_timestamp():
if os.path.exists(LAST_CHECKED_FILE):
with open(LAST_CHECKED_FILE, "r") as f:
timestamp_str = f.read().strip()
if timestamp_str:
return datetime.fromisoformat(timestamp_str).replace(tzinfo=timezone.utc)
return datetime.min.replace(tzinfo=timezone.utc)
def set_last_checked_timestamp(timestamp):
with open(LAST_CHECKED_FILE, "w") as f:
f.write(timestamp.isoformat())
def fetch_new_posts():
feed = feedparser.parse(RSS_FEED_URL)
new_posts = []
last_checked = get_last_checked_timestamp()
current_latest_post_timestamp = last_checked # Track the latest post in this run
for entry in feed.entries:
if 'published_parsed' in entry:
post_date = datetime(*entry.published_parsed[:6], tzinfo=timezone.utc)
if post_date > last_checked:
new_posts.append({
"title": entry.title,
"link": entry.link,
"published": post_date
})
if post_date > current_latest_post_timestamp:
current_latest_post_timestamp = post_date
new_posts.sort(key=lambda x: x["published"])
if new_posts:
set_last_checked_timestamp(current_latest_post_timestamp)
print(f"Updated last checked timestamp to: {current_latest_post_timestamp}")
return new_posts
def post_tweet(api, tweet_text):
try:
api.update_status(tweet_text)
print(f"Successfully tweeted: {tweet_text}")
except tweepy.TweepyException as e:
print(f"Error posting tweet: {e}")
if __name__ == "__main__":
print("Loading secrets...")
secrets = load_secrets(SECRETS_FILE)
API_KEY = secrets.get("API_KEY")
API_SECRET = secrets.get("API_SECRET")
ACCESS_TOKEN = secrets.get("ACCESS_TOKEN")
ACCESS_TOKEN_SECRET = secrets.get("ACCESS_TOKEN_SECRET")
if not all([API_KEY, API_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET]):
print("Error: Missing one or more X/Twitter API credentials in secrets.txt")
exit(1)
# Authenticate with X/Twitter API
auth = tweepy.OAuth1UserHandler(API_KEY, API_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)
print("Fetching new blog posts...")
posts = fetch_new_posts()
if posts:
for post in posts:
title = post['title']
link = post['link']
# Craft the tweet. X/Twitter will automatically shorten URLs.
# You might want to add hashtags dynamically or hardcode them.
tweet_template = "New blog post published: \"{title}\" Read it here: {link} #TechResolve #DevOps #Automation"
tweet_text = tweet_template.format(title=title, link=link)
# Basic length check - X/Twitter's API handles actual link shortening for character count
if len(tweet_text) > MAX_TWEET_LENGTH:
# Truncate title if tweet is too long
available_length_for_title = MAX_TWEET_LENGTH - (len(tweet_template) - len("{title}") + len(title) - len(link) + 23) # 23 for short_url length
if available_length_for_title < len(title):
title = title[:available_length_for_title-3] + "..."
tweet_text = tweet_template.format(title=title, link=link)
print(f"Attempting to tweet: {tweet_text}")
post_tweet(api, tweet_text)
else:
print("No new posts found to tweet.")
This enhanced script now reads your API credentials, initializes the tweepy API client, fetches new blog posts, formats a tweet, and sends it out. It also includes a basic length check for the tweet content, although Xâs API handles URL shortening which affects the final character count.
Step 4: Schedule the Automation with Cron
To make this a truly âset it and forget itâ solution, youâll need to schedule your Python script to run periodically. Cron is a time-based job scheduler in Unix-like operating systems and is perfect for this task.
- First, ensure your Python script is executable.
chmod +x /home/user/your_script_directory/tweet_blog_post.py
- Edit your userâs crontab:
crontab -e
- Add a line to run your script every, for example, 30 minutes. Replace
/usr/bin/python3with the actual path to your Python 3 interpreter and/home/user/your_script_directory/with the actual path to your script.
*/30 * * * * /usr/bin/python3 /home/user/your_script_directory/tweet_blog_post.py >> /tmp/logs/tweet_automation.log 2>&1
This cron entry will run the tweet_blog_post.py script every 30 minutes. All standard output and errors will be appended to /tmp/logs/tweet_automation.log, which is crucial for debugging.
Make sure the last_checked_timestamp.txt and secrets.txt files are in the same directory as your Python script, or adjust the paths in the script accordingly.
Common Pitfalls
While this automation is powerful, you might encounter a few common issues:
- X/Twitter API Rate Limits: The X API has rate limits on how many requests your application can make within a certain timeframe. If you have a very active RSS feed or run the script too frequently, you might hit these limits. Always refer to the X Developer Documentation for current limits. For most blogs, checking every 30 minutes should be well within limits.
-
Authentication Errors: Incorrect API keys, expired access tokens, or insufficient app permissions (âRead and Writeâ is crucial) can lead to authentication failures. Double-check all credentials in your
secrets.txtfile and verify your appâs permissions in the X Developer Portal. -
RSS Feed Malformation or Downtime: If your blogâs RSS feed is temporarily unavailable or malformed,
feedparsermight fail to parse it. Implement robust error handling (e.g., try-except blocks) and logging to catch these issues. Ensure your blogâs RSS feed is regularly updated and accessible. -
Duplicate Posts (without
last_checked_timestamp.txt): If you remove or corrupt thelast_checked_timestamp.txtfile, the script might re-tweet old posts. Always ensure this file persists and is correctly updated after each run.
Conclusion
Youâve successfully built a custom, automated solution to broadcast your new blog posts on X/Twitter. By leveraging the power of Python, RSS feeds, and the X API, youâve eliminated a repetitive manual task, gained full control over your social media announcements, and reduced reliance on third-party services. This setup is not only cost-effective but also provides the flexibility to evolve with your specific needs.
This foundation opens doors for further enhancements. Consider adding more sophisticated error logging, integrating image attachments with your tweets, or even expanding this automation to other social media platforms like LinkedIn or Mastodon. For a more production-ready setup, you could containerize this application using Docker and deploy it to a cloud service, ensuring higher availability and scalability. The journey of automation is continuous, and youâve just taken a significant step forward in making your content dissemination more efficient.
đ Read the original article on TechResolve.blog
â Support my work
If this article helped you, you can buy me a coffee:

Top comments (0)