#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.setProxy(settings->proxy_ip, settings->proxy_port); pageManager.setDebugMode(settings->debugMode); 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; } settings->modus = UPDATE_MODUS; 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); default: 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); if(myThreadData->settings->debugMode) std::cout << " > Thread " << myThreadData->id << allLinks << std::endl << ( (Link == "") ? "" : " -> Link: 'https://s.to") << 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"); if(Link == "") { //Wenn gar keine Links vorhanden sind: if(allLinks == "") { myThreadData->returnValue = " => " + red + "KEINEN Hoster für die Folge " + folgenID + " gefunden." + "\033[0m"; if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePath, std::string("KEINEN Hoster für die Folge ") + folgenID + 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 " + folgenID + " gefunden." + "\033[0m" + "\n" + "Alle Links:" + "\n" + myThreadData->pageManager->replace( myThreadData->pageManager->replace( myThreadData->pageManager->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->outputFilePath, std::string("Keinen PASSENDEN Hoster für die Folge ") + folgenID + 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://s.to" + 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("/s.to/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 { myThreadData->returnValue = " => " + folgenID + ( (folgenID == "") ? "" : ": " ) + green + newUrl + "\033[0m"; if(myThreadData->settings->outputFilePath != "") { if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePath,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); } } myThreadData->returnValue = " => " + folgenID + ( (folgenID == "") ? "" : ": " ) + red + "https://s.to" + Link + "\033[0m"; if(myThreadData->settings->outputFilePath != "") if(myThreadData->pageManager->writeToFile(myThreadData->settings->outputFilePath, folgenID + ( (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, line; //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 || finds.find("|") == std::string::npos ) { // || if(settings->debugMode) std::cerr << ">>> Debug In " << __FUNCTION__ << ": searchModus's returnValue contains no / or | => error " << std::endl; return 45; // 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::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.erase(0, line.find_last_of("|") + 1) << 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("/") + 1, line.find("|", line.find("/")) - line.find("/") -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 { //Speicher die Zeile für Namenausgabe: line = finds; //Überschreibe eine Zeile mit nur dem url Namen if ( (finds = finds.substr( finds.find("/") + 1, finds.find("|", finds.find("/")) - finds.find("/") -1) ) == "" ) { 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; } //Frag den User ob das die Richtige Serie ist: std::cout << " -> Ist das deine gewünschte Serie: '" << line.erase(0, line.find_last_of("|") + 1) << "'" << std::endl << "Drücke nur [Enter] um fortzufahren: " << std::flush; 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; } } //Überprüfe ob es die serie gibt wenn ja speicher ihn in newname und beende Function if ( (newName = pageManager.checkName(finds)) == "-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) { if(settings->updateWarningDays == 0) { 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) { 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." << "\033[0m" << std::endl;; } 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 << " => Error: 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 27; } } //Überprüfe ob ein Muster existiert: if(settings->default_checkPath != "" && settings->default_Searchmuster == "") { std::cout << " => Error: [-m]: Kein Muster angegeben." << std::endl; return 31; } //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 ) != 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(); if(settings->debugMode && settings->default_checkPath != "") //Wenn Debug Mode, gib die Liste aus std::cout << " > [-C] Files:\n" << dirFiles << std::endl; //Führe Function aus, die überprüft ob die serie existiert std::string nameInUrl =pageManager.checkName(settings->name); if(nameInUrl == "-1") { //Wenn nicht, dann fühe noch eine Suche nach ähnlichen durch && Wenn nur 1ne dacnn frag ob es diese ist. if( 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 202; } } /* Wenn multihtreading seaktiviert ist, normal login sonst bereite threads vor if(settings->maxThreads == 0) { // melde bei s.to 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->outputFilePath != "" && !fileExists( settings->default_checkPath )) if(pageManager.writeToFile(settings->outputFilePath, "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") { if(settings->debugMode) std::cerr << ">>> Debug In " << __FUNCTION__ << ": getServerRequest failed, when download startpage." << 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(pageManager.replace( pageManager.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); if(settings->debugMode) std::cout << allLinks << std::endl << ( (Link == "") ? "" : " -> Link: 'https://s.to") << 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 << " => Error: 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 76; } std::istringstream iStrStream( pageManager.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("s.to") == std::string::npos) ? 0 : line.find("s.to") + 4 )), &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->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 << " => Error: 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 27; } 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("|", line.find("/")) + 1, line.length() - line.find("|", line.find("/")) -1 ) << "\t[" << line.substr(line.find("/") + 1, line.find("|", line.find("/")) - line.find("/") - 1) << "]" << ( (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 << " => Error: 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 27; } //Führe Function aus, die überprüft ob die serie existiert std::string nameInUrl = pageManager.checkName(settings->name); if(nameInUrl == "-1") { //Wenn nicht, dann fühe noch eine Suche nach ähnlichen durch. if( sucheNach_1_Serien(settings, pageManager, nameInUrl) != 0) { if(settings->debugMode) std::cerr << ">>> Debug In " << __FUNCTION__ << ": sucheNach_1_Serien function failed." << std::endl; return 28; } } //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; } //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; } std::cout << "Die Staffel " << staffel << " hat " << pageManager.counterContains(tmpReply.html, "/episode-%i") << " Folge(n)." << std::endl; 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 = pageManager.replace(html, "\n", ""); html = pageManager.replace(html, "", "\n"); std::stringstream folgenListe(html); std::string line; while (std::getline(folgenListe, line).good()) { std::string titel; 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 + 3); if( (pos = line.find(" ")) == std::string::npos) { std::cout << " => Error: Konnte Position von ' ' nicht finden." << std::endl; return 44; } std::cout << " Staffel " << staffel << " " << line.substr(0, pos) << ":" <")) == 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 << " > Titel1: " << titel << std::endl; 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 << " > Titel2: " << titel << std::endl; } } //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 = pageManager.replace( pageManager.replace( tmp_reply.html.substr(pos + 23, pos2 - pos - 23), "\n", "" ), "
", "" ); //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); std::cout << "Produktion von " << startStopDates[0] << " bis " << startStopDates[1] << std::endl << "FSK: " << fsk << std::endl << "Cover Bild: " << coverLink << std::endl << "Genre(s): " << std::flush; for( const auto &e : genres) std::cout << e << " "; std::cout << std::endl << "\nBeschreibung: " << description << std::endl; 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://s.to/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; } #include int ProgramManager::updateModus(Settings *settings) { std::cout << "Check newst Version..." << std::endl; std::string html; if( (html = pageManager.getServerRequest(settings->VersionFileUrl).html) == "-1") { if(settings->debugMode) std::cerr << "Download newst Version file failed" << std::endl; return 1; } else { html = pageManager.replace(html, "\r", ""); } // Get newst Version std::stringstream strstream(html+ "\n"); std::string neusteVersion, dieseVersion; std::getline(strstream, neusteVersion); if( !isNumber( (neusteVersion = pageManager.replace(neusteVersion, ".", "")) ) ) { std::cout << " => Error: Gedownloadete neuste Version ist ungültig: '" << neusteVersion << "'" << std::endl; return 2; } else { dieseVersion = pageManager.replace(settings->version, ".", ""); } std::cout << "Neueste Version: " << neusteVersion << " diese Version " << dieseVersion << std::endl; if(neusteVersion <= dieseVersion) { std::cout << " => INFO: Du benützt bereits die neuste Release-Version." << std::endl; return 0; } std::cout << "Lade Dateien herunter..." << std::endl; std::string downloadUrl; std::getline(strstream, downloadUrl); if(downloadUrl.find("/download") == std::string::npos) { std::cout << " => Error: Gedownloadete Datei hat ungültigen DownloadLink: '" << downloadUrl << "'" << std::endl; return 3; } std::string downloadedFilePath = settings->cacheDir + "NeusteVersion" + ((settings->pathSymbol == '\\') ? ".exe" : ""); if( pageManager.downLoadToFile(downloadedFilePath, downloadUrl) != 0) { if(settings->debugMode) std::cerr << "Download new Version failed" << std::endl; return 3; } std::cout << "Mache das Programm ausführbar..." << std::endl; #ifdef __linux__ chmod(downloadedFilePath.c_str(), S_IRWXU); #endif std::cout << "Überprüfe funktionalität der neuen Version..." << std::endl; if( system((downloadedFilePath + " --version" ).c_str()) != 0) { perror("Ausführen der neues Version fehlgeschlagen"); return 4; } std::string exePath; #ifdef __linux__ char result[PATH_MAX + 1]; if(readlink("/proc/self/exe", result, PATH_MAX) == -1) { perror("Readlink failed"); return 5; } exePath = result; #endif #ifdef _WIN32 wchar_t buffer[MAX_PATH + 1]; GetModuleFileName( nullptr, buffer, MAX_PATH ); std::wstring wstr(buffer); exePath = std::string(wstr.begin(), wstr.end()); #endif std::cout << "Ersetzte jetzige Version mit neuer Version des Programms..." << std::endl; if(rename(downloadedFilePath.c_str(), exePath.c_str()) != 0) { perror("Mv failed"); return 6; } else { std::cout << "Erfolgreich verschoben: '" << downloadedFilePath << "' -> '" << exePath << "'" << std::endl; } std::cout << "Update Erfolgreich ausgeführt." << std::endl; return 0; } int ProgramManager::searchModus_update(Settings *settings) { Reply reply = pageManager.getServerRequest("https://s.to/serien"); 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 = pageManager.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 = pageManager.replace(serienListe, "
  • 2012 - Das Jahr Null\n... serienListe = pageManager.replace(serienListe, "\" href=\"", "|"); //...\n|/serie/stream/2012-das-jahr-null" title="2012 - Das Jahr Null Stream anschauen">2012 - Das Jahr Null\n... serienListe = pageManager.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 = pageManager.replace(line, "\">", "|"); //...\n|/serie/stream/2012-das-jahr-null|2012 - Das Jahr Null\n... line = pageManager.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(); //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) << "'" << "\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) << "'" << "\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) { //Wenn Pfad zu einem TextFile geht if(fileExists(path)) { 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()); return 0; } // Sonst normal Ordner listen else if(maxDepth <= 0) 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] != '/') path.push_back('/'); DIR* dirp = opendir(path.c_str()); if(!dirp) { perror(std::string(" => Error: Konnte Verzeichnis nicht öffnen: " + path).c_str()); return -1; } 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 + "/"))) { //if(dp->d_type == DT_DIR) { listDir(list, (path + dp->d_name + "/"), maxDepth); } else list.append( std::string(dp->d_name) + "\n" ); } 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 " << folgenID << " gefunden." << "\033[0m" << std::endl; if(pageManager.writeToFile(settings->outputFilePath, std::string("KEINEN Hoster für die Folge ") + folgenID + 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 " << folgenID << " gefunden." << "\033[0m" << std::endl << "Alle Links:" << std::endl << pageManager.replace( pageManager.replace( pageManager.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->outputFilePath, std::string("Keinen PASSENDEN Hoster für die Folge ") + folgenID + 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://s.to" + redirectLink); if (newUrl == "-1") { if(settings->debugMode) std::cerr << ">>> Debug In " << __FUNCTION__ << ": getUrlAfterRedirect f() failed." << std::endl; return 102; } else if(newUrl.find("/s.to/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; } else { std::cout << " => " << folgenID << ( (folgenID == "") ? "" : ": " ) << green << newUrl << "\033[0m" << std::endl; if(settings->outputFilePath != "") if(pageManager.writeToFile(settings->outputFilePath,folgenID + ( (folgenID == "") ? "" : ": " ) + newUrl) != 0) { if(settings->debugMode) std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; return 108; } return 0; } } std::cout << " => " << folgenID << ( (folgenID == "") ? "" : ": " ) << red << "https://s.to" << redirectLink << "\033[0m" << std::endl; if(settings->outputFilePath != "") { if(pageManager.writeToFile(settings->outputFilePath, folgenID + ( (folgenID == "") ? "" : ": " ) + redirectLink) != 0) { if(settings->debugMode) std::cerr << ">>> Debug In " << __FUNCTION__ << ": writeToFile f() failed." << std::endl; return 114; } } return 0; }