ladici/irc_client.lua

171 lines
6.6 KiB
Lua

-- -*- Mode: Lua; indent-tabs-mode: nil; lua-indent-level: 2 -*-
-- LADI Continuous Integration (ladici)
-- SPDX-FileCopyrightText: Copyright © 2010-2023 Nedko Arnaudov */
-- SPDX-License-Identifier: GPL-2.0-or-later
--module('irc_client', package.seeall)
local function connect(location)
assert(location.args.host)
assert(location.args.nick)
local host = location.args.host
local port = location.args.port or 6667
local nick = location.args.nick
local username = location.args.username or nick
local realname = location.args.realname or nick
local join = location.args.join
local print = function(msg) hub.incoming_message(msg, location) end
local peer
local function send(msg) irc.send_to_peer(peer, msg) end
local function print_notice(msg, prefix)
if msg then
if type(msg) == 'string' then print(prefix .. msg) end
if type(msg) == 'table' then print(prefix .. table.concat(msg, ' ')) end
end
end
local server_capabilities = {}
local command_handlers = {}
command_handlers['PING'] = function(prefix, command, params)
--print("PING received")
if #params ~= 0 then
local msg = "PONG"
for _, server in pairs(params) do
msg = msg .. ' ' .. server
end
send(msg)
end
end
command_handlers['NOTICE'] = function(prefix, command, params) print_notice(params[2], 'NOTICE: ') end
command_handlers['MODE'] = function(prefix, command, params)
print(('MODE: [%s] [%s]'):format(params[1], params[2]))
end
command_handlers['PRIVMSG'] =
function(prefix, command, params)
nick, user, host = irc.parse_nick_prefix(prefix)
-- print(("'%s' -> '%s' : '%s'"):format(nick, params[1], params[2]))
if params[1]:sub(1, 1) == "#" then
channel = params[1]:sub(2)
else
channel = nil
end
-- print(("channel is '%s'"):format(tostring(channel)))
hub.incoming_message(params[2], location, nick, channel)
end
command_handlers['JOIN'] = function(prefix, command, params)
nick, user, host = irc.parse_nick_prefix(prefix)
print(("'%s':'%s':'%s' joined '%s'"):format(tostring(nick), tostring(user), tostring(host), params[1]))
hub.join(location, params[1]:sub(2), nick)
end
-- welcome
command_handlers['001'] = function(prefix, command, params) print_notice(table.concat(params, ' ', 2), 'WELCOME: ') end
-- your host
command_handlers['002'] = function(prefix, command, params) print_notice(table.concat(params, ' ', 2), 'SHOST: ') end
-- server created
command_handlers['003'] = function(prefix, command, params) print_notice(table.concat(params, ' ', 2), 'SCREAT: ') end
-- server info
command_handlers['004'] = function(prefix, command, params)
local server_name = params[2]
local server_version = params[3]
local user_modes_available = params[4]
local channel_modes_available = params[5]
print_notice(server_name, 'SNAME: ')
print_notice(server_version, 'SVER: ')
print_notice(user_modes_available, 'UMODES: ')
print_notice(channel_modes_available, 'CMODES: ')
end
-- bounce / supported stuff
command_handlers['005'] = function(prefix, command, params)
if #params > 2 then
for i = 2, #params - 1 do
local param = params[i]
local _, _, key, value = param:find('^([^=]+)=(.+)')
if not key then
print(('SCAPS: %s is available'):format(param))
key = param
value = true
else
print(('SCAPS: %s is [%s]'):format(key, value))
end
server_capabilities[key] = value
end
end
end
local function stats_reply(prefix, command, params)
print_notice(table.concat(params, ' ', 2), 'SSTATS: ')
end
command_handlers['250'] = stats_reply
command_handlers['251'] = stats_reply
command_handlers['252'] = stats_reply
command_handlers['253'] = stats_reply
command_handlers['254'] = stats_reply
command_handlers['255'] = stats_reply
command_handlers['265'] = stats_reply
command_handlers['266'] = stats_reply
local function motd_reply(prefix, command, params)
print_notice(table.concat(params, ' ', 2), 'MOTD: ')
end
command_handlers['375'] = motd_reply -- MOTD start
command_handlers['372'] = motd_reply -- MOTD middle
command_handlers['376'] = motd_reply -- MOTD end
peer, err = remotes.connect_tcp(host, port)
if not peer then return nil, err end
local disconnect_function = nil
remotes.add_thread(function()
send(("NICK %s"):format(nick))
send(("USER %s %s %s :%s"):format(username, peer.get_local_ip(), host, realname))
if join then send("JOIN " .. join) end
err = irc.receive(peer, command_handlers, function(msg) print(msg) end)
-- print(err)
peer.close()
if disconnect_function then
-- print("Calling disconnect callback")
disconnect_function()
end
peer = nil
end)
return {
disconnect = function(disconnect_function_param)
print("Disconnecting from " .. host)
peer.close() -- this will break the receive loop
disconnect_function = disconnect_function_param
end,
send = send
}
end
local descriptor = {
name = 'IRC',
required_params = {
host="IP address or a host name if IRC server",
nick="Nickname",
},
optional_params = {
port="TCP port, defaults to 6667",
username="Username, defaults to nick",
realname="Real name, defaults to nick",
},
connect=connect,
}
return descriptor