Repository navigation
Post email-intake coupons to the c0upons.com/bbs forums - #82
Merged
Merged
Conversation
Each coupon submit@c0upons.com creates gets a thread on the tsbb board, in the forum its words fit (freebies, grocery, tech, home, fashion, travel; else Coupons & Promo Codes for a code, Hot Deals for a sale), linking to its page. - lib/bbs-post.ts: pickForum, topicFor, postCouponsToBbs (POST /api/v1/forums/<slug>/topics with BBS_POST_TOKEN; bbs_posts table so a coupon is posted once; 16 s spacing and one retry for tsbb's flood guard) - inbound-email: returns `created` (id, store slug, code, discount, expiry) for the coupons it inserted; the webhook posts them after answering - ops/bbs/mint-poster.ts: board user `c0upons` + its token (already run; token in vault c0upons--prod) - 7 tests (forums, thread text, once-only, flood retry, no token, refusals, intake hand-over) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| let last = 0; | ||
| for (const c of coupons) { | ||
| const forum = pickForum(c); | ||
| const prior = await db.sql`SELECT status, topic_url FROM bbs_posts WHERE coupon_id = ${c.id} LIMIT 1`; |
| }); | ||
| result.posted.push({ store: name, code: o.code, title: o.title }); | ||
| // upsertCoupon returns nothing; the row's id is what its page and its thread link to. | ||
| const row = await db.sql`SELECT id FROM coupons WHERE source = ${SOURCE} AND source_id = ${sourceId} LIMIT 1`; |
| const out = await postCouponsToBbs(db, [coupon({ id: 301 })], { fetch: b.fetch, token: '', sleep: noSleep }); | ||
| assert.equal(out[0].status, 'disabled'); | ||
| assert.equal(b.calls.length, 0); | ||
| const rows = await db.sql`SELECT * FROM bbs_posts WHERE coupon_id = ${301}`.catch(() => []); |
| assert.equal(out[0].status, 'failed'); | ||
| assert.match(out[0].error, /403/); | ||
| assert.equal(calls.length, 1); | ||
| const [row] = await db.sql`SELECT status FROM bbs_posts WHERE coupon_id = ${401}`; |
| ); | ||
| assert.equal(res.outcome, 'posted'); | ||
| assert.equal(res.created.length, 1); | ||
| const [row] = await db.sql`SELECT id, code FROM coupons WHERE id = ${res.created[0].id}`; |
ThreatCrush Security Scan37 finding(s) MEDIUM: 31 | LOW: 6
Snippets are redacted; ThreatCrush never prints matched credential material. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Every coupon that mail to submit@c0upons.com creates now also gets a thread on https://c0upons.com/bbs, in the forum that fits it, linking back to its coupon page. This applies to the email intake only: the nichedb, Flipp and Reddit syncs import in bulk and would flood the forums.
Store: offer (code X). The body has store, code, deal and expiry, plus "Get this deal on c0upons".bbs_poststable makes sure a coupon is posted once.floodingrefusal (its guard is 15 s per account). The webhook doesn't wait for this: it answers Forward Email first.c0upons(Pages cache with empty data — Next.js Full Route Cache not bypassed #4) using atsbb_token.ops/bbs/mint-poster.tswas run on the live board, and the token is in vaultc0upons--prodasBBS_POST_TOKEN.GET /bbs/api/v1/mewith the token answersc0upons.Verified
bun test test: 77 pass, including 7 new ones covering:tsc --noEmitand eslint on the changed files are clean.After merge
CI deploys to dev2, and the deploy's vault step puts
BBS_POST_TOKENinto app.env. The next real offer mail will open a thread.🤖 Generated with Claude Code