This commit is contained in:
Wirlaburla 2023-10-06 03:11:55 -05:00
parent fb666f1d92
commit ce204d0f8f
9 changed files with 250 additions and 27 deletions

View File

@ -1,7 +1,10 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
project(pengobot) project(pengobot)
add_definitions(-DCURL_STATICLIB)
SET(CMAKE_CXX_STANDARD 17) SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED True) SET(CMAKE_CXX_STANDARD_REQUIRED True)
SET(CMAKE_CXX_FLAGS "-O3") SET(CMAKE_CXX_FLAGS "-O3")
find_package(CURL REQUIRED)
include_directories(${CURL_INCLUDE_DIR})
add_subdirectory(src) add_subdirectory(src)
install(TARGETS pengobot RUNTIME DESTINATION bin) install(TARGETS pengobot RUNTIME DESTINATION bin)

81
conf.examples/filth.list Normal file
View File

@ -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

View File

@ -1,4 +1,4 @@
add_executable(pengobot add_executable(pengobot
main.cpp main.cpp
) )
target_link_libraries(pengobot -static) target_link_libraries(pengobot ${CURL_LIBRARIES} -static)

View File

@ -16,7 +16,7 @@ public:
} }
ACFile(const char* path) { ACFile(const char* path) {
std::ifstream infile(path); std::ifstream infile(path);
printf("info: reading file %s\n", path);
std::string line; std::string line;
while (std::getline(infile, line)) { while (std::getline(infile, line)) {
if (line.length() == 0) continue; if (line.length() == 0) continue;
@ -30,9 +30,6 @@ public:
} }
std::map<std::string, std::string> get() { std::map<std::string, std::string> get() {
for (auto const& c : this->conf) {
printf("info: (%s),(%s)\n", c.first.c_str(), c.second.c_str());
}
return this->conf; return this->conf;
} }
@ -76,7 +73,7 @@ public:
this->rng = std::mt19937(rd()); this->rng = std::mt19937(rd());
std::ifstream infile(path); std::ifstream infile(path);
printf("info: reading file %s\n", path);
std::string line; std::string group; std::string line; std::string group;
while (std::getline(infile, line)) { while (std::getline(infile, line)) {
if (line.length() == 0) continue; if (line.length() == 0) continue;
@ -113,5 +110,32 @@ private:
std::mt19937 rng; 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<std::string> getLines() {
return list;
}
private:
std::vector<std::string> list;
};
#endif #endif

View File

@ -11,11 +11,13 @@ bool debug = false;
std::random_device rd; std::random_device rd;
std::mt19937 rng(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"; std::string confFile = "conf/bot.conf";
ACFile* mainConf; ACFile* mainConf;
ACFile* worldlist; ACFile* worldlist;
ACFile* replylist; ACFile* replylist;
AMFile* messages; AMFile* messages;
ALFile* filth;
#define BUFFERSIZE 65535 #define BUFFERSIZE 65535

View File

@ -1,5 +1,6 @@
#ifndef H_DRONE #ifndef H_DRONE
#define H_DRONE #define H_DRONE
#include "group.h"
class Drone { class Drone {
public: public:
@ -10,6 +11,17 @@ public:
Drone(char* &_name) : name{ _name } { }; Drone(char* &_name) : name{ _name } { };
bool operator != (Drone &d) { return strcmp(this->name, d.name) != 0; }; bool operator != (Drone &d) { return strcmp(this->name, d.name) != 0; };
Drone operator = (Drone *d) { return *d; }; 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 #endif

View File

@ -21,6 +21,9 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#define CURL_STATICLIB
#include <curl/curl.h>
#include "client.h" #include "client.h"
#include "verrors.h" #include "verrors.h"
#include "cmds.h" #include "cmds.h"
@ -33,11 +36,11 @@ public:
QueuedPacket() {}; QueuedPacket() {};
QueuedPacket(const QueuedPacket &other) { QueuedPacket(const QueuedPacket &other) {
this->sock = other.sock; this->sock = other.sock;
memcpy(this->buf, other.buf, 255); memcpy(this->buf, other.buf, other.buf[0]);
} }
QueuedPacket(int *sock, unsigned char str[]) { QueuedPacket(int *sock, unsigned char str[]) {
this->sock = *sock; this->sock = *sock;
memcpy(this->buf, str, 255); memcpy(this->buf, str, str[0]);
}; };
int flush(int flags) { int flush(int flags) {
@ -82,6 +85,7 @@ void loadConfig() {
worldlist = new ACFile(mainConf->getValue("worldfile", "conf/worldlist.conf").c_str()); worldlist = new ACFile(mainConf->getValue("worldfile", "conf/worldlist.conf").c_str());
replylist = new ACFile(mainConf->getValue("replyfile", "conf/replies.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()); 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_username = mainConf->getValue("username", "");
login_password = mainConf->getValue("password", ""); login_password = mainConf->getValue("password", "");
room = mainConf->getValue("room", "GroundZero#Reception<dimension-1>"); room = mainConf->getValue("room", "GroundZero#Reception<dimension-1>");
@ -520,14 +524,16 @@ bool handleCommand(char* buffer, std::string from, std::string message) {
if (args.size() > 0) { if (args.size() > 0) {
if (args[0] == "roll" && args.size() > 1) { if (args[0] == "roll" && args.size() > 1) {
int dice = 1; int sides = 6; int roll = 0; 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 { try {
int dinx = args[1].find("d"); int dinx = args[darg].find("d");
if (dinx > 0) { 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())); sides = std::stoi(args[darg].substr(dinx+1, args[darg].length()));
} catch (const std::out_of_range& e) { } } catch (...) { }
} }
std::uniform_int_distribution<int> rno(1,sides); std::uniform_int_distribution<int> 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()); sprintf(buffer, messages->getMessage("greets").c_str(), from.c_str());
return true; return true;
} else {
std::string response;
if ((response = getValueOfIncludedName(replylist->get(), message)).length() > 0) {
sprintf(buffer, response.c_str());
}
return true;
} }
return false; 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()); if (debug) printf("debug: received text from %s: \"%s\"\n", username.c_str(), message.c_str());
char *msgout = new char[BUFFERSIZE]; char *msgout = new char[BUFFERSIZE];
if (username.compare(login_username) != 0) { 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; int alen = 0;
// Someone has requested P3NG0s attention. // Someone has requested P3NG0s attention.
// We'll accept some variations. // 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. // Strip out the attention. We got it.
message = message.substr(alen+1, message.length()); if (handleCommand(msgout, username, message.substr(alen+1, message.length()))) {
if (handleCommand(msgout, username, message)) {
printf("info: processed command\n"); 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"); printf("info: processed phrase\n");
} }
sendChatMessage(sock, std::string(msgout)); sendChatMessage(sock, std::string(msgout));
} else if (message == "ping") { } else if (lowermsg == "ping") {
sprintf(msgout, mainConf->getValue("pong_msg", "Pong!").c_str()); sprintf(msgout, mainConf->getValue("pong_msg", "Pong!").c_str());
sendChatMessage(sock, std::string(msgout)); 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>: curl_easy_perform() failed > %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
if (httpContents.length() > 0 && httpContents.find("<title>") != 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); if (queue) bufferQueue.push_back(*qp);
else qp->flush(0); else qp->flush(0);
} }

18
src/urlname.cpp Normal file
View File

@ -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) {
}

View File

@ -9,6 +9,11 @@
#include <iterator> #include <iterator>
#include <algorithm> #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> template <typename Out>
void split(const std::string &s, char delim, Out result) { void split(const std::string &s, char delim, Out result) {
std::istringstream iss(s); std::istringstream iss(s);
@ -24,6 +29,17 @@ std::vector<std::string> split(const std::string &s, char delim) {
return elems; 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 strcontains(std::string needle, std::string haystack) {
bool found = haystack.find(needle) != std::string::npos; bool found = haystack.find(needle) != std::string::npos;
return found; return found;
@ -40,6 +56,43 @@ int vstrcontains(std::string needle, std::vector<std::string> haystack) {
return 0; 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, "&amp;", "&");
in = replaceAll(in, "&lt;", "<");
in = replaceAll(in, "&gt;", ">");
return in;
}
std::string getValueOfIncludedName(std::map<std::string, std::string> list, std::string input) { std::string getValueOfIncludedName(std::map<std::string, std::string> list, std::string input) {
for (auto v : list) { for (auto v : list) {
if (strcontains(v.first, input)) return v.second; if (strcontains(v.first, input)) return v.second;