Software / code / prosody-modules
Comparison
mod_archive/mod_archive.lua @ 165:fd8d76daad97
mod_archive: preference handling is done.
| author | shinysky<shinysky1986(AT)gmail.com> |
|---|---|
| date | Sun, 06 Jun 2010 00:04:04 +0800 |
| parent | 159:9a37898f4f7c |
| child | 172:ac826882a8cf |
comparison
equal
deleted
inserted
replaced
| 164:0b238b2b0801 | 165:fd8d76daad97 |
|---|---|
| 4 -- This project is MIT/X11 licensed. Please see the | 4 -- This project is MIT/X11 licensed. Please see the |
| 5 -- COPYING file in the source package for more information. | 5 -- COPYING file in the source package for more information. |
| 6 -- | 6 -- |
| 7 | 7 |
| 8 local st = require "util.stanza"; | 8 local st = require "util.stanza"; |
| 9 local dm = require "util.datamanager" | 9 local dm = require "util.datamanager"; |
| 10 | |
| 11 local PREFS_DIR = "archive_prefs"; | |
| 12 local ARCHIVE_DIR = "archive"; | |
| 10 | 13 |
| 11 module:add_feature("urn:xmpp:archive"); | 14 module:add_feature("urn:xmpp:archive"); |
| 12 module:add_feature("urn:xmpp:archive:auto"); | 15 module:add_feature("urn:xmpp:archive:auto"); |
| 13 module:add_feature("urn:xmpp:archive:manage"); | 16 module:add_feature("urn:xmpp:archive:manage"); |
| 14 module:add_feature("urn:xmpp:archive:manual"); | 17 module:add_feature("urn:xmpp:archive:manual"); |
| 15 module:add_feature("urn:xmpp:archive:pref"); | 18 module:add_feature("urn:xmpp:archive:pref"); |
| 16 | 19 |
| 20 ------------------------------------------------------------ | |
| 21 -- Utils | |
| 22 ------------------------------------------------------------ | |
| 23 local function load_prefs(node, host, dir) | |
| 24 return st.deserialize(dm.load(node, host, dir or PREFS_DIR)); | |
| 25 end | |
| 26 | |
| 27 local function store_prefs(data, node, host, dir) | |
| 28 dm.store(node, host, dir or PREFS_DIR, st.preserialize(data)); | |
| 29 end | |
| 30 | |
| 31 ------------------------------------------------------------ | |
| 32 -- Preferences | |
| 33 ------------------------------------------------------------ | |
| 17 local function preferences_handler(event) | 34 local function preferences_handler(event) |
| 18 local origin, stanza = event.origin, event.stanza; | 35 local origin, stanza = event.origin, event.stanza; |
| 19 module:log("debug", "-- Enter preferences_handler()"); | 36 module:log("debug", "-- Enter preferences_handler()"); |
| 20 module:log("debug", "-- pref:\n%s", tostring(stanza)); | 37 module:log("debug", "-- pref:\n%s", tostring(stanza)); |
| 21 if stanza.attr.type == "get" then | 38 if stanza.attr.type == "get" then |
| 22 -- dm.store(origin.username, origin.host, "archive_prefs", st.preserialize(reply.tags[1])); | 39 local data = load_prefs(origin.username, origin.host); |
| 23 local data = st.deserialize(dm.load(origin.username, origin.host, "archive_prefs")); | |
| 24 if data then | 40 if data then |
| 25 origin.send(st.reply(stanza):add_child(data)); | 41 origin.send(st.reply(stanza):add_child(data)); |
| 26 else | 42 else |
| 27 local reply = st.reply(stanza):tag('pref', {xmlns='urn:xmpp:archive'}); | 43 local reply = st.reply(stanza):tag('pref', {xmlns='urn:xmpp:archive'}); |
| 28 reply:tag('default', {otr='concede', save='false', unset='true'}):up(); | 44 reply:tag('default', {otr='concede', save='false', unset='true'}):up(); |
| 29 reply:tag('method', {type='auto', use='concede'}):up(); | 45 reply:tag('method', {type='auto', use='concede'}):up(); |
| 30 reply:tag('method', {type='local', use='concede'}):up(); | 46 reply:tag('method', {type='local', use='concede'}):up(); |
| 31 reply:tag('method', {type='manual', use='concede'}):up(); | 47 reply:tag('method', {type='manual', use='concede'}):up(); |
| 32 reply:tag('auto', {save='false'}):up(); | 48 reply:tag('auto', {save='false'}):up(); |
| 33 origin.send(reply); | 49 origin.send(reply); |
| 34 -- origin.send(st.reply(stanza)); | 50 end |
| 35 end | |
| 36 return true; | |
| 37 elseif stanza.attr.type == "set" then | 51 elseif stanza.attr.type == "set" then |
| 38 return false; | 52 local node, host = origin.username, origin.host; |
| 39 end | 53 local data = load_prefs(node, host); |
| 54 if not data then | |
| 55 data = st.stanza('pref', {xmlns='urn:xmpp:archive'}); | |
| 56 data:tag('default', {otr='concede', save='false'}):up(); | |
| 57 data:tag('method', {type='auto', use='concede'}):up(); | |
| 58 data:tag('method', {type='local', use='concede'}):up(); | |
| 59 data:tag('method', {type='manual', use='concede'}):up(); | |
| 60 data:tag('auto', {save='false'}):up(); | |
| 61 end | |
| 62 local elem = stanza.tags[1].tags[1]; -- iq:pref:xxx | |
| 63 if not elem then return false end | |
| 64 -- "default" | "item" | "session" | "method" | |
| 65 -- FIXME there may be many item/session/method sections!! | |
| 66 elem.attr["xmlns"] = nil; -- TODO why there is an extra xmlns attr? | |
| 67 if elem.name == "default" then | |
| 68 local setting = data:child_with_name(elem.name) | |
| 69 for k, v in pairs(elem.attr) do | |
| 70 setting.attr[k] = v; | |
| 71 end | |
| 72 -- setting.attr["unset"] = nil | |
| 73 elseif elem.name == "item" then | |
| 74 local found = false; | |
| 75 for child in data:children() do | |
| 76 -- TODO bare JID or full JID? | |
| 77 if child.name == elem.name and child.attr["jid"] == elem.attr["jid"] then | |
| 78 for k, v in pairs(elem.attr) do | |
| 79 child.attr[k] = v; | |
| 80 end | |
| 81 found = true; | |
| 82 break; | |
| 83 end | |
| 84 end | |
| 85 if not found then | |
| 86 data:tag(elem.name, elem.attr):up(); | |
| 87 end | |
| 88 elseif elem.name == "session" then | |
| 89 local found = false; | |
| 90 for child in data:children() do | |
| 91 if child.name == elem.name and child.attr["thread"] == elem.attr["thread"] then | |
| 92 for k, v in pairs(elem.attr) do | |
| 93 child.attr[k] = v; | |
| 94 end | |
| 95 found = true; | |
| 96 break; | |
| 97 end | |
| 98 end | |
| 99 if not found then | |
| 100 data:tag(elem.name, elem.attr):up(); | |
| 101 end | |
| 102 elseif elem.name == "method" then | |
| 103 local newpref = stanza.tags[1]; -- iq:pref | |
| 104 for _, e in ipairs(newpref.tags) do | |
| 105 -- if e.name ~= "method" then continue end | |
| 106 local found = false; | |
| 107 for child in data:children() do | |
| 108 if child.name == "method" and child.attr["type"] == e.attr["type"] then | |
| 109 child.attr["use"] = e.attr["use"]; | |
| 110 found = true; | |
| 111 break; | |
| 112 end | |
| 113 end | |
| 114 if not found then | |
| 115 data:tag(e.name, e.attr):up(); | |
| 116 end | |
| 117 end | |
| 118 end | |
| 119 store_prefs(data, node, host); | |
| 120 origin.send(st.reply(stanza)); | |
| 121 local user = bare_sessions[node.."@"..host]; | |
| 122 local push = st.iq({type="set"}); | |
| 123 push = push:tag('pref', {xmlns='urn:xmpp:archive'}); | |
| 124 if elem.name == "method" then | |
| 125 for child in data:children() do | |
| 126 if child.name == "method" then | |
| 127 push:add_child(child); | |
| 128 end | |
| 129 end | |
| 130 else | |
| 131 push:add_child(elem); | |
| 132 end | |
| 133 push = push:up(); | |
| 134 for _, res in pairs(user and user.sessions or NULL) do -- broadcast to all resources | |
| 135 if res.presence then -- to resource | |
| 136 push.attr.to = res.full_jid; -- TODO how to gen the message that new modes're set? | |
| 137 res.send(push); | |
| 138 end | |
| 139 end | |
| 140 end | |
| 141 return true; | |
| 142 end | |
| 143 | |
| 144 local function itemremove_handler(event) | |
| 145 local origin, stanza = event.origin, event.stanza; | |
| 146 if stanza.attr.type ~= "set" then | |
| 147 return false; | |
| 148 end | |
| 149 local elem = stanza.tags[1].tags[1]; | |
| 150 if not elem or elem.name ~= "item" then | |
| 151 return false; | |
| 152 end | |
| 153 local node, host = origin.username, origin.host; | |
| 154 local data = load_prefs(node, host); | |
| 155 if not data then | |
| 156 return false; | |
| 157 end | |
| 158 for i, child in ipairs(data) do | |
| 159 if child.name == "item" and child.attr["jid"] == elem.attr["jid"] then | |
| 160 table.remove(data, i) | |
| 161 break; | |
| 162 end | |
| 163 end | |
| 164 store_prefs(data, node, host); | |
| 165 origin.send(st.reply(stanza)); | |
| 166 return true; | |
| 167 end | |
| 168 | |
| 169 local function sessionremove_handler(event) | |
| 170 local origin, stanza = event.origin, event.stanza; | |
| 171 if stanza.attr.type ~= "set" then | |
| 172 return false; | |
| 173 end | |
| 174 local elem = stanza.tags[1].tags[1]; | |
| 175 if not elem or elem.name ~= "session" then | |
| 176 return false; | |
| 177 end | |
| 178 local node, host = origin.username, origin.host; | |
| 179 local data = load_prefs(node, host); | |
| 180 if not data then | |
| 181 return false; | |
| 182 end | |
| 183 for i, child in ipairs(data) do | |
| 184 if child.name == "session" and child.attr["thread"] == elem.attr["thread"] then | |
| 185 table.remove(data, i) | |
| 186 break; | |
| 187 end | |
| 188 end | |
| 189 store_prefs(data, node, host); | |
| 190 origin.send(st.reply(stanza)); | |
| 191 return true; | |
| 40 end | 192 end |
| 41 | 193 |
| 42 local function auto_handler(event) | 194 local function auto_handler(event) |
| 43 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | 195 -- event.origin.send(st.error_reply(event.stanza, "cancel", "feature-not-implemented")); |
| 44 if event.stanza.attr.type == "set" then | 196 local origin, stanza = event.origin, event.stanza; |
| 45 event.origin.send(st.error_reply(event.stanza, "cancel", "feature-not-implemented")); | 197 if stanza.attr.type ~= "set" then |
| 46 return true; | 198 return false; |
| 47 end | 199 end |
| 200 local elem = stanza.tags[1]; | |
| 201 local node, host = origin.username, origin.host; | |
| 202 local data = load_prefs(node, host); | |
| 203 if not data then | |
| 204 return false; | |
| 205 end | |
| 206 local setting = data:child_with_name(elem.name) | |
| 207 setting.attr["save"] = elem.attr["save"]; | |
| 208 store_prefs(data, node, host); | |
| 209 origin.send(st.reply(stanza)); | |
| 210 return true; | |
| 48 end | 211 end |
| 49 | 212 |
| 50 local function chat_handler(event) | 213 local function chat_handler(event) |
| 51 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | 214 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); |
| 52 return true; | 215 return true; |
| 53 end | 216 end |
| 54 | 217 |
| 55 local function itemremove_handler(event) | |
| 56 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | |
| 57 return true; | |
| 58 end | |
| 59 | |
| 60 local function list_handler(event) | 218 local function list_handler(event) |
| 61 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | 219 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); |
| 62 return true; | 220 return true; |
| 63 end | 221 end |
| 64 | 222 |
| 81 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | 239 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); |
| 82 return true; | 240 return true; |
| 83 end | 241 end |
| 84 | 242 |
| 85 module:hook("iq/self/urn:xmpp:archive:pref", preferences_handler); | 243 module:hook("iq/self/urn:xmpp:archive:pref", preferences_handler); |
| 244 module:hook("iq/self/urn:xmpp:archive:itemremove", itemremove_handler); | |
| 245 module:hook("iq/self/urn:xmpp:archive:sessionremove", sessionremove_handler); | |
| 86 module:hook("iq/self/urn:xmpp:archive:auto", auto_handler); | 246 module:hook("iq/self/urn:xmpp:archive:auto", auto_handler); |
| 87 module:hook("iq/self/urn:xmpp:archive:chat", chat_handler); | 247 -- module:hook("iq/self/urn:xmpp:archive:chat", chat_handler); |
| 88 module:hook("iq/self/urn:xmpp:archive:itemremove", itemremove_handler); | |
| 89 module:hook("iq/self/urn:xmpp:archive:list", list_handler); | 248 module:hook("iq/self/urn:xmpp:archive:list", list_handler); |
| 90 module:hook("iq/self/urn:xmpp:archive:modified", modified_handler); | 249 module:hook("iq/self/urn:xmpp:archive:modified", modified_handler); |
| 91 module:hook("iq/self/urn:xmpp:archive:remove", remove_handler); | 250 module:hook("iq/self/urn:xmpp:archive:remove", remove_handler); |
| 92 module:hook("iq/self/urn:xmpp:archive:retrieve", retrieve_handler); | 251 module:hook("iq/self/urn:xmpp:archive:retrieve", retrieve_handler); |
| 93 module:hook("iq/self/urn:xmpp:archive:save", save_handler); | 252 module:hook("iq/self/urn:xmpp:archive:save", save_handler); |