startup.lua

Guest Toast
By Guest Toast in Plugins,
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)
  • 8 replies