Communal Mailbox script


(acQu) #1

Copying this over from the etpub forums (just in case it gets lost some day).
Source: http://etpub.org/viewtopic.php?f=10&t=95


-- commail.lua - communal mailbox for etpub
-- this module implements a server side mailbox system intended to give players more fexibility in providing server related feedback, e.g. maprotation, complaints, teamkills etc.
-- 
-- script by fart11eleven - nmueller1 at gmx dot net
--

SCRIPTVERSION = "0.1"
MODSUPPORT = "etpub"
MODULENAME = "Communal Mailbox"

-------------------------------------------------------------------------------------
-------------------------------CONFIG START------------------------------------------

MAILBOX_FILENAME = "commail.log"
MAILBOX_MAX_FILESIZE = 8192 -- in bytes

CMD_MSG_WRITE = "!msgwrite"
CMD_MSG_DELETE = "!msgdelete"
CMD_MSG_DELETE_PAGE = "!msgdeletepage"
CMD_MSG_DELETE_ALL = "!msgdeleteall"
CMD_MSG_LIST = "!msglist"
CMD_MSG_SIZE = "!msgsize"

SHRUBLEVEL_CMD_MSG_WRITE = 2
SHRUBLEVEL_CMD_MSG_DELETE = 5
SHRUBLEVEL_CMD_MSG_DELETE_PAGE = 5
SHRUBLEVEL_CMD_MSG_DELETE_ALL = 5
SHRUBLEVEL_CMD_MSG_LIST = 5
SHRUBLEVEL_CMD_MSG_SIZE = 5

SPAM_PROTECTION = 1
RCV_TIMEOUT = 20000 -- in milliseconds

AUTO_CLEANUP = 1
AUTO_CLEANUP_MSG_OLDER = 30 -- in days

-------------------------------CONFIG END--------------------------------------------
-------------------------------------------------------------------------------------

last_message_time = 0

mailbox = {}
mailbox.msg = {}
mailbox.filesize = 0

function et_InitGame( levelTime, randomSeed, restart )

   et.RegisterModname( MODULENAME .. ":" .. SCRIPTVERSION .. ":" .. MODSUPPORT )

   local fd, len = et.trap_FS_FOpenFile( MAILBOX_FILENAME, et.FS_READ )
   if len == -1 then
      et.G_Print( string.format("%s: cannot open %s
", MODULENAME, MAILBOX_FILENAME) )
      et.trap_FS_FCloseFile( fd )
      return 0
   end

   if len == 0 then
      et.trap_FS_FCloseFile( fd )
      return 0
   end

   local filedata = et.trap_FS_Read( fd, len )
   et.trap_FS_FCloseFile( fd )
   
   local newlinepos, parsefiledata, findmsg, msghead, msgtail, msgnum = 0, true, true, nil, nil, 1

   while ( parsefiledata == true ) do

      newlinepos, newlinepos = string.find (filedata, "
", newlinepos + 1)
      if newlinepos == nil then
         parsefiledata = false
      end

      findmsg = true

      while ( findmsg == true and parsefiledata == true ) do
         msghead = newlinepos
         newlinepos, newlinepos = string.find (filedata, "
", newlinepos + 1)
         if newlinepos == nil then
            parsefiledata = false
         end

         if msghead + 1 ~= newlinepos and parsefiledata == true then
            findmsg = false
            msgtail = newlinepos
         end
      end

      if parsefiledata == true then
         mailbox.msg[msgnum] = {}
         mailbox.msg[msgnum].rawstring = string.sub(filedata, msghead, msgtail)
         mailbox.msg[msgnum].rawsize = string.len(mailbox.msg[msgnum].rawstring)
         mailbox.filesize = mailbox.filesize + mailbox.msg[msgnum].rawsize
         msgnum = msgnum + 1
      end     
   end

end

function et_ShutdownGame( restart )

   if AUTO_CLEANUP == 1 then
      AutoCleanUp()
   end

   local filedata = ""

   for i = 1, #mailbox.msg do
      filedata = filedata .. mailbox.msg[i].rawstring
   end

   local fd, len = et.trap_FS_FOpenFile( MAILBOX_FILENAME, et.FS_WRITE )
   if len == -1 then
      et.G_Print( string.format("%s: cannot open %s
", MODULENAME, MAILBOX_FILENAME) )
      return 0
   end

   local count = et.trap_FS_Write( filedata, string.len(filedata), fd )
   if count <= 0 then
      et.G_Print( string.format("%s: cannot write %s.
", MODULENAME, MAILBOX_FILENAME) )
   end

   et.trap_FS_FCloseFile( fd )
end

function et_ClientCommand( clientNum, command )

   if command ~= "say" then
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_WRITE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_WRITE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_WRITE) )
         return 0
      end

      local args = et.ConcatArgs( 2 )
      local argslen = string.len(args)
      if argslen == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Missing arguments.
\"", MODULENAME) )
         return 0
      end

      if argslen > 800 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed (too big).
\"", MODULENAME) )
         return 0
      end

      if SPAM_PROTECTION == 1 then
         millisec = et.trap_Milliseconds()
         if millisec - last_message_time < RCV_TIMEOUT then         
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Please wait ^1%d^7 seconds.
\"", MODULENAME, (RCV_TIMEOUT - (millisec - last_message_time))/1000) )
            return 0
         end

         last_message_time = millisec
      end

      local date = os.date()     
      local userinfo = et.trap_GetUserinfo( clientNum )
      local name = et.Info_ValueForKey( userinfo, "name" )
      local guid = et.Info_ValueForKey( userinfo, "cl_guid" )
      if string.len(guid) == 32 then
         guid = string.sub(guid, 1, 24)
      else
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Cannot verify guid.
\"", MODULENAME) )
         return 0
      end

      local msg = string.format("
%s %s %s MSG: %s
", date, guid .. "...", et.Q_CleanStr( name ), et.Q_CleanStr( args ))
      local msglen = string.len(msg)
      local newfilesize = mailbox.filesize + msglen

      if newfilesize > MAILBOX_MAX_FILESIZE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Box too full.
\"", MODULENAME) )
         et.G_Print( string.format("%s: attempt to write to %s denied. Maxfilesize %d bytes reached.
", MODULENAME, MAILBOX_FILENAME, MAILBOX_MAX_FILESIZE) )
         return 0
      end

      local msgnum = #mailbox.msg + 1
      mailbox.msg[msgnum] = {}
      mailbox.msg[msgnum].rawstring = msg
      mailbox.msg[msgnum].rawsize = msglen
      mailbox.filesize = newfilesize

      et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message filed.
\"", MODULENAME) )
      et.G_Print( string.format("%s: message filed.
", MODULENAME) )
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_DELETE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_DELETE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_DELETE) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: empty. Nothing to delete.
\"", MODULENAME) )
         return 0
      end

      local cmdline_delstring = et.ConcatArgs( 2 )
      if string.len(cmdline_delstring) == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: missing argument.
