Skip to content

Latest commit

Β 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

post-forge

Python FastAPI Stripe SQLite License

Social media post scheduler with multi-platform support and analytics

Schedule posts intelligently β€’ Track engagement metrics β€’ Batch operations β€’ Export analytics

Features β€’ Quick Start β€’ Configuration β€’ API Reference β€’ Examples


Overview

post-forge is a Python-based social media automation tool designed for content creators and marketing teams. Schedule posts across multiple platforms, track performance in real-time, and export detailed analyticsβ€”all from a unified CLI or API.

Use Cases:

  • Automate content calendar management
  • Schedule posts during optimal engagement hours
  • Track post performance across platforms
  • Batch-import campaigns from CSV
  • Export analytics for reporting

Features

Feature Details
Multi-Platform Twitter, LinkedIn, Instagram (extensible to TikTok, Pinterest)
Batch Scheduling Import posts from CSV, schedule with offsets
Performance Tracking Real-time engagement metrics (likes, shares, comments)
Analytics Export JSON, CSV, Markdown formats for reporting
Rate Limiting Configurable max posts per platform per day
Retry Logic Automatic retry with exponential backoff
CLI & API Use as command-line tool or import as Python module
Lightweight Minimal dependencies, quick startup
SQLite Backend No database setup required

System Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  CLI / API Client                β”‚
β”‚  (post_forge.py / Python API)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Core Scheduler Service          β”‚
β”‚  - Task queue management         β”‚
β”‚  - Rate limiting logic           β”‚
β”‚  - Retry handler                 β”‚
β”‚  - Time-based scheduling         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Platform Adapters               β”‚
β”‚  - Twitter/X API v2              β”‚
β”‚  - LinkedIn API                  β”‚
β”‚  - Instagram Graph API           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  SQLite Database                 β”‚
β”‚  - posts table                   β”‚
β”‚  - analytics table               β”‚
β”‚  - accounts table                β”‚
β”‚  - schedule_log table            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Directory Structure

post-forge/
β”œβ”€β”€ post_forge.py          # Main CLI entry point
β”œβ”€β”€ scheduler.py           # Core scheduling logic
β”œβ”€β”€ platforms/
β”‚   β”œβ”€β”€ twitter.py         # Twitter/X adapter
β”‚   β”œβ”€β”€ linkedin.py        # LinkedIn adapter
β”‚   └── instagram.py       # Instagram adapter
β”œβ”€β”€ analytics.py           # Performance tracking
β”œβ”€β”€ database.py            # SQLite operations
β”œβ”€β”€ config.json            # Platform & rate limit config
└── requirements.txt       # Python dependencies

Installation

Prerequisites

Quick Install

# Clone the repository
git clone https://github.com/SSH-PuR66/post-forge.git
cd post-forge

# Create virtual environment
python -m venv .venv

# Activate virtual environment
# On macOS/Linux:
source .venv/bin/activate
# On Windows:
.venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

Verify installation:

python post_forge.py --version

Configuration

Environment Variables

Create a .env file in the project root:

# Twitter/X API v2
TWITTER_API_KEY=xxxxxxxxxxxxx
TWITTER_API_SECRET=xxxxxxxxxxxxx
TWITTER_ACCESS_TOKEN=xxxxxxxxxxxxx
TWITTER_ACCESS_SECRET=xxxxxxxxxxxxx
TWITTER_BEARER_TOKEN=Bearer xxxxxxxxxxxxx

# LinkedIn
LINKEDIN_ACCESS_TOKEN=xxxxxxxxxxxxx
LINKEDIN_ORG_ID=xxxxxxxxxxxxx

# Instagram (via Facebook Graph API)
INSTAGRAM_ACCESS_TOKEN=xxxxxxxxxxxxx
INSTAGRAM_BUSINESS_ACCOUNT_ID=xxxxxxxxxxxxx

# Platform Configuration
TWITTER_MAX_POSTS_PER_DAY=10
LINKEDIN_MAX_POSTS_PER_DAY=3
INSTAGRAM_MAX_POSTS_PER_DAY=5

