Skip to content

Commit

Permalink
build TürkAnimu Downloader v6
Browse files Browse the repository at this point in the history
  • Loading branch information
KebabLord committed Feb 8, 2021
1 parent 2302369 commit cfc80e5
Show file tree
Hide file tree
Showing 6 changed files with 182 additions and 119 deletions.
21 changes: 14 additions & 7 deletions turkanime.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
""" TürkAnimu Downloader v5.3 """
""" TürkAnimu Downloader v6 """
from os import path,mkdir
from sys import exit as kapat
from atexit import register
Expand All @@ -8,14 +8,14 @@
from rich import print as rprint
from questionary import select,autocomplete,prompt

from turkanime_api import AnimeSorgula,Anime,dosya,get_config
from turkanime_api import AnimeSorgula,Anime,get_config,add_new_options
from turkanime_api import elementi_bekle,webdriver_hazirla,prompt_tema

with Progress(SpinnerColumn(), '[progress.description]{task.description}', BarColumn(bar_width=40)) as progress:
task = progress.add_task("[cyan]Sürücü başlatılıyor..", start=False)
driver = webdriver_hazirla()
driver = webdriver_hazirla(progress)
register(lambda: (print("Program kapatılıyor..",end="\r") or driver.quit()))

add_new_options()
progress.update(task, description="[cyan]TürkAnime'ye bağlanılıyor..")
try:
driver.get("https://turkanime.net/kullanici/anonim")
Expand Down Expand Up @@ -47,7 +47,6 @@
style=prompt_tema
).ask()