\"", MODULENAME) )
         return 0
      end

      local a, b, numdeleted = 1, 1, 0
      for i = #mailbox.msg, 1, -1 do
         a, b  = string.find(mailbox.msg[i].rawstring, cmdline_delstring, 1)
         if a ~= nil then
            mailbox.filesize = mailbox.filesize - mailbox.msg[i].rawsize
            table.remove(mailbox.msg, i)
            numdeleted = numdeleted + 1
         end
      end

      et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: %d messages to trash.
\"", MODULENAME, numdeleted) )
      et.G_Print( string.format("%s: %d messages to trash.
", MODULENAME, numdeleted) )
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_DELETE_PAGE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_DELETE_PAGE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_DELETE_PAGE) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: box is empty.
\"", MODULENAME) )
         return 0
      end

      local page = {}
      local i, condition, pagenum, currentpagesize, createpage, upperlimitforpage = 1, true, 0, 0, false, 900

      while ( condition ) do

         if createpage == false then
            pagenum = pagenum + 1
            page[pagenum] = {}
            page[pagenum].pagehead = i
            currentpagesize = 0
            createpage = true
         end

         currentpagesize = currentpagesize + mailbox.msg[i].rawsize

         if currentpagesize > upperlimitforpage then
            page[pagenum].pagetail = i - 1
            page[pagenum].pagesize = currentpagesize - mailbox.msg[i].rawsize
            i = i - 1
            createpage = false
         end

         if i == #mailbox.msg then
            if createpage == true then
               page[pagenum].pagetail = i
               page[pagenum].pagesize = currentpagesize
            else
               pagenum = pagenum + 1
               page[pagenum] = {}
               page[pagenum].pagehead = i
               page[pagenum].pagetail = i
               page[pagenum].pagesize = mailbox.msg[i].rawsize
            end
            condition = false
         end

         i = i + 1
      end

      local totalnumpages = pagenum
      local pagerequested = tonumber(et.trap_Argv(2))

      if pagerequested == nil then
         et.trap_SendServerCommand( clientNum, string.format("print \"%s: no valid argument.
\"", MODULENAME) )
         return 0
      else
         if pagerequested > 0 and pagerequested <= totalnumpages then
         
            local i, numdeleted = page[pagerequested].pagetail, 0
            while i >= page[pagerequested].pagehead do               
               table.remove(mailbox.msg, i)
               numdeleted = numdeleted + 1
               i = i - 1
            end
            mailbox.filesize = mailbox.filesize - page[pagerequested].pagesize
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: page %d deleted (%d bytes).
\"", MODULENAME, pagerequested, page[pagerequested].pagesize) )
         else
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: page %d out of range %d - %d.
\"", MODULENAME, pagerequested, 1, totalnumpages) )
         end
      end
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_DELETE_ALL then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_DELETE_ALL then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_DELETE_ALL) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: empty. Nothing to delete.
\"", MODULENAME) )
      else
         local numdeleted, filediff, nummessages = 0, 0, #mailbox.msg
         for i = nummessages, 1, -1 do
            filediff = filediff + mailbox.msg[i].rawsize
            table.remove(mailbox.msg, i)
            numdeleted = numdeleted + 1
         end
         mailbox.filesize = mailbox.filesize - filediff
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: %d bytes gone (%d messages).
\"", MODULENAME, filediff, nummessages) )
         et.G_Print( string.format("%s: %d bytes gone.
", MODULENAME, filediff) )
      end
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_LIST then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_LIST then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_LIST) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: box is empty.
\"", MODULENAME) )
         return 0
      end

      local page = {}
      local i, condition, pagenum, currentpagesize, createpage, upperlimitforpage = 1, true, 0, 0, false, 900

      while ( condition ) do

         if createpage == false then
            pagenum = pagenum + 1
            page[pagenum] = {}
            page[pagenum].pagehead = i
            currentpagesize = 0
            createpage = true
         end

         currentpagesize = currentpagesize + mailbox.msg[i].rawsize

         if currentpagesize > upperlimitforpage then
            page[pagenum].pagetail = i - 1
            page[pagenum].pagesize = currentpagesize - mailbox.msg[i].rawsize
            i = i - 1
            createpage = false
         end

         if i == #mailbox.msg then
            if createpage == true then
               page[pagenum].pagetail = i
               page[pagenum].pagesize = currentpagesize
            else
               pagenum = pagenum + 1
               page[pagenum] = {}
               page[pagenum].pagehead = i
               page[pagenum].pagetail = i
               page[pagenum].pagesize = mailbox.msg[i].rawsize
            end
            condition = false
         end

         i = i + 1
      end

      local totalnumpages = pagenum
      local pagerequested = tonumber(et.trap_Argv(2))

      if pagerequested == nil then
         et.trap_SendServerCommand( clientNum, string.format("print \"%s: total number of %d pages (%d bytes).
\"", MODULENAME, totalnumpages, mailbox.filesize) )
         return 0
      else
         if pagerequested > 0 and pagerequested <= totalnumpages then
            local rawpagecontent = ""
            for i = page[pagerequested].pagehead, page[pagerequested].pagetail do
               rawpagecontent = rawpagecontent .. mailbox.msg[i].rawstring
            end

            local msg = string.format("print \"
%s: Page: %d/%d (%d bytes)
%s
\"", MODULENAME, pagerequested, totalnumpages, page[pagerequested].pagesize, rawpagecontent)
            et.trap_SendServerCommand( clientNum, msg )
            return 0
         else
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: page %d out of range %d - %d.
\"", MODULENAME, pagerequested, 1, totalnumpages) )
         end
      end
     
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_SIZE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_SIZE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_SIZE) )
         return 0
      end
     
      et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: %d bytes used. %d bytes free.
