Ency Grabber v2.0

سحب ملفات DevUploads إلى استضافتك — ٣ طرق، منها مضمونة ١٠٠٪
🤖 تلقائي
🔗 رابط مباشر
🧩 سكريبت المتصفح مضمون
📁 الملفات 1

الصق رابط صفحة الملف من devuploads.com وسيحاول السيرفر تنفيذ كل الخطوات وحفظ الملف في مجلد downloads/.
ملاحظة صادقة: هذه الطريقة تنجح إذا لم تكن حماية Cloudflare غاضبة من IP استضافتك. إن ظهرت رسالة الحجب — استخدم التبويب الثالث (مضمون ١٠٠٪).

🛰️ سير العمل التلقائي: فتح صفحة الملف → إرسال البيانات لصفحة المقال → انتظار ٢٠ ثانية → توليد الرابط (POST op=download2) → تحميل الملف إلى downloads/

عندك رابط مباشر للملف (من سكريبت المتصفح أو أي مصدر)؟ الصقه هنا وسيحفظه السيرفر فوراً في downloads/ ويعطيك رابط مشاركة. يعمل مع أي موقع

الطريقة المضمونة ١٠٠٪: سكريبت صغير يُثبَّت في متصفحك ويعمل بدلاً منك — يفتح أي رابط DevUploads ويتجاوز الإعلانات والعدّادات وCloudflare (لأنه يعمل من متصفحك الحقيقي)، ثم يستخرج الرابط المباشر ويحفظ الملف على هذا السيرفر تلقائياً.

  1. ثبّت إضافة Tampermonkey في متصفح كروم/فايرفوكس/إيدج — من متجر الإضافات (مرة واحدة فقط).
  2. اضغط زر تثبيت السكريبت بالأسفل ثم Install في نافذة Tampermonkey.
  3. افتح أي رابط devuploads.com في المتصفح وكأنك ستُحمّل الملف عادةً.
  4. ستظهر لوحة برتقالية Ency Grabber تُجري كل شيء تلقائياً: تجاوز العدّادات → توليد الرابط → حفظ الملف على السيرفر → إعطاؤك رابط المشاركة.
⬇️ تثبيت السكريبت (.user.js) 👁️ عرض الكود
🔑 رمز الربط بين السكريبت والسيرفر (مضمّن تلقائياً في النسخة المحمّلة من هنا):
8e6027cc5ba126458f39
إن حمّلت السكريبت من مكان آخر، انسخ رمزك إلى السطر TOKEN داخل إعداداته.
🧠 لماذا مضمونة؟ لأن الخطوة التي يمنعها Cloudflare (توليد الرابط) تُنفَّذ من متصفحك أنت — متصفح حقيقي بعنوان IP نظيف — فيمرّ كما تمرّ تحميلتك العادية تماماً.
🔧 عرض الكود المصدري للسكريبت
// ==UserScript==
// @name         Ency Grabber — DevUploads Direct Link (Auto)
// @namespace    ency.tv.grabber
// @version      2.1.0
// @description  يجلب الرابط المباشر من DevUploads تلقائياً داخل متصفحك (يتجاوز Cloudflare) — ويمكنه حفظ الملف على استضافتك مباشرة
// @author       Ency TV Store
// @match        *://devuploads.com/*
// @match        *://*.devuploads.com/*
// @match        *://djxmaza.in/*
// @match        *://*.djxmaza.in/*
// @match        *://gujjukhabar.in/*
// @match        *://*.gujjukhabar.in/*
// @match        *://smartfeecalculator.com/*
// @match        *://*.smartfeecalculator.com/*
// @match        *://pdfhindibook.com/*
// @match        *://*.pdfhindibook.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_setClipboard
// @connect      *
// @run-at       document-start
// @noframes     false
// ==/UserScript==

