]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/core/userdata.rb
Licensing uniformity: dual-license rbot core under MIT+acknowledgement and GPLv2
[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   end
42 end
43
44 # User data is stored in registries indexed by BotUser
45 # name and Irc::User nick. This core module takes care
46 # of handling its usage.
47 #
48 class UserDataModule < CoreBotModule
49
50   def initialize
51     super
52     @ircuser = @registry.sub_registry('ircuser')
53     @transient = @registry.sub_registry('transient')
54     @botuser = @registry.sub_registry('botuser')
55   end
56
57   def get_data_hash(user, opts={})
58     plain = opts[:plain]
59     iu = user.to_irc_user
60     bu = iu.botuser
61
62     ih = @ircuser[iu.nick] || {}
63
64     if bu.default?
65       return ih
66     elsif bu.transient?
67       bh = @transient[bu.netmasks.first.fullform] || {}
68     else
69       bh = @botuser[bu.username] || {}
70     end
71     ih.merge!(bh)
72
73     unless plain
74       class << ih
75         alias :single_retrieve :[]
76         alias :single_assign :[]=
77           include DottedIndex
78       end
79     end
80
81     return ih
82   end
83
84   def get_data(user, key=nil)
85     h = get_data_hash(user)
86     debug h
87     return h if key.nil?
88     return h[key]
89   end
90
91   def set_data_hash(user, hh)
92     iu = user.to_irc_user
93     bu = iu.botuser
94
95     # we .dup the hash to remove singleton methods
96     # and make it dump-able
97     h = hh.dup
98
99     @ircuser[iu.nick] = h
100     return h if bu.default?
101
102     if bu.transient?
103       @transient[bu.netmasks.first.fullform] = h
104     else
105       @botuser[bu.username] = h
106     end
107     return h
108   end
109
110   def set_data(user, key, value=nil, &block)
111     h = get_data_hash(user)
112     debug h
113
114     ret = value
115
116     if not block_given?
117       h[key] = value
118     else
119       if value and not h.has_key?(key)
120         h[key] = value
121       end
122       ret = yield h[key]
123     end
124     debug ret
125
126     set_data_hash(user, h)
127
128     return ret
129   end
130
131   def with_data(user, &block)
132     h = get_data_hash(user)
133     debug h
134     yield h
135
136     set_data_hash(user, h)
137
138     return h
139   end
140
141   def handle_get(m, params)
142     user = m.server.get_user(params[:nick]) || m.source
143     key = params[:key].intern
144     data = get_data(user, key)
145     if data
146       m.reply(_("%{key} data for %{user}: %{data}") % {
147         :key => key,
148         :user => user.nick,
149         :data => data
150       })
151     else
152       m.reply(_("sorry, no %{key} data for %{user}") % {
153         :key => key,
154         :user => user.nick,
155       })
156     end
157   end
158
159   ### TODO FIXME not yet: are we going to allow non-string
160   ### values for data? if so, this can't work ...
161   #
162   # def handle_set(m, params)
163   #   user = m.server.get_user(params[:nick]) || m.source
164   #   key = params[:key].intern
165   #   data = params[:data].to_s
166   # end
167
168   def event_botuser(action, opts={})
169     case action
170     when :copy, :rename
171       source = opts[:source]
172       return unless @botuser.key?(source)
173       dest = opts[:dest]
174       @botuser[dest] = @botuser[source].dup
175       @botuser.delete(source) if action == :rename
176     when :pre_perm
177       @permification ||= {}
178       k = [opts[:irc_user], opts[:bot_user]]
179       @permification[k] = get_data_hash(opts[:irc_user], :plain => true)
180     when :post_perm
181       @permification ||= {}
182       k = [opts[:irc_user], opts[:bot_user]]
183       if @permification.has_key?(k)
184         @botuser[opts[:bot_user]] = @permification[k]
185         @permification.delete(k)
186       end
187     end
188   end
189
190 end
191
192 plugin = UserDataModule.new
193
194 plugin.map "get [:nick's] :key [data]",   :action => 'handle_get'
195 plugin.map "get :key [data] [for :nick]", :action => 'handle_get'
196 plugin.map "get :key [data] [of :nick]",  :action => 'handle_get'
197
198 # plugin.map "set [:nick's] :key [data] to :data", :action => handle_get
199 # plugin.map "set :key [data] [for :nick] to :data", :action => handle_get
200 # plugin.map "set :key [data] [of :nick] to :data", :action => handle_get