Some checks failed
deploy / deploy (push) Failing after 14s
- Главная: hero, адрес Люблинская 100 (Аквапарк ФЭНТАЗИ), 4 кликабельных tel:, карта Яндекса - /privacy: политика 152-ФЗ + ConsentRevoke (отозвать/сбросить) - Аналитика перенесена 1:1 с WP: Яндекс.Метрика 47169531 (Webvisor) + GA4 GT-WRF7ZZ8 - Скрипты в type=text/plain, активируются после согласия (pit-consent в localStorage+cookie) - robots.txt с явным Allow для GPTBot/ClaudeBot/PerplexityBot/Google-Extended/CCBot - llms.txt + ai.txt (spawning.ai стандарт) - IndexNow ключ 901a779d62ca4702ad810c863b45e1f7 - JSON-LD AutoPartsStore с адресом и 4 телефонами - nginx:1.29-alpine runtime, контейнер на :4147 - Gitea Actions deploy.yml + Trivy scan + IndexNow ping
76 lines
2.5 KiB
JavaScript
76 lines
2.5 KiB
JavaScript
// IndexNow: уведомить Yandex/Bing о новых/обновлённых URL.
|
||
// Запуск: node scripts/indexnow.js (из CI после деплоя или вручную)
|
||
import fs from 'node:fs';
|
||
import path from 'node:path';
|
||
import { fileURLToPath } from 'node:url';
|
||
|
||
const __filename = fileURLToPath(import.meta.url);
|
||
const __dirname = path.dirname(__filename);
|
||
const root = path.resolve(__dirname, '..');
|
||
const BASE = 'https://pitstopavto.su';
|
||
const HOST = 'pitstopavto.su';
|
||
const KEY = '901a779d62ca4702ad810c863b45e1f7';
|
||
|
||
const keyFile = path.join(root, 'public', `${KEY}.txt`);
|
||
if (!fs.existsSync(keyFile)) {
|
||
fs.writeFileSync(keyFile, KEY, 'utf-8');
|
||
console.log(`created key file: public/${KEY}.txt`);
|
||
}
|
||
|
||
function extractLocs(xml) {
|
||
return [...xml.matchAll(/<loc>([^<]+)<\/loc>/g)].map((m) => m[1].trim());
|
||
}
|
||
|
||
let urls = [];
|
||
const distDir = path.join(root, 'dist');
|
||
const sitemapIndex = path.join(distDir, 'sitemap-index.xml');
|
||
|
||
if (fs.existsSync(sitemapIndex)) {
|
||
const idx = fs.readFileSync(sitemapIndex, 'utf-8');
|
||
for (const sub of extractLocs(idx)) {
|
||
const fname = sub.split('/').pop();
|
||
const localPath = path.join(distDir, fname);
|
||
if (fs.existsSync(localPath)) {
|
||
urls.push(...extractLocs(fs.readFileSync(localPath, 'utf-8')));
|
||
}
|
||
}
|
||
} else {
|
||
console.log('no local sitemap-index.xml, fetching from production…');
|
||
try {
|
||
const idxResp = await fetch(`${BASE}/sitemap-index.xml`);
|
||
if (!idxResp.ok) throw new Error(`HTTP ${idxResp.status}`);
|
||
for (const sub of extractLocs(await idxResp.text())) {
|
||
const subResp = await fetch(sub);
|
||
if (!subResp.ok) continue;
|
||
urls.push(...extractLocs(await subResp.text()));
|
||
}
|
||
} catch (e) {
|
||
console.error(`failed to fetch sitemap from ${BASE}: ${e.message}`);
|
||
process.exit(1);
|
||
}
|
||
}
|
||
|
||
urls = [...new Set(urls)].filter((u) => u.startsWith(BASE));
|
||
if (urls.length === 0) { console.error('no URLs collected'); process.exit(1); }
|
||
|
||
console.log(`Submitting ${urls.length} URLs to IndexNow…`);
|
||
const payload = { host: HOST, key: KEY, keyLocation: `${BASE}/${KEY}.txt`, urlList: urls };
|
||
|
||
async function submit(endpoint) {
|
||
try {
|
||
const r = await fetch(endpoint, {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json; charset=utf-8' },
|
||
body: JSON.stringify(payload),
|
||
});
|
||
console.log(` ${endpoint}: HTTP ${r.status}`);
|
||
} catch (e) {
|
||
console.error(` ${endpoint}: ${e.message}`);
|
||
}
|
||
}
|
||
|
||
await Promise.all([
|
||
submit('https://yandex.com/indexnow'),
|
||
submit('https://api.indexnow.org/indexnow'),
|
||
]);
|