Mercurial > prosody-modules
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 |