SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
10 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%
3.9 KB · 98 lines typescript
Raw Blame History
1import type { ConnectorMeta } from '@rareindex/connectors';2import { CertLookupConnector, type PageStatus, type ParsedCert } from '../_g2-grading-lib/cert-base.js';3import { ccgClassify, ccgParse, ccgTrim, pick } from '../_g2-grading-lib/ccg.js';4import { clean, comicsCategorySlug, parseCardGrade, parseDate, yearOf } from '../_g2-grading-lib/text.js';56/**7 * CGC Comics certificate verification — https://www.cgccomics.com/certlookup/<cert>/ (public; the CGC8 * census / population report proper is login-gated and never fetched). Same CCG AngularJS template as9 * NGC/PMG/CGC Cards; behind a Cloudflare managed challenge, rendered by Firecrawl.10 */11const PARSER_VERSION = '1.0.0';12const PATTERNS = [/^https?:\/\/(?:www\.)?cgccomics\.com\/(?:certlookup\/)?(\d{6,12})\/?(?:[?#].*)?$/i];1314export function certUrl(cert: string): string {15  return `https://www.cgccomics.com/certlookup/${clean(cert).replace(/\D/g, '')}/`;16}1718export function certFromUrl(url: string): string | null {19  const m = url.match(PATTERNS[0]!);20  return m ? m[1]! : null;21}2223export class CgcCertConnector extends CertLookupConnector {24  readonly version = '1.0.0';25  readonly parserVersion = PARSER_VERSION;26  readonly grader = 'cgc';27  readonly idKey = 'cgc_cert';28  readonly format = 'html' as const;29  override readonly urlPatterns = PATTERNS;3031  certUrl(cert: string): string {32    return certUrl(cert);33  }34  certFromUrl(url: string): string | null {35    return certFromUrl(url);36  }37  classify(doc: string): PageStatus {38    return ccgClassify(doc);39  }40  trim(doc: string): string {41    return ccgTrim(doc);42  }4344  parse(snapshot: string, info: { cert: string; url: string }): ParsedCert | null {45    const page = ccgParse(snapshot);46    const f = page.fields;47    const cert = pick(f, 'CGC Cert #', 'Cert #', 'Cert') ?? info.cert;48    const title = pick(f, 'Title');49    if (!title) return null;50    const issue = pick(f, 'Issue');51    const publisher = pick(f, 'Publisher');52    const issueDate = pick(f, 'Issue Date');53    const gradeRaw = pick(f, 'Grade');54    const g = parseCardGrade(gradeRaw);55    const label = pick(f, 'Label Category');56    const labelQualifier = label && !/^universal$/i.test(label) ? label : null;57    const qualifier = [g.qualifier, labelQualifier].filter(Boolean).join(' ') || null;58    const year = yearOf(pick(f, 'Issue Year')) ?? parseDate(issueDate)?.getUTCFullYear() ?? null;59    const keyComments = page.lines['Key Comments'] ?? [];60    const variant = pick(f, 'Variant', 'Variant Description', 'Edition') ?? null;61    const rawTitle = `${title}${issue ? ` #${issue}` : ''}${publisher || issueDate ? ` (${[publisher, issueDate].filter(Boolean).join(', ')})` : ''}${gradeRaw ? ` CGC ${gradeRaw}` : ''}${labelQualifier ? ` ${labelQualifier}` : ''}`;62    return {63      title: rawTitle,64      attributes: {65        categorySlug: comicsCategorySlug(publisher),66        brand: publisher,67        series: title,68        name: `${title}${issue ? ` #${issue}` : ''}`,69        number: issue,70        year,71        variant,72        identifiers: {},73        metadata: {74          cgc_cert: cert,75          issue_date: issueDate,76          page_quality: pick(f, 'Page Quality'),77          grade_date: pick(f, 'Grade Date'),78          label_category: label,79          art_comments: page.lines['Art Comments'] ?? null,80          key_comments: keyComments.length ? keyComments : null,81          grader_notes: page.lines['Grader Notes'] ?? null,82          population_url: page.populationUrl,83          fields: f,84        },85      },86      grade: g.grade,87      qualifier,88      gradeLabel: g.label || null,89      description: keyComments.length ? keyComments.join(' ') : null,90      images: page.images,91      population: page.atGrade !== null ? { gradeKey: g.grade ?? page.popGradeKey ?? g.label, atGrade: page.atGrade, higher: page.higher, url: page.populationUrl } : null,92      confidence: 0.92,93    };94  }95}9697export default (meta: ConnectorMeta) => new CgcCertConnector(meta);98