# Scheduling
TIMEZONE=US/Eastern
AUTO_RETRY=true
RETRY_DELAY_MINUTES=30

# Output
DEFAULT_EXPORT_FORMAT=csv

config.json

Override defaults:

{
  "platforms": {
    "twitter": {
      "enabled": true,
      "max_posts_per_day": 10,
      "rate_limit_per_hour": 450,
      "retry_failed": true
    },
    "linkedin": {
      "enabled": true,
      "max_posts_per_day": 3,
      "rate_limit_per_hour": 300
    },
    "instagram": {
      "enabled": true,
      "max_posts_per_day": 5,
      "rate_limit_per_hour": 200
    }
  },
  "scheduling": {
    "timezone": "US/Eastern",
    "auto_retry": true,
    "retry_delay_minutes": 30,
    "retry_max_attempts": 3
  },
  "analytics": {
    "track_engagement": true,
    "update_interval_minutes": 60,
    "retention_days": 90
  }
}

Quick Start

1. Schedule a Single Post

python post_forge.py schedule \
  --platform twitter \
  --text "Check out our new product launch! πŸš€ #innovation #tech" \
  --schedule "2026-06-21 10:00" \
  --media product.jpg

2. Schedule Multiple Posts (Batch)

Create posts.csv:

platform,text,media,hashtags,scheduled_time
twitter,"Q3 sales up 40%!","chart.png","#sales #growth",2026-06-21 09:00
linkedin,"Excited to announce our new partnership","banner.jpg","#partnership #news",2026-06-21 10:00
instagram,"Behind the scenes at the office","office.jpg","#teamlife #startup",2026-06-21 11:00
twitter,"Did you know? 95% of startups fail. We're not one of them.","tip.jpg","#startup #tips",2026-06-21 14:00

Schedule all:

python post_forge.py batch \
  --file posts.csv \
  --schedule-offset 1h \
  --verbose

This schedules posts starting from 9:00 AM, with 1-hour intervals between each.

3. Check Performance

# Get analytics for today
python post_forge.py analytics --date-range today

# Get analytics for last 7 days
python post_forge.py analytics --date-range last_7_days

# Filter by platform
python post_forge.py analytics --platform twitter --date-range last_7_days

# Export to CSV
python post_forge.py analytics \
  --date-range last_30_days \
  --export csv \
  --output campaign_report.csv

Usage Guide

Command Reference

Schedule Operations

# Single post
python post_forge.py schedule \
  --platform twitter \
  --text "Your message" \
  --schedule "2026-06-21 14:30" \
  --media image.jpg \
  --hashtags "#topic #news"

# From template
python post_forge.py schedule \
  --template "product_launch.txt" \
  --platform all

# Interactive mode
python post_forge.py schedule --interactive

Batch Operations

# Import and schedule
python post_forge.py batch \
  --file posts.csv \
  --schedule-offset 2h \
  --dry-run          # Preview without posting

# Schedule existing drafts
python post_forge.py batch --file posts.csv --force

Listing & Management

# List all scheduled posts
python post_forge.py list --status scheduled

# List published posts
python post_forge.py list --status published

# List failed posts
python post_forge.py list --status failed

# Retry failed posts
python post_forge.py retry --status failed

# Cancel scheduled post
python post_forge.py cancel --id post_12345

# Reschedule post
python post_forge.py reschedule --id post_12345 --new-time "2026-06-22 10:00"

Analytics

# Daily breakdown
python post_forge.py analytics --date-range today

# Weekly trends
python post_forge.py analytics --date-range last_7_days --granularity daily

# Campaign performance
python post_forge.py analytics \
  --filter "tag:campaign_summer" \
  --export json \
  --output summer_campaign_report.json

# Platform comparison
python post_forge.py analytics --compare-platforms

Configuration Management

# Show current configuration
python post_forge.py config --show

# Update rate limit
python post_forge.py config --set twitter.max_posts_per_day=15

# Reset to defaults
python post_forge.py config --reset

Batch CSV Format

Required columns:

platform,text,scheduled_time
twitter,"Your message",2026-06-21 10:00

