وضع علامة على المشاركات في الموضوع كـ "مقروءة"

لقد حاولت إجراء هندسة عكسية للموقع عن طريق إرسال طلبات POST إلى “https://{hostUrl}/topics/timings” مع محتوى-النوع (content-type) ورمز الحماية من التزييف (csrf token) وعامل المستخدم (user-agent).

يبدو جسم الطلب (json) كما يلي:

payload = {
  "topic_id": topic_id,
  "topic_time": post_count * 60000,
  "timings": timings
}

يعيد رمز حالة 200 ولكن سجل القراءة لا يتغير أبدًا على https://{hostUrl}/u/USERNAME/activity/read

لقد حاولت البحث في هذا المنشور ولكنه لم يكن مفيدًا جدًا:

إليك جزء كبير من الكود:

def get_csrf(session):
    r = session.get(f"https://{hostUrl}/session/csrf.json")

    if r.status_code != 200:
        raise RuntimeError("فشل في الحصول على CSRF")

    data = r.json()

    if "csrf" not in data:
        raise RuntimeError("لا يوجد CSRF في الاستجابة")

    return data["csrf"]

def load_topics(session, page):
    print(f"[المواضيع] الصفحة {page}")

    r = session.get(
        f"https://{hostUrl}/latest.json?page={page}"
    )

    if r.status_code != 200:
        return []

    data = r.json()

    return [
        {
            "id": t["id"],
            "posts_count": t["posts_count"]
        }
        for t in data["topic_list"]["topics"]
    ]

def mark_post_as_read(session, topic_id, post_count):
    url = f"https://{hostUrl}/topics/timings"

    timings = {
        str(i): 60000
        for i in range(1, post_count + 1)
    }

    payload = {
        "topic_id": topic_id,
        "topic_time": post_count * 60000,
        "timings": timings
    }

    csrf = get_csrf(session)

    r = session.post(
        url,
        json=payload,
        headers={
            "X-CSRF-Token": csrf,
            "User-Agent": "Mozilla/5.0",
            "Content-Type": "application/json"
        }
    )

    print(f"[قراءة] {topic_id} → {r.status_code}")

    if r.status_code != 200:
        print(r.text[:300])

def tab_worker(session):
    page = 1

    while True:
        topics = load_topics(session, page)

        if not topics:
            break

        for t in topics:
            mark_post_as_read(
                session,
                t["id"],
                t["posts_count"]
            )

            time.sleep(0.4)

        page += 1

أنا أرفع هذا الموضوع لأنني ما زلت بحاجة إلى الإجابة.

شكرًا

ماذا لو أرسلت هذا كـ \"timings[post_number]\": [duration_in_ms] مسطح؟ هل يعمل؟

إعجابَين (2)

لا يبدو أنه يعمل بالضبط.

إليك مقتطف الكود الذي قمت بتعديله.

def mark_post_as_read(session, topic_id, post_count):
    url = f"https://{hostUrl}/topics/timings"

    payload = {
        "topic_id": topic_id,
        "topic_time": post_count * 60000
    }

    for i in range(1, post_count):
        payload[f"timings[{i}]"] = 60000

    csrf = get_csrf(session)

    r = session.post(
        url,
        json=payload,
        headers={
            "X-CSRF-Token": csrf,
            "User-Agent": "Mozilla/5.0",
            "Content-Type": "application/json"
        }
    )

    print(f"[Read] {topic_id} → {r.status_code}")

    if r.status_code != 200:
        print(r.text[:300])

لا يزال يُرجع 200 ولكنه لا يتم تحديثه.

شكرًا

يبدو الكود جيدًا، لست متأكدًا من مصدر المشكلة. :confused:
حدسي يخبرني أننا نفتقد شيئًا واضحًا في مكان ما :sweat_smile:

هذا يعمل:

