Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal
Sign in to follow this  

Recommended Posts

There was no IRC library for OpenComputers, so I've made one. Here's a demo bot that uses it:

local com = require("component")
local event = require("event")
local thread = require("thread")

local gpu = com.gpu

local irc = require("irc")
local events = irc.events

local env = setmetatable({
  irc = irc,
  events = events,
}, {__index = _G})

local client = irc.builder()
  :connection {
    host = "irc.esper.net:6667",
    throttling = {
      maxDelay = 2,
      maxThroughput = 5,
    },
  }
  :auth {
    nickname = "oc-finger-irc",
    username = "fingercomp",
    realname = "OpenComputers IRC client library",
  }
  :bot {
    channels = {"#oc-finger-irc"},
    tracking = {
      users = true,
      modes = true,
      account = true,
      userInfo = true,
    },
  }
  :execution {
    threaded = true,
    reconnect = true,
    catchErrors = true,
  }
  :subscribe(events.irc.command, events.priority.high, function(self, client, evt)
    gpu.setForeground(0x00ff00)
    print("→ " .. evt.rawLine)
    gpu.setForeground(0xffffff)
  end)
  :subscribe(events.irc.write, events.priority.normal, function(self, client, evt)
    gpu.setForeground(0x00dbff)
    print("← " .. evt.line:gsub("[\r\n]*$", ""))
    gpu.setForeground(0xffffff)
  end)
  :subscribe(events.irc.message, irc.events.priority.normal, function(self, client, evt)
    if evt.source.nickname == "fingercomp" then
      if evt.message == "::quit" then
        evt:reply("Quitting.")
        evt.client:stop(("%s told me to quit."):format(evt.source.nickname))
      elseif evt.message == "::spam" then
        evt:reply("1")
        evt:reply("2")
        evt:reply("3")
        evt:reply("4")
        evt:reply("5")
      elseif evt.message == "::longmsg" then
        local msg = {}
        for i = 1, 256 do
          if i == 128 then
            table.insert(msg, tostring(i) .. " ")
          else
            table.insert(msg, tostring(i))
          end
        end
        evt:reply(table.concat(msg))
      elseif evt.message == "::error" then
        (nil).test()
      elseif evt.message:sub(1, #"::exec ") == "::exec " then
        local code = evt.message:sub(#"::exec " + 1)

        local chunk, reason = load("return " .. code, "=irc", "t", env)

        if not chunk then
          chunk, reason = load(code, "=irc", "t", env)
        end

        if not chunk then
          evt:reply(("\x0304Error:\x0f %s"):format(reason))
        else
          local result = table.pack(xpcall(chunk, debug.traceback))
          local success = table.remove(result, 1)
          result.n = result.n - 1

          for i = 1, result.n, 1 do
            if type(result) ~= "string" and type(result) ~= "number" and
                type(result) ~= "boolean" and type(result) ~= "nil" then
              result[i] = tostring(result[i])
            else
              result[i] = ("%q"):format(result[i]):gsub("\\\n", "\n")
            end
          end

          if not success then
            evt:reply(("\x0304Error:\x0f %s"):format(result[1]:match("^[^\n]*")))

            io.stderr:write(("%s\r\n"):format(result[1]))
          elseif result.n > 0 then
            evt:reply(table.concat(result, "  ", i, result.n))
          else
            evt:reply("\x0309Success")
          end
        end
      end
    end
  end)
  :subscribe(events.irc.ctcpRequest, irc.events.priority.normal, function(self, client, evt)
    if evt.ctcpCommand == "TIME" then
      evt:reply(os.date("%F %T"))
    end
  end)
  :subscribe(events.client.error, irc.events.priority.top, function(self, client, evt)
    print("Caught: " .. evt.traceback)
    evt:cancel()
  end)
  :build()

local t = thread.create(function()
  repeat
    local evt = event.pull("interrupted")
  until evt
end)

env.client = client
client:run()

thread.waitForAny({t, client.thread})
client:stop("Quitting.")

os.exit()

I don't want to brag about it too much, but I think the code is pretty.

Features

  • Threaded execution.
  • A nice API.
  • IRCv3.2 capability negotiation.
  • Throttling to prevent the bot from triggering anti-flood mechanisms.
  • Tracks channel members, modes, nick changes, account names, etc.
  • Automatically reconnects if it's disconnected from the IRC server.
  • Splits long messages over multiple lines.
  • The event bus can use coroutines as message handlers.

Links

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.