# Anime'yi ara ve bölüm seç
secilen_bolumler = prompt({
'type': "checkbox" if "indir" in islem else "select",
'message': 'Bölüm seç',
Expand All @@ -72,18 +71,26 @@
while True:
parser.read(path.join(".",get_config() ))
isAutosave = parser.getboolean("TurkAnime","izlerken kaydet")
isAutosub = parser.getboolean("TurkAnime","manuel fansub")
dlFolder = parser.get("TurkAnime","indirilenler")
opsiyon = select(
'İşlemi seç',
['İndirilenler klasörünü seç',
f'İzlerken kaydet: {isAutosave}',
f'Manuel fansub seç: {isAutosub}',
'Geri dön'],
style=prompt_tema,
instruction=" ",
instruction=" "
).ask()
if opsiyon == 'İndirilenler klasörünü seç':
from easygui import diropenbox
parser.set('TurkAnime','indirilenler',diropenbox())
indirilenler_dizin=diropenbox()
if indirilenler_dizin:
parser.set('TurkAnime','indirilenler',indirilenler_dizin)

elif opsiyon == f'Manuel fansub seç: {isAutosub}':
parser.set('TurkAnime','manuel fansub',str(not isAutosub))

elif opsiyon == f'İzlerken kaydet: {isAutosave}':
parser.set('TurkAnime','izlerken kaydet',str(not isAutosave))
if not path.isdir(path.join(".","Kayıtlar")):
Expand Down
61 changes: 3 additions & 58 deletions turkanime_api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,5 @@
from sys import exit as kapat
import subprocess as sp
from os import name
from prompt_toolkit import styles
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
""" TurkAnimu API """
from .anime import AnimeSorgula,Anime
from .players import elementi_bekle
from .compile import dosya,get_config

def gereksinim_kontrol():
""" Gereksinimlerin erişilebilir olup olmadığını kontrol eder """
eksik=False
stdout="\n"
for gereksinim in ["geckodriver","youtube-dl","mpv"]:
status = sp.Popen(f'{gereksinim} --version',stdout=sp.PIPE,stderr=sp.PIPE,shell=True).wait()
if status>0:
stdout += f"x {gereksinim} bulunamadı.\n"
eksik=True
else:
stdout += f"+ {gereksinim} bulundu.\n"
if eksik:
print(stdout+"\nBelirtilen program yada programlar",
"program dizininde yada sistem PATH'ında bulunamadı.",
"Lütfen klavuzdaki kurulum talimatlarını uygulayın.")
kapat(1)

def webdriver_hazirla():
""" Selenium webdriver'ı hazırla """
options = Options()
options.add_argument('--headless')
profile = webdriver.FirefoxProfile()
profile.set_preference("dom.webdriver.enabled", False)
profile.set_preference('useAutomationExtension', False)
profile.set_preference('permissions.default.image', 2)
profile.set_preference("network.proxy.type", 0)
profile.update_preferences()
desired = webdriver.DesiredCapabilities.FIREFOX
if name == 'nt':
return webdriver.Firefox(
profile, options=options,service_log_path='NUL',
executable_path=dosya('geckodriver.exe'), desired_capabilities=desired
)
return webdriver.Firefox(
profile, options=options,
service_log_path='/dev/null',desired_capabilities=desired
)

prompt_tema = styles.Style([
('qmark', 'fg:#5F819D bold'),
('question', 'fg:#289c64 bold'),
('answer', 'fg:#48b5b5 bg:#hidden bold'),
('pointer', 'fg:#48b5b5 bold'),
('highlighted', 'fg:#07d1e8'),
('selected', 'fg:#48b5b5 bg:black bold'),
('separator', 'fg:#6C6C6C'),
('instruction', 'fg:#77a371'),
('text', ''),
('disabled', 'fg:#858585 italic')
])
from .tools import gereksinim_kontrol,webdriver_hazirla,prompt_tema
from .compile import get_config,add_new_options,dosya
36 changes: 15 additions & 21 deletions turkanime_api/anime.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from configparser import ConfigParser
from bs4 import BeautifulSoup as bs4
from rich.progress import Progress, BarColumn, SpinnerColumn
from rich import print as rprint

from .players import url_getir
from .compile import dosya,get_config
Expand All @@ -21,7 +22,7 @@ def get_seriler(self):
return self.tamliste.keys()

soup = bs4(
self.driver.execute_script("return $.get('https://www.turkanime.net/ajax/tamliste')"),
self.driver.execute_script("return $.get('https://www.turkanime.net/ajax/tamliste')"),
"html.parser"
)
raw_series, self.tamliste = soup.findAll('span',{"class":'animeAdi'}) , {}
Expand All @@ -35,9 +36,9 @@ def get_bolumler(self, isim):
with Progress(SpinnerColumn(), '[progress.description]{task.description}', BarColumn(bar_width=40)) as progress:
task = progress.add_task("[cyan]Bölümler getiriliyor..", start=False)
anime_slug=self.tamliste[isim]
self.anime_ismi = anime_slug
raw = self.driver.execute_script(f"return $.get('/anime/{anime_slug}')")
soup = bs4(raw,"html.parser")
self.anime_ismi = soup.title.text
anime_code = soup.find('meta',{'name':'twitter:image'}).get('content').split('lerb/')[1][:-4]

raw = self.driver.execute_script(f"return $.get('https://www.turkanime.net/ajax/bolumler&animeId={anime_code}')")
Expand All @@ -54,47 +55,40 @@ def get_bolumler(self, isim):


class Anime():
""" İstenilen bölümü izle, yada bölümleri indir. """
""" İstenilen bölümü veya bölümleri oynat ya da indir. """

def __init__(self,driver,seri,bolumler):
self.driver = driver
self.seri = seri
self.bolumler = bolumler
self.parser = ConfigParser()
self.parser.read(path.join(".",get_config()))
self.otosub = self.parser.getboolean("TurkAnime","manuel fansub")

def indir(self):
parser = ConfigParser()
parser.read(get_config())
dlfolder = parser.get("TurkAnime","indirilenler")
dlfolder = self.parser.get("TurkAnime","indirilenler")

if not path.isdir(path.join(dlfolder,self.seri)):
mkdir(path.join(dlfolder,self.seri))

for bolum in self.bolumler:
print(" "*50+"\rBölüm getiriliyor..",end="\r")
self.driver.get(f"https://turkanime.net/video/{bolum}")
print(" "*50+f"\r\n{self.driver.title} indiriliyor:")
url = url_getir(self.driver)
for i,bolum in enumerate(self.bolumler):
print(" "*50+f"\r\n{i+1}. bölüm indiriliyor:")
otosub = bool(len(self.bolumler)==1 and self.otosub)
url = url_getir(bolum,self.driver,manualsub=otosub)
suffix="--referer https://video.sibnet.ru/" if "sibnet" in url else ""
system(f'{dosya("youtube-dl.exe")} --no-warnings -o "{path.join(dlfolder,self.seri,bolum)}.%(ext)s" "{url}" {suffix}')
return True

def oynat(self):
with Progress(SpinnerColumn(), '[progress.description]{task.description}', BarColumn(bar_width=40)) as progress:
task = progress.add_task("[cyan]Sayfa yükleniyor..", start=False)
self.driver.get(f"https://turkanime.net/video/{self.bolumler}")
progress.update(task,visible=False)
url = url_getir(self.driver)
url = url_getir(self.bolumler,self.driver,manualsub=self.otosub)

if not url:
print("Çalışan bir video bulunamadı.")
rprint("[red]Bu bölüme ait çalışan bir player bulunamadı.[/red]")
return False

parser = ConfigParser()
parser.read(get_config())

suffix ="--referrer=https://video.sibnet.ru/ " if "sibnet" in url else ""
suffix+= "--msg-level=display-tags=no "
suffix+="--stream-record={}.mp4 ".format(path.join(".","Kayıtlar",self.bolumler)) if parser.getboolean("TurkAnime","izlerken kaydet") else ""
suffix+="--stream-record={}.mp4 ".format(path.join(".","Kayıtlar",self.bolumler)) if self.parser.getboolean("TurkAnime","izlerken kaydet") else ""

system(f'{dosya("mpv.exe")} "{url}" {suffix} ')
return True
16 changes: 16 additions & 0 deletions turkanime_api/compile.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import sys
from configparser import ConfigParser

def dosya(relative_path):
""" PyInstaller için gömülü dosyaların dizinini getir """
Expand All @@ -17,7 +18,22 @@ def get_config():
with open(confdir,"w") as f:
f.write(
"[TurkAnime]\n"+
"manuel fansub = False\n"+
"izlerken kaydet = False\n"+
"indirilenler = .\n"
)
return confdir

def add_new_options():
"""
Programın önceki sürümünü kullananların config dosyasına
eğer mevcut değilse yeni eklenmiş ayarları ekler.
"""
new_options = ["manuel fansub"]
parser = ConfigParser()
parser.read(get_config())
for i in new_options:
if not parser.has_option("TurkAnime",i):
parser.set("TurkAnime",i,"False")
with open(get_config(),"w") as f:
parser.write(f)
88 changes: 55 additions & 33 deletions turkanime_api/players.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
from selenium.common.exceptions import NoSuchElementException
from rich.progress import Progress, BarColumn, SpinnerColumn
from rich import print as rprint
from questionary import select
from bs4 import BeautifulSoup as bs4

from .tools import prompt_tema
from .compile import dosya

desteklenen_players = [
Expand All @@ -25,8 +26,8 @@
]

def elementi_bekle(selector,_driver):
""" Element yüklenene dek bekler, ayrıyetten 10 saniye boyunca
yanıt alamazsa, timeout hatası verip programı kapatır.
""" Element yüklenene dek bekler. Eğer 10 saniye
boyunca yanıt alamazsa error verir.
"""
start=round(time())
while round(time())-start<10:
Expand All @@ -47,51 +48,71 @@ def check_video(url):
stdexit = test.returncode
if stdexit == 0 and "php" not in stdout:
return True
# print("Playerdaki video silinmiş, sıradakine geçiliyor",end="\r")
return False

def url_getir(driver):
def fansub_sec(src):
""" Fansubları parselar, hash kodunu çeker ve kullanıcıdan seçim yapmasını ister """
fansub_bar = re.search(".*birden fazla grup",src)
if not fansub_bar:
return ""
fansublar = re.findall("(&f=.*?)\'.*?</span> (.*?)</a>",fansub_bar.group())

secilen_sub = select(
"Fansub seçiniz",
[{"name":i[1],"value":i[0]} for i in fansublar],
style=prompt_tema,
instruction=" "
).ask()
return secilen_sub if secilen_sub else ""

def url_getir(bolum,driver,manualsub=False):
""" Ajax sorgularıyla tüm player url'lerini (title,url) formatında listeler
Ardından desteklenen_player'da belirtilen hiyerarşiye göre sırayla desteklenen
ve çalışan bir alternatif bulana dek bu listedeki playerları itere eder.
Prosedür:
- Herhangi bir fansub butonundan bölümün hash kodunu çek
- Talep edilen bölümün hash kodunu çek
- Bölüm hash'ini kullanarak tüm playerları getir
- Her bir player'ın iframe sayfasındaki gerçek url'yi decryptleyip test et
- Her bir player'ın iframe sayfasındaki gerçek url'yi decryptle
"""
with Progress(SpinnerColumn(), '[progress.description]{task.description}', BarColumn(bar_width=40), transient=True) as progress:
task = progress.add_task("[cyan]Bölüm sayfası getiriliyor..", start=False)
bolum_src = driver.execute_script(f'return $.get("/video/{bolum}")')

fansub_hash = fansub_sec(bolum_src) if manualsub else ""
with Progress(SpinnerColumn(), '[progress.description]{task.description}', BarColumn(bar_width=40)) as progress:
task = progress.add_task("[cyan]Video url'si çözülüyor..", start=False)
elementi_bekle("button.btn.btn-sm",driver)
try:
bolum_hash = re.findall(
r"rik\('(.*)&f",
driver.find_element_by_css_selector("button.btn.btn-sm").get_attribute("onclick")
)[0]
except TypeError: # Yalnızca bir fansub olduğunda hash'i playerlardan al
bolum_hash = re.findall(
r"rik\('(.*)&f",
driver.find_elements_by_css_selector("button.btn.btn-sm")[2].get_attribute("onclick")
)[0]

soup = bs4(
driver.execute_script(f"return $.get('ajax/videosec&b={bolum_hash}')"),
"html.parser"
)

parent = soup.find("div", {"id": "videodetay"}).findAll("div",class_="btn-group")[1]
videos = [ (i.text, i.get("onclick").split("'")[1]) for i in parent.findAll("button") if "btn-danger" not in str(i) ]

videos = []
regex = re.search("videosec&b=(.*?)&", bolum_src)

if regex:
bolum_hash = regex.group()
soup = bs4(
driver.execute_script(f"return $.get('ajax/videosec&b={bolum_hash}{fansub_hash}')"),
"html.parser"
)
parent = soup.find("div", {"id": "videodetay"}).findAll("div",class_="btn-group")[1]

for i in parent.findAll("button"):
if "btn-danger" not in str(i):
# (PLAYER, URI)
videos.append( (i.text, i.get("onclick").split("'")[1]) )

# Tek fansub varsa otomatik yüklenen videoyu da listeye ekle
for i in re.findall('iframe src=\\"(.*?)\\\".*?span> (.*?)</button>',bolum_src):
videos.append(i[::-1])

for player in desteklenen_players:
for uri in [ u for t,u in videos if player in t ]:
progress.update(task, description=f"[cyan]{player.title()} url'si getiriliyor..")
try:
iframe_src = driver.execute_script("return $.get('{}')".format(
re.findall(
r"(\/\/www.turkanime.net\/iframe\/.*)\" width",
driver.execute_script(f"return $.get('{uri}')")
)[0]
))
iframe_url= re.findall(
r"(\/\/www.turkanime.net\/iframe\/.*)\" width",
driver.execute_script(f"return $.get('{uri}')")
)[0] if "iframe" not in uri else uri

iframe_src = driver.execute_script(f"return $.get('{iframe_url}')")
except IndexError:
continue
else:
Expand All @@ -102,7 +123,7 @@ def url_getir(driver):
var_iframe = re.findall(r'{"ct".*?}',iframe_src)[0]
var_sifre = re.findall(r"pass.*?\'(.*)?\'",iframe_src)[0]

# Türkanimenin iframe şifreleme algoritması.
# Türkanimenin iframe şifreleme kodu.
url = "https:"+driver.execute_script(f"var iframe='{var_iframe}';var pass='{var_sifre}';"+r"""
var CryptoJSAesJson = {
stringify: function (cipherParams) {
Expand All @@ -128,4 +149,5 @@ def url_getir(driver):
progress.update(task,visible=False)
rprint("[green]Video aktif, başlatılıyor![/green]")
return url
progress.update(task,visible=False)
return False
Loading

0 comments on commit cfc80e5

Please sign in to comment.