Advertisement
fingercomp

Chatserver for GoogolGlasses (OpenComputers)

May 24th, 2015
1,045
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.00 KB | None | 0 0
  1. local PORTS = {{6667, false}, {35565, false}, {12345, false}} -- Тут вводим порты для сетевого интерфейса.
  2.             -- false - порт фильтруется, true - не фильтруется.
  3. local ALLOWED = {"e51", "83f7"}  -- Собственно, фильтр адресов. Сюда можно вводить только часть адреса (что я и делаю).
  4. local MAX_MSG = 10 -- Максимальное количество сообщений отображаемых.
  5. local LIFETIME = math.huge -- Количество итераций основного цикла, после которого удаляется первое сообщение, если всего написано более половины.
  6. local MAX_LEN = 75 -- Максимальная длина сообщения.
  7. local MOTD = true -- Включить/отключить MOTD. Выводит в чат при старте сервера содержимое файла /etc/chatserver.motd.
  8. local UTEST = false -- Просто фишка "для красоты". Если чат будет постоянно выключаться, ставим true, и бокс красится в жёлтый.
  9. local WBOX = 250 -- Ширина бокса. В пикселах.
  10. local HBOX = 100 -- Высота бокса. Тоже в пикселах.
  11.  
  12. local com = require("component")
  13. local gpu = com.gpu
  14. local term = require("term")
  15. local modem = com.modem
  16. local event = require("event")
  17. local bridge = com.openperipheral_bridge
  18. local fs = require("filesystem")
  19. local unicode = require("unicode")
  20. comp = require("computer")
  21.  
  22. bridge.clear()
  23. bridge.sync()
  24.  
  25. local noexit = true
  26. local chat = {}
  27. local ct = {}
  28. local cmds = {}
  29. local group = {}
  30. local user = {}
  31. local muted = {}
  32.  
  33. -- Управление группами --
  34. -- Набросал несколько в качестве примера.
  35. --[[GROUPS]]--
  36.  
  37. group.default = {
  38.   ["prefix"] = "",
  39.   ["suffix"] = "",
  40.   ["rank"] = 1
  41. }
  42.  
  43. group.prog = {
  44.   ["prefix"] = "[P]",
  45.   ["suffix"] = "",
  46.   ["rank"] = 2
  47. }
  48.  
  49. group.moder = {
  50.   ["prefix"] = "[M]",
  51.   ["suffix"] = "",
  52.   ["rank"] = 3
  53. }
  54.  
  55. group.admin = {
  56.   ["prefix"] = "[A]",
  57.   ["suffix"] = "",
  58.   ["rank"] = 4
  59. }
  60.  
  61. user["Fingercomp"] = "admin"
  62. user["Asummonster"] = "moder"
  63. user["Totoro"] = "moder"
  64. user["Zer0Galaxy"] = "moder"
  65. user["Krutoy"] = "moder"
  66. user["AlexCC"] = "admin"
  67. user["MineUbuntu"] = "prog"
  68. user["NEO"] = "prog"
  69. user["YuRaNnNzZZ"] = "moder"
  70. user["LeshaInc"] = "prog"
  71.  
  72. --[[END]]--
  73.  
  74. -- Игроки, которые будут в муте при старте сервера автоматически.
  75. --[[MUTED]]--
  76.  
  77. muted["Ki-Hun"] = true
  78. muted["Byte-Griefer"] = true
  79. muted["Spam-bot"] = true
  80.  
  81. --[[END]]--
  82.  
  83.  
  84. if not fs.exists("/var/log/") then
  85.   if not fs.exists("/var/") then
  86.     fs.makeDirectory("/var/")
  87.   end
  88.   fs.makeDirectory("/var/log/")
  89. end
  90. local time = os.date():match("(%d+:%d+):%d")
  91. local logFile = io.open("/var/log/chatserver_" .. time .. ".log", "w")
  92. local box = bridge.addGradientBox(5, 30, WBOX, HBOX, 0x000000, 0, 0x00FF00, 0.6, 2)
  93. for i = 1, MAX_MSG, 1 do
  94.   ct[i] = bridge.addText(5, 20 + i*10, "", 0xFFFFFF)
  95.   ct[i].setScale(0.8)
  96. end
  97. bridge.sync()
  98. if UTEST then
  99.   box.setColor2(0xFFFF00)
  100. else
  101.   box.setColor2(0x000000)
  102. end
  103. bridge.sync()
  104. modem.setStrength(400)
  105.  
  106. for i = 1, #PORTS, 1 do
  107.   modem.open(PORTS[i][1])
  108.   print("Port \"" .. PORTS[i][1] .. "\" opened!")
  109. end
  110.  
  111. local function log(msg)
  112.   logFile:write(msg.."\n")
  113.   print(msg)
  114. end
  115.  
  116. local function insertMsg(msg)
  117.   print("Inserted: " .. msg)
  118.   table.insert(chat, msg)
  119.   if #chat > MAX_MSG then
  120.     table.remove(chat, 1)
  121.   end
  122.   for i = 1, #PORTS, 1 do
  123.     modem.broadcast(PORTS[i][1], msg)
  124.   end
  125.   log(msg)
  126. end
  127.  
  128. local function updateChat()
  129.   print("Syncing...")
  130.   for i = 1, MAX_MSG, 1 do
  131.     if chat[i] ~= nil and chat[i] ~= ""  then
  132.       ct[i].setText(chat[i])
  133.     else
  134.       ct[i].setText("")
  135.     end
  136.   end
  137.   bridge.sync()
  138. end
  139.  
  140. -- Система команд.
  141. -- Базовые команды набросал здесь.
  142. --[[COMMANDS]]--
  143. cmds.help = {} -- Объявляем ОБЯЗАТЕЛЬНО команду, как массив (cmds.имякоманды = {})
  144. cmds.help.desc = "List of available commands" -- Описание команды. (cmds.имякоманды.desc = "описание команды")
  145. cmds.help.rank = 1 -- Уровень доступа (указывается в группах) (cmds.имякоманды.rank = уровень)
  146. function cmds.help.func()
  147.   -- Функция вызываемая (function cmds.имяфункции.func(args, sender) end). args - аргументы, разделённые пробелом. sender - тот, кто выполнил команду.
  148.   insertMsg("Help page")
  149.   for i, j in pairs(cmds) do
  150.     insertMsg(i .. " - " .. j.desc)
  151.   end
  152. end
  153.  
  154. cmds.stop = {}
  155. cmds.stop.desc = "Stop the server"
  156. cmds.stop.rank = 4
  157. function cmds.stop.func()
  158.   log("Stopped")
  159.   box.setColor2(0xFF0000)
  160.   bridge.sync()
  161.   os.sleep(1)
  162.   noexit = false
  163. end
  164.  
  165. cmds.list = {}
  166. cmds.list.desc = "List users who are currently online"
  167. cmds.list.rank = 1
  168. function cmds.list.func()
  169.   local users = bridge.getUsers()
  170.   insertMsg("Users")
  171.   for i = 1, #users, 1 do
  172.     insertMsg(users[i]["name"] .. " (" .. users[i]["uuid"] .. ")")
  173.   end
  174. end
  175.  
  176. cmds.clear = {}
  177. cmds.clear.desc = "Clear the chat"
  178. cmds.clear.rank = 3
  179. function cmds.clear.func()
  180.   for i = 1, #chat, 1 do
  181.     table.remove(chat, 1)
  182.   end
  183.   insertMsg("Chat cleared!")
  184. end
  185.  
  186. cmds.setgroup = {}
  187. cmds.setgroup.desc = "Add a user to a specified group"
  188. cmds.setgroup.rank = 4
  189. function cmds.setgroup.func(args)
  190.   local usr = args[1]
  191.   local groupR = args[2]
  192.   if group[groupR] then
  193.     user[usr] = groupR
  194.     insertMsg("User " .. usr .. " joined the group \"" .. groupR .. "\"!")
  195.   end
  196. end
  197.  
  198. cmds.broadcast = {}
  199. cmds.broadcast.desc = "Broadcast a message"
  200. cmds.broadcast.rank = 3
  201. function cmds.broadcast.func(args)
  202.   local message = ""
  203.   for i = 1, #args, 1 do
  204.     message = message .. args[i] .. " "
  205.   end
  206.   message = unicode.sub(message, 1, -2)
  207.   insertMsg("["..os.date() .. "][!B!] " .. unicode.upper(message))
  208. end
  209.  
  210. cmds.mute = {}
  211. cmds.mute.desc = "Mute the user"
  212. cmds.mute.rank = 3
  213. function cmds.mute.func(args, muter)
  214.   local usr = args[1]
  215.   muted[usr] = true
  216.   insertMsg("User \"" .. usr .. "\" is muted ("..muter.."). Enjoy the silence!")
  217. end
  218.  
  219. cmds.unmute = {}
  220. cmds.unmute.desc = "Unmute the user"
  221. cmds.unmute.rank = 3
  222. function cmds.unmute.func(args, unmuter)
  223.   local usr = args[1]
  224.   muted[usr] = false
  225.   insertMsg("User \"" .. usr .. "\" is unmuted (" .. unmuter .. "). Enjoy the freedom!")
  226. end
  227.  
  228. cmds.me = {}
  229. cmds.me.desc = ""
  230. cmds.me.rank = 1
  231. function cmds.me.func(args, usr)
  232.   local msg = ""
  233.   for i = 1, #args, 1 do
  234.     msg = msg .. args[i] .. " "
  235.   end
  236.   msg = unicode.sub(msg, 1, -2)
  237.   insertMsg("["..os.date().."] *** " .. usr .. " " .. msg)
  238. end
  239.  
  240. cmds.ping = {}
  241. cmds.ping.desc = "Ping the server"
  242. cmds.ping.rank = 1
  243. function cmds.ping.func()
  244.   insertMsg("["..os.date() .."] Pong! :)")
  245. end
  246.  
  247. cmds.getinfo = {}
  248. cmds.getinfo.desc = "Get info about the server"
  249. cmds.getinfo.rank = 4
  250. function cmds.getinfo.func()
  251.   local energy = comp.energy()
  252.   local maxEn = comp.maxEnergy()
  253.   local memFree = comp.freeMemory()
  254.   local mem = comp.totalMemory()
  255.   insertMsg("Energy: " .. energy .. "/" .. maxEn)
  256.   insertMsg("Free: " .. memFree .. "B, cons: " .. mem - memFree .. "B, total: " .. mem)
  257. end
  258.  
  259. --[[END]]--
  260.  
  261. local function checkCommand(potCom)
  262.   local isCom = false
  263.   if potCom:sub(1,1) == "/" then
  264.     isCom = true
  265.   end
  266.   return isCom
  267. end
  268.  
  269. local function getInfo() end -- For further declaration...
  270.  
  271. local function issueCommand(sender, command, args)
  272.   local allowed = false
  273.   log("["..sender.."] Command: " .. command)
  274.   _, _, rank = getInfo(sender)
  275.   if cmds[command] then
  276.     if rank >= cmds[command].rank then
  277.       insertMsg("["..sender.."]: /" .. command)
  278.       cmds[command].func(args, sender)
  279.     end
  280.   end
  281. end
  282.  
  283. function getInfo(usr)
  284.   local prefix, suffix, rank, info
  285.   if user[usr] then
  286.     info = group[user[usr]]
  287.   else
  288.     info = group["default"]
  289.   end
  290.   prefix = info["prefix"]
  291.   suffix = info["suffix"]
  292.   rank = info["rank"]
  293.   return prefix, suffix, rank
  294. end
  295.  
  296. local function onReceive(sender, msg)
  297.   if not muted[sender] then
  298.     if not checkCommand(msg) then
  299.       local prefix, suffix, _ = getInfo(sender)
  300.       insertMsg("[" .. os.date():match("%d+:%d+:%d+") .. "] " .. prefix .. sender .. ": " .. msg .. suffix)
  301.     else  
  302.       local args = {}
  303.       for i in msg:gmatch("%s(%S+)") do
  304.         table.insert(args, i)
  305.       end
  306.       local command = msg:match("%w+")
  307.       issueCommand(sender, command, args)
  308.     end
  309.     updateChat()
  310.   end
  311. end
  312.  
  313. local function modemMsg(sender, port, dist, name, msg)
  314.   print(sender, port, dist, name, msg)
  315.   if name:sub(1, 1) == "!" then
  316.     print("Alternate message: " .. name)
  317.     name, msg = name:match("!(w+):(.+)")
  318.   end
  319.   if name and msg then
  320.     msg = unicode.sub(msg, 1, MAX_LEN)
  321.     local allowedPort = false
  322.     local allowedIP = false
  323.     for i = 1, #PORTS, 1 do
  324.       if PORTS[i][1] == port and PORTS[i][2] == true then
  325.         allowedPort = true
  326.         allowedIP = true
  327.       elseif PORTS[i][1] == port and PORTS[i][2] == false then
  328.         allowedPort = true
  329.       end
  330.     end
  331.     for i = 1, #ALLOWED, 1 do
  332.       if sender:match(ALLOWED[i]) then
  333.         allowedIP = true
  334.       end
  335.     end
  336.     if allowedPort and allowedIP then
  337.       onReceive("[NET]" .. name, msg)
  338.     end
  339.   end
  340. end
  341.  
  342. local i = 1
  343. if MOTD then
  344.   if fs.exists("/etc/chatserver.motd") then
  345.     local file = io.open("/etc/chatserver.motd", "r")
  346.     while true do
  347.       local curLine = file:read()
  348.       if not curLine then break end
  349.       insertMsg(curLine)
  350.     end
  351.     file:close()
  352.     updateChat()
  353.   else
  354.     local file = io.open("/etc/chatserver.motd", "w")
  355.     file:write("")
  356.     file:flush()
  357.     file:close()
  358.   end
  359. end
  360. while noexit do
  361.   local event, _, sender, uuid, msg, modem_name, modem_msg = event.pull(1)
  362.   if event == "modem_message" then
  363.     if modem_name ~= nil and modem_name ~= "" then
  364.       modemMsg(sender, uuid, msg, modem_name, modem_msg)
  365.     end
  366.   elseif event == "glasses_chat_command" then
  367.     if msg ~= nil and msg ~= "" then
  368.       msg = unicode.sub(msg, 1, MAX_LEN)
  369.       onReceive(sender, msg)
  370.     end
  371.   elseif event == "glasses_attach" then
  372.     insertMsg("User \"" .. sender .. "\" joined the chat server!")
  373.     updateChat()
  374.   elseif event == "glasses_detach" then
  375.     insertMsg("User \"" .. sender .. "\" left the chat server.")
  376.     updateChat()
  377.   end
  378.   if i == LIFETIME then
  379.     if chat[math.floor(MAX_MSG / 2) + 1] then
  380.       print("clearing...")
  381.       table.remove(chat, 1)
  382.       i = 0
  383.       updateChat()
  384.     else
  385.       i = 0
  386.     end
  387.     logFile:flush()
  388.   end
  389.   i = i + 1
  390. end
  391.  
  392. bridge.clear()
  393. bridge.sync()
  394. logFile:close()
  395. for i = 1, #PORTS, 1 do
  396.   modem.close(PORTS[i][1])
  397. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement