Advertisement
Guest User

Untitled

a guest
Jul 7th, 2018
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 60.70 KB | None | 0 0
  1. -- Max K. - 20.08.2017
  2. -- Shyvana HTC#2 - mcskill.ru
  3. local component = require("component")
  4. local computer = require("computer")
  5. local term = require("term")
  6. local event = require("event")
  7. local gpu = component.gpu
  8. local serialization = require("serialization")
  9. local unicode = require("unicode")
  10. local chat = component.chat_box
  11. local fs = require("filesystem")
  12. local shell = require("shell")
  13.  
  14. function sayLocal(msg)
  15. chat.say("local: " .. tostring(msg),40)
  16. end
  17.  
  18. chat.setName("§6G§7")
  19. setFG = gpu.setForeground
  20. setBG = gpu.setBackground
  21. gpu.setResolution(160,28)
  22. term.clear()
  23. color1 = "§3" -- дефолтное значение, переписывается в _config
  24. color2 = "§d" -- дефолтное значение, переписывается в _config
  25.  
  26. function dec(t)
  27. local s = ""
  28. for k,v in ipairs(t) do s = s .. string.char(v) end
  29. return s
  30. end
  31. function getCodedLink(filepath)
  32. local f,err = io.open(filepath,"r")
  33. if err then error(err) end
  34. local t = serialization.unserialize(f:read())
  35. return dec(t)
  36. end
  37. function getNormalLink(filepath)
  38. local f,err = io.open(filepath,"r")
  39. if err then error(err) end
  40. local l = f:read()
  41. return l
  42. end
  43. local c = {
  44. --download_main = "https://", -- ссылка на код бота, для самоапдейта -- эта и следующие ссылки инициализируются ниже
  45. --download_q = "https://", -- ссылка на список вопросов
  46. --download_rules = "https://", -- ссылка на список правил
  47. --download_config = "https://", -- ссылка на конфиг
  48. persiki = true, -- ответы в стиле "не флуди, персик"
  49. history_borderUp = 1,
  50. history_borderDown = 1,
  51. history_borderLeft = 1,
  52. history_borderRight = 1,
  53. history_rows = nil,
  54. history_highglight_color = 0xff0000,
  55. history_tabs_y = 1,
  56. screenWidth = nil,
  57. screenHeight = nil,
  58. frame_main_color = 0xff00ff,
  59. frame_tabs_name_color = 0xffffff,
  60. white = 0xffffff,
  61. server_reboot_period = 10800, -- нужно указать как часто сервер делает рестарты
  62. timeout_question = 60, -- кд на повторный ответ на тот же самый вопрос в чате
  63. timeout_greeting = 60, -- кд на приветствие в чате
  64. timeout_bye = 60, -- кд на прощание в чате
  65. cooldown_seen_command = 10, -- личный кд на команду -seen
  66. command_help = "-help",
  67. command_help2 = "-help2",
  68. command_inf = "-inf",
  69. command_mods = "-mods",
  70. command_yes = "-yes",
  71. command_no = "-no",
  72. --command_server = "-server",
  73. command_seen = "-seen",
  74. command_colors = "-colors",
  75. command_votestats = "-votestats",
  76. command_votestop = "-votestop",
  77. command_is_player_muted = "-ismuted",
  78. command_is_player_warned = "-iswarned",
  79. command_unmute = "-unmute",
  80. command_unwarn = "-unwarn",
  81. command_toggle_detect = "-toggledetect", -- стать невидимым для -mods
  82. command_memory_used = "-memory",
  83. command_retranslate = "==", -- говорить от имени бота
  84. command_reboot = "=restart", -- перезагрузка бота (обновляется код бота)
  85. command_reboot_2 = "=restart2", -- перезагрузка бота (обновляется список вопросов, правила, конфиг)
  86. command_reboot_3 = "=restart3", -- перезагрузка бота (обновляется все: код + вопросы + правила + конфиг)
  87. command_load_config = "=loadconfig", -- скачать _config по ссылке в чат
  88. command_stop = "=stop", -- остановить бота, сохранив только историю
  89. command_get_stats = "-stats", -- статистика мутов/варнов
  90. server_command_personal_cooldown = 5, -- личный кулдаун на команду -server
  91. warn_decay = 3600, -- период в секундах, на который бот запоминает свои варны. повторное нарушение дает мут вместо варна
  92. double_warn_mute_duration = 1800, -- длительность мута в случае двойного варна за censoredWords
  93. vote_easy_yes_to_pass = 2, -- во сколько голосов должен быть перевес для того, чтоб isEasy голосование прошло
  94. duration_mute_caps = 600, -- длительность мута за капс
  95. duration_mute_symbol_flood = 600, -- длительность мута за флуд символами
  96. duration_mute_flood = 900, -- длительность мута за флуд, в т.ч. торговыми сообщениями
  97. ratio_flood_symbol = 0.8, -- процент символов в сообщении для получения мута
  98. ratio_caps_symbol = 0.85, -- процент капса в сообщении для получения мута (также используется в isUsernameBad())
  99. flood_timeout = 45, -- таймаут для одинаковых сообщений
  100. flood_normal_messages_trigger = 3, -- сколько одинаковых сообщений подряд для мута
  101. flood_identical_trade_messages_trigger = 2, -- сколько одинаковых торговых сообщений подряд для мута
  102. flood_any_trade_messages_trigger = 3, -- сколько любых торговых сообщений ЗА flood_any_trade_messages_period СЕКУНД для получения мута
  103. flood_any_trade_messages_period = 180, -- период, за который учитываются торговые сообщения игрока для получения мута
  104.  
  105. }
  106.  
  107. if not serverCommandDisabled then
  108. c.command_server = "-server"
  109. end
  110.  
  111. c.download_main = getCodedLink("/MAIN_link")
  112. c.download_rules = getNormalLink("/_rules_link")
  113. c.download_q = getNormalLink("/_q_link")
  114. c.download_config = getNormalLink("/_config_link")
  115.  
  116. local historyTabs = {
  117. [1] = {name = "Questions", start = 2, width = 37, prefix = "[Q]", prefix2 = "%[Q%]", prefixColor = 0x00ff00}, -- 2 45
  118. [2] = {name = "Warned/Muted", start = 41, width = 93,prefix = "[M]", prefix2 = "%[M%]", prefixColor = 0xcd8700}, --49 91
  119. [3] = {name = "Commands", start = 136, width = 23,prefix = "[C]", prefix2 = "%[C%]", prefixColor = 0x00ff00},
  120. }
  121.  
  122. local censoredWords = {
  123. [1] = {list = {"пидор", "пидар", "ебать", "ёбаный", "ёбанный", "ёбырь", "ебырь", "ебнутый", "ёбнутый", "хер ", "хуй","хуйл", "нихуя", "хуя ", "ебись", "ебать", "пидр", "хуйня", "хуи ", "хуила", "нахуй", "похуй", "хуев", "хуёв", "хуес", "хуег", "отъебись", "отьебись", "отебись", "долбаеб", "долбаёб", "долбоеб", "долбоёб", "хуета", "хуита", "пизд", "ебаны","ебанны", "ёбан", "ебал", "наеб", "наёб", "ебу", "ебло", "уебок", "уёбо", "уебан", "уебки", "уёбки", "ахуеть", "ахуительно", "ахуенно", "охуенно", "охуительно", "заебись", "заебал", "ебет", "ебёт", "ебаца", "ебацца", "нехуя", "ебацо", "ибаца", "ибацца", "ебанат", "уебище", "уёбище", "выеб", "блядь", "блядин", "хуйня", "выбляд", "еблищ", "пиздяч", "впиздяч", "выблядова", "blyad", "blyat", "ebal", "pidor", "pidar", "hui", "huesos", "ueban", "uebok", "xyi", "xui", "пидрила", "мразь", "залуп", "гандон"}, duration = 1800},
  124. [2] = {list = {}, duration = 1200},
  125. [3] = {list = {"бля ", "сука", "чмо ", "педик", "хули ", "мудак", "мудила", "мудень", "мудозвон", "курва", "cyka", "suka",}, duration = "warn"},
  126. }
  127.  
  128. local helloWords = {"прив","q","ку","здаров","здоров","доброе утро","добрый день","добрый вечер","хай"}
  129. local byeWords = {"bb","бб","пока","свидания","досвид","спокойной"}
  130. local helloPhrases = {"Привет, persik :*","Как дела, persik :*","Давно не виделись, persik :*"}
  131. local byePhrases = {"Спокойной ночи, persik :*","Я буду скучать, persik :*","Не уходи, persik :(","до завтра, persik :*"}
  132. local ignoredCaps = {"ЭХПФ", "МФЭХ", "МФЭ", "SHIFT", "CTRL", "ALT"}
  133. local persiki = {"солнышко", "зайчик", "пупсик", "котик", "сладкий", "милый", "медвежонок", "ангелочек", "одуванчик", "малыш", "кисик", "любимый", "родной", "симпотяжка", "львеночек", "тигреночек", "пушистик", "персик", "пончик", "котенок","апельсинчик","арбузик","бельчонок","лапочка","лисёнок","очаровашка",}
  134.  
  135. c.screenWidth, c.screenHeight = gpu.getResolution()
  136. c.history_rows = c.screenHeight - c.history_borderUp - c.history_borderDown
  137.  
  138. local messages = {}
  139. -- инициализируются в initialization()
  140. --local history = {}
  141. --local mutes = {} -- mutes["Shyvana"] = 29111 - содержит computer.uptime() момента, когда мут истечет
  142. --local warns = {} -- warns["Shyvana"] = 29111 - содержит computer.uptime() момента, когда варн истечет
  143. --local stats = {} -- статы банов, мутов, длительности мутов
  144. --local timesAnswered = {} -- сколько раз ответил на вопросы
  145.  
  146. function initialization()
  147. -- считывает файлы _q, _rules, _config и не стартует без них. потом загружает __history, __messages, __mutes, __warns чтобы продолжить работу там где закончил до рестарта. иначе начинает с нуля
  148. local currentTime = computer.uptime()
  149. local exit = false
  150. local files = {
  151. "/home/_q",
  152. "/home/_rules",
  153. "/home/_config",
  154. }
  155.  
  156. sayLocal(color2 .. "Запуск . . .")
  157. for _,file in ipairs(files) do
  158. if fs.exists(file) then
  159. loadfile(file)()
  160. print(file .. " - OK")
  161. sayLocal(color1 .. file .. "§2 - ok")
  162. else
  163. sayLocal(color1 .. file .. "§c - !не найден!")
  164. print(" !!! не найден файл " .. file)
  165. exit = true
  166. end
  167. end
  168. if exit then
  169. sayLocal("§4 запуск невозможен")
  170. os.exit()
  171. end
  172. function historyInitialize()
  173. for i = 1,#historyTabs do
  174. history[i] = {}
  175. for ii = 1,c.history_rows do
  176. history[i][ii] = {text = "", highlight = nil}
  177. end
  178. end
  179. end
  180. function restoreTable(file,noRemove) -- noRemove чтобы не удалять файл после загрузки (для статов банов/мутов)
  181. if fs.exists(file) then
  182. local f,err = io.open(file,"r")
  183. if err then
  184. print(err)
  185. exit = true
  186. else
  187. local res = f:read()
  188. f:close()
  189. res = serialization.unserialize(res)
  190. sayLocal(color1 .. file .. "§2 - возобновлен")
  191. if not noRemove then
  192. fs.remove(file)
  193. end
  194. return res
  195. end
  196. else
  197. sayLocal(color1 .. file .. "§c не возобновлен")
  198. end
  199. end
  200.  
  201. function fixMutesAndWarns(table) -- фиксит mutes и warns (в файле записано оставшееся время мута, а ф-я меняет его на computer.uptime() момента, когда мут истечет минус пару сек для компенсации времени рестарта)
  202. for k,v in pairs(table) do
  203. table[k] = table[k] + currentTime - 5
  204. end
  205. end
  206. -- продублировать все в saveAllStates()
  207. history = restoreTable("/home/__history")
  208. if history == nil then
  209. history = {}
  210. historyInitialize()
  211. end
  212. --messages = restoreTable("/home/__messages") or {}
  213. mutes = restoreTable("/home/__mutes") or {}
  214. warns = restoreTable("/home/__warns") or {}
  215.  
  216. fixMutesAndWarns(mutes)
  217. fixMutesAndWarns(warns)
  218.  
  219. stats = restoreTable("/home/__stats",true) or {}
  220.  
  221. if exit then
  222. os.exit()
  223. else
  224. sayLocal(color2 .. "Бот запущен")
  225. term.clear()
  226. end
  227. end
  228.  
  229. initialization()
  230.  
  231. local coloring = {"&0","&1","&2","&3","&4","&5","&6","&7","&8","&9","&a","&b","&c","&d","&e","&f","&l","&m","&n","&o","&r"}
  232.  
  233. --local mainWorld = 0 -- id главного мира, через component.debug.getWorld().getDimensionId() например
  234. local activeVote = false -- "=votesun"
  235. local activeVoteTimerId
  236. local hasUserVoted = {}
  237. local currentVoteResults = {
  238. yes = 0,
  239. no = 0,
  240. }
  241. local questionLastTriggered = {}
  242. local serverCommandCooldowns = {} -- serverCommandCooldowns["Shyvana"] = 29111 - содержит computer.uptime() момента, когда кд на команду -server истечет
  243. local seenCommandCooldowns = {} -- seenCommandCooldowns["Shyvana"] = 29111 - содержит computer.uptime() момента, когда кд на команду -seen истечет
  244. local greetingCooldown = 0 -- содержит computer.uptime() момента, когда глобальный кд на приветствие истечет
  245. local byeCooldown = 0 -- содержит computer.uptime() момента, когда глобальный кд на прощание истечет
  246. function isRaining()
  247. return debug.getWorld(mainWorld).isRaining()
  248. end
  249. function turnOffRain()
  250. debug.getWorld(mainWorld).setRaining(false)
  251. end
  252. function setMorning()
  253. debug.getWorld(mainWorld).setTime(0)
  254. end
  255. function none()
  256. return true
  257. end
  258. local votes = {
  259. ["-votesun"] = {
  260. lastActivatedByPlayer = {}, -- не трогать
  261. lastActivated = 0, -- не трогать
  262. StaticGlobalCooldown = 900, -- глобальный кулдаун для всех игроков на использование именно этого голосования
  263. StaticPersonalCooldown = 1800, -- личный кулдаун каждого игрока на использование именно этого голосования
  264. text = "отключение дождя", -- "игрок начал голосование за" ..
  265. duration = 25, -- время в секундах, которое дается на голосование
  266. isEasy = true, -- легко проголосовать "да" (не юзать в votemute). перевес определяется в c.vote_easy_yes_to_pass
  267. startCondition = isRaining, -- возможно начать голосование только если эта функция вернет true. ВСЕ ФУНКЦИИ ДОЛЖНЫ СТОЯТЬ ВЫШЕ ЭТОЙ ТАБЛИЦЫ. указать none если условие не нужно
  268. denyMsg = "в данный момент дождя нет", -- что получит пользователь в ответ если startCondition == false
  269. passFunction = turnOffRain, -- функция, которая вызовется если голосование пройдет
  270. passMessage = "дождь отключен", -- отчет в глобал чат если голосование пройдет
  271. failFunction = none, -- функция, которая вызовется, если голосование провалится
  272. failMessage = "дождь не отключен", -- отчет в глобал чат если голосование не пройдет
  273. },
  274. ["-voteday"] = {
  275. lastActivatedByPlayer = {},
  276. lastActivated = 0,
  277. StaticGlobalCooldown = 1800,
  278. StaticPersonalCooldown = 3600,
  279. text = "смену времени суток на утро",
  280. duration = 25,
  281. isEasy = true,
  282. startCondition = none,
  283. denyMsg = " ",
  284. passFunction = setMorning,
  285. passMessage = "утро включено",
  286. failFunction = none,
  287. failMessage = "время суток не изменено",
  288. },
  289. }
  290.  
  291. function say(msg0,shouldIgnore) -- shouldIgnore - будет ли ф-я будет игнорировать uppercaseGlobal (true - не будет менять первую букву на заглавную)
  292. local msg = tostring(msg0)
  293. if uppercaseGlobal and not shouldIgnore then
  294. if string.find(msg,"§") == 1 then -- если вдруг первая буква - установка цвета
  295. msg = unicode.sub(msg,0,2) .. unicode.upper(unicode.sub(msg,3,3)) .. unicode.sub(msg,4)
  296. else
  297. msg = unicode.upper(unicode.sub(msg,0,1)) .. unicode.sub(msg,2)
  298. end
  299. end
  300. if LIVE then
  301. chat.say(CHATNAME .. msg)
  302. else
  303. chat.say(CHATNAME .. msg,40)
  304. end
  305. end
  306.  
  307. function cmdReal(command)
  308. chat.say(tostring(command))
  309. end
  310. function cmd(command)
  311. if LIVE then
  312. chat.say(tostring(command))
  313. else
  314. say("CMD: " .. command)
  315. end
  316. end
  317. function whisper(player,text0)
  318. local text = tostring(text0)
  319. if uppercaseWhisper then
  320. if string.find(text,"§") == 1 then -- если вдруг первая буква - установка цвета
  321. text = unicode.sub(text,0,2) .. unicode.upper(unicode.sub(text,3,3)) .. unicode.sub(text,4)
  322. else
  323. text = unicode.upper(unicode.sub(text,0,1)) .. unicode.sub(text,2)
  324. end
  325. end
  326. chat.say("m " .. player .. " " .. text)
  327. end
  328. function drawMainFrame()
  329. setFG(c.frame_main_color)
  330. gpu.set(1,1,string.rep("─",c.screenWidth)) -- ═
  331. gpu.set(1,c.screenHeight,string.rep("─",c.screenWidth)) -- ═
  332. gpu.set(1,1,string.rep("│",c.screenHeight),true) -- ║
  333. gpu.set(c.screenWidth,1,string.rep("│",c.screenHeight),true)
  334. gpu.set(1,1,"┌") --╔
  335. gpu.set(c.screenWidth,1,"┐")
  336. gpu.set(1,c.screenHeight,"└")
  337. gpu.set(c.screenWidth,c.screenHeight,"┘")
  338. for i = 1,#historyTabs do
  339. drawCenteredText(historyTabs[i].start,c.history_tabs_y,historyTabs[i].width,"┤ " .. historyTabs[i].name .. " ├")
  340. setFG(c.frame_tabs_name_color)
  341. drawCenteredText(historyTabs[i].start,c.history_tabs_y,historyTabs[i].width,historyTabs[i].name )
  342. setFG(c.frame_main_color)
  343. end
  344. for ii = 1,#historyTabs-1 do
  345. gpu.set(historyTabs[ii].start+historyTabs[ii].width+1,c.history_tabs_y,string.rep("│",c.history_rows+2),true)
  346. gpu.set(historyTabs[ii].start+historyTabs[ii].width+1,c.history_tabs_y,"┬")
  347. gpu.set(historyTabs[ii].start+historyTabs[ii].width+1,c.history_tabs_y+c.history_rows+1,"┴")
  348. end
  349. setFG(c.white)
  350. end
  351.  
  352. function drawCenteredText(x,y,width,text)
  353. gpu.set(x+math.floor(width/2)-math.floor(unicode.len(text)/2),y,text)
  354. end
  355. function log(index,text,highlightedText)
  356. local text = historyTabs[index].prefix .. text
  357. local extra = unicode.len(text) - historyTabs[index].width
  358. if extra <= 0 then
  359. table.insert(history[index],{text = text .. string.rep(" ",-extra), highlight = highlightedText})
  360. table.remove(history[index],1)
  361. else
  362. local text1
  363. local text2
  364. if highlightedText then
  365. local a,b = string.find(text,highlightedText)
  366. if a then
  367. if a <= historyTabs[index].width and b > historyTabs[index].width then
  368. text1 = unicode.sub(text,0,a-1)
  369. text2 = unicode.sub(text,a,a+historyTabs[index].width)
  370. else
  371. text1 = unicode.sub(text,0,historyTabs[index].width)
  372. text2 = unicode.sub(text,historyTabs[index].width+1,historyTabs[index].width*2)
  373. end
  374. else
  375. text1 = unicode.sub(text,0,historyTabs[index].width)
  376. text2 = unicode.sub(text,historyTabs[index].width+1,historyTabs[index].width*2)
  377. end
  378. else
  379. text1 = unicode.sub(text,0,historyTabs[index].width)
  380. text2 = unicode.sub(text,historyTabs[index].width+1,historyTabs[index].width*2)
  381. end
  382. table.insert(history[index],{text = text1 .. string.rep(" ",historyTabs[index].width-unicode.len(text1)), highlight = highlightedText})
  383. table.insert(history[index],{text = text2 .. string.rep(" ",historyTabs[index].width-unicode.len(text2)), highlight = highlightedText})
  384. table.remove(history[index],1)
  385. table.remove(history[index],2)
  386. end
  387. historyDraw()
  388. end
  389. function historyDraw()
  390. for column = 1,#historyTabs do
  391. for row = c.history_rows,1,-1 do
  392. drawStringWithHighlight(historyTabs[column].start,c.history_borderUp+row,history[column][row].text,history[column][row].highlight,column)
  393. end
  394. end
  395. end
  396. function drawStringWithHighlight(x,y,string,highlight,index)
  397. if index and string.find(string,historyTabs[index].prefix2) == 1 then
  398. gpu.set(x,y,string.sub(historyTabs[index].prefix,1,1))
  399. setFG(historyTabs[index].prefixColor)
  400. gpu.set(x+1,y,string.sub(historyTabs[index].prefix,2,2))
  401. setFG(c.white)
  402. gpu.set(x+2,y,string.sub(historyTabs[index].prefix,3,3))
  403. local newstring = string.sub(string,string.len(historyTabs[index].prefix)+1)
  404. drawStringWithHighlight(x+string.len(historyTabs[index].prefix),y,newstring,highlight)
  405. else
  406. if highlight ~= nil then
  407. local a,b = string.find(unicode.lower(string),highlight)
  408. if a == nil then
  409. gpu.set(x,y,string)
  410. elseif a > 1 then
  411. local newstring0 = string.sub(string,0,a-1)
  412. gpu.set(x,y,newstring0)
  413. local newstring = string.sub(string,a)
  414. drawStringWithHighlight(x+unicode.len(newstring0),y,newstring,highlight)
  415. elseif a == 1 then
  416. setFG(c.history_highglight_color)
  417. local newstring0 = string.sub(string,0,b)
  418. gpu.set(x,y,newstring0)
  419. setFG(0xffffff)
  420. local newstring = string.sub(string,b+1)
  421. drawStringWithHighlight(x+unicode.len(newstring0),y,newstring,highlight)
  422. end
  423. else
  424. gpu.set(x,y,string)
  425. end
  426. end
  427. end
  428. function getIndex(table,ind)
  429. --say("getindex")
  430. local ind = unicode.lower(ind)
  431. for k,_ in pairs(table) do
  432. if unicode.lower(k) == ind then
  433. return k
  434. end
  435. end
  436. end
  437. function isModerator(name)
  438. for _,group in ipairs(mods) do
  439. for _,nick in ipairs(group.list) do
  440. if nick == name then
  441. return true
  442. end
  443. end
  444. end
  445. return false
  446. end
  447. function isPlayerMuted(name0,specificCase) -- если specificCase = true то будет проверять ник только по заданному регистру, а не по всем
  448. local currentTime = computer.uptime()
  449. local name = name0
  450. if not specificCase then
  451. name = getIndex(mutes,name)
  452. end
  453. if mutes[name] and (mutes[name] > currentTime) then
  454. return true, math.floor(mutes[name] - currentTime), name
  455. else
  456. return false
  457. end
  458. end
  459. function isPlayerWarned(name) -- имеет ли активный варн
  460. local currentTime = computer.uptime()
  461. name = getIndex(warns,name)
  462. if warns[name] and (warns[name] > currentTime) then
  463. return true, math.floor(warns[name] - currentTime), name
  464. else
  465. return false
  466. end
  467. end
  468. function canPlayerUseServerCommand(name)
  469. local currentTime = computer.uptime()
  470. if serverCommandCooldowns[name] and (serverCommandCooldowns[name] > currentTime) then
  471. return false, math.floor(serverCommandCooldowns[name] - currentTime)
  472. else
  473. return true
  474. end
  475. end
  476. function canPlayerUseSeenCommand(name)
  477. local currentTime = computer.uptime()
  478. if seenCommandCooldowns[name] and (seenCommandCooldowns[name] > currentTime) then
  479. return false, math.floor(seenCommandCooldowns[name] - currentTime)
  480. else
  481. return true
  482. end
  483. end
  484. function statsAdd(player,type,duration)
  485. if not stats[player] then
  486. stats[player] = {mutes = 0 , warns = 0, duration = 0}
  487. end
  488. if type == "mute" then
  489. stats[player].mutes = stats[player].mutes + 1
  490. stats[player].duration = stats[player].duration + duration
  491. elseif
  492. type == "warn" then
  493. stats[player].warns = stats[player].warns + 1
  494. end
  495. saveStateOf("stats",stats,1,true)
  496. end
  497. function tempMute(name,duration,reason)
  498. mutes[name] = computer.uptime() + duration
  499. cmd("tempmute " .. name .. " " .. duration .. " sec " .. reason)
  500. statsAdd(name,"mute",duration)
  501. end
  502. function warn(name,reason)
  503. cmd("warn " .. name .. " " .. reason)
  504. warns[name] = computer.uptime() + c.warn_decay
  505. statsAdd(name,"warn")
  506. end
  507. function isGlobal(msg)
  508. if LIVE == true then
  509. if string.find(msg,"!") == 1 then
  510. return true
  511. else
  512. return false
  513. end
  514. else
  515. if string.find(msg,"%.") == 1 or string.find(msg,"!") == 1 then
  516. return true
  517. else
  518. return false
  519. end
  520. end
  521. end
  522. function isOnline(player)
  523. if debug.getPlayer(player).getGameType() == nil then
  524. return false
  525. else
  526. return true
  527. end
  528. end
  529. function isOnlineFaster(table,name) -- получает таблицу debug.getPlayers()
  530. for k,v in ipairs(table) do
  531. if v == name then
  532. return true
  533. end
  534. end
  535. return false
  536. end
  537. function deColor(string)
  538. local text = string
  539. for _,v in pairs(coloring) do
  540. text = string.gsub(text,v,"")
  541. end
  542. return text
  543. end
  544. function processMods(msg0,player)
  545. local msg = unicode.lower(msg0)
  546. if msg == c.command_mods then
  547. local strings = {}
  548. log(3,player .. ": " .. msg0)
  549. local t = debug.getPlayers()
  550. for index,this in ipairs(mods) do
  551. for _,name in ipairs(this.list) do
  552. if isOnlineFaster(t,name) then
  553.  
  554. if (not masters[name]) or (not masters[name].undetectable) then
  555. table.insert(strings,"m " .. player .. " §aonline §8> [" .. this.prefixColor .. this.group .. "§8] " .. this.nameColor .. name)
  556. end
  557. end
  558. end
  559. end
  560. for k,v in ipairs(strings) do
  561. cmdReal(v)
  562. end
  563. end
  564. end
  565. function processQuestions(msg0,name)
  566. local msg = unicode.lower(msg0)
  567. local currentTime = computer.uptime()
  568. function checkWordBlock(wordblock)
  569. for _,word in ipairs(wordblock) do
  570. if string.find(msg,word) then
  571. return true
  572. end
  573. end
  574. return false
  575. end
  576. function canTriggerQuestion(ind)
  577. if questionLastTriggered[ind] then
  578. if (questionLastTriggered[ind] + c.timeout_question) > currentTime then
  579. return false
  580. else
  581. return true
  582. end
  583. else
  584. return true
  585. end
  586. end
  587.  
  588. for ind,question in ipairs(Q) do
  589. local shouldAnswer = true
  590. for _,wordblock in ipairs(question) do
  591. if checkWordBlock(wordblock) == false then
  592. shouldAnswer = false
  593. break
  594. end
  595. end
  596. if shouldAnswer then
  597. if canTriggerQuestion(ind) or (masters[name] and masters[name].canSkipQuestionsCooldown) then
  598. local answer = Q[ind].response
  599. answer = string.gsub(string.gsub(answer,"#c1",color1),"#c2",color2)
  600. say(answer)
  601. questionLastTriggered[ind] = currentTime
  602. log(1,name .. ": " .. msg0)
  603. return true
  604. end
  605. end
  606. end
  607. end
  608. function processCensoredWords(msg0,name)
  609. local msg = unicode.lower(msg0)
  610. if not (masters[name] and masters[name].canCurse) then
  611. for _,wordSet in ipairs(censoredWords) do
  612. for _,word in pairs(wordSet.list) do
  613. if string.find(msg,word) then
  614. if not string.find(msg,"%S" .. word) then
  615. if isModerator(name) == false or (masters[name] and masters[name].canIgnoreModeratorCheckForCW) then
  616. if wordSet.duration == "warn" then
  617. if not isPlayerWarned(name) then
  618. warn(name,"autowarn 3.1 (ругательства)")
  619. persikAnswer(5,name)
  620. log(2,"(3.1) warn " .. name .. ": " .. msg0,word)
  621. else
  622. tempMute(name,c.double_warn_mute_duration,"automute 3.1 (ругательства)+")
  623. persikAnswer(2,name)
  624. log(2,"(3.1) " .. name .. ": " .. msg0,word)
  625. warns[name] = nil
  626. end
  627. return true
  628. else
  629. tempMute(name,wordSet.duration,"automute 3.1 (ругательства)")
  630. persikAnswer(2,name)
  631. log(2,"(3.1) " .. name .. ": " .. msg0,word)
  632. return true
  633. end
  634. else
  635. say(color1 .. name .. ", ты же модератор, не ругайся :*")
  636. log(2," mod? " .. name .. ": " .. msg0,word)
  637. return true
  638. end
  639. end
  640. end
  641. end
  642. end
  643. end
  644. end
  645. function processInf(msg0,name)
  646. local msg = unicode.lower(msg0)
  647. if msg == c.command_inf then
  648. whisper(name,color1 .. "необходимо указать пункт правил, например, " .. color2 .. c.command_inf .. " 3.1")
  649. else
  650. if string.find(msg,c.command_inf .. " ") == 1 then
  651. local rule = rules[string.sub(msg,string.len(c.command_inf)+2)] or rules[string.gsub(string.sub(msg,string.len(c.command_inf)+2),",",".")]
  652. if rule then
  653. whisper(name,color2 .. string.gsub(string.sub(msg,string.len(c.command_inf)+2),",",".") .. ": " .. color1 .. rule.text)
  654. if rule.punishment then
  655. whisper(name,string.gsub(string.gsub(rule.punishment,"Наказание:",color2 .. "Наказание:" .. color1),"За нарушение правил:",color2 .. "За нарушение правил:" .. color2))
  656. end
  657. log(3,name .. ": " .. msg0)
  658. else
  659. whisper(name,color1 .. "пункт правил указан неверно")
  660. end
  661. end
  662. end
  663. end
  664. function processCaps(msg,name)
  665. local newmsg
  666. function isUsernameBad(username)
  667. local username = string.gsub(username,"%d","")
  668. local username = string.gsub(username,"%p","")
  669. local total = unicode.len(username)
  670. if total > 5 then
  671. local bad = 0
  672. for i = 1,total do
  673. local char = unicode.sub(username,i,i)
  674. if char ~= unicode.lower(char) then
  675. bad = bad + 1
  676. end
  677. end
  678. if bad/total > c.ratio_caps_symbol then
  679. return true
  680. else
  681. return false
  682. end
  683. else
  684. return false
  685. end
  686. end
  687. function getBadUsernames()
  688. local t = debug.getPlayers()
  689. local res = {}
  690. for _,player in ipairs(t) do
  691. if isUsernameBad(player) then
  692. table.insert(res,player)
  693. end
  694. end
  695. return res
  696. end
  697.  
  698. for _,word in ipairs(ignoredCaps) do
  699. newmsg = string.gsub(msg,word,"")
  700. end
  701. local newmsg = string.gsub(newmsg,"%d","")
  702. local newmsg = string.gsub(newmsg,"%p","")
  703. local newmsg = string.gsub(newmsg," ","")
  704. if unicode.len(newmsg) > 7 then
  705. local total = unicode.len(newmsg)
  706. local bad = 0
  707. for i = 1,total do
  708. local char = unicode.sub(newmsg,i,i)
  709. if char ~= unicode.lower(char) then
  710. bad = bad + 1
  711. end
  712. end
  713. if bad/total > c.ratio_caps_symbol then
  714. for k,player in ipairs(getBadUsernames()) do
  715. if string.find(msg,player) then
  716. return true
  717. end
  718. end
  719. if isModerator(name) == false or (masters[name] and masters[name].canIgnoreModeratorCheckForCW) then
  720. tempMute(name,c.duration_mute_caps,"automute 3.1 (капс)")
  721. persikAnswer(1,name)
  722. log(2,"(3.1 caps)" .. name .. ": " .. msg)
  723. else
  724. say(color1 .. name .. ", ты же модератор, не капси :*")
  725. end
  726. end
  727. end
  728. end
  729. function processSymbolFlood(msg,name)
  730. local len1 = unicode.len(msg)
  731. if len1 >= 12 then
  732. local _,len2 = string.gsub(msg,"%p","")
  733. if (len2/len1) > c.ratio_flood_symbol then
  734. if isModerator(name) == false or (masters[name] and masters[name].canIgnoreModeratorCheckForCW) then
  735. tempMute(name,c.duration_mute_symbol_flood,"automute 3.1 (флуд символами)")
  736. persikAnswer(3,name)
  737. log(2,"3.1 (symbol flood)" .. name .. ": " .. msg)
  738. else
  739. say(color1 .. name .. ", ты же модератор, не флуди :*")
  740. end
  741. end
  742. end
  743. end
  744. function processFlood(msg0,name)
  745. local msg = unicode.lower(msg0)
  746. local function isTradeMsg(msg)
  747. local len = unicode.len(msg)
  748. local tradeFilter = {"купл","продам","кто продаст","продаю "}
  749. local tradeFilter2 = {"warp"}
  750. for _,word in ipairs(tradeFilter) do
  751. if string.find(msg,word) and len > 12 then
  752. return true
  753. end
  754. end
  755. for _,word in ipairs(tradeFilter2) do
  756. if string.find(msg,word) and len > 30 then
  757. return true
  758. end
  759. end
  760. return false
  761. end
  762. local isTrade = isTradeMsg(msg)
  763. local currentTime = computer.uptime()
  764. if not messages[name] then
  765. messages[name] = {}
  766. end
  767. if not messages[name].previous then
  768. messages[name].anyTradeTimers = {}
  769. for i = 1,c.flood_any_trade_messages_trigger do
  770. messages[name].anyTradeTimers[i] = 0
  771. end
  772. end
  773. if not messages[name].previous or messages[name].previous ~= msg or messages[name].time <= currentTime - c.flood_timeout then
  774. messages[name].previous = msg
  775. messages[name].time = currentTime
  776. messages[name].subsequents = 1
  777. else
  778. messages[name].subsequents = messages[name].subsequents + 1
  779. end
  780. if isTrade then
  781. table.insert(messages[name].anyTradeTimers,currentTime)
  782. table.remove(messages[name].anyTradeTimers,1)
  783. end
  784. if isTrade and messages[name].subsequents >= c.flood_identical_trade_messages_trigger then
  785. if isModerator(name) == false or (masters[name] and masters[name].canIgnoreModeratorCheckForCW) then
  786. tempMute(name,c.duration_mute_flood,"automute 3.6 (частая реклама)")
  787. persikAnswer(4,name)
  788. messages[name].previous = nil
  789. log(2,"(3.6: x" .. c.flood_identical_trade_messages_trigger .." in a row)" .. name .. ": " .. msg0,word)
  790. else
  791. say(color1 .. name .. ", ты же модератор, не флуди :*")
  792. end
  793. elseif messages[name].subsequents >= c.flood_normal_messages_trigger then
  794. if isModerator(name) == false or (masters[name] and masters[name].canIgnoreModeratorCheckForCW) then
  795. tempMute(name,c.duration_mute_flood,"automute 3.1 (флуд)")
  796. persikAnswer(3,name)
  797. messages[name].previous = nil
  798. log(2,"(3.1: x" .. c.flood_normal_messages_trigger ..")" .. name .. ": " .. msg0,word)
  799. else
  800. say(color1 .. name .. ", ты же модератор, не флуди :*")
  801. end
  802. elseif isTrade and messages[name].anyTradeTimers[1] ~= 0 and (currentTime - messages[name].anyTradeTimers[1]) <= c.flood_any_trade_messages_period then
  803. if isModerator(name) == false or (masters[name] and masters[name].canIgnoreModeratorCheckForCW) then
  804. tempMute(name,c.duration_mute_flood,"automute 3.6 (частая реклама+)")
  805. persikAnswer(4,name)
  806. messages[name].previous = nil
  807. log(2,"(3.6+: x" .. c.flood_any_trade_messages_trigger .." in " .. c.flood_any_trade_messages_period .. "s)" .. name .. ": " .. msg0,word)
  808. else
  809. say(color1 .. name .. ", ты же модератор, не флуди :*")
  810. end
  811. end
  812. end
  813. function getVoteCurrentGlobalCooldown(command)
  814. if votes[command] then
  815. if votes[command].lastActivated == 0 then
  816. return 0
  817. else
  818. local cd = (votes[command].lastActivated + votes[command].StaticGlobalCooldown) - computer.uptime()
  819. if cd <= 0 then
  820. return 0
  821. elseif cd > 0 then
  822. return cd
  823. end
  824. end
  825. else
  826. error("#1")
  827. end
  828. end
  829. function getCurrentVoteTimer()
  830. if activeVote then
  831. local time = (votes[activeVote].lastActivated + votes[activeVote].duration) - computer.uptime()
  832. if time > 0 then
  833. return time
  834. else
  835. return 0
  836. end
  837. else
  838. return "NIL"
  839. end
  840. end
  841. function getVoteCurrentPersonalCooldown(command,name)
  842. if votes[command] then
  843. local last = votes[command].lastActivatedByPlayer[name]
  844. if last then
  845. local cd = (last + votes[command].StaticPersonalCooldown) - computer.uptime()
  846. if cd <= 0 then
  847. return 0
  848. elseif cd > 0 then
  849. return cd
  850. end
  851. else
  852. return 0
  853. end
  854. else
  855. error("#2")
  856. end
  857. end
  858. function pushEndvoteSignal()
  859. event.push("endvote",1) -- 1 значит что голосование закончилось само по себе и выдаст результат
  860. end
  861. function processVoteStart(msg0,name)
  862. local msg = unicode.lower(msg0)
  863. if votes[msg] then
  864. currentTime = computer.uptime()
  865. if not activeVote then
  866. if votes[msg].startCondition() == true or (masters[name] and masters[name].canSkipVoteStartCondition) then
  867. if getVoteCurrentGlobalCooldown(msg) == 0 or (masters[name] and masters[name].canSkipVoteGlobalCooldown) then
  868. if getVoteCurrentPersonalCooldown(msg,name) == 0 or (masters[name] and masters[name].canSkipVotePersonalCooldown) then
  869. log(3,name .. ": " .. msg0)
  870. activeVote = msg
  871. votes[msg].lastActivated = currentTime
  872. votes[msg].lastActivatedByPlayer[name] = currentTime
  873. activeVoteTimerId = event.timer(votes[msg].duration,pushEndvoteSignal,1)
  874. currentVoteResults.yes = currentVoteResults.yes+1
  875. hasUserVoted[name] = true
  876. say(color1 .. "Игрок ".. color2 .. name .. color1 .. " начал голосование за " .. votes[msg].text)
  877. say(color1 .. "Введите " .. color2 .. c.command_yes .. color1 .. " или " .. color2 .. c.command_no .. color1 .. " в локальный чат. Голосование длится " .. color2 .. votes[msg].duration .. color1 .. " секунд")
  878. else
  879. local answer = color1 .. "твой личный кулдаун на это голосование еще не истек. Осталось " .. color2 .. math.floor(getVoteCurrentPersonalCooldown(msg,name)) .. color1 .. " секунд"
  880. whisper(name,answer)
  881. end
  882. else
  883. local answer = color1 .. "глобальный кулдаун на это голосование еще не истек. Осталось " .. color2 .. math.floor(getVoteCurrentGlobalCooldown(msg)) .. color1 .. " секунд"
  884. whisper(name,answer)
  885. end
  886. else
  887. local answer = color1 .. votes[msg].denyMsg
  888. whisper(name,answer)
  889. end
  890. else
  891. local answer = color1 .. "идет другое голосование"
  892. whisper(name,answer)
  893. end
  894. end
  895. end
  896. function processActiveVote(msg0,name)
  897. local msg = unicode.lower(msg0)
  898. if msg == c.command_yes or msg == c.command_no then
  899. if activeVote then
  900. if not hasUserVoted[name] or (masters[name] and masters[name].infiniteVote) then
  901. if msg == c.command_yes then
  902. currentVoteResults.yes = currentVoteResults.yes+1
  903. whisper(name,color1 .. "ты проголосовал §2\"за\"")
  904. elseif msg == c.command_no then
  905. currentVoteResults.no = currentVoteResults.no+1
  906. whisper(name,color1 .. "ты проголосовал §4\"против\"")
  907. end
  908. hasUserVoted[name] = true
  909. end
  910. else
  911. whisper(name,color1 .. "нет активных голосований")
  912. end
  913. end
  914. end
  915. function processServerCommand(msg,name)
  916. local msg = unicode.lower(msg)
  917. if msg == c.command_server then
  918. local can,leftt = canPlayerUseServerCommand(name)
  919. if can or (masters[name] and masters[name].canSkipServerCommandCooldown) then
  920. log(3,name .. ": " .. msg)
  921. local _,report = chat.say("mem")
  922. if report then
  923. local hour = string.match(report,"(%d+)%Dчас") or 0
  924. local min = string.match(report,"(%d+)%Dмину") or 0
  925. local sec = string.match(report,"(%d+)%Dсеку") or 0
  926. local tps = string.match(report,"TPS%D*(.-)\n") or "NIL"
  927. local left = c.server_reboot_period-(hour*3600+min*60+sec)
  928. local hoursleft = math.floor(left/3600)
  929. local minleft = math.floor((left-hoursleft*3600)/60)
  930. local secleft = math.floor(left-hoursleft*3600-minleft*60)
  931. local answer = color1 .. "До рестарта: "
  932. if hoursleft ~= 0 then
  933. answer = answer .. color2 .. hoursleft .. color1 .. " час(а) "
  934. end
  935. local answer = answer .. color2 .. minleft .. color1 .. " минут " .. color2 .. secleft .. color1 .. " секунд"
  936.  
  937. if fakeTPS then
  938. tps = math.random(18,19)
  939. if tps == 18 then
  940. tps = tostring(tps) .. "." .. tostring(math.random(7,9))
  941. else
  942. tps = tostring(tps) .. "." .. tostring(math.random(0,9))
  943. end
  944. end
  945.  
  946. whisper(name,color1 .. "TPS: " .. color2 .. tps)
  947. whisper(name,answer)
  948. serverCommandCooldowns[name] = computer.uptime() + c.server_command_personal_cooldown
  949. end
  950. else
  951. whisper(name,color1 .. "Времени до повторного использования этой команды: " .. color2 .. leftt .. color1 .. " секунд(ы)")
  952. end
  953. end
  954. end
  955. function processSeen(msg,name)
  956. if string.find(msg,c.command_seen) == 1 then
  957. log(3,name .. ": " .. msg)
  958. local can, dur = canPlayerUseSeenCommand(name)
  959. if can or (masters[name] and masters[name].canSkipSeenCommandCooldown) then
  960. local target = string.sub(msg,unicode.len(c.command_seen)+2)
  961. if target == "" then
  962. whisper(name,color1 .. "не указано имя")
  963. return true
  964. elseif masters[getIndex(masters,target)] and masters[getIndex(masters,target)].hiddenFromSeenCommand then
  965. whisper(name,color1 .. "ты не можешь использовать эту команду на " .. color2 .. getIndex(masters,target))
  966. return true
  967. end
  968. local _,str = chat.say("seen " .. target)
  969. local status = ""
  970. if string.find(str,"Ошибка") then
  971. whisper(name,color1 .. "игрок " .. color2 .. target .. color1 .. " не найден")
  972. return true
  973. end
  974. seenCommandCooldowns[name] = computer.uptime() + c.cooldown_seen_command
  975.  
  976. local month = string.match(str,"(%d+)%Dмес") or 0
  977. local day = string.match(str,"(%d+)%Dдне") or 0
  978. local hour = string.match(str,"(%d+)%Dчас") or 0
  979. local min = string.match(str,"(%d+)%Dмину") or 0
  980. local sec = string.match(str,"(%d+)%Dсеку") or 0
  981.  
  982. if day == 0 then
  983. day = string.match(str,"(%d+)%Dден") or 0
  984. end
  985.  
  986. if string.find(str,"онлайн") then
  987. status = " §2онлайн "
  988. elseif string.find(str,"оффлайн") then
  989. status = " §4оффлайн "
  990. end
  991. local targetname = string.match(str,"Игрок.+%s(.+)%s.+лайн") or "null"
  992. if string.find(targetname,"§") == 1 then
  993. targetname = string.sub(targetname,4)
  994. end
  995. local answer = color1 .. "игрок " .. color2 .. targetname .. status .. color1
  996. if month ~= 0 then
  997. answer = answer .. color2 .. month .. color1 .. " месяцев, "
  998. end
  999. if day ~= 0 then
  1000. answer = answer .. color2 .. day .. color1 .. " дней, "
  1001. end
  1002. if day ~= 0 or hour ~= 0 then
  1003. answer = answer .. color2 .. hour .. color1 .. " часов, "
  1004. end
  1005. if day ~= 0 or hour ~= 0 or min ~= 0 then
  1006. answer = answer .. color2 .. min .. color1 .. " минут, "
  1007. end
  1008. if day ~= 0 or hour ~= 0 or min ~= 0 then
  1009. if sec ~= 0 then
  1010. answer = answer .. color2 .. sec .. color1 .. " секунд, "
  1011. end
  1012. else
  1013. answer = answer .. color2 .. sec .. color1 .. " секунд, "
  1014. end
  1015. answer = answer:sub(0,-3)
  1016. whisper(name,answer)
  1017. else
  1018. whisper(name,color1 .. "ты сможешь повторно использовать эту команду через " .. color2 .. dur .. color1 .. " секунд")
  1019. end
  1020. end
  1021. end
  1022. function processColors(msg,name)
  1023. if msg == c.command_colors then
  1024. local answer = color2 .. "цветовые коды чата:\n§00 - черный \n§11 - темно-синий \n§22 - зеленый \n§33 - темный аквамарин \n§44 - темно-красный \n§55 - фиолетовый \n§66 - оранжевый \n§77 - серый \n§88 - темно-серый \n§99 - синий \n§aa - салатовый§r \n§bb - аквамарин \n§cc - красный \n§dd - розовый \n§ee - желтый \n§ff - белый \n§r§ll - жирный \n§r§mm - зачеркнутый \n§r§nn - подчеркнутый \n§r§oo - курсив \n§rr - сброс форматирования"
  1025. whisper(name,answer)
  1026. log(3,name .. ": " .. msg)
  1027. end
  1028. end
  1029. function saveStateOf(tablename,table,mode,silentMode) -- mode 1 для обычного сохранения, 2 для пересчитывания computer.uptime()
  1030. local currentTime = computer.uptime()
  1031. local f,err = io.open("__" .. tablename,"w")
  1032. if err then
  1033. print(err)
  1034. sayLocal(color1 .. tablename .. "§c не сохранен ")
  1035. return true
  1036. elseif mode == 1 then
  1037. f:write(serialization.serialize(table))
  1038. if not silentMode then
  1039. sayLocal(color1 .. tablename .. "§2 сохранен ")
  1040. end
  1041. f:close()
  1042. elseif mode == 2 then
  1043. local newtable = {}
  1044. for k,v in pairs(table) do
  1045. local newtime = math.floor(v - currentTime)
  1046. if newtime > 0 then
  1047. newtable[k] = newtime
  1048. end
  1049. end
  1050. f:write(serialization.serialize(newtable))
  1051. if not silentMode then
  1052. sayLocal(color1 .. tablename .. "§2 сохранен ")
  1053. end
  1054. f:close()
  1055. end
  1056. end
  1057. function saveAllStates()
  1058. sayLocal(color2 .. "Подготовка к рестарту:")
  1059. saveStateOf("history",history,1)
  1060. --saveStateOf("messages",messages,1)
  1061. saveStateOf("mutes",mutes,2)
  1062. saveStateOf("warns",warns,2)
  1063. end
  1064.  
  1065.  
  1066. function reboot()
  1067. saveAllStates()
  1068. sayLocal(color2 .. "Скачивание обновления . . .")
  1069. loadfile("/bin/wget.lua")("-f",c.download_main,"/home/MAIN")
  1070. --shell.execute("wget -f " .. c.download_main .. "/home/MAIN")
  1071. sayLocal(color2 .. "Обновление завершено, рестарт")
  1072. computer.shutdown(1)
  1073. --os.exit()
  1074. end
  1075. function reboot2()
  1076. sayLocal(color2 .. "Обновление списка вопросов . . .")
  1077. loadfile("/bin/wget.lua")("-f",c.download_q,"/home/_q")
  1078. sayLocal(color2 .. "Обновление списка правил . . .")
  1079. loadfile("/bin/wget.lua")("-f",c.download_rules,"/home/_rules")
  1080. sayLocal(color2 .. "Обновление конфига . . .")
  1081. loadfile("/bin/wget.lua")("-f",c.download_config,"/home/_config")
  1082. saveAllStates()
  1083. computer.shutdown(1)
  1084. end
  1085. function reboot3()
  1086. sayLocal(color2 .. "Скачивание обновления . . .")
  1087. loadfile("/bin/wget.lua")("-f",c.download_main,"/home/MAIN")
  1088. sayLocal(color2 .. "Обновление списка вопросов . . .")
  1089. loadfile("/bin/wget.lua")("-f",c.download_q,"/home/_q")
  1090. sayLocal(color2 .. "Обновление списка правил . . .")
  1091. loadfile("/bin/wget.lua")("-f",c.download_rules,"/home/_rules")
  1092. sayLocal(color2 .. "Обновление конфига . . .")
  1093. loadfile("/bin/wget.lua")("-f",c.download_config,"/home/_config")
  1094. saveAllStates()
  1095. computer.shutdown(1)
  1096. end
  1097.  
  1098. function fixAutorun()
  1099. if fs.exists("/ShyvanaChatBotInstalled") == false then
  1100. local f,err = io.open("/home/.shrc","a")
  1101. f:write("\n/home/MAIN")
  1102. f:close()
  1103. local ff,err = io.open("/ShyvanaChatBotInstalled","w")
  1104. ff:write("true")
  1105. ff:close()
  1106. end
  1107. end
  1108. function loadConfig(link)
  1109. if link and link ~= "" then
  1110. local a,b = loadfile("/bin/wget.lua")("-f",link,"/home/_config")
  1111. if a == true then
  1112. sayLocal(color2 .. "loadconfig: ok")
  1113. reboot()
  1114. else
  1115. sayLocal(color2 .. "loadconfig: error " .. tostring(b))
  1116. end
  1117. else
  1118. sayLocal(color2 .. "loadconfig error no link")
  1119. end
  1120. end
  1121. function stop()
  1122. local function saveStateOf2(tablename,table,mode) -- порезанная savestateoff только для истории
  1123. local f,err = io.open("__" .. tablename,"w")
  1124. if err then
  1125. print(err)
  1126. sayLocal(color1 .. tablename .. "§c не сохранен ")
  1127. return true
  1128. elseif mode == 1 then
  1129. f:write(serialization.serialize(table))
  1130. sayLocal(color1 .. tablename .. "§2 сохранен ")
  1131. f:close()
  1132. end
  1133. end
  1134. saveStateOf2("history",history,1)
  1135. os.exit()
  1136. end
  1137.  
  1138. function randomPersik()
  1139. return persiki[math.random(1,#persiki)]
  1140. end
  1141. function persikAnswer(reason,name)
  1142. local persik = randomPersik()
  1143. local tab = {
  1144. [1] = {
  1145. "не капси, " .. persik .. " :*",
  1146. "отпусти шифт, " .. persik .. " :(",
  1147. },
  1148. [2] = {
  1149. "не ругайся, " .. persik .. " :*",
  1150. "так некрасиво говорить, " .. persik .. " :(",
  1151. "как неприлично, " .. persik .. " :(",
  1152. },
  1153. [3] = {
  1154. "не флуди, " .. persik .. " :*",
  1155. "не загрязняй чат, " .. persik .. ", пожалуйста :(",
  1156. },
  1157. [4] = {
  1158. "не рекламируй так часто, " .. persik .. " :*",
  1159. },
  1160. [5] = {
  1161. "на этот раз только предупреждение, " .. persik .. ". больше так не делай :*",
  1162. }
  1163. }
  1164. say(color1 .. tab[reason][math.random(1,#tab[reason])])
  1165. end
  1166.  
  1167.  
  1168. function processHelloBye(msg0,name)
  1169. if c.persiki then
  1170. local msg = unicode.lower(msg0)
  1171. local currentTime = computer.uptime()
  1172. if string.find(msg,"всем") and not string.find(msg,"%Sвсем") then
  1173. if greetingCooldown < currentTime or (masters[name] and masters[name].canSkipHelloByeCooldowns) then
  1174. for _,word in pairs(helloWords) do
  1175. if string.find(msg,word) then
  1176. local name1 = randomPersik()
  1177. local phrase = string.gsub(helloPhrases[math.random(1,#helloPhrases)],"persik",name1)
  1178. greetingCooldown = currentTime + c.timeout_greeting
  1179. say(color1 .. phrase)
  1180. return true
  1181. end
  1182. end
  1183. end
  1184. if byeCooldown < currentTime or (masters[name] and masters[name].canSkipHelloByeCooldowns) then
  1185. for _,word in pairs(byeWords) do
  1186. if string.find(msg,word) then
  1187. local name1 = randomPersik()
  1188. local phrase = string.gsub(byePhrases[math.random(1,#byePhrases)],"persik",name1)
  1189. byeCooldown = currentTime + c.timeout_bye
  1190. say(color1 .. phrase)
  1191. return true
  1192. end
  1193. end
  1194. end
  1195. end
  1196. end
  1197. end
  1198. function getStats()
  1199. function compareDuration(a,b)
  1200. return a.duration > b.duration
  1201. end
  1202. local toDisplay = 10
  1203. local answer = color2 .. "Топ нарушителей:\n"
  1204. local t = {}
  1205. for k,v in pairs(stats) do
  1206. table.insert(t,{name = k, duration = v.duration,mutes = v.mutes, warns = v.warns})
  1207. end
  1208. table.sort(t,compareDuration)
  1209. if #t >= 1 then
  1210. for i = 1,math.min(#t,toDisplay) do
  1211. answer = answer .. color1 .. tostring(i) .. ". " .. color2 .. t[i].name .. color1 .. " - в муте " .. color2 .. math.floor(t[i].duration/60) .. color1 .. " минут (" .. color2 .. t[i].mutes .. color1 .. " мутов, " .. color2 .. t[i].warns .. color1 .." варнов)\n"
  1212. end
  1213. else
  1214. answer = color1 .. "еще никто не нарушал :("
  1215. end
  1216. return answer
  1217. end
  1218. function getPlayerStat(name0)
  1219. local name = getIndex(mutes,name0)
  1220. if stats[name] then
  1221. return color1 .. "игрок " .. color2 .. name .. color1 .. ": всего в муте " .. color2 .. math.floor(stats[name].duration/60) .. color1 .. " секунд (" .. color2 .. stats[name].mutes .. color1 .. " мутов, " .. color2 .. stats[name].warns .. color1 .. " варнов)"
  1222. else
  1223. return color1 .. "игрок " .. color2 .. name0 .. color1 .. " еще не нарушал"
  1224. end
  1225. end
  1226. function processMasterCommand(msg,name)
  1227. -- msg = unicode.lower(msg) мешает isplayermuted
  1228. if masters[name] then
  1229. local answer = ""
  1230. if msg == c.command_votestats then
  1231. if masters[name].canAccessVoteStats then
  1232. if activeVote then
  1233. answer = color1 .. "Активное голосование: " .. color2 .. activeVote .. color1 .. ": §2" .. currentVoteResults.yes .. color1 .. "/§4" .. currentVoteResults.no .. color1 .. ". До окончания: " .. color2 .. math.floor(getCurrentVoteTimer()) .. color1 .. " секунд"
  1234. else
  1235. answer = color1 .. "нет активных голосований"
  1236. end
  1237. else
  1238. answer = color1 .. "у тебя нет доступа к этой команде"
  1239. end
  1240. elseif string.find(msg,c.command_is_player_muted) == 1 then
  1241. local username = string.sub(msg,string.len(c.command_is_player_muted)+2)
  1242. local a,b = isPlayerMuted(username)
  1243. if a then
  1244. answer = color2 .. tostring(a) .. color1 .. " : " .. color2 .. b .. color1 .. " секунд осталось"
  1245. else
  1246. answer = color2 .. tostring(a)
  1247. end
  1248. elseif string.find(msg,c.command_unmute) == 1 then
  1249. if masters[name].canCancelIssuedMutes then
  1250. local username = string.sub(msg,string.len(c.command_unmute)+2)
  1251. unmute(username,name)
  1252. else
  1253. whisper(name,"у тебя нет доступа к " .. c.command_unmute)
  1254. end
  1255. elseif string.find(msg,c.command_is_player_warned) == 1 then
  1256. local username = string.sub(msg,string.len(c.command_is_player_warned)+2)
  1257. local a,b = isPlayerWarned(username)
  1258. if a then
  1259. answer = color2 .. tostring(a) .. color1 .. " : " .. color2 .. b .. color1 .. " секунд осталось"
  1260. else
  1261. answer = color2 .. tostring(a)
  1262. end
  1263. elseif string.find(msg,c.command_unwarn) == 1 then
  1264. if masters[name].canCancelIssuedMutes then
  1265. local username = string.sub(msg,string.len(c.command_unwarn)+2)
  1266. unwarn(username,name)
  1267. else
  1268. whisper(name,"у тебя нет доступа к " .. c.command_unwarn)
  1269. end
  1270. elseif msg == c.command_votestop and masters[name].canStopVotes then
  1271. event.push("endvote",2,name)
  1272. elseif msg == c.command_toggle_detect then
  1273. if masters[name].undetectable then
  1274. whisper(name,color1 .. "теперь тебя видно в " .. color2 .. c.command_mods)
  1275. masters[name].undetectable = nil
  1276. else
  1277. whisper(name,color1 .. "теперь тебя не видно в " .. color2 .. c.command_mods)
  1278. masters[name].undetectable = true
  1279. end
  1280. elseif msg == c.command_memory_used then
  1281. answer = color1 .. "Использование памяти: " .. color2 .. math.floor((computer.totalMemory()-computer.freeMemory())/1024) .. color1 .. "/" .. color2 .. math.floor(computer.totalMemory()/1024) .. " kB"
  1282. elseif string.find(msg,c.command_retranslate) == 1 then
  1283. if masters[name].canUseRetranslate then
  1284. local speech = string.sub(msg,unicode.len(c.command_retranslate)+1)
  1285. if speech ~= "" then
  1286. speech = string.gsub(speech,"#love","§4❤" .. color1)
  1287. say(color1 .. speech,true)
  1288. end
  1289. end
  1290. elseif msg == c.command_reboot and masters[name].canReboot then
  1291. log(2," *** RESTART *** ")
  1292. reboot()
  1293. elseif msg == c.command_reboot_2 and masters[name].canReboot then
  1294. log(2," *** RESTART2 *** ")
  1295. reboot2()
  1296. elseif msg == c.command_reboot_3 and masters[name].canReboot then
  1297. log(2," *** RESTART3 *** ")
  1298. reboot3()
  1299. elseif string.find(msg,c.command_load_config) == 1 and masters[name].canLoadConfig then
  1300. local args = string.sub(msg,unicode.len(c.command_load_config)+2)
  1301. loadConfig(args)
  1302. elseif msg == c.command_stop and masters[name].canReboot then
  1303. log(2," *** STOP *** ")
  1304. stop()
  1305. elseif msg == c.command_get_stats then
  1306. answer = getStats(name)
  1307. elseif string.find(msg,c.command_get_stats) == 1 then
  1308. local username = string.sub(msg,string.len(c.command_get_stats)+2)
  1309. answer = getPlayerStat(username)
  1310. end
  1311. if answer ~= "" then
  1312. whisper(name,answer)
  1313. end
  1314. end
  1315. end
  1316. function endCurrentVote(arg,name) --arg 1 или 2, 1 чтоб закончить голосование само по себе (таймером), 2 для принудительного закрытия без результатов
  1317. if arg == 1 then
  1318. say(color1 .. "Голосование окончено: §2\"за\"" .. color1 .. ": " .. color2 .. currentVoteResults.yes .. color1 .. ", §4\"против\"" .. color1 .. ": " .. color2 .. currentVoteResults.no)
  1319. if votes[activeVote].isEasy then
  1320. if currentVoteResults.yes - currentVoteResults.no >= c.vote_easy_yes_to_pass then
  1321. votes[activeVote].passFunction()
  1322. say(color1 .. votes[activeVote].passMessage)
  1323. else
  1324. votes[activeVote].failFunction()
  1325. say(color1 .. votes[activeVote].failMessage)
  1326. end
  1327. end
  1328. activeVote = nil
  1329. currentVoteResults = {yes = 0, no = 0}
  1330. hasUserVoted = {}
  1331. elseif arg == 2 then
  1332. if activeVote then
  1333. event.cancel(activeVoteTimerId)
  1334. say(color1 .. "Голосование остановлено игроком " .. color2 .. name)
  1335. activeVote = nil
  1336. currentVoteResults = {yes = 0, no = 0}
  1337. hasUserVoted = {}
  1338. else
  1339. whisper(name,color1 .. "нет активных голосований")
  1340. end
  1341. end
  1342. end
  1343. function unmute(player0,name) -- player - тот, кто в муте, name - заказчик
  1344. local a,b,player = isPlayerMuted(player0)
  1345. if a then
  1346. cmd("unmute " .. player)
  1347. mutes[player] = nil
  1348. whisper(name,"мут снят с " .. player .. " (оставалось " .. b .. " секунд)")
  1349. say(color2 .. name .. color1 .. " отменил мут игрока " .. color2 .. player)
  1350. elseif not player then
  1351. whisper(name,color1 .. "игрок не указан")
  1352. else
  1353. whisper(name,color1 .. "игрок " .. color2 .. player .. color1 .. " не имеет актуальных мутов от бота или неправильно указано имя")
  1354. end
  1355. end
  1356. function unwarn(player0,name)
  1357. local a,b,player = isPlayerWarned(player0)
  1358. if a then
  1359. cmd("unwarn " .. player)
  1360. warns[player] = nil
  1361. say(color2 .. name .. color1 .. " отменил варн игрока " .. color2 .. player)
  1362. elseif not player then
  1363. whisper(name,color1 .. "игрок не указан")
  1364. else
  1365. whisper(name,color1 .. "игрок " .. color2 .. player0 .. color1 .. " не имеет актуальных варнов от бота или неправильно указано имя")
  1366. end
  1367. end
  1368. function processHelp(msg,name)
  1369. msg = unicode.lower(msg)
  1370. if msg == c.command_help then
  1371. local answer
  1372. function addCommand(command,description)
  1373. answer = answer .. color2 .. command .. " " .. color1 .. "- " .. description .. "\n"
  1374. end
  1375. answer = color2 .. "Доступные команды (вводятся в локальный чат): \n"
  1376. addCommand(c.command_inf,"информация по определенному пункту правил (напр. " .. color2 .. c.command_inf .. " 3.1" .. color1 .. ")")
  1377. addCommand(c.command_mods,"список модераторов онлайн")
  1378. if not serverCommandDisabled then
  1379. addCommand(c.command_server,"узнать время до рестарта сервера и ТПС")
  1380. end
  1381. addCommand(c.command_seen .. " [имя]","узнать когда игрок заходил в игру последний раз")
  1382. addCommand(c.command_colors,"посмотреть список цветовых кодов чата (доступны прем аккаунтам)")
  1383. addCommand("-votesun","начать голосование за отключение дождя")
  1384. addCommand("-voteday","начать голосование за установку времени на утро")
  1385. addCommand(c.command_yes .. " / " .. c.command_no,"отдать голос в текущем голосовании")
  1386. whisper(name,answer)
  1387. log(3,name .. ": " .. msg)
  1388. end
  1389. end
  1390. function processHelp2(msg,name)
  1391. msg = unicode.lower(msg)
  1392. if msg == c.command_help2 and masters[name] then
  1393. local answer
  1394. function addCommand(command,description)
  1395. answer = answer .. color2 .. command .. " " .. color1 .. "- " .. description .. "\n"
  1396. end
  1397. answer = color2 .. "Доступные команды для администраторов бота: \n (работают только при наличии соответствующих прав в конфиге)\n"
  1398. addCommand(c.command_votestats,"получить инфу о текущем голосовании")
  1399. addCommand(c.command_votestop,"отменить текущее голосование")
  1400. addCommand(c.command_is_player_muted .. " [имя]","проверить наличие текущих мутов от бота игроку")
  1401. addCommand(c.command_unmute .. " [имя]","отменить выданный ботом мут (если отменить вручную, бот продолжит игнорировать игрока на время бывшего мута)")
  1402. addCommand(c.command_is_player_warned .. " [имя]","проверить наличие текущих варнов от бота игроку")
  1403. addCommand(c.command_unwarn .. " [имя]","отменить выданный ботом варн")
  1404. addCommand(c.command_get_stats,"посмотреть статистику по мутам и варнам игроков")
  1405. addCommand(c.command_get_stats .. " [имя]","посмотреть статистику мутов/варнов определенного игрока")
  1406. addCommand(c.command_toggle_detect,"стать невидимым для команды " .. color2 .. c.command_mods)
  1407. addCommand(c.command_memory_used,"инфа по оперативной памяти бота")
  1408. addCommand(c.command_retranslate,"говорить от имени бота, #love = ❤")
  1409. addCommand(c.command_reboot,"обновить код бота и перезапустить")
  1410. addCommand(c.command_reboot_2,"обновить список вопросов, список правил, конфиг и перезапустить")
  1411. addCommand(c.command_reboot_3,"обновить все (вопросы, правила, конфиг, код бота) и перезапустить")
  1412. addCommand(c.command_stop,"сохранить только историю и остановить бота")
  1413. addCommand(c.command_load_config .. " [ссылка]","скачать конфиг файл с указанной ПРЯМОЙ ссылки и перезапустить (использовать не нужно)")
  1414. whisper(name,answer)
  1415. end
  1416. end
  1417.  
  1418. function getEvent()
  1419. local evt,arg1,name,msg = event.pullMultiple("chat_message","endvote")
  1420. if evt == "chat_message" then
  1421. msg = deColor(msg)
  1422. if isGlobal(msg) then
  1423. if not isPlayerMuted(name,true) or (masters[name] and masters[name].canNOTGetIgnoredByBot) then
  1424. msg = string.sub(msg,2)
  1425. processHelloBye(msg,name)
  1426. processCaps(msg,name)
  1427. processQuestions(msg,name)
  1428. processCensoredWords(msg,name)
  1429. processSymbolFlood(msg,name)
  1430. processFlood(msg,name)
  1431. --log(2,"[g]" .. name .. ": " .. msg,"test")
  1432. else
  1433. --log(3,"(muted)" .. name .. ": " .. msg,"test")
  1434. end
  1435. else -- is local
  1436. processHelp(msg,name)
  1437. processHelp2(msg,name)
  1438. processActiveVote(msg,name)
  1439. processVoteStart(msg,name)
  1440. processInf(msg,name)
  1441. processMods(msg,name)
  1442. processSeen(msg,name)
  1443. processColors(msg,name)
  1444. processMasterCommand(msg,name)
  1445. if not serverCommandDisabled then
  1446. processServerCommand(msg,name)
  1447. end
  1448. end
  1449. elseif evt == "endvote" then
  1450. endCurrentVote(arg1,name)
  1451. end
  1452. end
  1453.  
  1454. fixAutorun()
  1455. drawMainFrame()
  1456. --historyInitialize()
  1457. historyDraw()
  1458. while true do
  1459. getEvent()
  1460. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement