<?php
// ================= CONFIG =================
$indexNowKey     = '5f16385d675b4e4d81093cad20b17089';            // ← Your generated IndexNow key
$yourHost        = 'https://discordbooster.com';                  // ← Your verified site (with https://)
$keyFileLocation = $yourHost . '/' . $indexNowKey . '.txt';       // Must be publicly accessible

// Where to read the sitemap from. Local path is tried first (faster, no HTTP),
// then the URL is used as a fallback. Adjust to match where the file actually lives.
$sitemapLocalPath = __DIR__ . '/sitemap7.xml';                    // ← Local file next to this script
$sitemapUrl       = $yourHost . '/sitemap7.xml';                  // ← Public URL fallback

$batchSize = 100; // URLs per IndexNow POST request (IndexNow allows up to 10,000)

// ================= FUNCTIONS =================

/**
 * Load the sitemap XML from a local file (preferred) or remote URL (fallback).
 * Returns the raw XML string, or null on failure.
 */
function loadSitemap($localPath, $url) {
    if (is_readable($localPath)) {
        $xml = @file_get_contents($localPath);
        if ($xml !== false && $xml !== '') {
            return $xml;
        }
    }

    // Fallback: fetch over HTTP
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 15,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_USERAGENT      => 'IndexNow-Submitter/1.0',
    ]);
    $xml = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($xml !== false && $code >= 200 && $code < 300 && $xml !== '') {
        return $xml;
    }

    return null;
}

/**
 * Extract all <loc> URLs from sitemap XML.
 * Keeps only URLs that belong to $host. Returns a de-duplicated array.
 */
function extractUrlsFromSitemap($xmlString, $host) {
    $urls = [];

    // Prefer proper XML parsing; fall back to regex if libxml is unavailable.
    $prev = libxml_use_internal_errors(true);
    $xml  = simplexml_load_string($xmlString);
    libxml_use_internal_errors($prev);

    if ($xml !== false) {
        // Namespaces vary, so just walk every <loc> node we can find.
        foreach ($xml->xpath('//*[local-name()="loc"]') as $loc) {
            $u = trim((string) $loc);
            if ($u !== '') {
                $urls[] = $u;
            }
        }
    } else {
        // Regex fallback
        if (preg_match_all('/<loc>\s*(.*?)\s*<\/loc>/is', $xmlString, $m)) {
            foreach ($m[1] as $u) {
                $u = trim(html_entity_decode($u));
                if ($u !== '') {
                    $urls[] = $u;
                }
            }
        }
    }

    // Keep only same-host URLs, de-duplicate, re-index.
    $urls = array_filter($urls, function ($u) use ($host) {
        return strpos($u, $host) === 0;
    });

    return array_values(array_unique($urls));
}

/**
 * Submit a single URL via simple GET (kept for the single-URL form).
 */
function submitUrlToIndexNow($urlToSubmit, $key) {
    $endpoint     = 'https://api.indexnow.org/indexnow';
    $simpleGetUrl = $endpoint . '?url=' . urlencode($urlToSubmit) . '&key=' . urlencode($key);

    $ch = curl_init($simpleGetUrl);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_FOLLOWLOCATION => true,
    ]);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error    = curl_error($ch);
    curl_close($ch);

    $ok = ($httpCode >= 200 && $httpCode < 300);
    return [
        'success'   => $ok,
        'http_code' => $httpCode,
        'message'   => $ok ? 'URL submitted successfully (IndexNow accepted)'
                           : ($error ?: 'Failed - check key, key file location, or URL format'),
        'raw'       => $response ?: '(no body - normal for 200/202)',
    ];
}

/**
 * Submit a batch of URLs via POST with a urlList payload.
 */
function submitBatchToIndexNow(array $urlList, $key, $host, $keyLocation) {
    $endpoint = 'https://api.indexnow.org/indexnow';

    $payload = json_encode([
        'host'        => parse_url($host, PHP_URL_HOST), // just the domain
        'key'         => $key,
        'keyLocation' => $keyLocation,
        'urlList'     => array_values($urlList),
    ]);

    $ch = curl_init($endpoint);
    curl_setopt_array($ch, [
        CURLOPT_POST           => true,
        CURLOPT_POSTFIELDS     => $payload,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => ['Content-Type: application/json; charset=utf-8'],
        CURLOPT_TIMEOUT        => 30,
    ]);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error    = curl_error($ch);
    curl_close($ch);

    $ok = ($httpCode >= 200 && $httpCode < 300);
    return [
        'success'   => $ok,
        'http_code' => $httpCode,
        'count'     => count($urlList),
        'message'   => $ok ? 'Batch accepted by IndexNow'
                           : ($error ?: 'Batch failed - check key / key file location'),
        'raw'       => $response ?: '(no body - normal for 200/202)',
    ];
}

// ================= REQUEST HANDLING =================
$result  = '';
$success = false;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    // ---- Action 1: Submit ALL URLs from the sitemap ----
    if (isset($_POST['submit_sitemap'])) {
        $xml = loadSitemap($sitemapLocalPath, $sitemapUrl);

        if ($xml === null) {
            $result = "Could not load sitemap.\n"
                    . "Tried local path: " . $sitemapLocalPath . "\n"
                    . "Tried URL: " . $sitemapUrl;
        } else {
            $urls = extractUrlsFromSitemap($xml, $yourHost);

            if (empty($urls)) {
                $result = "No matching URLs found in the sitemap for host " . $yourHost . ".";
            } else {
                $chunks    = array_chunk($urls, $batchSize);
                $allOk     = true;
                $submitted = 0;
                $lines     = [];

                foreach ($chunks as $i => $chunk) {
                    $r = submitBatchToIndexNow($chunk, $indexNowKey, $yourHost, $keyFileLocation);
                    $allOk = $allOk && $r['success'];
                    if ($r['success']) {
                        $submitted += $r['count'];
                    }
                    $lines[] = sprintf(
                        "Batch %d/%d: %d URLs -> HTTP %s (%s)",
                        $i + 1, count($chunks), $r['count'], $r['http_code'], $r['message']
                    );
                }

                $success = $allOk;
                $result  = sprintf("Submitted %d of %d URLs from sitemap.\n\n", $submitted, count($urls))
                         . implode("\n", $lines);
            }
        }
    }

    // ---- Action 2: Submit a single URL (original behaviour) ----
    elseif (!empty($_POST['url'])) {
        $urlToSubmit = trim($_POST['url']);

        if (filter_var($urlToSubmit, FILTER_VALIDATE_URL) === false) {
            $result = 'Invalid URL format.';
        } elseif (strpos($urlToSubmit, $yourHost) !== 0) {
            $result = 'URL must belong to your domain (' . $yourHost . ')';
        } else {
            $apiResult = submitUrlToIndexNow($urlToSubmit, $indexNowKey);
            $success   = $apiResult['success'];
            $result    = ($success ? "Success! URL submitted to IndexNow.\n" : "Error submitting URL.\n")
                       . "HTTP Code: " . $apiResult['http_code'] . "\n"
                       . $apiResult['message']
                       . ($success ? '' : "\n\nRaw response:\n" . $apiResult['raw']);
        }
    }
}

// Preview count for the page (best-effort, non-fatal).
$previewCount = null;
$previewXml   = loadSitemap($sitemapLocalPath, $sitemapUrl);
if ($previewXml !== null) {
    $previewCount = count(extractUrlsFromSitemap($previewXml, $yourHost));
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bing IndexNow URL Submission (2026)</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; }
        h2 { color: #0067c5; }
        h3 { margin-top: 32px; }
        input[type="url"] { width: 100%; max-width: 500px; padding: 10px; font-size: 16px; }
        button { padding: 10px 20px; font-size: 16px; background: #0067c5; color: white; border: none; cursor: pointer; }
        button:hover { background: #0054a0; }
        .secondary { background: #2e7d32; }
        .secondary:hover { background: #1b5e20; }
        pre { background: #f8f9fa; padding: 15px; border: 1px solid #ddd; white-space: pre-wrap; word-wrap: break-word; }
        .success { color: green; font-weight: bold; }
        .error   { color: red;   font-weight: bold; }
        .divider { border: 0; border-top: 1px solid #ddd; margin: 32px 0; }
    </style>
</head>
<body>

<h2>Bing IndexNow – Submit URLs for Fast Indexing</h2>
<p>Uses the modern IndexNow protocol (recommended by Bing in 2026 – no Azure needed).</p>

<h3>Submit entire sitemap</h3>
<p>
    Reads every <code>&lt;loc&gt;</code> URL from your sitemap and submits them in batches.
    <?php if ($previewCount !== null): ?>
        <br><strong><?= (int) $previewCount ?></strong> URL(s) currently detected in the sitemap.
    <?php else: ?>
        <br><span class="error">Sitemap not reachable yet — check the path/URL in the config.</span>
    <?php endif; ?>
</p>
<form method="post">
    <button type="submit" name="submit_sitemap" value="1" class="secondary">
        Submit All Sitemap URLs to Bing (IndexNow)
    </button>
</form>

<hr class="divider">

<h3>Submit a single URL</h3>
<form method="post">
    <p>
        <input type="url" name="url" placeholder="https://discordbooster.com/new-page">
    </p>
    <p>
        <button type="submit">Submit URL to Bing (IndexNow)</button>
    </p>
</form>

<?php if ($result): ?>
    <h3>Result:</h3>
    <pre class="<?= $success ? 'success' : 'error' ?>"><?= htmlspecialchars($result) ?></pre>
<?php endif; ?>

<p><small>Note: Make sure your key file is live at <code><?= htmlspecialchars($keyFileLocation) ?></code></small></p>

</body>
</html>