\"", MODULENAME, mailbox.filesize, MAILBOX_MAX_FILESIZE - mailbox.filesize) )
      return 0
   end

end

function AutoCleanUp()

   if mailbox.filesize == 0 then
      return 0
   end

   local currenttime = os.date("*t")
   local cleanuptime = AUTO_CLEANUP_MSG_OLDER * 86400

   local numdeleted = 0
   for i = #mailbox.msg, 1, -1 do
     
      local msgtime = { }
      msgtime.month = tonumber(string.sub(mailbox.msg[i].rawstring, 2, 3))
      msgtime.day = tonumber(string.sub(mailbox.msg[i].rawstring, 5, 6))
      msgtime.year = 2000 + tonumber(string.sub(mailbox.msg[i].rawstring, 8, 9))

      if (os.difftime(os.time(currenttime), os.time(msgtime))) > cleanuptime then
         et.G_Print( string.format("%s: auto cleaned %s
", MODULENAME, string.sub(mailbox.msg[i].rawstring, 1, 17)) )
         table.remove(mailbox.msg, i)
         numdeleted = numdeleted + 1
      end
   end

   if numdeleted > 0 then
      et.G_Print( string.format("%s: auto cleaned %d messages.
", MODULENAME, numdeleted) )
   end
end



(NovaPrime) #2

Sorry to reply to an old post, but since there was no reply to this it would seem sill to copy to a new thread.

Anyway, has anyone got this script to work? this is a great idea but I just loaded on server and it does not seem to save the messages. If a message is written, it says that it is filed. But on the next map it says mailbox is empty.

Thoughts?


(TimOOn) #3

It works fine for me. Are you runnig this on etpub?


(NovaPrime) #4

yes etpub v1.0, but not the client, only the server. Would this lua require the client?


(TimOOn) #5

No, lua is server side script. But I know what seems to cause problems. The os.date() function returns date and time but date format may vary depending on locale and operating system. Firstly I tested this script on my PC and it worked fine but on Linux server it doesn’t.
I changed the parameters for os.date() function so it would present the same date format. This should work now.

-- commail.lua - communal mailbox for etpub
-- this module implements a server side mailbox system intended to give players more fexibility in providing server related feedback, e.g. maprotation, complaints, teamkills etc.
-- 
-- script by fart11eleven - nmueller1 at gmx dot net
--
-- EDIT: changed os.date() function format so it displayed the same date format for any locale

SCRIPTVERSION = "0.1"
MODSUPPORT = "etpub"
MODULENAME = "Communal Mailbox"

-------------------------------------------------------------------------------------
-------------------------------CONFIG START------------------------------------------

MAILBOX_FILENAME = "commail.log"
MAILBOX_MAX_FILESIZE = 8192 -- in bytes

CMD_MSG_WRITE = "!msgwrite"
CMD_MSG_DELETE = "!msgdelete"
CMD_MSG_DELETE_PAGE = "!msgdeletepage"
CMD_MSG_DELETE_ALL = "!msgdeleteall"
CMD_MSG_LIST = "!msglist"
CMD_MSG_SIZE = "!msgsize"

SHRUBLEVEL_CMD_MSG_WRITE = 2
SHRUBLEVEL_CMD_MSG_DELETE = 5
SHRUBLEVEL_CMD_MSG_DELETE_PAGE = 5
SHRUBLEVEL_CMD_MSG_DELETE_ALL = 5
SHRUBLEVEL_CMD_MSG_LIST = 5
SHRUBLEVEL_CMD_MSG_SIZE = 5

SPAM_PROTECTION = 1
RCV_TIMEOUT = 20000 -- in milliseconds

AUTO_CLEANUP = 1
AUTO_CLEANUP_MSG_OLDER = 30 -- in days

-------------------------------CONFIG END--------------------------------------------
-------------------------------------------------------------------------------------

last_message_time = 0

mailbox = {}
mailbox.msg = {}
mailbox.filesize = 0

function et_InitGame( levelTime, randomSeed, restart )

   et.RegisterModname( MODULENAME .. ":" .. SCRIPTVERSION .. ":" .. MODSUPPORT )

   local fd, len = et.trap_FS_FOpenFile( MAILBOX_FILENAME, et.FS_READ )
   if len == -1 then
      et.G_Print( string.format("%s: cannot open %s
", MODULENAME, MAILBOX_FILENAME) )
      et.trap_FS_FCloseFile( fd )
      return 0
   end

   if len == 0 then
      et.trap_FS_FCloseFile( fd )
      return 0
   end

   local filedata = et.trap_FS_Read( fd, len )
   et.trap_FS_FCloseFile( fd )
   
   local newlinepos, parsefiledata, findmsg, msghead, msgtail, msgnum = 0, true, true, nil, nil, 1

   while ( parsefiledata == true ) do

      newlinepos, newlinepos = string.find (filedata, "
", newlinepos + 1)
      if newlinepos == nil then
         parsefiledata = false
      end

      findmsg = true

      while ( findmsg == true and parsefiledata == true ) do
         msghead = newlinepos
         newlinepos, newlinepos = string.find (filedata, "
", newlinepos + 1)
         if newlinepos == nil then
            parsefiledata = false
         end

         if msghead + 1 ~= newlinepos and parsefiledata == true then
            findmsg = false
            msgtail = newlinepos
         end
      end

      if parsefiledata == true then
         mailbox.msg[msgnum] = {}
         mailbox.msg[msgnum].rawstring = string.sub(filedata, msghead, msgtail)
         mailbox.msg[msgnum].rawsize = string.len(mailbox.msg[msgnum].rawstring)
         mailbox.filesize = mailbox.filesize + mailbox.msg[msgnum].rawsize
         msgnum = msgnum + 1
      end     
   end

end

function et_ShutdownGame( restart )

   if AUTO_CLEANUP == 1 then
      AutoCleanUp()
   end

   local filedata = ""

   for i = 1, #mailbox.msg do
      filedata = filedata .. mailbox.msg[i].rawstring
   end

   local fd, len = et.trap_FS_FOpenFile( MAILBOX_FILENAME, et.FS_WRITE )
   if len == -1 then
      et.G_Print( string.format("%s: cannot open %s
", MODULENAME, MAILBOX_FILENAME) )
      return 0
   end

   local count = et.trap_FS_Write( filedata, string.len(filedata), fd )
   if count <= 0 then
      et.G_Print( string.format("%s: cannot write %s.
", MODULENAME, MAILBOX_FILENAME) )
   end

   et.trap_FS_FCloseFile( fd )
end

function et_ClientCommand( clientNum, command )

   if command ~= "say" then
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_WRITE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_WRITE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_WRITE) )
         return 0
      end

      local args = et.ConcatArgs( 2 )
      local argslen = string.len(args)
      if argslen == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Missing arguments.
\"", MODULENAME) )
         return 0
      end

      if argslen > 800 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed (too big).
\"", MODULENAME) )
         return 0
      end

      if SPAM_PROTECTION == 1 then
         millisec = et.trap_Milliseconds()
         if millisec - last_message_time < RCV_TIMEOUT then         
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Please wait ^1%d^7 seconds.
\"", MODULENAME, (RCV_TIMEOUT - (millisec - last_message_time))/1000) )
            return 0
         end

         last_message_time = millisec
      end

      local date = os.date("%m/%d/%Y %I:%M:%S %p")     
      local userinfo = et.trap_GetUserinfo( clientNum )
      local name = et.Info_ValueForKey( userinfo, "name" )
      local guid = et.Info_ValueForKey( userinfo, "cl_guid" )
      if string.len(guid) == 32 then
         guid = string.sub(guid, 1, 24)
      else
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Cannot verify guid.
\"", MODULENAME) )
         return 0
      end

      local msg = string.format("
%s %s %s MSG: %s
", date, guid .. "...", et.Q_CleanStr( name ), et.Q_CleanStr( args ))
      local msglen = string.len(msg)
      local newfilesize = mailbox.filesize + msglen

      if newfilesize > MAILBOX_MAX_FILESIZE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Box too full.
\"", MODULENAME) )
         et.G_Print( string.format("%s: attempt to write to %s denied. Maxfilesize %d bytes reached.
", MODULENAME, MAILBOX_FILENAME, MAILBOX_MAX_FILESIZE) )
         return 0
      end

      local msgnum = #mailbox.msg + 1
      mailbox.msg[msgnum] = {}
      mailbox.msg[msgnum].rawstring = msg
      mailbox.msg[msgnum].rawsize = msglen
      mailbox.filesize = newfilesize

      et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message filed.
\"", MODULENAME) )
      et.G_Print( string.format("%s: message filed.
", MODULENAME) )
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_DELETE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_DELETE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_DELETE) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: empty. Nothing to delete.
\"", MODULENAME) )
         return 0
      end

      local cmdline_delstring = et.ConcatArgs( 2 )
      if string.len(cmdline_delstring) == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: missing argument.
\"", MODULENAME) )
         return 0
      end

      local a, b, numdeleted = 1, 1, 0
      for i = #mailbox.msg, 1, -1 do
         a, b  = string.find(mailbox.msg[i].rawstring, cmdline_delstring, 1)
         if a ~= nil then
            mailbox.filesize = mailbox.filesize - mailbox.msg[i].rawsize
            table.remove(mailbox.msg, i)
            numdeleted = numdeleted + 1
         end
      end

      et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: %d messages to trash.
\"", MODULENAME, numdeleted) )
      et.G_Print( string.format("%s: %d messages to trash.
", MODULENAME, numdeleted) )
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_DELETE_PAGE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_DELETE_PAGE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_DELETE_PAGE) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: box is empty.
\"", MODULENAME) )
         return 0
      end

      local page = {}
      local i, condition, pagenum, currentpagesize, createpage, upperlimitforpage = 1, true, 0, 0, false, 900

      while ( condition ) do

         if createpage == false then
            pagenum = pagenum + 1
            page[pagenum] = {}
            page[pagenum].pagehead = i
            currentpagesize = 0
            createpage = true
         end

         currentpagesize = currentpagesize + mailbox.msg[i].rawsize

         if currentpagesize > upperlimitforpage then
            page[pagenum].pagetail = i - 1
            page[pagenum].pagesize = currentpagesize - mailbox.msg[i].rawsize
            i = i - 1
            createpage = false
         end

         if i == #mailbox.msg then
            if createpage == true then
               page[pagenum].pagetail = i
               page[pagenum].pagesize = currentpagesize
            else
               pagenum = pagenum + 1
               page[pagenum] = {}
               page[pagenum].pagehead = i
               page[pagenum].pagetail = i
               page[pagenum].pagesize = mailbox.msg[i].rawsize
            end
            condition = false
         end

         i = i + 1
      end

      local totalnumpages = pagenum
      local pagerequested = tonumber(et.trap_Argv(2))

      if pagerequested == nil then
         et.trap_SendServerCommand( clientNum, string.format("print \"%s: no valid argument.
\"", MODULENAME) )
         return 0
      else
         if pagerequested > 0 and pagerequested <= totalnumpages then
         
            local i, numdeleted = page[pagerequested].pagetail, 0
            while i >= page[pagerequested].pagehead do               
               table.remove(mailbox.msg, i)
               numdeleted = numdeleted + 1
               i = i - 1
            end
            mailbox.filesize = mailbox.filesize - page[pagerequested].pagesize
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: page %d deleted (%d bytes).
\"", MODULENAME, pagerequested, page[pagerequested].pagesize) )
         else
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: page %d out of range %d - %d.
\"", MODULENAME, pagerequested, 1, totalnumpages) )
         end
      end
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_DELETE_ALL then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_DELETE_ALL then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_DELETE_ALL) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: empty. Nothing to delete.
\"", MODULENAME) )
      else
         local numdeleted, filediff, nummessages = 0, 0, #mailbox.msg
         for i = nummessages, 1, -1 do
            filediff = filediff + mailbox.msg[i].rawsize
            table.remove(mailbox.msg, i)
            numdeleted = numdeleted + 1
         end
         mailbox.filesize = mailbox.filesize - filediff
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: %d bytes gone (%d messages).
\"", MODULENAME, filediff, nummessages) )
         et.G_Print( string.format("%s: %d bytes gone.
", MODULENAME, filediff) )
      end
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_LIST then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_LIST then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_LIST) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: box is empty.
\"", MODULENAME) )
         return 0
      end

      local page = {}
      local i, condition, pagenum, currentpagesize, createpage, upperlimitforpage = 1, true, 0, 0, false, 900

      while ( condition ) do

         if createpage == false then
            pagenum = pagenum + 1
            page[pagenum] = {}
            page[pagenum].pagehead = i
            currentpagesize = 0
            createpage = true
         end

         currentpagesize = currentpagesize + mailbox.msg[i].rawsize

         if currentpagesize > upperlimitforpage then
            page[pagenum].pagetail = i - 1
            page[pagenum].pagesize = currentpagesize - mailbox.msg[i].rawsize
            i = i - 1
            createpage = false
         end

         if i == #mailbox.msg then
            if createpage == true then
               page[pagenum].pagetail = i
               page[pagenum].pagesize = currentpagesize
            else
               pagenum = pagenum + 1
               page[pagenum] = {}
               page[pagenum].pagehead = i
               page[pagenum].pagetail = i
               page[pagenum].pagesize = mailbox.msg[i].rawsize
            end
            condition = false
         end

         i = i + 1
      end

      local totalnumpages = pagenum
      local pagerequested = tonumber(et.trap_Argv(2))

      if pagerequested == nil then
         et.trap_SendServerCommand( clientNum, string.format("print \"%s: total number of %d pages (%d bytes).
\"", MODULENAME, totalnumpages, mailbox.filesize) )
         return 0
      else
         if pagerequested > 0 and pagerequested <= totalnumpages then
            local rawpagecontent = ""
            for i = page[pagerequested].pagehead, page[pagerequested].pagetail do
               rawpagecontent = rawpagecontent .. mailbox.msg[i].rawstring
            end

            local msg = string.format("print \"
%s: Page: %d/%d (%d bytes)
%s
\"", MODULENAME, pagerequested, totalnumpages, page[pagerequested].pagesize, rawpagecontent)
            et.trap_SendServerCommand( clientNum, msg )
            return 0
         else
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: page %d out of range %d - %d.
\"", MODULENAME, pagerequested, 1, totalnumpages) )
         end
      end
     
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_SIZE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_SIZE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_SIZE) )
         return 0
      end
     
      et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: %d bytes used. %d bytes free.
