Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

MyDC.ru _ Библиотеки и модули для RusHub'а _ Модули для скриптов RusHub

Автор: Setuper 9.1.2010, 20:27

Модули кладутся в папку libs.
Давайте сделаем некое правила написания модулей: файлы модулей будем писать строчными буквами, а модули объявлять тем же словом, но начинающемся с заглавной буквы. Так будет проще отличать название файла с модулем, от названия самого модуля (для того чтобы вникнуть в их суть).

Пример использования функций модуля:

Код
require"files" -- подключение модуля
Files.SaveTable("myfile.txt", tTable, "tTable") -- Вызов функции модуля


Модуль для работы с файлами:  files.lua ( 1.34 килобайт ) : 646

Модуль различных утилит:  utils.lua ( 1.77 килобайт ) : 280




Давайте в этой теме обсуждать те функции, которые часто используются скриптами, и запихивать их в модули

Автор: STRELOK 9.1.2010, 20:31

Цитата(Setuper @ 9.1.2010, 22:27) *
local function Serialize(tTable, sTableName, hFile, sTab)
sTab = sTab or ''
hFile:write(sTab..sTableName.." = {\n")
for k, v in base.pairs(tTable) do
if base.type(v) ~= "function" then
local sKey = base.type(k) == "string" and ("[%q]"):format(k) or ("[%d]"):format(k)
if base.type(v) == "table" then
Serialize(v, sKey, hFile, sTab..'\t')
else
local sValue = base.type(v) == "string" and ("%q"):format(v) or base.tostring(v)
hFile:write(sTab..'\t'..sKey.." = "..sValue)
end
hFile:write(",\n")
end
end
hFile:write(sTab.."}")
end

big_smile.gif

Автор: Setuper 9.1.2010, 20:34

Локальные функции не выходят за модуль, то есть они могут быть вызваны только внутри модуля, и не могут быть вызваны из скрипта

Для того чтобы было более понятно как использовать модули в скриптах, приведу простой пример на примере функции SaveTable:

Код
require"files" -- подключение модуля
Files.SaveTable(sFile, tTable, sTableName) -- Вызов функции модуля


Обратите внимание, что файл модуля у нас называется files.lua, а сам модуль имеет название Files (module"Files"). поэтому подключается модуль так: require"files", а вызываются функции модуля по таблице Files. (Files.SaveTable(sFile, tTable, sTableName)).

Автор: STRELOK 9.1.2010, 20:35

Цитата(Setuper @ 9.1.2010, 22:32) *
Локальные функции не выходят за модуль, то есть они могут быть вызваны только внутри модуля, и не могут быть вызваны из скрипта

В прикреплённом модуле ошибка big_smile.gif
Код
local function Serialize(tTable, sTableName, hFile, sTab)

а должно быть
Код
function Serialize(tTable, sTableName, hFile, sTab)

big_smile.gif

Автор: Setuper 9.1.2010, 20:44

Нет никакой ошибки. Я просто таким образом закрыл доступ к этой функции из вне модуля.
Это своего рода инкапсуляция.

Разве тебе пишет ошибку?
Смело используй функцию Files.SaveTable(sFile, tTable, sTableName)
Я конечно понимаю, что для тебя это немного по-новому, однако поверь, что тут всё грамотно написано.

Автор: STRELOK 9.1.2010, 20:46

