core/userdata: refactor set_data_hash method
[rbot] / 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 # Copyright:: (C) 2006,2007 Giuseppe Bilotta
8 # License:: GPL v2
9
10 module ::Irc
11   class User
12     # Retrive Bot data associated with the receiver. This method is
13     # intended for data retrieval only. See #set_bot_data() if you
14     # need to alter User data.
15     #
16     def botdata(key=nil)
17       Irc::Utils.bot.plugins['userdata'].get_data(self,key)
18     end
19     alias :get_botdata :botdata
20
21     # This method is used to store Bot data associated with the
22     # receiver. If no block is passed, _value_ is stored for the key
23     # _key_; if a block is passed, it will be called with the previous
24     # _key_ value as parameter, and its return value will be stored as
25     # the new value. If _value_ is present in the block form, it will
26     # be used to initialize _key_ if it's missing.
27     #
28     # If you have to do large-scale editing of the Bot data Hash,
29     # please use with_botdata.
30     # 
31     def set_botdata(key, value=nil, &block)
32       Irc::Utils.bot.plugins['userdata'].set_data(self, key, value, &block)
33     end
34
35     # This method yields the entire Bot data Hash to the block,
36     # and stores any changes done to it, returning a copy
37     # of the (changed) Hash.
38     #
39     def with_botdata(&block)
40       Irc::Utils.bot.plugins['userdata'].with_data(self, &block)
41     end
42
43   end
44 end
45
46 # User data is stored in registries indexed by BotUser
47 # name and Irc::User nick. This core module takes care
48 # of handling its usage.
49 #
50 class UserDataModule < CoreBotModule
51
52   def initialize
53     super
54     @ircuser = @registry.sub_registry('ircuser')
55     @botuser = @registry.sub_registry('botuser')
56   end
57
58   def get_data_hash(user)
59     iu = user.to_irc_user
60     bu = iu.botuser
61
62     ih = @ircuser[iu.nick] || {}
63
64     if bu.transient? or bu.default?
65       return ih
66     else
67       bh = @botuser[bu.username] || {}
68       return ih.merge! bh
69     end
70   end
71
72   def get_data(user, key=nil)
73     h = get_data_hash(user)
74     debug h
75     return h if key.nil?
76     return h[key]
77   end
78
79   def set_data_hash(user, h)
80     iu = user.to_irc_user
81     bu = iu.botuser
82
83     if bu.transient? or bu.default?
84       @ircuser[iu.nick] = h
85     else
86       @botuser[bu.username] = h
87     end
88   end
89
90   def set_data(user, key, value=nil, &block)
91     h = get_data_hash(user)
92     debug h
93
94     ret = value
95
96     if not block_given?
97       h[key] = value
98     else
99       if value and not h.has_key?(key)
100         h[key] = value
101       end
102       ret = yield h[key]
103     end
104     debug ret
105
106     set_data_hash(user, h)
107
108     return ret
109   end
110
111   def with_data(user, &block)
112     h = get_data_hash(user)
113     debug h
114     yield h
115
116     set_data_hash(user, h)
117
118     return h
119   end
120
121   def handle_get(m, params)
122     user = m.server.get_user(params[:nick]) || m.source
123     key = params[:key].intern
124     data = get_data(user, key)
125     if data
126       m.reply (_("%{key} data for %{user}: %{data}") % {
127         :key => key,
128         :user => user.nick,
129         :data => data
130       })
131     else
132       m.reply (_("sorry, no %{key} data for %{user}") % {
133         :key => key,
134         :user => user.nick,
135       })
136     end
137   end
138
139   ### TODO FIXME not yet: are we going to allow non-string
140   ### values for data? if so, this can't work ...
141   #
142   # def handle_set(m, params)
143   #   user = m.server.get_user(params[:nick]) || m.source
144   #   key = params[:key].intern
145   #   data = params[:data].to_s
146   # end
147
148 end
149
150 plugin = UserDataModule.new
151
152 plugin.map "get [:nick's] :key [data]",   :action => 'handle_get'
153 plugin.map "get :key [data] [for :nick]", :action => 'handle_get'
154 plugin.map "get :key [data] [of :nick]",  :action => 'handle_get'
155
156 # plugin.map "set [:nick's] :key [data] to :data", :action => handle_get
157 # plugin.map "set :key [data] [for :nick] to :data", :action => handle_get
158 # plugin.map "set :key [data] [of :nick] to :data", :action => handle_get