Optional columns:

platform,text,media,hashtags,scheduled_time,metadata
twitter,"Message","image.jpg","#tag1 #tag2",2026-06-21 10:00,campaign_id:123
linkedin,"Message","banner.png","#tag1",2026-06-21 11:00,utm_source:email
instagram,"Message","photo.jpg","#tag1 #tag2 #tag3",2026-06-21 12:00,country:US

API Reference

Python Module Usage

from post_forge import Scheduler, Analytics, PostManager

# Initialize scheduler
scheduler = Scheduler(config_file="config.json")

# Schedule a single post
post = scheduler.schedule(
    platform="twitter",
    text="Hello world!",
    scheduled_time="2026-06-21 10:00",
    media_paths=["image.jpg"],
    hashtags=["#hello", "#world"]
)
print(f"Post queued: {post.id}")

# Batch schedule
posts = scheduler.batch_schedule(
    posts_data=[
        {"platform": "twitter", "text": "Post 1", "scheduled_time": "2026-06-21 10:00"},
        {"platform": "linkedin", "text": "Post 2", "scheduled_time": "2026-06-21 11:00"},
    ]
)

# Get analytics
analytics = Analytics()
report = analytics.get_performance(days=7)
print(f"Total engagements: {report['total_engagement']}")
print(f"Average reach: {report['avg_reach']}")

# Manage posts
manager = PostManager()
manager.cancel_post("post_id")
manager.list_posts(status="scheduled")
manager.retry_failed_posts()

Database Schema