\"", MODULENAME, mailbox.filesize, MAILBOX_MAX_FILESIZE - mailbox.filesize) )
      return 0
   end

end

function AutoCleanUp()

   if mailbox.filesize == 0 then
      return 0
   end

   local currenttime = os.date("*t")
   local cleanuptime = AUTO_CLEANUP_MSG_OLDER * 86400

   local numdeleted = 0
   for i = #mailbox.msg, 1, -1 do
     
      local msgtime = { }
      msgtime.month = tonumber(string.sub(mailbox.msg[i].rawstring, 2, 3))
      msgtime.day = tonumber(string.sub(mailbox.msg[i].rawstring, 5, 6))
      msgtime.year = tonumber(string.sub(mailbox.msg[i].rawstring, 8, 11))

      if (os.difftime(os.time(currenttime), os.time(msgtime))) > cleanuptime then
         et.G_Print( string.format("%s: auto cleaned %s
", MODULENAME, string.sub(mailbox.msg[i].rawstring, 1, 17)) )
         table.remove(mailbox.msg, i)
         numdeleted = numdeleted + 1
      end
   end

   if numdeleted > 0 then
      et.G_Print( string.format("%s: auto cleaned %d messages.
", MODULENAME, numdeleted) )
   end
end

(NovaPrime) #6

Thanks, the log entry remains now after maps end I believe, but when I use !msglist it just says there is 1 page and 74 bytes, but does not show the actual message in the log.


(TimOOn) #7

You have to type !msglist 1 to see whole first page of messages. There is no option to print a single message from mailbox. But you can also check your messages in commail.log file which lua script creates in etpub folder.


(NovaPrime) #8

Thanks!

question:

is page 1 always going to be the latest incoming messages? is there a way to customize how many messages per page?

thanks for help, sorry I am such a lua noob


(TimOOn) #9

The latest massages will always appear on the last page.
Pagelimit is set to 900 bytes. It is 243th script line and I guess you can change that if you like.

local i, condition, pagenum, currentpagesize, createpage, upperlimitforpage = 1, true, 0, 0, false, [B]900[/B]

(NovaPrime) #10

Thanks for all the help


(NovaPrime) #11

is there anyway to remove the guid from the output of the messages? I tried removing “guid” from the line below but it seems to make the whole output to .txt file fail

“local msg = string.format(”
%s %s %s MSG: %s
“, date, guid … “…”, et.Q_CleanStr( name ), et.Q_CleanStr( args ))”


(Micha) #12

the following removed the guide completely but could cause trouble if this gets readen out because it is missing one part.
“local msg = string.format(”
%s %s MSG: %s
“, date, et.Q_CleanStr( name ), et.Q_CleanStr( args ))”

So you could try to replace the guide with random stuff:
“local msg = string.format(”
%s %s %s MSG: %s
“, date, “000000”, et.Q_CleanStr( name ), et.Q_CleanStr( args ))”


(fart11eleven) #13

Ha, cool that my old script is being used :slight_smile:

I changed the guid request. It now displays last 8 characters of the guid like the !listplayers command. Looked around and hope this screws nothing up.

@Timoon: nice find with the locales of the date. Have seen that coming somehow when i wrote the script back then, but i think it worked on my ubuntu and windows, not sure.

Here is the modified script with the changed guid format:

-- commail.lua - communal mailbox for etpub
-- this module implements a server side mailbox system intended to give players more fexibility in providing server related feedback, e.g. maprotation, complaints, teamkills etc.
-- 
-- script by fart11eleven - nmueller1 at gmx dot net
--
-- EDIT: changed os.date() function format so it displayed the same date format for any locale
--       changed guid format so it displays only last 8 chars

SCRIPTVERSION = "0.1"
MODSUPPORT = "etpub"
MODULENAME = "Communal Mailbox"

-------------------------------------------------------------------------------------
-------------------------------CONFIG START------------------------------------------

MAILBOX_FILENAME = "commail.log"
MAILBOX_MAX_FILESIZE = 8192 -- in bytes

CMD_MSG_WRITE = "!msgwrite"
CMD_MSG_DELETE = "!msgdelete"
CMD_MSG_DELETE_PAGE = "!msgdeletepage"
CMD_MSG_DELETE_ALL = "!msgdeleteall"
CMD_MSG_LIST = "!msglist"
CMD_MSG_SIZE = "!msgsize"

SHRUBLEVEL_CMD_MSG_WRITE = 2
SHRUBLEVEL_CMD_MSG_DELETE = 5
SHRUBLEVEL_CMD_MSG_DELETE_PAGE = 5
SHRUBLEVEL_CMD_MSG_DELETE_ALL = 5
SHRUBLEVEL_CMD_MSG_LIST = 5
SHRUBLEVEL_CMD_MSG_SIZE = 5

SPAM_PROTECTION = 1
RCV_TIMEOUT = 20000 -- in milliseconds

AUTO_CLEANUP = 1
AUTO_CLEANUP_MSG_OLDER = 30 -- in days

-------------------------------CONFIG END--------------------------------------------
-------------------------------------------------------------------------------------

last_message_time = 0

mailbox = {}
mailbox.msg = {}
mailbox.filesize = 0

function et_InitGame( levelTime, randomSeed, restart )

   et.RegisterModname( MODULENAME .. ":" .. SCRIPTVERSION .. ":" .. MODSUPPORT )

   local fd, len = et.trap_FS_FOpenFile( MAILBOX_FILENAME, et.FS_READ )
   if len == -1 then
      et.G_Print( string.format("%s: cannot open %s
", MODULENAME, MAILBOX_FILENAME) )
      et.trap_FS_FCloseFile( fd )
      return 0
   end

   if len == 0 then
      et.trap_FS_FCloseFile( fd )
      return 0
   end

   local filedata = et.trap_FS_Read( fd, len )
   et.trap_FS_FCloseFile( fd )
   
   local newlinepos, parsefiledata, findmsg, msghead, msgtail, msgnum = 0, true, true, nil, nil, 1

   while ( parsefiledata == true ) do

      newlinepos, newlinepos = string.find (filedata, "
", newlinepos + 1)
      if newlinepos == nil then
         parsefiledata = false
      end

      findmsg = true

      while ( findmsg == true and parsefiledata == true ) do
         msghead = newlinepos
         newlinepos, newlinepos = string.find (filedata, "
", newlinepos + 1)
         if newlinepos == nil then
            parsefiledata = false
         end

         if msghead + 1 ~= newlinepos and parsefiledata == true then
            findmsg = false
            msgtail = newlinepos
         end
      end

      if parsefiledata == true then
         mailbox.msg[msgnum] = {}
         mailbox.msg[msgnum].rawstring = string.sub(filedata, msghead, msgtail)
         mailbox.msg[msgnum].rawsize = string.len(mailbox.msg[msgnum].rawstring)
         mailbox.filesize = mailbox.filesize + mailbox.msg[msgnum].rawsize
         msgnum = msgnum + 1
      end     
   end

end

function et_ShutdownGame( restart )

   if AUTO_CLEANUP == 1 then
      AutoCleanUp()
   end

   local filedata = ""

   for i = 1, #mailbox.msg do
      filedata = filedata .. mailbox.msg[i].rawstring
   end

   local fd, len = et.trap_FS_FOpenFile( MAILBOX_FILENAME, et.FS_WRITE )
   if len == -1 then
      et.G_Print( string.format("%s: cannot open %s
", MODULENAME, MAILBOX_FILENAME) )
      return 0
   end

   local count = et.trap_FS_Write( filedata, string.len(filedata), fd )
   if count <= 0 then
      et.G_Print( string.format("%s: cannot write %s.
", MODULENAME, MAILBOX_FILENAME) )
   end

   et.trap_FS_FCloseFile( fd )
end

function et_ClientCommand( clientNum, command )

   if command ~= "say" then
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_WRITE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_WRITE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_WRITE) )
         return 0
      end

      local args = et.ConcatArgs( 2 )
      local argslen = string.len(args)
      if argslen == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Missing arguments.
\"", MODULENAME) )
         return 0
      end

      if argslen > 800 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed (too big).
\"", MODULENAME) )
         return 0
      end

      if SPAM_PROTECTION == 1 then
         millisec = et.trap_Milliseconds()
         if millisec - last_message_time < RCV_TIMEOUT then         
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Please wait ^1%d^7 seconds.
\"", MODULENAME, (RCV_TIMEOUT - (millisec - last_message_time))/1000) )
            return 0
         end

         last_message_time = millisec
      end

      local date = os.date("%m/%d/%Y %I:%M:%S %p")     
      local userinfo = et.trap_GetUserinfo( clientNum )
      local name = et.Info_ValueForKey( userinfo, "name" )
      local guid = et.Info_ValueForKey( userinfo, "cl_guid" )
      if string.len(guid) == 32 then
         guid = string.format("(*%s)", string.sub(guid, 25, 32))
      else
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Cannot verify guid.
\"", MODULENAME) )
         return 0
      end

      local msg = string.format("
%s %s %s MSG: %s
", date, guid, et.Q_CleanStr( name ), et.Q_CleanStr( args ))
      local msglen = string.len(msg)
      local newfilesize = mailbox.filesize + msglen

      if newfilesize > MAILBOX_MAX_FILESIZE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message not filed. Box too full.
\"", MODULENAME) )
         et.G_Print( string.format("%s: attempt to write to %s denied. Maxfilesize %d bytes reached.
", MODULENAME, MAILBOX_FILENAME, MAILBOX_MAX_FILESIZE) )
         return 0
      end

      local msgnum = #mailbox.msg + 1
      mailbox.msg[msgnum] = {}
      mailbox.msg[msgnum].rawstring = msg
      mailbox.msg[msgnum].rawsize = msglen
      mailbox.filesize = newfilesize

      et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: message filed.
\"", MODULENAME) )
      et.G_Print( string.format("%s: message filed.
", MODULENAME) )
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_DELETE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_DELETE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_DELETE) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: empty. Nothing to delete.
\"", MODULENAME) )
         return 0
      end

      local cmdline_delstring = et.ConcatArgs( 2 )
      if string.len(cmdline_delstring) == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: missing argument.
