comparison mod_archive/mod_archive.lua @ 225:95d4d53f09a1

mod_archive: keep collections in REVERSE chronological order(not tested).
author shinysky<shinysky1986(AT)gmail.com>
date Thu, 29 Jul 2010 14:36:41 +0800
parents 96e29ff5fa07
children 7fe326037070
comparison
equal deleted inserted replaced
224:96e29ff5fa07 225:95d4d53f09a1
36 36
37 local function store_prefs(data, node, host) 37 local function store_prefs(data, node, host)
38 dm.store(node, host, PREFS_DIR, st.preserialize(data)); 38 dm.store(node, host, PREFS_DIR, st.preserialize(data));
39 end 39 end
40 40
41 local function os_time() 41 local function os_date()
42 -- return tostring(os.time(os.date('!*t'))); 42 return os.date("!*t");
43 return datetime.datetime(); 43 end
44
45 local function date_time(t)
46 return datetime.datetime(t);
44 end 47 end
45 48
46 local function date_parse(s) 49 local function date_parse(s)
47 local year, month, day, hour, min, sec = s:match("(....)-?(..)-?(..)T(..):(..):(..)Z"); 50 local year, month, day, hour, min, sec = s:match("(....)-?(..)-?(..)T(..):(..):(..)Z");
48 return os.time({year=year, month=month, day=day, hour=hour, min=min, sec=sec}); 51 return os.time({year=year, month=month, day=day, hour=hour, min=min, sec=sec});
52 end
53
54 -- local function list_push(node, host, collection)
55 -- local data = dm.list_load(node, host, ARCHIVE_DIR);
56 -- if data then
57 -- table.insert(data, collection, 1);
58 -- dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data));
59 -- else
60 -- dm.list_append(node, host, ARCHIVE_DIR, st.preserialize(collection));
61 -- end
62 -- end
63
64 local function list_insert(node, host, collection)
65 local data = dm.list_load(node, host, ARCHIVE_DIR);
66 if data then
67 local s, e = 1, #data;
68 while true do
69 local c = st.deserialize(data[s]);
70 if collection.attr["start"] >= c.attr["start"] then
71 table.insert(data, collection, s);
72 break;
73 end
74 c = st.deserialize(data[e]);
75 if collection.attr["start"] <= c.attr["start"] then
76 table.insert(data, collection, e+1);
77 break;
78 end
79 local m = math.floor((s + e) / 2);
80 c = st.deserialize(data[m]);
81 if collection.attr["start"] > c.attr["start"] then
82 e = m - 1;
83 elseif collection.attr["start"] < c.attr["start"] then
84 s = m + 1;
85 else
86 table.insert(data, collection, m);
87 break;
88 end
89 end
90 dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data));
91 else
92 dm.list_append(node, host, ARCHIVE_DIR, st.preserialize(collection));
93 end
49 end 94 end
50 95
51 local function store_msg(msg, node, host, isfrom) 96 local function store_msg(msg, node, host, isfrom)
52 local body = msg:child_with_name("body"); 97 local body = msg:child_with_name("body");
53 local thread = msg:child_with_name("thread"); 98 local thread = msg:child_with_name("thread");
54 local data = dm.list_load(node, host, ARCHIVE_DIR); 99 local data = dm.list_load(node, host, ARCHIVE_DIR);
55 local tag = (isfrom and "from") or "to"; 100 local tag = isfrom and "from" or "to";
56 local utc = os_time(); 101 local with = isfrom and msg.attr.to or msg.attr.from;
102 local utc = os_date();
103 local utc_secs = os.time(utc);
104 local utc_datetime = date_time(utc);
57 if data then 105 if data then
58 if thread then 106 -- TODO assuming the collection list are in REVERSE chronological order
59 for k, v in ipairs(data) do 107 for k, v in ipairs(data) do
60 local collection = st.deserialize(v); 108 local collection = st.deserialize(v);
61 if collection.attr["thread"] == thread:get_text() then 109 if thread and collection.attr["thread"] == thread:get_text()
62 -- TODO figure out secs 110 or
63 collection:tag(tag, {secs='1', utc=utc}):add_child(body); 111 not thread
64 local ver = tonumber(collection.attr["version"]) + 1; 112 and collection.attr["with"] == with
65 collection.attr["version"] = tostring(ver); 113 and os.difftime(utc_secs, date_parse(collection.attr["start"])) < 14400 then
66 collection.attr["access"] = utc; 114 local dt = 1;
67 data[k] = collection; 115 for i = #collection, 1, -1 do
68 dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data)); 116 local s = collection[i].attr["utc_secs"];
69 return; 117 if s then
70 end 118 dt = os.difftime(utc_secs, tonumber(s));
71 end 119 break;
72 else -- if the last collection occurs on the same day, then join it 120 end
73 -- TODO assuming the collection list are in chronological order 121 end
74 local collection = st.deserialize(data[#data]); 122 collection:tag(tag, {secs=dt, utc_secs=utc_secs}):add_child(body);
75 local difftime = os.difftime(date_parse(utc), date_parse(collection.attr["start"]));
76 if difftime < 86400 then -- 60 * 60 * 24
77 collection:tag(tag, {secs='1', utc=utc}):add_child(body);
78 local ver = tonumber(collection.attr["version"]) + 1; 123 local ver = tonumber(collection.attr["version"]) + 1;
79 collection.attr["version"] = tostring(ver); 124 collection.attr["version"] = tostring(ver);
80 collection.attr["access"] = utc; 125 collection.attr["access"] = utc_datetime;
81 data[#data] = collection; 126 data[k] = collection;
82 dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data)); 127 dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data));
83 return; 128 return;
84 end 129 end
85 end 130 end
86 end 131 end
87 -- not found, create new collection 132 -- not found, create new collection
88 local collection = st.stanza('chat', {with = isfrom and msg.attr.to or msg.attr.from, start=utc, thread=thread:get_text(), version='0', access=utc}); 133 local collection = st.stanza('chat', {with=with, start=utc_datetime, thread=thread and thread:get_text() or nil, version='0', access=utc_datetime});
89 collection:tag(tag, {secs='0', utc=utc}):add_child(body); 134 collection:tag(tag, {secs='0', utc_secs=utc_secs}):add_child(body);
90 dm.list_append(node, host, ARCHIVE_DIR, st.preserialize(collection)); 135 list_insert(node, host, collection);
91 end 136 end
92 137
93 local function save_result(collection) 138 local function save_result(collection)
94 local save = st.stanza('save', {xmlns='urn:xmpp:archive'}); 139 local save = st.stanza('save', {xmlns='urn:xmpp:archive'});
95 local chat = st.stanza('chat', collection.attr); 140 local chat = st.stanza('chat', collection.attr);
155 end 200 end
156 -- setting.attr["unset"] = nil 201 -- setting.attr["unset"] = nil
157 elseif elem.name == "item" then 202 elseif elem.name == "item" then
158 local found = false; 203 local found = false;
159 for child in data:children() do 204 for child in data:children() do
160 -- TODO bare JID or full JID?
161 if child.name == elem.name and child.attr["jid"] == elem.attr["jid"] then 205 if child.name == elem.name and child.attr["jid"] == elem.attr["jid"] then
162 for k, v in pairs(elem.attr) do 206 for k, v in pairs(elem.attr) do
163 child.attr[k] = v; 207 child.attr[k] = v;
164 end 208 end
165 found = true; 209 found = true;
339 end 383 end
340 end 384 end
341 local ver = tonumber(collection.attr["version"]) + 1; 385 local ver = tonumber(collection.attr["version"]) + 1;
342 collection.attr["version"] = tostring(ver); 386 collection.attr["version"] = tostring(ver);
343 collection.attr["subject"] = elem.attr["subject"]; 387 collection.attr["subject"] = elem.attr["subject"];
344 collection.attr["access"] = os_time(); 388 collection.attr["access"] = date_time();
345 origin.send(st.reply(stanza):add_child(save_result(collection))); 389 origin.send(st.reply(stanza):add_child(save_result(collection)));
346 data[k] = collection; 390 data[k] = collection;
347 dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data)); 391 dm.list_store(node, host, ARCHIVE_DIR, st.preserialize(data));
348 return true; 392 return true;
349 end 393 end
350 end 394 end
351 end 395 end
352 -- not found, create new collection 396 -- not found, create new collection
353 elem.attr["version"] = "0"; 397 elem.attr["version"] = "0";
354 elem.attr["access"] = os_time(); 398 elem.attr["access"] = date_time();
355 origin.send(st.reply(stanza):add_child(save_result(elem))); 399 origin.send(st.reply(stanza):add_child(save_result(elem)));
356 -- TODO check if elem is valid(?) 400 -- TODO check if elem is valid(?)
357 dm.list_append(node, host, ARCHIVE_DIR, st.preserialize(elem)); 401 list_insert(node, host, elem);
358 -- TODO unsuccessful reply 402 -- TODO unsuccessful reply
359 return true; 403 return true;
360 end 404 end
361 405
362 ------------------------------------------------------------ 406 ------------------------------------------------------------
554 res = res and filter_start(elem.attr["start"], collection.attr["start"]); 598 res = res and filter_start(elem.attr["start"], collection.attr["start"]);
555 res = res and filter_end(elem.attr["end"], collection.attr["start"]); 599 res = res and filter_end(elem.attr["end"], collection.attr["start"]);
556 if res then 600 if res then
557 -- table.remove(data, i); 601 -- table.remove(data, i);
558 local temp = st.stanza('chat', collection.attr); 602 local temp = st.stanza('chat', collection.attr);
559 temp.attr["access"] = os_time(); 603 temp.attr["access"] = date_time();
560 data[i] = temp; 604 data[i] = temp;
561 found = true; 605 found = true;
562 end 606 end
563 end 607 end
564 end 608 end