-- Posts table
CREATE TABLE posts (
    id TEXT PRIMARY KEY,
    platform TEXT NOT NULL,
    content TEXT NOT NULL,
    media_urls TEXT,
    hashtags TEXT,
    scheduled_time DATETIME,
    published_time DATETIME,
    status TEXT,  -- scheduled, published, failed, cancelled
    retry_count INTEGER DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Analytics table
CREATE TABLE analytics (
    id TEXT PRIMARY KEY,
    post_id TEXT NOT NULL,
    platform TEXT NOT NULL,
    likes INTEGER,
    shares INTEGER,
    comments INTEGER,
    impressions INTEGER,
    reach INTEGER,
    engagement_rate REAL,
    captured_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (post_id) REFERENCES posts(id)
);

-- Accounts table
CREATE TABLE accounts (
    id TEXT PRIMARY KEY,
    platform TEXT NOT NULL,
    account_handle TEXT NOT NULL,
    access_token TEXT ENCRYPTED,
    token_expires_at DATETIME,
    connected_at DATETIME,
    UNIQUE(platform, account_handle)
);

-- Schedule log
CREATE TABLE schedule_log (
    id TEXT PRIMARY KEY,
    post_id TEXT NOT NULL,
    event TEXT,  -- scheduled, published, failed, retried
    status_code INTEGER,
    error_message TEXT,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (post_id) REFERENCES posts(id)
);

Examples

Example 1: Daily Post Automation

# Create posts.csv with your daily content
cat > daily_posts.csv << EOF
platform,text,hashtags,scheduled_time
twitter,"Good morning! What are you working on today?","#motivation #startup",2026-06-21 07:00
linkedin,"6 lessons I learned building a SaaS in 30 days","#startup #learning",2026-06-21 09:00
twitter,"The best time to start was yesterday. The second best time is now.","#startup #inspiration",2026-06-21 12:00
twitter,"Just shipped a major feature. Feeling productive!","#development #shipping",2026-06-21 18:00
EOF

# Schedule all
python post_forge.py batch --file daily_posts.csv

# Check results
python post_forge.py list --status published

Example 2: Campaign Tracking

# Create campaign posts with metadata
cat > campaign.csv << EOF
platform,text,media,hashtags,scheduled_time,metadata
twitter,"Summer sale starts TODAY! 🌞 20% off everything","banner.jpg","#sale #summer",2026-06-21 08:00,campaign_id:summer_2026
linkedin,"Announcing our Summer Flash Sale - Learn more on our blog","graphic.png","#sale",2026-06-21 09:00,campaign_id:summer_2026
instagram,"Hot deals this season! Swipe to shop","summer.jpg","#sale #summer #deals",2026-06-21 10:00,campaign_id:summer_2026
twitter,"Only 2 days left! Grab 20% off while supplies last πŸ”₯","banner.jpg","#sale #urgency",2026-06-22 09:00,campaign_id:summer_2026
EOF

# Schedule campaign
python post_forge.py batch --file campaign.csv

# Track performance
python post_forge.py analytics \
  --filter "metadata:campaign_id:summer_2026" \
  --date-range "2026-06-21 to 2026-06-23" \
  --export csv \
  --output summer_campaign_metrics.csv

Example 3: Multi-Platform Distribution

# Write post once, publish everywhere
python post_forge.py schedule \
  --platform all \
  --text "Just launched: New analytics dashboard. 10x faster, 100% free. Check it out!" \
  --media dashboard.jpg \
  --hashtags "#launch #analytics #startup" \
  --schedule "2026-06-21 14:00"

Example 4: Performance Analysis

# Compare platforms
python post_forge.py analytics --compare-platforms

# Output:
# Platform | Posts | Avg Likes | Avg Shares | Avg Comments | Engagement %
# ---------|-------|-----------|-----------|--------------|-------------
# Twitter  | 45    | 12.3      | 2.1       | 1.8          | 0.85%
# LinkedIn | 23    | 45.2      | 8.9       | 3.2          | 2.15%
# Instagram| 18    | 156.7     | 12.1      | 8.3          | 4.32%

# Find best-performing content
python post_forge.py analytics \
  --sort-by engagement_rate \
  --limit 10 \
  --export markdown \
  --output top_posts.md

Troubleshooting

"Authentication failed"

# Verify credentials in .env
echo $TWITTER_BEARER_TOKEN

# Test API connection
python post_forge.py test --platform twitter

# Regenerate tokens from platform dashboards
# Twitter: https://developer.twitter.com/en/portal/dashboard
# LinkedIn: https://www.linkedin.com/developers/apps

"Rate limited"

# Check current rate limits
python post_forge.py config --show | grep rate_limit

# Adjust configuration
python post_forge.py config --set twitter.rate_limit_per_hour=300

# Schedule posts further apart
python post_forge.py batch --file posts.csv --schedule-offset 2h

"Post didn't publish"

# Check logs
tail -f logs/post_forge.log

# List failed posts
python post_forge.py list --status failed

# View error details
python post_forge.py list --status failed --verbose

# Retry with debug output
python post_forge.py retry --debug

"Database locked"

# Close all instances of post_forge
pkill -f post_forge

# Clear locks
rm -f posts.db-wal posts.db-shm

# Restart
python post_forge.py list

Advanced Configuration

Custom Platform Adapter

# platforms/custom.py
from platforms.base import PlatformAdapter

class CustomPlatform(PlatformAdapter):
    def publish_post(self, post_data):
        # Your custom implementation
        pass
    
    def get_engagement_metrics(self, post_id):
        # Track engagement
        pass

Scheduled Background Execution

# macOS/Linux: Add to crontab
crontab -e

# Run every hour to check scheduled posts
0 * * * * cd /path/to/post-forge && python post_forge.py execute --background

# Retry failed posts every 30 minutes
*/30 * * * * cd /path/to/post-forge && python post_forge.py retry

Docker Deployment

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "post_forge.py", "execute", "--background"]
docker build -t post-forge .
docker run -d \
  -e TWITTER_BEARER_TOKEN="..." \
  -e LINKEDIN_ACCESS_TOKEN="..." \
  post-forge

Contributing

See CONTRIBUTING.md for guidelines.


License

MIT License β€” see LICENSE file


Author

Built by Sergio Rodriguez


Roadmap

  • Twitter/X support
  • LinkedIn support
  • Instagram support
  • TikTok support
  • Pinterest support
  • Mastodon support
  • AI-powered caption generation
  • Sentiment analysis
  • Competitor tracking
  • Web dashboard
  • Webhooks & integrations

Made for content creators who want to automate, not cut corners.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages