پرش به محتویات

API

بررسی جامع API و پایگاه دانش «دانشنامه فیلترشکن»

در دنیای مبارزه با سانسور اینترنت و فیلترینگ، دسترسی سریع و ساختاریافته به اطلاعات فنی حیاتی است. وب‌سایت filtershekan.sbs که به عنوان «دانشنامه فیلترشکن» شناخته می‌شود، یکی از کامل‌ترین مراجع متن‌باز (Open Source) در این زمینه است. فایل JSON مورد اشاره، قلب تپنده قابلیت جستجوی این سایت و دروازه‌ای برای توسعه‌دهندگان جهت استخراج داده‌های آن است.

۱. ماهیت فنی API

این فایل یک API دینامیک (Dynamic API) به معنای سنتی که درخواست بگیرد و پردازش کند نیست؛ بلکه یک Static Data Dump (مخزن داده ایستا) است.

  • فرمت: JSON (JavaScript Object Notation)
  • ساختار: این فایل معمولاً خروجی استاندارد ابزارهای تولید سایت استاتیک (مانند MkDocs) است.
  • محتوا: حاوی آرایه‌ای از اشیاء (Objects) است که هر شیء نمایانگر یک صفحه یا بخش از وب‌سایت می‌باشد.

ساختار احتمالی داده‌ها

هر رکورد در این فایل JSON معمولاً شامل فیلدهای زیر است:

  • title: عنوان مقاله یا بخش (مثلاً "آموزش راه‌اندازی V2Ray").
  • text: متن کامل محتوای آن بخش (شامل دستورات، توضیحات و کدها).
  • location: آدرس نسبی (URL) آن صفحه در وب‌سایت.
  • tags (احتمالی): برچسب‌های مرتبط برای دسته‌بندی.

۲. تحلیل محتوای موجود در پایگاه داده

با بررسی این فایل، شما عملاً به نسخه متنی کل وب‌سایت دسترسی دارید. بر اساس ساختار سایت، این فایل شامل اطلاعات جامع در دسته‌بندی‌های زیر است:

الف) ابزارها و پروتکل‌ها (Clients & Protocols)

اطلاعات دقیق و راهنمای راه‌اندازی برای کلاینت‌های محبوب:

  • V2Ray & Xray: آموزش هسته‌های اصلی دور زدن فیلترینگ.

  • Sing-box: راهنمایی‌های مربوط به این ابزار قدرتمند و جدید.

  • Hiddify & MahsaNG: تنظیمات پنل‌های مدیریتی و کلاینت‌های اندرویدی.

  • Warp & Wireguard: روش‌های استفاده از سرویس‌های کلودفلر و وایرگارد.

ب) روش‌های اتصال (Connection Methods)

توضیحات فنی درباره متدهای مختلف دور زدن سانسور:

  • CDN & Cloudflare: تکنیک‌های اسکن IP تمیز و استفاده از دامنه‌های پشت CDN.

  • Serverless: روش‌های اتصال بدون نیاز به خرید سرور (مانند استفاده از ورکرها).

  • Tunneling: آموزش‌های تانل کردن ترافیک بین سرور ایران و خارج.

  • Reality & Fragment: تکنیک‌های پیشرفته برای مخفی کردن ترافیک.

ج) مدیریت سرور و امنیت (DevOps & Security)

  • پنل‌ها: نصب و کانفیگ پنل‌هایی مثل x-ui، سنایی و مرزبان.

  • لینوکس و شبکه: دستورات پایه لینوکس، تنظیمات فایروال و امنیت SSH.

  • حریم خصوصی: آموزش‌های مربوط به عدم نشت اطلاعات (DNS Leak) و امنیت در پیام‌رسان‌ها.

۳. کاربردها برای توسعه‌دهندگان (Use Cases)

چرا این API برای برنامه‌نویسان و کنشگران آزادی اینترنت مهم است؟

  1. ساخت ربات‌های تلگرامی و دیسکورد: توسعه‌دهندگان می‌توانند با دریافت این فایل، یک ربات هوشمند بسازند که کاربران با جستجوی کلماتی مثل «آیفون» یا «همراه اول»، مستقیماً آموزش‌های مرتبط را در محیط چت دریافت کنند.

  2. ایجاد نسخه‌های آفلاین (Offline Readers): در زمان‌های قطعی شدید اینترنت (Blackout)، دسترسی به سایت‌ها دشوار است. اپلیکیشن‌های موبایل می‌توانند این فایل JSON را دانلود و ذخیره کنند تا کاربران بدون نیاز به اینترنت به آموزش‌ها دسترسی داشته باشند.

  3. تحلیل داده و داده‌کاوی: محققان می‌توانند با تحلیل متن این فایل، متوجه شوند که تمرکز جامعه فنی روی کدام پروتکل‌هاست یا کدام روش‌ها (مثلاً Fragment) اخیراً بیشتر مورد بحث قرار گرفته‌اند.

  4. همگام‌سازی (Mirroring): سایت‌های دیگر می‌توانند با استفاده از این داده‌ها، محتوای دانشنامه را روی دامنه‌های دیگر بازنشر کنند تا در صورت فیلتر شدن دامنه اصلی، اطلاعات از بین نرود.

