Refactor mod to use the new HTTPS API.

This commit makes several changes:
 ¤ The mod (finally) uses the lurkcoinV3 API.
 ¤ Transactions to non-existent users are reverted (provided both 
servers are using the updated mod)
   · There is a small processing fee on transactions to invalid users 
(definitely not a bug)
 ¤ Fix non-minetest_game formspec prepends on ATM formspecs.
 ¤ Stop overriding minetest.log.
 ¤ Add luacheck workflow based on the one at 
https://github.com/BlockySurvival/bls_custom
 ¤ Fix errors reported by luacheck.
This commit is contained in:
luk3yx 2020-10-04 17:19:46 +13:00
parent 640fbae0b3
commit 50f5b41ccd
6 changed files with 214 additions and 188 deletions

13
.github/workflows/luacheck.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: luacheck
on: [push, pull_request]
jobs:
luacheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Run luacheck
uses: Roang-zero1/factorio-mod-luacheck@master
with:
luacheckrc_url: https://raw.githubusercontent.com/luk3yx/minetest-lurkcoin/master/.luacheckrc

19
.luacheckrc Normal file
View File

@ -0,0 +1,19 @@
-- Originally from bls_custom
max_line_length = 80
globals = {
'atm',
'accounts',
'default',
'economy',
'lurkcoin',
'minetest',
'money',
'ItemStack'
}
read_globals = {
string = {fields = {'split', 'trim'}},
table = {fields = {'copy'}},
}

View File

