dumbtv
dumbtv takes the ads, screen tracking and update nags out of your Fire TV over ADB. No root, none of your apps touched, every step can be undone. Free and open source.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Stop scammers getting into communities while letting real builders in fast. Greenlight scores applications against community rules using AI, maintains a shared blocklist across communities (HMAC-hashed for privacy), and provides a review queue for moderators. Built for hackathon Track 1 (community infrastructure).
Greenlight was built in a single evening at the Grok Bot Community Engineering London Hackathon (22 Oct 2026) by two humans working alongside a team of Grok Bot agents. Each agent had its own chat, memory and job, and they handed work to each other the way a small team would.
Instead of picking a model on vibes, the agents built a labelled test set of 200 applicants (80 good fit, 50 borderline, 50 scammers, 10 bots, 10 cross-community repeats) and ran every candidate scorer on it.
| Model | Correct | False blocks | Scammers accepted |
|---|---|---|---|
| Jev (typesafe/jev-router) | 195/200 (97.5%) | 0 | 0 |
| GPT-6 Luna | 179/200 (89.5%) | 0 | 0 |
Honest misses: Jev sent 4 bots to "ask" rather than declining them, and accepted 1 borderline applicant it should have asked about. Full results are in data/eval_large_results.json.
openai/gpt-6-luna for best accuracy, 29/30 on test set)The shared blocklist lets communities warn each other about scammers without exposing member data:
HMAC-SHA256 hashing – Phone numbers, email addresses, and handles are hashed with a server-only secret (BLOCKLIST_HMAC_SECRET) before storage. The raw values never enter the database.
Handle normalization – Before hashing, handles are normalized (lowercase, strip @._- and trailing digits) so @cryptomax_alpha and @cryptomax_alpha1 produce the same hash and match.
Match-only checks – When another community checks a new applicant, the API returns only { match: true/false, matched_on: ["phone"|"handle"|"email"], status, reported_at }. The reporting community's identity and the evidence are never shared.
RLS (Row Level Security) – Each community sees only its own blocklist entries in full (with evidence). Cross-community matching happens server-side via the service role; moderators never query other communities' entries directly.
Confirmed entries only – The API checks only status='confirmed' entries. Demo mode auto-confirms for speed; production would require a second moderator to confirm before an entry becomes shared.
When a moderator reports a scammer:
HMAC-SHA256(normalize(phone)), HMAC-SHA256(normalize(handle)), HMAC-SHA256(normalize(email))status='confirmed'When another community checks an applicant:
blocklist_entries (service role, bypasses RLS) for matching HMACs where status='confirmed'@cryptomax_alpha to Community A and @cryptomax_alpha1 to Community B, normalization ensures both hash to the same value.audit_log with timestamps and actors.Install dependencies:
npm install
Set up environment variables:
Copy .env.example to .env.local and fill in:
NEXT_PUBLIC_SUPABASE_URL – Your Supabase project URLNEXT_PUBLIC_SUPABASE_ANON_KEY – Supabase anon public keySUPABASE_SERVICE_ROLE_KEY – Supabase service role key (server-only)BLOCKLIST_HMAC_SECRET – Secret for HMAC hashing (generate a random string, keep it safe)BOT_API_TOKEN – Bearer token for bot API accessGATEKEEPER_API_URL – Your deployed API URL (or http://localhost:3000 for dev)USE_MOCKS=true – Server-only flag for the mock routes and the queue page. The page receives it as a prop. Do not set NEXT_PUBLIC_USE_MOCKS.OPENROUTER_API_KEY – OpenRouter API key for LLM scoringSCORER_MODEL – Model to use (recommended: openai/gpt-6-luna for best accuracy; default: typesafe/jev-router)DISCORD_BOT_TOKEN – Discord bot token (optional)DISCORD_MOD_CHANNEL_ID – Discord mod channel ID (optional)COMMUNITY_SLUG – Your community slug (e.g. london-agent-builders)Apply Supabase migrations:
# Install Supabase CLI if needed: npm install -g supabase
supabase db push
# Or manually apply migrations in order: supabase/migrations/*.sql in your Supabase SQL editor
Run development server:
npm run dev
Visit http://localhost:3000
Run evaluation (optional):
npm run eval
# Scores all 30 test applicants, shows accuracy and false-block count
Test WhatsApp webhook (optional):
npx tsx scripts/simulate_whatsapp.ts
# Simulates a WhatsApp message with correct signature, no real phone needed
Greenlight can accept applications via WhatsApp using the official Meta WhatsApp Cloud API (no third-party libraries).
Create a Meta Business Account at business.facebook.com
Create a WhatsApp Business App in the Meta for Developers console
Add WhatsApp product to your app
Get credentials:
WHATSAPP_TOKEN: Permanent access token (Generate in Settings → WhatsApp → API Setup)WHATSAPP_PHONE_NUMBER_ID: Phone number ID from the test number or your own numberWHATSAPP_APP_SECRET: App secret from Settings → BasicWHATSAPP_VERIFY_TOKEN: Any random string you choose (used for webhook verification)WHATSAPP_COMMUNITY_SLUG: Which community receives WhatsApp applicationsConfigure webhook in WhatsApp → Configuration:
https://your-domain.com/api/whatsapp/webhookWHATSAPP_VERIFY_TOKEN abovemessages fieldTest with simulation script:
# Set WHATSAPP_APP_SECRET in .env.local
npx tsx scripts/simulate_whatsapp.ts
# Check /queue to see the scored application
POST /api/whatsapp/webhook with the messageaccept → "Thanks! Your application looks good, and a lead will confirm shortly."ask → Follow-up question from scorer's reason (e.g. "Missing info: which community do you run?")decline or blocklist hit → No auto-reply, goes to moderator queue/queue and makes final decisionAll decisions land in the queue. WhatsApp uses the channel adapter in lib/channels/.
Score an application against community rules and check the shared blocklist.
Request:
{
"community_slug": "london-agent-builders",
"application": {
"name": "Ada Testworth",
"handle": "@ada_builds",
"phone": "+44 7700 900101",
"email": "[email protected]",
"github": "ada-testworth-demo",
"text": "I'm building an open-source eval harness..."
}
}
Response:
{
"application_id": "uuid",
"decision": "accept"|"ask"|"decline",
"score": 95,
"reason": "Builds agents, open-source repo, offers to demo, London-based (rules 1, 2, 3).",
"signals": {
"rules_fit": {
"score": 95,
"rule_refs": ["london-agent-builders#1", "london-agent-builders#2"]
},
"spam_text": {
"score": 0.02,
"matched_patterns": []
},
"stopforumspam": {
"appears": false,
"frequency": 0,
"confidence": 0
},
"github": {
"exists": true,
"account_age_days": 450,
"public_repos": 8
},
"devpost": {
"projects_found": 2
},
"blocklist_hit": false
},
"blocklist_match": {
"matched_on": ["phone", "handle"],
"status": "confirmed",
"reported_at": "2026-10-22T18:00:00Z"
}
}
Signals:
rules_fit: LLM score (0-100) + rule citationsspam_text: Deterministic scam-text classifier (0-1 score, matched patterns)stopforumspam: StopForumSpam.org check (appears, frequency, confidence) or null if skippedgithub: GitHub account exists, age in days, public repo count, or null if skippeddevpost: Number of projects found on Devpost, or null if skippedblocklist_hit: Boolean, true if matched confirmed entry in shared blocklistblocklist_match: Present only when blocklist_hit is true; shows which fields matchedAll external checks (StopForumSpam, GitHub, Devpost) have 2s timeouts and are cached. They can never break scoring.
Record a moderator's final decision and optionally report to the shared blocklist.
Request:
{
"decision": "accept"|"decline",
"report_to_blocklist": true,
"evidence": "Crypto pump scam, identical to A21"
}
Response:
{
"ok": true,
"blocklist_entry_id": "uuid",
"blocklist_status": "confirmed"
}
Notes:
evidence is required when report_to_blocklist is trueconfirmed blocklist entry (demo mode; production would use pending → moderator review → confirmed)Check if identifiers match the shared blocklist.
Headers:
Authorization: Bearer <BOT_API_TOKEN>
Request:
{
"community_slug": "london-agent-builders",
"handle": "@cryptomax_alpha1",
"phone": "+44 7700 900901",
"email": "[email protected]"
}
Response:
{
"match": true,
"matched_on": ["phone", "handle"],
"status": "confirmed",
"reported_at": "2026-10-22T18:00:00Z"
}
Notes:
confirmed entriesA lead can turn Auto mode on per community at /settings (same gk_lead cookie as the queue). It is off by default.
When Auto mode is on, scoring may send a reply with no extra click, and only in these cases:
It never auto-sends:
signals.blocklist_hit or a blocklist_match)WhatsApp uses the Cloud API adapter. Successful sends are written to audit_log with auto=true, action='auto_send', and details {application_id, decision, channel} — no phone number. If the send fails, the failure is logged and the application stays in the queue. The queue header shows whether Auto mode is on, and an auto-sent badge marks items that were sent.
GET and PATCH /api/communities/:slug/settings read and update { auto_mode } with the service-role client. Both require the lead token.
supabase/migrations/*.sql in order.env.local above)INSERT INTO communities (slug, name, rules_md) VALUES ('your-slug', 'Your Community', '...');
-- First, create a moderator account via Supabase Auth (magic link)
-- Then add them to your community:
INSERT INTO moderators (user_id, community_id) VALUES ('<user-uuid>', '<community-uuid>');
USE_MOCKS=true to test with fixture dataUSE_MOCKS=false, share the /queue URL with moderatorsapp/ – Next.js App Router pages and API routes
api/score/ – Score applicant endpoint (real scoring with all signals)api/decisions/ – Moderator decision endpointapi/blocklist/ – Blocklist check endpoint (bot API)api/mock/ – Mock API routes (active when server USE_MOCKS=true; /api/_mock/* rewrites here)lib/ – Shared utilities
scorer.ts – OpenRouter LLM scorer (prompt v3, 29/30 accuracy on test set)spam-classifier.ts – Deterministic scam-text classifiersignals.ts – StopForumSpam, GitHub, Devpost API helpers with caching + timeoutshmac.ts – Handle/phone/email normalization + HMAC-SHA256supabase/ – Server (service role) and browser (anon) clientsscripts/ – Eval and utility scripts
eval.ts – Score all 30 test applicants, show accuracyeval_spam.ts – Evaluate spam_text classifier on SMS datasetfetch_sms_spam.ts – Download SMS spam dataset from HuggingFaceseed-demo.ts – Reset demo tables for clean demo runsupabase/migrations/ – Database schema
0001_init.sql – Tables, RLS policies, seed communities0002_rules.sql – Seed community rules from data/rules.md0004_auto_mode.sql – communities.auto_mode and audit_log.autofixtures/ – Mock data for /api/_mock/* routesdata/ – Fictional demo dataset (30 applicants, 2 communities, rules, expected decisions)docs/ – Build spec and handoff docsThe scorer has been tested with multiple models. For production:
Recommended: openai/gpt-6-luna
Budget-friendly: typesafe/jev-router (default)
Set via SCORER_MODEL environment variable. The code default is typesafe/jev-router.
The 30-applicant demo set is fictional. The 200-applicant eval set adds scrubbed spam texts to fictional applications:
All identities are fictional (Ofcom drama numbers, example.com). Sources, licences, and class counts are in data/DATASETS.md.
MIT – see LICENSE file