summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--bot.cpp14
-rw-r--r--bot.h21
-rw-r--r--main.cpp249
-rw-r--r--meson.build12
5 files changed, 300 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9f32893
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.idea
+builddir
+buildDir
+
diff --git a/bot.cpp b/bot.cpp
new file mode 100644
index 0000000..0505c3f
--- /dev/null
+++ b/bot.cpp
@@ -0,0 +1,14 @@
+//
+// Created by coleman on 4/13/24.
+//
+
+#include "bot.h"
+#include <strophe.h>
+
+
+void *bot::connect() {
+ xmpp_ctx_t *ctx;
+
+ xmpp_conn_new(ctx);
+ return nullptr;
+}
diff --git a/bot.h b/bot.h
new file mode 100644
index 0000000..0ce6dbb
--- /dev/null
+++ b/bot.h
@@ -0,0 +1,21 @@
+//
+// Created by coleman on 4/13/24.
+//
+
+#ifndef CHATOPS_BOT_H
+#define CHATOPS_BOT_H
+
+#include <strophe.h>
+
+
+class bot {
+
+public:
+ void *connect();
+
+private:
+
+};
+
+
+#endif //CHATOPS_BOT_H
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..b4fb5ab
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,249 @@
+#include <cstdio>
+#include <cstdlib>
+#include <strophe.h>
+#include <cstring>
+#include <string>
+#include <map>
+
+static int reconnect;
+int handle_message(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *const userdata) {
+ printf("Received message!\n");
+ return 1;
+}
+
+enum StanzaType {
+ UNKNOWN,
+ GROUP_CHAT,
+ DIRECT_MESSAGE
+};
+
+std::map<std::string, StanzaType> stanzaTypeMap = {
+ {"groupchat", GROUP_CHAT},
+ {"chat", DIRECT_MESSAGE},
+};
+
+StanzaType stanza_type_from_str(const char *s) {
+ std::string type(s);
+ auto it = stanzaTypeMap.find(type);
+ if (it != stanzaTypeMap.end()) {
+ return it->second;
+ }
+ // Unknown type; caller should log
+ return UNKNOWN;
+}
+
+int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
+{
+ xmpp_stanza_t *reply, *query, *name, *version, *text;
+ const char *ns;
+ xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
+
+ printf("Received version request from %s\n", xmpp_stanza_get_from(stanza));
+
+ reply = xmpp_stanza_reply(stanza);
+ xmpp_stanza_set_type(reply, "result");
+
+ query = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(query, "query");
+ ns = xmpp_stanza_get_ns(xmpp_stanza_get_children(stanza));
+ if (ns) {
+ xmpp_stanza_set_ns(query, ns);
+ }
+
+ name = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(name, "name");
+ xmpp_stanza_add_child(query, name);
+ xmpp_stanza_release(name);
+
+ text = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_text(text, "libstrophe example bot");
+ xmpp_stanza_add_child(name, text);
+ xmpp_stanza_release(text);
+
+ version = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_name(version, "version");
+ xmpp_stanza_add_child(query, version);
+ xmpp_stanza_release(version);
+
+ text = xmpp_stanza_new(ctx);
+ xmpp_stanza_set_text(text, "1.0");
+ xmpp_stanza_add_child(version, text);
+ xmpp_stanza_release(text);
+
+ xmpp_stanza_add_child(reply, query);
+ xmpp_stanza_release(query);
+
+ xmpp_send(conn, reply);
+ xmpp_stanza_release(reply);
+ return 1;
+}
+
+static int _quit_handler(xmpp_conn_t *conn, void *userdata)
+{
+ (void)userdata;
+ xmpp_disconnect(conn);
+ return 0;
+}
+
+int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
+{
+ xmpp_ctx_t *ctx;
+ ctx = (xmpp_ctx_t *) userdata;
+ xmpp_stanza_t *body, *reply;
+ const char *type;
+ char *intext, *replytext;
+
+ body = xmpp_stanza_get_child_by_name(stanza, "body");
+ if (body == nullptr)
+ return 1;
+ type = xmpp_stanza_get_type(stanza);
+ if (type != nullptr && strcmp(type, "error") == 0)
+ return 1;
+ // type: groupchat
+ intext = xmpp_stanza_get_text(body);
+ // contents of text in intext
+ printf("Incoming message from %s: %s\n", xmpp_stanza_get_from(stanza),
+ intext);
+
+ // Prevent infinite loop: ignore messages from self!
+ const char *fromtext = xmpp_stanza_get_from(stanza);
+ if (strcmp(fromtext, "system-monitor@rooms.de.limited/devil") == 0) {
+ // nothing to free...
+ return 1;
+ }
+
+ reply = xmpp_stanza_reply(stanza);
+ switch (stanza_type_from_str(type)) {
+ case UNKNOWN:
+ break;
+ case GROUP_CHAT:
+ xmpp_stanza_set_type(reply, type);
+ xmpp_stanza_set_attribute(reply, "to", "system-monitor@rooms.de.limited");
+ break;
+ case DIRECT_MESSAGE:
+ xmpp_stanza_set_type(reply, type);
+ break;
+ default:
+ // should never happen
+ break;
+ }
+// if (xmpp_stanza_get_type(reply) == nullptr)
+// xmpp_stanza_set_type(reply, type);
+
+ // Read text and reply
+ if (strcmp(intext, "quit") == 0) {
+ replytext = strdup("bye!");
+ xmpp_timed_handler_add(conn, _quit_handler, 500, nullptr);
+ } else if (strcmp(intext, "reconnect") == 0) {
+ replytext = strdup("alright, let's see what happens!");
+ reconnect = 1;
+ xmpp_timed_handler_add(conn, _quit_handler, 500, nullptr);
+ } else {
+ replytext = (char *)malloc(strlen(" to you too!") + strlen(intext) + 1);
+ strcpy(replytext, intext);
+ strcat(replytext, " to you too!");
+ }
+ xmpp_free(ctx, intext);
+ xmpp_message_set_body(reply, replytext);
+
+ xmpp_send(conn, reply);
+ xmpp_stanza_release(reply);
+ free(replytext);
+
+ return 1;
+}
+
+void join_muc(xmpp_conn_t *conn, const char *room_jid, const char *nick) {
+ xmpp_stanza_t *presence, *x, *history;
+
+ // Build presence stanza
+ presence = xmpp_stanza_new(xmpp_conn_get_context(conn));
+ xmpp_stanza_set_name(presence, "presence");
+ xmpp_stanza_set_attribute(presence, "to", room_jid);
+
+ // Add x element
+ x = xmpp_stanza_new(xmpp_conn_get_context(conn));
+ xmpp_stanza_set_name(x, "x");
+ xmpp_stanza_set_ns(x, "http://jabber.org/protocol/muc");
+
+ // Add history element to limit chat history
+ history = xmpp_stanza_new(xmpp_conn_get_context(conn));
+ xmpp_stanza_set_name(history, "history");
+ xmpp_stanza_set_attribute(history, "maxchars", "0");
+ xmpp_stanza_add_child(x, history);
+ xmpp_stanza_add_child(presence, x);
+
+ xmpp_send(conn, presence);
+
+ xmpp_stanza_release(presence);
+}
+
+void conn_handler(xmpp_conn_t *conn,
+ xmpp_conn_event_t status,
+ int error,
+ xmpp_stream_error_t *stream_error,
+ void *userdata)
+{
+ xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
+
+ (void)error;
+ (void)stream_error;
+
+ if (status == XMPP_CONN_CONNECT) {
+ xmpp_stanza_t *pres;
+ fprintf(stderr, "DEBUG: connected\n");
+
+ // Join MUC
+ join_muc(conn, "system-monitor@rooms.de.limited/devil", "devil");
+
+ xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", nullptr,
+ ctx);
+ xmpp_handler_add(conn, message_handler, nullptr, "message", nullptr, ctx);
+
+ /* Send initial <presence/> so that we appear online to contacts */
+ pres = xmpp_presence_new(ctx);
+ xmpp_send(conn, pres);
+ xmpp_stanza_release(pres);
+ } else {
+ fprintf(stderr, "DEBUG: client -------------- disconnected\n");
+ xmpp_stop(ctx);
+ }
+}
+
+int main(int argc, char **argv) {
+ xmpp_ctx_t *ctx;
+ xmpp_conn_t *conn;
+ xmpp_log_t *log;
+
+ // Initialize library
+ xmpp_initialize();
+
+ // Create a context
+ log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); // Later: XMPP_LEVEL_NONE
+ ctx = xmpp_ctx_new(nullptr, log);
+
+ // Create a connection
+ conn = xmpp_conn_new(ctx);
+ xmpp_conn_set_flags(conn, XMPP_CONN_FLAG_ENABLE_COMPRESSION);
+
+ xmpp_conn_set_jid(conn, "devil@de.limited");
+ xmpp_conn_set_pass(conn, "make-me-4offersW");
+
+ // Add handlers
+// xmpp_handler_add(conn, handle_message, nullptr, "message", nullptr, ctx);
+
+ // Connect and authenticate
+ if (xmpp_connect_client(conn, nullptr, 0, conn_handler, ctx) == XMPP_EOK) {
+
+
+ // Start the event loop
+ xmpp_run(ctx);
+ }
+
+ // Release resources
+ xmpp_conn_release(conn);
+ xmpp_ctx_free(ctx);
+ xmpp_shutdown();
+
+ return 0;
+}
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..b8f6c53
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,12 @@
+project('chatops', 'cpp',
+ version : '1.0.0',
+ default_options : ['warning_level=3', 'cpp_std=c++2a'])
+
+libstrophe = dependency('libstrophe')
+
+deps = [libstrophe]
+srcs = ['main.cpp', 'bot.cpp']
+
+chatops = executable('chatops', srcs, install : true, dependencies : deps)
+
+test('test', chatops) \ No newline at end of file