\"", MODULENAME) )
         return 0
      end

      local a, b, numdeleted = 1, 1, 0
      for i = #mailbox.msg, 1, -1 do
         a, b  = string.find(mailbox.msg[i].rawstring, cmdline_delstring, 1)
         if a ~= nil then
            mailbox.filesize = mailbox.filesize - mailbox.msg[i].rawsize
            table.remove(mailbox.msg, i)
            numdeleted = numdeleted + 1
         end
      end

      et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: %d messages to trash.
\"", MODULENAME, numdeleted) )
      et.G_Print( string.format("%s: %d messages to trash.
", MODULENAME, numdeleted) )
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_DELETE_PAGE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_DELETE_PAGE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_DELETE_PAGE) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: box is empty.
\"", MODULENAME) )
         return 0
      end

      local page = {}
      local i, condition, pagenum, currentpagesize, createpage, upperlimitforpage = 1, true, 0, 0, false, 900

      while ( condition ) do

         if createpage == false then
            pagenum = pagenum + 1
            page[pagenum] = {}
            page[pagenum].pagehead = i
            currentpagesize = 0
            createpage = true
         end

         currentpagesize = currentpagesize + mailbox.msg[i].rawsize

         if currentpagesize > upperlimitforpage then
            page[pagenum].pagetail = i - 1
            page[pagenum].pagesize = currentpagesize - mailbox.msg[i].rawsize
            i = i - 1
            createpage = false
         end

         if i == #mailbox.msg then
            if createpage == true then
               page[pagenum].pagetail = i
               page[pagenum].pagesize = currentpagesize
            else
               pagenum = pagenum + 1
               page[pagenum] = {}
               page[pagenum].pagehead = i
               page[pagenum].pagetail = i
               page[pagenum].pagesize = mailbox.msg[i].rawsize
            end
            condition = false
         end

         i = i + 1
      end

      local totalnumpages = pagenum
      local pagerequested = tonumber(et.trap_Argv(2))

      if pagerequested == nil then
         et.trap_SendServerCommand( clientNum, string.format("print \"%s: no valid argument.
\"", MODULENAME) )
         return 0
      else
         if pagerequested > 0 and pagerequested <= totalnumpages then
         
            local i, numdeleted = page[pagerequested].pagetail, 0
            while i >= page[pagerequested].pagehead do               
               table.remove(mailbox.msg, i)
               numdeleted = numdeleted + 1
               i = i - 1
            end
            mailbox.filesize = mailbox.filesize - page[pagerequested].pagesize
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: page %d deleted (%d bytes).
\"", MODULENAME, pagerequested, page[pagerequested].pagesize) )
         else
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: page %d out of range %d - %d.
\"", MODULENAME, pagerequested, 1, totalnumpages) )
         end
      end
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_DELETE_ALL then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_DELETE_ALL then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_DELETE_ALL) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: empty. Nothing to delete.
\"", MODULENAME) )
      else
         local numdeleted, filediff, nummessages = 0, 0, #mailbox.msg
         for i = nummessages, 1, -1 do
            filediff = filediff + mailbox.msg[i].rawsize
            table.remove(mailbox.msg, i)
            numdeleted = numdeleted + 1
         end
         mailbox.filesize = mailbox.filesize - filediff
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: %d bytes gone (%d messages).
\"", MODULENAME, filediff, nummessages) )
         et.G_Print( string.format("%s: %d bytes gone.
", MODULENAME, filediff) )
      end
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_LIST then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_LIST then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_LIST) )
         return 0
      end

      if mailbox.filesize == 0 then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: box is empty.
