]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/core/userdata.rb
ced5c1e7fb0eab0bbec478edf62a275a4bc619c8
[user/henk/code/ruby/rbot.git] / lib / rbot / core / userdata.rb
1 #-- vim:sw=2:et
2 #++
3 #
4 # :title: rbot user data management from IRC
5 #
6 # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
7
8 module ::Irc
9   class User
10     # Retrive Bot data associated with the receiver. This method is
11     # intended for data retrieval only. See #set_bot_data() if you
12     # need to alter User data.
13     #
14     def botdata(key=nil)
15       Irc::Utils.bot.plugins['userdata'].get_data(self,key)
16     end
17     alias :get_botdata :botdata
18
19     # This method is used to store Bot data associated with the
20     # receiver. If no block is passed, _value_ is stored for the key
21     # _key_; if a block is passed, it will be called with the previous
22     # _key_ value as parameter, and its return value will be stored as
23     # the new value. If _value_ is present in the block form, it will
24     # be used to initialize _key_ if it's missing.
25     #
26     # If you have to do large-scale editing of the Bot data Hash,
27     # please use with_botdata.
28     #
29     def set_botdata(key, value=nil, &block)
30       Irc::Utils.bot.plugins['userdata'].set_data(self, key, value, &block)
31     end
32
33     # This method yields the entire Bot data Hash to the block,
34     # and stores any changes done to it, returning a copy
35     # of the (changed) Hash.
36     #
37     def with_botdata(&block)
38       Irc::Utils.bot.plugins['userdata'].with_data(self, &block)
39     end
40
41     # This method removes the data associated with the key, returning
42     # the value of the deleted key.
43
44     def delete_botdata(*keys)
45       Irc::Utils.bot.plugins['userdata'].delete_data(self, *keys)
46     end
47
48   end
49 end
50
51 # User data is stored in registries indexed by BotUser
52 # name and Irc::User nick. This core module takes care
53 # of handling its usage.
54 #
55 class UserDataModule < CoreBotModule
56
57   def initialize
58     super
59     @ircuser = @registry.sub_registry('ircuser')
60     @transient = @registry.sub_registry('transient')
61     @botuser = @registry.sub_registry('botuser')
62   end
63
64   def get_data_hash(user, opts={})
65     plain = opts[:plain]
66     iu = user.to_irc_user
67     bu = iu.botuser
68
69     ih = @ircuser[iu.nick] || {}
70
71     if bu.default?
72       return ih
73     elsif bu.transient?
74       bh = @transient[bu.netmasks.first.fullform] || {}
75     else
76       bh = @botuser[bu.username] || {}
77     end
78     ih.merge!(bh)
79
80     unless plain
81       class << ih
82         alias :single_retrieve :[]
83         alias :single_assign :[]=
84           include DottedIndex
85       end
86     end
87
88     return ih
89   end
90
91   def get_data(user, key=nil)
92     h = get_data_hash(user)
93     debug h
94     return h if key.nil?
95     return h[key]
96   end
97
98   def set_data_hash(user, hh)
99     iu = user.to_irc_user
100     bu = iu.botuser
101
102     # we .dup the hash to remove singleton methods
103     # and make it dump-able
104     h = hh.dup
105
106     @ircuser[iu.nick] = h
107     return h if bu.default?
108
109     if bu.transient?
110       @transient[bu.netmasks.first.fullform] = h
111     else
112       @botuser[bu.username] = h
113     end
114     return h
115   end
116
117   def set_data(user, key, value=nil, &block)
118     h = get_data_hash(user)
119     debug h
120
121     ret = value
122
123     if not block_given?
124       h[key] = value
125     else
126       if value and not h.has_key?(key)
127         h[key] = value
128       end
129       ret = yield h[key]
130     end
131     debug ret
132
133     set_data_hash(user, h)
134
135     return ret
136   end
137
138   def with_data(user, &block)
139     h = get_data_hash(user)
140     debug h
141     yield h
142
143     set_data_hash(user, h)
144
145     return h
146   end
147
148   def delete_data(user, *keys)
149     h = get_data_hash(user)
150     debug h
151     rv = keys.map { |k| h.delete k }
152     set_data_hash(user, h)
153     rv.size == 1 ? rv.first : rv
154   end
155
156   def handle_get(m, params)
157     user = m.server.get_user(params[:nick]) || m.source
158     key = params[:key].intern
159     data = get_data(user, key)
160     if data
161       m.reply(_("%{key} data for %{user}: %{data}") % {
162         :key => key,
163         :user => user.nick,
164         :data => data
165       })
166     else
167       m.reply(_("sorry, no %{key} data for %{user}") % {
168         :key => key,
169         :user => user.nick,
170       })
171     end
172   end
173
174   ### TODO FIXME not yet: are we going to allow non-string
175   ### values for data? if so, this can't work ...
176   #
177   # def handle_set(m, params)
178   #   user = m.server.get_user(params[:nick]) || m.source
179   #   key = params[:key].intern
180   #   data = params[:data].to_s
181   # end
182
183   def event_botuser(action, opts={})
184     case action
185     when :copy, :rename
186       source = opts[:source]
187       return unless @botuser.key?(source)
188       dest = opts[:dest]
189       @botuser[dest] = @botuser[source].dup
190       @botuser.delete(source) if action == :rename
191     when :pre_perm
192       @permification ||= {}
193       k = [opts[:irc_user], opts[:bot_user]]
194       @permification[k] = get_data_hash(opts[:irc_user], :plain => true)
195     when :post_perm
196       @permification ||= {}
197       k = [opts[:irc_user], opts[:bot_user]]
198       if @permification.has_key?(k)
199         @botuser[opts[:bot_user]] = @permification[k]
200         @permification.delete(k)
201       end
202     end
203   end
204
205 end
206
207 plugin = UserDataModule.new
208
209 plugin.map "get [:nick's] :key [data]",   :action => 'handle_get'
210 plugin.map "get :key [data] [for :nick]", :action => 'handle_get'
211 plugin.map "get :key [data] [of :nick]",  :action => 'handle_get'
212
213 # plugin.map "set [:nick's] :key [data] to :data", :action => handle_get
214 # plugin.map "set :key [data] [for :nick] to :data", :action => handle_get
215 # plugin.map "set :key [data] [of :nick] to :data", :action => handle_get