A social reputation graph built on good vibes
Track positive relationships on Twitter/X and discover connection degrees between users
What It Does β’ How It Works β’ Quick Start β’ API β’ Deployment
The reputest bot monitors Twitter/X for #gmgv (Gives Me Good Vibes) hashtag tweets and builds a directed social graph of positive relationships. When someone tweets @username #gmgv (or username #gmgv for stealth mode π€«), they're attesting to the good vibes they get from that X user, creating a connection in the reputation graph.
Key Features:
- π Hashtag Monitoring β Automatically scans for #gmgv tweets every 5 minutes
- π Multi-Degree Analysis β Calculates 1st through 4th degree connection paths
- π€ Twitter Bot β Users can query vibe scores by mentioning @reputest
- π Encrypted Token Storage β AES-256-GCM encryption for all OAuth tokens
- β‘ High Performance β Built with Axum and async Rust for speed
- π‘οΈ Production Security β Rate limiting, security headers, and XSS protection
Alice ββgmgvβββΆ Bob ββgmgvβββΆ Charlie ββgmgvβββΆ Diana
β β
βββββββββββgmgvββββββββββββββββΆβ
Arrows show attestations: who tweeted β who was mentioned
- Emitter: The person emitting good vibes (mentioned user)
- Sensor: The person sensing/attesting to those vibes (author of the #gmgv tweet)
When Alice queries her vibe score with Diana:
| Degree | Meaning | Example Path |
|---|---|---|
| 1st | Direct connection | Alice β Diana |
| 2nd | One intermediary | Alice β Bob β Diana |
| 3rd | Two intermediaries | Alice β Bob β Charlie β Diana |
| 4th | Three intermediaries | Alice β X β Y β Z β Diana |
Tweet @reputest @username? to get your vibe scores with that user:
@reputest @elonmusk?
Reply:
Your vibes for @elonmusk are:
1st degree: 0
2nd degree: 3
3rd degree: 12
- Rust 1.70+
- PostgreSQL 14+
- Twitter Developer Account with OAuth 2.0 app
git clone https://github.com/julerex/reputest.git
cd reputestCreate the database and run the schema:
createdb reputest
psql -d reputest -f sql/database_ddl.sql# Required
export DATABASE_URL="postgres://user:password@localhost/reputest"
export TOKEN_ENCRYPTION_KEY="$(openssl rand -hex 32)" # 32-byte hex key
# Optional
export PORT=3000 # Default: 3000
export RUST_LOG=info # Options: debug, info, warn, error# Run the OAuth 2.0 authorization flow
cargo run --bin authorize_botThis will guide you through:
- Entering your Twitter OAuth 2.0 Client ID & Secret
- Authorizing the app in your browser
- Storing encrypted tokens in the database
cargo runVisit http://localhost:3000 to see the Good Vibes dashboard.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Good Vibes dashboard β displays all relationships with degree paths |
GET |
/reputest |
Test endpoint β returns "Reputesting!" |
POST |
/reputest |
Test endpoint β returns "Reputesting!" |
GET |
/health |
Health check β returns {"status": "healthy", "service": "reputest"} |
The homepage displays a comprehensive table showing all sensor-emitter pairs with their path counts across all four degrees:
| sensor | sensor name | emitter | emitter name | 1Β° | 2Β° | 3Β° | 4Β° |
|---|---|---|---|---|---|---|---|
| @alice | Alice Smith | @bob | Bob Jones | 1 | 0 | 0 | 0 |
| @alice | Alice Smith | @charlie | Charlie Brown | 0 | 2 | 5 | 8 |
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
TOKEN_ENCRYPTION_KEY |
32-byte hex key for AES-256-GCM encryption |
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
HTTP server port |
RUST_LOG |
info |
Log level (debug, info, warn, error) |
# Generate a secure 32-byte key
openssl rand -hex 32-- Twitter users in the vibes graph
users (id, username, name, created_at)
-- Good vibes relationships (directed graph edges)
good_vibes (tweet_id, emitter_id, sensor_id, created_at)
-- OAuth tokens (encrypted)
access_tokens (id, token, created_at)
refresh_tokens (id, token, created_at)
-- Processed tweet tracking
vibe_requests (tweet_id)The schema includes optimized views for path counting:
view_good_vibes_degree_onethroughview_good_vibes_degree_fourview_all_good_vibes_degreesβ Combined view used by the dashboardview_easy_*variants with human-readable usernames
reputest/
βββ src/
β βββ main.rs # Server initialization, routes, middleware
β βββ config.rs # Environment configuration
β βββ handlers.rs # HTTP route handlers
β βββ db.rs # Database operations & graph queries
β βββ crypto.rs # AES-256-GCM token encryption
β βββ cronjob.rs # Scheduled Twitter monitoring
β βββ oauth.rs # OAuth 2.0 token refresh
β βββ twitter/
β β βββ mod.rs # Twitter module exports
β β βββ api.rs # API client & utilities
β β βββ search.rs # Hashtag & mention search
β β βββ tweets.rs # Tweet posting & replies
β β βββ parsing.rs # Tweet text parsing
β βββ lib.rs # Library exports
β βββ tests.rs # Test suite
βββ scripts/
β βββ authorize_bot.rs # OAuth 2.0 authorization flow
β βββ refresh_access_token.rs # Manual token refresh
β βββ encrypt_token.rs # Token encryption utility
βββ sql/
β βββ database_ddl.sql # Schema & views
β βββ database_init.sql # Initial data (if any)
βββ docs/
β βββ BOT_SETUP.md # Twitter OAuth 2.0 setup guide
β βββ CLOUDFLARE_DOMAIN_SETUP.md # Custom domain configuration
β βββ TROUBLESHOOTING.md # Common issues & solutions
β βββ DEBUGGING.md # Developer debugging guide
βββ Cargo.toml
βββ Dockerfile
βββ fly.toml # Fly.io deployment config
# Build
docker build -t reputest .
# Run
docker run -p 3000:3000 \
-e DATABASE_URL="postgres://..." \
-e TOKEN_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
reputestThe project includes ready-to-use Fly.io configuration:
# Install Fly CLI
curl -L https://fly.io/install.sh | sh
# Login
fly auth login
# Deploy
fly launch # First time
fly deploy # Updates
# Set secrets
fly secrets set DATABASE_URL="postgres://..."
fly secrets set TOKEN_ENCRYPTION_KEY="$(openssl rand -hex 32)"The app is configured for:
- Region: Frankfurt (
fra) - Memory: 1GB
- Port: 8080 (internal)
- HTTPS: Forced
- Minimum machines: 1
cargo test # All tests
cargo test -- --nocapture # With output
cargo test handlers # Specific modulecargo build --releaseRelease builds are optimized for size (opt-level = "z") with LTO enabled.
# Authorize bot (OAuth 2.0 flow)
cargo run --bin authorize_bot
# Manually refresh access token
cargo run --bin refresh_token
# Encrypt a token for database storage
cargo run --bin encrypt_token- Token Encryption: All OAuth tokens encrypted with AES-256-GCM
- Rate Limiting: 30 requests/minute per IP via
tower_governor - Security Headers: X-Content-Type-Options, X-Frame-Options, CSP, etc.
- XSS Protection: HTML escaping on all user-generated content
- Input Validation: Log sanitization to prevent injection attacks
- Automatic Cleanup: Old tokens purged after 24 hours
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing) - Make your changes with tests
- Run
cargo testandcargo clippy - Commit (
git commit -m 'Add amazing feature') - Push (
git push origin feature/amazing) - Open a Pull Request
See CONTRIBUTING.md for detailed guidelines.
MIT License β see LICENSE for details.
- Axum β Web framework
- SQLx β Async PostgreSQL
- tokio-cron-scheduler β Job scheduling
- tower-governor β Rate limiting
Built with π¦ and good vibes