haixunMaster/lib/scan-recency.ts

83 lines
3.1 KiB
TypeScript
Raw Normal View History

2026-06-21 12:50:31 +00:00
/** 置入模式:超過此天數的貼文不適合留言推薦(求助通常已解決) */
export const PLACEMENT_MAX_POST_AGE_DAYS = 30;
/** 置入黃金窗口7 天內留言區仍活躍、需求多半未關閉 */
export const PLACEMENT_IDEAL_MAX_AGE_DAYS = 7;
/** 網搜 after: 篩選用,略寬於黃金窗口以補足結果 */
export const PLACEMENT_WEB_SEARCH_MAX_AGE_DAYS = 14;
/** 置入模式Brave 網搜單次海巡最多查詢次數 */
export const PLACEMENT_WEB_SEARCH_MAX_QUERIES = 8;
/** 置入模式Brave 網搜找到足夠貼文後即停止 */
export const PLACEMENT_WEB_SEARCH_TARGET_POSTS = 20;
/** 置入模式Threads API瀏覽器已找到足夠貼文時跳過 Brave 網搜 */
export const PLACEMENT_WEB_SEARCH_SKIP_IF_POSTS = 15;
/** 一般模式Brave 網搜單次海巡最多查詢次數 */
export const DEFAULT_WEB_SEARCH_MAX_QUERIES = 12;
export function postAgeDays(postedAt: Date, now = Date.now()): number {
return (now - postedAt.getTime()) / (1000 * 60 * 60 * 24);
}
export function postAgeHours(postedAt: Date, now = Date.now()): number {
return (now - postedAt.getTime()) / (1000 * 60 * 60);
}
export function isPostFreshEnough(
postedAt: Date | null | undefined,
maxAgeDays: number = PLACEMENT_MAX_POST_AGE_DAYS
): boolean {
if (!postedAt) return true;
return postAgeDays(postedAt) <= maxAgeDays;
}
/** 0100置入排序用越近期分數越高 */
export function computePlacementRecencyScore(
postedAt: Date | null | undefined,
now = Date.now()
): number {
if (!postedAt) return 35;
const hours = postAgeHours(postedAt, now);
if (hours <= 6) return 100;
if (hours <= 24) return 95;
if (hours <= 48) return 88;
if (hours <= 72) return 80;
const days = postAgeDays(postedAt, now);
if (days <= PLACEMENT_IDEAL_MAX_AGE_DAYS) return 70;
if (days <= 14) return 50;
if (days <= PLACEMENT_MAX_POST_AGE_DAYS) return 30;
return 0;
}
export function formatGoogleAfterDate(maxAgeDays: number, now = Date.now()): string {
const date = new Date(now - maxAgeDays * 24 * 60 * 60 * 1000);
const y = date.getUTCFullYear();
const m = String(date.getUTCMonth() + 1).padStart(2, "0");
const d = String(date.getUTCDate()).padStart(2, "0");
return `${y}-${m}-${d}`;
}
export function formatPostAgeLabel(postedAt?: Date | null): string {
if (!postedAt) return "發文日期未知";
const days = Math.floor(postAgeDays(postedAt));
if (days <= 0) return "今天";
if (days === 1) return "昨天";
if (days < 7) return `${days} 天前`;
if (days < 30) return `${Math.floor(days / 7)} 週前`;
return `${days} 天前`;
}
export function formatPlacementTimingHint(postedAt?: Date | null): string {
if (!postedAt) return "發文時間未知(置入窗口不明,需保守評估)";
const hours = postAgeHours(postedAt);
if (hours <= 24) return "剛發不久,置入窗口最佳";
if (hours <= 72) return "近 3 天內,置入窗口良好";
const days = Math.floor(postAgeDays(postedAt));
if (days <= PLACEMENT_IDEAL_MAX_AGE_DAYS) return "一週內,仍可置入";
if (days <= PLACEMENT_MAX_POST_AGE_DAYS) return "已超過一週,置入窗口收窄";
return "過舊,不建議置入";
}