about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/command/command.c62
-rw-r--r--src/profanity.c7
-rw-r--r--src/profanity.h2
-rw-r--r--src/ui/console.c11
-rw-r--r--src/ui/core.c62
-rw-r--r--src/ui/ui.h6
-rw-r--r--src/ui/window.h3
-rw-r--r--src/xmpp/message.c31
-rw-r--r--src/xmpp/stanza.c5
-rw-r--r--src/xmpp/stanza.h2
-rw-r--r--src/xmpp/xmpp.h1
11 files changed, 182 insertions, 10 deletions
diff --git a/src/command/command.c b/src/command/command.c
index 1a8d070f..cebb10c2 100644
--- a/src/command/command.c
+++ b/src/command/command.c
@@ -138,6 +138,7 @@ static gboolean _cmd_wins(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_nick(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_theme(gchar **args, struct cmd_help_t help);
 static gboolean _cmd_status(gchar **args, struct cmd_help_t help);
+static gboolean _cmd_duck(gchar **args, struct cmd_help_t help);
 
 /*
  * The commands are broken down into three groups:
@@ -454,6 +455,17 @@ static struct cmd_t main_commands[] =
           "Example : /tiny http://www.google.com",
           NULL } } },
 
+    { "/duck",
+        _cmd_duck, parse_args_with_freetext, 1, 1,
+        { "/duck query", "Perform search using DuckDuckGo chatbot.",
+        { "/duck query",
+          "-----------",
+          "Send a search query to the DuckDuckGo chatbot.",
+          "Your chat service must be federated, i.e. allow message to be sent/received outside of its domain.",
+          "",
+          "Example : /duck dennis ritchie",
+          NULL } } },
+
     { "/who",
         _cmd_who, parse_args, 0, 1,
         { "/who [status]", "Show contacts/room participants with chosen status.",
@@ -1094,6 +1106,17 @@ cmd_execute_default(const char * const inp)
         case WIN_CONSOLE:
             cons_show("Unknown command: %s", inp);
             break;
+
+        case WIN_DUCK:
+            if (status != JABBER_CONNECTED) {
+                ui_current_print_line("You are not currently connected.");
+            } else {
+                message_send_duck(inp);
+                ui_duck(inp);
+                free(recipient);
+            }
+            break;
+
         default:
             break;
     }
@@ -1921,6 +1944,45 @@ _cmd_msg(gchar **args, struct cmd_help_t help)
 }
 
 static gboolean
+_cmd_duck(gchar **args, struct cmd_help_t help)
+{
+    char *query = args[0];
+
+    jabber_conn_status_t conn_status = jabber_get_connection_status();
+
+    if (conn_status != JABBER_CONNECTED) {
+        cons_show("You are not currently connected.");
+        return TRUE;
+    }
+
+    if (ui_windows_full()) {
+        cons_show_error("Windows all used, close a window and try again.");
+        return TRUE;
+    }
+
+    // if no duck win open, create it and send a help command
+    if (!ui_duck_exists()) {
+        ui_create_duck_win();
+
+        if (query != NULL) {
+            message_send_duck(query);
+            ui_duck(query);
+        }
+
+    // window exists, send query
+    } else {
+        ui_open_duck_win();
+
+        if (query != NULL) {
+            message_send_duck(query);
+            ui_duck(query);
+        }
+    }
+
+    return TRUE;
+}
+
+static gboolean
 _cmd_status(gchar **args, struct cmd_help_t help)
 {
     char *usr = args[0];
diff --git a/src/profanity.c b/src/profanity.c
index f8441bdb..53441e94 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -141,6 +141,13 @@ prof_handle_delayed_message(char *from, char *message, GTimeVal tv_stamp,
 }
 
 void
+prof_handle_duck_result(const char * const result)
+{
+    ui_duck_result(result);
+    ui_current_page_off();
+}
+
+void
 prof_handle_error_message(const char *from, const char *err_msg)
 {
     win_type_t win_type = ui_current_win_type();
diff --git a/src/profanity.h b/src/profanity.h
index 2afe2a00..0f4699a7 100644
--- a/src/profanity.h
+++ b/src/profanity.h
@@ -78,5 +78,7 @@ void prof_handle_room_list(GSList *rooms, const char *conference_node);
 void prof_handle_disco_items(GSList *items, const char *jid);
 void prof_handle_disco_info(const char *from, GSList *identities,
     GSList *features);
+void prof_handle_duck_help(const char * const result);
+void prof_handle_duck_result(const char * const result);
 
 #endif
diff --git a/src/ui/console.c b/src/ui/console.c
index 4e4f074e..33cf1c51 100644
--- a/src/ui/console.c
+++ b/src/ui/console.c
@@ -265,7 +265,7 @@ cons_show_wins(void)
                 switch (window->type)
                 {
                     case WIN_CHAT:
-                        wprintw(console->win, "%d: chat %s", i + 1, window->from);
+                        wprintw(console->win, "%d: Chat %s", i + 1, window->from);
                         PContact contact = contact_list_get_contact(window->from);
 
                         if (contact != NULL) {
@@ -282,7 +282,7 @@ cons_show_wins(void)
                         break;
 
                     case WIN_PRIVATE:
-                        wprintw(console->win, "%d: private %s", i + 1, window->from);
+                        wprintw(console->win, "%d: Private %s", i + 1, window->from);
 
                         if (window->unread > 0) {
                             wprintw(console->win, ", %d unread", window->unread);
@@ -291,7 +291,7 @@ cons_show_wins(void)
                         break;
 
                     case WIN_MUC:
-                        wprintw(console->win, "%d: room %s", i + 1, window->from);
+                        wprintw(console->win, "%d: Room %s", i + 1, window->from);
 
                         if (window->unread > 0) {
                             wprintw(console->win, ", %d unread", window->unread);
@@ -299,6 +299,11 @@ cons_show_wins(void)
 
                         break;
 
+                    case WIN_DUCK:
+                        wprintw(console->win, "%d: DuckDuckGo search", i + 1);
+
+                        break;
+
                     default:
                         break;
                 }
diff --git a/src/ui/core.c b/src/ui/core.c
index 19be6cbf..eb592a8c 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -205,6 +205,20 @@ ui_windows_full(void)
     return TRUE;
 }
 
+gboolean
+ui_duck_exists(void)
+{
+    int i;
+    for (i = 1; i < NUM_WINS; i++) {
+        if (windows[i] != NULL) {
+            if (windows[i]->type == WIN_DUCK)
+                return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
 void
 ui_contact_typing(const char * const from)
 {
@@ -713,6 +727,54 @@ ui_new_chat_win(const char * const to)
 }
 
 void
+ui_create_duck_win(void)
+{
+    int win_index = _new_prof_win("DuckDuckGo search", WIN_DUCK);
+    ui_switch_win(win_index);
+    win_print_time(windows[win_index], '-');
+    wprintw(windows[win_index]->win, "Type ':help' to find out more.\n");
+}
+
+void
+ui_open_duck_win(void)
+{
+    int win_index = _find_prof_win_index("DuckDuckGo search");
+    if (win_index != NUM_WINS) {
+        ui_switch_win(win_index);
+    }
+}
+
+void
+ui_duck(const char * const query)
+{
+    int win_index = _find_prof_win_index("DuckDuckGo search");
+    if (win_index != NUM_WINS) {
+        win_print_time(windows[win_index], '-');
+        wprintw(windows[win_index]->win, "\n");
+        win_print_time(windows[win_index], '-');
+        wattron(windows[win_index]->win, COLOUR_ME);
+        wprintw(windows[win_index]->win, "Query  : ");
+        wattroff(windows[win_index]->win, COLOUR_ME);
+        wprintw(windows[win_index]->win, query);
+        wprintw(windows[win_index]->win, "\n");
+    }
+}
+
+void
+ui_duck_result(const char * const result)
+{
+    int win_index = _find_prof_win_index("DuckDuckGo search");
+    if (win_index != NUM_WINS) {
+        win_print_time(windows[win_index], '-');
+        wattron(windows[win_index]->win, COLOUR_THEM);
+        wprintw(windows[win_index]->win, "Result : ");
+        wattroff(windows[win_index]->win, COLOUR_THEM);
+        wprintw(windows[win_index]->win, result);
+        wprintw(windows[win_index]->win, "\n");
+    }
+}
+
+void
 ui_outgoing_msg(const char * const from, const char * const to,
     const char * const message)
 {
diff --git a/src/ui/ui.h b/src/ui/ui.h
index ac100588..6d110100 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -110,6 +110,12 @@ void ui_status_room(const char * const contact);
 void ui_status(void);
 void ui_status_private(void);
 
+void ui_create_duck_win(void);
+void ui_open_duck_win(void);
+void ui_duck(const char * const query);
+void ui_duck_result(const char * const result);
+gboolean ui_duck_exists(void);
+
 // create windows
 void create_title_bar(void);
 void create_status_bar(void);
diff --git a/src/ui/window.h b/src/ui/window.h
index 933d4e66..96c8f4af 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -32,7 +32,8 @@ typedef enum {
     WIN_CONSOLE,
     WIN_CHAT,
     WIN_MUC,
-    WIN_PRIVATE
+    WIN_PRIVATE,
+    WIN_DUCK
 } win_type_t;
 
 typedef struct prof_win_t {
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index d18abd62..0f69f4ff 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -71,10 +71,10 @@ message_send(const char * const msg, const char * const recipient)
     if (prefs_get_boolean(PREF_STATES) && chat_session_get_recipient_supports(recipient)) {
         chat_session_set_active(recipient);
         message = stanza_create_message(ctx, recipient, STANZA_TYPE_CHAT,
-            msg, STANZA_NAME_ACTIVE);
+            msg, STANZA_NAME_ACTIVE, NULL);
     } else {
         message = stanza_create_message(ctx, recipient, STANZA_TYPE_CHAT,
-            msg, NULL);
+            msg, NULL, NULL);
     }
 
     xmpp_send(conn, message);
@@ -87,7 +87,19 @@ message_send_groupchat(const char * const msg, const char * const recipient)
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
     xmpp_stanza_t *message = stanza_create_message(ctx, recipient,
-        STANZA_TYPE_GROUPCHAT, msg, NULL);
+        STANZA_TYPE_GROUPCHAT, msg, NULL, NULL);
+
+    xmpp_send(conn, message);
+    xmpp_stanza_release(message);
+}
+
+void
+message_send_duck(const char * const query)
+{
+    xmpp_conn_t * const conn = connection_get_conn();
+    xmpp_ctx_t * const ctx = connection_get_ctx();
+    xmpp_stanza_t *message = stanza_create_message(ctx, "im@ddg.gg",
+        STANZA_TYPE_CHAT, query, NULL, NULL);
 
     xmpp_send(conn, message);
     xmpp_stanza_release(message);
@@ -293,8 +305,19 @@ _chat_message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
     gchar *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
     Jid *jid = jid_create(from);
 
+    // handle ddg searches
+    if (strcmp(jid->barejid, "im@ddg.gg") == 0) {
+        xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
+        if (body != NULL) {
+            char *message = xmpp_stanza_get_text(body);
+            prof_handle_duck_result(message);
+        }
+
+        jid_destroy(jid);
+        return 1;
+
     // private message from chat room use full jid (room/nick)
-    if (muc_room_is_active(jid)) {
+    } else if (muc_room_is_active(jid)) {
         // determine if the notifications happened whilst offline
         GTimeVal tv_stamp;
         gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c
index 68232382..528f2055 100644
--- a/src/xmpp/stanza.c
+++ b/src/xmpp/stanza.c
@@ -55,7 +55,7 @@ stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const recipient,
 xmpp_stanza_t *
 stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
     const char * const type, const char * const message,
-    const char * const state)
+    const char * const state, const char * const id)
 {
     char *encoded_xml = encode_xml(message);
 
@@ -65,6 +65,9 @@ stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient,
     xmpp_stanza_set_name(msg, STANZA_NAME_MESSAGE);
     xmpp_stanza_set_type(msg, type);
     xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, recipient);
+    if (id != NULL) {
+        xmpp_stanza_set_id(msg, id);
+    }
 
     body = xmpp_stanza_new(ctx);
     xmpp_stanza_set_name(body, STANZA_NAME_BODY);
diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h
index 3aa0cf6f..8fb21deb 100644
--- a/src/xmpp/stanza.h
+++ b/src/xmpp/stanza.h
@@ -116,7 +116,7 @@ xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx,
 
 xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx,
     const char * const recipient, const char * const type,
-    const char * const message, const char * const state);
+    const char * const message, const char * const state, const char * const id);
 
 xmpp_stanza_t* stanza_create_room_join_presence(xmpp_ctx_t * const ctx,
     const char * const full_room_jid);
diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h
index 03b6ad85..c65fdfd9 100644
--- a/src/xmpp/xmpp.h
+++ b/src/xmpp/xmpp.h
@@ -99,6 +99,7 @@ void message_send_paused(const char * const recipient);
 void message_send_gone(const char * const recipient);
 void message_send_invite(const char * const room, const char * const contact,
     const char * const reason);
+void message_send_duck(const char * const query);
 
 // presence functions
 void presence_subscription(const char * const jid, const jabber_subscr_t action);