fix: TikTok Shop Apify girdi semasini duzelt

This commit is contained in:
2026-08-10 12:14:11 +03:00
parent 2b75e97ad6
commit cf1982a299
4 changed files with 14 additions and 3 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ import { planFromUser } from "@/lib/plans";
import { checkAndConsumeQuota, refundQuota } from "@/lib/quota";
import { hizSiniriAsimi } from "@/lib/rate-limit";
const schema = z.object({ query: z.string().trim().min(2).max(100), region: z.enum(["US", "GB", "DE", "FR", "TR"]).default("US"), maxResults: z.coerce.number().int().refine((v) => [10, 25, 50].includes(v)) });
const schema = z.object({ query: z.string().trim().min(2).max(100), region: z.enum(["US", "GB", "SG", "MY", "PH", "TH", "VN", "ID"]).default("US"), maxResults: z.coerce.number().int().refine((v) => [10, 25, 50].includes(v)) });
export async function POST(request: Request) {
const limited = hizSiniriAsimi(request, "arama");
+1 -1
View File
@@ -21,7 +21,7 @@ export function TikTokShopImport({ planLimit }: { planLimit: number }) {
}
return <div className="mb-5 grid gap-3 rounded-3xl bg-white p-4 shadow-soft md:grid-cols-[1fr_120px_130px_130px]">
<input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="TikTok Shop ürününü canlı ara" className="rounded-2xl border border-slate-200 px-4 py-3" />
<select value={region} onChange={(e) => setRegion(e.target.value)} className="rounded-2xl border border-slate-200 px-3"><option>US</option><option>GB</option><option>DE</option><option>FR</option><option>TR</option></select>
<select value={region} onChange={(e) => setRegion(e.target.value)} className="rounded-2xl border border-slate-200 px-3"><option>US</option><option>GB</option><option>SG</option><option>MY</option><option>PH</option><option>TH</option><option>VN</option><option>ID</option></select>
<select value={count} onChange={(e) => setCount(Number(e.target.value))} className="rounded-2xl border border-slate-200 px-3">{[10,25,50].filter((v) => v <= planLimit).map((v) => <option key={v} value={v}>{v} ürün</option>)}</select>
<button type="button" onClick={run} disabled={busy || planLimit === 0 || query.trim().length < 2} className="rounded-2xl bg-slate-950 px-4 py-3 font-bold text-white disabled:opacity-50">{busy ? "Getiriliyor…" : planLimit ? "Apifydan getir" : "Planı yükselt"}</button>
{message && <p className="text-sm font-semibold text-violet-700 md:col-span-4">{message}</p>}
+5 -1
View File
@@ -47,7 +47,7 @@ export async function runTikTokShopActor(input: { query: string; region: string;
const response = await fetch(`${API_BASE}/actors/${actor}/run-sync-get-dataset-items?${params}`, {
method: "POST",
headers: { authorization: `Bearer ${token}`, "content-type": "application/json", accept: "application/json" },
body: JSON.stringify({ search_word: input.query, region: input.region, maxItems: input.maxResults, enrichProductDetails: false }),
body: JSON.stringify(tikTokActorInput(input)),
signal: controller.signal,
cache: "no-store"
});
@@ -61,6 +61,10 @@ export async function runTikTokShopActor(input: { query: string; region: string;
} finally { clearTimeout(timer); }
}
export function tikTokActorInput(input: { query: string; region: string; maxResults: number }) {
return { keyword: input.query, region: input.region, maxItems: input.maxResults, addonProductDetails: false };
}
export async function importTikTokProducts(rows: Row[], region: string) {
let imported = 0;
let failed = 0;
+7
View File
@@ -5,6 +5,7 @@ import { normalizeApifyAd } from "../src/lib/apify";
import { getFeatureLimit } from "../src/lib/plans";
import { istemciIp, hizSiniriAsimi } from "../src/lib/rate-limit";
import { stripePriceFor } from "../src/lib/stripe";
import { tikTokActorInput } from "../src/lib/apify-tiktok";
test("Apify reklamı metin, medya ve ülke alanlarıyla normalize edilir", () => {
const ad = normalizeApifyAd({
@@ -49,3 +50,9 @@ test("Stripe fiyat kimliği env allowlist'inden okunur", () => {
if (previous === undefined) delete process.env.STRIPE_PRICE_BASIC_MONTHLY;
else process.env.STRIPE_PRICE_BASIC_MONTHLY = previous;
});
test("TikTok aktör girdisi resmi şemadaki alanları kullanır", () => {
assert.deepEqual(tikTokActorInput({ query: "phone case", region: "US", maxResults: 10 }), {
keyword: "phone case", region: "US", maxItems: 10, addonProductDetails: false
});
});