mirror of
https://github.com/sys4-fr/server-nalc.git
synced 2025-06-28 06:11:47 +02:00
Renamed Other > other_things
This commit is contained in:
3
other_things/irc-old-save/irc/.gitignore
vendored
Normal file
3
other_things/irc-old-save/irc/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/gh-pages/
|
||||
*~
|
||||
|
26
other_things/irc-old-save/irc/LICENSE.txt
Normal file
26
other_things/irc-old-save/irc/LICENSE.txt
Normal file
@ -0,0 +1,26 @@
|
||||
--[[
|
||||
Lua IRC library
|
||||
|
||||
Copyright (c) 2010 Jakob Ovrum
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.]]
|
||||
|
18
other_things/irc-old-save/irc/README.markdown
Normal file
18
other_things/irc-old-save/irc/README.markdown
Normal file
@ -0,0 +1,18 @@
|
||||
LuaIRC
|
||||
============
|
||||
|
||||
IRC library for Lua.
|
||||
|
||||
Dependencies
|
||||
-------------
|
||||
|
||||
* [LuaSocket](http://w3.impa.br/~diego/software/luasocket/)
|
||||
|
||||
**Only required if you want to make use of the TLS support**
|
||||
|
||||
* [LuaSec](http://www.inf.puc-rio.br/~brunoos/luasec/)
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
Documentation can be automatically generated by passing irc.luadoc (in doc/) to [LuaDoc](http://luadoc.luaforge.net/), or pre-generated documentation can be found in the 'gh-pages' branch, which can also be browsed [online](http://jakobovrum.github.com/LuaIRC/doc/modules/irc.html).
|
||||
|
90
other_things/irc-old-save/irc/asyncoperations.lua
Normal file
90
other_things/irc-old-save/irc/asyncoperations.lua
Normal file
@ -0,0 +1,90 @@
|
||||
local irc = require("irc.main")
|
||||
|
||||
local meta = irc.meta
|
||||
|
||||
function meta:send(msg, ...)
|
||||
if type(msg) == "table" then
|
||||
msg = msg:toRFC1459()
|
||||
else
|
||||
if select("#", ...) > 0 then
|
||||
msg = msg:format(...)
|
||||
end
|
||||
end
|
||||
self:invoke("OnSend", msg)
|
||||
|
||||
local bytes, err = self.socket:send(msg .. "\r\n")
|
||||
|
||||
if not bytes and err ~= "timeout" and err ~= "wantwrite" then
|
||||
self:invoke("OnDisconnect", err, true)
|
||||
self:shutdown()
|
||||
error(err, errlevel)
|
||||
end
|
||||
end
|
||||
|
||||
function meta:queue(msg)
|
||||
table.insert(self.messageQueue, msg)
|
||||
end
|
||||
|
||||
local function verify(str, errLevel)
|
||||
if str:find("^:") or str:find("%s%z") then
|
||||
error(("malformed parameter '%s' to irc command"):format(str), errLevel)
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
function meta:sendChat(target, msg)
|
||||
-- Split the message into segments if it includes newlines.
|
||||
for line in msg:gmatch("([^\r\n]+)") do
|
||||
self:queue(irc.msgs.privmsg(verify(target, 3), line))
|
||||
end
|
||||
end
|
||||
|
||||
function meta:sendNotice(target, msg)
|
||||
-- Split the message into segments if it includes newlines.
|
||||
for line in msg:gmatch("([^\r\n]+)") do
|
||||
self:queue(irc.msgs.notice(verify(target, 3), line))
|
||||
end
|
||||
end
|
||||
|
||||
function meta:join(channel, key)
|
||||
self:queue(irc.msgs.join(
|
||||
verify(channel, 3),
|
||||
key and verify(key, 3) or nil))
|
||||
end
|
||||
|
||||
function meta:part(channel, reason)
|
||||
channel = verify(channel, 3)
|
||||
self:queue(irc.msgs.part(channel, reason))
|
||||
if self.track_users then
|
||||
self.channels[channel] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function meta:trackUsers(b)
|
||||
self.track_users = b
|
||||
if not b then
|
||||
for k,v in pairs(self.channels) do
|
||||
self.channels[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function meta:setMode(t)
|
||||
local target = t.target or self.nick
|
||||
local mode = ""
|
||||
local add, rem = t.add, t.remove
|
||||
|
||||
assert(add or rem, "table contains neither 'add' nor 'remove'")
|
||||
|
||||
if add then
|
||||
mode = table.concat{"+", verify(add, 3)}
|
||||
end
|
||||
|
||||
if rem then
|
||||
mode = table.concat{mode, "-", verify(rem, 3)}
|
||||
end
|
||||
|
||||
self:queue(irc.msgs.mode(verify(target, 3), mode))
|
||||
end
|
||||
|
184
other_things/irc-old-save/irc/doc/irc.luadoc
Normal file
184
other_things/irc-old-save/irc/doc/irc.luadoc
Normal file
@ -0,0 +1,184 @@
|
||||
--- LuaIRC is a low-level IRC library for Lua.
|
||||
-- All functions raise Lua exceptions on error.
|
||||
--
|
||||
-- Use <code>new</code> to create a new IRC object.<br/>
|
||||
-- Example:<br/><br/>
|
||||
--<code>
|
||||
--require "irc"<br/>
|
||||
--local sleep = require "socket".sleep<br/>
|
||||
--<br/>
|
||||
--local s = irc.new{nick = "example"}<br/>
|
||||
--<br/>
|
||||
--s:hook("OnChat", function(user, channel, message)<br/>
|
||||
-- print(("[%s] %s: %s"):format(channel, user.nick, message))<br/>
|
||||
--end)<br/>
|
||||
--<br/>
|
||||
--s:connect("irc.example.net")<br/>
|
||||
--s:join("#example")<br/>
|
||||
--<br/>
|
||||
--while true do<br/>
|
||||
-- s:think()<br/>
|
||||
-- sleep(0.5)<br/>
|
||||
--end<br/>
|
||||
--</code>
|
||||
|
||||
module "irc"
|
||||
|
||||
--- Create a new IRC object. Use <code>irc:connect</code> to connect to a server.
|
||||
-- @param user Table with fields <code>nick</code>, <code>username</code> and <code>realname</code>.
|
||||
-- The <code>nick</code> field is required.
|
||||
--
|
||||
-- @return Returns a new <code>irc</code> object.
|
||||
function new(user)
|
||||
|
||||
--- Hook a function to an event.
|
||||
-- @param name Name of event.
|
||||
-- @param id Unique tag.
|
||||
-- @param f Callback function. [defaults to <code>id</code>]
|
||||
-- @see Hooks
|
||||
function irc:hook(name, id, f)
|
||||
|
||||
--- Remove previous hooked callback.
|
||||
-- @param name Name of event.
|
||||
-- @param id Unique tag.
|
||||
function irc:unhook(name, id)
|
||||
|
||||
--- Connect <code>irc</code> to an IRC server.
|
||||
-- @param host Host address.
|
||||
-- @param port Server port. [default 6667]
|
||||
function irc:connect(server, port)
|
||||
|
||||
-- @param table Table of connection details
|
||||
-- @see Connection
|
||||
function irc:connect(table)
|
||||
|
||||
--- Disconnect <code>irc</code> from the server.
|
||||
-- @param message Quit message.
|
||||
function irc:disconnect(message)
|
||||
|
||||
--- Handle incoming data for <code>irc</code>, and invoke previously hooked callbacks based on new server input.
|
||||
-- You should call this in some kind of main loop, or at least often enough to not time out.
|
||||
function irc:think()
|
||||
|
||||
--- Look up user info.
|
||||
-- @param nick Nick of user to query.
|
||||
-- @return Table with fields <code>userinfo</code>, <code>node</code>, <code>channels</code> and <code>account</code>.
|
||||
function irc:whois(nick)
|
||||
|
||||
--- Look up topic.
|
||||
-- Use this to invoke the hooks OnTopic and OnTopicInfo at any time.
|
||||
-- @param channel Channel to query.
|
||||
function irc:topic(channel)
|
||||
|
||||
--- Send a IRC message to the server.
|
||||
-- @param msg Message or raw line to send, excluding newline characters.
|
||||
-- @param ... Format parameters for <code>msg</code>, with <code>string.format</code> semantics. [optional]
|
||||
function irc:send(msg, ...)
|
||||
|
||||
--- Queue Message to be sent to the server.
|
||||
-- @param msg Message to be sent.
|
||||
function irc:queue(msg)
|
||||
|
||||
--- Send a message to a channel or user.
|
||||
-- @param target Nick or channel to send to.
|
||||
-- @param message Message text.
|
||||
function irc:sendChat(target, message)
|
||||
|
||||
--- Send a notice to a channel or user.
|
||||
-- @param target Nick or channel to send to.
|
||||
-- @param message Notice text.
|
||||
function irc:sendNotice(target, message)
|
||||
|
||||
--- Join a channel.
|
||||
-- @param channel Channel to join.
|
||||
-- @param key Channel key. [optional]
|
||||
function irc:join(channel, key)
|
||||
|
||||
--- Leave a channel.
|
||||
-- @param channel Channel to leave.
|
||||
function irc:part(channel)
|
||||
|
||||
--- Turn user information tracking on or off. User tracking is enabled by default.
|
||||
-- @param b Boolean whether or not to track user information.
|
||||
function irc:trackUsers(b)
|
||||
|
||||
--- Add/remove modes for a channel or nick.
|
||||
-- @param t Table with fields <code>target, nick, add</code> and/or <code>rem</code>. <code>target</code> or <code>nick</code>
|
||||
-- specifies the user or channel to add/remove modes. <code>add</code> is a list of modes to add to the user or channel.
|
||||
-- <code>rem</code> is a list of modes to remove from the user or channel.
|
||||
-- @usage Example which sets +m (moderated) for #channel: <br/>
|
||||
-- <code>irc:setMode{target = "#channel", add = "m"}</code>
|
||||
function irc:setMode(t)
|
||||
|
||||
--internal
|
||||
function irc:invoke(name, ...)
|
||||
function irc:handle(msg)
|
||||
function irc:shutdown()
|
||||
|
||||
--- Table with connection information.
|
||||
-- <ul>
|
||||
-- <li><code>host</code> - Server host name.</li>
|
||||
-- <li><code>port</code> - Server port. [defaults to <code>6667</code>]</li>
|
||||
-- <li><code>timeout</code> - Connect timeout. [defaults to <code>30</code>]</li>
|
||||
-- <li><code>password</code> - Server password.</li>
|
||||
-- <li><code>secure</code> - Boolean to enable TLS connection, pass a params table (described, [luasec]) to control</li>
|
||||
-- </ul>
|
||||
-- [luasec]: http://www.inf.puc-rio.br/~brunoos/luasec/reference.html
|
||||
-- @name Connection
|
||||
-- @class table
|
||||
|
||||
--- Class representing an IRC message.
|
||||
-- @name Message
|
||||
-- @class table
|
||||
-- @field args A list of the command arguments
|
||||
-- @field command The IRC command
|
||||
-- @field prefix The prefix of the message
|
||||
-- @field raw A raw IRC line for this message
|
||||
-- @field tags A table of IRCv3 tags
|
||||
-- @field user A User object describing the sender of the message
|
||||
-- Fields may be missing.
|
||||
-- Messages have the following methods:
|
||||
-- <ul>
|
||||
-- <li><code>toRFC1459()</code> - Returns the message serialized in RFC 1459 format.</li>
|
||||
-- </ul>
|
||||
|
||||
--- List of hooks you can use with irc:hook.
|
||||
-- The parameter list describes the parameters passed to the callback function.
|
||||
-- <ul>
|
||||
-- <li><code>PreRegister(connection)</code>Useful for CAP commands and SASL.</li>
|
||||
-- <li><code>OnRaw(line) - (any non false/nil return value assumes line handled and will not be further processed)</code></li>
|
||||
-- <li><code>OnSend(line)</code></li>
|
||||
-- <li><code>OnDisconnect(message, errorOccurred)</code></li>
|
||||
-- <li><code>OnChat(user, channel, message)</code></li>
|
||||
-- <li><code>OnNotice(user, channel, message)</code></li>
|
||||
-- <li><code>OnJoin(user, channel)</code>*</li>
|
||||
-- <li><code>OnPart(user, channel)</code>*</li>
|
||||
-- <li><code>OnQuit(user, message)</code></li>
|
||||
-- <li><code>NickChange(user, newnick, channel)</code>*<2A></li>
|
||||
-- <li><code>NameList(channel, names)</code></li>
|
||||
-- <li><code>OnTopic(channel, topic)</code></li>
|
||||
-- <li><code>OnTopicInfo(channel, creator, timeCreated)</code></li>
|
||||
-- <li><code>OnKick(channel, nick, kicker, reason)</code>* (kicker is a <code>user</code> table)</li>
|
||||
-- <li><code>OnUserMode(modes)</code></li>
|
||||
-- <li><code>OnChannelMode(user, channel, modes)</code></li>
|
||||
-- <li><code>OnModeChange(user, target, modes, ...)</code>* ('...' contains mode options such as banmasks)</li>
|
||||
-- <li><code>DoX(msg)</code>'X' is any IRC command or numeric with the first letter capitalized (eg, DoPing and Do001)</li>
|
||||
-- </ul>
|
||||
-- * Event also invoked for yourself.
|
||||
-- <20> Channel passed only when user tracking is enabled
|
||||
-- @name Hooks
|
||||
-- @class table
|
||||
|
||||
--- Table with information about a user.
|
||||
-- <ul>
|
||||
-- <li><code>server</code> - Server name.</li>
|
||||
-- <li><code>nick</code> - User nickname.</li>
|
||||
-- <li><code>username</code> - User username.</li>
|
||||
-- <li><code>host</code> - User hostname.</li>
|
||||
-- <li><code>realname</code> - User real name.</li>
|
||||
-- <li><code>access</code> - User access, available in channel-oriented callbacks. A table containing boolean fields for each access mode that the server supports. Eg: 'o', and 'v'.</li>
|
||||
-- </ul>
|
||||
-- Fields may be missing. To fill them in, enable user tracking and use irc:whois.
|
||||
-- @name User
|
||||
-- @class table
|
||||
|
207
other_things/irc-old-save/irc/handlers.lua
Normal file
207
other_things/irc-old-save/irc/handlers.lua
Normal file
@ -0,0 +1,207 @@
|
||||
local irc = require("irc.main")
|
||||
|
||||
irc.handlers = {}
|
||||
local handlers = irc.handlers
|
||||
|
||||
handlers["PING"] = function(conn, msg)
|
||||
conn:send(irc.Message({command="PONG", args=msg.args}))
|
||||
end
|
||||
|
||||
handlers["001"] = function(conn, msg)
|
||||
conn.authed = true
|
||||
conn.nick = msg.args[1]
|
||||
end
|
||||
|
||||
handlers["PRIVMSG"] = function(conn, msg)
|
||||
conn:invoke("OnChat", msg.user, msg.args[1], msg.args[2])
|
||||
end
|
||||
|
||||
|
||||
handlers["NOTICE"] = function(conn, msg)
|
||||
conn:invoke("OnNotice", msg.user, msg.args[1], msg.args[2])
|
||||
end
|
||||
|
||||
handlers["JOIN"] = function(conn, msg)
|
||||
local channel = msg.args[1]
|
||||
if conn.track_users then
|
||||
if msg.user.nick == conn.nick then
|
||||
conn.channels[channel] = {users = {}}
|
||||
else
|
||||
conn.channels[channel].users[msg.user.nick] = msg.user
|
||||
end
|
||||
end
|
||||
|
||||
conn:invoke("OnJoin", msg.user, msg.args[1])
|
||||
end
|
||||
|
||||
handlers["PART"] = function(conn, msg)
|
||||
local channel = msg.args[1]
|
||||
if conn.track_users then
|
||||
if msg.user.nick == conn.nick then
|
||||
conn.channels[channel] = nil
|
||||
else
|
||||
conn.channels[channel].users[msg.user.nick] = nil
|
||||
end
|
||||
end
|
||||
conn:invoke("OnPart", msg.user, msg.args[1], msg.args[2])
|
||||
end
|
||||
|
||||
handlers["QUIT"] = function(conn, msg)
|
||||
if conn.track_users then
|
||||
for chanName, chan in pairs(conn.channels) do
|
||||
chan.users[msg.user.nick] = nil
|
||||
end
|
||||
end
|
||||
conn:invoke("OnQuit", msg.user, msg.args[1], msg.args[2])
|
||||
end
|
||||
|
||||
handlers["NICK"] = function(conn, msg)
|
||||
local newNick = msg.args[1]
|
||||
if conn.track_users then
|
||||
for chanName, chan in pairs(conn.channels) do
|
||||
local users = chan.users
|
||||
local oldinfo = users[msg.user.nick]
|
||||
if oldinfo then
|
||||
users[newNick] = oldinfo
|
||||
users[msg.user.nick] = nil
|
||||
conn:invoke("NickChange", msg.user, newNick, chanName)
|
||||
end
|
||||
end
|
||||
else
|
||||
conn:invoke("NickChange", msg.user, newNick)
|
||||
end
|
||||
if msg.user.nick == conn.nick then
|
||||
conn.nick = newnick
|
||||
end
|
||||
end
|
||||
|
||||
local function needNewNick(conn, msg)
|
||||
local newnick = conn.nickGenerator(msg.args[2])
|
||||
conn:queue(msgs.nick(newnick))
|
||||
end
|
||||
|
||||
-- ERR_ERRONEUSNICKNAME (Misspelt but remains for historical reasons)
|
||||
handlers["432"] = needNewNick
|
||||
|
||||
-- ERR_NICKNAMEINUSE
|
||||
handlers["433"] = needNewNick
|
||||
|
||||
-- RPL_ISUPPORT
|
||||
handlers["005"] = function(conn, msg)
|
||||
local arglen = #msg.args
|
||||
-- Skip first and last parameters (nick and info)
|
||||
for i = 2, arglen - 1 do
|
||||
local item = msg.args[i]
|
||||
local pos = item:find("=")
|
||||
if pos then
|
||||
conn.supports[item:sub(1, pos - 1)] = item:sub(pos + 1)
|
||||
else
|
||||
conn.supports[item] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- RPL_MOTDSTART
|
||||
handlers["375"] = function(conn, msg)
|
||||
conn.motd = ""
|
||||
end
|
||||
|
||||
-- RPL_MOTD
|
||||
handlers["372"] = function(conn, msg)
|
||||
-- MOTD lines have a "- " prefix, strip it.
|
||||
conn.motd = conn.motd .. msg.args[2]:sub(3) .. '\n'
|
||||
end
|
||||
|
||||
-- NAMES list
|
||||
handlers["353"] = function(conn, msg)
|
||||
local chanType = msg.args[2]
|
||||
local channel = msg.args[3]
|
||||
local names = msg.args[4]
|
||||
if conn.track_users then
|
||||
conn.channels[channel] = conn.channels[channel] or {users = {}, type = chanType}
|
||||
|
||||
local users = conn.channels[channel].users
|
||||
for nick in names:gmatch("(%S+)") do
|
||||
local access, name = irc.parseNick(conn, nick)
|
||||
users[name] = {access = access}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- End of NAMES list
|
||||
handlers["366"] = function(conn, msg)
|
||||
if conn.track_users then
|
||||
conn:invoke("NameList", msg.args[2], msg.args[3])
|
||||
end
|
||||
end
|
||||
|
||||
-- No topic
|
||||
handlers["331"] = function(conn, msg)
|
||||
conn:invoke("OnTopic", msg.args[2], nil)
|
||||
end
|
||||
|
||||
handlers["TOPIC"] = function(conn, msg)
|
||||
conn:invoke("OnTopic", msg.args[1], msg.args[2])
|
||||
end
|
||||
|
||||
handlers["332"] = function(conn, msg)
|
||||
conn:invoke("OnTopic", msg.args[2], msg.args[3])
|
||||
end
|
||||
|
||||
-- Topic creation info
|
||||
handlers["333"] = function(conn, msg)
|
||||
conn:invoke("OnTopicInfo", msg.args[2], msg.args[3], tonumber(msg.args[4]))
|
||||
end
|
||||
|
||||
handlers["KICK"] = function(conn, msg)
|
||||
conn:invoke("OnKick", msg.args[1], msg.args[2], msg.user, msg.args[3])
|
||||
end
|
||||
|
||||
-- RPL_UMODEIS
|
||||
-- To answer a query about a client's own mode, RPL_UMODEIS is sent back
|
||||
handlers["221"] = function(conn, msg)
|
||||
conn:invoke("OnUserMode", msg.args[2])
|
||||
end
|
||||
|
||||
-- RPL_CHANNELMODEIS
|
||||
-- The result from common irc servers differs from that defined by the rfc
|
||||
handlers["324"] = function(conn, msg)
|
||||
conn:invoke("OnChannelMode", msg.args[2], msg.args[3])
|
||||
end
|
||||
|
||||
handlers["MODE"] = function(conn, msg)
|
||||
local target = msg.args[1]
|
||||
local modes = msg.args[2]
|
||||
local optList = {}
|
||||
for i = 3, #msg.args do
|
||||
table.insert(optList, msg.args[i])
|
||||
end
|
||||
if conn.track_users and target ~= conn.nick then
|
||||
local add = true
|
||||
local argNum = 1
|
||||
irc.updatePrefixModes(conn)
|
||||
for c in modes:gmatch(".") do
|
||||
if c == "+" then add = true
|
||||
elseif c == "-" then add = false
|
||||
elseif conn.modeprefix[c] then
|
||||
local nick = optList[argNum]
|
||||
argNum = argNum + 1
|
||||
local user = conn.channels[target].users[nick]
|
||||
user.access = user.access or {}
|
||||
local access = user.access
|
||||
access[c] = add
|
||||
if c == "o" then access.op = add
|
||||
elseif c == "v" then access.voice = add
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
conn:invoke("OnModeChange", msg.user, target, modes, unpack(optList))
|
||||
end
|
||||
|
||||
handlers["ERROR"] = function(conn, msg)
|
||||
conn:invoke("OnDisconnect", msg.args[1], true)
|
||||
conn:shutdown()
|
||||
error(msg.args[1], 3)
|
||||
end
|
||||
|
9
other_things/irc-old-save/irc/init.lua
Normal file
9
other_things/irc-old-save/irc/init.lua
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
local irc = require("irc.main")
|
||||
require("irc.util")
|
||||
require("irc.asyncoperations")
|
||||
require("irc.handlers")
|
||||
require("irc.messages")
|
||||
|
||||
return irc
|
||||
|
241
other_things/irc-old-save/irc/main.lua
Normal file
241
other_things/irc-old-save/irc/main.lua
Normal file
@ -0,0 +1,241 @@
|
||||
local socket = require "socket"
|
||||
|
||||
-- Module table
|
||||
local irc = {}
|
||||
|
||||
local meta = {}
|
||||
meta.__index = meta
|
||||
irc.meta = meta
|
||||
|
||||
local meta_preconnect = {}
|
||||
function meta_preconnect.__index(o, k)
|
||||
local v = rawget(meta_preconnect, k)
|
||||
|
||||
if not v and meta[k] then
|
||||
error(("field '%s' is not accessible before connecting"):format(k), 2)
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
function irc.new(data)
|
||||
local o = {
|
||||
nick = assert(data.nick, "Field 'nick' is required");
|
||||
username = data.username or "lua";
|
||||
realname = data.realname or "Lua owns";
|
||||
nickGenerator = data.nickGenerator or irc.defaultNickGenerator;
|
||||
hooks = {};
|
||||
track_users = true;
|
||||
supports = {};
|
||||
messageQueue = {};
|
||||
lastThought = 0;
|
||||
recentMessages = 0;
|
||||
}
|
||||
assert(irc.checkNick(o.nick), "Erroneous nickname passed to irc.new")
|
||||
return setmetatable(o, meta_preconnect)
|
||||
end
|
||||
|
||||
function meta:hook(name, id, f)
|
||||
f = f or id
|
||||
self.hooks[name] = self.hooks[name] or {}
|
||||
self.hooks[name][id] = f
|
||||
return id or f
|
||||
end
|
||||
meta_preconnect.hook = meta.hook
|
||||
|
||||
|
||||
function meta:unhook(name, id)
|
||||
local hooks = self.hooks[name]
|
||||
|
||||
assert(hooks, "no hooks exist for this event")
|
||||
assert(hooks[id], "hook ID not found")
|
||||
|
||||
hooks[id] = nil
|
||||
end
|
||||
meta_preconnect.unhook = meta.unhook
|
||||
|
||||
function meta:invoke(name, ...)
|
||||
local hooks = self.hooks[name]
|
||||
if hooks then
|
||||
for id, f in pairs(hooks) do
|
||||
if f(...) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function meta_preconnect:connect(_host, _port)
|
||||
local host, port, password, secure, timeout
|
||||
|
||||
if type(_host) == "table" then
|
||||
host = _host.host
|
||||
port = _host.port
|
||||
timeout = _host.timeout
|
||||
password = _host.password
|
||||
secure = _host.secure
|
||||
else
|
||||
host = _host
|
||||
port = _port
|
||||
end
|
||||
|
||||
host = host or error("host name required to connect", 2)
|
||||
port = port or 6667
|
||||
|
||||
local s = socket.tcp()
|
||||
|
||||
s:settimeout(timeout or 30)
|
||||
assert(s:connect(host, port))
|
||||
|
||||
if secure then
|
||||
local work, ssl = pcall(require, "ssl")
|
||||
if not work then
|
||||
error("LuaSec required for secure connections", 2)
|
||||
end
|
||||
|
||||
local params
|
||||
if type(secure) == "table" then
|
||||
params = secure
|
||||
else
|
||||
params = {mode = "client", protocol = "tlsv1"}
|
||||
end
|
||||
|
||||
s = ssl.wrap(s, params)
|
||||
local success, errmsg = s:dohandshake()
|
||||
if not success then
|
||||
error(("could not make secure connection: %s"):format(errmsg), 2)
|
||||
end
|
||||
end
|
||||
|
||||
self.socket = s
|
||||
setmetatable(self, meta)
|
||||
|
||||
self:queue(irc.Message({command="CAP", args={"REQ", "multi-prefix"}}))
|
||||
|
||||
self:invoke("PreRegister", self)
|
||||
self:queue(irc.Message({command="CAP", args={"END"}}))
|
||||
|
||||
if password then
|
||||
self:queue(irc.Message({command="PASS", args={password}}))
|
||||
end
|
||||
|
||||
self:queue(irc.msgs.nick(self.nick))
|
||||
self:queue(irc.Message({command="USER", args={self.username, "0", "*", self.realname}}))
|
||||
|
||||
self.channels = {}
|
||||
|
||||
s:settimeout(0)
|
||||
|
||||
repeat
|
||||
self:think()
|
||||
socket.sleep(0.1)
|
||||
until self.authed
|
||||
end
|
||||
|
||||
function meta:disconnect(message)
|
||||
message = message or "Bye!"
|
||||
|
||||
self:invoke("OnDisconnect", message, false)
|
||||
self:send(irc.msgs.quit(message))
|
||||
|
||||
self:shutdown()
|
||||
end
|
||||
|
||||
function meta:shutdown()
|
||||
self.socket:close()
|
||||
setmetatable(self, nil)
|
||||
end
|
||||
|
||||
local function getline(self, errlevel)
|
||||
local line, err = self.socket:receive("*l")
|
||||
|
||||
if not line and err ~= "timeout" and err ~= "wantread" then
|
||||
self:invoke("OnDisconnect", err, true)
|
||||
self:shutdown()
|
||||
error(err, errlevel)
|
||||
end
|
||||
|
||||
return line
|
||||
end
|
||||
|
||||
function meta:think()
|
||||
while true do
|
||||
local line = getline(self, 3)
|
||||
if line and #line > 0 then
|
||||
if not self:invoke("OnRaw", line) then
|
||||
self:handle(irc.Message({raw=line}))
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle outgoing message queue
|
||||
local diff = socket.gettime() - self.lastThought
|
||||
self.recentMessages = self.recentMessages - (diff * 2)
|
||||
if self.recentMessages < 0 then
|
||||
self.recentMessages = 0
|
||||
end
|
||||
for i = 1, #self.messageQueue do
|
||||
if self.recentMessages > 4 then
|
||||
break
|
||||
end
|
||||
self:send(table.remove(self.messageQueue, 1))
|
||||
self.recentMessages = self.recentMessages + 1
|
||||
end
|
||||
self.lastThought = socket.gettime()
|
||||
end
|
||||
|
||||
local handlers = handlers
|
||||
|
||||
function meta:handle(msg)
|
||||
local handler = irc.handlers[msg.command]
|
||||
if handler then
|
||||
handler(self, msg)
|
||||
end
|
||||
self:invoke("Do" .. irc.capitalize(msg.command), msg)
|
||||
end
|
||||
|
||||
local whoisHandlers = {
|
||||
["311"] = "userinfo";
|
||||
["312"] = "node";
|
||||
["319"] = "channels";
|
||||
["330"] = "account"; -- Freenode
|
||||
["307"] = "registered"; -- Unreal
|
||||
}
|
||||
|
||||
function meta:whois(nick)
|
||||
self:send(irc.msgs.whois(nick))
|
||||
|
||||
local result = {}
|
||||
|
||||
while true do
|
||||
local line = getline(self, 3)
|
||||
if line then
|
||||
local msg = irc.Message({raw=line})
|
||||
|
||||
local handler = whoisHandlers[msg.command]
|
||||
if handler then
|
||||
result[handler] = msg.args
|
||||
elseif msg.command == "318" then
|
||||
break
|
||||
else
|
||||
self:handle(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if result.account then
|
||||
result.account = result.account[3]
|
||||
elseif result.registered then
|
||||
result.account = result.registered[2]
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function meta:topic(channel)
|
||||
self:queue(irc.msgs.topic(channel))
|
||||
end
|
||||
|
||||
return irc
|
||||
|
200
other_things/irc-old-save/irc/messages.lua
Normal file
200
other_things/irc-old-save/irc/messages.lua
Normal file
@ -0,0 +1,200 @@
|
||||
local irc = require("irc.main")
|
||||
|
||||
irc.msgs = {}
|
||||
local msgs = irc.msgs
|
||||
|
||||
local msg_meta = {}
|
||||
msg_meta.__index = msg_meta
|
||||
|
||||
function irc.Message(opts)
|
||||
opts = opts or {}
|
||||
setmetatable(opts, msg_meta)
|
||||
if opts.raw then
|
||||
opts:fromRFC1459(opts.raw)
|
||||
end
|
||||
return opts
|
||||
end
|
||||
|
||||
local tag_escapes = {
|
||||
[";"] = "\\:",
|
||||
[" "] = "\\s",
|
||||
["\0"] = "\\0",
|
||||
["\\"] = "\\\\",
|
||||
["\r"] = "\\r",
|
||||
["\n"] = "\\n",
|
||||
}
|
||||
|
||||
local tag_unescapes = {}
|
||||
for x, y in pairs(tag_escapes) do tag_unescapes[y] = x end
|
||||
|
||||
function msg_meta:toRFC1459()
|
||||
local s = ""
|
||||
|
||||
if self.tags then
|
||||
s = s.."@"
|
||||
for key, value in pairs(self.tags) do
|
||||
s = s..key
|
||||
if value ~= true then
|
||||
value = value:gsub("[; %z\\\r\n]", tag_escapes)
|
||||
s = s.."="..value
|
||||
end
|
||||
s = s..";"
|
||||
end
|
||||
-- Strip trailing semicolon
|
||||
s = s:sub(1, -2)
|
||||
s = s.." "
|
||||
end
|
||||
|
||||
s = s..self.command
|
||||
|
||||
local argnum = #self.args
|
||||
for i = 1, argnum do
|
||||
local arg = self.args[i]
|
||||
local startsWithColon = (arg:sub(1, 1) == ":")
|
||||
local hasSpace = arg:find(" ")
|
||||
if i == argnum and (hasSpace or startsWithColon) then
|
||||
s = s.." :"
|
||||
else
|
||||
assert(not hasSpace and not startsWithColon,
|
||||
"Message arguments can not be "
|
||||
.."serialized to RFC1459 format")
|
||||
s = s.." "
|
||||
end
|
||||
s = s..arg
|
||||
end
|
||||
|
||||
return s
|
||||
end
|
||||
|
||||
local function parsePrefix(prefix)
|
||||
local user = {}
|
||||
user.nick, user.username, user.host = prefix:match("^(.+)!(.+)@(.+)$")
|
||||
if not user.nick and prefix:find(".", 1, true) then
|
||||
user.server = prefix
|
||||
end
|
||||
return user
|
||||
end
|
||||
|
||||
function msg_meta:fromRFC1459(line)
|
||||
-- IRCv3 tags
|
||||
if line:sub(1, 1) == "@" then
|
||||
self.tags = {}
|
||||
local space = line:find(" ", 1, true)
|
||||
-- For each semicolon-delimited section from after
|
||||
-- the @ character to before the space character.
|
||||
for tag in line:sub(2, space - 1):gmatch("([^;]+)") do
|
||||
local eq = tag:find("=", 1, true)
|
||||
if eq then
|
||||
self.tags[tag:sub(1, eq - 1)] =
|
||||
tag:sub(eq + 1):gsub("\\([:s0\\rn])", tag_unescapes)
|
||||
else
|
||||
self.tags[tag] = true
|
||||
end
|
||||
end
|
||||
line = line:sub(space + 1)
|
||||
end
|
||||
|
||||
if line:sub(1, 1) == ":" then
|
||||
local space = line:find(" ", 1, true)
|
||||
self.prefix = line:sub(2, space - 1)
|
||||
self.user = parsePrefix(self.prefix)
|
||||
line = line:sub(space + 1)
|
||||
end
|
||||
|
||||
local pos
|
||||
self.command, pos = line:match("(%S+)()")
|
||||
line = line:sub(pos)
|
||||
|
||||
self.args = self.args or {}
|
||||
for pos, param in line:gmatch("()(%S+)") do
|
||||
if param:sub(1, 1) == ":" then
|
||||
param = line:sub(pos + 1)
|
||||
table.insert(self.args, param)
|
||||
break
|
||||
end
|
||||
table.insert(self.args, param)
|
||||
end
|
||||
end
|
||||
|
||||
function msgs.privmsg(to, text)
|
||||
return irc.Message({command="PRIVMSG", args={to, text}})
|
||||
end
|
||||
|
||||
function msgs.notice(to, text)
|
||||
return irc.Message({command="NOTICE", args={to, text}})
|
||||
end
|
||||
|
||||
function msgs.action(to, text)
|
||||
return irc.Message({command="PRIVMSG", args={to, ("\x01ACTION %s\x01"):format(text)}})
|
||||
end
|
||||
|
||||
function msgs.ctcp(command, to, args)
|
||||
s = "\x01"..command
|
||||
if args then
|
||||
s = ' '..args
|
||||
end
|
||||
s = s..'\x01'
|
||||
return irc.Message({command="PRIVMSG", args={to, s}})
|
||||
end
|
||||
|
||||
function msgs.kick(channel, target, reason)
|
||||
return irc.Message({command="KICK", args={channel, target, reason}})
|
||||
end
|
||||
|
||||
function msgs.join(channel, key)
|
||||
return irc.Message({command="JOIN", args={channel, key}})
|
||||
end
|
||||
|
||||
function msgs.part(channel, reason)
|
||||
return irc.Message({command="PART", args={channel, reason}})
|
||||
end
|
||||
|
||||
function msgs.quit(reason)
|
||||
return irc.Message({command="QUIT", args={reason}})
|
||||
end
|
||||
|
||||
function msgs.kill(target, reason)
|
||||
return irc.Message({command="KILL", args={target, reason}})
|
||||
end
|
||||
|
||||
function msgs.kline(time, mask, reason, operreason)
|
||||
local args = nil
|
||||
if time then
|
||||
args = {time, mask, reason..'|'..operreason}
|
||||
else
|
||||
args = {mask, reason..'|'..operreason}
|
||||
end
|
||||
return irc.Message({command="KLINE", args=args})
|
||||
end
|
||||
|
||||
function msgs.whois(nick, server)
|
||||
local args = nil
|
||||
if server then
|
||||
args = {server, nick}
|
||||
else
|
||||
args = {nick}
|
||||
end
|
||||
return irc.Message({command="WHOIS", args=args})
|
||||
end
|
||||
|
||||
function msgs.topic(channel, text)
|
||||
return irc.Message({command="TOPIC", args={channel, text}})
|
||||
end
|
||||
|
||||
function msgs.invite(channel, target)
|
||||
return irc.Message({command="INVITE", args={channel, target}})
|
||||
end
|
||||
|
||||
function msgs.nick(nick)
|
||||
return irc.Message({command="NICK", args={nick}})
|
||||
end
|
||||
|
||||
function msgs.mode(target, modes)
|
||||
-- We have to split the modes parameter because the mode string and
|
||||
-- each parameter are seperate arguments (The first command is incorrect)
|
||||
-- MODE foo :+ov Nick1 Nick2
|
||||
-- MODE foo +ov Nick1 Nick2
|
||||
local mt = irc.split(modes)
|
||||
return irc.Message({command="MODE", args={target, unpack(mt)}})
|
||||
end
|
||||
|
19
other_things/irc-old-save/irc/push-luadoc.sh
Normal file
19
other_things/irc-old-save/irc/push-luadoc.sh
Normal file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$TRAVIS_REPO_SLUG" == "JakobOvrum/LuaIRC" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||
|
||||
echo -e "Generating luadoc...\n"
|
||||
|
||||
git config --global user.email "travis@travis-ci.org"
|
||||
git config --global user.name "travis-ci"
|
||||
git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG} gh-pages > /dev/null
|
||||
|
||||
cd gh-pages
|
||||
git rm -rf ./doc
|
||||
sh ./generate.sh
|
||||
git add -f ./doc
|
||||
git commit -m "Lastest documentation on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages"
|
||||
git push -fq origin gh-pages > /dev/null
|
||||
|
||||
echo -e "Published luadoc to gh-pages.\n"
|
||||
fi
|
52
other_things/irc-old-save/irc/set.lua
Normal file
52
other_things/irc-old-save/irc/set.lua
Normal file
@ -0,0 +1,52 @@
|
||||
local select = require "socket".select
|
||||
|
||||
local m = {}
|
||||
local set = {}
|
||||
set.__index = set
|
||||
|
||||
function m.new(t)
|
||||
t.connections = {}
|
||||
t.sockets = {}
|
||||
return setmetatable(t, set)
|
||||
end
|
||||
|
||||
function set:add(connection)
|
||||
local socket = connection.socket
|
||||
insert(self.sockets, socket)
|
||||
|
||||
self.connections[socket] = connection
|
||||
insert(self.connections, connection)
|
||||
end
|
||||
|
||||
function set:remove(connection)
|
||||
local socket = connection.socket
|
||||
self.connections[socket] = nil
|
||||
for k, s in ipairs(self.sockets) do
|
||||
if socket == s then
|
||||
remove(self.sockets, k)
|
||||
remove(self.connections, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function set:select()
|
||||
local read, write, err = select(self.sockets, nil, self.timeout)
|
||||
|
||||
if read then
|
||||
for k, socket in ipairs(read) do
|
||||
read[k] = self.connections[socket]
|
||||
end
|
||||
end
|
||||
|
||||
return read, err
|
||||
end
|
||||
|
||||
-- Select - but if it times out, it returns all connections.
|
||||
function set:poll()
|
||||
local read, err = self:select()
|
||||
return err == "timeout" and self.connections or read
|
||||
end
|
||||
|
||||
return m
|
||||
|
116
other_things/irc-old-save/irc/util.lua
Normal file
116
other_things/irc-old-save/irc/util.lua
Normal file
@ -0,0 +1,116 @@
|
||||
local irc = require("irc.main")
|
||||
|
||||
function irc.parseNick(conn, nick)
|
||||
local access = {}
|
||||
irc.updatePrefixModes(conn)
|
||||
local namestart = 1
|
||||
for i = 1, #nick - 1 do
|
||||
local c = nick:sub(i, i)
|
||||
if conn.prefixmode[c] then
|
||||
access[conn.prefixmode[c]] = true
|
||||
else
|
||||
namestart = i
|
||||
break
|
||||
end
|
||||
end
|
||||
access.op = access.o
|
||||
access.voice = access.v
|
||||
local name = nick:sub(namestart)
|
||||
return access, name
|
||||
end
|
||||
|
||||
function irc.updatePrefixModes(conn)
|
||||
if conn.prefixmode and conn.modeprefix then
|
||||
return
|
||||
end
|
||||
conn.prefixmode = {}
|
||||
conn.modeprefix = {}
|
||||
if conn.supports.PREFIX then
|
||||
local modes, prefixes = conn.supports.PREFIX:match("%(([^%)]*)%)(.*)")
|
||||
for i = 1, #modes do
|
||||
conn.prefixmode[prefixes:sub(i, i)] = modes:sub(i, i)
|
||||
conn.modeprefix[ modes:sub(i, i)] = prefixes:sub(i, i)
|
||||
end
|
||||
else
|
||||
conn.prefixmode['@'] = 'o'
|
||||
conn.prefixmode['+'] = 'v'
|
||||
conn.modeprefix['o'] = '@'
|
||||
conn.modeprefix['v'] = '+'
|
||||
end
|
||||
end
|
||||
|
||||
-- mIRC markup scheme (de-facto standard)
|
||||
irc.color = {
|
||||
black = 1,
|
||||
blue = 2,
|
||||
green = 3,
|
||||
red = 4,
|
||||
lightred = 5,
|
||||
purple = 6,
|
||||
brown = 7,
|
||||
yellow = 8,
|
||||
lightgreen = 9,
|
||||
navy = 10,
|
||||
cyan = 11,
|
||||
lightblue = 12,
|
||||
violet = 13,
|
||||
gray = 14,
|
||||
lightgray = 15,
|
||||
white = 16
|
||||
}
|
||||
|
||||
local colByte = string.char(3)
|
||||
setmetatable(irc.color, {__call = function(_, text, colornum)
|
||||
colornum = (type(colornum) == "string" and
|
||||
assert(irc.color[colornum], "Invalid color '"..colornum.."'") or
|
||||
colornum)
|
||||
return table.concat{colByte, tostring(colornum), text, colByte}
|
||||
end})
|
||||
|
||||
local boldByte = string.char(2)
|
||||
function irc.bold(text)
|
||||
return boldByte..text..boldByte
|
||||
end
|
||||
|
||||
local underlineByte = string.char(31)
|
||||
function irc.underline(text)
|
||||
return underlineByte..text..underlineByte
|
||||
end
|
||||
|
||||
function irc.checkNick(nick)
|
||||
return nick:find("^[a-zA-Z_%-%[|%]%^{|}`][a-zA-Z0-9_%-%[|%]%^{|}`]*$") ~= nil
|
||||
end
|
||||
|
||||
function irc.defaultNickGenerator(nick)
|
||||
-- LuaBot -> LuaCot -> LuaCou -> ...
|
||||
-- We change a random character rather than appending to the
|
||||
-- nickname as otherwise the new nick could exceed the ircd's
|
||||
-- maximum nickname length.
|
||||
local randindex = math.random(1, #nick)
|
||||
local randchar = string.sub(nick, randindex, randindex)
|
||||
local b = string.byte(randchar)
|
||||
b = b + 1
|
||||
if b < 65 or b > 125 then
|
||||
b = 65
|
||||
end
|
||||
-- Get the halves before and after the changed character
|
||||
local first = string.sub(nick, 1, randindex - 1)
|
||||
local last = string.sub(nick, randindex + 1, #nick)
|
||||
nick = first .. string.char(b) .. last -- Insert the new charachter
|
||||
return nick
|
||||
end
|
||||
|
||||
function irc.capitalize(text)
|
||||
-- Converts first character to upercase and the rest to lowercase.
|
||||
-- "PING" -> "Ping" | "hello" -> "Hello" | "123" -> "123"
|
||||
return text:sub(1, 1):upper()..text:sub(2):lower()
|
||||
end
|
||||
|
||||
function irc.split(str, sep)
|
||||
local t = {}
|
||||
for s in str:gmatch("%S+") do
|
||||
table.insert(t, s)
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
Reference in New Issue
Block a user