Тогда извиняюсь...(

Автор: Setuper 9.1.2010, 20:49

Не нужно извиняться, лучше больше спрашивай что непонятно.

Автор: STRELOK 9.1.2010, 20:56

Тогда вот первый вопрос:

Цитата
.../Hub/scripts/texts.lua:20: attempt to call global 'LoadText' (a nil value)

Автор: Setuper 9.1.2010, 21:04

Files.LoadText

Теперь функции принадлежат определённым модулям и не являются глобальными, что ускоряет их вызов.

Автор: STRELOK 9.1.2010, 21:17

Цитата
.../Hub/scripts/texts.lua:21: bad argument #2 to 'SendToUser' (string expected, got nil)

Код
        Core.SendToUser(UID, Files.LoadText(sPath..sCmd..".txt"), sBot, sBot)

Что же теперь не так? :(

Автор: Setuper 9.1.2010, 21:22

Файл не найден, поэтому функция Files.LoadText не смогла его открыть и вернула nil.

Вот правильный код:

Код
local sBot = "Security"
local sPath = Core.sMainDir.."texts/"
require "files" -- для Files.LoadText

function OnChat(UID, sData)
  local sCmd = sData:match"%b<>%s+[!+*](%S+)"
  if sCmd then
    local sText = Files.LoadText(sPath..sCmd..".txt")
    if sText then
      Core.SendToUser(UID, sText, sBot, sBot)
      return true
    end
  end
end

Автор: STRELOK 9.1.2010, 21:24

Сейчас попробую

UPD: Работает! Спасибо.

Автор: Setuper 13.1.2010, 15:54

В функции LoadText модуля files.lua добавлена замена

Код
sMsg = sMsg:gsub("|", "&#124;")
для того, чтобы в сообщениях отображался символ вертикальной черты, и для того чтобы этот символ не служил разделителем команд.

Автор: STRELOK_IS74 3.3.2010, 20:10

Прикрепляю модуль киков. При использовании команды $kick юзера не отключало от хаба.
 kick.lua ( 119 байт ) : 42

Установка:
1. Модуль кладём в папку libs
2. В любом скрипте(я добавил в BanManager.lua) добавляем в самом начале require "kick"

Автор: Setuper 3.3.2010, 20:20

Нет защиты от дурака.
То есть данную команду сможет применить любой пользователь против любого (даже самого админа), используя соответствующую RAW команду в своём клиенте.

Рекомендую все же в функции сделать проверку профиля.

Автор: STRELOK_IS74 3.3.2010, 20:38

Добавил.

Автор: Setuper 3.3.2010, 21:11

Не доступна только менюшка. Сама команда $Kick доступна.
Для защиты от дурака нужно проверить условие:

Код
if Core.GetUser(UID, 64) then -- проверка что киком воспользовался пользователь с ключиком
  Core.Disconnect(sNick)
end


Кстати, по протоколу ( http://mydc.ru/index.html?showtopic=915&view=findpost&p=6718 ) команда $Kick не содержит причины кика, а содержит только ник, поэтому бестолку извлекать из этой команды причину. В итоге получаем:
Код
function OnKick(UID, sData)
  if Core.GetUser(UID, 64) then
    Core.Disconnect(sData:match"$Kick (%S+)")
  end
end

Автор: STRELOK_IS74 11.3.2010, 17:05

Цитата(Setuper @ 9.1.2010, 22:27) *
Модуль различных утилит

Предлагаю добавить функцию преобразования шары.
Код
function DoShareUnits(iSize)
    local tShareUnits = {"Б", "КБ", "МБ", "ГБ", "ТБ", "ПБ"}
    local iTableSize = table.maxn(tShareUnits)
    local iSize = tonumber(iSize)
    local sUnits = ""
    for iTablePos = 1, iTableSize do
        if iSize < 1024 or iTablePos == iTableSize then
            sUnits = tShareUnits[iTablePos]
            break
        else
            iSize = iSize / 1024
        end
    end
    local sSize = string.format("%0.2f %s", iSize, sUnits)
    local sSize = string.gsub(sSize, "%.", ",")
    local _,_, s1stChar, s2ndChar = string.find(sSize, "%d+,(%d)(%d)")
    local s1stChar, s2ndChar = tonumber(s1stChar), tonumber(s2ndChar)
    if s2ndChar == 0 then
        sSize = string.gsub(sSize, ","..s1stChar..s2ndChar, ","..s1stChar)
        if s1stChar == 0 then
            sSize = string.gsub(sSize, ","..s1stChar, "")
        end
    end
    return sSize
end

Автор: Setuper 11.3.2010, 19:58

Добавил, немного оптимизировав big_smile.gif

Автор: Nickolya 12.3.2010, 11:19

Пользуясь случаем задам вопрос, как будет лучше, определить вот эту таблицу в функции:

Код
  local tUnits = {"Б", "КБ", "МБ", "ГБ", "ТБ", "ПБ"}
или же в глобальном окружении самого модуля дабы потом только ссылаться на нее? И тогда бы уже на будущее сразу бы добавили остальные единицы измерения:
Код
  local tUnits = {"Б", "КБ", "МБ", "ГБ", "ТБ", "ПБ", "ЭБ", "ЗБ", "ЙБ"}

Автор: Setuper 12.3.2010, 12:13

Тут дело такое... Если определить таблицу вне функции, то это безусловно будет быстрее, так как при вызове функции каждый раз не будет создаваться таблица, с другой стороны, эта таблица будет постоянно занимать некоторое место в памяти, в отличие от таблицы внутри функции, которая будет удаляться из памяти сразу же после отработки функции.

Можно и так и так, однако, не думаю, что данная функция так уж часто используется, чтобы задумываться о быстродействии, тем более если данный модуль будет использоваться в нескольких скриптах, то занимаемая этой таблицей память будет прямо пропорциональна числу скриптов, использующих этот модуль, даже если скрипт и не использует функцию DoShareUnits !!!

Насчёт расширения этой таблицы, то 1024 ПБ - это очень много. И я думаю, что в ближайшие лет 20 мы ещё не доберёмся до таких размеров big_smile.gif

Автор: Sekretchik 27.12.2010, 22:25

Илья, при вызове из модуля utils.lua функции - DoShareUnits получил такое сообщение об ошибке: utils.lua:44: attempt to call global 'tonumber' (a nil value)
Ошибка перестала появляться когда переместил саму функцию DoShareUnits в скрипт из которого запрашивал - Utils.DoShareUnits(tUser.iShare) Соответственно, что после переноса функции, запрос стал - DoShareUnits(tUser.iShare). В таком варианте работает.

Раскрывающийся текст
Код
function DoShareUnits(iSize)
  local tUnits = {"Б", "КБ", "МБ", "ГБ", "ТБ", "ПБ"}
  iSize = tonumber(iSize)
  for i = 1, 6 do
    if iSize < 1024 or i == 6 then
      iSize = ("%0.2f"):format(iSize):gsub("%.", ",")
      local a, b = iSize:match"(%d)(%d)$"
      if b == '0' then
        if a == '0' then
          iSize = iSize:sub(1, -4)
        else
          iSize = iSize:sub(1, -2)
        end
      end
      return iSize..' '..tUnits[i]
    else
      iSize = iSize / 1024
    end
  end
end
Я не сильно силен в lua, пока только постигаю сами азы. Хотелось бы узнать почему возможна такая ошибка. Возможно чего-то нет в самом модуле - utils.lua?

P.S.
После обновления - utils.lua - увидел в чем была разница. Спасибо Илья.

Автор: Setuper 27.12.2010, 22:49

Спасибо. Исправил и перезалил

Автор: Saymon21 5.5.2011, 13:43

IP2Country - Модуль работы с IP2Country.csv
Автор: Nickolya
Подключение модуля: require"IP2Country"
Функции:
IP2Country.GetCountryCode(sIP) - Возвращает код страны для указанного ip
IP2Country.GetCountryName(sIP) - Возвращает имя страны для указанного ip

База IP2Country.csv должна быть в корневой дериктории хаба.

 IP2Country.lua ( 2.41 килобайт ) : 91
 

Автор: KCAHDEP 24.6.2012, 21:54

--* Подключение модуля: require"IP2Country"
--* Функции:
--* IP2Country.GetCountryCode(sIP) -- Возвращает код страны для указанного ip
--* IP2Country.GetCountryName(sIP) -- Возвращает имя страны для указанного ip
Это куда вписывать? или просто в libs скопировать достаточно?

Автор: Alexey 7.6.2014, 22:32

Модули из первого поста, оформленные по стандартам Lua 5.2. Пригодны для использования с Lua 5.1 при указанном способе подключения.

Модуль для работы с файлами:  files.lua ( 1.39 килобайт ) : 10
Подключение модуля в скрипте:

Код
local Files = require("files")

Модуль различных утилит:  utils.lua ( 1.95 килобайт ) : 6
Подключение модуля в скрипте:
Код
local Utils = require("utils")


Что-бы сохранить в скрипте возможность использования старых модулей, надо добавить соответствующую строку сразу после подключения модуля:
Код
if Files and type(Files) ~= 'table' then Files = _G.Files end

Код
if Utils and type(Utils) ~= 'table' then Utils = _G.Utils end

Автор: Alexey 21.3.2017, 17:31

Улучшено оформление модулей, должны корректнее подключаться без правки скриптов.
Модуль для работы с файлами:  files.lua ( 1.35 килобайт ) : 3


Модуль различных утилит:  utils.lua ( 2.76 килобайт ) : 3

Добавлены функции:
Utils.Ip2Num(sIP) -- Преобразует IP в число
Utils.Num2Ip(i) -- Преобразует число в IP
Utils.tobin(n) -- Приводит десятичное число в бинарную строку