Fix almost everything 2 #10
@ -1,350 +0,0 @@
|
|||||||
-----------------------------------------------------------------------------
|
|
||||||
-- HTTP/1.1 client support for the Lua language.
|
|
||||||
-- LuaSocket toolkit.
|
|
||||||
-- Author: Diego Nehab
|
|
||||||
-- RCS ID: $Id: http.lua,v 1.71 2007/10/13 23:55:20 diego Exp $
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Declare module and import dependencies
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
local socket = require("socket")
|
|
||||||
local url = require("socket.url")
|
|
||||||
local ltn12 = require("ltn12")
|
|
||||||
local mime = require("mime")
|
|
||||||
local string = require("string")
|
|
||||||
local base = _G
|
|
||||||
local table = require("table")
|
|
||||||
module("socket.http")
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Program constants
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- connection timeout in seconds
|
|
||||||
TIMEOUT = 60
|
|
||||||
-- default port for document retrieval
|
|
||||||
PORT = 80
|
|
||||||
-- user agent field sent in request
|
|
||||||
USERAGENT = socket._VERSION
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Reads MIME headers from a connection, unfolding where needed
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local function receiveheaders(sock, headers)
|
|
||||||
local line, name, value, err
|
|
||||||
headers = headers or {}
|
|
||||||
-- get first line
|
|
||||||
line, err = sock:receive()
|
|
||||||
if err then return nil, err end
|
|
||||||
-- headers go until a blank line is found
|
|
||||||
while line ~= "" do
|
|
||||||
-- get field-name and value
|
|
||||||
name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
|
|
||||||
if not (name and value) then return nil, "malformed reponse headers" end
|
|
||||||
name = string.lower(name)
|
|
||||||
-- get next line (value might be folded)
|
|
||||||
line, err = sock:receive()
|
|
||||||
if err then return nil, err end
|
|
||||||
-- unfold any folded values
|
|
||||||
while string.find(line, "^%s") do
|
|
||||||
value = value .. line
|
|
||||||
line = sock:receive()
|
|
||||||
if err then return nil, err end
|
|
||||||
end
|
|
||||||
-- save pair in table
|
|
||||||
if headers[name] then headers[name] = headers[name] .. ", " .. value
|
|
||||||
else headers[name] = value end
|
|
||||||
end
|
|
||||||
return headers
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Extra sources and sinks
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
socket.sourcet["http-chunked"] = function(sock, headers)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function()
|
|
||||||
-- get chunk size, skip extention
|
|
||||||
local line, err = sock:receive()
|
|
||||||
if err then return nil, err end
|
|
||||||
local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
|
|
||||||
if not size then return nil, "invalid chunk size" end
|
|
||||||
-- was it the last chunk?
|
|
||||||
if size > 0 then
|
|
||||||
-- if not, get chunk and skip terminating CRLF
|
|
||||||
local chunk, err, part = sock:receive(size)
|
|
||||||
if chunk then sock:receive() end
|
|
||||||
return chunk, err
|
|
||||||
else
|
|
||||||
-- if it was, read trailers into headers table
|
|
||||||
headers, err = receiveheaders(sock, headers)
|
|
||||||
if not headers then return nil, err end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
socket.sinkt["http-chunked"] = function(sock)
|
|
||||||
return base.setmetatable({
|
|
||||||
getfd = function() return sock:getfd() end,
|
|
||||||
dirty = function() return sock:dirty() end
|
|
||||||
}, {
|
|
||||||
__call = function(self, chunk, err)
|
|
||||||
if not chunk then return sock:send("0\r\n\r\n") end
|
|
||||||
local size = string.format("%X\r\n", string.len(chunk))
|
|
||||||
return sock:send(size .. chunk .. "\r\n")
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- Low level HTTP API
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local metat = { __index = {} }
|
|
||||||
|
|
||||||
function open(host, port, create)
|
|
||||||
-- create socket with user connect function, or with default
|
|
||||||
local c = socket.try((create or socket.tcp)())
|
|
||||||
local h = base.setmetatable({ c = c }, metat)
|
|
||||||
-- create finalized try
|
|
||||||
h.try = socket.newtry(function() h:close() end)
|
|
||||||
-- set timeout before connecting
|
|
||||||
h.try(c:settimeout(TIMEOUT))
|
|
||||||
h.try(c:connect(host, port or PORT))
|
|
||||||
-- here everything worked
|
|
||||||
return h
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:sendrequestline(method, uri)
|
|
||||||
local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
|
|
||||||
return self.try(self.c:send(reqline))
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:sendheaders(headers)
|
|
||||||
local h = "\r\n"
|
|
||||||
for i, v in base.pairs(headers) do
|
|
||||||
h = i .. ": " .. v .. "\r\n" .. h
|
|
||||||
end
|
|
||||||
self.try(self.c:send(h))
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:sendbody(headers, source, step)
|
|
||||||
source = source or ltn12.source.empty()
|
|
||||||
step = step or ltn12.pump.step
|
|
||||||
-- if we don't know the size in advance, send chunked and hope for the best
|
|
||||||
local mode = "http-chunked"
|
|
||||||
if headers["content-length"] then mode = "keep-open" end
|
|
||||||
return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:receivestatusline()
|
|
||||||
local status = self.try(self.c:receive(5))
|
|
||||||
-- identify HTTP/0.9 responses, which do not contain a status line
|
|
||||||
-- this is just a heuristic, but is what the RFC recommends
|
|
||||||
if status ~= "HTTP/" then return nil, status end
|
|
||||||
-- otherwise proceed reading a status line
|
|
||||||
status = self.try(self.c:receive("*l", status))
|
|
||||||
local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
|
|
||||||
return self.try(base.tonumber(code), status)
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:receiveheaders()
|
|
||||||
return self.try(receiveheaders(self.c))
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:receivebody(headers, sink, step)
|
|
||||||
sink = sink or ltn12.sink.null()
|
|
||||||
step = step or ltn12.pump.step
|
|
||||||
local length = base.tonumber(headers["content-length"])
|
|
||||||
local t = headers["transfer-encoding"] -- shortcut
|
|
||||||
local mode = "default" -- connection close
|
|
||||||
if t and t ~= "identity" then mode = "http-chunked"
|
|
||||||
elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
|
|
||||||
return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
|
|
||||||
sink, step))
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:receive09body(status, sink, step)
|
|
||||||
local source = ltn12.source.rewind(socket.source("until-closed", self.c))
|
|
||||||
source(status)
|
|
||||||
return self.try(ltn12.pump.all(source, sink, step))
|
|
||||||
end
|
|
||||||
|
|
||||||
function metat.__index:close()
|
|
||||||
return self.c:close()
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
-- High level HTTP API
|
|
||||||
-----------------------------------------------------------------------------
|
|
||||||
local function adjusturi(reqt)
|
|
||||||
local u = reqt
|
|
||||||
-- if there is a proxy, we need the full url. otherwise, just a part.
|
|
||||||
if not reqt.proxy and not PROXY then
|
|
||||||
u = {
|
|
||||||
path = socket.try(reqt.path, "invalid path 'nil'"),
|
|
||||||
params = reqt.params,
|
|
||||||
query = reqt.query,
|
|
||||||
fragment = reqt.fragment
|
|
||||||
}
|
|
||||||
end
|
|
||||||
return url.build(u)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function adjustproxy(reqt)
|
|
||||||
local proxy = reqt.proxy or PROXY
|
|
||||||
if proxy then
|
|
||||||
proxy = url.parse(proxy)
|
|
||||||
return proxy.host, proxy.port or 3128
|
|
||||||
else
|
|
||||||
return reqt.host, reqt.port
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function adjustheaders(reqt)
|
|
||||||
-- default headers
|
|
||||||
local lower = {
|
|
||||||
["user-agent"] = USERAGENT,
|
|
||||||
["host"] = reqt.host,
|
|
||||||
["connection"] = "close, TE",
|
|
||||||
["te"] = "trailers"
|
|
||||||
}
|
|
||||||
-- if we have authentication information, pass it along
|
|
||||||
if reqt.user and reqt.password then
|
|
||||||
lower["authorization"] =
|
|
||||||
"Basic " .. (mime.b64(reqt.user .. ":" .. reqt.password))
|
|
||||||
end
|
|
||||||
-- override with user headers
|
|
||||||
for i,v in base.pairs(reqt.headers or lower) do
|
|
||||||
lower[string.lower(i)] = v
|
|
||||||
end
|
|
||||||
return lower
|
|
||||||
end
|
|
||||||
|
|
||||||
-- default url parts
|
|
||||||
local default = {
|
|
||||||
host = "",
|
|
||||||
port = PORT,
|
|
||||||
path ="/",
|
|
||||||
scheme = "http"
|
|
||||||
}
|
|
||||||
|
|
||||||
local function adjustrequest(reqt)
|
|
||||||
-- parse url if provided
|
|
||||||
local nreqt = reqt.url and url.parse(reqt.url, default) or {}
|
|
||||||
-- explicit components override url
|
|
||||||
for i,v in base.pairs(reqt) do nreqt[i] = v end
|
|
||||||
if nreqt.port == "" then nreqt.port = 80 end
|
|
||||||
socket.try(nreqt.host and nreqt.host ~= "",
|
|
||||||
"invalid host '" .. base.tostring(nreqt.host) .. "'")
|
|
||||||
-- compute uri if user hasn't overriden
|
|
||||||
nreqt.uri = reqt.uri or adjusturi(nreqt)
|
|
||||||
-- ajust host and port if there is a proxy
|
|
||||||
nreqt.host, nreqt.port = adjustproxy(nreqt)
|
|
||||||
-- adjust headers in request
|
|
||||||
nreqt.headers = adjustheaders(nreqt)
|
|
||||||
return nreqt
|
|
||||||
end
|
|
||||||
|
|
||||||
local function shouldredirect(reqt, code, headers)
|
|
||||||
return headers.location and
|
|
||||||
string.gsub(headers.location, "%s", "") ~= "" and
|
|
||||||
(reqt.redirect ~= false) and
|
|
||||||
(code == 301 or code == 302) and
|
|
||||||
(not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
|
|
||||||
and (not reqt.nredirects or reqt.nredirects < 5)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function shouldreceivebody(reqt, code)
|
|
||||||
if reqt.method == "HEAD" then return nil end
|
|
||||||
if code == 204 or code == 304 then return nil end
|
|
||||||
if code >= 100 and code < 200 then return nil end
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- forward declarations
|
|
||||||
local trequest, tredirect
|
|
||||||
|
|
||||||
function tredirect(reqt, location)
|
|
||||||
local result, code, headers, status = trequest {
|
|
||||||
-- the RFC says the redirect URL has to be absolute, but some
|
|
||||||
-- servers do not respect that
|
|
||||||
url = url.absolute(reqt.url, location),
|
|
||||||
source = reqt.source,
|
|
||||||
sink = reqt.sink,
|
|
||||||
headers = reqt.headers,
|
|
||||||
proxy = reqt.proxy,
|
|
||||||
nredirects = (reqt.nredirects or 0) + 1,
|
|
||||||
create = reqt.create
|
|
||||||
}
|
|
||||||
-- pass location header back as a hint we redirected
|
|
||||||
headers = headers or {}
|
|
||||||
headers.location = headers.location or location
|
|
||||||
return result, code, headers, status
|
|
||||||
end
|
|
||||||
|
|
||||||
function trequest(reqt)
|
|
||||||
-- we loop until we get what we want, or
|
|
||||||
-- until we are sure there is no way to get it
|
|
||||||
local nreqt = adjustrequest(reqt)
|
|
||||||
local h = open(nreqt.host, nreqt.port, nreqt.create)
|
|
||||||
-- send request line and headers
|
|
||||||
h:sendrequestline(nreqt.method, nreqt.uri)
|
|
||||||
h:sendheaders(nreqt.headers)
|
|
||||||
-- if there is a body, send it
|
|
||||||
if nreqt.source then
|
|
||||||
h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
|
|
||||||
end
|
|
||||||
local code, status = h:receivestatusline()
|
|
||||||
-- if it is an HTTP/0.9 server, simply get the body and we are done
|
|
||||||
if not code then
|
|
||||||
h:receive09body(status, nreqt.sink, nreqt.step)
|
|
||||||
return 1, 200
|
|
||||||
end
|
|
||||||
local headers
|
|
||||||
-- ignore any 100-continue messages
|
|
||||||
while code == 100 do
|
|
||||||
headers = h:receiveheaders()
|
|
||||||
code, status = h:receivestatusline()
|
|
||||||
end
|
|
||||||
headers = h:receiveheaders()
|
|
||||||
-- at this point we should have a honest reply from the server
|
|
||||||
-- we can't redirect if we already used the source, so we report the error
|
|
||||||
if shouldredirect(nreqt, code, headers) and not nreqt.source then
|
|
||||||
h:close()
|
|
||||||
return tredirect(reqt, headers.location)
|
|
||||||
end
|
|
||||||
-- here we are finally done
|
|
||||||
if shouldreceivebody(nreqt, code) then
|
|
||||||
h:receivebody(headers, nreqt.sink, nreqt.step)
|
|
||||||
end
|
|
||||||
h:close()
|
|
||||||
return 1, code, headers, status
|
|
||||||
end
|
|
||||||
|
|
||||||
local function srequest(u, b)
|
|
||||||
local t = {}
|
|
||||||
local reqt = {
|
|
||||||
url = u,
|
|
||||||
sink = ltn12.sink.table(t)
|
|
||||||
}
|
|
||||||
if b then
|
|
||||||
reqt.source = ltn12.source.string(b)
|
|
||||||
reqt.headers = {
|
|
||||||
["content-length"] = string.len(b),
|
|
||||||
["content-type"] = "application/x-www-form-urlencoded"
|
|
||||||
}
|
|
||||||
reqt.method = "POST"
|
|
||||||
end
|
|
||||||
local code, headers, status = socket.skip(1, trequest(reqt))
|
|
||||||
return table.concat(t), code, headers, status
|
|
||||||
end
|
|
||||||
|
|
||||||
request = socket.protect(function(reqt, body)
|
|
||||||
if base.type(reqt) == "string" then return srequest(reqt, body)
|
|
||||||
else return trequest(reqt) end
|
|
||||||
end)
|
|
@ -1,16 +1,23 @@
|
|||||||
local folder = (...):gsub('%.init$', '')
|
local folder = ({...})[1]:gsub('%.init$', '')
|
||||||
local md5 = require(folder .. ".md5" )
|
local md5 = require(folder .. ".md5" )
|
||||||
local http = require("socket.http")
|
local http = require("socket.http")
|
||||||
|
|
||||||
local GJ = {
|
local GJ = {
|
||||||
gameID, gameKey,
|
gameID, gameKey,
|
||||||
isLoggedIn = false,
|
isLoggedIn = false,
|
||||||
username, userToken
|
username, userToken,
|
||||||
|
trophies = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
local BASE_URL = "http://gamejolt.com/api/game/v1/"
|
local BASE_URL = "http://gamejolt.com/api/game/v1/"
|
||||||
|
|
||||||
local function req(s, f, pu, pt)
|
local escape = function (a)
|
||||||
|
return tostring(a):gsub("([^%w%-%.%_])",function (a)
|
||||||
|
return string.format("%%%02X",string.byte(a))
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function req(s, f, pu, pt, data)
|
||||||
local url = BASE_URL .. s .. "&game_id=" .. tostring(GJ.gameID) .. "&format=" .. f
|
local url = BASE_URL .. s .. "&game_id=" .. tostring(GJ.gameID) .. "&format=" .. f
|
||||||
if pu then url = url .. "&username=" .. GJ.username end
|
if pu then url = url .. "&username=" .. GJ.username end
|
||||||
if pt then url = url .. "&user_token=" .. GJ.userToken end
|
if pt then url = url .. "&user_token=" .. GJ.userToken end
|
||||||
@ -18,7 +25,7 @@ local function req(s, f, pu, pt)
|
|||||||
local b = md5.sumhexa(url .. GJ.gameKey)
|
local b = md5.sumhexa(url .. GJ.gameKey)
|
||||||
url = url .. "&signature=" .. b
|
url = url .. "&signature=" .. b
|
||||||
|
|
||||||
local r, e = http.request(url)
|
local r, e = http.request(url, data)
|
||||||
return r
|
return r
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -54,15 +61,46 @@ local function handleTrophies(str)
|
|||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
function GJ.init(id, key)
|
function GJ.init(id, key, args)
|
||||||
GJ.gameID = id
|
GJ.gameID = id
|
||||||
GJ.gameKey = key
|
GJ.gameKey = key
|
||||||
|
|
||||||
|
if args and type(args)=="table" then
|
||||||
|
for k,v in pairs(args) do
|
||||||
|
local a = v:match("^gjapi_(.*)")
|
||||||
|
|
||||||
|
if a then
|
||||||
|
key, value = a:match("^(.-)=(.-)$")
|
||||||
|
|
||||||
|
if key == "username" then
|
||||||
|
GJ.username = value
|
||||||
|
elseif key == "token" then
|
||||||
|
GJ.userToken = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function GJ.getCredentials(dir)
|
||||||
|
local f = io.open(dir.."gjapi-credentials.txt")
|
||||||
|
|
||||||
|
if f then
|
||||||
|
GJ.username = f:read()
|
||||||
|
GJ.userToken = f:read()
|
||||||
|
end
|
||||||
|
|
||||||
|
if GJ.username and GJ.userToken then
|
||||||
|
return true, GJ.username, GJ.userToken
|
||||||
|
else
|
||||||
|
return false, "Couldn't find, open or read the \"gjapi-credentials.txt\" file"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- users
|
-- users
|
||||||
function GJ.authUser(name, token)
|
function GJ.authUser(name, token)
|
||||||
GJ.username = name
|
GJ.username = name or GJ.username or ""
|
||||||
GJ.userToken = token
|
GJ.userToken = token or GJ.userToken or ""
|
||||||
|
|
||||||
local s = string.find(req("users/auth/?", "dump", true, true), "SUCCESS") ~= nil
|
local s = string.find(req("users/auth/?", "dump", true, true), "SUCCESS") ~= nil
|
||||||
GJ.isLoggedIn = s
|
GJ.isLoggedIn = s
|
||||||
@ -112,7 +150,8 @@ function GJ.fetchData(key, isGlobal)
|
|||||||
local pu, pt = true, true
|
local pu, pt = true, true
|
||||||
if isGlobal then pu, pt = false, false end
|
if isGlobal then pu, pt = false, false end
|
||||||
|
|
||||||
local d = req("data-store/?key=" .. key, "dump", pu, pt)
|
local d = req("data-store/?key=" .. escape(key), "dump", pu, pt)
|
||||||
|
|
||||||
return string.sub(d, string.find(d, "\n"), string.len(d))
|
return string.sub(d, string.find(d, "\n"), string.len(d))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -120,14 +159,21 @@ function GJ.setData(key, data, isGlobal)
|
|||||||
local pu, pt = true, true
|
local pu, pt = true, true
|
||||||
if isGlobal then pu, pt = false, false end
|
if isGlobal then pu, pt = false, false end
|
||||||
|
|
||||||
return string.find(req("data-store/set/?key=" .. key .. "&data=" .. tostring(data), "dump", pu, pt), "SUCCESS") ~= nil
|
return string.find(req("data-store/set/?key=" .. escape(key) .. '&data=' .. escape(data), "dump", pu, pt), "SUCCESS") ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function GJ.setBigData(key, data, isGlobal)
|
||||||
|
local pu, pt = true, true
|
||||||
|
if isGlobal then pu, pt = false, false end
|
||||||
|
|
||||||
|
return string.find(req("data-store/set/?key=" .. escape(key), "dump", pu, pt, "data="..escape(data)), "SUCCESS") ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function GJ.updateData(key, value, operation, isGlobal)
|
function GJ.updateData(key, value, operation, isGlobal)
|
||||||
local pu, pt = true, true
|
local pu, pt = true, true
|
||||||
if isGlobal then pu, pt = false, false end
|
if isGlobal then pu, pt = false, false end
|
||||||
|
|
||||||
local d = req("data-store/update/?key=" .. key .. "&operation=" .. operation .. "&value=" .. tostring(value), "dump", pu, pt)
|
local d = req("data-store/update/?key=" .. escape(key) .. "&operation=" .. operation .. "&value=" .. escape(value), "dump", pu, pt)
|
||||||
return string.sub(d, string.find(d, "\n"), string.len(d))
|
return string.sub(d, string.find(d, "\n"), string.len(d))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -135,7 +181,7 @@ function GJ.removeData(key, isGlobal)
|
|||||||
local pu, pt = true, true
|
local pu, pt = true, true
|
||||||
if isGlobal then pu, pt = false, false end
|
if isGlobal then pu, pt = false, false end
|
||||||
|
|
||||||
return string.find(req("data-store/remove/?key=" .. key, "dump", pu, pt), "SUCCESS") ~= nil
|
return string.find(req("data-store/remove/?key=" .. escape(key), "dump", pu, pt), "SUCCESS") ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function GJ.fetchStorageKeys(isGlobal)
|
function GJ.fetchStorageKeys(isGlobal)
|
||||||
@ -154,7 +200,9 @@ end
|
|||||||
|
|
||||||
-- trophies
|
-- trophies
|
||||||
function GJ.giveTrophy(id)
|
function GJ.giveTrophy(id)
|
||||||
return string.find(req("trophies/add-achieved/?trophy_id=" .. tostring(id), "dump", true, true), "SUCCESS") ~= nil
|
local s = string.find(req("trophies/add-achieved/?trophy_id=" .. id, "dump", true, true), "SUCCESS") ~= nil
|
||||||
|
GJ.fetchAllTrophies(true)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
function GJ.fetchTrophy(id)
|
function GJ.fetchTrophy(id)
|
||||||
@ -168,29 +216,32 @@ function GJ.fetchTrophy(id)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function GJ.fetchTrophiesByStatus(achieved)
|
function GJ.fetchTrophiesByStatus(achieved)
|
||||||
return handleTrophies("achieved=" .. tostring(achieved))
|
return handleTrophies("achieved=" .. (achieved and "true" or "false"))
|
||||||
end
|
end
|
||||||
|
|
||||||
function GJ.fetchAllTrophies()
|
function GJ.fetchAllTrophies(f)
|
||||||
return handleTrophies("")
|
if f then
|
||||||
|
GJ.trophies = handleTrophies("")
|
||||||
|
end
|
||||||
|
return GJ.trophies
|
||||||
end
|
end
|
||||||
|
|
||||||
-- scores
|
-- scores
|
||||||
function GJ.addScore(score, desc, tableID, guestName, extraData)
|
function GJ.addScore(score, desc, tableID, guestName, extraData)
|
||||||
local pu, pt, s = true, true, ""
|
local pu, pt, s = true, true, ""
|
||||||
if guestName then pu, pt = false, false, s .. "&guest=" .. guestName end
|
if guestName then pu, pt = false, false, s .. "&guest=" .. escape(guestName) end
|
||||||
|
|
||||||
if extraData then s = s .. "&extra_data=" .. tostring(extraData) end
|
if extraData then s = s .. "&extra_data=" .. escape(extraData) end
|
||||||
if tableID then s = s .. "&table_id=" .. tostring(tableID) end
|
if tableID then s = s .. "&table_id=" .. escape(tableID) end
|
||||||
|
|
||||||
return string.find(req("scores/add/?score=" .. tostring(desc) .. "&sort=" .. score .. s, "dump", pu, pt), "SUCCESS") ~= nil
|
return string.find(req("scores/add/?score=" .. escape(desc) .. "&sort=" .. score .. s, "dump", pu, pt), "SUCCESS") ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function GJ.fetchScores(limit, tableID)
|
function GJ.fetchScores(limit, tableID)
|
||||||
local pu, pt, s = true, true, ""
|
local pu, pt, s = true, true, ""
|
||||||
if tableID then pu, pt, s = false, false, "&table_id=" .. tostring(tableID) end
|
if tableID then pu, pt, s = false, false, "&table_id=" .. escape(tableID) end
|
||||||
|
|
||||||
local d = req("scores/?limit=" .. tostring(limit) .. s, "keypair", pu, pt)
|
local d = req("scores/?limit=" .. (tonumber(limit or "") or 10) .. s, "keypair", pu, pt)
|
||||||
local t, f = {}
|
local t, f = {}
|
||||||
|
|
||||||
parseKeypair(d, function(k, v)
|
parseKeypair(d, function(k, v)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
local md5 = {
|
local md5 = {
|
||||||
_VERSION = "md5.lua 0.5.0",
|
_VERSION = "md5.lua 1.0.0",
|
||||||
_DESCRIPTION = "MD5 computation in Lua (5.1)",
|
_DESCRIPTION = "MD5 computation in Lua (5.1-3, LuaJIT)",
|
||||||
_URL = "https://github.com/kikito/md5.lua",
|
_URL = "https://github.com/kikito/md5.lua",
|
||||||
_LICENSE = [[
|
_LICENSE = [[
|
||||||
MIT LICENSE
|
MIT LICENSE
|
||||||
@ -33,15 +33,23 @@ local md5 = {
|
|||||||
local floor, abs, max = math.floor, math.abs, math.max
|
local floor, abs, max = math.floor, math.abs, math.max
|
||||||
local char, byte, format, rep, sub =
|
local char, byte, format, rep, sub =
|
||||||
string.char, string.byte, string.format, string.rep, string.sub
|
string.char, string.byte, string.format, string.rep, string.sub
|
||||||
|
local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift
|
||||||
|
|
||||||
local function check_int(n)
|
local ok, bit = pcall(require, 'bit')
|
||||||
|
if not ok then ok, bit = pcall(require, 'bit32') end
|
||||||
|
|
||||||
|
if ok then
|
||||||
|
bit_or, bit_and, bit_not, bit_xor = bit.bor, bit.band, bit.bnot, bit.bxor
|
||||||
|
bit_rshift, bit_lshift = bit.rshift, bit.lshift
|
||||||
|
else
|
||||||
|
local function check_int(n)
|
||||||
-- checking not float
|
-- checking not float
|
||||||
if(n - floor(n) > 0) then
|
if(n - floor(n) > 0) then
|
||||||
error("trying to use bitwise operation on non-integer!")
|
error("trying to use bitwise operation on non-integer!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function tbl2number(tbl)
|
local function tbl2number(tbl)
|
||||||
local n = #tbl
|
local n = #tbl
|
||||||
|
|
||||||
local rslt = 0
|
local rslt = 0
|
||||||
@ -52,9 +60,9 @@ local function tbl2number(tbl)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return rslt
|
return rslt
|
||||||
end
|
end
|
||||||
|
|
||||||
local function expand(tbl_m, tbl_n)
|
local function expand(tbl_m, tbl_n)
|
||||||
local big = {}
|
local big = {}
|
||||||
local small = {}
|
local small = {}
|
||||||
if(#tbl_m > #tbl_n) then
|
if(#tbl_m > #tbl_n) then
|
||||||
@ -69,11 +77,11 @@ local function expand(tbl_m, tbl_n)
|
|||||||
small[i] = 0
|
small[i] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local to_bits -- needs to be declared before bit_not
|
local to_bits -- needs to be declared before bit_not
|
||||||
|
|
||||||
local function bit_not(n)
|
function bit_not(n)
|
||||||
local tbl = to_bits(n)
|
local tbl = to_bits(n)
|
||||||
local size = max(#tbl, 32)
|
local size = max(#tbl, 32)
|
||||||
for i = 1, size do
|
for i = 1, size do
|
||||||
@ -84,10 +92,10 @@ local function bit_not(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
return tbl2number(tbl)
|
return tbl2number(tbl)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- defined as local above
|
-- defined as local above
|
||||||
to_bits = function (n)
|
to_bits = function (n)
|
||||||
check_int(n)
|
check_int(n)
|
||||||
if(n < 0) then
|
if(n < 0) then
|
||||||
-- negative
|
-- negative
|
||||||
@ -108,9 +116,9 @@ to_bits = function (n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return tbl
|
return tbl
|
||||||
end
|
end
|
||||||
|
|
||||||
local function bit_or(m, n)
|
function bit_or(m, n)
|
||||||
local tbl_m = to_bits(m)
|
local tbl_m = to_bits(m)
|
||||||
local tbl_n = to_bits(n)
|
local tbl_n = to_bits(n)
|
||||||
expand(tbl_m, tbl_n)
|
expand(tbl_m, tbl_n)
|
||||||
@ -126,9 +134,9 @@ local function bit_or(m, n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return tbl2number(tbl)
|
return tbl2number(tbl)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function bit_and(m, n)
|
function bit_and(m, n)
|
||||||
local tbl_m = to_bits(m)
|
local tbl_m = to_bits(m)
|
||||||
local tbl_n = to_bits(n)
|
local tbl_n = to_bits(n)
|
||||||
expand(tbl_m, tbl_n)
|
expand(tbl_m, tbl_n)
|
||||||
@ -144,9 +152,9 @@ local function bit_and(m, n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return tbl2number(tbl)
|
return tbl2number(tbl)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function bit_xor(m, n)
|
function bit_xor(m, n)
|
||||||
local tbl_m = to_bits(m)
|
local tbl_m = to_bits(m)
|
||||||
local tbl_n = to_bits(n)
|
local tbl_n = to_bits(n)
|
||||||
expand(tbl_m, tbl_n)
|
expand(tbl_m, tbl_n)
|
||||||
@ -162,9 +170,9 @@ local function bit_xor(m, n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return tbl2number(tbl)
|
return tbl2number(tbl)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function bit_rshift(n, bits)
|
function bit_rshift(n, bits)
|
||||||
check_int(n)
|
check_int(n)
|
||||||
|
|
||||||
local high_bit = 0
|
local high_bit = 0
|
||||||
@ -179,9 +187,9 @@ local function bit_rshift(n, bits)
|
|||||||
n = bit_or(floor(n), high_bit)
|
n = bit_or(floor(n), high_bit)
|
||||||
end
|
end
|
||||||
return floor(n)
|
return floor(n)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function bit_lshift(n, bits)
|
function bit_lshift(n, bits)
|
||||||
check_int(n)
|
check_int(n)
|
||||||
|
|
||||||
if(n < 0) then
|
if(n < 0) then
|
||||||
@ -193,6 +201,7 @@ local function bit_lshift(n, bits)
|
|||||||
n = n*2
|
n = n*2
|
||||||
end
|
end
|
||||||
return bit_and(n, 4294967295) -- 0xFFFFFFFF
|
return bit_and(n, 4294967295) -- 0xFFFFFFFF
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- convert little-endian 32-bit int to a 4-char string
|
-- convert little-endian 32-bit int to a 4-char string
|
||||||
|
Reference in New Issue
Block a user