Merge branch 'master' of https://git.worlio.com/bonkmaykr/Tourbot
This commit is contained in:
commit
ac5b9a7f7f
35
src/client.h
35
src/client.h
|
@ -9,7 +9,7 @@
|
|||
#include "acfile.h"
|
||||
#define BUFFERSIZE 4096
|
||||
|
||||
bool debug = false;
|
||||
bool debug = true;
|
||||
std::random_device rd;
|
||||
std::mt19937 rng(rd());
|
||||
|
||||
|
@ -23,6 +23,7 @@ const std::string user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.
|
|||
std::string confFile = "conf/bot.conf";
|
||||
ACFile* mainConf;
|
||||
ACFile* worldlist;
|
||||
ACFile* marksLUT;
|
||||
ACFile* replylist;
|
||||
AMFile* messages;
|
||||
ALFile* filth;
|
||||
|
@ -49,7 +50,7 @@ uint16_t roomport = 5672;
|
|||
|
||||
std::string login_username;
|
||||
std::string login_password;
|
||||
std::string avatar = "avatar:pengo.mov";
|
||||
std::string avatar = "http://files.worlio.com/users/bonkmaykr/avatarsforme/gabu1s*4h*4v*.mov";
|
||||
|
||||
// Needs to include dimension too
|
||||
std::string room;
|
||||
|
@ -57,7 +58,7 @@ uint16_t roomID = 1;
|
|||
|
||||
int protocol = 24;
|
||||
char* version = "1000000000";
|
||||
int avatars = 253;
|
||||
int avatars = 253; // avoid culling users if possible... what could go wrong?
|
||||
int keepAliveTime;
|
||||
|
||||
uint16_t xPos = 0;
|
||||
|
@ -70,6 +71,30 @@ std::map<char, char*> properties;
|
|||
std::map<char, Drone*> objects;
|
||||
std::vector<Group> groups;
|
||||
|
||||
namespace internalTypes {
|
||||
struct dronePositionI {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int yaw;
|
||||
};
|
||||
|
||||
struct dronePositionF {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float yaw;
|
||||
};
|
||||
|
||||
struct markEntry {
|
||||
std::string name;
|
||||
std::string url;
|
||||
std::string room;
|
||||
dronePositionI position;
|
||||
bool blacklist;
|
||||
};
|
||||
}
|
||||
|
||||
void loadConfig();
|
||||
int deinit(int response);
|
||||
void autoInit();
|
||||
|
@ -101,6 +126,10 @@ void sendGroupMessage(Group* g, int *sock, std::string message);
|
|||
void safeDeleteGroupMember(Group* g, std::string member);
|
||||
void qsend(int *sock, unsigned char str[], bool queue);
|
||||
|
||||
void handleTeleportRequest(internalTypes::markEntry details);
|
||||
void handleTour(std::string destination[4]);
|
||||
void lookUpWorldName(std::string alias, char* buffer);
|
||||
|
||||
Drone* getDrone(std::string name) {
|
||||
for (auto o : objects)
|
||||
if (o.second->name == name) return o.second;
|
||||
|
|
122
src/main.cpp
122
src/main.cpp
|
@ -11,6 +11,7 @@
|
|||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
//#include <vector>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
@ -22,6 +23,7 @@
|
|||
#include <fcntl.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
#define CURL_STATICLIB
|
||||
#include <curl/curl.h>
|
||||
|
@ -32,6 +34,13 @@
|
|||
#include "props.h"
|
||||
#include "utils.h"
|
||||
|
||||
// Global variables used to prevent things from derailing
|
||||
bool onTour = false;
|
||||
std::string tourQueue[4];
|
||||
std::string realLocation;
|
||||
json worldsmarks;
|
||||
|
||||
|
||||
class QueuedPacket {
|
||||
public:
|
||||
QueuedPacket() {};
|
||||
|
@ -61,9 +70,10 @@ int main(int argc, char const* argv[]) {
|
|||
printf("info: primary conf file set to \"%s\"\n", confFile.c_str());
|
||||
}
|
||||
loadConfig();
|
||||
/*for (auto const& c : mainConf->get()) {
|
||||
printf("info: (%s),(%s)\n", c.first.c_str(), c.second.c_str());
|
||||
}*/
|
||||
|
||||
// initialize teleportation ability
|
||||
realLocation = mainConf->getValue("world", "http://jett.dacii.net/jett/Recreated%20Worlds/SummersGZ/groundzero%20summers.world");
|
||||
|
||||
autoInit();
|
||||
while (autoOnline || roomOnline) {
|
||||
while (!roomOnline) {} // We require the room but get disconnected from auto after awhile
|
||||
|
@ -84,6 +94,7 @@ int main(int argc, char const* argv[]) {
|
|||
void loadConfig() {
|
||||
mainConf = new ACFile(confFile.c_str());
|
||||
worldlist = new ACFile(mainConf->getValue("worldfile", "conf/worldlist.conf").c_str());
|
||||
marksLUT = new ACFile(mainConf->getValue("lutfile", "conf/lut.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());
|
||||
|
@ -99,6 +110,23 @@ void loadConfig() {
|
|||
spin = mainConf->getInt("spin", 0);
|
||||
keepAliveTime = mainConf->getInt("katime", 15);
|
||||
debug = mainConf->getInt("debug", 0) == 1;
|
||||
|
||||
// parse json routine
|
||||
//
|
||||
// data structure per entry is as follows:
|
||||
// name (friendly name used during tours)
|
||||
// url (the file location)
|
||||
// room (the chatroom ID for the roomserver)
|
||||
// position (an array containing the bot's resting position for that world while on tour)
|
||||
// position is an array with a length of 4, containing X, Y, Z, and yaw in that order.
|
||||
// blacklist (bool which skips the world during diceroll tours)
|
||||
// useful for preventing GZ reskins from appearing, exceptions made where appropriate
|
||||
// blacklisted worlds still need a specified idle position!
|
||||
//
|
||||
// feature idea: commentary/notes keyvalue pair which the bot will speak when entering a certain world, used to give tips ??
|
||||
|
||||
std::ifstream dictionaryStream("conf/marks.json"); // look for worldsmarks database in the configuration folder and open it
|
||||
worldsmarks = json::parse(dictionaryStream); // parse and remember data globally
|
||||
}
|
||||
|
||||
int deinit(int response) {
|
||||
|
@ -172,8 +200,8 @@ void roomKeepAlive() {
|
|||
void autoRandMessage() {
|
||||
int minTime = mainConf->getInt("minRandomMsgTime", 0);
|
||||
int maxTime = mainConf->getInt("maxRandomMsgTime", 0);
|
||||
int wait = 0;
|
||||
sendChatMessage(&roomsock, messages->getMessage("startup"));
|
||||
int wait = 600;
|
||||
//sendChatMessage(&roomsock, messages->getMessage("startup"));
|
||||
if (minTime != 0) {
|
||||
while (roomOnline) {
|
||||
if (wait != 0) {
|
||||
|
@ -349,11 +377,15 @@ void reciever(int *sock, uint16_t port, bool* status) {
|
|||
*status = false;
|
||||
}
|
||||
|
||||
// this only works correctly if using POSIX-compliant line endings in the bot.conf file
|
||||
// CR+LF breaks everything, should probably fix this if this becomes widely used at any point!
|
||||
void sessInit(int *sock, std::string username, std::string password) {
|
||||
bufout[1] = 0x01;
|
||||
bufout[2] = CMD_SESSINIT;
|
||||
int l = 3;
|
||||
int l = 3; // packet construction buffer
|
||||
|
||||
std::cout << "Logging in with screenname " + username + "\n"; //debug
|
||||
|
||||
// Username
|
||||
bufout[l++] = 2;
|
||||
bufout[l++] = username.length();
|
||||
|
@ -395,6 +427,7 @@ void sessInit(int *sock, std::string username, std::string password) {
|
|||
|
||||
bufout[0] = l;
|
||||
bufout[l+1] = 0;
|
||||
|
||||
qsend(sock, bufout, false);
|
||||
}
|
||||
|
||||
|
@ -755,6 +788,39 @@ bool handleGroups(char* buffer, std::string from, std::string message) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// unimplemented
|
||||
void handleTeleportRequest(internalTypes::markEntry details) {
|
||||
|
||||
}
|
||||
|
||||
// unimplemented
|
||||
void handleTour(std::string destination[4]) {
|
||||
|
||||
}
|
||||
|
||||
// avoid redundant CTRL + V code in handlePhrase()
|
||||
void lookUpWorldName(std::string alias, char* buffer/*replies*/) {
|
||||
auto key = worldsmarks.find(alias);
|
||||
if (key != worldsmarks.end()) {
|
||||
std::cout << "info: found world \"" + alias + "\", teleporting.";
|
||||
internalTypes::markEntry details;
|
||||
details.name = (*key)["name"].get<std::string>();
|
||||
details.url = (*key)["url"].get<std::string>();
|
||||
details.room = (*key)["room"].get<std::string>();
|
||||
|
||||
details.position.x = (*key)["position"][0];
|
||||
details.position.y = (*key)["position"][1];
|
||||
details.position.z = (*key)["position"][2];
|
||||
details.position.yaw = (*key)["position"][3];
|
||||
|
||||
handleTeleportRequest(details);
|
||||
}
|
||||
else {
|
||||
std::cout << "ERROR: no world with the name \"" + alias + "\" exists! aborting teleport request\n";
|
||||
sprintf(buffer, mainConf->getValue("world_not_found_msg", "Sorry, I don't know that one.").c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool handlePhrase(char* buffer, std::string from, std::string message) {
|
||||
std::vector<std::string> args = split(message, ' ');
|
||||
if (strcontains("flip a coin", message)) {
|
||||
|
@ -780,6 +846,31 @@ bool handlePhrase(char* buffer, std::string from, std::string message) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// in the interest of making things easier programmatically
|
||||
// i want to generate LUTs to map phrases to the JSON
|
||||
// which will allow aliases for each entry in the db
|
||||
//
|
||||
// having an admin command like "makelut" to instantly generate these
|
||||
// by recursively scanning the marks file would be nice
|
||||
else if (strcontains("take me to", message)) {
|
||||
std::cout << "info: remote user requested teleportation!\n";
|
||||
// lookup LUT first for aliases and then check JSON for key
|
||||
// using worldsmarks.find(message) if no alias present
|
||||
// spit back error if both are blank
|
||||
|
||||
std::string alias = getValueOfIncludedName(marksLUT->get(), message);
|
||||
if (alias.length() > 0) {
|
||||
std::cout << "info: found world with alias \"" + message + "\" in lookup table.\n";
|
||||
lookUpWorldName(alias, buffer);
|
||||
}
|
||||
else { // we didn't find an alias, search the DB directly
|
||||
std::cout << "info: no world with the alias \"" + message + "\" is in the lookup table.\n";
|
||||
lookUpWorldName(message, buffer);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -811,6 +902,7 @@ void processText(int *sock, std::string username, std::string message) {
|
|||
} 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) {
|
||||
} 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) {
|
||||
|
@ -866,6 +958,24 @@ void processWhisper(int *sock, std::string username, std::string message) {
|
|||
}
|
||||
sendWhisperMessage(sock, username, msgout);
|
||||
}
|
||||
|
||||
// needs to process geolocation requests and respond with a file path for valid teleporting
|
||||
if (lowermsg == "&|+where?") {
|
||||
// intentionally omit bot location if we're touring so players always start at world start
|
||||
// the bot should ideally be placed in the same starting room, within the player's view as soon as they spawn
|
||||
//
|
||||
// doing it this way requires that we handle bookmark room IDs separately from the destination URL
|
||||
if (onTour == true) {
|
||||
std::cout << "info: touring, sending truncated location\n";
|
||||
sendWhisperMessage(sock, username, "&|+where>" + realLocation + "#" + room);
|
||||
}
|
||||
else {
|
||||
// are all these concats really fucking neccessary?
|
||||
std::cout << "info: not touring, sending full location\n";
|
||||
sendWhisperMessage(sock, username, "&|+where>" + realLocation + "#" + room
|
||||
+ "@" + std::to_string(xPos) + "," + std::to_string(yPos) + "," + std::to_string(zPos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendChatMessage(int *sock, std::string msg) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user