#https://mainkronos.github.io/AnimeWorld-API/
#https://github.com/jellyfin/jellyfin-apiclient-python

#sudo pip3 install jellyfin-apiclient-python --break-system-packages
#sudo pip3 install animeworld --break-system-packages

import animeworld as aw # type: ignore
import requests # type: ignore
import json
import os
import re
from datetime import datetime

downloadedEp = 0

now = datetime.now()
start = now.strftime("%H:%M")
date = now.strftime("%d/%m")


# Dizionario per mappare i numeri romani ai numeri arabi
roman_to_arabic = {
    'I': 1, 'IV': 4, 'V': 5, 'IX': 9, 'X': 10,
    'XL': 40, 'L': 50, 'XC': 90, 'C': 100,
    'CD': 400, 'D': 500, 'CM': 900, 'M': 1000
}

# Funzione per convertire un singolo numero romano in arabo
def roman_to_int(roman):
    i = 0
    num = 0
    while i < len(roman):
        if i+1 < len(roman) and roman[i:i+2] in roman_to_arabic:
            num += roman_to_arabic[roman[i:i+2]]
            i += 2
        else:
            num += roman_to_arabic[roman[i]]
            i += 1
    return num

# Funzione per trovare e convertire tutti i numeri romani in una stringa
def convert_roman_in_string(text):
    # Espressione regolare per trovare numeri romani validi
    pattern = r'\b(M{0,3})(CM|CD|D?C{0,3})?(XC|XL|L?X{0,3})?(IX|IV|V?I{0,3})\b'
    
    def replace_roman(match):
        roman = match.group(0)
        if roman == '':
            return roman  # Se la stringa è vuota, non sostituire
        arabic = roman_to_int(roman)
        return str(arabic)
    
    return re.sub(pattern, replace_roman, text)

