From Makers Local 256
Jump to: navigation, search


Ackis 2.0 is targeted at an "Intelligent Internet Presence." It's a little bit of intelligent that has a couple of different ways to access it, the most popular being IRC.

The bot is comprised of one Engine, or Core, and at least one Client. Each Client and the Engine being separate processes communicate using the API described in the protocol section via ACLed tcp socket. The Engine has different modules, also separate processes, that can be loaded and unloaded at start and runtime. Each of these modules registers its event hooks when it connects and can continue registering new event hooks during the life of the connection. Each of the clients send every event they can to the engine.


Mid Development


Perl Implementation by Brimstone

  • Features
    • Basic core up and running.
    • [Perl module]
      • Needs documented usage, for now, see mod_movie
    • Clients
      • client_irc
        • still needs nickserv support
    • Modules
      • mod_wiki
        • Need to figure out why it hangs from time to time
      • mod_woot
        • Needs to move to a better module, not just an rss reader
        • Take into account wootoffs
        • Include sold out status
      • mod_movie
        • Need to combine !worthit and !showtimes
      • mod_bash
        • Waiting on multi-line support in client_irc
    • [svn code]

D Implementation by Opticron

How to write D modules

Project Code

  • [svn core implementation]
    • Protocol 2.0 tag: Supports Message Passing and Variable Retrieval
    • Protocol 2.1 branch: Supports Message Passing, Variable Retrieval, and Resource Components, and basic component transactions
  • Modules
    • [mod_misc]: Does !roll, !decide, !trans, !track, !ddate, !centime
    • [mod_links]: Does link title scrape, !qdb, !oito, !link, logs links to db
      • Does not do https
      • Generates tinyurl for links over 50 characters
      • If you msg the bot a link, it will toss it into syndication, checking to see if it's already been posted anywhere before lobbing
    • [mod_quote]: Does !addquote, !delquote, !quote and !quotestat
    • [mod_restaurant]: All commands start with !restaurant
        • The DB tables still need a web interface
      • No parameters yields a random restaurant
      • Locations, extras, and genres can be added like so: "!restaurant add extra wifi to Subway" (no double quoting is necessary)
      • Restaurants can be added using: "!restaurant add restaurant Papa Gyro's" (no double quoting is necessary)
      • Additionally, all can be added at once using this syntax: "!restaurant add "restaurant" "location" "genre"[ "extra"]*"
      • Searches for restaurants, locations, extras, or genres can be performed like so: "!restaurant genre mexican"
      • The type of search can be omitted for a broader search (or faster if you're lazy): "!restaurant deli"
  • Clients
    • [client_xmpp]: Implements the XMPP protocol to access jabber and gtalk servers as well as twitter.
      • Late Implementation (needs more modularity)
    • [client_dirc]: Implements the IRC protocol
      • Supports subscribing channels and users to events through the config file
  • Resources
    • [res_dbase]: Resource to provide database support to all components

Support Code

  • KXML: XML Parser
  • libxmpd: XMPP Client Backend Code
  • [Libackis] (allows easy implementation of modules and clients in D)
    • [Sample Code] (module, client, and resource)
    • Protocol 2.0 tag: Supports Message Passing and Variable Retrieval
    • Protocol 2.1 branch: Supports Message Passing, Variable Retrieval, and Resource Components (Auth up next)

To Do

  • implement core event messages

General Information

Please consolidate general information here and remove other redundant information.


The engine, or core, is expected to route data among components. Component types are currently modules, clients, and resources.

  • Base Implementation
    • Component callback registration
    • Component unload/reload
    • Message passing among components
    • A single connection can not have multiple registration types (can't be a client and a module)
    • No duplicate messages from engine
  • Extended Implementation
    • media translation (e.g. color encoded text -> plain text)
    • connected component information (name, callbacks, etc)
    • execution of other modules' callbacks
      • other modules don't know and don't care

Engine Flow

  • Read config file and command line parameters
    • things like port, paths to modules, etc
  • Start logging and component connection port
  • Start all components with first parameter being [host:]port to connect
  • gather pids and spawn a thread to ensure modules don't die
  • main loop
    • Accepts new connections
      • If not a local connection, require auth
    • Read data and process events


Clients are expected to connect to a server and provide services to users on that server. Some examples are IRC, Jabber, Facebook, GTalk, AIM, etc.. They are also expected to continue living if the core dies and reconnect when it comes back up so it appears that no services had been down.

  • ACLs
  • tracks nick changes
  • ability to not die or trash the connection when the engine kicks it
    • ability to restart or notify the Admin(via ACL) when the engine dies

Clients will typically expose several variables for modules to request. In general, clients should expose "user" and "protocol" along with anything else that could be relevant, such as "chat" for the name of the chat room that generated the event.


Modules are expected to provide a service that clients can tap for their associated users. They can also generate events for clients to catch.


Resources are expected to provide a backend service to clients and modules instead of users. Examples are database access and type conversion. Resources have a type associated with them and only one connected resource can be associated with a given type. Resources SHOULD NOT generate events, only respond to them. Other than the resource registration type, resources use the same messages as a module would.

Planned Work


  1. add support for network and protocol elements to register packets
    • needed for mod_redirect
    • needed also so client_irc can send a message about topic update with protocol="irc"
      • is it really necessary for this case? as far as I can think of, all protocols support multi-user chats
  2. resource support
  3. make sure the core sends failures when necessary (registrations or lack thereof, mostly, lack of auth when necessary, too)
  4. support multiple mime-types separated by commas


  1. Twitter
  2. AIM
  3. S2S IRC
  4. Asterisk
    • end user spoken word --> speech-to-text --> ackis2.0
    • culled web info requested --> text-to-speech --> end user over phone or voip
    • need ACL to restrict access
      • weather, imdb, restaurant info


  1. tv listings search with or other appropriate DB
  2. Client message redirection
  3.  !seen and related utilities
  4. "brain" to learn
    • Markov chains
  5. utorrent status
  6. wiki-talk
    • allows select discussion points to be written to the wiki talk tab for a given project.
    • allowable use from only #makerslocal on freenode
  7. wiki-search
    • allows an individual to search for particular projects.
    • allowable use from only #makerslocal on freenode


  1. res_dbase - allows database access to all modules and clients
  2. res_auth - allows authentication based on UIDs returned from clients
  3. res_conversion - converts among many different formats


Upon establishing a connection, a component will authenticate with the engine if prompted with a 403 info packet and register itself. All components on remote systems must authenticate.

There are two versions of the Ackis2.0 protocol. The original Ackis2.0 protocol is located at Ackis2.0/OriginalProtocol. The new and current version that we're moving to is located at Ackis2.0/Protocol.

Architectural Issues

Redundant Messages

Problem Statement

This can only occur when a single module or client registers multiple callbacks. An example follows:

  1. Module A registers the callbacks "^!roll " and "256"
  2. The core receives the message "!roll 256"
  3. As the core is going through it's callback list, it notices that Module A's callback ("^!roll") matches, and so forwards the message to Module A.
    1. Module A receives the message, but doesn't know which callback it was meant for, so it does it's own quick regex match to see what it was for.
    2. The message matches both registrations, so the module responds twice. Once for each callback.
  4. As the core continues going through it's callback list, it notices that Module A's callback ("256") matches, and so forwards the message to Module A.
    1. Module A receives the message, but doesn't know which callback it was meant for, so it does it's own quick regex match to see what it was for.
    2. The message matches both registrations, so the module responds twice. Once for each callback.
  5. The core has now received a total of 4 messages from Module A, which could possibly be all different, and all get sent back to the originator.

Possible Solutions

  1. Make the core smarter
    1. Solves the issue for all time
    2. Might be a complicated change
  2. Make the module smarter
    1. Only solves the issue for a specific module
    2. Relatively simple to implement on all modules

Patched Revisions

This has been fixed in D-core at revision 170.

Response Confusion

Problem Statement

It is possible for a new/unique message to be confused with a response to a previously sent message if the core's response ID generation range intersects with the initiator's response ID generation range. This is possible since both use the "message" event. The probability of this occurring depends on the hash/modification used to generate the core/target response ID from the initiator/core response ID. This also has malicious implications, but we assume all modules are trusted. Contrary to theory, this event is highly unprobable with the current core and component code written in Perl. When this event actually happens, it'll be acceptable to revisit this bug.

Problem Example

  • A client sends a message to the core
<packet type=message responseid="toast">
 <message data="whatever" mime="text/plain"/>
  • The core distributes this as necessary to modules with the modified responseid "butter"
  • Before the client times out its responseid "toast", a module originates this packet
<packet type=message responseid="butter">
 <message data="non-malicious intent" mime="text/plain"/>
  • The core has "butter" mapped to "toast" in its responseid mapping, and so sends this packet back to the original client
<packet type=message responseid="toast">
 <message data="non-malicious intent" mime="text/plain"/>
  • The client receives the message with the valid responseid "toast" and barfs "non-malicious intent" back at the user

Possible Solutions

  1. It has been determined that components and the core must keep track of exactly where things are sent so that this cannot occur. There is currently no way to detect a malformed client that is sending duplicate responseids.

Related Information