Skip to content

Latest commit

 

History

History
261 lines (203 loc) · 6.99 KB

File metadata and controls

261 lines (203 loc) · 6.99 KB

Count Von Countdown Semver license Open Source Love LinkedIn

voncountdown

Count Von Countdown

A Twitter bot that counts down from a very large number, posting tweets with the current count in word form. Inspired by Count Von Count from Sesame Street!

Count Von Countdown

Features

  • Automatic countdown tweets with random phrases and tags
  • Web interface showing current countdown state
  • Badge endpoint for displaying countdown in README files
  • Health check endpoint for monitoring
  • Secure with rate limiting, helmet.js, and input validation
  • Comprehensive error handling and retry logic

Setup Instructions

Prerequisites

  • Node.js 20+
  • AWS Account with DynamoDB access
  • Twitter Developer Account with API v2 access

Installation

  1. Clone the repository:
git clone https://github.com/brianfunk/voncountdown.git
cd voncountdown
  1. Install dependencies:
npm install
  1. Copy .env.example to .env:
cp .env.example .env
  1. Configure environment variables in .env:
# AWS Configuration
AWS_ACCESS_KEY_ID=your_aws_access_key_id
AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key
AWS_REGION=us-east-1
DYNAMODB_TABLE=voncountdown

# Application Configuration
PORT=8080
NODE_ENV=development

# Twitter API Configuration
TWITTER_API_KEY=your_twitter_api_key
TWITTER_API_SECRET=your_twitter_api_secret
TWITTER_ACCESS_TOKEN=your_twitter_access_token
TWITTER_ACCESS_TOKEN_SECRET=your_twitter_access_token_secret
  1. Create DynamoDB table:

    • Table name: voncountdown (or set DYNAMODB_TABLE env var)
    • Partition key: number (Number)
    • No sort key required
  2. Start the application:

npm start

For development with auto-reload:

npm run dev

API Endpoints

GET /

Home page displaying the current countdown state.

GET /badge

Returns a badge image showing the current countdown number.

  • Returns 503 if service is initializing
  • Returns 500 on error

GET /health

Health check endpoint returning JSON:

{
  "status": "ok",
  "current_number": 1111373357578,
  "current_string": "One trillion one hundred eleven billion...",
  "current_comma": "1,111,373,357,578",
  "uptime": 1234.56,
  "timestamp": "2026-01-13T15:30:00.000Z"
}

Development

Running Tests

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage report
npm run test:coverage

See tests/README.md for testing guide.

Logging

The application uses simple console logging (stdout/stderr) for compatibility with AWS App Runner and CloudWatch Logs.

Log Levels:

  • [INFO] - General information and flow tracking
  • [DEBUG] - Detailed debugging information
  • [WARN] - Warnings and non-critical issues
  • [ERROR] - Errors and exceptions

Log Format:

[INFO] [2026-01-13T16:30:00.000Z] Message {"key":"value"}

Features:

  • Automatic sanitization of sensitive data (credentials, tokens, keys)
  • Timestamped logs for easy debugging
  • Structured JSON data for parsing
  • Extensive logging throughout countdown flow, Twitter API calls, and DynamoDB operations

Viewing Logs:

  • Local: Logs appear in console when running npm start or npm run dev
  • AWS App Runner: View logs in CloudWatch Logs console
  • Heroku: View logs with heroku logs --tail

Architecture

The application consists of:

  • Express.js web server
  • DynamoDB for persistent storage of countdown state
  • Twitter API v2 for posting tweets
  • Console logging (stdout/stderr) for CloudWatch compatibility
  • Node-cache for in-memory caching
  • Handlebars for server-side templating

Countdown Flow

  1. On startup, loads the lowest number from DynamoDB (or initializes with start number)
  2. Decrements the number
  3. Formats number as words and comma-separated value
  4. Randomly adds phrase and tag (1 in 5 chance)
  5. Posts tweet via Twitter API
  6. Updates DynamoDB with new state
  7. Schedules next countdown with random delay (14-88 days)

Error Handling

  • Twitter rate limits: Automatically waits for rate limit reset
  • DynamoDB throttling: Exponential backoff with up to 5 retries
  • Other errors: Retries after 1 minute delay
  • Negative numbers: Countdown stops gracefully

Configuration

Environment Variables

Variable Description Default
AWS_ACCESS_KEY_ID AWS access key Required
AWS_SECRET_ACCESS_KEY AWS secret key Required
AWS_REGION AWS region us-east-1
DYNAMODB_TABLE DynamoDB table name voncountdown
PORT Server port 8080
NODE_ENV Environment development
TWITTER_API_KEY Twitter API key Required
TWITTER_API_SECRET Twitter API secret Required
TWITTER_ACCESS_TOKEN Twitter access token Required
TWITTER_ACCESS_TOKEN_SECRET Twitter access token secret Required

Security

  • Helmet.js for security headers with Content Security Policy (CSP)
  • CSP configured to allow external resources (Twitter widgets, jQuery, Wikipedia, YouTube)
  • Rate limiting (100 req/15min per IP, 60 req/min for health endpoint)
  • Input validation and sanitization
  • XSS protection in templates
  • Environment variable validation
  • Request timeout handling (30 seconds)
  • Log sanitization to prevent credential leakage

Deployment

AWS App Runner

  1. Create App Runner service
  2. Connect to GitHub repository
  3. Set environment variables in App Runner console:
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
    • AWS_REGION
    • DYNAMODB_TABLE
    • TWITTER_API_KEY
    • TWITTER_API_SECRET
    • TWITTER_ACCESS_TOKEN
    • TWITTER_ACCESS_TOKEN_SECRET
    • NODE_ENV=production
    • PORT=8080
  4. App Runner automatically:
    • Builds and deploys on push to main branch
    • Streams logs to CloudWatch Logs
    • Handles scaling and health checks

Logging: All logs go to stdout/stderr and are automatically captured by CloudWatch Logs. Use AWS Console to view logs.

Heroku

  1. Create Heroku app
  2. Set environment variables
  3. Deploy:
git push heroku main

Docker

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 8080
CMD ["npm", "start"]

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests: npm test
  5. Submit a pull request

License

Code and documentation copyright 2016 Brian Funk. Code released under the MIT license.

Ah ha ha ha!