i = 0
offset = 0
data = [" "]
isITA = r'\(ITA\)'
notFound = []
exception = ['Re:Zero kara Hajimeru Isekai Seikatsu 3', 'Toradora! (ITA)', 'Sword Art Online: Progressive Movie - Kuraki Yuuyami no Scherzo', 'Karakai Jouzu no Takagi-san Movie', 'Grisaia no Meikyuu: Caprice no Mayu 0', 'Code Geass: Hangyaku no Lelouch (ITA)', 'Code Geass: Hangyaku no Lelouch R2 (ITA)', 'Assassination Classroom The Movie: 365 Days', 'The Dangers in My Heart 2', 'Mangaka-san to Assistant-san to The Animation', 'Mangaka-san to Assistant-san to The Animation Specials', 'The Quintessential Quintuplets 2', 'The Quintessential Quintuplets Movie', 'The Quintessential Quintuplets~','Angel Beats! Specials', 'Angel Beats!: Another Epilogue', 'Ano Hana Movie', 'Re:Zero kara Hajimeru Isekai Seikatsu', 'Isekai wa Smartphone to Tomo ni.', 'Assassination Classroom 2', 'Assassination Classroom: Extracurricular Lesson (ITA)', 'Boku no Kanojo ga Majimesugiru Sho-bitch na Ken', 'Boku no Kanojo ga Majimesugiru Sho-bitch na Ken OVA', 'The Dangers in My Heart Special','5 cm al secondo', 'Charlotte: Tsuyoimono-tachi', 'Clannad: After Story', 'Clannad: After Story - Mou Hitotsu no Sekai, Kyou-hen', 'Clannad: Mou Hitotsu no Sekai, Tomoyo-hen', 'Clannad Movie', 'Code Geass: Fukkatsu no Lelouch', 'Code Geass: Hangyaku no Lelouch I - Koudou', 'Code Geass: Hangyaku no Lelouch II - Handou', 'Code Geass: Hangyaku no Lelouch III - Oudou', 'Dakara Boku wa, H ga Dekinai.', 'Dakara Boku wa, H ga Dekinai.: Mie Sugi! Mizugi Contest', 'Death Note: Rewrite', 'Death Note (ITA)', 'Dokyuu Hentai HxEros', 'Domestic na Kanojo','Dragon Ball GT (ITA)', 'Dragon Ball Z (ITA)', 'Dragon Ball (ITA)', 'Dragon Ball Super Movie: Broly', 'Dragon Ball Super: Super Hero', 'Dragon Ball Z: Il Super Saiyan della leggenda', 'DanMachi', 'Gakusen Toshi Asterisk', 'Gakusen Toshi Asterisk 2', 'Grisaia no Meikyuu: Caprice no Mayu 0 - Takizono Basketball Club no Nama Cream Party!', 'Grisaia no Rakuen', 'Guilty Crown: Lost Christmas', 'Hige wo Soru. Soshite Joshikousei wo Hirou.', 'High School DxD New', 'High School DxD BorN', 'High School DxD Hero', 'High School DxD BorN: Yomigaeranai Fushichou', 'High School DxD New: Oppai, Tsutsumimasu!', 'Highschool Of The Dead: Drifters of the Dead', "Don't Toy with Me, Miss Nagatoro 2nd Attack", 'Imawa no Kuni no Alice (OVA)', 'Ingress the Animation', 'Initial D Battle Stage 2', 'Initial D Extra Stage 2', 'Inuyashiki', 'How Not to Summon a Demon Lord Ω', 'Isekai Meikyuu de Harem wo', 'Isekai Meikyuu de Harem wo Specials', 'Isekai wa Smartphone to Tomo ni. 2', 'Kaifuku Jutsushi no Yarinaoshi', 'Kakegurui 2', 'Kakegurui Twin', 'Kakkou no Iinazuke', 'Kanojo mo Kanojo', 'Kanojo mo Kanojo 2', 'Rent-a-Girlfriend 2', 'Rent-a-Girlfriend 3', 'Karakai Jouzu no Takagi-san', 'Karakai Jouzu no Takagi-san OVA', 'Karakai Jouzu no Takagi-san 2', 'Karakai Jouzu no Takagi-san 3', 'Kawaikereba Hentai demo Suki ni Natte Kuremasu ka?', 'Kenja no Mago', 'Kimi ni Todoke', 'Kimi ni Todoke 2', 'Kimi ni Todoke 3', 'Your Name. (ITA)', 'Voglio mangiare il tuo pancreas (ITA)', 'A Silent Voice (ITA)', "Komi Can't Communicate 2", 'Il Giardino delle Parole (ITA)', 'Eureka Seven (ITA)', 'Black Butler 2', 'Black Butler: Book of Circus', 'Black Butler: Book of the Atlantic', 'Black Butler Special', 'Magia Record: Mahou Shoujo Madoka�\x98\x86Magica Gaiden (TV)','Mahouka Koukou no Rettousei', 'Mahouka Koukou no Rettousei Movie: Hoshi wo Yobu Shoujo', 'Mahouka Koukou no Rettousei: Raihousha-hen', 'Mahouka Koukou no Rettousei: Tsuioku-hen', 'Mahouka Koukou no Rettousei 3', 'Majo no Tabitabi', 'The Misfit of Demon King Academy 2', 'The Misfit of Demon King Academy 2 Part 2', 'The Café Terrace and Its Goddesses 2', 'MF Ghost 2', 'Mirai Nikki', 'Mirai Nikki: Redial', 'Mob Psycho 100 II', 'Mob Psycho 100: Reigen - Shirarezaru Kiseki no Reinouryokusha', 'Mob Psycho 100: Dai Ikkai Rei toka Soudansho Ian Ryokou - Kokoro Mitasu Iyashi no Tabi', 'Mob Psycho 100 III', 'Mushoku Tensei II: Isekai Ittara Honki Dasu', 'Mushoku Tensei II: Isekai Ittara Honki Dasu Part 2', 'Mushoku Tensei: Isekai Ittara Honki Dasu', 'Mushoku Tensei: Isekai Ittara Honki Dasu Part 2', 'Mushoku Tensei: Isekai Ittara Honki Dasu Special', 'New Initial D Movie: Legend 1 - Kakusei', 'New Initial D Movie: Legend 2 - Tousou', 'Nichijou', 'No Game No Life', 'Noragami Aragoto', 'Noragami OVA', 'Noragami Aragoto OVA', 'One Punch Man 2', 'One Punch Man Specials', 'One Punch Man: Road to Hero', 'One Punch Man 2 Specials', 'Solo Leveling 2: Arise from the Shadow', 'Pokemon Movie 12: Arceus e il Gioiello della Vita (ITA)', 'Prison School: Mad Wax', 'Psycho-Pass 2', 'Psycho-Pass Movie', 'Psycho-Pass SS Case 1: Tsumi to Batsu', 'Psycho-Pass SS Case 2: First Guardian', 'Psycho-Pass: Sinners of the System Case.3 - Onshuu no Kanata ni', 'Psycho-Pass 3', 'Psycho-Pass 3: First Inspector', 'Psycho-Pass Movie: Providence', 'Rail Romanesque 2', 'Re:Zero kara Hajimeru Isekai Seikatsu - Memory Snow', 'Re:Zero kara Hajimeru Isekai Seikatsu 2', 'Re:Zero kara Hajimeru Isekai Seikatsu - Hyouketsu no Kizuna', 'Saenai Heroine no Sodatekata 2', 'Saenai Heroine no Sodatekata', 'Saenai Heroine no Sodatekata Fine', 'Seishun Buta Yarou wa Bunny Girl Senpai no Yume wo Minai', 'Seishun Buta Yarou wa Odekake Sister no Yume wo Minai', 'Seishun Buta Yarou wa Yumemiru Shoujo no Yume wo Minai', 'Senryuu Shoujo', 'Shigatsu wa Kimi no Uso', 'Shigatsu wa Kimi no Uso: Moments', 'Yuyushiki', 'Flavors of Youth', 'Shimoneta', 'Sono Bisque Doll wa Koi wo Suru', 'Special A', 'Steins;Gate Movie: Fuka Ryouiki no Déj�  vu', 'Steins;Gate: Kyoukaimenjou no Missing Link - Divide By Zero', 'Strike the Blood 2', 'Strike the Blood: Valkyria no Oukoku-hen', 'Strike the Blood 3', 'Strike the Blood 4', 'Sword Art Online 2', 'Sword Art Online Alternative: Gun Gale Online', 'Sword Art Online 3: Alicization', 'Sword Art Online: Alicization - War of Underworld', 'Sword Art Online Alternative: Gun Gale Online 2', 'Sword Art Online Movie: Ordinal Scale', 'Sword Art Online: Alicization - War of Underworld Reflection', 'Sword Art Online: Alicization - War of Underworld 2', 'The Rising of the Shield Hero 2', 'The Rising of the Shield Hero 3', 'Teekyuu', 'Teekyuu 2', 'Teekyuu 2 Specials', 'Teekyuu 3', 'Teekyuu 3 Specials', 'Tokyo Ghoul �\x88\x9aA', 'Tokyo Ghoul:re', 'Tokyo Ghoul:re 2', 'Tokyo Magnitude 8.0 (ITA)', 'Tonari no Seki-kun', 'Toradora!: Bentou no Gokui', 'Tsubasa Chronicle', 'Tsubasa: Tokyo Revelations', 'Tsubasa: Shunraiki', 'Tsuki ga Kirei', 'Uzaki-chan wa Asobitai!', 'Uzaki-chan wa Asobitai! 2', 'Violet Evergarden Specials', 'Violet Evergarden Movie', 'Violet Evergarden (ITA)', 'Violet Evergarden Specials (ITA)', 'Violet Evergarden Side Story: Eternity and the Auto Memory Doll (ITA)', 'Yosuga no Sora', 'Classroom of the Elite 2', 'Classroom of the Elite 3', 'Yumemiru Danshi wa Genjitsushugisha', 'Zankyou no Terror', 'Zutto Mae kara Suki deshita.: Kokuhaku Jikkou Iinkai']
exclusion = ['Re:Zero kara Hajimeru Isekai Seikatsu 2 Part 2 (ITA)','The Rising of the Shield Hero 4 (ITA)','My Dress-Up Darling 2 (ITA)','Miru Tights', 'Yuyushiki', 'Iya na Kao sare nagara Opantsu Misete Moraitai', 'Death Note', 'Violet Evergarden', 'Violet Evergarden Side Story Eternity and the Auto Memory Doll', 'Violet Evergarden Specials', 'ReZero kara Hajimeru Isekai Seikatsu Shin Henshuu-ban', 'SteinsGate 0', 'SteinsGate 0 Kesshou Takei no Valentine - Bittersweet Intermedio' 'Re:Zero kara Hajimeru Isekai Seikatsu: Shin Henshuu-ban', 'Violet Evergarden Side Story: Eternity and the Auto Memory Doll', "Frieren: Beyond Journey's End Mini Anime", "Le Bizzarre Avventure di JoJo: Stone Ocean Parte 2 (ITA)", "Grisaia no Kajitsu Specials", "Le Bizzarre Avventure di JoJo: Stone Ocean Parte 3 (ITA)", "Le Bizzarre Avventure di JoJo: Stone Ocean (ITA)", "Le Bizzarre Avventure di JoJo: Stone Ocean Parte 3 ITA", "Le Bizzarre Avventure di JoJo: Stone Ocean Parte 2 ITA", "Le Bizzarre Avventure di JoJo: Stone Ocean ITA", "Steins;Gate 0", "Steins;Gate 0", 'Sword Art Online (ITA)','Sword Art Online: Extra Edition (ITA)', 'Sword Art Online 2 (ITA)', 'Sword Art Online Movie: Ordinal Scale (ITA)', 'Sword Art Online Alternative: Gun Gale Online (ITA)', 'Sword Art Online 3: Alicization (ITA)', 'Sword Art Online: Alicization - War of Underworld (ITA)', 'Sword Art Online: Alicization - War of Underworld Reflection (ITA)', 'Sword Art Online: Alicization - War of Underworld 2 (ITA)', 'Sword Art Online: Alicization - War of Underworld Recap (ITA)', 'Sword Art Online: Progressive Movie - Hoshi Naki Yoru no Aria (ITA)', 'Sword Art Online: Progressive Movie - Kuraki Yuuyami no Scherzo (ITA)']
awForced = ['','','Madan no Ou to Vanadis','A Couple of Cuckoos','My Dress-Up Darling 2','The Rising of the Shield Hero 4','Seishun Buta Yarou wa Santa Claus no Yume wo Minai','Sakamoto desu ga?','A Couple of Cuckoos 2','The 100 Girlfriends Who Really, Really, Really, Really, Really Love You 2','Rent-a-Girlfriend 4','Jidou Hanbaiki ni Umarekawatta Ore wa Meikyuu wo Samayou 2nd Season','Toradora! (ITA)', 'Frieren', 'Sousou_no_Frieren', 'Sword Art Online: Progressive Movie - Kuraki Yuuyami no Scherzo', 'Karakai Jouzu no Takagi-san Movie', 'Le Bizzarre Avventure di JoJo: Stardust Crusaders', 'Le Bizzarre Avventure di JoJo: Stardust Crusaders 2' ,'Le Bizzarre Avventure di JoJo: Diamond is Unbreakable', 'Le Bizzarre Avventure di JoJo: Vento Aureo', 'Le Bizzarre Avventure di JoJo: Stone Ocean', 'Le Bizzarre Avventure di JoJo: Stone Ocean Parte 2', 'Le Bizzarre Avventure di JoJo: Stone Ocean Parte 3', 'Lost Song (ITA)', 'K: Project', 'Re:Zero kara Hajimeru Isekai Seikatsu 2 Part 2', "Frieren: Beyond Journey?s End", "Frieren: Beyond Journey's End", "Frieren Beyond Journeys End", 'Steins;Gate (ITA)', 'Neon Genesis Evangelion (ITA)', 'Neon Genesis Evangelion: Death & Rebirth (ITA)', 'Neon Genesis Evangelion: The End of Evangelion (ITA)']


url = "https://myanimelist.net/animelist/nidran/load.json?status=7&offset="

while data != []:
    response = requests.get(url+str(offset))
    if response.status_code == 200:
        data = response.json()
        for x in data:
            mal = x["anime_title"]
            malEng = x["anime_title_eng"]
            status = x["status"]
            malRoman = convert_roman_in_string(mal)
            malEngRoman = convert_roman_in_string(malEng)
            if status != 4 and status != 6 and status != 3: #if would like to skip on hold, add value 3
                res = aw.find(malEng)
                if res == []:
                    res = aw.find(mal)
                    if res == []:
                        res = aw.find(malRoman)
                    if res == []:
                        res = aw.find(malEngRoman)

                for x in res:
                    if "(ITA)" in x["name"]:
                        x["jtitle"] = x["jtitle"]+" (ITA)"
                    x["name"] = str(x["name"]).split(" (TV)")[0]
                    if ((x["name"] == malEng or x["jtitle"] == mal or  convert_roman_in_string(x["name"]) == malEngRoman or convert_roman_in_string(x["jtitle"]) == malRoman or x["name"] in exception or x["jtitle"] in exception) and x["name"] not in exclusion ) and x["jtitle"] not in exclusion:
                    
                        link = x["link"]
                        awname = x["name"]
                            #if re.search(isITA, awname) == None:
                        anime = aw.Anime(link)
                        try:
                            episodes = anime.getEpisodes()
                        except aw.AnimeNotAvailable as e:
                            episodes = []
                            print("Anime not yet available :(")

                        folder = "/home/nidran/Documenti/jellyfin/media/server/Videoteca/Anime/"+anime.getName() 
                        
                        if not os.path.exists(folder):
                            folder = re.sub(r'[^a-zA-Z0-9.,/\-!~Ω; ]', '', folder)
                            os.makedirs(folder, exist_ok=True)  
                        mp4_files = []
                        for file in os.listdir(folder):
                            if file.endswith(".mp4"):
                                mp4_files.append(file)
                        #listdir = len(mp4_files)    #os.listdir(folder)
                        if len(episodes) == len(mp4_files):
                            episodes =[]
                        listEpDir = []
                        for dir in mp4_files:
                            if "Episodio " in dir:
                                listEpDir.append(dir.split("Episodio ")[1][0:2])
                            else:
                                listEpDir.append(dir)
                            #print(f"Downloading episode from anime : {anime.getName()}.")
                            #episodes = episodes[len(listdir):]

                        for ep in episodes:
                        
                            if float(ep.number) < 10 and "0" + ep.number not in listEpDir:
                                print(f"Downloading episode {ep.number}.")
                                print(folder)
                                ep.download("Episodio 0"+ep.number, folder) 
                                print(f"Download completed.")
                                downloadedEp+=1
                            elif float(ep.number) >= 10 and ep.number not in listEpDir:
                                print(f"Downloading episode {ep.number}.")
                                print(folder)
                                ep.download("Episodio "+ep.number, folder) 
                                print(f"Download completed.")
                                downloadedEp+=1

                        print(awname)
                        print(link)
                        print(" ")
                    else:
                        notFound.append(x["name"])
                i+=1
    offset+=300
    for n in awForced:
        res = aw.find(n)
        for n in res:
            if n["name"] not in exclusion:
                link = n["link"]
                awname = n["name"]
                anime = aw.Anime(link)
                try:
                    episodes = anime.getEpisodes()
                    print("DEBUG Episodi raw:", episodes)
                except aw.AnimeNotAvailable as e:
                    episodes = []
                    print("Anime not yet available :(")

                folder = "/home/nidran/Documenti/jellyfin/media/server/Videoteca/Anime/"+anime.getName() 
                
                if not os.path.exists(folder):
                    folder = re.sub(r'[^a-zA-Z0-9.,/\-!~Ω; ]', '', folder)
                    os.makedirs(folder, exist_ok=True)
                mp4_files = []
                for file in os.listdir(folder):
                    if file.endswith(".mp4"):
                        mp4_files.append(file)
                #listdir = len(mp4_files) #listdir = os.listdir(folder)
                if len(episodes) == len(mp4_files):
                    episodes =[]
                listEpDir = []
                for dir in mp4_files:
                    listEpDir.append(dir.split("Episodio ")[1][0:2])

                for ep in episodes:
                    if float(ep.number) < 10 and "0" + ep.number not in listEpDir:
                        print(f"Downloading episode {ep.number}.")
                        print(folder)
                        ep.download("Episodio 0"+ep.number, folder) 
                        print(f"Download completed.")
                        downloadedEp+=1

                    elif float(ep.number) >= 10 and ep.number not in listEpDir:
                        print(f"Downloading episode {ep.number}.")
                        print(folder)
                        ep.download("Episodio "+ep.number, folder) 
                        print(f"Download completed.")
                        downloadedEp+=1
                print(awname)
                print(link)
                print(" ")
        i+=1
print(i)
print(notFound)
print(downloadedEp)

now = datetime.now()
end = now.strftime("%H:%M")

with open("/home/nidran/Documenti/script/anime-log/log.txt", "a") as file: 
    file.write(date + " - iniziato alle " + start + ", finito alle " + end + "    " + "Episodi scaricati: " + str(downloadedEp) + "\n")
