Since there isn't any script forum yet for script i had to put this in here
Here is a awsome startup script made by ATAG that makes lua scripts easier to manage
a additional script is needed to run this startup script and that script is called libsimplepickle.lua
please replace the current startup script with this one its really so much better then the old startup script
--[[ startup.lua: version 2.1.2d 2009/01/22
modded by ATAG - atagster [at] gmail [dot] com
2.1.2d:
fixed: error on missing libsimplepickle.lua - reported by [NH]Nando
2.1.2c:
first public release
NMDC Listeners (events):
chat = normal chat message (you won't get your own messages)
function chat( hub, user, "message" )
DISCARDABLE:
* return non-nil to hide the msg from BCDC++
unknownchat = incoming messages displayed without any nick
function unknownchat( hub, "message" )
DISCARDABLE
ownChat = normal chat message from yourself (incoming from the hub)
function ownChat( hub, "message" )
DISCARDABLE
pm = normal pm message
function pm( hub, user, "message" )
DISCARDABLE
hubPm = pm message with a different prefix than the nick in the From field
function hubPm( hub, user, "message which may include a <nickname>" )
DISCARDABLE
userConnected = a user connected (or rather.. the first getUser call was made)
function userConnected( hub, user )
userMyInfo = a myinfo message from a user, use this as "userConnected"
function userMyInfo( hub, user, "$MyINFO $ALL ... 1234$|" )
DISCARDABLE
userQuit = a quit message from a user
function userQuit( hub, nick )
DISCARDABLE
raw = a full message
function raw( hub, "line" )
DISCARDABLE (message won't get parsed.. no other listeners will be called)
ADC Listeners:
adcChat = normal chat message (you won't get your own messages).
function adcChat( hub, user, "message", me_msg )
DISCARDABLE:
* return non-nil to hide the msg from BCDC++,
* me_msg is true if a /me-style message is sent
adcOwnChat = normal chat message from yourself (incoming from the hub)
function adcOwnChat( hub, "message", me_msg )
DISCARDABLE
adcPm = normal pm message
function adcPm( hub, user, "message", me_msg )
DISCARDABLE
groupPm = pm message with a different reply-sid than the one who talks (probably chatroom or bot)
function groupPm( hub, user, "message", reply_sid, me_msg )
DISCARDABLE
userInf = an INF message from a user
function userInf( hub, user, flags )
flags is a table where all named flags are stored (ie: flags["NI"], flags["I4"], ...)
DISCARDABLE
adcUserCon = a user connected (or rather.. the first getUser call was made)
function adcUserCon( hub, user )
adcUserQui = a quit message from a user
function adcUserQui( hub, sid, flags )
flags is a table where all named flags are stored (ie: flags["ID"], flags["MS"], ...)
Common Listeners:
ownChatOut = normal chat message from yourself (outgoing to the hub)
function ownChatOut( hub, "message" )
DISCARDABLE
connected = connecting to a hub (many functions may be unavailable (return nil))
function connected( hub )
disconnected = disconnected from a hub
function disconnected( hub )
timer = called every second (if DC():RunTimer(1) is called), use
dcpp:getHubs()[k]:getAddress() or :getUrl() to select a hub
function timer()
clientIn = peer to peer line oriented transfer control input, userp is a pointer
(lightuserdata)
function clientIn( userp, "line" )
DISCARDABLE (returning non-nil kills the connection)
clientOut = peer to peer line oriented transfer control output, userp is a pointer
(lightuserdata)
function clientOut( userp, "line" )
DISCARDABLE (returning non-nil kills the connection)
Example listener:
function chat( hub, user, text )
local s = string.lower( text )
if string.find( s, "[^a-z]bier+[^a-z]" ) or string.find( s, "[^a-z]biertje[^a-z]" ) then
hub:sendChat( "bier? ja lekker! :)" )
end
end
Example Usercommand:
function connected( hub )
if ( hub:getProtocol() ~= "adc" ) then
hub:injectChat( '$UserCommand 1 2 Ignore$%[lua:scriptMan:Run("AddUser","!%!{userNI!}")]||' )
hub:injectChat( '$UserCommand 1 2 Unignore$%[lua:scriptMan:Run("RmUser","!%!{userNI!}")]||' )
end
end
]]
DC():PrintDebug( " ** Started startup.lua **" )
--/////////////////////////////////////
--// Helper functions
--/////////////////////////////////////
if not dcu then
dcu = {}
end
dcu.NmdcEscape = function(this, msg )
msg = msg:gsub( "[%$|]", function(s) return "&#"..string.byte(s)..";" end )
return msg
end
dcu.AdcEscape = function(this, msg, inverse)
msg = string.gsub(msg, "\r", "")
local ret = ""
if inverse then
local replacetable = {
["\\\\"] = [[\]],
["\\s"] = [[ ]],
["\\n"] = "\n"
}
local skip = false
for k = 1, #msg do
if skip then
skip = false
else
local c = msg:sub( k, k + 1)
if replacetable[c] then
ret = ret .. replacetable[c]
skip = true
else
ret = ret .. c:sub(1, 1)
end
end
end
else
local replacetable = {
["\\"] = [[\\]],
[" "] = [[\s]],
["\n"] = [[\n]]
}
for k = 1, #msg do
local c = msg:sub( k, k)
if replacetable[c] then
ret = ret .. replacetable[c]
else
ret = ret .. c
end
end
end
return ret
end
--// Checks if the given decimal number has the 2^exp bit set
dcu.BBit = function(this, num, exp)
if string.find( math.floor(num / 2^exp), "[13579]$") then
return true
end
return false
end
--/////////////////////////////////////
--// Hub manager
--/////////////////////////////////////
if not dcpp or dcpp._init_me_anyway == true then
dcpp = {}
dcpp._hubs = {}
dcpp._listeners = { id = {} }
end
dcpp.addHub = function( this, hub, isitadc )
if not this._hubs[hub] then
-- DC():PrintDebug( "Hub added (id = "..tostring( hub )..")" )
if isitadc then
this._hubs[hub] = createAdcHub( hub )
DC():PrintDebug( "ADC hub added (id = " .. tostring( hub ) ..")" )
else
this._hubs[hub] = createNmdcHub( hub )
end
local h = dcpp:getHub( hub )
scriptMan:Run( "connected", h )
return this._hubs[hub]
else
--DC():PrintDebug( "Tried to add existing hub on: "..this._hubs[hub]:getHubName()..
-- " (id = "..tostring( hub )..")" )
return nil
end
end
dcpp.getHub = function( this, hub )
if this._hubs[hub] then
return this._hubs[hub]
else
--DC():PrintDebug( "Tried to fetch an unknown hub (id = "..tostring( hub )..")" )
return this:addHub( hub ):setPartial() -- tell the object that we missed the logon
end
end
dcpp.getHubs = function( this )
return this._hubs
end
dcpp.hasHub = function( this, hub )
if this._hubs[hub] then
return 1
else
return nil
end
end
dcpp.findHub = function( this, url )
for k, h in pairs(this._hubs) do
if h:getUrl() == url then
return h
end
end
return false
end
dcpp.removeHub = function( this, hub )
if this._hubs[hub] then
--DC():PrintDebug( "Hub removed: "..this._hubs[hub]:getHubName().." (id = "..tostring( hub )..")" )
local h = dcpp:getHub( hub )
scriptMan:Run( "disconnected", h )
this._hubs[hub]:destroy()
this._hubs[hub] = nil
else
--DC():PrintDebug( "Tried to remove non-existent hub (id = "..tostring( hub )..")" )
end
end
dcpp.listHubs = function( this )
DC():PrintDebug( "** Listing hubs **" )
for k,v in pairs(this._hubs) do
DC():PrintDebug( tostring( k ).." ("..v:getHubName()..")" )
end
end
dcpp.setListener = function( this, ltype, id, func )
-- load func into the caller's environment
getfenv(2)[ltype] = func
end
dcpp.getListeners = function( this, ltype )
-- only for backward compatibility :)
end
--/////////////////////////////////////
--// Hub object
--/////////////////////////////////////
function createAdcHub( hubid )
local hub = {}
hub._id = hubid
hub._mySID = nil
hub._myNick = nil
hub._myCID = nil
hub._nick = nil
hub._description = nil
hub._users = {}
hub._uptime = os.time()
hub.getId = function( this )
return this._id
end
hub.getUptime = function( this )
return ( os.time() - hub._uptime ) / 60
end
hub.getProtocol = function( this )
return "adc"
end
hub.getAddress = function( this )
return DC():GetHubIpPort( this._id )
end
hub.getHubName = function( this )
--// TODO: Shall we return with NI or DE? or both?
--// For now just returning the nick with the url
if this._nick then
return this._nick .. " ("..this:getUrl()..")"
else
return this:getUrl()
end
end
hub.getUrl = function( this )
return DC():GetHubUrl( this._id )
end
hub.getOwnNick = function( this )
return this._myNick
end
hub.setOwnNick = function( this, newnick )
this._myNick = newnick
DC():PrintDebug( " [STATUS] Own nick set: " .. newnick )
end
hub.getOwnSid = function( this )
if this._mySID then
return this._mySID
end
DC():PrintDebug( " [" .. this:getUrl() .."] Own SID not set, your scripts are failing. Reconnect please." )
end
hub.getOwnCid = function( this )
if this._myCID then
return this._myCID
end
DC():PrintDebug( " [" .. this:getUrl() .."] Own CID not set, your scripts are failing. Reconnect please." )
end
hub.getUser = function( this, sid, inf )
local newuser = false
if sid == "HUB9" and inf then
-- INF is about the hub itself
local params = {}
string.gsub(inf, "([^ ]+)", function(s) table.insert(params, s) end )
for k in pairs(params) do
local name = string.sub( params[k], 1, 2 )
if name == "NI" then
local NI = dcu:AdcEscape(string.sub( params[k], 3), true)
this._nick = NI
DC():PrintDebug(" [STATUS] HUB nick set: " .. NI )
elseif name == "DE" then
local DE = dcu:AdcEscape(string.sub( params[k], 3), true)
this._description = DE
DC():PrintDebug(" [STATUS] HUB description set: " .. DE )
end
end
end
if not this._users[sid] then
this._users[sid] = createAdcUser( this, sid )
newuser = true
if this:getUptime() >= 2 then -- start sending messages AFTER logon
scriptMan:Run( "adcUserCon", this, this._users[sid] )
end
end
local r = this._users[sid]
if inf then
local params = {}
string.gsub(inf, "([^ ]+)", function(s) table.insert(params, s) end )
for k in pairs(params) do
local name = string.sub( params[k], 1, 2 )
if name == "ID" then
local ID = string.sub( params[k], 3)
r:setCid(ID)
if sid == this._mySID then
this._myCID = ID
DC():PrintDebug(" [STATUS] Own CID set: " .. ID )
end
elseif name == "CT" then
local CT = string.sub( params[k], 3)
r:processCt(CT)
elseif name == "I4" then
local I4 = string.sub( params[k], 3)
r:setIp(I4)
elseif name == "NI" then
local NI = dcu:AdcEscape(string.sub( params[k], 3), true)
if not newuser then
local oldNI = r:getNick()
r:setNick(NI)
this:addLine( oldNI .. " is now known as " .. NI )
else
r:setNick(NI)
end
if sid == this._mySID then
this:setOwnNick(NI)
end
end
end
end
return r
end
hub.removeUser = function( this, sid )
this._users[sid] = nil
end
hub.isOp = function( this, sid )
if this._users[sid] then
return this._users[sid]._op
end
return nil
end
hub.getSidbyNick = function( this, nick )
for k in pairs(this._users) do
if this._users[k]._nick == nick then
return k
end
end
return nil
end
hub.getSidbyCid = function( this, cid )
for k in pairs(this._users) do
if this._users[k]._cid == cid then
return k
end
end
return nil
end
hub.sendChat = function( this, msg )
local ownSid = this:getOwnSid()
msg = dcu:AdcEscape( msg )
DC():SendHubMessage( this:getId(), "BMSG " .. ownSid .. " " .. msg .. "\n" )
end
hub.injectChat = function( this, msg )
DC():PrintDebug(" [WARNING] Your scripts trying to use hub:injectChat on ADC hub. Please use hub:injectMessage() to inject an ADC message or hub:addLine() to inject a chat line." )
-- hub:injectMessage( msg )
end
hub.injectMessage = function( this, msg )
DC():InjectHubMessageADC( this:getId(), msg )
end
hub.addLine = function( this, msg, fmt )
--// TODO: need a function which adds a chat line without nick
msg = dcu:AdcEscape( msg )
DC():InjectHubMessageADC( this:getId(), "ISTA 000 " .. msg )
end
hub.sendPrivMsgTo = function( this, victimSid, msg_unescaped, hideFromSelf )
local ownSid = this:getOwnSid()
local msg = dcu:AdcEscape( msg_unescaped )
if ownSid then
if hideFromSelf then
DC():SendHubMessage( this:getId(), "DMSG ".. ownSid .. " " .. victimSid .." " .. msg .. " PM" .. ownSid .."\n" )
else
DC():SendHubMessage( this:getId(), "EMSG ".. ownSid .. " " .. victimSid .." " .. msg .. " PM" .. ownSid .."\n" )
end
end
end
hub.injectPrivMsg = function( this, victimSid, fromSid, msg )
DC():InjectHubMessageADC( this:getId(), "DMSG " .. fromSid .." ".. victimSid .." ".. msg .. " PM" .. victimSid .. "\n" )
end
hub.findUsers = function( this, nick, notag )
-- you get a possibly empty table of users
if not notag then
return { this._users[this:getSidbyNick(nick)] }
else
local list = {}
for k in pairs(this._users) do
local ret,c,n = string.find( this._users[k]._nick, "^%[.*%](.-)$" )
if n == nick then
table.insert( list, this._users[k] )
end
end
return list
end
end
hub.destroy = function( this )
end
--// events
hub.onChatMessage = function( this, user, text, me_msg )
return scriptMan:Run( "adcChat", this, user, text, me_msg )
end
hub.onChatFromSelf = function( this, text, me_msg )
return scriptMan:Run( "adcOwnChat", this, text, me_msg )
end
hub.onINF = function( this, user, flags )
return scriptMan:Run( "userInf", this, user, flags )
end
hub.onQUI = function( this, sid, flags )
scriptMan:Run( "adcUserQui", this, sid, flags )
end
hub.onPrivateMessage = function( this, user, targetSid, replySid, text, me_msg )
if targetSid == this:getOwnSid() then
if user:getSid() == replySid then
return scriptMan:Run( "adcPm", this, user, text, me_msg )
else
return scriptMan:Run( "groupPm", this, user, replySid, text, me_msg )
end
end
end
hub.attention = function( this )
DC():HubWindowAttention( this:getId() )
end
return hub
end
function createNmdcHub( hubid )
local hub = {}
hub._id = hubid
hub._users = {}
hub._name = nil
hub._myNick = nil
hub._partial = nil
hub._gotOpList = nil
hub._uptime = os.time()
hub._hubUC = {}
hub._customUC = {}
hub.getId = function( this )
return this._id
end
hub.getProtocol = function( this )
return "nmdc"
end
hub.getUptime = function( this )
return ( os.time() - hub._uptime ) / 60
end
hub.getUser = function( this, nick, op )
if not this._users[nick] then
this._users[nick] = createNmdcUser( this, nick )
if this:getUptime() >= 2 then -- start sending messages AFTER logon
scriptMan:Run( "userConnected", this, this._users[nick] )
end
end
local r = this._users[nick]
if op then
r:setOp( true )
r:setClass( "op" )
this._gotOpList = 1
end
return r
end
hub.findUsers = function( this, nick, notag )
-- you get a possibly empty table of users
if not notag then
return { this._users[nick] }
else
local list = {}
for k,v in pairs(this._users) do
local ret,c,n = string.find( k, "^%[.*%](.-)$" )
if n == nick then
table.insert( list, v )
end
end
return list
end
end
hub.gotOpList = function( this )
return this._gotOpList
end
hub.isOp = function( this, nick )
if this._users[nick] and this._users[nick]:isOp() then
return 1
end
end
hub.removeUser = function( this, nick )
this._users[nick] = nil
end
hub.setPartial = function( this )
--// we're most likely missing logon info
this._partial = 1
end
hub.isPartial = function( this )
--// are we missing logon info?
return this._partial
end
hub.setHubName = function( this, msg )
this._name = msg
end
hub.getAddress = function( this )
return DC():GetHubIpPort( this._id )
end
hub.getUrl = function( this )
return DC():GetHubUrl( this._id )
end
hub.getHubName = function( this )
if this._name then
return this._name.." ("..this:getUrl()..")"
else
return this:getUrl()
end
end
hub.setOwnNick = function( this, nick )
this._myNick = nick
end
hub.getOwnNick = function( this )
if not this:isPartial() then
return this._myNick
end
DC():PrintDebug( "[" .. this:getUrl() .."] Your scripts are failing. "..
"Own nick not set. Reconnect please." )
end
hub.destroy = function( this )
end
hub.sendChat = function( this, msg )
local ownNick = this:getOwnNick()
msg = dcu:NmdcEscape( msg )
if ownNick then
DC():SendHubMessage( this:getId(), "<"..ownNick.."> "..msg.."|" )
end
end
hub.injectChat = function( this, msg, skipusercommand )
DC():InjectHubMessage( this:getId(), msg )
-- test if it's usercommand
if ( string.sub(msg, 1, 13) == "$UserCommand " ) and (not skipusercommand) then
this:customUC( msg )
end
end
hub.addLine = function( this, msg, fmt )
if not fmt then
msg = "*** " .. msg
end
DC():InjectHubMessage( this:getId(), msg )
end
hub.sendPrivMsgTo = function( this, victim, msg, hideFromSelf )
local ownNick = this._myNick
msg = dcu:NmdcEscape( msg )
if ownNick then
DC():SendHubMessage( this:getId(), "$To: "..victim.." From: "..ownNick.." $"..msg.."|" )
if not hideFromSelf then
this:injectPrivMsg( victim, ownNick, msg )
end
end
end
hub.injectPrivMsg = function( this, from, to, msg )
DC():InjectHubMessage( this:getId(), "$To: "..to.." From: "..from.." $"..msg )
end
hub.injectPrivMsgFmt = function( this, from, to, msg )
this:injectPrivMsg( from, to, "<"..from.."> "..msg )
end
hub.attention = function( this )
DC():HubWindowAttention( this:getId() )
end
--///////////////////////////
--// $UserCommand manager
--///////////////////////////
-- Todo: context sensitivitiy at UC 255
hub.hubUC = function( this, msg )
local uc_type = string.gsub( msg, "%$UserCommand (%d+) .+", "%1")
-- DC():PrintDebug( "UserCommand " .. uc_type .. " arrived from " .. this:getHubName() .. " : " .. msg)
if uc_type == "255" then
-- clear user command list and resend our own commands to prevent it from disappearing
-- DC():PrintDebug( "Clearing Hub UC list.." )
this:clearHubUCList()
-- DC():PrintDebug( "Resending Custom commands.." )
this:reSendCustomUC()
else
-- add usercommands to UClist
-- DC():PrintDebug( "Adding hubUC.." )
this:addHubUC( msg )
end
return true
end
hub.customUC = function ( this, msg )
local uc_type = string.gsub( msg, "%$UserCommand (%d+) .+", "%1")
-- DC():PrintDebug( "UserCommand " .. uc_type .. " arrived from a script: " .. msg)
if uc_type == "255" then
-- clear own user command list and resend hub usercommands to prevent it from disappearing
this:clearCustomUCList()
this:reSendHubUC()
else
-- add usercommands to UClist
this:addCustomUC( msg )
end
return true
end
hub.addHubUC = function( this, msg )
table.insert( this._hubUC, msg )
return true
end
hub.addCustomUC = function( this, msg)
table.insert( this._customUC, msg )
return true
end
hub.clearHubUCList = function( this )
this._hubUC = {}
return true
end
hub.clearCustomUCList = function( this )
this._customUC = {}
return true
end
hub.reSendCustomUC = function( this )
for k in pairs(this._customUC) do
hub:injectChat( this._customUC[k] , true )
-- DC():PrintDebug("Sending custom uc from stored table: " .. this._customUC[k] )
end
return true
end
hub.reSendHubUC = function( this )
for k in pairs(this._hubUC) do
hub:injectChat( this._hubUC[k] , true)
end
return true
end
--////////////////
--// Own functions
--////////////////
hub.onRaw = function( this, msg )
return scriptMan:Run( "raw", this, msg )
end
hub.onSearch = function( this, msg )
--DC():PrintDebug( this:getHubName().."> "..msg )
end
hub.onHello = function( this, user, msg )
end
hub.onMyInfo = function( this, user, msg )
return scriptMan:Run( "userMyInfo", this, user, msg )
end
hub.onQuit = function( this, nick, msg )
return scriptMan:Run( "userQuit", this, nick )
end
hub.onHubName = function( this, hubname, msg )
end
hub.onPrivateMessage = function( this, user, to, prefix, text, full )
if to == this:getOwnNick() then
if prefix == "<"..user:getNick().."> " then
return scriptMan:Run( "pm", this, user, text )
else
return scriptMan:Run( "hubPm", this, user, text )
end
end
end
hub.onChatMessage = function( this, user, text )
return scriptMan:Run( "chat", this, user, text ) or scriptMan:Run( "ChatArrival", this, user, text )
end
hub.onUnknownChatMessage = function( this, text )
return scriptMan:Run( "unknownchat", this, text )
end
hub.onChatFromSelf = function( this, text )
return scriptMan:Run( "ownChat", this, text )
end
return hub
end
--/////////////////////////////////////
--// User object
--/////////////////////////////////////
function createNmdcUser( hub, nick )
local user = {}
user._hub = hub
user._nick = nick
user._op = false
user._ip = ""
user._class = "user"
user._handled_messages = {} -- flood protection
setmetatable( user, {__index = {
sNick = user._nick,
bOperator = function() return user._op end,
sIP = function() return user._ip end,
}
})
user.getProtocol = function( this )
return "nmdc"
end
user.setOp = function( this, op )
this._op = op
return this
end
user.isOp = function( this )
return this._op
end
user.setClass = function( this, param )
this._class = param
return this
end
user.getClass = function( this )
return this._class
end
user.setIp = function( this, ip )
this._ip = ip
end
user.getIp = function( this )
return this._ip
end
user.getNick = function( this )
return this._nick
end
user.sendPrivMsgFmt = function( this, msg, hideFromSelf )
local ownNick = this._hub:getOwnNick()
if ownNick then
this._hub:sendPrivMsgTo( this._nick, "<"..ownNick.."> "..msg, hideFromSelf )
end
return this
end
user.setMsgHandled = function( this, which )
this._handled_messages[which] = 1
return this
end
user.msgHandled = function( this, which )
return this._handled_messages[which]
end
return user
end
function createAdcUser( hub, sid )
local user = {}
user._sid = sid
user._cid = ""
user._hub = hub
user._nick = ""
user._op = false
user._bot = false
user._registered = false
user._hubitself = false
user._class = "user"
user._ip = ""
user._handled_messages = {} -- flood protection
user.getProtocol = function( this )
return "adc"
end
user.setOp = function( this, op )
this._op = op
return this
end
user.isOp = function( this )
return this._op
end
user.processCt = function( this, param )
local num = tonumber(param)
if num then
--// Init
this._class = "user"
--// 2^0: bot
if dcu:BBit(num, 0) then
this:setBot(true)
DC():PrintDebug("BOT set: " .. this:getSid())
else
this:setBot(false)
end
--// 2^1: registered
if dcu:BBit(num, 1) then
this:setReg(true)
else
this:setReg(false)
end
--// 2^2, 2^3, 2^4: some type of operator
if dcu:BBit(num, 2) or dcu:BBit(num, 3) or dcu:BBit(num, 4) then
this:setOp(true)
if dcu:BBit(num, 2) then
this._class = "op"
elseif dcu:BBit(num, 3) then
this._class = "su"
else
this._class = "owner"
end
else
this:setOp(false)
end
if dcu:BBit(num, 5) then
this:setHub(true)
this._class = "hub"
else
this:setHub(false)
end
else
--// Empty CT field should cause all properties gone
this:setBot(false)
this:setOp(false)
this:setReg(false)
this:setHub(false)
this._class = "user"
end
DC():PrintDebug("CLASS: " .. this._class .. " [" .. tostring(param) .. "]" )
return this
end
--// Possible values: "user", "op", "su", "owner", "hub"
user.getClass = function( this )
return this._class
end
user.setBot = function(this, bot)
this._bot = bot
return this
end
user.isBot = function(this)
return this._bot
end
user.setReg = function(this, registered)
this._registered = registered
return this
end
user.isReg = function(this)
return this._registered
end
user.setHub = function(this, hubitself)
this._hubitself = hubitself
return this
end
user.isHub = function(this)
return this._hubitself
end
user.setIp = function( this, ip )
this._ip = ip
end
user.getIp = function( this )
return this._ip
end
user.setCid = function( this, cid )
this._cid = cid
end
user.getCid = function( this )
return this._cid
end
user.getSid = function( this )
return this._sid
end
user.getNick = function( this )
return this._nick
end
user.setNick = function( this, nick )
this._nick = nick
-- DC():PrintDebug("Nick set: " .. nick )
end
user.sendPrivMsg = function( this, msg, hideFromSelf )
local victimSid = this:getSid()
this._hub:sendPrivMsgTo( victimSid, msg, hideFromSelf )
return this
end
-- Backward compatibility
user.sendPrivMsgFmt = user.sendPrivMsg
user.setMsgHandled = function( this, which )
this._handled_messages[which] = 1
return this
end
user.msgHandled = function( this, which )
return this._handled_messages[which]
end
return user
end
--/////////////////////////////////////
--// Handlers
--/////////////////////////////////////
nmdch = {}
function nmdch.DataArrival( hub, msg )
local h = dcpp:getHub( hub )
--// If we missed the logon, we really have no business here,
--// modify only if you really have to.
--// Note that if not h:isPartial and not h:getOwnNick(),
--// functions requiring an ownNick will silently fail.
if h:isPartial() then
return
end
--// raw/unparsed message
if h:onRaw( msg ) then
return scriptMan:Run( "UnknownArrival", msg )
end
--// parse message and fire appropriate
local ret,c,cmd = string.find( msg, "^%$([^ ]+)" )
if ret then
if cmd == "Search" then
return h:onSearch( msg )
elseif cmd == "Hello" then
local nick = string.sub( msg, 8 )
if not h:getOwnNick() then
h:setOwnNick( nick ) -- don't trust this nick on h:isPartial()
end
return h:onHello( h:getUser( nick ), msg )
elseif cmd == "MyINFO" and string.sub( msg, 1, 13 ) == "$MyINFO $ALL " then
local nick = string.sub( msg, 14, string.find( msg, " ", 14, 1 ) - 1 )
return h:onMyInfo( h:getUser( nick ), msg )
elseif cmd == "Quit" then
local nick = string.sub( msg, 7 )
h:removeUser( nick )
return h:onQuit( nick, msg )
elseif cmd == "HubName" then
local hubname = string.sub( msg, 10 )
h:setHubName( hubname )
return h:onHubName( hubname, msg )
elseif cmd == "OpList" then
for nick in string.gfind( string.sub( msg, 9 ), "[^$]+") do
h:getUser( nick, 1 )
end
return nil
elseif cmd == "UserIP" then
local nick,ip
for combo in string.gfind( string.sub( msg, 9 ), "[^$]+") do
ret,c,nick,ip = string.find( combo, "^(%S+) (%S+)$" )
if ret then
h:getUser( nick ):setIp( ip )
end
end
return nil
elseif cmd == "UserCommand" then
h:hubUC( msg )
--elseif string.sub( msg, 1, 10 ) == "$NickList " then
-- for nick in string.gfind( string.sub( msg, 9, -1), "[^$]+") do
-- h:getUser( nick )
-- end
-- return nil
elseif cmd == "To:" then
local ret,c,to,from,fulltext = string.find( msg, "^%$To: ([^ ]+) From: ([^ ]+) %$(.*)$" )
if ret then
local ret,c,prefix,text = string.find( fulltext, "^(%b<> )(.*)$" )
if ret then
return h:onPrivateMessage( h:getUser( from ), to, prefix, text, msg )
else
return h:onPrivateMessage( h:getUser( from ), to, nil, fulltext, msg )
end
end
end
elseif string.sub( msg, 1, 1 ) == "<" then
local ret,c,nick,text = string.find( msg, "^<([^>]+)> (.*)$" )
if ret and h:getOwnNick() then
if nick ~= h:getOwnNick() then -- don't be flooding mainchat now..
return h:onChatMessage( h:getUser( nick ), text )
else
return h:onChatFromSelf( text )
end
end
elseif msg ~= "" then
return h:onUnknownChatMessage(msg)
end
end
function dcpp.UserDataIn( user, msg )
return scriptMan:Run( "clientIn", user, msg )
end
function dcpp.UserDataOut( user, msg )
return scriptMan:Run( "clientOut", user, msg )
end
function dcpp.OnCommandEnter( hub, text )
local h = dcpp:getHub( hub )
return scriptMan:Run( "ownChatOut", h, text )
end
function dcpp.OnTimer()
-- Called every second.
return scriptMan:Run( "timer" )
end
function nmdch.OnHubAdded( hub )
dcpp:addHub( hub, false )
end
function nmdch.OnHubRemoved( hub )
dcpp:removeHub( hub )
end
adch = {}
function adch.DataArrival( hub, msg )
if msg == "" then
return nil
end
local h = dcpp:getHub( hub )
local params = {}
string.gsub(msg, "([^ ]+)", function(s) table.insert(params, s) end )
local mtype = string.sub(params[1], 1, 1)
local cmd = string.sub(params[1], 2, 4)
local sid, targetSid, parameters = false, false, ""
if mtype == "I" then
parameters = string.sub( msg, 6)
sid = "HUB9"
elseif mtype == "B" then
parameters = string.sub( msg, 11)
sid = params[2]
elseif mtype == "D" or mtype == "E" then
parameters = string.sub( msg, 16 )
sid = params[2]
targetSid = params[3]
end
-- Building flags table
local flags = {}
string.gsub(parameters, "([^ ]+)", function(s) flags[string.sub(s, 1, 2)] = dcu:AdcEscape( string.sub(s, 3), true ) end )
if cmd == "SID" then
DC():PrintDebug( "[STATUS] SID received: " .. params[2] )
h._mySID = params[2]
elseif cmd == "QUI" then
h:removeUser( params[2] )
h:onQUI( params[2], flags )
elseif cmd == "INF" then
local u = h:getUser( sid, parameters )
return h:onINF( u, flags )
elseif cmd == "MSG" then
local pm, replySid, me_msg = false, false, false
local tmp = {}
string.gsub(parameters, "([^ ]+)", function(s) table.insert(tmp, s) end )
local text = dcu:AdcEscape(tmp[1], true)
tmp[1] = nil
-- Check for named parameters
for k in pairs(tmp) do
local name = string.sub(tmp[k], 1,2)
local value = string.sub(tmp[k], 3)
if name == "ME" then
if value == "1" then
me_msg = true
end
elseif name == "PM" then
pm = true
replySid = value
end
end
if pm then
return h:onPrivateMessage( h:getUser( sid ), targetSid, replySid, text, me_msg )
else
if sid ~= h:getOwnSid() then -- don't be flooding mainchat now..
return h:onChatMessage( h:getUser( sid ), text, me_msg )
else
return h:onChatFromSelf( text, me_msg )
end
end
end
end
function adch.OnHubAdded( hub )
dcpp:addHub( hub, true )
end
function adch.OnHubRemoved( hub )
dcpp:removeHub( hub )
end
--/////////////////////////////////////
--// Utility functions
--/////////////////////////////////////
function SendActiveSearchResult( hub, ip_port, search_nick, filename, filesize, open_slots, total_slots )
DC():SendUDP( ip_port, "$SR "..search_nick.." "..filename.."\005".. filesize.." "..open_slots..
"/"..total_slots.."\005"..dcpp:getHub( hub ):getHubName() ) -- no pipe in UDP $SR
end
--/////////////////////////////////////
--// Start Lua Manager
--/////////////////////////////////////
local fnc, err = loadfile( DC():GetAppPath().."scripts\\libsimplepickle.lua" )
if fnc then
fnc()
fnc = nil
else
DC():PrintDebug( " LUA ERROR: "..err)
pickle = { store = function() end }
end
scriptMan = {}
scriptMan.Init = function( filename )
dcpp._listeners = { id = {} }
scriptMan.script = {}
setmetatable( scriptMan.script, { __index = {
load = function( this, filename )
local ret
if scriptMan.script:getid( filename ) then
scriptMan.script:unload( filename )
ret = "successfully reloaded."
else
ret = "successfully loaded."
end
local i = #dcpp._listeners.id +1
local func, err = loadfile( DC():GetAppPath().."scripts\\"..filename )
if not func then return nil, err end
-- load into a new environment
dcpp._listeners[i] = {}
setmetatable( dcpp._listeners[i], { __index = _G } )
setfenv( func, dcpp._listeners[i] )
func()
dcpp._listeners.id[i] = filename
-- change status flag if exists
local known = false
for i in ipairs(scriptlist) do
if scriptlist[i][1] == filename then
scriptlist[i][2] = 1
known = true
break
end
end
-- insert if it's new
if not known then table.insert( scriptlist, { filename, 1 } ) end
scriptMan.script:save()
return ret
end,
remove = function( this, filename )
local id = scriptMan.script:getid( filename )
if id then
table.remove( dcpp._listeners.id, id ) -- remove its id
table.remove( dcpp._listeners, id ) -- remove its environment
collectgarbage("collect")
end
-- remove from scriptlist
for i in ipairs(scriptlist) do
if scriptlist[i][1] == filename then
table.remove( scriptlist, i )
scriptMan.script:save()
return "removed."
end
end
return "not found."
end,
unload = function( this, filename )
local id = scriptMan.script:getid( filename )
if id then
table.remove( dcpp._listeners.id, id ) -- remove its id
table.remove( dcpp._listeners, id ) -- remove its environment
collectgarbage("collect")
end
-- change status flag to 0 (inactive)
for i in ipairs(scriptlist) do
if scriptlist[i][1] == filename then
scriptlist[i][2] = 0
scriptMan.script:save()
return "unloaded."
end
end
return "not found"
end,
getid = function( this, filename )
for id, name in pairs( dcpp._listeners.id ) do
if name == filename then
return id
end
end
return nil
end,
save = function( this )
pickle.store( DC():GetAppPath().."scripts\\scriptlist.tbl", { scriptlist = scriptlist } )
end}
})
-- load scriptmanager first
dcpp._listeners.id[1] = "startup.lua"
dcpp._listeners[1] = {
ownChatOut = function( hub, message )
if message:sub(1,1) ~= "/" then return nil end
local _,_, cmd, fname = message:find( "([^ ]+)[ ]*(.*)" )
if cmd == nil then
return nil
elseif cmd == "/lualist" then
local sc, a = {}, 0
for i, n in ipairs( scriptlist ) do
if n[2] == 1 then a = a +1 end
table.insert( sc, ("[ ".. n[2] .." ] ".. n[1]) )
end
hub:addLine( "Scripts: (".. a .."/".. #sc ..")\r\nVersion: ".. _VERSION .."\r\n"..table.concat(sc, "\r\n").."\r\n" )
return 1
elseif cmd == "/luaload" then
if fname ~= "startup.lua" then
local ret, err = scriptMan.script:load( DC():FromUtf8(fname) )
hub:addLine( (err and err or "Lua script '"..fname.."' "..ret) )
else
hub:addLine( "ERROR: Use '/luafile startup.lua' if you really want to reload it." )
end
return 1
elseif cmd == "/luareload" then
if scriptMan.script:getid( DC():FromUtf8(fname) ) then
local ret, err = scriptMan.script:load( DC():FromUtf8(fname) )
hub:addLine( (err and err or "Lua script '"..fname.."' "..ret) )
else
hub:addLine( "ERROR: Lua script '"..fname.."' is not running." )
end
return 1
elseif cmd == "/luaunload" then
if fname ~= "startup.lua" then
local ret = scriptMan.script:unload( DC():FromUtf8(fname) )
hub:addLine( "Lua script '"..fname.."' "..ret )
else
hub:addLine( "ERROR: Use '/luafile startup.lua' if you really want to reload it." )
end
return 1
elseif cmd == "/luaremove" then
if fname ~= "startup.lua" then
local ret = scriptMan.script:remove( DC():FromUtf8(fname) )
hub:addLine( "Lua script '"..fname.."' "..ret )
else
hub:addLine( "ERROR: Use '/luafile startup.lua' if you really want to reload it." )
end
return 1
elseif cmd == "/meminfo" then
collectgarbage("collect")
local mem = collectgarbage("count")
local t, i = { "KiB", "MiB", "GiB", "TiB" }, 1
while mem >= 1024 and i < #t do mem = (mem / 1024); i = i+1 end
hub:addLine( "Scripts are using ".. string.format("%.2f", mem ) .. " "..t[i].." of memory." )
return 1
elseif cmd == "/help" then
hub:addLine( "\r\n"..string.rep("-", 156).."\r\n Script Manager\r\n"..string.rep("-", 156).."\r\n"..
"/lualist scriptlist\r\n"..
"/luaload <filename> load <filename> script\r\n"..
"/luareload <filename> reload <filename> script\r\n"..
"/luaunload <filename> unload <filename> script\r\n"..
"/luaremove <filename> unload and/or remove <filename> from scriptlist\r\n"..
"/meminfo memory usage by scripts\r\n"..
"/luafile startup.lua reload scripting interface" )
return nil
end
end
}
setmetatable( dcpp._listeners[1], { __index = _G } )
setfenv( dcpp._listeners[1].ownChatOut, dcpp._listeners[1] )
end
scriptMan.Run = function( this, fname, ... )
for i in ipairs( dcpp._listeners ) do
if type( dcpp._listeners[i][fname] ) == "function" then
local res, ret = pcall( dcpp._listeners[i][fname], ... )
if not res then
DC():PrintDebug( " LUA ERROR: ("..dcpp._listeners.id[i]..": "..fname..") "..ret )
else
if ret then return 1 end
end
end
end
end
scriptMan.Init()
if not scriptlist then
local func = loadfile( DC():GetAppPath() .. "scripts\\scriptlist.tbl" )
if func then
func()
else
local f = io.open( DC():GetAppPath() .. "scripts\\scriptlist.tbl", "w+")
if f then f:close() end
end
if type(scriptlist) ~= "table" then
scriptlist = {} -- [1] = {scriptname, active (1/0)}
scriptMan.script:save()
end
end
dofile = function( filename )
local fnc, err = loadfile( filename )
if fnc then
setfenv(fnc, getfenv(2))
fnc()
else
DC():PrintDebug( " LUA ERROR: "..err )
end
end
-- _always_ start formatting.lua
scriptMan.script:load( "formatting.lua" )
-- autostart last running scripts but (running) formatting.lua
for i in ipairs( scriptlist ) do
if scriptlist[i][2] == 1 and scriptlist[i][1] ~= "formatting.lua" then
local res, err = scriptMan.script:load( scriptlist[i][1] )
if not res then
DC():PrintDebug( " "..err)
end
end
end
-- run timer
DC():RunTimer(1)