def load_topics(session, page):
    print(f"[Topics] Loading page {page}")
    r = session.get(f"https://{hostUrl}/latest.json?page={page}")
    if r.status_code != 200:
        return []
    return [{"id": t["id"], "posts_count": t["posts_count"]} for t in r.json()["topic_list"]["topics"]]
    timings = {
        str(i): 60000
        for i in range(1, post_count + 1)
    }
    payload = {
        "topic_id": topic_id,
        "topic_time": post_count * 60000,
        "timings": timings 
    }    

    # استخدم json=payload للإرسال كتطبيق/json
    r = session.post(url, json=payload, headers = {
        "X-CSRF-Token": csrf,
        "User-Agent": "Mozilla/5.0",
        "X-Requested-With": "XMLHttpRequest",
        "Content-Type": "application/json"
      }
    )
إعجاب واحد (1)

شكرًا جزيلاً!!!

هذا يعمل أخيرًا.

إعجاب واحد (1)

في الواقع، شيء آخر.

هذا مثير للاهتمام حقًا!

  1. إنه يُحدِّث سجل قراءة المنشورات بالفعل :white_check_mark:
  2. عدد قراءات المنشورات يزداد :white_check_mark:

ولكن:

  1. عدد قراءات الموضوع لا يزداد :cross_mark:

هذان هما الاثنان اللذان أتحدث عنهما!

مثير للاهتمام حقًا.

لن أتفاجأ إذا تم تحديث هذه الإحصائيات بواسطة مهمة جانبية عادية، لأسباب تتعلق بالأداء.

ما هي حالة الاستخدام الخاصة بك لتحديث التوقيتات باستخدام برنامج نصي؟

يمكنني القول بيقين 100% أن هذا البيان صحيح!
تم تحديث قراءات المشاركات عدة مرات ولكن قراءات المواضيع لم تتغير. هل هي على فترات زمنية مختلفة؟ لقد مر حوالي 20 ساعة منذ ذلك الحين واستمر عدد قراءات المشاركات في الزيادة ولكن قراءات المواضيع لم تتغير.

أريد فقط أن أحاول عكس هندسة نقاط النهاية! هذا رائع.

أعتقد أنه يجب أن أنتظر قليلاً قبل العودة ورؤية ما إذا كانت القيم قد تغيرت

يمكنك تشغيل مهمة sidekiq يدويًا في /sidekiq/scheduler إذا اكتشفت أي واحدة هي :slight_smile:

ربما يكون Jobs::DirectoryRefreshDaily.

هل ترى نفس الشيء في دليل المستخدم على /u?period=daily أو أسبوعيًا؟ هناك، يمكنك رؤية متى تم تحديث الأرقام في الأعلى.
image

أعتقد أنه يتم تحديث الأرقام الخاصة بـ “اليوم” مرة واحدة في الساعة، بينما يتم تحديث النطاقات الزمنية الأخرى مرة واحدة فقط في اليوم.

إعجاب واحد (1)

@Canapin، أنا لست مالك الموقع. إذا كان لا يزال بإمكاني تشغيله بمجرد تسجيل الدخول كمستخدم عادي، فأخبرني بالطريقة للقيام بذلك.

@Moin
الموقع الذي أستخدمه قام بتعطيل ذلك وسيعرض دائمًا “سيتم عرض قائمة بأعضاء المجتمع الذين يظهرون نشاطهم هنا. في الوقت الحالي القائمة فارغة لأن مجتمعك جديد تمامًا!”.

في حالته لا يمكنك ذلك. كونك مستخدمًا عاديًا ليس مثاليًا للهندسة العكسية لواجهة برمجة التطبيقات (API).
إذا استطعت، جرب تثبيت تطوير محلي أو تثبيت إنتاج على خادم افتراضي خاص (VPS) رخيص (خادم بقيمة 3-4 دولارات جيد)، نظرًا لأن Discourse لم يعد يتطلب اسم مضيف أو SMTP.

إعجاب واحد (1)

مرحباً @Canapin، شكراً لمساعدتك المستمرة.

كيف يمكنني فعل ذلك؟ تقول حاليًا 22 موضوعًا مقروءًا و 2.6 مليون مشاركة مقروءة