mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-22 21:46:51 +02:00
CLOSES #1393
This commit is contained in:
+42
-2
@@ -26,6 +26,7 @@ local ModIndex = {}
|
||||
-- single repo's releases; a whole index is heavier and changes more slowly.
|
||||
ModIndex.CACHE_TTL = 24 * 60 * 60
|
||||
ModIndex.SCHEMA_VERSION = 1
|
||||
ModIndex.CACHE_VERSION = 2
|
||||
|
||||
-- ------- pure: source resolution
|
||||
|
||||
@@ -149,6 +150,43 @@ local function parseLatest(raw)
|
||||
}
|
||||
end
|
||||
|
||||
local function parseDownloads(raw)
|
||||
if type(raw) == "number" or type(raw) == "string" then
|
||||
local n = tonumber(raw)
|
||||
return n and { total = n } or nil
|
||||
end
|
||||
if type(raw) ~= "table" then return nil end
|
||||
local out = {
|
||||
total = tonumber(raw.total),
|
||||
recent = tonumber(raw.recent),
|
||||
window_days = tonumber(raw.window_days),
|
||||
as_of = str(raw.as_of),
|
||||
}
|
||||
if out.total == nil and out.recent == nil then return nil end
|
||||
return out
|
||||
end
|
||||
|
||||
-- downloadStats(entry) -> { total, recent, window_days, as_of } | nil
|
||||
function ModIndex.downloadStats(entry)
|
||||
if type(entry) ~= "table" then return nil end
|
||||
return parseDownloads(entry.downloads)
|
||||
end
|
||||
|
||||
local function isoDay(v)
|
||||
if type(v) ~= "string" then return nil end
|
||||
return v:match("^(%d%d%d%d%-%d%d%-%d%d)")
|
||||
end
|
||||
|
||||
-- releaseDates(entry) -> { first, latest } | nil
|
||||
function ModIndex.releaseDates(entry)
|
||||
if type(entry) ~= "table" then return nil end
|
||||
local first = isoDay(entry.first_release)
|
||||
local latest = isoDay(entry.last_release)
|
||||
or isoDay(entry.latest and entry.latest.published_at)
|
||||
if not (first or latest) then return nil end
|
||||
return { first = first, latest = latest }
|
||||
end
|
||||
|
||||
local function parseEntry(raw)
|
||||
if type(raw) ~= "table" or not str(raw.id) then return nil end
|
||||
return {
|
||||
@@ -175,11 +213,11 @@ local function parseEntry(raw)
|
||||
conflicts = raw.conflicts,
|
||||
thumbnail = str(raw.thumbnail),
|
||||
description_url = str(raw.description_url),
|
||||
-- Optional release stats a feed author can publish: total downloads
|
||||
-- Optional release stats a feed author can publish: download counts
|
||||
-- across all releases plus first/last release dates. Additive-only,
|
||||
-- so a feed that carries them stays readable by every build that
|
||||
-- predates them (and one that does not still renders fine here).
|
||||
downloads = tonumber(raw.downloads),
|
||||
downloads = parseDownloads(raw.downloads),
|
||||
first_release = str(raw.first_release),
|
||||
last_release = str(raw.last_release),
|
||||
latest = parseLatest(raw.latest),
|
||||
@@ -516,6 +554,7 @@ function ModIndex.cacheFresh(entry, now, ttl)
|
||||
now = now or os.time()
|
||||
ttl = ttl or ModIndex.CACHE_TTL
|
||||
return entry ~= nil and type(entry.checkedAt) == "number"
|
||||
and entry.version == ModIndex.CACHE_VERSION
|
||||
and (now - entry.checkedAt) < ttl
|
||||
end
|
||||
|
||||
@@ -527,6 +566,7 @@ function ModIndex.writeCache(feed, index)
|
||||
opts.modIndexCache = opts.modIndexCache or {}
|
||||
opts.modIndexCache[feed] = {
|
||||
checkedAt = os.time(),
|
||||
version = ModIndex.CACHE_VERSION,
|
||||
generatedAt = index.generatedAt,
|
||||
categories = index.categories,
|
||||
mods = index.mods,
|
||||
|
||||
+34
-1
@@ -265,9 +265,42 @@ function ModUpdate.downloadsLine(total)
|
||||
ModUpdate.formatCount(total))
|
||||
end
|
||||
|
||||
ModUpdate.NO_COUNT = "?"
|
||||
|
||||
function ModUpdate.abbrevCount(n)
|
||||
n = tonumber(n)
|
||||
if not n or n ~= n or n < 0 then return ModUpdate.NO_COUNT end
|
||||
n = math.floor(n)
|
||||
if n < 1000 then return tostring(n) end
|
||||
local units, idx, value = { "k", "M", "B" }, 0, n
|
||||
repeat
|
||||
value = value / 1000
|
||||
idx = idx + 1
|
||||
until idx >= #units or math.floor(value * 10 + 0.5) / 10 < 1000
|
||||
local scaled = math.floor(value * 10 + 0.5) / 10
|
||||
local shown = (scaled % 1 == 0) and tostring(math.floor(scaled))
|
||||
or string.format("%.1f", scaled)
|
||||
return shown .. units[idx]
|
||||
end
|
||||
|
||||
function ModUpdate.downloadsShort(total)
|
||||
return Strings("%s downloads", ModUpdate.abbrevCount(total))
|
||||
end
|
||||
|
||||
function ModUpdate.trendingLine(recent, windowDays)
|
||||
if recent == nil then return nil end
|
||||
if not windowDays then
|
||||
return Strings("%s recently", ModUpdate.abbrevCount(recent))
|
||||
end
|
||||
return Strings("%s in the last %d days", ModUpdate.abbrevCount(recent),
|
||||
math.floor(windowDays))
|
||||
end
|
||||
|
||||
function ModUpdate.datesLine(first, latest)
|
||||
if not (first or latest) then return nil end
|
||||
return Strings("Released %s - Updated %s", first or "?", latest or "?")
|
||||
if not first then return Strings("Updated %s", latest) end
|
||||
if not latest then return Strings("Released %s", first) end
|
||||
return Strings("Released %s - Updated %s", first, latest)
|
||||
end
|
||||
|
||||
function ModUpdate.statsLine(total, first, latest)
|
||||
|
||||
Reference in New Issue
Block a user