fix(socials): canonicalize twitter.com → x.com in normalizeProfileUrl#755
Conversation
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 22 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe ChangesProfile URL Normalization
Estimated code review effort: 1 (Trivial) | ~3 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
lib/socials/normalizeProfileUrl.ts (1)
13-21: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSolid, well-anchored implementation.
The anchored
^twitter\.com(\/|$)pattern correctly avoids false positives (e.g.nottwitter.com,twitter.com.evil.com) while preserving handle casing. Good use of the capture group to retain the trailing slash or end-of-string boundary.One gap: the
www.(line 18) and protocol (line 17) stripping remain case-sensitive, so a host likeWWW.TWITTER.COM/handlewould skip both strips entirely and bypass the new alias rewrite too — sincestrippedwould still start withWWW.rather thantwitter.com. The scrape write-back path (handleTwitterProfileScraperResults.ts) masks this by calling.toLowerCase()afternormalizeProfileUrl, butupdateArtistSocials.tsdoes not, so mixed-case artist-submitted URLs could still land on a different key than expected — which is one of the two paths this PR states it fixes.💡 Optional fix: make protocol/www stripping case-insensitive
const stripped = url - .replace(/^https?:\/\//, "") - .replace(/^www\./, "") + .replace(/^https?:\/\//i, "") + .replace(/^www\./i, "") .replace(/\/$/, "");🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/socials/normalizeProfileUrl.ts` around lines 13 - 21, The normalizeProfileUrl helper still misses mixed-case inputs because the protocol and www stripping are case-sensitive, which can prevent the twitter.com to x.com rewrite from running. Update normalizeProfileUrl to handle case-insensitive protocol/www prefixes before the existing anchored twitter.com replacement, so URLs like WWW.TWITTER.COM/handle normalize consistently for both updateArtistSocials and handleTwitterProfileScraperResults.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@lib/socials/normalizeProfileUrl.ts`:
- Around line 13-21: The normalizeProfileUrl helper still misses mixed-case
inputs because the protocol and www stripping are case-sensitive, which can
prevent the twitter.com to x.com rewrite from running. Update
normalizeProfileUrl to handle case-insensitive protocol/www prefixes before the
existing anchored twitter.com replacement, so URLs like WWW.TWITTER.COM/handle
normalize consistently for both updateArtistSocials and
handleTwitterProfileScraperResults.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0d27d5b4-5664-4509-9bed-3ab10a072c0d
⛔ Files ignored due to path filters (1)
lib/socials/__tests__/normalizeProfileUrl.test.tsis excluded by!**/*.test.*,!**/__tests__/**and included bylib/**
📒 Files selected for processing (1)
lib/socials/normalizeProfileUrl.ts
There was a problem hiding this comment.
No issues found across 2 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant Scraper as Apify X Scraper
participant API as Artist Update API
participant Normalize as normalizeProfileUrl()
participant DB as Socials Table
participant Artist as Artist Entity
Note over Scraper,Artist: NEW: Canonical domain normalization ensures one upsert key
Scraper->>API: POST /artist/update (profile_url="https://x.com/ashnikko")
API->>Normalize: url = "https://x.com/ashnikko"
Normalize->>Normalize: strip protocol, www., trailing slash
Normalize->>Normalize: no twitter.com match → leave unchanged
Normalize-->>API: "x.com/ashnikko"
API->>DB: upsert socials WHERE profile_url = "x.com/ashnikko"
DB-->>API: row created/updated
API->>Artist: connect artist to socials.id
Note over Scraper,Artist: Any previous twitter.com links also map here
API->>Normalize: url="https://twitter.com/disclosure"
Normalize->>Normalize: strip protocol, www., trailing slash
Normalize->>Normalize: match "twitter.com/" case-insensitive → rewrite to "x.com/"
Normalize-->>API: "x.com/disclosure"
API->>DB: upsert socials WHERE profile_url = "x.com/disclosure"
DB-->>API: same row as x.com spelling (single canonical key)
alt Old behavior (before this PR)
Note over Normalize: Different keys for twitter.com vs x.com → twin rows
else New behavior (after this PR)
Note over Normalize,DB: One key → scrape updates existing artist links
end
Requires human review: Functional change to URL normalization that alters database upsert keys (twitter.com to x.com) – low risk but touches core data logic, better for human review.
Re-trigger cubic
Preview verification — 2026-07-06Preview: Method: created a throwaway artist under the test account, exercised
Done-when status (chat#1851):
No secrets echoed; test fixtures fully cleaned up. Merge order per the issue: this PR → database#40. |
X scrape write-backs land on x.com/* keys (the Apify actor echoes x.com) while artists stay connected to twitter.com/* rows, so follower counts never reach the connected social (recoupable/chat#1851). Canonicalizing in normalizeProfileUrl fixes both the scrape write-back and the artist profileUrls update path, which share this function for lookup + insert. Canonical domain decision (x.com) recorded on the issue, 2026-07-06. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
8521abf to
d08139a
Compare
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
…win rows (#40) Companion to recoupable/api#755 (normalizeProfileUrl canonicalization). Merges 403 twitter/x twin pairs (repointing 7 FK columns with unique- constraint guards) and renames 23,622 twinless twitter.com keys in place. Post-condition check raises if any twitter.com key survives. Tracking: recoupable/chat#1851 (PR #2 of 2 required). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
Canonicalizes
twitter.com/*→x.com/*insidenormalizeProfileUrlso every reader/writer agrees on onesocials.profile_urlupsert key. Fixes the X scrape gap where results persisted to orphanedx.com/*twin rows while artists stayed connected to staletwitter.com/*rows.Tracking issue: recoupable/chat#1851 (PR #1 of 2 required + 1 optional). Canonical-domain decision (x.com — official brand, matches the Apify actor's echo) recorded on the issue 2026-07-06.
What changed
lib/socials/normalizeProfileUrl.ts: after stripping protocol/www./trailing slash, rewrite a leadingtwitter.comhost tox.com(anchored —nottwitter.comand path occurrences untouched; case-insensitive host match; preserves handle casing).lib/socials/__tests__/normalizeProfileUrl.test.ts: 5 new canonicalization cases (equal keys for both spellings, x.com passthrough, no-false-positive domains, bare domain); 2 existing expectations updated to the new contract.Merge sequencing
No docs PR — no request/response contract change (same reasoning as docs#262 closed unmerged on chat#1840). This PR leads; the database dedupe migration (chat#1851 PR #2) follows it, since the migration implements the same canonical-domain decision. Independent of the optional tweetless-fallback PR.
Tests
vitest run lib/socials lib/apify lib/artist lib/artists→ 53 files, 263 tests passed.tsc --noEmit: 200 pre-existing errors on cleanorigin/test(all inlib/triggertests), 200 after — no new errors. eslint clean on changed files.Done-when (from chat#1851)
normalizeProfileUrl("https://x.com/Foo") === normalizeProfileUrl("https://twitter.com/Foo")twitter.com/*row updates that row (preview verification pending — note: full effect on existing rows also needs the PR adding inputSchema #2 migration, since current connected rows keep theirtwitter.comkeys until migrated)🤖 Generated with Claude Code
Summary by cubic
Canonicalizes twitter.com/* to x.com/* during profile URL normalization so all readers/writers use the same upsert key. Fixes X scrape write-backs landing on orphaned x.com rows while artists stayed linked to twitter.com (chat#1851).
Written for commit d08139a. Summary will update on new commits.
Summary by CodeRabbit
Bug Fixes
www., and trailing slashes so links are stored in a uniform way.Documentation