Author Topic: urlbot extension to chat daemon.  (Read 579 times)

Offline quixadhal

  • BFF
  • ***
  • Posts: 629
    • View Profile
    • WileyMUD
urlbot extension to chat daemon.
« on: December 27, 2015, 06:28:46 AM »
Hey guys, with the help of Drakkos and Aidil, I finally got around to changing my MUD to use a built-in solution to populate my URL channel, instead of the tinyfugue triggers I'd been using.

This should serve as a handy example of how to use external programs with fluffos.  NOTE:  I don't redirect errors away to NULL or anything... you might want to or everyone will see error messages on your channel. :)

For those who don't know... a while back, I write a small perl script to go get information about URL's that get posted to various intermud channels.  Because I didn't have a way to do the kind of regexp matching on channel input I needed, I programmed some triggers in my client to handle it and splat the result out to a specific channel.

This worked pretty well, but required me to be logged in (not a problem), and would break on occasions when the mud output line wrapped or otherwise disrupted the pattern.  I was thinking of making an NPC to listen to and respond to the I3 traffic, but Dead Souls makes it obnoxiously hard to do this for "security" reasons.

So, the next best thing was to code it inside the chat daemon itself, where all messages have to go anyways.  Dead Souls ALSO tried to stop me here, but a one line fix removed that "security" feature. :)

So, here's the goodies.

Code: (mudos.cfg) [Select]
# The external programs we allow to be run.
external_cmd_1 : /home/bloodlines/bin/untiny.pl

Code: (/daemon/services/channel.c) [Select]
@@ -83,7 +83,7 @@ void eventReceiveChannelMessage(mixed array packet) {
     tn("eventReceiveChannelMessage: "+identify(packet),"green");

     if( file_name(previous_object()) != INTERMUD_D ) return;
-    if( packet[2] == mud_name() ) return;
+    if( packet[2] == mud_name() && packet[3] != "chat_d" ) return;
     if( !packet[2] || packet[2] == "" ) packet[2] = "BustedAssMUD";

     CHAT_D->eventSendChannel(packet[7] + "@" + packet[2], packet[6],

Code: (/secure/daemon/chat.c) [Select]
static private mapping url_callback_buffer = ([]);

void url_read_callback(int fd, mixed msg) {
    if(member_array(fd, keys(url_callback_buffer)) < 0) {
        url_callback_buffer[fd] = "";
    }
    url_callback_buffer[fd] += msg;
}

void url_write_callback(int fd) {
    // This should never happen.
}

void url_close_callback(int fd) {
    // Here, we should send off the result we got back.
    SERVICES_D->eventSendChannel("CHAT_D", "url", url_callback_buffer[fd], 0, "", "");
    map_delete(url_callback_buffer, fd);
}

int check_for_url(string channel, string msg) {
    mixed check_url;
    int fd;
    string check;
    string *patterns = ({
        "(https?://www.youtube.com/watch\?.*?v=[^&\?\.\ ]+)",
        "(https?://tinyurl.com/[^&\?\.\ ]+)",
        "(https?://bit.ly/[^&\?\.\ ]+)",
        "(https?://goo.gl/[^&\?\.\ ]+)",
        "(https?://mcaf.ee/[^&\?\.\ ]+)",
        "(https?://migre.me/[^&\?\.\ ]+)",
        "(https?://durl.me/[^&\?\.\ ]+)",
        "(https?://is.gd/[^&\?\.\ ]+)",
        "(https?://dailym.ai/[^&\?\.\ ]+)",
        "(https?://ebay.to/[^&\?\.\ ]+)",
        "(https?://youtu.be/[^&\?\.\ ]+)",
        "(https?://onforb.es/[^&\?\.\ ]+)",
        "(https?://imgur.com/[^&\>\.\ ]+)",
        "(https?://amzn.to/[^&\?\.\ ]+)",
    });

    if(!channel || channel == "" || channel == "url") {
        // tn("CHAT_D->check_for_url : channel " + channel, "red");
        return 0;
    }

    foreach( check in patterns ) {
        check_url = pcre_extract(msg, check);
        if(check_url && sizeof(check_url) > 0) {
            string command_string = check_url[0] + " " + channel;
            tn("CHAT_D->check_for_url : pattern " + check + " match " + command_string,"green");
            fd = external_start(1, command_string, "url_read_callback", "url_write_callback", "url_close_callback");
            return 1;
        }
    }
    return 0;
}

and your chat daemon likely differs from mine, but somewhere down there you'll see something like:

        eventChannelMsgToListeners(who, ch, msg, emote, target, targmsg);

after that, add:

        if (check_for_url(ch, msg)) {
            // debug stuff
        }

And last but not least, the perl script.