From eccaf98c1bf211e22e37e5326512c8c04fbe1e08 Mon Sep 17 00:00:00 2001 From: Markus Date: Fri, 5 Jun 2020 15:30:20 +0200 Subject: [PATCH] v4.1.3: fix error with s.to not seri... .sx url in unteroption url... && now to debug but colorless mode whent want to use *-hoster && ka --- src/.programManager.cpp.~6d88e3e2 | 0 src/parameterManager.h | 2 +- ...er (conflicted copy 2020-06-05 151208).cpp | 1602 +++++++++++++++++ src/programManager.cpp | 4 +- 4 files changed, 1605 insertions(+), 3 deletions(-) create mode 100644 src/.programManager.cpp.~6d88e3e2 create mode 100644 src/programManager (conflicted copy 2020-06-05 151208).cpp diff --git a/src/.programManager.cpp.~6d88e3e2 b/src/.programManager.cpp.~6d88e3e2 new file mode 100644 index 0000000..e69de29 diff --git a/src/parameterManager.h b/src/parameterManager.h index fd74e23..a1d11b4 100644 --- a/src/parameterManager.h +++ b/src/parameterManager.h @@ -91,7 +91,7 @@ struct Settings { proxy_ip = "127.0.0.1", languages = "GerDub,GerSub,Eng,", genaueHoster = "", - version = "4.1.2", + version = "4.1.3", defaultFileVersion="1.8", default_checkPath = "", default_Searchmuster = "S%Staffel%E%Folge%"; diff --git a/src/programManager (conflicted copy 2020-06-05 151208).cpp b/src/programManager (conflicted copy 2020-06-05 151208).cpp new file mode 100644 index 0000000..e5b4dda --- /dev/null +++ b/src/programManager (conflicted copy 2020-06-05 151208).cpp @@ -0,0 +1,1602 @@ +#include "programManager.h" + + +ProgramManager::ProgramManager() + : nextThread(0) +{ + +} + +ProgramManager::~ProgramManager() +{ + for(auto e : threadList) { + delete e->pageManager; + delete e; + e = nullptr; + } +} + +int ProgramManager::start(Settings *settings) +{ + pageManager.setDebugMode(settings->debugMode); + pageManager.setProxy(settings->proxy_ip, settings->proxy_port); + pageManager.setCookieFilePath(settings->cookieFilePath); + if(dirExists(settings->cookieFilePath)) { + std::cout << " => Error: Kann Cokkie-File nicht erstellen: Es existiert bereits ein Ordner mit diesem Namen: \n '" + << settings->cookieFilePath << "'." << std::endl; + return 174; + } + + switch (settings->modus) { + case Modus::DEFAULT_MODUS: + return defaultModus(settings); + case Modus::DIRECT_LINK_MODUS: + return directLinkModus(settings); + case Modus::SEARCH_MODUS: + return searchModus(settings); + case Modus::INFO_MODUS: + return infoModus(settings); + case Modus::NEWS_MODUS: + return newsModus(settings); + case Modus::UPDATE_MODUS: + return updateModus(settings); + case Modus::REMOVE_SETTINGS_AND_CACHE_MODUS: + return cleanUpSettingsAndCache(settings); + default: + std::cout << " => Error: Keine Unteroption ausgewählt." << std::endl; + return -1; + } +} + +void * threadFunction(void * data) { + ThreadData * myThreadData = reinterpret_cast(data); + myThreadData->returnValue=""; + myThreadData->exitState=0; + + + Reply tmp_reply = myThreadData->pageManager->getServerRequest(myThreadData->pageManager->UrlPraefix + myThreadData->nameInUrl + + "/staffel-" + std::to_string(myThreadData->staffel) + "/episode-" + std::to_string(myThreadData->folge)); + if(tmp_reply.html == "-1") { + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": getServerRequest Function reurns -1." << std::endl; + return myThreadData->setState(10); + } + std::string allLinks = myThreadData->pageManager->getLinks(tmp_reply.html); + std::string Link = myThreadData->pageManager->chooseHosterLink(allLinks, myThreadData->settings->genaueHoster, myThreadData->settings->languages, myThreadData->settings->debugMode); + + if(myThreadData->settings->debugMode) + std::cout << " > Thread " << myThreadData->id << allLinks << std::endl << ( (Link == "") ? "" : " -> Link: 'https://serienstream.sx") << Link << ( (Link == "") ? "" : "'\n" ); + + + + + std::string folgenID = std::string((myThreadData->staffel == -1 || myThreadData->folge == -1 ) ? "" : "S" + + std::string( (myThreadData->staffel < 10) ? "0" : "" ) + std::to_string(myThreadData->staffel) + + "E" + std::string( (myThreadData->folge < 10) ? "0" : "" ) + std::to_string( myThreadData->folge ) ); + std::string green = ((myThreadData->settings->colorless) ? "" : "\033[32m"), + red = ((myThreadData->settings->colorless) ? "" : "\033[31m"), + orange =((myThreadData->settings->colorless) ? "" : "\033[33m"), + blue = ((myThreadData->settings->colorless) ? "" : "\033[34m"), + clearColor = ((myThreadData->settings->colorless) ? "" : "\033[0m"); + + if(Link == "") { + //Wenn gar keine Links vorhanden sind: + if(allLinks == "") { + myThreadData->returnValue = " => " + red + "KEINEN Hoster für die Folge " + replace(folgenID, "E", " E") + " gefunden." + clearColor; + if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePaths, std::string("KEINEN Hoster für die Folge ") + + replace(folgenID, "E", " E") + std::string(" gefunden.")) != 0) { + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": writeToFile Function failed." << std::endl; + return myThreadData->setState(14); + } + //Wenn nur kein passender Link gefunden wurde: + } else { + myThreadData->returnValue = " => " + orange + "Keinen PASSENDEN Hoster für die Folge " + replace(folgenID, "E", " E") + " gefunden." + clearColor + "\n" + + "Alle Links:" + "\n" + + replace( + replace( replace( allLinks, "data-lang-key=\"1\"", "language=\"GerDub\"" ), + "data-lang-key=\"2\"", "language=\"Eng\"" ), "data-lang-key=\"3\"", "language=\"GerSub\""); + if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePaths, + std::string("Keinen PASSENDEN Hoster für die Folge ") + replace(folgenID, "E", " E") + + std::string(" gefunden.")) != 0) { + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": writeToFile Function failed." << std::endl; + return myThreadData->setState(15); + } + } + + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": closeThread, no (good) Link was found." << std::endl; + return myThreadData->setState(0); + } + + for (int i = 1; i <= 3; ++i) { + std::string newUrl = myThreadData->pageManager->getUrlAfterRedirect("https://serienstream.sx" + Link); + if (newUrl == "-1") { + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": getUrlAfterRedirect Function failed: returned -1." << std::endl; + return myThreadData->setState(16); + + // Get redirect link after getUrlAfterRedirect function + } else if(newUrl.find("/serienstream.sx/redirect/") != std::string::npos ) { + if(myThreadData->settings->debugMode) + std::cout << " > Thread " << myThreadData->id << "Warnung: Redirect Link nach umwandlung (Capcha?) --> Neuer Account" << std::endl; + if(myThreadData->pageManager->login(myThreadData->accountManager->getNextAccount()) != 0) { + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": login Function failed." << std::endl; + return myThreadData->setState(17); + } + continue; + + // get NO-Redirect Link after getUrlAfterRedirect Function + } else { + if( (newUrl = myThreadData->pageManager->getLinkAfterHosterBasedOperation(newUrl)) == "") { + if(myThreadData->settings->debugMode) + std::cout << " => Error in getLinkAfterHosterBasedOperation() -> exit threadFunction()" << std::endl; + return myThreadData->setState(22); + } + + myThreadData->returnValue = " => " + folgenID + ( (folgenID == "") ? "" : ": " ) + green + newUrl + clearColor; + if(myThreadData->settings->outputFilePaths.size() != 0) { + if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePaths,folgenID + ( (folgenID == "") ? "" : ": " ) + newUrl) != 0) { + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": writeToFile Function failed." << std::endl; + return myThreadData->setState(18); + } + } + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": get a NO Redirect Link after function: Good! => return 0." << std::endl; + return myThreadData->setState(0); + } + } + + //error at 3 time + myThreadData->returnValue = " => " + replace(folgenID, "E", " E") + ( (folgenID == "") ? "" : ": " ) + red + "https://serienstream.sx" + Link + clearColor; + if(myThreadData->settings->outputFilePaths.size() != 0) + if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePaths, replace(folgenID, "E", " E") + ( (folgenID == "") ? "" : ": " ) + Link) != 0) { + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": writeToFile Function failed." << std::endl; + return myThreadData->setState(19); + } + if(myThreadData->settings->debugMode) + std::cerr << " => Debug: In Thread: "<< myThreadData->id << ": 3 Times to convert fails, but return 0." << std::endl; + return myThreadData->setState(0); + +} + +int ProgramManager::waitForThreads() +{ + for( auto &e : threadList) { + if( e->exitState != -1 && pthread_join(e->thread, nullptr) == 0) { + if(e->exitState != 0) { + std::cout << "\33[2K\r => Error: Thread gab error zurück." << std::endl; + return e->exitState; + } else + if(e->returnValue != "") + std::cout << ("\33[2K\r(T" + std::to_string(e->id) + ")" + e->returnValue ) << std::endl; + } + e->exitState = -1; + e->returnValue = ""; + e->setData(0, 0); + e->thread = 0; + } + return 0; +} + +int ProgramManager::sucheNach_1_Serien(Settings *settings, PageManager &pageManager, std::string &newName) +{ + std::string finds; + //Führe unterfunction zum suchen von Serien aus, aber ohne suche auszugeben und speichere datein in variable + if(searchModus(settings, &finds, true) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Function searchModus returned error." << std::endl; + return 24; + + // Wenn der Rückgabe wert ungültig ist brich ab... + } else if( finds.find("|/") == std::string::npos ) { // || + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": searchModus's returnValue contains no / or | => error " << std::endl; + + return -10101; + + // Wenn der Rückgabewert mehrene newlines enthält gibt es mehrere Möglichkeiten + } else if (finds.find("\n") != std::string::npos) { + + //Gib alle gefundenen Serien Zeilenweise aus und schreibe davor die Zeile: + std::stringstream myStrStream(finds + "\n"); + std::string line; + + std::cout << "\nWähle eine der folgenden Serien, oder nur [Enter] um Forgang abzubrechen." << std::endl; + for (unsigned i = 1; std::getline(myStrStream, line).good() ; ++i) { + if(line.find_last_of("|") == std::string::npos) { + std::cout << " => Error: Invalid Line: " << line << std::endl; + return -21; + } + std::cout << i << ": " << line.substr(line.find_last_of("|") + 1) << ( (line[0] != '|') ? " ( " + line.substr(0, line.find("|")) + " )" : "" ) << std::endl; + } + + //Lass Benutzer Zeile auswählen: + std::cout << "Zeile: " << std::flush; + std::string input; + std::getline(std::cin, input); + + //Wenn kein Input, brich ab + if(input == "") { + std::cout << " => Abbruch..." << std::endl; + return -1; + } + + //Wähle Zeile aus + myStrStream.clear(); + myStrStream.str(finds + "\n"); + bool hasNewName = false; + + //Geh die Liste nochmal durch + for (unsigned i = 1; std::getline(myStrStream, line).good() ; ++i) { + if(line.find_last_of("|") == std::string::npos) { + std::cout << " => Error: Invalid Line: " << line << std::endl; + return -22; + + // Wenn die Zeile gleich der ausgewählten ist: + } else if(static_cast(i) == atoi(input.c_str()) ) { + //Speichere den Namen der Serie und setzte hasName auf true und brich schleife ab + if ( (finds = line.substr( line.find("|/") + 2, // beginn: nach dem |/ + line.find("|", line.find("|/") + 2) // Bis zu dem | ab dem ende von |/ + - line.find("|/") -2) ) == "" ) { // wegen nicht bi sondern länge, suptrahiere Pos 1 + std::cout << " => Error: Konnte den Namen aus der zurückgegebenen Zeile nicht extrahieren. In ausWahlVariante" << std::endl; + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Return value from searchModus.subStr(pos(/)-> next |, after /) is ''." << std::endl; + return 48; + } + hasNewName = true; + break; + } + } + //Wenn keine der Zeilen gelcih dem Input war, input invali -> brich ab... + if(!hasNewName) { + std::cout << " => Error: Ungültige Eingabe: '" << input << "'" << std::endl; + return 123; + } + + //Wenn nur 1 Serie gefunden wurde: + } else { + + //Frag den User ob das die Richtige Serie ist: + std::cout << " -> Ist das deine gewünschte Serie: '" + << finds.substr(finds.find_last_of("|") + 1) << "'" << ( (finds[0] != '|') ? " ( " + finds.substr(0, finds.find("|")) + " )" : "" ) << std::endl + << "Drücke nur [Enter] um fortzufahren: " << std::flush; + + std::string line; + std::getline(std::cin, line); + + //Wenn input => abbruch + if ( line != "") { + std::cout << " => Abbruch..." << std::endl; + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": User tipped an Value => wrong serie." << std::endl; + return 48; + } + + //Überschreibe eine Zeile mit nur dem url Namen + if ( (finds = finds.substr( finds.find("|/") + 2, finds.find("|", finds.find("|/") + 2) - finds.find("|/") -2) ) == "" ) { + std::cout << " => Error: Konnte den Namen aus der zurückgegebenen Zeile nicht extrahieren." << std::endl; + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Return value from searchModus.subStr(pos(/)-> next |, after /) is ''." << std::endl; + return 46; + } + + } + + //Überprüfe ob es die serie gibt wenn ja speicher ihn in newname und beende Function + newName = pageManager.checkName(finds); + if(newName == "-2") + return 23; + else if( newName == "-1" ) { + std::cout << " => Error: Konnte die von der Suche vorgeschlagene Serie nicht finden." << std::endl; + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Extracted Name from searchModus is invalid." << std::endl; + return 47; + } else { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Use new SerienName: '" << newName << "'." << std::endl; + return 0; + } +} + +int ProgramManager::checkLastUpdate(Settings *settings, ssize_t *days = nullptr) +{ + //Wenn die Funktion deaktiviert ist brich ab, wenn nicht nur diffdays verlangt wird + if(settings->updateWarningDays == 0 && !days) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": In settings: upDateWaring is deaktivated(seted to 0)." << std::endl; + return 0; + } + + std::ifstream ifs(settings->lastUpdateDateFilePath); + if(!ifs.is_open()) { + perror(("Konnte die Datei '" + settings->lastUpdateDateFilePath + "' nicht öffnen").c_str()); + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Failed to open Last Update Date File:'" << settings->lastUpdateDateFilePath << "'." << std::endl; + return 1; + } + std::string line; + ssize_t difDays = 0; + if(!std::getline(ifs, line).good()) { + perror("GetLine from Date failed"); + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Get the first Line of the LastUpdateDate File failed." << std::endl; + return 2; + + } else if( ( ( difDays = static_cast(pageManager.getDate()) - atoll(line.c_str()) )) >= settings->updateWarningDays) { + //Gib nachricht nicht aus wenn nur diffday verlangt wird + if(!days) { + std::cout << ((settings->colorless) ? "" : "\033[93m") << " => Warnung: SerienListe wurde zuletzt vor " << difDays << " Tagen aktualisiert." + << std::endl << " Mit '" << settings->programName << " search -u' kannst du die Liste aktualisieren." << ((settings->colorless) ? "" : "\033[0m") << std::endl; + } + } + //Wenn keine Ausgabe, sondern nur Tage gespeichgtert werden sollen(days != nullptr), speicher diffdays darin + if(days) + *days = difDays; + + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Exit with success." << std::endl; + return 0; +} + +int ProgramManager::defaultModus(Settings *settings) +{ + AccountManager accountManager(settings->accountFilePath, settings->accountNumberPath); + + //Wenn kein Name mit -n Angegeben wurde: + if(settings->name == "") { + if(settings->default_checkPath != "") { + if(settings->default_checkPath[settings->default_checkPath.length()-1] == settings->pathSymbol) + settings->default_checkPath.pop_back(); + size_t pos = settings->default_checkPath.find_last_of(std::string(1, settings->pathSymbol)); + if( pos != std::string::npos) { + settings->name = settings->default_checkPath.substr(pos + 1); + if(settings->debugMode) + std::cout << " > Use Path from -C for Name: " << settings->default_checkPath << " -> " << settings->name << std::endl; + } + } if(settings->name == "") { + std::cout << " => Kein Name angegeben." << std::endl; + std::cout << "Aufruf: " << settings->programName << " default [OPTION]... [NAME]..." << std::endl; + std::cout << "\"" << settings->programName << " default --help\" liefert weitere Informationen." << std::endl; + return 0; + } + } + + //Überprüfe ob ein Muster existiert: + if(settings->default_checkPath != "" && settings->default_Searchmuster == "") { + std::cout << " => Error: [-m]: Kein Muster angegeben." << std::endl; + return 0; + } + + + //Liste alle Dateien in dem Ornder von -C auf und speichere diese + std::string dirFiles; + if(settings->default_checkPath != "") + if(listDir(dirFiles, settings->default_checkPath, settings->default_maxDirs, settings->debugMode ) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": listDir failed." << std::endl; + return 28; + } + if(dirFiles.length() > 0) //Entferne von der liste das \n am ende + dirFiles.pop_back(); + + //Führe Function aus, die überprüft ob die serie existiert + std::string nameInUrl =pageManager.checkName(settings->name); + if(nameInUrl == "-2") + return 67; + else if(nameInUrl == "-1") { + //Wenn nicht, dann fühe noch eine Suche nach ähnlichen durch && Wenn nur 1ne dacnn frag ob es diese ist. + int res = 0; + if( ( res = sucheNach_1_Serien(settings, pageManager, nameInUrl) ) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": sucheNach_1_Serien failed or found more options." << std::endl; + return (res == -10101) ? 0 : 202; + } + } + + /* Wenn multihtreading seaktiviert ist, normal login sonst bereite threads vor + if(settings->maxThreads == 0) { + // melde bei serienstream.sx an und speicher cookies. + if (pageManager.login(accountManager.getNextAccount()) != 0) //---------------------------------------- + return 29; + }*/ + + if(settings->maxThreads > 0) { + for (unsigned i = 0; i < settings->maxThreads; ++i) { + if(dirExists(settings->cookieFilePath + std::to_string( i ))) { + std::cout << " => Error: Kann Cokkie-File nicht erstellen: Es existiert bereits ein Ordner mit diesem Namen: \n '" + << settings->cookieFilePath + std::to_string( i ) << "'." << std::endl; + return 174; + } + PageManager * pm = new PageManager(settings->proxy_ip + ":" + std::to_string(settings->proxy_port), settings->cookieFilePath + std::to_string( i )); + pm->setDebugMode(settings->debugMode); + + //pm->setProxy(settings->proxy_ip, settings->proxy_port); + //pm->setCookieFilePath(settings->cookieFilePath + std::to_string( i )); + + ThreadData * newThreadData = new ThreadData(i, 0, nameInUrl, -1, settings, &accountManager, pm); + threadList.push_back(newThreadData); + } + } + + //Write Name to File if -o is set und kein TXT-FILE angegeben wird + if(settings->outputFilePaths.size() != 0 && !fileExists( settings->default_checkPath )) + if(pageManager.writeToFile(settings->outputFilePaths, "Name: " + settings->name) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile Function fails when write Name." << std::endl; + return 31; + } + + //Finde die anzahl der staffel heraus: + //download html von der startpage einer serie + Reply tmp_reply = pageManager.getServerRequest(pageManager.UrlPraefix + nameInUrl); + if(tmp_reply.html == "-1" || tmp_reply.html == "") { + std::cerr << " => Error: Konnte Seitenquelltext nicht herunterladen." << std::endl; + return 32; + } + + //speicher zahl -1, ab da wo /staffel-x nicht mehr vorkommt + int maxStaffel = pageManager.counterContains(tmp_reply.html, "/staffel-%i"); + if(settings->debugMode) + std::cout << " > Die Serie " << settings->name << " hat " << maxStaffel << " Staffeln." << std::endl; + + //wenn starterstaffel 0 ist, also letzte staffel, dann ersetzte variable mit maxStaffeln + if(settings->startSeason == 0) + settings->startSeason = maxStaffel; + + //For every season + for (int staffel = settings->startSeason; staffel <= maxStaffel; ++staffel) { + //Test for stopping Program caused -E, -S + if(staffel > settings->stopSeason && settings->stopSeason > 0) { + if(settings->maxThreads != 0) + if(waitForThreads() != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl; + return 261; + } + if(settings->debugMode) + std::cout << " > Stoppe, weil Staffel: " << staffel << " > StopStaffel " << settings->stopSeason << std::endl; + std::cout << " > Fertig, da Staffel " << staffel << " größer ist als StopStaffel " << settings->stopSeason << std::endl; + return 0; + } + + //Find out number of all episodes + if( (tmp_reply = pageManager.getServerRequest(pageManager.UrlPraefix + nameInUrl + "/staffel-" + std::to_string(staffel))).html == "-1") { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest failed when download season page." << std::endl; + return 40; + } + int maxFolge = pageManager.counterContains(tmp_reply.html, "/episode-%i"); + + //Print seasons + if(settings->debugMode) + std::cout << " > Die Staffel " << staffel << " hat " << maxFolge << " Folgen." << std::endl; + + //for every episode + for (int folge = settings->startEpisode; folge <= maxFolge; ++folge) { + + // stoppe wenn stopfolge größer der folge ist und stopstaffel nicht gesetzt wurde. und stopepisode gröser 0, also aktiv ist + if(folge > settings->stopEpisode && settings->stopSeason < 1 && settings->stopEpisode > 0) { + if(settings->maxThreads != 0) + if(waitForThreads() != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl; + return 261; + } + std::cout << " > Fertig, da Folge " << folge << " größer ist als Stopfolge " << settings->stopEpisode << "."<< std::endl; + return 0; + + + // stoppe wenn stopfolge > folge && stopstaffel >= staffel und stopepisode gröser 0, also aktiv ist + } else if ( folge > settings->stopEpisode && staffel >= settings->stopSeason && settings->stopEpisode > 0) { + if(settings->maxThreads != 0) + if(waitForThreads() != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl; + return 267; + } + std::cout << " > Fertig, da Folge " << folge << " größer ist als Stopfolge " << settings->stopEpisode << std::endl + << " und Staffel " << staffel << " größer gleich Stopstaffel " << settings->stopSeason << " ist." << std::endl; + return 0; + } + + //Überprüfe ob, wenn -C vorhanden, die Folge in dem Ordner bereits vorkommt. + if(settings->default_checkPath != "") { + if(dirFiles.find(replace( replace( settings->default_Searchmuster, "%Staffel%", ((staffel < 10) ? "0" : "") + std::to_string(staffel) ), + "%Folge%", ((folge < 10) ? "0" : "") + std::to_string(folge) ) ) != std::string::npos) { + if(settings->debugMode) + std::cout << " > Skippe Folge: S" << staffel << "E" << folge << std::endl; + continue; + } + } + + //Multihreading Mode + if(settings->maxThreads > 0) { + //Wenn nex Thread noch in den Vector passt(weniger Threads als Max), dann Starte neuen mit data aus dem Vector... + if(nextThread < threadList.size()) { + threadList[nextThread]->exitState = 0; + threadList[nextThread]->setData(staffel, folge); + if(pthread_create(&threadList[nextThread]->thread, nullptr, threadFunction, reinterpret_cast(threadList[nextThread])) != 0 ) { + perror("pthread_creat failed"); + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Create thread for redirect converting failed." << std::endl; + return 48; + } + ++nextThread; + } else { // Sonnst warte bis alle Fertig sind und restarte die Folge + if(waitForThreads() != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl; + return 231; + } + nextThread=0; + folge--; + continue; + } + + + // Default Mode + } else { + tmp_reply =pageManager.getServerRequest(pageManager.UrlPraefix + nameInUrl + "/staffel-" + std::to_string(staffel) + "/episode-" + std::to_string(folge)); + if(tmp_reply.html == "-1") { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest failed when download episoden page." << std::endl; + return 50; + } + std::string allLinks = pageManager.getLinks(tmp_reply.html); + if(settings->genaueHoster == "*," && settings->debugMode) { + if(settings->debugMode) + std::cout << allLinks << std::endl; + std::stringstream strstrem(allLinks); + std::string line; + while (std::getline(strstrem, line).good()) { + size_t pos = line.find("/redirect/"); + if(pos == std::string::npos) { + std::cout << " => Error: Konnte den Redirect Link in der Zeile aus LinksListe nicht finden." << std::endl; + return 400; + } else + line.erase(0, pos); + line.erase(line.find("\"")); + if(convertLink(line, &accountManager, settings, staffel, folge, allLinks) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": convertLink failed." << std::endl; + return 51; + } + } + //Stop beacause same episode every account can only 2 videos not 10-12 + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Stop Program, because '*'-Hoster is inperformatnt: Every Account can only 2 Vidoes not 10-12." << std::endl; + return 0; + + } else { + std::string Link = pageManager.chooseHosterLink(allLinks, settings->genaueHoster, settings->languages, settings->debugMode); + + if(settings->debugMode) + std::cout << allLinks << std::endl << ( (Link == "") ? "" : " -> Link: 'https://serienstream.sx") << Link << ( (Link == "") ? "" : "'\n" ); + if(convertLink(Link, &accountManager, settings, staffel, folge, allLinks) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": convert Link failed." << std::endl; + return 51; + } + } + + + } + } + //Setzte Startepisode zurück für nächste Staffel + settings->startEpisode = 1; + } + + if(settings->maxThreads != 0) + if(waitForThreads() != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Wait for the Threads failed." << std::endl; + return 292; + } + + std::cout << " > Fertig" << std::endl; + return 0; +} + +int ProgramManager::directLinkModus(Settings *settings) +{ + AccountManager accountManager(settings->accountFilePath, settings->accountNumberPath); + + if(settings->name == "") { + std::cout << " => Kein(e) Link(s) angegeben." << std::endl; + std::cout << "Aufruf: " << settings->programName << " url [OPTION]... [URL]..." << std::endl; + std::cout << "\"" << settings->programName << " url --help\" liefert weitere Informationen." << std::endl; + return 0; + } + + std::istringstream iStrStream( replace( settings->name, ",", "\n" ) + "\n" ); + std::string line; + + //if(pageManager.login(accountManager.getNextAccount()) != 0) + // return 71; + + while (getline(iStrStream, line).good()) { + if(line.find("/redirect/") == std::string::npos) { + std::cout << " => Error: Invalid Redirect Link: '" << line << "'" << std::endl; + continue; + + } else if(convertLink(line.erase(0, line.find("/redirect/") ), &accountManager, settings) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": convert Link failed." << std::endl; + return 78; + } + } + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Success." << std::endl; + return 0; +} + +int ProgramManager::searchModus(Settings *settings, std::string *saveTo, bool noPrint) +{ + if(settings->showLastUpdate) { + ssize_t dayddiff; + if(checkLastUpdate(settings, &dayddiff) != 0) { + std::cout << " => Error: CheckLasUpdate-Funktion gab einen Error zurück." << std::endl; + return -1; + } else + std::cout << " => Letzte Aktualisierung: Vor " << dayddiff << " Tagen." << std::endl; + if(!settings->search_wantUpdate && settings->name == "") { + if(settings->debugMode) + std::cout << " >>> Debug: Verlasse Funktion searchModus: Nur -l" << std::endl; + return 0; + } + + } if(settings->search_wantUpdate) { + int res = searchModus_update(settings) ; + if(res == 0) { + std::cout << "Erfolgreich geupdatet: Die Serienliste ist nun auf dem neusten Stand." << std::endl; + if (settings->name == "") { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": Stop after Update: No Name => Only Updating." << std::endl; + return 0; + } + + } else { + std::cout << " => Error: Das updaten der Serienliste ist fehlgeschlagen." << std::endl; + return res; + } + + } else if(settings->name == "") { + std::cout << " => Kein Name angegeben." << std::endl; + std::cout << "Aufruf: " << settings->programName << " search [OPTION]... [NAME]..." << std::endl; + std::cout << "\"" << settings->programName << " search --help\" liefert weitere Informationen." << std::endl; + return 0; + } + + std::ifstream ifs(settings->serienListPath); + if(!ifs.is_open()) { + std::cout << " => Keine SerienListe vorhanden. Erstelle eine neue..." << std::endl; + if(searchModus_update(settings) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": searchModus_update function failed." << std::endl; + return 354; + } + else { + ifs.open(settings->serienListPath); + if(!ifs.is_open()) { + perror(" => Error: Couldn't open SerienList file after update again."); + return 434; + } + std::cout << "Erfolgreich gedownloadet." << std::endl; + } + } + + //Check for last Update.. + if(checkLastUpdate(settings) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": checkLastUpdate function failed." << std::endl; + return -1; + } + + //Save file in string: + std::string serienListe((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + + //Suche alle Möglichkeiten + std::string finds = pageManager.grep(serienListe, settings->name, settings->search_IgnoreUpperLower); + serienListe.clear(); // Speicher freigeben + + /*//Text mit Farben versehen + if(!settings->colorless) { + for (size_t pos = pageManager.upper_string( finds ).find( pageManager.upper_string( settings->name ), 0); + pos != std::string::npos; + pos = pageManager.upper_string( finds ).find( pageManager.upper_string( settings->name ), pos + settings->name.length() + strlen("\033[37m\033[0m"))) + finds.insert(pos, ( (finds.find(settings->name, pos) == pos) ? "\033[32m" : "\033[36m" ) ).insert(pos + settings->name.length() + strlen("\033[37m"), "\033[0m"); + }*/ + + if(saveTo) { + //Save List to Variable if set + *saveTo=finds; + } if (noPrint) { + return 0; + } + + //Text mit Farben versehen + if(!settings->colorless) { + std::string UpperFinds = pageManager.upper_string( finds ); + std::string UpperName = pageManager.upper_string( settings->name ); + for (size_t pos = UpperFinds.find( UpperName, 0); pos != std::string::npos; pos = UpperFinds.find( UpperName, pos + settings->name.length() + strlen("\033[37m\033[0m"))) { + bool exaktGeschrieben = (finds.find(settings->name, pos) == pos); + finds.insert(pos, ( (exaktGeschrieben) ? "\033[32m" : "\033[36m" ) ).insert(pos + settings->name.length() + strlen("\033[37m"), "\033[0m"); + UpperFinds.insert(pos, ( (exaktGeschrieben ) ? "\033[32m" : "\033[36m" ) ).insert(pos + settings->name.length() + strlen("\033[37m"), "\033[0m"); + } + } + //Ausgabe + if(finds == "") { + std::cout << " => Für '" << settings->name << "' wurde(n) keine Serie(n) gefunden." << std::endl; + return 0; + } + std::stringstream strstream(finds); + std::string line; + std::cout << " => Für '" << settings->name << "' wurde(n) folgende Serie(n) gefunden: " << std::endl; + while (getline(strstream, line)) { + std::cout << " > " << line.substr(line.find_last_of('|') + 1, std::string::npos ) + << "\t[" << line.substr(line.find("|/") + 2, line.find("|", line.find("|/") + 2) - line.find("|/") - 2) << "]" + << ( (line[0] == '|') ? "" : "\t( " + line.substr(0, line.find("|")) + " )" ) << std::endl; + } + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": success." << std::endl; + return 0; +} + +int ProgramManager::infoModus(Settings *settings) +{ + if(settings->name == "") { + std::cout << " => Kein Name angegeben." << std::endl; + std::cout << "Aufruf: " << settings->programName << " info [OPTION]... [NAME]..." << std::endl; + std::cout << "\"" << settings->programName << " info --help\" liefert weitere Informationen." << std::endl; + return 0; + } + + //Führe Function aus, die überprüft ob die serie existiert + std::string nameInUrl = pageManager.checkName(settings->name); + if(nameInUrl == "-2") + return 145; + else if(nameInUrl == "-1") { + //Wenn nicht, dann fühe noch eine Suche nach ähnlichen durch. + int res = 0; + if( ( res = sucheNach_1_Serien(settings, pageManager, nameInUrl) ) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": sucheNach_1_Serien function failed." << std::endl; + return (res = -10101) ? 0 : 28; + } + } + + //write Name to file + if(pageManager.writeToFile(settings->outputFilePaths, "\n\nSerie: " + settings->name + " (" + nameInUrl + ")") != 0) + { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 100; + } + + + //Finde Anzahl der Staffel heraus: + Reply tmp_reply = pageManager.getServerRequest(pageManager.UrlPraefix + nameInUrl); + if(tmp_reply.html == "-1") { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest function failed: at homepage." << std::endl; + return 32; + } + + std::string green = ((settings->colorless) ? "" : "\033[92m"), + lila = ((settings->colorless) ? "" : "\033[95m"), + Lightyellow = ((settings->colorless) ? "" : "\033[93m"), + Darkyellow = ((settings->colorless) ? "" : "\033[33m"), + blue = ((settings->colorless) ? "" : "\033[96m"), + white = ((settings->colorless) ? "" : "\033[0m"); + + + if( ! settings->skipEpisodenNameOutput) { + + //Für FolgenNummer ingesmammt + int gesammtFolge = 0; + //speicher (zahl -1), ab da wo /staffel-x nicht mehr vorkommt + int maxStaffel = pageManager.counterContains(tmp_reply.html, "/staffel-%i"); + + //Um namen der Folge für jede Staffel zu bekommen + for (int staffel = 1; staffel <= maxStaffel; ++staffel) { + Reply tmpReply = pageManager.getServerRequest(pageManager.UrlPraefix + nameInUrl + "/staffel-" + std::to_string(staffel)); + if(tmpReply.html == "-1") { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest function failed: at season page." << std::endl; + return 40; + } + + int folgen = pageManager.counterContains(tmpReply.html, "/episode-%i"); + std::cout << std::endl + << green << "Die Staffel " << staffel << " hat " << folgen << " Folge" << ((folgen > 1) ? "n" : "") << "." << white << std::endl + << std::endl; + if(pageManager.writeToFile(settings->outputFilePaths, "\nDie Staffel " + std::to_string(staffel) + + " hat " + std::to_string(folgen) + " Folge" + ((folgen > 1) ? "n" : "") + ".\n") != 0) + { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 110; + } + + + std::string html = tmpReply.html; + size_t pos = 0; + if( (pos = html.find(" Error: Konnte Position von '")) == std::string::npos) { + std::cout << " => Error: Konnte Position von '' nicht finden." << std::endl; + return 42; + } else + html.erase(pos, std::string::npos); + + html = replace(html, "\n", ""); + html = replace(html, "", "\n"); + + std::stringstream folgenListe(html); + std::string line; + + while (std::getline(folgenListe, line).good()) { + std::string titel; + gesammtFolge = gesammtFolge + 1; + + if( (pos = line.find("\"> Folge")) == std::string::npos) { + std::cout << " => Error: Konnte Position von '\"> Folge' nicht finden." << std::endl; + return 43; + } else + line.erase(0, pos + 9); + if( (pos = line.find(" ")) == std::string::npos) { + std::cout << " => Error: Konnte Position von ' ' nicht finden." << std::endl; + return 44; + } + std::cout << lila << "Ep. " << blue << ( (gesammtFolge < 100) ? ( (gesammtFolge < 10) ? "00" : "0" ) : "" ) << gesammtFolge << lila + << " ( " << blue << "S" << ( (staffel < 10) ? "0" : "" ) << staffel + << "E" << ( ( atoi( line.substr(0, pos).c_str() ) < 10) ? "0" : "" ) << line.substr(0, pos) << lila << " ):" << white <outputFilePaths, "Ep. " + std::string( (gesammtFolge < 100) ? ( (gesammtFolge < 10) ? "00" : "0" ) : "" ) + + std::to_string(gesammtFolge) + " ( S" + ( (staffel < 10) ? "0" : "" ) + std::to_string(staffel) + "E" + + ( ( atoi( line.substr(0, pos).c_str() ) < 10) ? "0" : "" ) + line.substr(0, pos) + " ):" ) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 105; + } + + if( (pos = line.find("")) == std::string::npos) { + std::cout << " => Error: Konnte Position von '' nicht finden." << std::endl; + return 43; + } else + line.erase(0, pos + 8); + if( (pos = line.find("")) == std::string::npos) { + std::cout << " => Error: Konnte Position von '' nicht finden." << std::endl; + return 44; + } + titel = line.substr(0, pos); + if(titel != "") { + std::cout << lila << " > Titel 1: " << Lightyellow << titel << white << std::endl; + if(pageManager.writeToFile(settings->outputFilePaths, " > Titel 1: " + titel) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 110; + } + } + + if( (pos = line.find("")) == std::string::npos) { + std::cout << " => Error: Konnte Position von '' nicht finden." << std::endl; + return 43; + } else + line.erase(0, pos + 6); + if( (pos = line.find("")) == std::string::npos) { + std::cout << " => Error: Konnte Position von '' nicht finden." << std::endl; + return 44; + } + titel = line.substr(0, pos); + if(titel != "") { + std::cout << lila << " > Titel 2: " << Darkyellow << titel << white << std::endl; + if(pageManager.writeToFile(settings->outputFilePaths, " > Titel 2: " + titel) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 120; + } + + } + } + + } + + } + + //Datum & FSK + std::string line = pageManager.grep(tmp_reply.html, " ( Error: Konnte ' ( Error: Konnte 'href=' nicht finden." << std::endl; + return 84; + } else + line.erase(0, pos + 5); + + if( (pos = line.find(">")) == std::string::npos ) { + std::cout << " => Error: Konnte '>' nicht finden." << std::endl; + return 85; + } else if ((pos2 = line.find("")) == std::string::npos ) { + std::cout << " => Error: Konnte '' nicht finden." << std::endl; + return 86; + } + startStopDates[i] = line.substr(pos + 1, pos2 - pos -1); + } + + //FSK + if( (pos = line.find("data-fsk=\"")) == std::string::npos ) { + std::cout << " => Error: Konnte 'data-fsk=\"' nicht finden." << std::endl; + return 87; + } else if ((pos2 = line.find("\" class=\"fsk")) == std::string::npos ) { + std::cout << " => Error: Konnte '\" class=\"fsk' nicht finden." << std::endl; + return 86; + } + std::string fsk = line.substr(pos + 10, pos2 -pos - 10); + + //Deskription + if( (pos = tmp_reply.html.find("data-full-description=")) == std::string::npos) { + std::cout << " => Error: Konnte 'data-full-description=' nicht finden." << std::endl; + return 83; + } else if ((pos2 = tmp_reply.html.find("\">", pos)) == std::string::npos ) { + std::cout << " => Error: Konnte '\">' nicht finden." << std::endl; + return 86; + } + std::string description = replace( replace( tmp_reply.html.substr(pos + 23, pos2 - pos - 23), "\n", "" ), "
", "" ); + + //remove bug text: + description = replace(description, "&quot;", "\""); // + + description = replace(description, "&", "&"); // + description = replace(description, "<", "<"); // + description = replace(description, ">", ">"); // + + description = replace(description, "
", " "); // + description = replace(description, """, "\""); // + description = replace(description, "'", "'"); // + + + //Genres + std::vector genres; + line = pageManager.grep(tmp_reply.html, "\"genre\">"); + if(line == "") { + std::cout << " => Error: Konnte '\"genre\">' nicht finden." << std::endl; + return 87; + } + for (pos = line.find("\"genre\">"); pos != std::string::npos; pos = line.find("\"genre\">", pos + 7)) { + if( (pos2 = line.find("", pos)) == std::string::npos) { + std::cout << " => Error: Konnte '' nicht finden." << std::endl; + return 89; + } + genres.push_back(line.substr(pos + 8, pos2 - pos - 8)); + } + + //CoverLink + line = pageManager.grep(tmp_reply.html, "title=\"Cover"); + if( (pos = line.find("data-src=\"")) == std::string::npos) { + std::cout << " => Error: Konnte 'data-src=\"' nicht finden." << std::endl; + return 90; + } else if ((pos2 = line.find("\"", pos + 10)) == std::string::npos ) { + std::cout << " => Error: Konnte '\"' nicht finden." << std::endl; + return 86; + } + std::string coverLink = line.substr(pos + 10, pos2 - pos -10); + + + //Ausgabe + + std::cout << lila << "\nProduktion von " << blue << startStopDates[0] << lila << " bis " << blue << startStopDates[1] << lila << std::endl + << "FSK: " << blue << fsk << lila << std::endl + << "Cover Bild: " << green << coverLink << lila << std::endl + << "Genre(s): " << blue << std::flush; + for( const auto &e : genres) + std::cout << e << " "; + + std::cout << lila << std::endl << "\nBeschreibung: " << green << description << white << std::endl; + + + //Schreibe das auch in ein Text file: + std::string all_genres; + for( const auto &e : genres) + all_genres += e + " "; + + if(pageManager.writeToFile(settings->outputFilePaths, "\nProduktion von " + startStopDates[0] + " bis " + startStopDates[1] + "\n" + "FSK: " + fsk + "\n" + "Cover Bild: " + coverLink + "\n" + "Genre(s): " + all_genres + "\n" + "\nBeschreibung: " + description + "\n") != 0) + { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 130; + } + + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": success exit." << std::endl; + return 0; +} + +int ProgramManager::newsModus(Settings *settings) +{ + size_t pos = 0; + std::string html = pageManager.getServerRequest("https://serienstream.sx/neue-episoden").html; + if(html == "-1") { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest function failed." << std::endl; + return 1; + } + + if( (pos = html.find("
")) == std::string::npos ) { + std::cout << " => Error: Konnte Position von '
'' nicht finden" <
")) == std::string::npos ) { + std::cout << " => Error: Konnte Position von '
' nicht finden" <"); + size_t pos2 = line.find(""); + if(pos == std::string::npos) { + std::cout << " => Error: Konnte Position von '' nicht finden" < Error: Konnte Position von '' nicht finden" <")) == std::string::npos) { + std::cout << " => Error: Konnte Position von 'blue2\">' nicht finden" <", pos)) == std::string::npos) { + std::cout << " => Error: Konnte Position von '' nicht finden" <")) == std::string::npos) { + std::cout << " => Error: Konnte Position von 'Right\">' nicht finden" <", pos)) == std::string::npos) { + std::cout << " => Error: Konnte Position von '' nicht finden" < " << ((settings->colorless) ? "" : "\033[97m") << date << ((settings->colorless) ? "" : "\033[0m") << ": " + << ((settings->colorless) ? "" : "\033[96m") << name << ((settings->colorless) ? "" : "\033[0m") << ": " + << ((settings->colorless) ? "" : "\033[92m") << id << ((settings->colorless) ? "" : "\033[0m") << std::endl; + } + + return 0; +} + +int ProgramManager::updateModus(Settings *settings) +{ + if(settings->VersionFileUrl == "" || settings->ProgrammFileUrl == "") { + std::cout << " => Error: Kein Download Link verfügbar!" << std::endl; + return 4; + } + + std::cout << " => INFO: Suche nach der neusten Version..." << std::endl; + std::string html = pageManager.getServerRequest(settings->VersionFileUrl).html; + + if( html == "-1" || html == "" || html.find("\n") == std::string::npos) { + // Wenn debug mode print error + if(settings->debugMode) + std::cerr << " => Error: Download newst Version failed." << std::endl; + // no error output in pagemanager => print error + else if(html == "") + std::cout << " => Error: Das herunterladen der neusten Version ist fehlgeschlagen." << std::endl; + return 1; + } else { + html = replace(html, "\r", ""); + } + + + // Get newst Version + std::string neusteVersion = html.substr(0, html.find("\n")); + html.erase(0, html.find("\n") + 1); + + //Überprüfe onb neue Version einen . enthält + if(neusteVersion.find(".") == std::string::npos) { + size_t pos; + if((pos = html.find("h1>")) != std::string::npos) + std::cout << " => Das herunterladen ist fehlgeschlagen: '" << html.substr(pos + 3, html.find("") - pos -3) << "'." << std::endl; + else + std::cout << " => Error: Die neuste Version ist ungültig: '" << neusteVersion << "'." << std::endl; + return -3; + } + + //Gib Versionenunterschie aus + std::cout << " => INFO: Jetzige Version: '" << settings->version << "' - Neueste Version: '" << neusteVersion << "'" << std::endl; + + //Print INFOs + std::cout << " => Infos (zur Version): " << std::endl; + std::string line; + std::stringstream strstream(html+ "\n"); + while (std::getline(strstream, line).good()) { + if(line != "") + std::cout << "\033[92m > " << line << "\033[0m" << std::endl; + } + + //Vergleiche Versionen: + switch (pageManager.compareVersions(settings->version, neusteVersion)) { + case 0: + std::cout << "\n => Du benützt bereits die neuste Release-Version." << std::endl; + return 0; + case 1: + //Diese Version ist klleienr als aktuelle Version => Updatete + break; + case 2: + std::cout << "\n => Du benützt bereits eine Aktuellere Version als die neuste Release-Version." << std::endl; + return 0; + default: + //Error + return 2; + } + + //lege pfad zum speichern fest + std::string downloadedFilePath = settings->cacheDir + "NeusteVersion" + ((settings->pathSymbol == '\\') ? ".exe" : ""); + + //wenn dort schon eine datei existiert, lösche diese + std::cout << " => INFO: Lösche Download-Datei, fallst bereits eine vorhanden ist..." << std::endl; + if(fileExists(downloadedFilePath)) { + if(remove(downloadedFilePath.c_str()) != 0) { + perror((" => Error: Das löschen der Datei '" + downloadedFilePath + "' ist fehlgeschlagen").c_str()); + return 13; + } else if (settings->debugMode) { + std::cout << " => DEBUG: Erfolgreich alte gedownloadete Datei '" << downloadedFilePath << "' gelöscht." << std::endl; + } + } + + //Download new Version of Program + std::cout << " => INFO: Lade neue Version herunter..." << std::endl; + + if( pageManager.downLoadToFile(downloadedFilePath, settings->ProgrammFileUrl) != 0) { + std::cout << "\n => Error: Das herunterladen der neuen Version ist fehlgeschlagen." << std::endl; + return 3; + } std::cout << std::endl; + + + //Make ist executable for test execution +#ifdef __linux__ + std::cout << " => INFO: Mache das Programm ausführbar..." << std::endl; + if(chmod(downloadedFilePath.c_str(), S_IRWXU) != 0) { + perror(" => Error: Chmod failed"); + return 4; + } +#endif + + //Führe neue Version aus und überprüfe rückgabewert + std::cout << " => INFO: Überprüfe die Funktionalität der neuen Version..." << std::endl; + + if( system((downloadedFilePath + " --version" ).c_str()) != 0) { + std::cerr << (" => Error: Ausführen der neuen Version ist fehlgeschlagen") << std::endl; + return 5; + } + + //find exePath heraus + std::string exePath = pageManager.getExePath(); + if(exePath == "") { + std::cout << " => Error: Function getExepath() ist fehlgeschlagen." << std::endl; + return 6; + } + + //lege pfad für alte version fest + std::string oldVersionPah = settings->cacheDir + "oldVersion" + ((settings->pathSymbol == '\\') ? ".exe" : ""); + + //lösche falls vorhanden altes backup + std::cout << " => INFO: Lösche alte Nofall Version falls vorhanden..." << std::endl; + if(fileExists(oldVersionPah)) { + if(remove( oldVersionPah.c_str() ) != 0) { + perror((" => Error: Das löschen der Datei '" + oldVersionPah + "' ist fehlgeschlagen.").c_str()); + return 14; + } else if (settings->debugMode) { + std::cout << " => DEBUG: Erfolgreich Notfall Version '" << oldVersionPah << "' gelöscht." << std::endl; + } + } + + //verschiebe neue jetzige version zu backup + std::cout << " => INFO: Verschiebe alte Version für Notfälle zu: '" << oldVersionPah << "'." << std::endl; + + if(rename(exePath.c_str(), oldVersionPah.c_str() ) != 0) { + perror((" => Error das Verschieben von '" + exePath + "' -> '" + oldVersionPah + "' ist fehlgeschlagen").c_str()); + return 7; + } + + //verschibe neue Version + std::cout << " => INFO: Ersetzte alte Version mit neuer Version des Programms..." << std::endl; + + if(rename(downloadedFilePath.c_str(), exePath.c_str() ) != 0) { + perror((" => Error: Das Verschieben von '" + downloadedFilePath + "' nach '" + exePath + "' ist fehlgeschlagen").c_str()); + return 7; + } else { + std::cout << " => INFO: Erfolgreich verschoben und ersetzt:\n '" + << downloadedFilePath << "' -> '" << exePath << "'" << std::endl; + } + + std::cout << "\n => Update Erfolgreich ausgeführt: '" << settings->version << "' -> '" << neusteVersion << "'" << std::endl; + + return 0; +} + +int ProgramManager::cleanUpSettingsAndCache(Settings *settings) +{ + //Alle Groß + settings->name = pageManager.upper_string(settings->name); + + //setting dir + if(settings->name == "SETTINGS" || settings->name == "ALL") { + if( ! removeDirIsOk(settings->configDir, settings)) { + std::cout << " => Error: Das löschen des Settings-Ordners ist fehlgeschlagen." << std::endl; + return 1; + } + + } + + //Cache Dir + if (settings->name == "CACHE" || settings->name == "ALL") { + if( ! removeDirIsOk(settings->cacheDir, settings)) { + std::cout << " => Error: Das löschen des Cache-Ordners ist fehlgeschlagen." << std::endl; + return 2; + } + + } + if(settings->name != "CACHE" && settings->name != "SETTINGS" && settings->name != "ALL") + { + std::cout << " => Error: Unbekannte Option '" << settings->name << "' für Ordnerauswahl." << std::endl; + std::cout << "Aufruf: " << settings->programName << " --remove [OPTION]... [settings|cache|all]" << std::endl; + std::cout << "\"" << settings->programName << " --remove --help\" liefert weitere Informationen." << std::endl; + return 3; + } + + + return 0; +} + + +int ProgramManager::searchModus_update(Settings *settings) +{ + Reply reply = pageManager.getServerRequest("https://serienstream.sx/serien-alphabet"); + if(reply.html == "-1") { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest function failed." << std::endl; + return 21; + } + else if(reply.html.find("") == std::string::npos ) { + std::cout << " => Error: Konnte in searchModus_update() nicht finden." << std::endl; + return 22; + } + + std::string serienListe = replace( pageManager.grep( reply.html, "data-alternative-title" ), "", "\n" ); + + if(reply.html.find("\" href=\"") == std::string::npos || + reply.html.find("
  • ") == std::string::npos) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ + << ": hatml doesnt contain:' \" href=\" or
  • ' after preparing." << std::endl; + return 51; + } + + //...\n
  • 2012 - Das Jahr Null\n... + serienListe = replace(serienListe, "
  • 2012 - Das Jahr Null\n... + serienListe = replace(serienListe, "\" href=\"", "|"); + //...\n|/serie/stream/2012-das-jahr-null" title="2012 - Das Jahr Null Stream anschauen">2012 - Das Jahr Null\n... + serienListe = replace(serienListe, "|/serie/stream/", "|/"); + + std::stringstream strstream(serienListe); + std::string line; + serienListe.clear(); + + while (getline(strstream, line)) { + if(line.find(" title=\"") == std::string::npos) + continue; + + line.erase(line.find(" title="), line.find(">") - line.find(" title=")); + //...\n|/serie/stream/2012-das-jahr-null"_weg_>2012 - Das Jahr Null\n... + line = replace(line, "\">", "|"); + //...\n|/serie/stream/2012-das-jahr-null|2012 - Das Jahr Null\n... + line = replace(line, "", ""); + //...\n|/serie/stream/2012-das-jahr-null"_weg_>2012 - Das Jahr Null|\n... + + serienListe += line + "\n"; + } + if(serienListe.length() > 0) + serienListe.pop_back(); + + //Entferne Html Sonderzeichen + serienListe = replace(serienListe, "&quot;", "\""); // + + serienListe = replace(serienListe, "&", "&"); // + serienListe = replace(serienListe, "<", "<"); // + serienListe = replace(serienListe, ">", ">"); // + + serienListe = replace(serienListe, "
    ", " "); // + serienListe = replace(serienListe, """, "\""); // + serienListe = replace(serienListe, "'", "'"); // + + + + //Anzahl der Serien/Zeilen vorher: + ssize_t countBef = 0; + std::ifstream myFileBef(settings->serienListPath); + std::string alteListe; + if(myFileBef.is_open()) { + for(countBef = 0; std::getline(myFileBef,line); ++countBef) { + //Speicher alteListe für verglkeich nach Update + alteListe.append(line + "\n"); + + //Vergeliche neue und alte list => entfernte Serien + if(line != "" && serienListe.find(line) == std::string::npos) { + std::cout << ((settings->colorless) ? "" : "\033[91m") << "Entfernt: '" << line.substr(line.find_last_of("|") + 1) << "'" << ((settings->colorless) ? "" : "\033[0m") + << std::endl; + } + } + myFileBef.close(); + } + + //Schreibe die Liste in das TextFile + std::ofstream ofs(settings->serienListPath, std::ios::trunc); + if(!ofs.is_open()) { + perror("Konnte SerienListe-Datei nicht öffnen"); + return 111; + } else { + //Schreibe Liste in das TextFile + ofs << serienListe << std::endl; + ofs.close(); + } + + //Anzahl der Zeile nachher + ssize_t countAf = 0; + std::ifstream myFileAf(settings->serienListPath); + if(myFileAf.is_open()) { + for(countAf = 0; std::getline(myFileAf,line); ++countAf) { + //Vergeliche neu mit Alt => gib neue Serien aus + if(line != "" && alteListe.find(line) == std::string::npos) { + std::cout << ((settings->colorless) ? "" : "\033[92m") << "Neu: '" << line.substr(line.find_last_of("|") + 1) << "'" << ((settings->colorless) ? "" : "\033[0m") + << std::endl; + } + } + myFileAf.close(); + } else { + perror("Konnte SerienListe-Datei nicht öffnen"); + return 112; + } + + std::cout << ((settings->colorless) ? "" : "\033[93m") << "Serienunterschied: " << ( ((countAf - countBef) > 0) ? "+" : "") << countAf - countBef << " Serien." << "\033[0m" << std::endl; + + //Speicher Dateim des Updates... + ofs.open(settings->lastUpdateDateFilePath, std::ios::trunc); + if(!ofs.is_open()) { + perror("Konnte UpdateDate-Datei nicht öffnen"); + return 113; + } else { + //Schreibe Liste in das TextFile + ofs << pageManager.getDate() << std::endl; + ofs.close(); + } + + + return 0; +} + +int ProgramManager::listDir(std::string &list,std::string path, int maxDepth, bool debugMode) +{ + //Wenn Pfad zu einem TextFile geht + if(fileExists(path)) { + if(debugMode) + std::cout << "INFO: Überprüfe Textdatei auf bereits gedownloadete Folgen (-C): '" << path << "'." << std::endl; + + std::ifstream ifs(path); + if(!ifs.is_open()) { + perror(" => Error: Konnte Textdatei nicht öffnen."); + return -1; + } + list = std::string((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + + if(debugMode) + std::cout << "Inhald des TextFiles (-C):\n" << list << std::endl << std::endl; + + return 0; + + } // Sonst normal Ordner listen + else if(maxDepth <= 0) { + if(debugMode) + std::cout << "INFO: Brich Vorgang für '" << path << "' ab, da max. Anzahl an zu durchsuchende Ordner erreicht wurde." << std::endl; + return 0; + } + else if(nothingExists(path)) { + std::cout << " => Warnug: Datei oder Verzeichnis existiert nicht: '" << path << "'" << std::endl; + return 0; + } + + //verkleiner varibable um 1, um zu verhindern, das endlose schleife entsteht + maxDepth--; + + if(path[path.length()-1] != '/') { + if(path[path.length()-1] != '\\') { // Wenn kein \ oder / am ende ist + if(path.find("/") == std::string::npos) { // wenn im namen ein / ist füge am ende / hinzu + if(path.find("\\") == std::string::npos) { // wenn im name ein \ ist add \ to en or error + std::cout << " => Error: Pfad zu dem Ordner enthält kein Pfadsymbol." << std::endl; + return -2; + } else { + path.push_back('\\'); + } + } else { + path.push_back('/'); + } + } + } + + DIR* dirp = opendir(path.c_str()); + if(!dirp) { + perror(std::string(" => Error: Konnte Verzeichnis nicht öffnen: " + path).c_str()); + return -1; + } + if(debugMode) + std::cout << "-> Durchsuche Ordner '" << path << "'..." << std::endl; + + struct dirent * dp; + while ((dp = readdir(dirp)) != nullptr) { + if(strcmp( dp->d_name, "." ) == 0 || strcmp ( dp->d_name, ".." ) == 0) + continue; + + else if(dirExists((path + dp->d_name + ((path.find("/") == std::string::npos) ? "\\" : "/") ))) { //if(dp->d_type == DT_DIR) { + listDir(list, (path + dp->d_name + ((path.find("/") == std::string::npos) ? "\\" : "/") ), maxDepth, debugMode); + } else { + list.append( std::string(dp->d_name) + "\n" ); + if(debugMode) + std::cout << " > " << dp->d_name << std::endl; + } + } + closedir(dirp); + return 0; +} + +int ProgramManager::convertLink(std::string redirectLink, AccountManager * accountManager, + Settings * settings, int Staffel, int Folge, std::string allLinks) +{ + std::string folgenID = std::string((Staffel == -1 || Folge == -1 ) ? "" : "S" + std::string( (Staffel < 10) ? "0" : "" ) + std::to_string(Staffel) + + "E" + std::string( (Folge < 10) ? "0" : "" ) + std::to_string( Folge ) ); + std::string green = ((settings->colorless) ? "" : "\033[32m"), + red = ((settings->colorless) ? "" : "\033[31m"), + orange =((settings->colorless) ? "" : "\033[33m"); + + if(redirectLink == "" && settings->modus == Modus::DEFAULT_MODUS) { + if(allLinks == "") { + std::cout << " => " << red << "KEINEN Hoster für die Folge " << replace(folgenID, "E", " E") << " gefunden." << ((settings->colorless) ? "" : "\033[0m") << std::endl; + if(pageManager.writeToFile(settings->outputFilePaths, std::string("KEINEN Hoster für die Folge ") + replace(folgenID, "E", " E") + std::string(" gefunden.")) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 130; + } + } else { + std::cout << " => " << orange << "Keinen PASSENDEN Hoster für die Folge " << replace(folgenID, "E", " E") << " gefunden." << ((settings->colorless) ? "" : "\033[0m") << std::endl + << "Alle Links:" << std::endl + << replace( replace( replace( allLinks, "data-lang-key=\"1\"", "language=\"GerDub\"" ), + "data-lang-key=\"2\"", "language=\"Eng\"" ), "data-lang-key=\"3\"", "language=\"GerSub\"") << std::endl; + if(pageManager.writeToFile(settings->outputFilePaths, std::string("Keinen PASSENDEN Hoster für die Folge ") + replace(folgenID, "E", " E") + std::string(" gefunden.")) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 138; + } + } + //Remove this return ?? + return 0; + } + + for (int i = 1; i <= 3; ++i) { + std::string newUrl = pageManager.getUrlAfterRedirect("https://serienstream.sx" + redirectLink); + //wenn function fehl schlug beende das Programm + if (newUrl == "-1") { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": getUrlAfterRedirect f() failed." << std::endl; + return 102; + + // wenn nach der Umwandlung immern och ein redirect vorhanden ist, also wenn z.B.: account gewechselt werden muss + } else if(newUrl.find("/serienstream.sx/redirect/") != std::string::npos ) { + if(settings->debugMode) + std::cout << "Warnung: Redirect Link nach umwandlung (Capcha?) --> Neuer Account" << std::endl; + if(pageManager.login(accountManager->getNextAccount()) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": login f() failed." << std::endl; + return -1; + } + continue; + + //wenn nach der Umwandlung https://serienstream.sx/ vorhanden ist, die ist wenn der Link Ungültig war: + } else if (newUrl == "https://serienstream.sx/") { + std::cout << " => " << red << replace(folgenID, "E", " E") << ( (folgenID == "") ? "" : ": " ) << "Ungültige Url: 'https://serienstream.sx" << redirectLink << "'" + << ((settings->colorless) ? "" : "\033[0m") << std::endl; + if(settings->outputFilePaths.size() != 0) + if(pageManager.writeToFile(settings->outputFilePaths, replace(folgenID, "E", " E") + ( (folgenID == "") ? "" : ": " ) + "Ungültige Url: https://serienstream.sx" + redirectLink) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 108; + } + return 0; + //sonst war die umwandlung erfolgreich + } else { + if( (newUrl = pageManager.getLinkAfterHosterBasedOperation(newUrl)) == "") { + if(settings->debugMode) + std::cout << " => Error in getLinkAfterHosterBasedOperation() -> exit convertLink()" << std::endl; + return 118; + } + + std::cout << " => " << folgenID << ( (folgenID == "") ? "" : ": " ) << green << newUrl << ((settings->colorless) ? "" : "\033[0m") << std::endl; + if(settings->outputFilePaths.size() != 0) + if(pageManager.writeToFile(settings->outputFilePaths,folgenID + ( (folgenID == "") ? "" : ": " ) + newUrl) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 108; + } + return 0; + } + } + + //nach 3temn Versuch gib error aus: + std::cout << " => " << replace(folgenID, "E", " E") << ( (folgenID == "") ? "" : ": " ) << red << "https://serienstream.sx" << redirectLink << ((settings->colorless) ? "" : "\033[0m") << std::endl; + if(settings->outputFilePaths.size() != 0) { + if(pageManager.writeToFile(settings->outputFilePaths, replace(folgenID, "E", " E") + ( (folgenID == "") ? "" : ": " ) + redirectLink) != 0) { + if(settings->debugMode) + std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; + return 114; + } + } + return 0; +} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/programManager.cpp b/src/programManager.cpp index b49bf33..a9fcb07 100644 --- a/src/programManager.cpp +++ b/src/programManager.cpp @@ -548,7 +548,7 @@ int ProgramManager::defaultModus(Settings *settings) return 50; } std::string allLinks = pageManager.getLinks(tmp_reply.html); - if(settings->genaueHoster == "*," && settings->debugMode) { + if(settings->genaueHoster == "*," && settings->colorless) { if(settings->debugMode) std::cout << allLinks << std::endl; std::stringstream strstrem(allLinks); @@ -624,7 +624,7 @@ int ProgramManager::directLinkModus(Settings *settings) std::cout << " => Error: Invalid Redirect Link: '" << line << "'" << std::endl; continue; - } else if(convertLink(line.erase(0, ((line.find("serienstream.sx") == std::string::npos) ? 0 : line.find("serienstream.sx") + 15 )), &accountManager, settings) != 0) { + } else if(convertLink(line.erase(0, line.find("/redirect/") ), &accountManager, settings) != 0) { if(settings->debugMode) std::cerr << ">>> Debug In " << __FUNCTION__ << ": convert Link failed." << std::endl; return 78;