mirror of
https://github.com/bjc/prosody.git
synced 2025-04-03 21:27:38 +03:00
217 lines
5.1 KiB
Lua
217 lines
5.1 KiB
Lua
local datamanager = require "core.storagemanager".olddm;
|
|
local array = require "util.array";
|
|
local datetime = require "util.datetime";
|
|
local st = require "util.stanza";
|
|
local now = require "util.time".now;
|
|
local id = require "util.id".medium;
|
|
|
|
local host = module.host;
|
|
|
|
local driver = {};
|
|
|
|
function driver:open(store, typ)
|
|
local mt = self[typ or "keyval"]
|
|
if not mt then
|
|
return nil, "unsupported-store";
|
|
end
|
|
return setmetatable({ store = store, type = typ }, mt);
|
|
end
|
|
|
|
function driver:stores(username) -- luacheck: ignore 212/self
|
|
return datamanager.stores(username, host);
|
|
end
|
|
|
|
function driver:purge(user) -- luacheck: ignore 212/self
|
|
return datamanager.purge(user, host);
|
|
end
|
|
|
|
local keyval = { };
|
|
driver.keyval = { __index = keyval };
|
|
|
|
function keyval:get(user)
|
|
return datamanager.load(user, host, self.store);
|
|
end
|
|
|
|
function keyval:set(user, data)
|
|
return datamanager.store(user, host, self.store, data);
|
|
end
|
|
|
|
function keyval:users()
|
|
return datamanager.users(host, self.store, self.type);
|
|
end
|
|
|
|
local archive = {};
|
|
driver.archive = { __index = archive };
|
|
|
|
function archive:append(username, key, value, when, with)
|
|
when = when or now();
|
|
if not st.is_stanza(value) then
|
|
return nil, "unsupported-datatype";
|
|
end
|
|
value = st.preserialize(st.clone(value));
|
|
value.when = when;
|
|
value.with = with;
|
|
value.attr.stamp = datetime.datetime(when);
|
|
value.attr.stamp_legacy = datetime.legacy(when);
|
|
|
|
if key then
|
|
local items, err = datamanager.list_load(username, host, self.store);
|
|
if not items and err then return items, err; end
|
|
if items then
|
|
items = array(items);
|
|
items:filter(function (item)
|
|
return item.key ~= key;
|
|
end);
|
|
value.key = key;
|
|
items:push(value);
|
|
local ok, err = datamanager.list_store(username, host, self.store, items);
|
|
if not ok then return ok, err; end
|
|
return key;
|
|
end
|
|
else
|
|
key = id();
|
|
end
|
|
|
|
value.key = key;
|
|
|
|
local ok, err = datamanager.list_append(username, host, self.store, value);
|
|
if not ok then return ok, err; end
|
|
return key;
|
|
end
|
|
|
|
function archive:find(username, query)
|
|
local items, err = datamanager.list_load(username, host, self.store);
|
|
if not items then
|
|
if err then
|
|
return items, err;
|
|
else
|
|
return function () end, 0;
|
|
end
|
|
end
|
|
local count = #items;
|
|
local i = 0;
|
|
if query then
|
|
items = array(items);
|
|
if query.key then
|
|
items:filter(function (item)
|
|
return item.key == query.key;
|
|
end);
|
|
end
|
|
if query.with then
|
|
items:filter(function (item)
|
|
return item.with == query.with;
|
|
end);
|
|
end
|
|
if query.start then
|
|
items:filter(function (item)
|
|
return item.when >= query.start;
|
|
end);
|
|
end
|
|
if query["end"] then
|
|
items:filter(function (item)
|
|
return item.when <= query["end"];
|
|
end);
|
|
end
|
|
count = #items;
|
|
if query.reverse then
|
|
items:reverse();
|
|
if query.before then
|
|
for j = 1, count do
|
|
if (items[j].key or tostring(j)) == query.before then
|
|
i = j;
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
elseif query.after then
|
|
for j = 1, count do
|
|
if (items[j].key or tostring(j)) == query.after then
|
|
i = j;
|
|
break;
|
|
end
|
|
end
|
|
end
|
|
if query.limit and #items - i > query.limit then
|
|
items[i+query.limit+1] = nil;
|
|
end
|
|
end
|
|
return function ()
|
|
i = i + 1;
|
|
local item = items[i];
|
|
if not item then return; end
|
|
local key = item.key or tostring(i);
|
|
local when = item.when or datetime.parse(item.attr.stamp);
|
|
local with = item.with;
|
|
item.key, item.when, item.with = nil, nil, nil;
|
|
item.attr.stamp = nil;
|
|
item.attr.stamp_legacy = nil;
|
|
item = st.deserialize(item);
|
|
return key, item, when, with;
|
|
end, count;
|
|
end
|
|
|
|
function archive:dates(username)
|
|
local items, err = datamanager.list_load(username, host, self.store);
|
|
if not items then return items, err; end
|
|
return array(items):pluck("when"):map(datetime.date):unique();
|
|
end
|
|
|
|
function archive:delete(username, query)
|
|
if not query or next(query) == nil then
|
|
return datamanager.list_store(username, host, self.store, nil);
|
|
end
|
|
local items, err = datamanager.list_load(username, host, self.store);
|
|
if not items then
|
|
if err then
|
|
return items, err;
|
|
end
|
|
-- Store is empty
|
|
return 0;
|
|
end
|
|
items = array(items);
|
|
local count_before = #items;
|
|
if query then
|
|
if query.key then
|
|
items:filter(function (item)
|
|
return item.key ~= query.key;
|
|
end);
|
|
end
|
|
if query.with then
|
|
items:filter(function (item)
|
|
return item.with ~= query.with;
|
|
end);
|
|
end
|
|
if query.start then
|
|
items:filter(function (item)
|
|
return item.when < query.start;
|
|
end);
|
|
end
|
|
if query["end"] then
|
|
items:filter(function (item)
|
|
return item.when > query["end"];
|
|
end);
|
|
end
|
|
if query.truncate then
|
|
if query.reverse then
|
|
-- Before: { 1, 2, 3, 4, 5, }
|
|
-- After: { 1, 2, 3 }
|
|
for i = #items, query.truncate + 1, -1 do
|
|
items[i] = nil;
|
|
end
|
|
else
|
|
-- Before: { 1, 2, 3, 4, 5, }
|
|
-- After: { 3, 4, 5 }
|
|
local offset = #items - query.truncate;
|
|
for i = 1, #items do
|
|
items[i] = items[i+offset];
|
|
end
|
|
end
|
|
end
|
|
end
|
|
local count = count_before - #items;
|
|
local ok, err = datamanager.list_store(username, host, self.store, items);
|
|
if not ok then return ok, err; end
|
|
return count;
|
|
end
|
|
|
|
module:provides("storage", driver);
|