mcp-scraper 0.3.22 → 0.3.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9644,14 +9644,14 @@ var init_rates = __esm({
9644
9644
  paa: 100,
9645
9645
  page_scrape: 100,
9646
9646
  url_map: 2e3,
9647
- yt_channel: 50,
9647
+ yt_channel: 100,
9648
9648
  yt_transcription: 200,
9649
- fb_ad: 50,
9649
+ fb_ad: 100,
9650
9650
  maps_search: 2e3,
9651
9651
  maps_place: 2e3,
9652
- maps_review: 50,
9653
- fb_search: 50,
9654
- fb_transcribe: 50,
9652
+ maps_review: 100,
9653
+ fb_search: 100,
9654
+ fb_transcribe: 200,
9655
9655
  instagram_profile: 100,
9656
9656
  instagram_media: 100,
9657
9657
  instagram_transcribe: 50,
@@ -9749,11 +9749,11 @@ var init_rates = __esm({
9749
9749
  },
9750
9750
  {
9751
9751
  key: "fb_transcribe",
9752
- label: "Facebook ad transcription",
9753
- aliases: ["facebook_transcribe", "fb_transcribe", "fb ad transcript"],
9752
+ label: "Facebook video / ad transcription",
9753
+ aliases: ["facebook_transcribe", "facebook_video_transcribe", "fb_transcribe", "fb ad transcript"],
9754
9754
  credits: mcToCredits(MC_COSTS.fb_transcribe),
9755
- unit: "per call",
9756
- notes: "Whisper transcription of Facebook ad video via fal.ai."
9755
+ unit: "per minute",
9756
+ notes: "A hold is taken, then reconciled to actual video duration."
9757
9757
  },
9758
9758
  {
9759
9759
  key: "instagram_profile",
@@ -9784,15 +9784,15 @@ var init_rates = __esm({
9784
9784
  label: "Interactive browser session",
9785
9785
  aliases: ["browser_open", "browser agent", "browser_agent", "live browser", "browse", "browser control", "interactive browser"],
9786
9786
  credits: mcToCredits(MC_COSTS.browser_minute),
9787
- unit: "per minute the browser is open",
9788
- notes: "Metered for the full time the browser session is open (active or idle) \u2014 every minute the session stays alive is billed. Close the session to stop the meter; abandoned sessions are auto-closed after a short idle window."
9787
+ unit: "per minute of use",
9788
+ notes: "Metered per minute of use for the whole time the browser session is open. Close the session to stop the meter; abandoned sessions are auto-closed after a short idle window."
9789
9789
  }
9790
9790
  ];
9791
9791
  CONCURRENCY_PRICE_ID = "price_1Ta1NRS8aAcsk3TGwsRnYbix";
9792
9792
  SUBSCRIPTION_TIERS = {
9793
- "price_1TmiHRS8aAcsk3TGwmSNfNIa": { tier: "starter", label: "Starter", price_id: "price_1TmiHRS8aAcsk3TGwmSNfNIa", monthly_usd: 12, credits_mc: 10312500, concurrency: 3, intro_coupon: "mcp-starter-1dollar-intro-12" },
9794
- "price_1Tmg1nS8aAcsk3TGe8zcnGTM": { tier: "growth", label: "Growth", price_id: "price_1Tmg1nS8aAcsk3TGe8zcnGTM", monthly_usd: 100, credits_mc: 9075e4, concurrency: 10, intro_coupon: null },
9795
- "price_1Tmg1nS8aAcsk3TGsZw34iXS": { tier: "scale", label: "Scale", price_id: "price_1Tmg1nS8aAcsk3TGsZw34iXS", monthly_usd: 250, credits_mc: 226875e3, concurrency: 20, intro_coupon: null }
9793
+ "price_1TmiHRS8aAcsk3TGwmSNfNIa": { tier: "starter", label: "Starter", price_id: "price_1TmiHRS8aAcsk3TGwmSNfNIa", monthly_usd: 12, credits_mc: 8e6, concurrency: 3, intro_coupon: "mcp-starter-1dollar-intro-12" },
9794
+ "price_1Tmg1nS8aAcsk3TGe8zcnGTM": { tier: "growth", label: "Growth", price_id: "price_1Tmg1nS8aAcsk3TGe8zcnGTM", monthly_usd: 100, credits_mc: 8e7, concurrency: 10, intro_coupon: null },
9795
+ "price_1Tmg1nS8aAcsk3TGsZw34iXS": { tier: "scale", label: "Scale", price_id: "price_1Tmg1nS8aAcsk3TGsZw34iXS", monthly_usd: 250, credits_mc: 24e7, concurrency: 20, intro_coupon: null }
9796
9796
  };
9797
9797
  SUBSCRIPTION_TIER_BY_KEY = Object.fromEntries(
9798
9798
  Object.values(SUBSCRIPTION_TIERS).map((t) => [t.tier, t])
@@ -14445,17 +14445,22 @@ var init_facebook_ad_routes = __esm({
14445
14445
  });
14446
14446
  if (!gate.ok) return c.json(concurrencyLimitExceededResponse(gate), 429, { "Retry-After": String(gate.retryAfterSeconds) });
14447
14447
  import_client5.fal.config({ credentials: process.env.FAL_KEY });
14448
+ const holdMc = MC_COSTS.fb_transcribe * 5;
14448
14449
  let debited = false;
14449
14450
  try {
14450
- const { ok, balance_mc } = await debitMc(fbUser.id, MC_COSTS.fb_transcribe, LedgerOperation.FB_TRANSCRIBE, videoUrl);
14451
- if (!ok) return c.json(insufficientBalanceResponse(balance_mc, MC_COSTS.fb_transcribe), 402);
14451
+ const { ok, balance_mc } = await debitMc(fbUser.id, holdMc, LedgerOperation.FB_TRANSCRIBE, videoUrl);
14452
+ if (!ok) return c.json(insufficientBalanceResponse(balance_mc, holdMc), 402);
14452
14453
  debited = true;
14453
14454
  const transcript = await transcribeFacebookVideoUrl(videoUrl, "# Facebook Ad Transcript");
14455
+ const actualMins = Math.max(1, Math.ceil((Number.isFinite(transcript.durationMs) ? transcript.durationMs / 1e3 : 60) / 60));
14456
+ const diff = holdMc - MC_COSTS.fb_transcribe * actualMins;
14457
+ if (diff > 0) await creditMc(fbUser.id, diff, LedgerOperation.FB_TRANSCRIBE_REFUND, "overestimate refund");
14458
+ else if (diff < 0) await debitMc(fbUser.id, -diff, LedgerOperation.FB_TRANSCRIBE, videoUrl);
14454
14459
  await logRequestEvent({ userId: fbUser.id, source: "facebook_transcribe", status: "done", query: videoUrl, resultCount: transcript.chunks.length, result: { text: transcript.text, chunks: transcript.chunks, durationMs: transcript.durationMs } });
14455
14460
  return c.json(transcript);
14456
14461
  } catch (err) {
14457
14462
  const msg = err instanceof Error ? err.message : String(err);
14458
- if (debited) await creditMc(fbUser.id, MC_COSTS.fb_transcribe, LedgerOperation.FB_TRANSCRIBE_REFUND, "failed call");
14463
+ if (debited) await creditMc(fbUser.id, holdMc, LedgerOperation.FB_TRANSCRIBE_REFUND, "failed call");
14459
14464
  await logRequestEvent({ userId: fbUser.id, source: "facebook_transcribe", status: "failed", query: videoUrl, error: msg });
14460
14465
  return c.json({ error: msg }, 500);
14461
14466
  } finally {
@@ -14485,16 +14490,21 @@ var init_facebook_ad_routes = __esm({
14485
14490
  if (!gate.ok) return c.json(concurrencyLimitExceededResponse(gate), 429, { "Retry-After": String(gate.retryAfterSeconds) });
14486
14491
  import_client5.fal.config({ credentials: process.env.FAL_KEY });
14487
14492
  const driver = new BrowserDriver();
14493
+ const holdMc = MC_COSTS.fb_transcribe * 5;
14488
14494
  let debited = false;
14489
14495
  try {
14490
- const { ok, balance_mc } = await debitMc(fbUser.id, MC_COSTS.fb_transcribe, LedgerOperation.FB_TRANSCRIBE, sourceUrl.href);
14491
- if (!ok) return c.json(insufficientBalanceResponse(balance_mc, MC_COSTS.fb_transcribe), 402);
14496
+ const { ok, balance_mc } = await debitMc(fbUser.id, holdMc, LedgerOperation.FB_TRANSCRIBE, sourceUrl.href);
14497
+ if (!ok) return c.json(insufficientBalanceResponse(balance_mc, holdMc), 402);
14492
14498
  debited = true;
14493
14499
  await driver.launch(await kernelLaunchOptsResidential());
14494
14500
  await driver.navigateTo(sourceUrl.href);
14495
14501
  const page = driver.getPage();
14496
14502
  const video = await extractFacebookOrganicVideoFromPage(page, sourceUrl.href, body.quality);
14497
14503
  const transcript = await transcribeFacebookVideoUrl(video.videoUrl, "# Facebook Organic Video Transcript");
14504
+ const actualMins = Math.max(1, Math.ceil((Number.isFinite(transcript.durationMs) ? transcript.durationMs / 1e3 : 60) / 60));
14505
+ const diff = holdMc - MC_COSTS.fb_transcribe * actualMins;
14506
+ if (diff > 0) await creditMc(fbUser.id, diff, LedgerOperation.FB_TRANSCRIBE_REFUND, "overestimate refund");
14507
+ else if (diff < 0) await debitMc(fbUser.id, -diff, LedgerOperation.FB_TRANSCRIBE, sourceUrl.href);
14498
14508
  const result = {
14499
14509
  ...video,
14500
14510
  videoDurationSec: video.durationSec,
@@ -14507,7 +14517,7 @@ var init_facebook_ad_routes = __esm({
14507
14517
  return c.json(result);
14508
14518
  } catch (err) {
14509
14519
  const msg = err instanceof Error ? err.message : String(err);
14510
- if (debited) await creditMc(fbUser.id, MC_COSTS.fb_transcribe, LedgerOperation.FB_TRANSCRIBE_REFUND, "failed call");
14520
+ if (debited) await creditMc(fbUser.id, holdMc, LedgerOperation.FB_TRANSCRIBE_REFUND, "failed call");
14511
14521
  await logRequestEvent({ userId: fbUser.id, source: "facebook_video_transcribe", status: "failed", query: sourceUrl.href, error: msg });
14512
14522
  if (msg.toLowerCase().includes("blocked") || msg.toLowerCase().includes("captcha")) {
14513
14523
  return c.json({ error: msg }, 503);
@@ -23881,7 +23891,7 @@ var PACKAGE_VERSION;
23881
23891
  var init_version = __esm({
23882
23892
  "src/version.ts"() {
23883
23893
  "use strict";
23884
- PACKAGE_VERSION = "0.3.22";
23894
+ PACKAGE_VERSION = "0.3.24";
23885
23895
  }
23886
23896
  });
23887
23897