Commit graph

5 commits

Author SHA1 Message Date
c8cdfde066 fix: replace http.server with SPA fallback server for Vue Router
Python's http.server returns 404 for any path that isn't a real file,
breaking Vue Router history-mode navigation (/campaigns, /queue, etc.).

scripts/spa_server.py: minimal static server that falls back to index.html
for any path that doesn't resolve to a real file in the dist directory.
Both _start_web and the `serve` subcommand now use it.
2026-05-27 16:37:26 -07:00
99d17b1898 feat: prefer static dist over Vite dev server in _start_web
manage.sh now checks for frontend/dist/index.html at startup.
If present, uses Python http.server (no host-blocking, production mode).
Falls back to Vite dev server only when dist is absent.

Fixes Vite's "Blocked request. This host is not allowed" error
when proxied behind Caddy at menagerie.circuitforge.tech.
2026-05-27 16:30:43 -07:00
e9b4cdd88e feat: link_url variants, team accounts, session layout, menagerie route (#18 #19)
#19 — link_url on campaign variants (migration 019)
- ADD COLUMN link_url TEXT on campaign_variants
- create_variant, upsert_variant, update_variant all carry link_url
- RedditClient.post() supports kind=link when link_url set + body empty
- RedditPostStrategy passes link_url from extra dict
- poster.py merges link_url from variant into extra (same as slug/tags)
- API VariantCreate/VariantUpdate schemas include link_url
- CampaignDetail: link_url field in Add Variant form with copy button;
  link_url shown in variant list with clickable link + copy button
- Variant button disabled if neither body nor link_url is set

#18 — Multi-user team accounts (migrations 020-022)
- 020: team_accounts table (display_name, platform, username, session_file)
- 021: opportunities.assigned_to + post_as FK → team_accounts
- 022: posts.posted_by_account_id FK → team_accounts
- Store: list/get/get_by_username/create_team_account, assign_opportunity
- API: GET/POST /api/v1/team; POST /api/v1/team/{id}/assign
- config.py: sessions_dir added; reddit_session_file now points to
  sessions/alan_reddit.json (backward compat path kept)
- scripts/migrate_sessions.py: one-shot move session.json →
  sessions/alan_reddit.json + creates placeholder files for future accounts
- manage.sh: build (VITE_BASE_URL=/magpie/ npm build), serve (static),
  migrate-sessions subcommands added; login updated to new session path
- Caddy: @magpie_no_session gate + handle /magpie/api* and /magpie*
  blocks added to menagerie.circuitforge.tech site block
2026-05-27 15:31:58 -07:00
a6ea0b9c58 feat(#7,#10): signal crawler -- Reddit + Lemmy community monitoring
Implements the full signal detection pipeline:

Backend:
- app/services/lemmy/client.py: async Lemmy API v3 client, community@instance
  addressing, integer cursor dedup, normalised post dicts
- app/services/scraper.py: platform-agnostic scraper; Reddit (.json API,
  fullname cursor) + Lemmy (integer ID cursor); keyword/regex/all match modes,
  min_score gate, NormalizedPost shape, upsert dedup via UNIQUE post_id
- app/api/endpoints/signals.py: CRUD for signal_rules + signals queue;
  POST /signals/scrape manual trigger; scrape-state viewer
- migrations 010-012: signal_rules, signals, signal_scrape_state tables
- scheduler: interval job every 30 min (scraper_enabled=True in config)
- Fixed migration collision: 007_signal_rules.sql → 010, 008 → 011, 009 → 012

Frontend:
- SignalsView.vue: signal feed with status filter (new/saved/dismissed),
  keyword chips, score/comment counts, save/dismiss actions, rules editor panel
- api.ts: SignalRule, Signal types + signalRules/signals API methods
- Nav: Signals as default landing route (replaces /campaigns default)

Closes #7 (signal extraction), closes #10 (Lemmy JSON crawler)
2026-04-22 11:00:14 -07:00
2cc85d8fc5 feat: scaffold Magpie — campaign scheduler + social posting platform
FastAPI backend (SQLite + APScheduler), Vue 3 frontend, MCP server for
Claude integration, and Docker Compose stack. Includes campaign data model
(campaigns → variants → subs), post history, sub rules, and Playwright-based
Reddit posting layer migrated from claude-bridge/reddit-poster.

Also seeds legacy campaigns (6) and sub rules (14) from reddit-poster history.

Closes #1 (scaffold), resolves migration from claude-bridge.
2026-04-21 16:51:33 -07:00