From ce204d0f8f5ec23147d74f37b8555b836adfddd1 Mon Sep 17 00:00:00 2001 From: Wirlaburla Date: Fri, 6 Oct 2023 03:11:55 -0500 Subject: [PATCH] stuff --- CMakeLists.txt | 3 ++ conf.examples/filth.list | 81 ++++++++++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 2 +- src/acfile.h | 34 ++++++++++++++--- src/client.h | 2 + src/drone.h | 12 ++++++ src/main.cpp | 72 ++++++++++++++++++++++++----------- src/urlname.cpp | 18 +++++++++ src/utils.h | 53 ++++++++++++++++++++++++++ 9 files changed, 250 insertions(+), 27 deletions(-) create mode 100644 conf.examples/filth.list create mode 100644 src/urlname.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c172c68..003b6e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,10 @@ cmake_minimum_required(VERSION 3.5) project(pengobot) +add_definitions(-DCURL_STATICLIB) SET(CMAKE_CXX_STANDARD 17) SET(CMAKE_CXX_STANDARD_REQUIRED True) SET(CMAKE_CXX_FLAGS "-O3") +find_package(CURL REQUIRED) +include_directories(${CURL_INCLUDE_DIR}) add_subdirectory(src) install(TARGETS pengobot RUNTIME DESTINATION bin) diff --git a/conf.examples/filth.list b/conf.examples/filth.list new file mode 100644 index 0000000..9c689dd --- /dev/null +++ b/conf.examples/filth.list @@ -0,0 +1,81 @@ +masturbater +masturbation +jerking +blowjob +asshole +cunt +b1tch +slut +pussy +nigga +fukk +lesbian +dildo +whore +dick +phuck +fuck +clit +cock +penis +bitch +fucking +pussyeaster +cuntfucker +eatmypussy +NIGGER +shit +fag +fuk +fuc +nigga +cocksucker +pussy +asshole +lezbo +cunt +clit +bitch +fucking +cumeater +dick +pussyeater +cuntfucker +eatmypussy +nigger +fuck +Fucking +Fucked +Fucker +Fuckface +Motherfucker +Cocksucker +Shit +Shithead +Shitter +Cunt +Bitch +Asshole +Prick +fuck +fucking +fucked +fucker +fuckface +motherfucker +cocksucker +shit +shithead +shitter +cunt +bitch +asshole +prick +d-i-c-k +sextape +kike +pornography +porno +porn +sex +xxx \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff85a2c..4313b8c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ add_executable(pengobot main.cpp ) -target_link_libraries(pengobot -static) +target_link_libraries(pengobot ${CURL_LIBRARIES} -static) diff --git a/src/acfile.h b/src/acfile.h index b496893..8d9c8a7 100644 --- a/src/acfile.h +++ b/src/acfile.h @@ -16,7 +16,7 @@ public: } ACFile(const char* path) { std::ifstream infile(path); - + printf("info: reading file %s\n", path); std::string line; while (std::getline(infile, line)) { if (line.length() == 0) continue; @@ -30,9 +30,6 @@ public: } std::map get() { - for (auto const& c : this->conf) { - printf("info: (%s),(%s)\n", c.first.c_str(), c.second.c_str()); - } return this->conf; } @@ -76,7 +73,7 @@ public: this->rng = std::mt19937(rd()); std::ifstream infile(path); - + printf("info: reading file %s\n", path); std::string line; std::string group; while (std::getline(infile, line)) { if (line.length() == 0) continue; @@ -113,5 +110,32 @@ private: std::mt19937 rng; }; +// Another List File +class ALFile { +public: + ALFile() {}; + ALFile(const ALFile &other) { + this->list = other.list; + } + ALFile(const char* path) { + std::ifstream infile(path); + printf("info: reading file %s\n", path); + std::string line; + while (std::getline(infile, line)) { + if (line.length() == 0) continue; + // Check if line is a group defining line. + if (line.rfind("#", 0) != 0) { + list.push_back(line); + } + } + } + + std::vector getLines() { + return list; + } +private: + std::vector list; +}; + #endif diff --git a/src/client.h b/src/client.h index fba27bc..49644ab 100644 --- a/src/client.h +++ b/src/client.h @@ -11,11 +11,13 @@ bool debug = false; std::random_device rd; std::mt19937 rng(rd()); +const std::string user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"; std::string confFile = "conf/bot.conf"; ACFile* mainConf; ACFile* worldlist; ACFile* replylist; AMFile* messages; +ALFile* filth; #define BUFFERSIZE 65535 diff --git a/src/drone.h b/src/drone.h index c24d6ca..1f2e205 100644 --- a/src/drone.h +++ b/src/drone.h @@ -1,5 +1,6 @@ #ifndef H_DRONE #define H_DRONE +#include "group.h" class Drone { public: @@ -10,6 +11,17 @@ public: Drone(char* &_name) : name{ _name } { }; bool operator != (Drone &d) { return strcmp(this->name, d.name) != 0; }; Drone operator = (Drone *d) { return *d; }; + void setGroup(Group* newGroup) { + activeGroup = newGroup; + } + Group* getCurrentGroup() { + return activeGroup; + } + bool inGroup() { + return activeGroup != nullptr; + } +private: + Group* activeGroup; }; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 17eb0de..6e7c8e9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,6 +21,9 @@ #include #include +#define CURL_STATICLIB +#include + #include "client.h" #include "verrors.h" #include "cmds.h" @@ -33,11 +36,11 @@ public: QueuedPacket() {}; QueuedPacket(const QueuedPacket &other) { this->sock = other.sock; - memcpy(this->buf, other.buf, 255); + memcpy(this->buf, other.buf, other.buf[0]); } QueuedPacket(int *sock, unsigned char str[]) { this->sock = *sock; - memcpy(this->buf, str, 255); + memcpy(this->buf, str, str[0]); }; int flush(int flags) { @@ -82,6 +85,7 @@ void loadConfig() { worldlist = new ACFile(mainConf->getValue("worldfile", "conf/worldlist.conf").c_str()); replylist = new ACFile(mainConf->getValue("replyfile", "conf/replies.conf").c_str()); messages = new AMFile(mainConf->getValue("messages", "conf/messages.list").c_str()); + filth = new ALFile(mainConf->getValue("filthlist", "conf/filth.list").c_str()); login_username = mainConf->getValue("username", ""); login_password = mainConf->getValue("password", ""); room = mainConf->getValue("room", "GroundZero#Reception"); @@ -520,14 +524,16 @@ bool handleCommand(char* buffer, std::string from, std::string message) { if (args.size() > 0) { if (args[0] == "roll" && args.size() > 1) { int dice = 1; int sides = 6; int roll = 0; - if (args.size() > 1) { + int darg = 1; + if (args[1] == "a") darg = 2; + if (args.size() > darg) { try { - int dinx = args[1].find("d"); + int dinx = args[darg].find("d"); if (dinx > 0) { - dice = std::stoi(args[1].substr(0, dinx)); + dice = std::stoi(args[darg].substr(0, dinx)); } - sides = std::stoi(args[1].substr(dinx+1, args[1].length())); - } catch (const std::out_of_range& e) { } + sides = std::stoi(args[darg].substr(dinx+1, args[darg].length())); + } catch (...) { } } std::uniform_int_distribution rno(1,sides); @@ -600,14 +606,6 @@ bool handlePhrase(char* buffer, std::string from, std::string message) { sprintf(buffer, messages->getMessage("greets").c_str(), from.c_str()); return true; - } else { - - std::string response; - if ((response = getValueOfIncludedName(replylist->get(), message)).length() > 0) { - sprintf(buffer, response.c_str()); - } - return true; - } return false; } @@ -616,22 +614,53 @@ void processText(int *sock, std::string username, std::string message) { if (debug) printf("debug: received text from %s: \"%s\"\n", username.c_str(), message.c_str()); char *msgout = new char[BUFFERSIZE]; if (username.compare(login_username) != 0) { - message = toLower(message); // Make it a lowercase string so we can work with it. + // We'll make a lowercase version so we can work with it without worrying about cases. + std::string lowermsg = toLower(message); // Assign message to lowermsg to make a copy. int alen = 0; // Someone has requested P3NG0s attention. // We'll accept some variations. - if ((alen = vstrcontains(message, messages->getMessages("attention"))) > 0) { + if ((alen = vstrcontains(lowermsg, messages->getMessages("attention"))) > 0) { // Strip out the attention. We got it. - message = message.substr(alen+1, message.length()); - if (handleCommand(msgout, username, message)) { + if (handleCommand(msgout, username, message.substr(alen+1, message.length()))) { printf("info: processed command\n"); - } else if (handlePhrase(msgout, username, message)) { + } else if (handlePhrase(msgout, username, lowermsg.substr(alen+1, lowermsg.length()))) { printf("info: processed phrase\n"); } sendChatMessage(sock, std::string(msgout)); - } else if (message == "ping") { + } else if (lowermsg == "ping") { sprintf(msgout, mainConf->getValue("pong_msg", "Pong!").c_str()); sendChatMessage(sock, std::string(msgout)); + } else if (lowermsg.find("http") != std::string::npos) { + int pos; + if ((pos = lowermsg.find("http://")) != std::string::npos || (pos = lowermsg.find("https://")) != std::string::npos) { + std::string url = message.substr(pos, message.substr(pos, message.length()).find(" ")); + if (debug) printf("debug: getting title for url \"%s\"\n", url.c_str()); + if(CURL* curl = curl_easy_init()) { + std::string httpContents; + + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); + curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent.c_str()); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &httpContents); + + CURLcode res = curl_easy_perform(curl); + if(res != CURLE_OK) fprintf(stderr, "Error: curl_easy_perform() failed > %s\n", curl_easy_strerror(res)); + curl_easy_cleanup(curl); + if (httpContents.length() > 0 && httpContents.find("") != std::string::npos) { + std::string linktitle = httpContents.substr(httpContents.find("<title>")+7, httpContents.length()); + linktitle = decodeHTML(filter(filth->getLines(), linktitle.substr(0, linktitle.find("<")))); + if (linktitle.length() > 0) { + if (linktitle.length() > 180) linktitle = linktitle.substr(0, 180)+"..."; + if (debug) printf("debug: got title \"%s\"\n", linktitle.c_str()); + sprintf(msgout, mainConf->getValue("link_msg", "[%s] Link: %s").c_str(), username.c_str(), linktitle.c_str()); + sendChatMessage(sock, std::string(msgout)); + } + } + } + } } } } @@ -711,3 +740,4 @@ void qsend(int *sock, unsigned char str[], bool queue) { if (queue) bufferQueue.push_back(*qp); else qp->flush(0); } + diff --git a/src/urlname.cpp b/src/urlname.cpp new file mode 100644 index 0000000..027dfad --- /dev/null +++ b/src/urlname.cpp @@ -0,0 +1,18 @@ +#include <iostream> +#define CURL_STATICLIB +#include <curl/curl.h> +#include <math.h> +#include <unistd.h> +#ifdef __linux__ + #include <sys/ioctl.h> +#endif + + + +size_t my_array_write(char *ptr, size_t size, size_t nmemb, void *userdata) { + +} + +void getTitle(std::string url, const char* filename) { + +} \ No newline at end of file diff --git a/src/utils.h b/src/utils.h index a2db991..fd95580 100644 --- a/src/utils.h +++ b/src/utils.h @@ -9,6 +9,11 @@ #include <iterator> #include <algorithm> +static size_t CurlWriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { + ((std::string*)userp)->append((char*)contents, size * nmemb); + return size * nmemb; +} + template <typename Out> void split(const std::string &s, char delim, Out result) { std::istringstream iss(s); @@ -24,6 +29,17 @@ std::vector<std::string> split(const std::string &s, char delim) { return elems; } +bool strcontains(std::string needle, std::string haystack); +bool vfind(std::vector<std::string> v, std::string i); +int vstrcontains(std::string needle, std::vector<std::string> haystack); +std::string filter(std::vector<std::string> filterlist, std::string input); +std::string getValueOfIncludedName(std::map<std::string, std::string> list, std::string input); +std::string strcombine(std::vector<std::string> args, int start, int end, char pad); +static char* toLower(char* str); +static std::string toLower(std::string str); +static char* trim(char *str); + + bool strcontains(std::string needle, std::string haystack) { bool found = haystack.find(needle) != std::string::npos; return found; @@ -40,6 +56,43 @@ int vstrcontains(std::string needle, std::vector<std::string> haystack) { return 0; } +std::string replaceAll(std::string input, std::string find, std::string replacement) { + int pos; + while ((pos = input.find(find)) != std::string::npos) { + input = input.replace(pos, find.length(), replacement); + } + return input; +} + +std::string filter(std::vector<std::string> filterlist, std::string input) { + for (std::string str : filterlist) { + int pos; + while ((pos = toLower(input).find(toLower(str))) != std::string::npos) { + std::string replacement; + for (int i = 0; i < str.length(); i++) replacement+="*"; + input = input.replace(pos, str.length(), replacement); + } + } + return input; +} + +std::string decodeHTML(std::string in) { + int pos; + while ((pos = in.find("&#")) != std::string::npos) { + try { + char c = std::stoi(in.substr(pos+2, in.length())); + int endpos = in.substr(pos, in.length()).find(";"); + if (endpos == std::string::npos) continue; + in = in.replace(pos, endpos+1, std::string(1, c)); + } catch (...) { }; + } + // We should be good to try and parse named encodes. + in = replaceAll(in, "&", "&"); + in = replaceAll(in, "<", "<"); + in = replaceAll(in, ">", ">"); + return in; +} + std::string getValueOfIncludedName(std::map<std::string, std::string> list, std::string input) { for (auto v : list) { if (strcontains(v.first, input)) return v.second;