import { type RobotsVerdict } from './robots.js';
/**
* 네이버 서치어드바이저 — 검색 노출·색인 도구.
*
* 서치어드바이저에는 **공개 웹마스터 API 가 없다**(사이트 등록·사이트맵/RSS 제출·리포트는 콘솔 전용).
* 자동화할 수 있는 면은 두 가지뿐이라 그것만 다룬다:
* - IndexNow: 네이버가 참여 엔진이다. 새/수정/삭제 URL 을 즉시 알린다. 인증 = 사이트에 올린 키 파일.
* - 크롤러 관점 점검: 네이버 검색로봇(Yeti)이 보는 robots.txt·상태 코드·리다이렉트·메타 태그를 확인한다.
* 어느 쪽도 `~/.mimi-seed/` 자격증명을 쓰지 않는다.
*
* 점검 대상 사이트의 응답(HTML·robots.txt·헤더)은 **적대적 입력**으로 다룬다: 본문은 상한까지만 읽고,
* 파싱은 선형 스캔으로만 한다. 정규식 백트래킹이나 무한 버퍼링 한 번이면 stdio 서버 전체가 멈춘다.
*/
/** 네이버가 공개한 검색로봇 User-Agent. UA 로 봇을 막는 서버를 잡아내려고 그대로 보낸다. */
export declare const YETI_USER_AGENT = "Mozilla/5.0 (compatible; Yeti/1.1; +https://naver.me/spd)";
/** indexnow.org/searchengines.json 에 등록된 네이버 엔드포인트. */
export declare const NAVER_INDEXNOW_ENDPOINT = "https://searchadvisor.naver.com/indexnow";
/** IndexNow 프로토콜: POST 1회 최대 URL 수. */
export declare const INDEXNOW_MAX_URLS = 10000;
/** IndexNow 프로토콜: 8–128자, 영문·숫자·대시. */
export declare const INDEXNOW_KEY_PATTERN: RegExp;
/** RFC 9309: 크롤러는 robots.txt 를 최소 500 KiB 까지 해석해야 한다. 그 이상은 버린다. */
export declare const ROBOTS_MAX_BYTES: number;
/** HTML 은 이만큼만 읽는다 — head·본문 추정에는 충분하고 메모리는 묶인다. */
export declare const HTML_MAX_BYTES: number;
/**
* 응답 본문을 `maxBytes` 까지만 읽고 나머지는 끊는다. 인코딩은 content-type 의 charset
* (EUC-KR 등 레거시 한국어 페이지 포함), 모르면 UTF-8. BOM 은 TextDecoder 가 벗긴다.
*/
export declare function readCapped(res: Response, maxBytes: number): Promise<{
text: string;
truncated: boolean;
}>;
export interface PageHead {
title?: string;
description?: string;
canonical?: string;
/** `` — 상대 canonical 을 풀 때 쓴다. */
base?: string;
lang?: string;
og: {
title?: string;
description?: string;
image?: string;
url?: string;
};
/** `` 와 `` 의 지시어(소문자). */
robots: string[];
naverSiteVerification: boolean;
/** script/style 을 뺀 원본 HTML 의 보이는 글자 수. */
textLength: number;
scriptCount: number;
}
export declare function decodeEntities(value: string): string;
/** 속성 문자열 파서. HTML 처럼 같은 이름은 **처음 것**이 이긴다. */
export declare function parseAttrs(src: string): Record;
export declare function parseHead(html: string): PageHead;
export interface XRobots {
/** 이 크롤러에 확실히 적용되는 지시어. */
applies: string[];
/**
* 다른 봇 접두어(`googlebot: …`) 뒤에 콤마로 이어진 지시어. 같은 헤더의 연속이면 그 봇 전용이지만,
* 헤더가 여러 개면 fetch 가 `, ` 로 합쳐 버려 **접두어 없는 별도 헤더**였을 수도 있다 — 구분할 수 없다.
*/
ambiguous: string[];
}
/**
* `X-Robots-Tag` 에서 이 크롤러에 적용되는 지시어를 뽑는다.
* UA 접두어가 없는 지시어는 모두에게, `yeti: …` 는 Yeti 에게, `googlebot: …` 은 건너뛴다.
*/
export declare function xRobotsDirectives(header: string | null, crawler?: string): XRobots;
/** HTTP `Link: <…>; rel="canonical"` 헤더의 대상. */
export declare function linkHeaderCanonical(header: string | null): string | undefined;
export type IssueLevel = 'error' | 'warn' | 'info';
export interface PageIssue {
level: IssueLevel;
code: string;
message: string;
}
export interface RedirectHop {
url: string;
status: number;
location: string;
}
export interface PageCheck {
url: string;
finalUrl: string;
status: number;
contentType: string | null;
redirects: RedirectHop[];
robotsTxt: {
url: string;
status: number | null;
verdict: RobotsVerdict | null;
sitemaps: string[];
};
directives: {
meta: string[];
header: string[];
headerAmbiguous: string[];
};
head: PageHead | null;
issues: PageIssue[];
summary: Record;
}
/** 네이버 검색로봇(Yeti) 관점에서 URL 1개를 점검한다. 쓰기 없음. */
export declare function checkPage(input: string): Promise;
export interface IndexNowInput {
urls: string[];
key: string;
/** 키 파일이 사이트 루트(`/.txt`)가 아닐 때만. */
keyLocation?: string;
}
export interface IndexNowResult {
endpoint: string;
status: number;
host: string;
keyLocation: string;
submitted: number;
}
/**
* 네이버 IndexNow 로 URL 변경을 알린다.
*
* 보내기 전에 키 파일을 직접 받아 key 와 같은지 확인한다 — 틀린 키는 엔드포인트가 403 만 돌려주고,
* 같은 호스트에 틀린 키로 반복 제출하면 스팸 판정 위험만 커진다. 같은 URL 재제출은 안전하다.
*/
export declare function submitIndexNow({ urls, key, keyLocation }: IndexNowInput): Promise;