\"", MODULENAME) )
         return 0
      end

      local page = {}
      local i, condition, pagenum, currentpagesize, createpage, upperlimitforpage = 1, true, 0, 0, false, 900

      while ( condition ) do

         if createpage == false then
            pagenum = pagenum + 1
            page[pagenum] = {}
            page[pagenum].pagehead = i
            currentpagesize = 0
            createpage = true
         end

         currentpagesize = currentpagesize + mailbox.msg[i].rawsize

         if currentpagesize > upperlimitforpage then
            page[pagenum].pagetail = i - 1
            page[pagenum].pagesize = currentpagesize - mailbox.msg[i].rawsize
            i = i - 1
            createpage = false
         end

         if i == #mailbox.msg then
            if createpage == true then
               page[pagenum].pagetail = i
               page[pagenum].pagesize = currentpagesize
            else
               pagenum = pagenum + 1
               page[pagenum] = {}
               page[pagenum].pagehead = i
               page[pagenum].pagetail = i
               page[pagenum].pagesize = mailbox.msg[i].rawsize
            end
            condition = false
         end

         i = i + 1
      end

      local totalnumpages = pagenum
      local pagerequested = tonumber(et.trap_Argv(2))

      if pagerequested == nil then
         et.trap_SendServerCommand( clientNum, string.format("print \"%s: total number of %d pages (%d bytes).
\"", MODULENAME, totalnumpages, mailbox.filesize) )
         return 0
      else
         if pagerequested > 0 and pagerequested <= totalnumpages then
            local rawpagecontent = ""
            for i = page[pagerequested].pagehead, page[pagerequested].pagetail do
               rawpagecontent = rawpagecontent .. mailbox.msg[i].rawstring
            end

            local msg = string.format("print \"
%s: Page: %d/%d (%d bytes)
%s
\"", MODULENAME, pagerequested, totalnumpages, page[pagerequested].pagesize, rawpagecontent)
            et.trap_SendServerCommand( clientNum, msg )
            return 0
         else
            et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: page %d out of range %d - %d.
