""" مرتب‌سازی پست‌ها بر اساس سال تولید فیلم ================================================== وردپرس به‌صورت پیش‌فرض پست‌ها رو از جدید به قدیم (بر اساس تاریخ انتشار پست) لیست می‌کنه. این اسکریپت برای هر پست توی دسته‌بندی(های) انتخابی، سال تولید فیلم (فیلد released) رو می‌خونه، پست‌ها رو بر اساس اون سال از قدیم به جدید مرتب می‌کنه، و به هرکدوم یه تاریخ انتشار واقعی (post_date) می‌ده که با همون ترتیب هماهنگه - یعنی فیلم‌های ۲۰۲۶ جدیدترین تاریخ رو می‌گیرن و همیشه اول لیست دسته‌بندی نمایش داده می‌شن. نکته: تاریخ‌ها طوری محاسبه می‌شن که هیچ‌وقت از "همین الان" جلوتر نرن (وگرنه وردپرس پست رو "زمان‌بندی‌شده" حساب می‌کنه و تا اون تاریخ مخفیش می‌کنه). قبل از اجرا باید نسخه‌ی جدید my-custom-api-posttype-fixer.php (که روت‌های get-released-year و set-post-date رو هم داره) روی سایت فعال شده باشه. """ import re import time from datetime import datetime, timedelta import requests from requests.auth import HTTPBasicAuth # ============================== تنظیمات ============================== WP_URL = "https://moviepix.ir" USERNAME = "alireza_fr2005" APP_PASSWORD = "Alirezafaraji.2005.@" CATEGORIES = { "1": {"name": "انیمیشن های دوبله ویژه", "slug": "انیمیشن-های-دوبله-ویژه"}, "2": {"name": "فیلم های خارجی دوبله ویژه", "slug": "فیلم-های-خارجی-دوبله-ویژه"}, } # سالی که برای فیلم‌های بدون سال معتبر (یا سال خراب) در نظر گرفته میشه - همیشه ته لیست میره FALLBACK_YEAR = 0 REQUEST_DELAY_SECONDS = 0.3 # ======================================================================= class SortByYearBot: def __init__(self): self.session = requests.Session() self.session.auth = HTTPBasicAuth(USERNAME, APP_PASSWORD) self.session.headers.update({ "Accept": "application/json", "Content-Type": "application/json", }) # ---------- پیدا کردن پست‌های یه دسته‌بندی ---------- def get_category_id(self, slug): resp = self.session.get( f"{WP_URL}/wp-json/wp/v2/categories", params={"slug": slug}, timeout=30, ) resp.raise_for_status() data = resp.json() if not data: raise ValueError(f"دسته‌بندی‌ای با اسلاگ '{slug}' پیدا نشد.") return data[0]["id"] def get_post_ids_in_category(self, category_id): post_ids = [] page = 1 while True: resp = self.session.get( f"{WP_URL}/wp-json/wp/v2/posts", params={ "categories": category_id, "per_page": 100, "page": page, "_fields": "id", }, timeout=30, ) if resp.status_code == 400: break resp.raise_for_status() batch = resp.json() if not batch: break post_ids.extend([p["id"] for p in batch]) page += 1 return post_ids # ---------- خوندن سال تولید و نوشتن تاریخ انتشار ---------- def get_released_year(self, post_id): resp = self.session.get(f"{WP_URL}/wp-json/myapi-fix/v1/get-released-year/{post_id}", timeout=30) resp.raise_for_status() raw = resp.json().get("released", "") digits = re.sub(r"\D", "", str(raw or "")) if not digits: return FALLBACK_YEAR return int(digits[:4]) # اگه فرمت عجیبی بود فقط ۴ رقم اول رو در نظر می‌گیریم def set_post_date(self, post_id, post_date_str): resp = self.session.post( f"{WP_URL}/wp-json/myapi-fix/v1/set-post-date/{post_id}", json={"post_date": post_date_str}, timeout=30, ) resp.raise_for_status() return resp.json() # ---------- مرتب‌سازی یک دسته‌بندی ---------- def sort_category(self, category_name, category_slug): print(f"\n{'=' * 60}") print(f"📂 دسته‌بندی: {category_name}") print("=" * 60) category_id = self.get_category_id(category_slug) post_ids = self.get_post_ids_in_category(category_id) total = len(post_ids) if total == 0: print("⚠️ هیچ پستی توی این دسته‌بندی پیدا نشد.") return print(f"🎬 {total} پست پیدا شد. در حال خوندن سال تولید هر کدوم...") posts_with_year = [] no_year_ids = [] for idx, post_id in enumerate(post_ids, start=1): try: year = self.get_released_year(post_id) except Exception as e: print(f" ⚠️ خطا در خوندن سال پست {post_id}: {e}") year = FALLBACK_YEAR if year == FALLBACK_YEAR: no_year_ids.append(post_id) posts_with_year.append((post_id, year)) if idx < total: time.sleep(REQUEST_DELAY_SECONDS) if no_year_ids: print(f" ⚠️ {len(no_year_ids)} پست سال تولید معتبر نداشتن، ته لیست قرار می‌گیرن: {no_year_ids}") # مرتب‌سازی پایدار: قدیم -> جدید (سال کوچیک‌تر اول، بزرگ‌تر آخر) posts_with_year.sort(key=lambda x: x[1]) # بازه‌ی تاریخ: از "الان منهای total روز" تا "الان منهای یه ساعت" (که هیچ‌وقت آینده نشه) end_date = datetime.now() - timedelta(hours=1) start_date = end_date - timedelta(days=total) span = (end_date - start_date).total_seconds() step = span / max(total - 1, 1) print(f"\n📅 در حال تنظیم تاریخ انتشار (قدیم‌ترین: {start_date:%Y-%m-%d}, جدیدترین: {end_date:%Y-%m-%d})...") updated, failed = 0, [] for idx, (post_id, year) in enumerate(posts_with_year): target_date = start_date + timedelta(seconds=step * idx) date_str = target_date.strftime("%Y-%m-%d %H:%M:%S") print(f"[{idx + 1}/{total}] پست {post_id} (سال {year or 'نامشخص'}) -> {date_str}", end=" ") try: self.set_post_date(post_id, date_str) print("✅") updated += 1 except Exception as e: print(f"❌ خطا: {e}") failed.append((post_id, str(e))) if idx < total - 1: time.sleep(REQUEST_DELAY_SECONDS) print(f"\n📊 نتیجه‌ی این دسته: {updated} تاریخشون تنظیم شد | {len(failed)} ناموفق") if failed: print("❌ ناموفق‌ها:") for pid, err in failed: print(f" - {pid}: {err}") def main(): bot = SortByYearBot() print("کدوم دسته‌بندی(ها) رو مرتب کنم؟\n") for key, cat in CATEGORIES.items(): print(f" {key}) {cat['name']}") both_choice = str(len(CATEGORIES) + 1) print(f" {both_choice}) هر دو") choice = input("\nشماره رو وارد کنید: ").strip() if choice == both_choice: selected = list(CATEGORIES.values()) elif choice in CATEGORIES: selected = [CATEGORIES[choice]] else: print("❌ گزینه‌ی نامعتبر بود، اسکریپت متوقف شد.") return for cat in selected: bot.sort_category(cat["name"], cat["slug"]) if __name__ == "__main__": main() 2018 – برگه 44 – مووی پیکس

2018

pwa

دنیای فیلم، سریال و انیمیشن در مووی پیکس منتظرته! جدیدترین فیلم ها و سریال هارو با دوبله فارسی و زیرنویس فارسی دانلود و آنلاین تماشا کنید