/*****************************************************************************
 *  الإعدادات — عدّل السطرين SERVER و TOKEN فقط
 *  SERVER : رابط ملف grab.php على استضافتك (بدون ? في النهاية)
 *  TOKEN  : رمز الحماية الذي يظهر لك في صفحة grab.php (تبويب "سكريبت المتصفح")
 *  ملاحظة: إذا فتحت هذا السكريبت من زر التحميل داخل grab.php فسيكون
 *          مضبوطاً تلقائياً ولا تحتاج لتعديل أي شيء.
 *****************************************************************************/
const CFG = {
  SERVER: 'https://insta.encylife.com/grab.php',   // مثال: https://mysite.com/grab.php
  TOKEN:  '8e6027cc5ba126458f39',    // مثال: a1b2c3d4e5
  WAIT:   20,                  // ثواني الانتظار قبل توليد الرابط (مثل الموقع)
  AUTO_SAVE: true,             // حفظ تلقائي على السيرفر بعد ظهور الرابط
  BLOB_LIMIT_MB: 300,          // الحد الأقصى لرفع ملف مستلم مباشرة كـ stream
};

/*****************************************************************************/

(function () {
  'use strict';

  const U = location.href;
  const $ = (s, r) => (r || document).querySelector(s);
  const sleep = (ms) => new Promise(r => setTimeout(r, ms));
  const log = (...a) => console.log('%c[EncyGrabber]', 'color:#f7931e;font-weight:bold', ...a);

  /* ---------- منع التكرار: لا نشغّل نفس الخطوة مرتين ---------- */
  const guard = (k, v) => { sessionStorage.setItem(k, v); };
  const guarded = (k) => sessionStorage.getItem(k) === '1';

  /* ======================= لوحة الع ======================= */
  let PANEL = null, P = {};
  function panel() {
    if (PANEL) return;
    const st = document.createElement('style');
    st.textContent = `
      #ency-grab-panel{position:fixed;bottom:18px;inset-inline-start:18px;z-index:2147483647;
        width:340px;max-width:calc(100vw - 36px);background:#0d1321;color:#e8ecf4;border-radius:14px;
        box-shadow:0 12px 40px rgba(0,0,0,.5);font-family:system-ui,'Segoe UI',Tahoma,sans-serif;
        direction:rtl;overflow:hidden;border:1px solid #26324b;font-size:13.5px}
      #ency-grab-panel .hd{display:flex;align-items:center;gap:8px;padding:10px 14px;
        background:linear-gradient(135deg,#f7931e,#e8590c);color:#fff;font-weight:800;font-size:14px}
      #ency-grab-panel .hd .sp{flex:1}
      #ency-grab-panel .bd{padding:12px 14px}
      #ency-grab-panel .fn{font-weight:700;color:#ffd9a8;word-break:break-all;margin-bottom:2px}
      #ency-grab-panel .st{color:#9fb0cd;line-height:1.7}
      #ency-grab-panel .bar{height:6px;background:#1c2740;border-radius:99px;margin:10px 0;overflow:hidden}
      #ency-grab-panel .bar i{display:block;height:100%;width:8%;border-radius:99px;
        background:linear-gradient(90deg,#f7931e,#ffb45e);transition:width .5s}
      #ency-grab-panel .lnk{background:#131c30;border:1px solid #2c3a5c;border-radius:9px;padding:8px 10px;
        margin:8px 0;word-break:break-all;color:#8ec2ff;max-height:74px;overflow:auto;user-select:all;font-size:12px}
      #ency-grab-panel .row{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap}
      #ency-grab-panel button{flex:1;min-width:86px;cursor:pointer;border:0;border-radius:9px;padding:9px 8px;
        font-weight:800;font-family:inherit;font-size:12.5px;transition:.2s}
      #ency-grab-panel .b1{background:linear-gradient(135deg,#f7931e,#e8590c);color:#fff}
      #ency-grab-panel .b2{background:#1d2a45;color:#bcd0f2;border:1px solid #33456e}
      #ency-grab-panel .b3{background:#173b2b;color:#7fe0a7;border:1px solid #1f5c40}
      #ency-grab-panel .min{background:transparent;color:#fff;border:0;font-size:16px;cursor:pointer;line-height:1;padding:0 2px}
      #ency-grab-panel .note{color:#7d8db0;font-size:11.5px;margin-top:8px;line-height:1.7}
      #ency-grab-panel .err{color:#ff9c9c}
      #ency-grab-panel .ok{color:#7fe0a7}
    `;
    document.documentElement.appendChild(st);
    PANEL = document.createElement('div');
    PANEL.id = 'ency-grab-panel';
    PANEL.innerHTML = `
      <div class="hd">⬇️ Ency Grabber <span class="sp"></span><button class="min" title="إخفاء">—</button></div>
      <div class="bd">
        <div class="fn"></div>
        <div class="st">جارٍ التحليل…</div>
        <div class="bar"><i></i></div>
        <div class="lnk" style="display:none"></div>
        <div class="row" style="display:none"></div>
        <div class="note"></div>
      </div>`;
    document.documentElement.appendChild(PANEL);
    P = {
      fn:  PANEL.querySelector('.fn'),
      st:  PANEL.querySelector('.st'),
      bar: PANEL.querySelector('.bar i'),
      lnk: PANEL.querySelector('.lnk'),
      row: PANEL.querySelector('.row'),
      note: PANEL.querySelector('.note'),
    };
    PANEL.querySelector('.min').onclick = () => {
      const b = PANEL.querySelector('.bd');
      b.style.display = b.style.display === 'none' ? 'block' : 'none';
    };
  }
  function setStatus(t, pct, cls) {
    panel(); P.st.innerHTML = t; if (cls) P.st.className = 'st ' + cls;
    if (pct != null) P.bar.style.width = Math.max(5, Math.min(100, pct)) + '%';
  }
  function showLink(url) { panel(); P.lnk.style.display = 'block'; P.lnk.textContent = url; }
  function showButtons(list) {
    panel(); P.row.style.display = 'flex'; P.row.innerHTML = '';
    for (const [label, cls, fn] of list) {
      const b = document.createElement('button');
      b.className = cls; b.textContent = label; b.onclick = fn;
      P.row.appendChild(b);
    }
  }
  function meta(name, size) {
    if (name) { P.fn.textContent = name + (size ? `  (${size})` : ''); }
  }

  /* ======================= محلل الروابط العامة ======================= */
  const BAD_RE = /(clickadu|propeller|doubleclick|googlesynd|adservice|googlesyndication|facebook|twitter|t\.me|telegram|google\.|bing\.|youtube|publify|otieu|exoclick|juicyads|adskeeper)/i;
  const FILE_RE = /\/d\/|\/download\/|\/files?\//i;
  const EXT_RE = /\.(apk|xapk|apkm|zip|rar|7z|exe|ipa|pdf|mp3|mp4|mkv|avi|epub|m4b|iso|tar|gz|txt|jpg|jpeg|png|webm)([?#]|$)/i;

  function absolutize(u, base) { try { return new URL(u, base).href; } catch (e) { return null; } }

  function findDirectLink(html, baseUrl) {
    let doc = null;
    try { doc = new DOMParser().parseFromString(html, 'text/html'); } catch (e) {}

    // 1) meta refresh
    const mr = doc && doc.querySelector('meta[http-equiv="refresh" i]');
    if (mr && mr.content) {
      const m = mr.content.match(/url\s*=\s*(.+)$/i);
      if (m) {
        const u = absolutize(m[1].trim().replace(/^["']|["']$/g, ''), baseUrl);
        if (u && !BAD_RE.test(u)) return u;
      }
    }
    // 2) تعليمات JS للتحويل
    const pats = [
      /location(?:\.href)?\s*=\s*["']([^"']+)["']/gi,
      /location\.replace\s*\(\s*["']([^"']+)["']\s*\)/gi,
      /location\.assign\s*\(\s*["']([^"']+)["']\s*\)/gi,
    ];
    for (const re of pats) {
      let m;
      while ((m = re.exec(html))) {
        const u = absolutize(m[1], baseUrl);
        if (u && !BAD_RE.test(u) && (FILE_RE.test(u) || EXT_RE.test(u))) return u;
      }
    }
    // 3) روابط <a>
    if (doc) {
      for (const a of doc.querySelectorAll('a[href]')) {
        const u = absolutize(a.getAttribute('href'), baseUrl);
        if (!u || BAD_RE.test(u)) continue;
        if (FILE_RE.test(u) || EXT_RE.test(u)) return u;
      }
    }
    // 4) أي رابط /d/ في النص
    let m = html.match(/https?:\/\/[^\s"'<>]+\/d\/[^\s"'<>]+/i);
    if (m && !BAD_RE.test(m[0])) return m[0];
    return null;
  }

  /* ======================= أدوات GM ======================= */
  function gmPost(url, fields, referer) {
    return new Promise((resolve, reject) => {
      GM_xmlhttpRequest({
        method: 'POST',
        url,
        data: new URLSearchParams(fields).toString(),
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Referer': referer || location.href,
        },
        timeout: 120000,
        onload: r => resolve(r),
        onerror: () => reject(new Error('network')),
        ontimeout: () => reject(new Error('timeout')),
      });
    });
  }

  function gmSaveOnServer(payload) {
    return new Promise((resolve, reject) => {
      GM_xmlhttpRequest({
        method: 'POST',
        url: CFG.SERVER.replace(/[?&]+$/, '') + '?api=save',
        data: new URLSearchParams(payload).toString(),
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        timeout: 0, // بلا مهلة — التحميل قد يطول
        onload: r => {
          try { resolve(JSON.parse(r.responseText)); }
          catch (e) { reject(new Error('bad json: ' + r.responseText.slice(0, 200))); }
        },
        onerror: () => reject(new Error('network')),
      });
    });
  }

  /* ======================= منطق الصفحات ======================= */

  // -- صفحة تحدي Cloudflare؟ ننتظر حتى تحلّ نفسها (المتصفح الحقيقي يحلها تلقائياً)
  async function waitChallenge() {
    if (!/just a moment|attention required/i.test(document.title) &&
        !$('#challenge-form') && !$('#challenge-running')) return false;
    setStatus('⏳ Cloudflare يتحقق من المتصفح… انتظر قليلاً', 15);
    for (let i = 0; i < 60; i++) {
      await sleep(1500);
      if (!/just a moment|attention required/i.test(document.title) && !$('#challenge-form')) {
        setStatus('✅ تم التحقق — نكمل العمل', 25, 'ok');
        await sleep(800);
        location.reload(); // نعيد التحليل على الصفحة الحقيقية
        return true;
      }
    }
    setStatus('❌ تعذر تجاوز تحقق Cloudflare — حدّث الصفحة', null, 'err');
    return true;
  }

  // -- الخطوة 1: صفحة الملف (form#downloadpage)
  async function handlePage1() {
    const f = $('#downloadpage');
    if (!f) return false;

    const title = (f.querySelector('[name=title]') || {}).value || '';
    const size  = (f.querySelector('[name=size]') || {}).value || '';
    const rand  = (f.querySelector('[name=rand]') || {}).value || '';
    GM_setValue('ency_meta', JSON.stringify({ name: title, size, rand, t: Date.now() }));
    GM_setValue('ency_host', location.host); // نتذكر نطاق السلسلة (لمطابقة الصفحة النهائية)
    guard('ency_page1', '1');

    meta(title, size);
    setStatus('📄 تم التعرف على الملف — فتح صفحة التوليد…', 20);
    P.note.textContent = 'سيتم تجاوز الإعلانات والعدّادات تلقائياً';

    // تسريع: الصفحة الحقيقية تخفي body 12 ثانية ثم تُرسل النموذج تلقائياً عبر go()
    // نستدعي go() فوراً إن لم يُستدَع خلال ثانيتين
    setTimeout(() => {
      if (location.href === U && $('#downloadpage')) {
        try {
          if (typeof unsafeWindow.go === 'function') { unsafeWindow.go(); return; }
        } catch (e) {}
        f.submit();
      }
    }, 2000);
    return true;
  }

  // -- الخطوة 2: صفحة المقال (form#dlform) — نستبدل العدّاد بطلب مباشر عبر GM
  async function handleArticle() {
    const f = $('#dlform') || document.querySelector('form[name="F1"]');
    if (!f) return false;
    if (guarded('ency_art_' + location.pathname + location.search)) { return true; }
    guard('ency_art_' + location.pathname + location.search, '1');

    const m = JSON.parse(GM_getValue('ency_meta', '{}') || '{}');
    meta(m.name, m.size);

    // نمنع الإرسال الطبيعي للنموذج (كي لا يقلع من الصفحة قبل أن نلتقط الرابط)
    // مهم: بعض السكربتات تستدعي form.submit() مباشرة ولا تمر عبر حدث submit —
    // لذلك نعطّل الدالة نفسها مع الاحتفاظ بالنسخة الحقيقية للاستخدام في الاحتياطات
    const realSubmit = f.submit.bind(f);
    try { f.submit = function () {}; } catch (e) {}
    f.addEventListener('submit', e => { e.preventDefault(); e.stopImmediatePropagation(); }, true);

    const fields = {};
    f.querySelectorAll('input,select,textarea,button[name]').forEach(el => {
      if (el.name) fields[el.name] = el.value;
    });

    const start = (m.t || Date.now());
    const elapsed = Math.round((Date.now() - start) / 1000);
    let wait = Math.max(0, CFG.WAIT - elapsed);
    log('waiting', wait, 's before generating link');

    const tick = setInterval(() => {
      setStatus(`⏱️ تجهيز الرابط المباشر… انتظار <b>${wait}</b> ثانية (تجاوز العدّاد)`, 30 + ((CFG.WAIT - wait) / CFG.WAIT) * 35);
      if (--wait < -1) clearInterval(tick);
    }, 1000);

    await sleep(wait * 1000 + 300);
    clearInterval(tick);
    setStatus('⚙️ توليد الرابط المباشر من DevUploads…', 70);

    try {
      const r = await gmPost(f.action, fields, location.href);
      const cd = (r.responseHeaders || '').match(/content-disposition:\s*([^\r\n]+)/i);
      const isCF = r.status === 403 || r.status === 503 || /just a moment/i.test(r.responseText || '');

      if (cd) {
        // الاستجابة هي الملف نفسه — نستخدم الرابط النهائي
        const direct = r.finalUrl || f.action;
        await deliver(direct, m);
        return true;
      }
      if (isCF) {
        setStatus('☁️ ظهر تحقق Cloudflare — نجرب المسار الطبيعي…', 60);
        await sleep(1500);
        realSubmit(); // التصفح الطبيعي: المتصفح يحل التحدي بنفسه
        return true;
      }
      const link = findDirectLink(r.responseText || '', f.action);
      if (link) { await deliver(link, m); return true; }

      // صفحة غير متوقعة (رسائل: انتظر / انتهت الصلاحية / لا يوجد ملف)
      const txt = (r.responseText || '').replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 160);
      if (/file not found|not found/i.test(r.responseText || '')) {
        setStatus('❌ الملف غير موجود أو حُذف من DevUploads', 100, 'err'); return true;
      }
      setStatus('⚠️ استجابة غير متوقعة — نجرب المسار الطبيعي…<br><span style="font-size:11px">' + txt + '</span>', 60, 'err');
      await sleep(1200);
      realSubmit();
    } catch (e) {
      setStatus('⚠️ فشل الاتصال (' + e.message + ') — نجرب المسار الطبيعي…', 60, 'err');
      await sleep(1200);
      realSubmit();
    }
    return true;
  }

  // -- الخطوة 3: الصفحة النهائية (وصلناها بتصفح طبيعي) أو رابط جاهز
  async function scanFinalPage() {
    // صفحة devuploads أو نطاق السلسلة نفسه (بعد تحدي Cloudflare مثلاً)
    const chainHost = GM_getValue('ency_host', '');
    if (!/devuploads\.com/.test(location.host) && location.host !== chainHost) return false;
    if ($('#downloadpage')) return false; // صفحة 1 يراها handlePage1
    if ($('#dlform')) return false;       // صفحة مقال يراها handleArticle

    const m = JSON.parse(GM_getValue('ency_meta', '{}') || '{}');
    if (!m.name && !document.body) return false;

    let tries = 0;
    const hunt = setInterval(() => {
      tries++;
      const html = document.documentElement.outerHTML;
      const link = findDirectLink(html, location.href);
      if (link) {
        clearInterval(hunt);
        deliver(link, m);
      } else if (tries > 40) { clearInterval(hunt); }
    }, 500);
    return true;
  }

  // -- تسليم النتيجة: لوحة + أزرار (+ حفظ تلقائي)
  async function deliver(direct, m) {
    log('DIRECT:', direct);
    GM_setValue('ency_lastlink', direct);
    meta(m.name, m.size);
    setStatus('✅ الرابط المباشر جاهز!', 100, 'ok');
    showLink(direct);
    P.note.textContent = '';

    const btns = [
      ['📋 نسخ', 'b2', () => { GM_setClipboard(direct); P.note.textContent = '✔ تم نسخ الرابط'; }],
    ];

    // تحميل مباشر للجهاز
    btns.push(['⬇️ تحميل', 'b1', () => { location.href = direct; }]);

    if (CFG.SERVER && CFG.SERVER.indexOf('http') === 0 && !CFG.SERVER.includes('__GRAB')) {
      const save = async () => {
        setStatus('☁️ يحفظ الملف على السيرفر… حسب الحجم قد يستغرق دقائق', 50);
        try {
          const res = await gmSaveOnServer({ token: CFG.TOKEN, url: direct, name: m.name || '' });
          if (res.ok) {
            setStatus('✅ الملف على السيرفر! (' + res.size + ')', 100, 'ok');
            showLink(res.url);
            P.note.innerHTML = 'رابط المشاركة: <b>' + res.url + '</b>';
            showButtons([
              ['📋 نسخ الرابط', 'b3', () => { GM_setClipboard(res.url); P.note.textContent = '✔ تم النسخ'; }],
              ['🌐 فتح', 'b2', () => { window.open(res.url, '_blank'); }],
              ['↩️ رجوع', 'b2', () => deliver(direct, m)],
            ]);
          } else {
            setStatus('❌ فشل الحفظ: ' + (res.error || 'خطأ غير معروف'), 100, 'err');
            showButtons(btns);
          }
        } catch (e) {
          setStatus('❌ فشل الحفظ على السيرفر: ' + e.message, 100, 'err');
          showButtons(btns);
        }
      };
      if (CFG.AUTO_SAVE) {
        btns.unshift(['☁️ حفظ على السيرفر', 'b3', save]);
        // نظهر حالة "الرابط جاهز" ثانية حتى يراها المستخدم ثم نبدأ الحفظ تلقائياً
        await sleep(1200);
        save();
      }
      else btns.unshift(['☁️ حفظ على السيرفر', 'b3', save]);
    } else {
      P.note.textContent = 'للحفظ على استضافتك: افتح grab.php وانسخ SERVER و TOKEN إلى إعدادات السكريبت';
    }
    showButtons(btns);
  }

  /* ======================= الإقلاع ======================= */
  function boot() {
    if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', bootOnce); }
    else bootOnce();
  }
  let booted = false;
  function bootOnce() {
    if (booted) return; booted = true;
    (async () => {
      panel();
      try {
        if (await waitChallenge()) return;
        if (await handlePage1()) return;
        if (await handleArticle()) return;
        await scanFinalPage();
        setStatus('👁️ تتابع الصفحة… (إن ظهر زر التحميل سيُلتقط تلقائياً)', 10);
      } catch (e) {
        setStatus('❌ خطأ: ' + e.message, null, 'err');
      }
    })();
  }
  boot();
})();

كل الملفات المحفوظة في downloads/ مع روابط المشاركة العامة.

الملفالحجمالتاريخالرابط
0vrkgal4ow3k 10.1 KB 2026-09-12 21:48 فتح ↗