From 5bc61cf4b4096722760d52fa1de8bb6c6daa7829 Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 6 Jul 2019 20:47:29 +0200 Subject: [PATCH] default mode works + no qtwebview --- S_New4.pro | 35 ++++++ accountManager.cpp | 52 ++++++++ accountManager.h | 28 +++++ main.cpp | 13 ++ pageManager.cpp | 288 +++++++++++++++++++++++++++++++++++++++++++ pageManager.h | 42 +++++++ parameterManager.cpp | 15 +++ parameterManager.h | 25 ++++ programManager.cpp | 132 ++++++++++++++++++++ programManager.h | 26 ++++ 10 files changed, 656 insertions(+) create mode 100644 S_New4.pro create mode 100644 accountManager.cpp create mode 100644 accountManager.h create mode 100644 main.cpp create mode 100644 pageManager.cpp create mode 100644 pageManager.h create mode 100644 parameterManager.cpp create mode 100644 parameterManager.h create mode 100644 programManager.cpp create mode 100644 programManager.h diff --git a/S_New4.pro b/S_New4.pro new file mode 100644 index 0000000..8551fef --- /dev/null +++ b/S_New4.pro @@ -0,0 +1,35 @@ +QT -= gui +LIBS += -lcurl + + +CONFIG += c++11 console +CONFIG -= app_bundle + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + pageManager.cpp \ + parameterManager.cpp \ + programManager.cpp \ + accountManager.cpp + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +HEADERS += \ + pageManager.h \ + parameterManager.h \ + programManager.h \ + accountManager.h diff --git a/accountManager.cpp b/accountManager.cpp new file mode 100644 index 0000000..8d46574 --- /dev/null +++ b/accountManager.cpp @@ -0,0 +1,52 @@ +#include "accountManager.h" + +AccountManager::AccountManager(std::string pathToFile) + : lastReturnedAccount(0) +{ + std::ifstream ifs(pathToFile); + if(!ifs.is_open()) { + perror("Konnte Accounts Datei nicht öffnen"); + exit(12); + } + + std::string line; + while (std::getline(ifs, line)) { + Account account; + size_t Delimeter = line.find("/"); + + if(Delimeter == std::string::npos) { + account.Email = line; + account.Password = line; + } else { + account.Email = std::string(line).erase(Delimeter, line.length() - Delimeter); + account.Password = line.erase(0, Delimeter + 1); + } + if(account.Email == "" || account.Password == "") + continue; + else + accounts.push_back(account); + } + +} + +Account AccountManager::getNextAccount() +{ + lastReturnedAccount++; + if( lastReturnedAccount >= accounts.size() ) + lastReturnedAccount=0; + return accounts.at(lastReturnedAccount); +} + +bool AccountManager::isDirExist(const std::string& path) +{ + struct stat info; + if (stat(path.c_str(), &info) != 0) { + return false; + } + return (info.st_mode & S_IFDIR) != 0; +} + +bool AccountManager::createDir(std::string path, std::string atLinux) +{ + return system(std::string("mkdir " + atLinux + "'" + path +"'").c_str()); // -p if is linux +} diff --git a/accountManager.h b/accountManager.h new file mode 100644 index 0000000..64909f9 --- /dev/null +++ b/accountManager.h @@ -0,0 +1,28 @@ +#ifndef ACCOUNTMANAGER_H +#define ACCOUNTMANAGER_H + +#include +#include +#include +#include + +struct Account { + std::string Email, Password; +}; + + +class AccountManager +{ +public: + AccountManager(std::string pathToFile); + Account getNextAccount(); + + bool isDirExist(const std::string& path); + bool createDir(std::string path, std::string atLinux = "-p "); + +private: + std::vector accounts; + size_t lastReturnedAccount; +}; + +#endif // ACCOUNTMANAGER_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..c862079 --- /dev/null +++ b/main.cpp @@ -0,0 +1,13 @@ +#include "parameterManager.h" +#include "programManager.h" + + +#include "pageManager.h" + +int main(int argc, char *argv[]) +{ + ProgramManager mainProgram; + + Settings settings = manageParameter(argc, argv); + return mainProgram.start(settings); +} diff --git a/pageManager.cpp b/pageManager.cpp new file mode 100644 index 0000000..a9ad03c --- /dev/null +++ b/pageManager.cpp @@ -0,0 +1,288 @@ +#include "pageManager.h" + +PageManager::PageManager(std::string sock5Proxy, std::string cookieFilePath) + : sock5Proxy(sock5Proxy), cookieFilePath(cookieFilePath) +{ + +} + +PageManager::~PageManager() +{ + ///remove(cookieFilePath.c_str()); +} + +size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) +{ + //Function für CURL + static_cast(userp)->append(static_cast(contents),size * nmemb); + return size * nmemb; +} + +Reply PageManager::getServerRequest(std::string Url, bool useCookies, std::string data, bool generateCookieFile) +{ + CURL *curl; + CURLcode res; + std::string readBuffer; + char *url; + std::string returnUrl; + + std::cout << "Lade: '" << Url << "'..."; + std::cout.flush(); + + curl = curl_easy_init(); + if(!curl) { + perror("\33[2K\rError: Curl easy init failed"); + return Reply("-1"); + } + + //Settings + curl_easy_setopt(curl, CURLOPT_URL, Url.c_str()); //Url für Curl + curl_easy_setopt(curl, CURLOPT_PROXY, sock5Proxy.c_str() ); //Sock5Proxy für Curl + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); //follows redirection + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); // Funktion zum Speichern des outputs in einem string + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); //Legt die Variable readbuffer fest + if(useCookies) + curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFilePath.c_str()); + if(data != "") + curl_easy_setopt (curl, CURLOPT_POSTFIELDS, data.c_str()); + if(generateCookieFile) + curl_easy_setopt (curl, CURLOPT_COOKIEJAR, cookieFilePath.c_str()); + + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); std::cout << "\33[2K\r"; + + if(res != CURLE_OK) { + perror((std::string("Error: curl_easy_perform() failed: ") + curl_easy_strerror(res)).c_str()); + return Reply("-1"); + } + + //Get Url + res = curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url); + if( res != CURLE_OK || !url ) { + perror((std::string("Error: curl_easy_getinfo failed: ") + curl_easy_strerror(res)).c_str()); + return Reply("-1"); + } else + returnUrl=url; + + + /* always cleanup */ /* Mach den Griff zu, schreib die Kekse! */ + curl_easy_cleanup(curl); + + return Reply(readBuffer, returnUrl); +} + +int PageManager::login(Account account) +{ + std::string html = getServerRequest("https://s.to/login", false, std::string("email=" + account.Email + "&password=" + account.Password), true ).html; + if(html == "" ) + return 0; + else if (html.find("Das Feld Email muss eine gültige E-Mail-Adresse enthalten.") != std::string::npos) + std::cout << "Error: Login failed: Das Feld Email muss eine gültige E-Mail-Adresse enthalten." << std::endl + << " Email: '" << account.Email << "' Passwort: '" << account.Password << "'" << std::endl; + else if (html.find("Das Passwort ist nicht korrekt") != std::string::npos) + std::cout << "Error: Login failed: Das Passwort ist nicht korrekt." << std::endl + << " Email: '" << account.Email << "' Passwort: '" << account.Password << "'" << std::endl; + else if (html.find("Ein Account mit dieser E-Mail Adresse wurde nicht gefunden.") != std::string::npos) + std::cout << "Error: Login failed: Ein Account mit dieser E-Mail Adresse wurde nicht gefunden." << std::endl + << " Email: '" << account.Email << "' Passwort: '" << account.Password << "'" << std::endl; + else + std::cout << "Error: Login failed: Keine Weiterleitung bei Login." << std::endl + << " Email: '" << account.Email << "' Passwort: '" << account.Password << "'" << std::endl; + return -1; +} + +std::string PageManager::getUrlAfterRedirect(std::string Url) +{ + return getServerRequest(Url, true).url; +} + +std::string PageManager::checkName(std::string Name) +{ + std::string name = replace(Name, " ", "-"); + std::cout << "Name: " << name << std::endl; + + std::string html = getServerRequest("https://s.to/serie/stream/" + name).html; + if(html.find("Die gewünschte Serie wurde nicht gefunden oder ist im Moment deaktiviert.") != std::string::npos) { + std::cout << "Die gewünschte Serie wurde nicht gefunden oder ist im Moment deaktiviert: " << Name << std::endl; + return "-1"; + } else if (html.find("404 - Seite nicht gefunden") != std::string::npos) { + std::cout << "Ungültiger Name: " << Name << std::endl; + return "-1"; + } else { + return name; + } +} + +std::string PageManager::getLinks(std::string HTML) +{ + size_t pos = HTML.find("
    "); + if(pos == std::string::npos) { + std::cout << "Konnte Position von \"" << "
      " << " nicht finden" <", "\n"); + HTML = replace(HTML, "", "\n"); + HTML = grep(HTML,"href=\"/redirect/"); + + std::istringstream iStrStream( HTML + "\n" ); + std::string line, ReturnValue; + size_t pos2; + + while (getline(iStrStream, line).good()) { + pos=line.find("data-lang-key="); + if(pos == std::string::npos) { + std::cout << "Error: Konnte Position von \"data-lang-key=\" nicht finden." << std::endl; + continue; + } + //entferne alles bis pos + line.erase(0,pos); + + pos=line.find("data-link-id="); + if(pos == std::string::npos) { + std::cout << "Error: Konnte Position von \"data-link-id=\" nicht finden." << std::endl; + continue; + } + pos2=line.find("href=\""); + if(pos2 == std::string::npos) { + std::cout << "Error: Konnte Position von 'href=\"' nicht finden." << std::endl; + continue; + } + //Entferne alles von pos bis pos2 + line.erase(pos,pos2-pos); + + pos=line.find("target="); + if(pos == std::string::npos) { + std::cout << "Error: Konnte Position von \"target=\" nicht finden." << std::endl; + continue; + } + pos2=line.find("title="); + if(pos2 == std::string::npos) { + std::cout << "Error: Konnte Position von \"title=\" nicht finden." << std::endl; + continue; + } + //entferne alles von pos bis pos2 + line.erase(pos,pos2-pos); + + pos=line.find("><"); + if(pos == std::string::npos) { + std::cout << "Error: Konnte Position von \"><\" nicht finden." << std::endl; + continue; + } + //entferne alles von pos bis zum ende + line.erase(pos,line.length()-pos); + + line = replace(line, "title=\"Hoster ", "hoster=\""); + + ReturnValue+=line+"\n"; + } + + if(ReturnValue.size() > 0) + return ReturnValue.erase( ReturnValue.size()-1 , 1); + else + return ""; + +} + +std::string PageManager::replace(std::string str, std::string substr1, std::string substr2) +{ + size_t index = 0; + for (index = str.find(substr1, index); index != std::string::npos; index = str.find(substr1, index + strlen(substr1.c_str())) ) + str.replace(index, strlen(substr1.c_str()), substr2); + return str; +} + +int PageManager::counterContains(std::string text, std::string substring_with_prozent_i_for_number, int starte_mit_dieser_Zahl) +{ + int i = starte_mit_dieser_Zahl; + for (; text.find( replace(substring_with_prozent_i_for_number, "%i", std::to_string(i)) ) != std::string::npos; i++); + return i-1; +} + +std::string PageManager::grep(std::string text, std::string substring) +{ + std::istringstream iStrStream(text + "\n"); + std::string line, returnValue; + while( std::getline(iStrStream, line).good() ) //auto start_of_line_position = begin( line ); //auto end_of_line_position = end( line ); + if(line.find(substring) != std::string::npos) + returnValue += line + "\n"; + if(returnValue.length() >= 1) + return returnValue.erase(returnValue.length()-1,1); + else + return ""; + +} + +std::string PageManager::chooseHosterLink(std::string HosterList, std::string Hoster_with_Highst_Priority_at_First, std::string languages_with_highst_priority_at_first) +{ + std::istringstream SListLang ( replace( languages_with_highst_priority_at_first, ",", "\n") + "\n" ); + std::istringstream SListHoster( replace( Hoster_with_Highst_Priority_at_First, ",", "\n") + "\n" ); + + int LangId = 0; + size_t pos = 0; + std::string LanguageSortedHoster, Line, langId, hoster; + //QTextStream stream(); + + //Für jede Sprache: + while (getline(SListLang, langId).good()) { + + if ( langId == "GerDub" ) + LangId=1; + else if ( langId == "Eng" ) + LangId=2; + else if ( langId == "GerSub" ) + LangId=3; + else { + std::cout << "Unbekannte Sprache: " << langId << std::endl; + continue; + } + + //Liste aller Links mit der Sprache des durchgangs der schleife + LanguageSortedHoster = grep(HosterList, ( "data-lang-key=\"" + std::to_string(LangId) + "\"" ) ); + //std::cout << "Alle Folgen mi der Sprache " << langId << ":\n'" << LanguageSortedHoster << "'" << std::endl; + + //Für jeden Angegebenen Hoster: + while (getline(SListHoster, hoster).good()) { + //Wenn es den hoster bei dieser prache nicht gibt, wähle nächsten + if(LanguageSortedHoster.find("hoster=\"" + hoster + "\"") == std::string::npos) { + //std::cout << "Hoster " << hoster << " gibt es bei der sprache" << langId << " nicht " << std::endl; + continue; + } + + Line = grep(LanguageSortedHoster, ("hoster=\"" + hoster + "\"" ) ); + pos = Line.find("href=\""); + if(pos == std::string::npos) { + std::cout << "Error: Konnte 'href=\"' nicht finden." << std::endl; + continue; + } + + Line.erase(0, pos + static_cast(strlen("href=\""))); + + pos = Line.find("\""); + if(pos == std::string::npos) { + std::cout << "Error: Konnte '\"' nicht finden." << std::endl; + continue; + } + + return Line.erase(pos, Line.length()-pos); + + + } + + } + return ""; +} + + + + diff --git a/pageManager.h b/pageManager.h new file mode 100644 index 0000000..9661bef --- /dev/null +++ b/pageManager.h @@ -0,0 +1,42 @@ +#ifndef MANAGEPAGE_H +#define MANAGEPAGE_H + +#include +#include +#include +#include + +#include "accountManager.h" + +struct Reply { + Reply() {} + Reply(std::string value_both) : html(value_both), url(value_both) {} + Reply(std::string html, std::string url) : html(html), url(url) {} + + std::string html, url; +}; + + +class PageManager +{ +public: + PageManager(std::string sock5Proxy = "socks5://127.0.0.1:9150", std::string cookieFilePath = "/tmp/S_New4_cookies"); + ~PageManager(); + + Reply getServerRequest(std::string Url, bool useCookies = false, std::string data = "", bool generateCookieFile = false); + int login(Account account); + std::string getUrlAfterRedirect(std::string Url); + std::string checkName(std::string Name); + std::string getLinks(std::string HTML); + std::string chooseHosterLink(std::string HosterList, std::string Hoster_with_Highst_Priority_at_First, std::string languages_with_highst_priority_at_first); + + std::string replace(std::string str, std::string substr1, std::string substr2); + int counterContains(std::string text, std::string substring_with_prozent_i_for_number, int starte_mit_dieser_Zahl = 1); + std::string grep(std::string text, std::string substring); + + const std::string UrlPraefix = "https://s.to/serie/stream/"; +private: + std::string sock5Proxy, cookieFilePath; +}; + +#endif // MANAGEPAGE_H diff --git a/parameterManager.cpp b/parameterManager.cpp new file mode 100644 index 0000000..346fd7e --- /dev/null +++ b/parameterManager.cpp @@ -0,0 +1,15 @@ +#include "parameterManager.h" + +Settings manageParameter(int argc, char **argv) +{ + Settings settings; + if(argc < 2) { + std::cout << " => Kein Name angegeben" << std::endl; + settings.modus = Modus::EXIT; + return settings; + } + settings.name = argv[1]; + + + return settings; +} diff --git a/parameterManager.h b/parameterManager.h new file mode 100644 index 0000000..56a7081 --- /dev/null +++ b/parameterManager.h @@ -0,0 +1,25 @@ +#ifndef PARAMETERMANAGER_H +#define PARAMETERMANAGER_H + +#include + +enum Modus { + EXIT = -1, + DEFAULT_MODUS = 0, + DIRECT_LINK_MODUS = 1 +}; + + +struct Settings { + Settings() {} + Settings(std::string name) : name(name) {} + + std::string name; + Modus modus = Modus::DEFAULT_MODUS; + std::string accountFilePath = "/home/markus/a"; + bool color; +}; + +Settings manageParameter(int argc, char ** argv); + +#endif // PARAMETERMANAGER_H diff --git a/programManager.cpp b/programManager.cpp new file mode 100644 index 0000000..c555e6d --- /dev/null +++ b/programManager.cpp @@ -0,0 +1,132 @@ +#include "programManager.h" + +ProgramManager::ProgramManager() +{ + +} + +int ProgramManager::start(Settings setting) +{ + switch (setting.modus) { + case Modus::DEFAULT_MODUS: + return defaultModus(&setting); + case Modus::DIRECT_LINK_MODUS: + return directLinkModus(&setting); + default: + return -1; + } +} + +int ProgramManager::defaultModus(Settings *settings) +{ + std::cout << "Default Modus" << std::endl; + + AccountManager accountManager(settings->accountFilePath); + std::string nameInUrl =pageManager.checkName(settings->name); + if(nameInUrl == "-1") + return 25; + else if (pageManager.login(accountManager.getNextAccount()) != 0) + return 29; + + //Find out number of all seasons + Reply tmp_reply = pageManager.getServerRequest(pageManager.UrlPraefix + nameInUrl); + int maxStaffel = pageManager.counterContains(tmp_reply.html, "/staffel-%i"); + //For every season + for (int staffel = 1; staffel <= maxStaffel; ++staffel) { + + //Find out number of all episodes + tmp_reply = pageManager.getServerRequest(pageManager.UrlPraefix + nameInUrl + "/staffel-" + std::to_string(staffel)); + int maxFolge = pageManager.counterContains(tmp_reply.html, "/episode-%i"); + //for every episode + for (int folge = 1; folge <= maxFolge; ++folge) { + + tmp_reply =pageManager.getServerRequest(pageManager.UrlPraefix + nameInUrl + "/staffel-" + std::to_string(staffel) + "/episode-" + std::to_string(folge)); + std::string allLinks = pageManager.getLinks(tmp_reply.html); + std::string Link = pageManager.chooseHosterLink(allLinks, "GoUnlimited", "GerDub,Eng,GerSub"); + + std::cout << " -> Link: " << Link << std::endl; + if(convertLink(Link, &accountManager, settings, staffel, folge, allLinks) != 0) + return 51; + + } std::cout << "season: " << staffel << " hat " << maxFolge << " folgen" << std::endl; + + } + + return 0; +} + +int ProgramManager::directLinkModus(Settings *settings) +{ + std::cout << "Direct Link Modus" << std::endl; + + AccountManager accountManager(settings->accountFilePath); + std::istringstream iStrStream( pageManager.replace( settings->name, ",", "\n" ) + "\n" ); + std::string line; + + while (getline(iStrStream, line).good()) { + if(line.find("://s.to/redirect/") == std::string::npos) { + std::cout << "Invalid Redirect Link: '" << line << "'" << std::endl; + continue; + } + if(convertLink(line, &accountManager, settings) != 0) + return 78; + } + + 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 )); + if(redirectLink == "") { + std::cout << " => " << ( (allLinks == "" ) ? "KEINEN" : "Keinen PASSENDEN" ) << " Hoster für die Folge " << folgenID << " gefunden." << std::endl; + return 0; + } + + for (int i = 1; i <= 4; ++i) { + std::string newUrl = pageManager.getUrlAfterRedirect("https://s.to" + redirectLink); + if (newUrl == "-1") { + return 102; + } else if(newUrl.find("/s.to/redirect/") != std::string::npos ) { + if(pageManager.login(accountManager->getNextAccount()) != 0) + return -1; + continue; + } + else { + std::cout << " => " << folgenID << ": " << ((settings->color) ? "\033[33m" : "") << newUrl << "\033[0m" << std::endl; + return 0; + } + } + std::cout << " => " << ": " << ((settings->color) ? "\033[32m" : "") << "https://s.to" << redirectLink << "\033[0m" << std::endl; + return 0; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/programManager.h b/programManager.h new file mode 100644 index 0000000..ba58d48 --- /dev/null +++ b/programManager.h @@ -0,0 +1,26 @@ +#ifndef MANAGEPROGRAM_H +#define MANAGEPROGRAM_H + +#include "parameterManager.h" +#include "pageManager.h" +#include "accountManager.h" + + +class ProgramManager +{ +public: + ProgramManager(); + int start(Settings setting); + +private: + int defaultModus(Settings * settings); + int directLinkModus(Settings * settings); + + PageManager pageManager; + + + int convertLink(std::string redirectLink, AccountManager *accountManager, Settings * settings, int Staffel = -1, int Folge = -1, std::string allLinks = "NOT_EMPTY"); + +}; + +#endif // MANAGEPROGRAM_H