\"", MODULENAME, pagerequested, 1, totalnumpages) )
         end
      end
     
      return 0
   end

   if et.trap_Argv(1) == CMD_MSG_SIZE then

      local level = et.G_shrubbot_level( clientNum )
      if level < SHRUBLEVEL_CMD_MSG_SIZE then
         et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: denied. Level %d needed.
\"", MODULENAME, SHRUBLEVEL_CMD_MSG_SIZE) )
         return 0
      end
     
      et.trap_SendServerCommand( clientNum, string.format("cpm \"%s: %d bytes used. %d bytes free.
\"", MODULENAME, mailbox.filesize, MAILBOX_MAX_FILESIZE - mailbox.filesize) )
      return 0
   end

end

function AutoCleanUp()

   if mailbox.filesize == 0 then
      return 0
   end

   local currenttime = os.date("*t")
   local cleanuptime = AUTO_CLEANUP_MSG_OLDER * 86400

   local numdeleted = 0
   for i = #mailbox.msg, 1, -1 do
     
      local msgtime = { }
      msgtime.month = tonumber(string.sub(mailbox.msg[i].rawstring, 2, 3))
      msgtime.day = tonumber(string.sub(mailbox.msg[i].rawstring, 5, 6))
      msgtime.year = tonumber(string.sub(mailbox.msg[i].rawstring, 8, 11))

      if (os.difftime(os.time(currenttime), os.time(msgtime))) > cleanuptime then
         et.G_Print( string.format("%s: auto cleaned %s
", MODULENAME, string.sub(mailbox.msg[i].rawstring, 1, 17)) )
         table.remove(mailbox.msg, i)
         numdeleted = numdeleted + 1
      end
   end

   if numdeleted > 0 then
      et.G_Print( string.format("%s: auto cleaned %d messages.
", MODULENAME, numdeleted) )
   end
end

Something to note: the pages are there because ET has a limited amount of bytes it can send per message (1024 bytes). Since the lua script sits at server, it sends messages to each client requesting information about the mailbox. All messages bigger 1024 will be truncated. That is why i made pages around 900 bytes (totally random number). You could modify the script to send multiple messages when using !msglist i guess. Only thing i would advice is not to fiddle with the page size, cause there is some hardcoded stuff in the script and its very error prone to make changes that way.