From c615ea4b1fc52be52cc88f0b6e7fe3ac2319def5 Mon Sep 17 00:00:00 2001 From: Paul Liverman III Date: Sun, 4 Mar 2018 11:41:07 -0800 Subject: [PATCH] re-initialized tl;dr: rewriting history of this repo because I have accidentally included the history of OTHER repos in it due to either a bug with git subtree or a misunderstanding of how it functions on my part --- LICENSE | 21 +++++++++++++ calc.moon | 30 ++++++++++++++++++ datetime.moon | 36 +++++++++++++++++++++ fs.moon | 10 ++++++ gstring.moon | 59 +++++++++++++++++++++++++++++++++++ gtable.moon | 33 ++++++++++++++++++++ migrations.moon | 13 ++++++++ models/Settings.moon | 5 +++ settings.moon | 74 ++++++++++++++++++++++++++++++++++++++++++++ shell.moon | 18 +++++++++++ 10 files changed, 299 insertions(+) create mode 100644 LICENSE create mode 100644 calc.moon create mode 100644 datetime.moon create mode 100644 fs.moon create mode 100644 gstring.moon create mode 100644 gtable.moon create mode 100644 migrations.moon create mode 100644 models/Settings.moon create mode 100644 settings.moon create mode 100644 shell.moon diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..29fad8e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Paul Liverman III + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/calc.moon b/calc.moon new file mode 100644 index 0000000..4dbc5a3 --- /dev/null +++ b/calc.moon @@ -0,0 +1,30 @@ +import bytes from require "resty.random" +import byte from string +import floor from math + +-- return a random number between min/max +random = (min, max) -> + unless max + max = min or 1 + min = 0 + + a, b = byte bytes(2), 1, 2 + c, d = byte bytes(2), 1, 2 + value = a + b * 256 + c * 65536 + d * 16777216 -- 0 to 4294967296 + range = max - min + + if max == floor(max) and min == floor(min) + return floor value * range / 4294967296 + min + else + return value * range / 4294967296 + min + +-- map a value within a range of numbers to another range +map = (min1, max1, value, min2, max2) -> + range1 = max1 - min1 + range2 = max2 - min2 + return ((value - min1) * range2 / range1) + min2 + +{ + :random + :map +} diff --git a/datetime.moon b/datetime.moon new file mode 100644 index 0000000..c256061 --- /dev/null +++ b/datetime.moon @@ -0,0 +1,36 @@ +import date, time from os + +-- for database +now = -> + return date "!%Y-%m-%d %X" + +-- database date -> display +pretty_date = (str) -> + year, month, day = str\match "(%d%d%d%d)-(%d%d)-(%d%d)" + return date "%B %d, %Y", time :year, :month, :day + +-- from database +to_seconds = (str) -> + year, month, day, hour, min, sec = str\match "(%d%d%d%d)-(%d%d)-(%d%d) (%d%d):(%d%d):(%d%d)" + return time :year, :month, :day, :hour, :min, :sec + +-- seconds -> for database +for_db = (seconds) -> + return date "!%Y-%m-%d %X", seconds + +gmt_date = -> + return date "!*t" + +gmt_time = -> + return time date "!*t" + +{ + none: "1970-01-01 00:00:00" -- TODO deprecate + zero: "1970-01-01 00:00:00" -- for use in database + :now + :pretty_date + :to_seconds + :for_db + :gmt_date + :gmt_time +} diff --git a/fs.moon b/fs.moon new file mode 100644 index 0000000..0901125 --- /dev/null +++ b/fs.moon @@ -0,0 +1,10 @@ +exists = (file_path) -> + handle = io.open file_path, "r" + if handle + handle\close! + return true + return false + +{ + :exists +} diff --git a/gstring.moon b/gstring.moon new file mode 100644 index 0000000..a8f0a6c --- /dev/null +++ b/gstring.moon @@ -0,0 +1,59 @@ +import insert, sort, concat from table +import sub, len from string + +-- splits string by newline into array of strings +lines = (str) -> + tab = {} + for line in str\gmatch "[^\n]+" + insert tab, line + return tab + +-- splits string by spaces into a table of strings +-- (handles bad spacing and duplicate substrings) +split = (str) -> + tab1, tab2 = {}, {} + for word in str\gmatch "%S+" + tab1[word] = true + for word in pairs tab1 + insert tab2, word + return tab2 + +-- splits string by commas into a table of strings +-- (expects a well-formated string!) +comma_split = (str) -> + tab = {} + for word in str\gmatch "[^,]+" + insert tab, word + return tab + +-- bool: does str1 start with str2 +starts = (str1, str2) -> + return str2 == sub str1, 1, len str2 + +-- takes space-separated string and puts it in alphabetical order +-- (handles weird spacing, returns with single-spacing) +alphabetize = (str) -> + tab = split str + sort tab + return concat tab, " " + +-- takes space-separated string and removes duplicate entries from it +remove_duplicates = (str) -> + strings = split str + tab, result = {}, {} + + for str in *strings + tab[str] = true + for str in pairs tab + insert result, str + + return concat result, " " + +{ + :lines + :split + :comma_split + :starts + :alphabetize + :remove_duplicates +} diff --git a/gtable.moon b/gtable.moon new file mode 100644 index 0000000..f9b9505 --- /dev/null +++ b/gtable.moon @@ -0,0 +1,33 @@ +-- appends n arrays to the end of the first array +append = (tab1, ...) -> + for n = 1, select "#", ... + tab2 = select n, ... + for i = 1, #tab2 + tab1[#tab1+1] = tab2[i] + return tab1 + +-- returns a new table shallow copying data from all arguments +-- later arguments overwrite any keys in earlier arguments +-- ignores non-table arguments (skipping them) +shallow_copy = (...) -> + new = {} + for n = 1, select "#", ... + tab = select n, ... + if "table" == type tab + for k,v in pairs tab + new[k] = v + return new + +-- returns a new table with flipped keys and values +invert = (tab) -> + new = {} + for key, value in pairs tab + new[value] = key + return new + +{ + :append + :shallow_copy + shallow_merge: shallow_copy -- TODO deprecate + :invert +} diff --git a/migrations.moon b/migrations.moon new file mode 100644 index 0000000..21cad91 --- /dev/null +++ b/migrations.moon @@ -0,0 +1,13 @@ +import create_table, types, create_index from require "lapis.db.schema" + +{ + [1518948992]: => + create_table "settings", { + {"name", types.varchar primary_key: true, unique: true} + {"value", types.text null: true} + + {"created_at", types.time} + {"updated_at", types.time} + } + create_index "settings", "name", unique: true +} diff --git a/models/Settings.moon b/models/Settings.moon new file mode 100644 index 0000000..25ae17b --- /dev/null +++ b/models/Settings.moon @@ -0,0 +1,5 @@ +import Model from require "lapis.db.model" + +class Settings extends Model + @timestamp: true + @primary_key: "name" diff --git a/settings.moon b/settings.moon new file mode 100644 index 0000000..142ce27 --- /dev/null +++ b/settings.moon @@ -0,0 +1,74 @@ +import Settings from require "models" + +totype = (str) -> + if value = tonumber str + return value + if str == "true" + return true + if str == "false" + return false + if str == "nil" + return nil + return str + +cache = {} + +local settings +settings = { + get: (name, skip_index=false) -> + unless name + return settings.load! + + unless skip_index -- for metamethods to not loop endlessly + return settings[name] if settings[name] + setting = Settings\find :name + unless setting + setting = Settings\create :name + cache[name] = setting + val = totype setting.value + settings[name] = val + return val + + set: (name, value) -> + unless name + return settings.save! + + setting = cache[name] + unless setting + setting = Settings\find :name + unless setting + setting = Settings\create :name + cache[name] = setting + + if value ~= nil + settings[name] = value + return setting\update value: tostring value + else + return setting\update value: tostring settings[name] + + save: -> + for name, value in pairs settings + unless "function" == type value + unless cache[name] + cache[name] = Settings\find :name + unless cache[name] + cache[name] = Settings\create :name + + for _, setting in pairs cache + setting\update value: tostring settings[setting.name] + return true + + load: -> + all_settings = Settings\select "WHERE true" + for setting in *all_settings + cache[setting.name] = setting + settings[setting.name] = totype setting.value + return settings +} + +return setmetatable settings, { + __call: (t, name) -> + return settings.get name, true + __index: (t, name) -> + return settings.get name, true + } diff --git a/shell.moon b/shell.moon new file mode 100644 index 0000000..d4d2bf7 --- /dev/null +++ b/shell.moon @@ -0,0 +1,18 @@ +execute = (cmd, capture_exit_code=true) -> + local handle + if capture_exit_code + handle = io.popen "#{cmd}\necho $?" + else + handle = io.popen cmd + result = handle\read "*a" + handle\close! + + exit_start, exit_end = result\find "(%d*)[%c]$" + exit_code = tonumber result\sub(exit_start, exit_end)\sub 1, -2 + output = result\sub 1, exit_start - 1 + + return exit_code, output + +{ + :execute +}