S_New4/programManager.cpp

1482 lines
67 KiB
C++

#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<struct ThreadData*>(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;
//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 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::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<int>(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)
{
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<long long>(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 == "-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.
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<void*>(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<char>(ifs)), std::istreambuf_iterator<char>());
//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 << " => 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 == "-2")
return 145;
else 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;
}
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 = "\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;
}
std::cout << std::endl
<< green << "Die Staffel " << staffel << " hat " << pageManager.counterContains(tmpReply.html, "/episode-%i") << " Folge(n)." << white << std::endl
<< std::endl;
std::string html = tmpReply.html;
size_t pos = 0;
if( (pos = html.find("<tr ")) == std::string::npos) {
std::cout << " => Error: Konnte Position von '<tr ' nicht finden." << std::endl;
return 41;
} else
html.erase(0, pos);
if( (pos = html.find("</tbody>")) == std::string::npos) {
std::cout << " => Error: Konnte Position von '</tbody>' nicht finden." << std::endl;
return 42;
} else
html.erase(pos, std::string::npos);
html = pageManager.replace(html, "\n", "");
html = pageManager.replace(html, "</tr>", "\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(" </a>")) == std::string::npos) {
std::cout << " => Error: Konnte Position von ' </a>' 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 <<std::endl;
if( (pos = line.find("<strong>")) == std::string::npos) {
std::cout << " => Error: Konnte Position von '<strong>' nicht finden." << std::endl;
return 43;
} else
line.erase(0, pos + 8);
if( (pos = line.find("</strong>")) == std::string::npos) {
std::cout << " => Error: Konnte Position von '</strong>' nicht finden." << std::endl;
return 44;
}
titel = line.substr(0, pos);
if(titel != "")
std::cout << lila << " > Titel 1: " << Lightyellow << titel << white << std::endl;
if( (pos = line.find("<span>")) == std::string::npos) {
std::cout << " => Error: Konnte Position von '<span>' nicht finden." << std::endl;
return 43;
} else
line.erase(0, pos + 6);
if( (pos = line.find("</span>")) == std::string::npos) {
std::cout << " => Error: Konnte Position von '</span>' nicht finden." << std::endl;
return 44;
}
titel = line.substr(0, pos);
if(titel != "")
std::cout << lila << " > Titel 2: " << Darkyellow << titel << white << std::endl;
}
}
}
//Datum & FSK
std::string line = pageManager.grep(tmp_reply.html, "<small> (<span itemprop=\"startDate\"><a");
if(line == "") {
std::cout << " => Error: Konnte '<small> (<span itemprop=\"startDate\"><a' nicht finden." << std::endl;
return 83;
}
std::string startStopDates[2];
size_t pos = 0, pos2 = 0;
//Date
for (int i = 0; i < 2; ++i) {
if( (pos = line.find("href=")) == std::string::npos ) {
std::cout << " => 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("</a>")) == std::string::npos ) {
std::cout << " => Error: Konnte '</a>' 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", "" ), "<br />", "" );
//remove bug text:
description = pageManager.replace(description, "&amp;quot;", "\""); //
description = pageManager.replace(description, "&amp;", "&"); //
description = pageManager.replace(description, "&lt;", "<"); //
description = pageManager.replace(description, "&gt;", ">"); //
description = pageManager.replace(description, "<br />", " "); //
description = pageManager.replace(description, "&quot;", "\""); //
description = pageManager.replace(description, "&apos;", "'"); //
//Genres
std::vector<std::string> 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("</a>", pos)) == std::string::npos) {
std::cout << " => Error: Konnte '</a>' 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 << lila << "Produktion 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;
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("<div class=\"row\">")) == std::string::npos ) {
std::cout << " => Error: Konnte Position von '<div class=\"row\">'' nicht finden" <<std::endl;
return 2;
} else
html.erase(0, pos + 17);
if( (pos = html.find("<div class=\"cf\"></div>")) == std::string::npos ) {
std::cout << " => Error: Konnte Position von '<div class=\"cf\"></div>' nicht finden" <<std::endl;
return 2;
} else
html.erase(pos + 12);
html = pageManager.replace(html, "\n", "");
html = pageManager.replace(html, "class=\"row\"", "\n");
std::stringstream strstream(html + "\n");
html.clear();
std::string line;
while (std::getline(strstream, line).good()) {
size_t pos = line.find("<strong>");
size_t pos2 = line.find("</strong>");
if(pos == std::string::npos) {
std::cout << " => Error: Konnte Position von '<strong>' nicht finden" <<std::endl;
return 3;
} else if(pos2 == std::string::npos) {
std::cout << " => Error: Konnte Position von '</strong>' nicht finden" <<std::endl;
return 4;
}
std::string name = line.substr(pos + 8, pos2 - pos - 8);
if( (pos = line.find("blue2\">")) == std::string::npos) {
std::cout << " => Error: Konnte Position von 'blue2\">' nicht finden" <<std::endl;
return 5;
} else if( (pos2 = line.find("</span>", pos)) == std::string::npos) {
std::cout << " => Error: Konnte Position von '' nicht finden" <<std::endl;
return 6;
}
std::string id = pageManager.replace( line.substr(pos + 7, pos2 - pos - 7), " ", "");
if( (pos = line.find("Right\">")) == std::string::npos) {
std::cout << " => Error: Konnte Position von 'Right\">' nicht finden" <<std::endl;
return 5;
} else if( (pos2 = line.find("</span>", pos)) == std::string::npos) {
std::cout << " => Error: Konnte Position von '</span>' nicht finden" <<std::endl;
return 6;
}
std::string date = line.substr(pos + 7, pos2 - pos - 7);
std::cout << " > " << ((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)
{
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 = pageManager.replace(html, "\r", "");
}
// Get newst Version
std::string neusteVersion = html.substr(0, html.find("\n"));
html.erase(0, html.find("\n") + 1);
//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 << " > " << line << 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) {
perror(" => Error: Ausführen der neuen Version ist fehlgeschlagen");
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://s.to/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("</html>") == std::string::npos ) {
std::cout << " => Error: Konnte </html> in searchModus_update() nicht finden." << std::endl;
return 22;
}
std::string serienListe = pageManager.replace( pageManager.grep( reply.html, "data-alternative-title" ), "</li>", "\n" );
if(reply.html.find("\" href=\"") == std::string::npos ||
reply.html.find("<li><a data-alternative-title=\"") == std::string::npos ||
reply.html.find("/serie/stream/") == std::string::npos ||
reply.html.find("</a>") == std::string::npos) {
if(settings->debugMode)
std::cerr << ">>> Debug In " << __FUNCTION__
<< ": hatml doesnt contain:' \" href=\" or <li><a data-alternative-title=\" or /serie/stream/ or </a> ' after preparing." << std::endl;
return 51;
}
//...\n<li><a data-alternative-title="" href="/serie/stream/2012-das-jahr-null" title="2012 - Das Jahr Null Stream anschauen">2012 - Das Jahr Null</a>\n...
serienListe = pageManager.replace(serienListe, "<li><a data-alternative-title=\"", "");
//...\n" href="/serie/stream/2012-das-jahr-null" title="2012 - Das Jahr Null Stream anschauen">2012 - Das Jahr Null</a>\n...
serienListe = pageManager.replace(serienListe, "\" href=\"", "|");
//...\n|/serie/stream/2012-das-jahr-null" title="2012 - Das Jahr Null Stream anschauen">2012 - Das Jahr Null</a>\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</a>\n...
line = pageManager.replace(line, "\">", "|");
//...\n|/serie/stream/2012-das-jahr-null|2012 - Das Jahr Null</a>\n...
line = pageManager.replace(line, "</a>", "");
//...\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 = pageManager.replace(serienListe, "&amp;quot;", "\""); //
serienListe = pageManager.replace(serienListe, "&amp;", "&"); //
serienListe = pageManager.replace(serienListe, "&lt;", "<"); //
serienListe = pageManager.replace(serienListe, "&gt;", ">"); //
serienListe = pageManager.replace(serienListe, "<br />", " "); //
serienListe = pageManager.replace(serienListe, "&quot;", "\""); //
serienListe = pageManager.replace(serienListe, "&apos;", "'"); //
//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<char>(ifs)), std::istreambuf_iterator<char>());
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] != '/') {
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;
}
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);
} 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);
//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("/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;
//wenn nach der Umwandlung https://s.to/ vorhanden ist, die ist wenn der Link Ungültig war:
} else if (newUrl == "https://s.to/") {
std::cout << " => " << red << folgenID << ( (folgenID == "") ? "" : ": " ) << "Ungültige Url: 'https://s.to" << redirectLink << "'\033[0m" << std::endl;
if(settings->outputFilePath != "")
if(pageManager.writeToFile(settings->outputFilePath, folgenID + ( (folgenID == "") ? "" : ": " ) + "Ungültige Url: https://s.to" + 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 {
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;
}
}
//nach 3temn Versuch gib error aus:
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;
}