@ -14,30 +14,34 @@ local formspecs = {}
-- 0.4 compatibility -- 0.4 compatibility
lurkcoin.formspec_prepend = '' lurkcoin.formspec_prepend = ''
if minetest.get_modpath('default') and rawget(_G, 'default') and if minetest.global_exists('default') and default.gui_bg and
default.gui_bg and default.gui_bg_img and default.gui_slots then default.gui_bg_img and default.gui_slots then
lurkcoin.formspec_prepend = default.gui_bg .. default.gui_bg_img .. lurkcoin.formspec_prepend = default.gui_bg .. default.gui_bg_img ..
default.gui_slots default.gui_slots
end end
-- The formspec code is based on something random I did in 2017(?) for local function centre_label(pos, label)
-- lurkcoinV1, formspecs are weird and I somehow got it right™ then. return 'image_button[' .. pos .. ';blank.png;;' .. e(label) ..
';true;false;]'
end
-- The formspec code is based on something I did in 2017(?) for lurkcoinV1,
-- formspecs are weird and I somehow got it right then.
local function get_formspec(name, page, params) local function get_formspec(name, page, params)
-- The formspec template -- The formspec template
local formspec = 'size[8,9;]' .. lurkcoin.formspec_prepend .. local formspec = 'size[8,9]' .. lurkcoin.formspec_prepend ..
'label[0.5,1.75;Your balance: ' .. 'label[0.5,1.75;Your balance: ' ..
e(lurkcoin.bank.getbal(name)) .. 'cr.]' .. e(lurkcoin.bank.getbal(name)) .. 'cr.]' ..
'image_button[2,0.55;4,0.5;default_dirt.png^\\[colorize:#343434;y;' .. centre_label('1,0.55;6,0.5', 'Welcome to a ' .. lurkcoin.server_name ..
'Welcome to a ' .. e(lurkcoin.server_name) .. ' ATM!]' .. 'ATM!') ..
'label[0.5,2.25;Exchange rate: \194\1641.00 is equal to ' .. 'label[0.5,2.25;Exchange rate: \194\1641.00 is equal to ' ..
e(lurkcoin.exchange_rate) .. 'cr.]' .. e(lurkcoin.exchange_rate) .. 'cr.]' ..
'image_button[1.75,1.05;4.5,0.5;default_dirt.png^\\[colorize:' .. centre_label('1.75,1.05;4.5,0.5', 'Your account: ' .. name) ..
'#343434;y; Your account: ' .. e(name) .. ']' .. 'image[0.5,0.5;1,1;default_mese_crystal.png]' ..
'image[0.5,0.5;1,1;default_mese_crystal.png]' ..
'image[6.5,0.5;1,1;default_mese_crystal.png]' 'image[6.5,0.5;1,1;default_mese_crystal.png]'
-- Get the page formspec -- Get the page formspec
local page = formspecs[page] or formspecs.main page = formspecs[page] or formspecs.main
if type(page) == 'string' then if type(page) == 'string' then
formspec = formspec .. page formspec = formspec .. page
elseif type(page) == 'function' then elseif type(page) == 'function' then
@ -52,7 +56,7 @@ end
local withdrawls = false local withdrawls = false
-- Payment screen -- Payment screen
function formspecs.pay(name, fields, guessed_amount) function formspecs.pay(name, fields)
fields = fields or {} fields = fields or {}
local formspec = local formspec =
'field[0.8,3.5;7,1;user;User to pay;' .. e(fields.user or '') .. ']' .. 'field[0.8,3.5;7,1;user;User to pay;' .. e(fields.user or '') .. ']' ..
@ -93,7 +97,7 @@ function formspecs.pay(name, fields, guessed_amount)
exc = tostring(math.floor(exc * 100) / 100) exc = tostring(math.floor(exc * 100) / 100)
formspec = formspec .. '\n' .. fields.amount .. 'cr is ' .. formspec = formspec .. '\n' .. fields.amount .. 'cr is ' ..
'equal to \194\164' .. exc .. '.' 'equal to ' .. exc .. '.'
end end
formspec = formspec .. ']' .. formspec = formspec .. ']' ..
'button[0.5,8;3.5,1;payuser;Cancel]' .. 'button[0.5,8;3.5,1;payuser;Cancel]' ..
@ -140,16 +144,20 @@ if minetest.get_modpath('currency') then
} }
-- Remove non-registered notes -- Remove non-registered notes
local remove = {}
for id, note in pairs(withdrawls) do for id, note in pairs(withdrawls) do
if not minetest.registered_items[note] then if not minetest.registered_items[note] then
withdrawls[id] = nil table.insert(remove, id)
end end
end end
for _, id in ipairs(remove) do
withdrawls[id] = nil
end
assert(#withdrawls > 0, 'The "currency" mod did not register any notes!') assert(#withdrawls > 0, 'The "currency" mod did not register any notes!')
-- Create a detached inventory for depositing -- Create a detached inventory for depositing
local inv = minetest.create_detached_inventory('lurkcoin:atm_deposit', { local inv = minetest.create_detached_inventory('lurkcoin:atm_deposit', {
on_put = function(inv, listname, index, stack, player) on_put = function(inv, listname, _, stack, player)
local name = stack:get_name() local name = stack:get_name()
if name:sub(1, 17) == 'currency:minegeld' then if name:sub(1, 17) == 'currency:minegeld' then
local m = name:sub(19) local m = name:sub(19)
@ -157,6 +165,8 @@ if minetest.get_modpath('currency') then
if m:sub(1, 5) == 'cent_' then if m:sub(1, 5) == 'cent_' then
m = tonumber(m:sub(6)) m = tonumber(m:sub(6))
if m then m = m / 100 end if m then m = m / 100 end
elseif m == 'bundle' then
m = 0.05 * 9
else else
m = tonumber(m) m = tonumber(m)
end end
@ -170,16 +180,16 @@ if minetest.get_modpath('currency') then
if not lurkcoin.bank.add(pname, m, 'Deposit') then if not lurkcoin.bank.add(pname, m, 'Deposit') then
player:get_inventory():add_item('main', stack) player:get_inventory():add_item('main', stack)
end end
core.log('action', 'Player ' .. pname .. ' deposits ' .. minetest.log('action', 'Player ' .. pname ..
tostring(m) .. 'Mg (' .. stack:to_string() .. ' deposits ' .. tostring(m) .. 'Mg (' ..
') into a lurkcoin ATM.') stack:to_string() .. ') into a lurkcoin ATM.')
end end
end end
inv:set_list(listname, {}) inv:set_list(listname, {})
lurkcoin.show_atm(player:get_player_name(), 'deposit') lurkcoin.show_atm(player:get_player_name(), 'deposit')
end, end,
allow_put = function(inv, listname, index, stack, player) allow_put = function(_, _, _, stack, _)
local name = stack:get_name() local name = stack:get_name()
if name:sub(1, 17) == 'currency:minegeld' then if name:sub(1, 17) == 'currency:minegeld' then
return stack:get_count() return stack:get_count()
@ -198,8 +208,7 @@ if minetest.get_modpath('currency') then
'list[current_player;main;0,6.08;8,3;8]' .. 'list[current_player;main;0,6.08;8,3;8]' ..
'list[detached:lurkcoin:atm_deposit;lurkcoin;3.5,3;1,1;]' .. 'list[detached:lurkcoin:atm_deposit;lurkcoin;3.5,3;1,1;]' ..
'listring[]' .. 'listring[]' ..
'image_button[0,3;3.5,1;default_dirt.png^\\[colorize:#343434;' .. centre_label('0,3;3.5,1', 'Deposit money here →') ..
'ignore;Deposit money here →]' ..
'button[5.25,3;2,1;home;Finish]' 'button[5.25,3;2,1;home;Finish]'
else else
-- When there is no physical currency, the only thing you can do is pay -- When there is no physical currency, the only thing you can do is pay
@ -208,19 +217,17 @@ else
end end
-- "Transaction accepted" screen -- "Transaction accepted" screen
function formspecs.success(name, text) function formspecs.success(_, text)
return 'image[2.1,3;4.5,4.5;lurkcoin_success.png]' .. return 'image[2.1,3;4.5,4.5;lurkcoin_success.png]' ..
'image_button[1,7;6,1;default_dirt.png^\\[colorize:#343434;' .. centre_label('1,7;6,1', text or 'Transaction sent!') ..
'ignore;' .. e(text or 'Transaction sent!') .. ']' ..
'button[0.5,8;3.5,1;home;Go back]' .. 'button[0.5,8;3.5,1;home;Go back]' ..
'button_exit[4,8;3.5,1;quit;Quit]' 'button_exit[4,8;3.5,1;quit;Quit]'
end end
-- "Transaction failed" screen -- "Transaction failed" screen
function formspecs.error(name, text) function formspecs.error(_, text)
return 'image[2.1,3;4.5,4.5;lurkcoin_error.png]' .. return 'image[2.1,3;4.5,4.5;lurkcoin_error.png]' ..
'image_button[1,7;6,1;default_dirt.png^\\[colorize:#343434;' .. centre_label('1,7;6,1', text or 'An error has occurred!') ..
'ignore;' .. e(text or 'An error has occurred!') .. ']' ..
'button[0.5,8;3.5,1;home;Go back]' .. 'button[0.5,8;3.5,1;home;Go back]' ..
'button_exit[4,8;3.5,1;quit;Quit]' 'button_exit[4,8;3.5,1;quit;Quit]'
end end
@ -228,10 +235,8 @@ end
-- Processing screen -- Processing screen
formspecs.processing = formspecs.processing =
'image[2.1,3;4.5,4.5;lurkcoin_processing.png]' .. 'image[2.1,3;4.5,4.5;lurkcoin_processing.png]' ..
'image_button[1,7;6,1;default_dirt.png^\\[colorize:#343434;' .. centre_label('1,7;6,1', 'Processing your transaction...') ..
'ignore;Processing your transaction...]' .. centre_label('1,8;6,1', 'This should only take a few seconds.')
'image_button[1,8;6,1;default_dirt.png^\\[colorize:#343434;' ..
'ignore;This should only take a few seconds.]'
-- A wrapper function -- A wrapper function
function lurkcoin.show_atm(name, page, params) function lurkcoin.show_atm(name, page, params)
@ -267,10 +272,12 @@ minetest.register_on_player_receive_fields(function(player, formname, raw)
'ERROR: You cannot afford to do that!') 'ERROR: You cannot afford to do that!')
end end
local note = false local note
for id, item in pairs(withdrawls) do for id, item in pairs(withdrawls) do
-- HACK: Multiply both amount and id by 1000 to avoid
-- floating-point bugs.
if (not note or id > note) and if (not note or id > note) and
math.floor(amount / id) * id == amount then (amount * 1000) % (id * 1000) == 0 then
local def = minetest.registered_items[item] local def = minetest.registered_items[item]
if def and amount / id <= (def.stack_max or 99) then if def and amount / id <= (def.stack_max or 99) then
note = id note = id
@ -286,7 +293,7 @@ minetest.register_on_player_receive_fields(function(player, formname, raw)
local stack = ItemStack({ local stack = ItemStack({
name = withdrawls[note], name = withdrawls[note],
count = amount / note, count = (amount * 1000) / (note * 1000),
}) })
local inv = player:get_inventory() local inv = player:get_inventory()
if not inv:room_for_item('main', stack) then if not inv:room_for_item('main', stack) then
@ -372,14 +379,5 @@ minetest.register_on_player_receive_fields(function(player, formname, raw)
end) end)
minetest.register_on_leaveplayer(function(player) minetest.register_on_leaveplayer(function(player)
-- TODO: I forgot what one register_on_leaveplayer uses and am too lazy to open_atms[player:get_player_name()] = nil
-- check.
local name
if type(player) == 'string' then
name = player
else
name = player:get_player_name()
end
open_atms[name] = nil
end) end)

View File

@ -22,7 +22,7 @@ minetest.register_node('lurkcoin:atm', {
end end
end, end,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) on_rightclick = function(_, _, clicker, _, _)
return lurkcoin.show_atm(clicker:get_player_name()) return lurkcoin.show_atm(clicker:get_player_name())
end, end,
}) })

254
core.lua
View File

@ -4,28 +4,40 @@
-- © 2019 by luk3yx -- © 2019 by luk3yx
-- --
lurkcoin.version = 0 -- Change this if you are hosting your own lurkcoin-core instance
local baseurl = 'https://us.xeroxirc.net:7000'
lurkcoin.version = 3
lurkcoin.timeout = 10 lurkcoin.timeout = 10
lurkcoin.exchange_rate = 1 lurkcoin.exchange_rate = 1
-- Do not allow other mods to modify this, or they may be able to bypass mod local function log(level, text)
-- security restrictions! if text then
local baseurl = 'https://us.xeroxirc.net:7000/v2' text = text:gsub('[\r\n]', ' ')
else
level, text = 'action', level:gsub('[\r\n]', ' ')
end
return minetest.log(level, '[lurkcoin] ' .. text)
end
local function logf(text, ...)
return log(text:format(...))
end
-- Get the username and API token -- Get the username and API token
lurkcoin.server_name = minetest.settings:get('lurkcoin.username') lurkcoin.server_name = minetest.settings:get('lurkcoin.username')
local token = minetest.settings:get('lurkcoin.token') local token = minetest.settings:get('lurkcoin.token')
-- Make sure lurkcoin.server_name exists -- Make sure lurkcoin.server_name exists
if not lurkcoin.server_name then if not lurkcoin.server_name then
lurkcoin.server_name = '<unknown>' lurkcoin.server_name = '<unknown>'
minetest.log('warning', 'lurkcoin has no server name set!') log('warning', 'lurkcoin.server_name is not set!')
end end
-- Make sure the HTTP API exists -- Make sure the HTTP API exists
local http = ... local http = ...
if not http then if not http then
minetest.log('warning', 'lurkcoin is not allowed to use the HTTP API! ' .. log('warning', 'lurkcoin is not allowed to use the HTTP API! ' ..
'Please add lurkcoin to secure.http_mods in minetest.conf.') 'Please add lurkcoin to secure.http_mods in minetest.conf.')
end end
@ -34,177 +46,185 @@ end
lurkcoin.user_agent = 'Minetest ' .. minetest.get_version().string .. lurkcoin.user_agent = 'Minetest ' .. minetest.get_version().string ..
' (with lurkcoin mod v' .. tostring(lurkcoin.version) .. ')' ' (with lurkcoin mod v' .. tostring(lurkcoin.version) .. ')'
-- Create the HTTP header list
local headers
if token then
local raw = lurkcoin.server_name:gsub(':', '_') .. ':' .. token
local auth = minetest.encode_base64(raw)
headers = {
-- minetest.encode_base64() doesn't add padding
'Authorization: Basic ' .. auth .. ('='):rep(4 - #auth % 4),
'Content-Type: application/json',
'X-Force-OK: true'
}
end
local function E(code, msg)
return {sucess = false, error = code, message = msg}
end
-- Download functions -- Download functions
local function get(url, data, callback) local function get(url, data, callback)
-- To prevent race conditions, these callbacks wait until at least the next -- To prevent race conditions, these callbacks wait until at least the next
-- globalstep. -- globalstep.
if not data then if not http then
data = {} minetest.after(0, callback, E('ERR_CONNECTIONFAILED',
elseif not http then 'The lurkcoin mod is not in secure.http_mods!'))
minetest.after(0, callback, {
completed = true,
succeeded = false,
timeout = true,
code = 500,
data = 'ERROR: The lurkcoin mod is not in secure.http_mods!'
})
return return
elseif not lurkcoin.server_name or not token then elseif not headers then
minetest.after(0, callback, { minetest.after(0, callback, E('ERR_INVALIDLOGIN',
completed = true, 'The lurkcoin mod does not have (correct) credentials!'))
succeeded = false,
timeout = true,
code = 401,
data = 'ERROR: The lurkcoin mod does not have (correct) ' ..
'account credentials!'
})
return return
end end
data.name = lurkcoin.server_name
data.token = token
-- Minetest eats any non-200 code.
data.force_200 = '200'
http.fetch({ http.fetch({
url = baseurl .. '/' .. url, url = baseurl .. '/v3/' .. url,
timeout = lurkcoin.timeout, timeout = lurkcoin.timeout,
post_data = data, post_data = data and minetest.write_json(data),
user_agent = lurkcoin.user_agent, user_agent = lurkcoin.user_agent,
}, function(res) extra_headers = headers
if res.timeout then }, function(http_res)
minetest.log('warning', '[lurkcoin] Could not connect to lurkcoin!') local res
res.code = 500 if http_res.timeout then
res.data = 'ERROR: Could not connect to lurkcoin!' log('warning', 'Could not connect to lurkcoin!')
elseif res.code == 401 or res.code == 418 then res = E('ERR_CONNECTIONFAILED', 'Could not connect to lurkcoin!')
minetest.log('warning', '[lurkcoin] Invalid username or API token!') else
lurkcoin.server_name, token = '<unknown>', nil res = minetest.parse_json(http_res.data)
elseif res.code == 200 and res.data:sub(1, 7) == 'ERROR: ' then if type(data) ~= 'table' then data = nil end
res.code = 501
end end
local success, msg = pcall(callback, res) local ok, msg = pcall(callback, res or E('ERR_UNKNOWNERROR', '???'))
if not success then if not ok then
minetest.log('error', '[lurkcoin] Error: ' .. msg) log('error', msg)
end end
end) end)
end end
-- Process incoming transactions. -- Process incoming transactions.
local handled_transactions = {} local acknowledged_transactions = {}
local function _sync(res) local function sync_callback(res)
if res.code == 200 then if not res.success then return end
local data = minetest.parse_json(res.data)
-- Update the exchange rate -- Process any unprocessed transactions
assert(type(data.exchange_rate) == 'number') local reject = {}
assert(data.exchange_rate == data.exchange_rate) for _, t in ipairs(res.result) do
lurkcoin.exchange_rate = data.exchange_rate local id = t.id
if not acknowledged_transactions[id] then
-- Process any unprocessed transactions if lurkcoin.bank.user_exists(t.target) then
for _, t in ipairs(data.transactions) do acknowledged_transactions[id] = true
assert(type(t[3]) == 'number') logf('[%s] \194\164%s (sent %s, received %scr) - ' ..
local id = minetest.serialize(t) 'Transaction from %q on %q to %q.',
if not handled_transactions[id] then t.id, t.amount, t.sent_amount, t.received_amount, t.source,
handled_transactions[id] = true t.source_server, t.target)
core.log('action', '[lurkcoin] ' .. t[4]) lurkcoin.bank.add(t.target, t.received_amount)
lurkcoin.bank.add(t[2], t[3]) else
logf('Rejecting transaction %s, user %q does not exist.',
t.id, t.target)
table.insert(reject, t.id)
end end
end end
end
-- Tell lurkcoin to remove processed transactions -- Acknowledge transactions (if any)
if #data.transactions > 0 then if next(acknowledged_transactions) then
get('remove_transactions', {count = tostring(#data.transactions)}, local ack = {}
function(res) for id, _ in pairs(acknowledged_transactions) do
if res.code == 200 then table.insert(ack, id)
for _, t in ipairs(data.transactions) do
handled_transactions[minetest.serialize(t)] = nil
end
end
end)
end end
get('acknowledge_transactions', {transactions = ack}, function(res2)
if res2.success then
for _, id in ipairs(ack) do
acknowledged_transactions[id] = nil
end
end
end)
end
-- Reject transactions (if any)
if #reject > 0 then
get('reject_transactions', {transactions = reject}, function() end)
end end
end end
-- Periodically sync with lurkcoin. -- Periodically sync with lurkcoin.
local function sync() local function sync()
get('get_transactions', {as_object = 'true'}, _sync) get('pending_transactions', nil, sync_callback)
-- Only set lurkcoin.exchange_rate once
if not lurkcoin.exchange_rate then
get('exchange_rates', {source = lurkcoin.server_name, target = '',
amount = 1}, function(res)
if res.success and type(res.result) == 'number' then
lurkcoin.exchange_rate = res.result
end
end)
end
minetest.after(300, sync) minetest.after(300, sync)
end end
-- Start syncing once the game is loaded.
minetest.after(0, sync) minetest.after(0, sync)
-- Get an exchange rate -- Get an exchange rate
function lurkcoin.get_exchange_rate(amount, to, callback) function lurkcoin.get_exchange_rate(amount, target, callback)
assert(callback) assert(callback)
amount = amount and tonumber(amount)
if not amount or amount ~= amount then return callback(nil) end
get('exchange_rates', { get('exchange_rates', {
from = lurkcoin.server_name, source = lurkcoin.server_name,
to = to or 'lurkcoin', target = target or '',
amount = tostring(amount), amount = amount,
}, function(res) }, function(res)
if res.code == 200 then if res.success then
local amount = tonumber(res.data) callback(res.result, nil)
if amount == amount then return callback(amount, nil) end elseif res.error == 'ERR_TARGETSERVERNOTFOUND' then
end callback(nil, 'That server does not exist!')
local msg
if res.code == 502 then
msg = 'That server does not exist!'
else else
msg = res.data callback(nil, tostring(res.message))
end end
return callback(nil, tostring(msg))
end) end)
end end
-- Pay a user (cross-server) -- Pay a user (cross-server)
function lurkcoin.pay(from, to, server, amount, callback) function lurkcoin.pay(source, target, target_server, amount, callback)
assert(type(amount) == 'number' and callback) assert(type(amount) == 'number' and callback)
-- Run lurkcoin.bank.pay() if this is not a cross-server transaction. -- Run lurkcoin.bank.pay() if this is not a cross-server transaction.
if not server or server == '' or server:lower() == if not target_server or target_server == '' or
lurkcoin.server_name:lower() then target_server:lower() == lurkcoin.server_name:lower() then
return callback(lurkcoin.bank.pay(from, to, amount)) return callback(lurkcoin.bank.pay(source, target, amount))
end end
-- Sanity checks -- Sanity checks
amount = math.floor(amount * 100) / 100 amount = math.floor(amount * 100) / 100
if not lurkcoin.bank.user_exists(from) then if not lurkcoin.bank.user_exists(source) then
return callback(false, 'ERROR: The "from" user does not exist!') return callback(false, 'ERROR: The "from" user does not exist!')
elseif amount ~= amount or amount <= 0 then elseif amount ~= amount or amount <= 0 then
return callback(false, 'ERROR: Invalid number!') return callback(false, 'ERROR: Invalid number!')
elseif lurkcoin.bank.getbal(from) - amount < 0 then elseif amount > lurkcoin.bank.getbal(source) then
return callback(false, 'ERROR: You cannot afford to do that!') return callback(false, 'ERROR: You cannot afford to do that!')
end end
if not lurkcoin.bank.subtract(from, amount, 'Transaction to "' .. to .. if not lurkcoin.bank.subtract(source, amount, 'Transaction to "' ..
'" on server "' .. server .. '".') then source .. '" on server "' .. target_server .. '".') then
return callback(false, 'ERROR: Transaction failed!') return callback(false, 'ERROR: Transaction failed!')
end end
-- Send the request -- Send the request
return get('pay', { return get('pay', {
target = to, source = source,
server = server, target = target,
amount = tostring(amount), target_server = target_server,
local_currency = 'true' amount = amount,
local_currency = true
}, function(res) }, function(res)
if res.code ~= 200 then if res.success then
lurkcoin.bank.add(from, amount, 'Reverting failed transaction.') logf('User %q paid %q (on server %q) %scr.', source, target,
if res.data == 'ERROR: You cannot afford to do that!' then target_server, amount)
res.data = 'ERROR: This server cannot afford to do that!' return callback(true, 'Transaction sent!')
end
else
minetest.log('action', '[lurkcoin] User ' .. from .. ' paid ' ..
to .. ' (on server ' .. server .. ') ' .. tostring(amount) .. 'cr.')
end end
lurkcoin.bank.add(source, amount, 'Reverting failed transaction.')
return callback(res.code == 200, res.data or 'ERROR: Unknown error!') if res.code == 'ERR_CANNOTAFFORD' then
res.message = 'This server cannot afford to do that!'
end
return callback(false, 'ERROR: ' .. tostring(res.message))
end) end)
end end

View File

@ -26,30 +26,6 @@ dofile(modpath .. '/atm-core.lua')
-- Load the ATM blocks -- Load the ATM blocks
dofile(modpath .. '/atm-nodes.lua') dofile(modpath .. '/atm-nodes.lua')
-- Backport https://github.com/minetest/minetest/pull/8420 if required
if not minetest.get_modpath('cloaking') or not cloaking.hide_player then
table.insert(minetest.registered_on_chat_messages, 1, function(name, msg)
if msg:find('[\r\n]') then
minetest.chat_send_player(name,
'New lines are not permitted in chat messages')
return true
end
end)
-- Also tweak minetest.log because of paranoia.
local log = minetest.log
function minetest.log(level, text)
level = level:gsub('[\r\n]', ' ')
if text then
text = text:gsub('[\r\n]', ' ')
else
text = level
level = 'none'
end
return log(level, text)
end
end
-- Display loaded message -- Display loaded message
minetest.log('action', '[lurkcoin] Loaded on server "' .. minetest.log('action', '[lurkcoin] Loaded on server "' ..
lurkcoin.server_name .. '".') lurkcoin.server_name .. '".')