۴. راهنمای استفاده (نمونه کد مفهومی)

برای استفاده از این داده‌ها در پایتون، می‌توان به سادگی فایل را دانلود و جستجو کرد:

import requests

url = "https://filtershekan.sbs/search/search_index.json"
response = requests.get(url)

if response.status_code == 200:
    data = response.json()
    # جستجو برای کلمه "آیفون" در کل مقالات
    documents = data.get('docs', []) # بسته به ساختار دقیق ممکن است متفاوت باشد

    for doc in documents:
        if "آیفون" in doc['text'] or "آیفون" in doc['title']:
            print(f"عنوان: {doc['title']}")
            print(f"لینک: https://filtershekan.sbs/{doc['location']}")
            print("-" * 30)
else:
    print("خطا در دریافت اطلاعات")

۵. نتیجه‌گیری

آدرس filtershekan.sbs/search/search_index.json بیش از یک فایل ساده است؛ این فایل حافظه جمعی و فنی مبارزه با سانسور اینترنت در ایران است که به صورت ساختاریافته در اختیار عموم قرار گرفته است. این رویکرد متن‌باز (Open Data) تضمین می‌کند که دانش دور زدن فیلترینگ در انحصار یک گروه خاص نماند و ابزارهای مختلف بتوانند به راحتی از این منبع غنی تغذیه کنند.

استفاده از این API به توسعه‌دهندگان ابزارهای فیلترشکن توصیه می‌شود تا بخش «راهنما» یا «پشتیبانی» نرم‌افزارهای خود را با محتوای به‌روز این دانشنامه غنی‌سازی کنند.

Frontend

برای ساخت یک فرانت (Frontend) ساده برای این API، بهترین گزینه استفاده از HTML و JavaScript خالص به همراه یک کتابخانه استایل‌دهی مثل Tailwind CSS است تا ظاهر مدرن و تمیزی داشته باشد.

چالش اصلی در فراخوانی این API در مرورگر، مبحث CORS است (مرورگرها اجازه نمی‌دهند شما از یک دامنه لوکال یا متفاوت، دیتای یک دامنه دیگر را بخوانید مگر اینکه آن سرور اجازه داده باشد). برای حل این مشکل در این نمونه کد، از یک CORS Proxy استفاده کرده‌ام تا کد بلافاصله برای شما کار کند.

ویژگی‌های این کد:

  1. جستجوی آنی (Live Search): به محض تایپ کردن نتایج نمایش داده می‌شوند.
  2. طراحی ریسپانسیو (Responsive): روی موبایل و دسکتاپ عالی نمایش داده می‌شود.
  3. پشتیبانی از زبان فارسی: راست‌چین (RTL) و استفاده از فونت «وزیرمتن».
  4. لینک‌دهی هوشمند: نتایج مستقیماً به بخش مربوطه در سایت اصلی لینک می‌شوند.

کد کامل (یک فایل HTML)

این کد را کپی کنید و در یک فایل با نام index.html ذخیره کنید و سپس آن را با مرورگر باز کنید.

<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>جستجوگر دانشنامه فیلترشکن</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/gh/rastikerdar/[email protected]/Vazirmatn-font-face.css" rel="stylesheet" type="text/css" />

    <style>
        body {
            font-family: 'Vazirmatn', sans-serif;
            background-color: #f3f4f6;
        }
        .highlight {
            background-color: #fde047; /* Yellow highlight */
            padding: 0 2px;
            border-radius: 2px;
        }
    </style>
</head>
<body class="min-h-screen p-6">

    <div class="max-w-3xl mx-auto">
        <div class="text-center mb-8">
            <h1 class="text-3xl font-bold text-gray-800 mb-2">جستجوگر دانشنامه</h1>
            <p class="text-gray-600 text-sm">متصل به API دانشنامه فیلترشکن (filtershekan.sbs)</p>
        </div>

        <div class="relative mb-8">
            <div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
                <svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
            </div>
            <input type="text" id="searchInput" disabled 
                class="block w-full p-4 pr-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-white focus:ring-blue-500 focus:border-blue-500 shadow-sm disabled:bg-gray-100 disabled:cursor-not-allowed transition-all" 
                placeholder="در حال دریافت اطلاعات از سرور (لطفا صبر کنید)...">
        </div>

        <div id="status" class="text-center text-sm text-blue-600 mb-4 hidden"></div>

        <div id="results" class="space-y-4">
            </div>
    </div>

    <script>
        // Constants
        // We use a proxy to bypass CORS restrictions since we are running client-side
        const PROXY = 'https://corsproxy.io/?'; 
        const TARGET_API = 'https://filtershekan.sbs/search/search_index.json';
        const BASE_URL = 'https://filtershekan.sbs/';

        let allDocs = [];
        const searchInput = document.getElementById('searchInput');
        const resultsContainer = document.getElementById('results');
        const statusDiv = document.getElementById('status');

        // 1. Fetch Data on Load
        async function init() {
            try {
                statusDiv.textContent = "در حال دانلود دیتابیس...";
                statusDiv.classList.remove('hidden');

                const response = await fetch(PROXY + encodeURIComponent(TARGET_API));
                if (!response.ok) throw new Error("Network error");

                const data = await response.json();

                // The structure is usually { docs: [...] } or just [...]
                allDocs = data.docs ? data.docs : data;

                // Enable Search
                searchInput.disabled = false;
                searchInput.placeholder = "جستجو کنید (مثلا: V2ray, آیفون, سرور)...";
                searchInput.focus();
                statusDiv.textContent = `${allDocs.length} مقاله بارگذاری شد.`;

                setTimeout(() => statusDiv.classList.add('hidden'), 3000);

            } catch (error) {
                console.error(error);
                statusDiv.textContent = "خطا در دریافت اطلاعات. لطفا اتصال اینترنت یا VPN را بررسی کنید.";
                statusDiv.classList.add('text-red-600');
            }
        }

        // 2. Search Logic
        searchInput.addEventListener('input', (e) => {
            const query = e.target.value.toLowerCase();
            resultsContainer.innerHTML = '';

            if (query.length < 2) return; // Don't search for single chars

            // Filter results
            const filtered = allDocs.filter(doc => {
                return (doc.title && doc.title.toLowerCase().includes(query)) || 
                       (doc.text && doc.text.toLowerCase().includes(query));
            });

            // Limit to top 20 results for performance
            renderResults(filtered.slice(0, 20), query);
        });

        // 3. Render Function
        function renderResults(docs, query) {
            if (docs.length === 0) {
                resultsContainer.innerHTML = '<div class="text-center text-gray-500">نتیجه‌ای یافت نشد.</div>';
                return;
            }

            docs.forEach(doc => {
                // Create Card HTML
                const card = document.createElement('div');
                card.className = 'bg-white p-5 rounded-lg shadow hover:shadow-md transition-shadow border border-gray-100';

                // Generate Snippet
                let snippet = getSnippet(doc.text, query);

                card.innerHTML = `
                    <h2 class="text-lg font-bold text-blue-700 mb-2">
                        <a href="${BASE_URL}${doc.location}" target="_blank" class="hover:underline">
                            ${doc.title}
                        </a>
                    </h2>
                    <p class="text-gray-600 text-sm leading-relaxed mb-3">...${snippet}...</p>
                    <a href="${BASE_URL}${doc.location}" target="_blank" 
                       class="inline-flex items-center text-sm font-medium text-blue-600 hover:text-blue-800">
                       مطالعه کامل
                       <svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
                    </a>
                `;
                resultsContainer.appendChild(card);
            });
        }

        // Helper: Create text snippet around the keyword
        function getSnippet(text, query) {
            if (!text) return "";
            const lowerText = text.toLowerCase();
            const index = lowerText.indexOf(query);

            if (index === -1) return text.substring(0, 150);

            const start = Math.max(0, index - 50);
            const end = Math.min(text.length, index + 100);

            let excerpt = text.substring(start, end);

            // Simple highlighting logic
            // Note: This is a basic replace, for production use regex with proper escaping
            const regex = new RegExp(`(${query})`, 'gi');
            return excerpt.replace(regex, '<span class="highlight">$1</span>');
        }

        // Start
        init();
    </script>
</body>
</html>

راهنمای استفاده فنی

  1. ساختار JSON: این کد فرض می‌کند فایل JSON خروجی استاندارد MkDocs است که شامل آرایه‌ای از آبجکت‌هاست که فیلدهای title, text, و location را دارند.
  2. مشکل CORS: در خط ۸۳ کد (const PROXY), من از سرویس api.allorigins.win استفاده کرده‌ام. این سرویس درخواست شما را می‌گیرد، به سرور filtershekan.sbs می‌فرستد و پاسخ را برمی‌گرداند.
    • چرا؟ چون اگر مستقیم درخواست بزنید، مرورگر خطای امنیتی می‌دهد (مگر اینکه این کد را روی همان دامنه‌ی اصلی اجرا کنید).
  3. لینک‌دهی: آدرس‌دهی در فایل JSON به صورت نسبی (Relative) است (مثلاً overview/index.html). من در کد ثابت BASE_URL را تعریف کرده‌ام تا با چسباندن آن به آدرس نسبی، لینک کامل و قابل کلیک ساخته شود.

نحوه اجرا

کافیست کد بالا را در نوت‌پد یا هر ویرایشگر متنی کپی کنید، با نام search.html ذخیره کنید و روی آن دابل کلیک کنید. برنامه در مرورگر باز شده و شروع به دانلود دیتابیس می‌کند.

نمونه سایت

https://searching-2ud.pages.dev/

https://gitlab.com/encyclopedia1/freeInternet/-/raw/main/searching/index.html?ref_type=heads

https://gitlab.com/encyclopedia1/freeInternet/-/raw/main/searching/search.html?ref_type=heads