Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ Response: { "ok": true }
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/clout` | Get user's clout score, tier, and breakdown |
| POST | `/api/clout` | Acknowledge tier change modal was shown |

### GET /api/clout
Returns the user's clout score and tier when queue pacing is enabled. Clout is computed from the engagement on the user's last 10 matured clips (48h+ old). Users with fewer than 10 matured clips default to Rising tier.
Expand All @@ -257,14 +258,24 @@ Response: {
"icon": "/icons/clout/viral.png",
"breakdown": [{ "clipId": "...", "score": 2 }, ...],
"nextTier": { "tier": "iconic", "tierName": "Iconic", "minScore": 1.0, "burst": 5, "queueLimit": null, "icon": "..." },
"underperforming": [{ "clipId": "...", "title": "...", "platform": "tiktok", "originalUrl": "...", "thumbnailPath": "..." }]
"underperforming": [{ "clipId": "...", "title": "...", "platform": "tiktok", "originalUrl": "...", "thumbnailPath": "..." }],
"lastTier": "rising",
"tierChanged": true
}
```

**Tiers:** Fresh (<0.4) → Rising (0.4–0.6) → Viral (0.7–0.9) → Iconic (≥1.0). Each tier adjusts cooldown multiplier, burst size, and queue depth limit.

**Per-clip scoring:** 0 = no reactions/favorites from others, 1 = reaction or favorite but no comment, 2 = reaction/favorite AND comment. Self-interactions excluded.

**Tier change detection:** The server tracks each user's last acknowledged tier (`cloutTier`) and last modal shown time (`cloutChangeShownAt`). When the computed tier differs from the acked tier and the 3-day cooldown has elapsed, `tierChanged: true` is returned. The `lastTier` field shows what the user was previously at.

### POST /api/clout
Acknowledges that the tier change modal was shown. Updates the user's stored tier and resets the cooldown timer.
```
Response: { "ok": true }
```

## Queue Management

Manage queued clips when share pacing is enabled.
Expand Down Expand Up @@ -378,13 +389,14 @@ Response: { "dailyShareLimit": 5 }
### PATCH /api/group/share-pacing
Host-only. Configures queue-based share pacing. When switching away from `queue` mode, all queued clips are flushed to `ready`.
```
Request: { "sharePacingMode": "queue", "shareBurst": 2, "shareCooldownMinutes": 120, "dailyShareLimit": null }
Response: { "sharePacingMode": "queue", "shareBurst": 2, "shareCooldownMinutes": 120, "dailyShareLimit": null }
Request: { "sharePacingMode": "queue", "shareBurst": 2, "shareCooldownMinutes": 120, "dailyShareLimit": null, "cloutEnabled": true }
Response: { "sharePacingMode": "queue", "shareBurst": 2, "shareCooldownMinutes": 120, "dailyShareLimit": null, "cloutEnabled": true }
```
- `sharePacingMode`: `"off"` | `"daily_cap"` | `"queue"`
- `shareBurst`: 1–10 (clips per scheduled time slot)
- `shareCooldownMinutes`: 30 | 60 | 120 | 240 | 360
- `dailyShareLimit`: positive integer or null
- `cloutEnabled`: boolean (enables reputation-based queue adjustments)

### GET /api/group/provider
```
Expand Down
3 changes: 3 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ scrolly/
│ │ │ ├── AddVideoModal.svelte # Modal wrapper for AddVideo
│ │ │ ├── AvatarCropModal.svelte # Profile picture crop UI
│ │ │ ├── QueueSheet.svelte # Bottom sheet for viewing/reordering queued clips
│ │ │ ├── QueueCloutBanner.svelte # Clout tier banner inside QueueSheet
│ │ │ ├── CloutChangeModal.svelte # Tier change celebration modal
│ │ │ ├── CloutTipsView.svelte # Clout tips/breakdown view (tier details, scoring)
│ │ │ ├── CatchUpModal.svelte # Catch-up modal for bulk unwatched clips
│ │ │ ├── MeGrid.svelte # Profile clip grid (favorites/uploads)
│ │ │ ├── MeReelView.svelte # Profile reel overlay view
Expand Down
5 changes: 4 additions & 1 deletion docs/data-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ SQLite database via Drizzle ORM. All IDs are UUIDs stored as text. Timestamps ar
| share_pacing_mode | text | Default `'off'`. `'off'` / `'daily_cap'` / `'queue'`. |
| share_burst | integer | Default 2. Clips per scheduled time slot in queue mode (1–10). |
| share_cooldown_minutes | integer | Default 120. Minutes between clip groups in queue mode. |
| clout_enabled | integer | Boolean (0/1). Default 1. Enables reputation-based queue adjustments. |
| shortcut_token | text | Nullable, unique. Token for iOS Shortcut clip sharing. |
| shortcut_url | text | Nullable. URL for iOS Shortcut integration. |
| created_by | text | FK → users.id (host/admin) |
Expand All @@ -42,6 +43,8 @@ SQLite database via Drizzle ORM. All IDs are UUIDs stored as text. Timestamps ar
| avatar_path | text | Nullable. Path to uploaded profile picture. |
| last_legacy_share_at | integer | Nullable. Unix timestamp of last legacy shortcut share. Used for upgrade banner. |
| used_new_share_flow | integer | Boolean (0/1). Default 0. Tracks if user has adopted new web view share flow. |
| clout_tier | text | Nullable. Last acknowledged clout tier (for tier change detection). |
| clout_change_shown_at | integer | Nullable. Unix timestamp when tier change modal was last shown (3-day cooldown). |
| removed_at | integer | Nullable. Unix timestamp when removed from group. |
| created_at | integer | Unix timestamp |

Expand Down Expand Up @@ -249,4 +252,4 @@ users 1──∞ verification_codes
- **Duplicate URL prevention:** A unique index on `(group_id, original_url)` prevents the same link from being shared twice within a group.
- **Music clip trim workflow:** Music clips enter `pending_trim` status after download. The user can trim audio via the trim UI or skip trimming. If neither occurs before `trim_deadline`, the clip auto-publishes to `ready` status via the scheduler.
- **Dismissed clips:** The `dismissed_clips` table tracks clips dismissed by users in the catch-up modal. Users can dismiss unwatched clips in bulk, then restore them later from the Skipped Clips viewer in settings.
- **Clout (reputation):** Computed on-demand from existing tables — no new schema. A user's clout score is the rolling average of per-clip engagement scores (0/1/2) for their last 10 matured clips (48h+ old). Scores are derived from `reactions`, `favorites`, and `comments` tables, excluding self-interactions. Tiers (Fresh/Rising/Viral/Iconic) determine queue cooldown multiplier, burst size, and queue depth limits.
- **Clout (reputation):** Computed on-demand from `reactions`, `favorites`, and `comments` tables. A user's clout score is the rolling average of per-clip engagement scores (0/1/2) for their last 10 matured clips (48h+ old). Self-interactions are excluded. Tiers (Fresh/Rising/Viral/Iconic) determine queue cooldown multiplier, burst size, and queue depth limits. The `clout_enabled` flag on `groups` controls whether clout adjustments are applied. The `clout_tier` and `clout_change_shown_at` columns on `users` track server-driven tier change notifications with a 3-day cooldown.
Loading