From 478abdd11956f5de0d8250cd2dbe44e8a104c4d1 Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Sun, 23 Sep 2007 10:57:08 +0000 Subject: UserData cote botmodule to handle user data storage/retrieval --- lib/rbot/botuser.rb | 51 ------------------ lib/rbot/core/userdata.rb | 130 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 51 deletions(-) create mode 100644 lib/rbot/core/userdata.rb (limited to 'lib') diff --git a/lib/rbot/botuser.rb b/lib/rbot/botuser.rb index d61926b8..a710a863 100644 --- a/lib/rbot/botuser.rb +++ b/lib/rbot/botuser.rb @@ -237,9 +237,6 @@ class Bot attr_reader :password attr_reader :netmasks attr_reader :perm - # Please remember to #set_changed() the Auth.manager - # when modifying data - attr_reader :data attr_writer :login_by_mask attr_writer :transient @@ -317,9 +314,6 @@ class Bot raise "must provide a usable mask for transient BotUser #{@username}" if @transient and @netmasks.empty? @perm = {} - - # @data = AuthNotifyingHash.new - @data = {} end # Inspection @@ -332,11 +326,6 @@ class Bot str << " @perm=#{@perm.inspect}" str << " @login_by_mask=#{@login_by_mask}" str << " @autologin=#{@autologin}" - if @data.empty? - str << " no data" - else - str << " data for #{@data.keys.join(', ')}" - end str << ">" end @@ -354,7 +343,6 @@ class Bot :perm => @perm, :login_by_mask => @login_by_mask, :autologin => @autologin, - :data => @data } end @@ -393,7 +381,6 @@ class Bot @netmasks.each { |n| Auth.manager.maskdb.add(self, n) } if @autologin end @perm = h[:perm] if h.has_key?(:perm) - @data.replace(h[:data]) if h.has_key?(:data) end # This method sets the password if the proposed new password @@ -904,44 +891,6 @@ end def botuser Irc::Bot::Auth.manager.irc_to_botuser(self) end - - # Bot-specific data can be stored with Irc::Users. This is - # internally obtained by storing data to the associated BotUser, - # but this is a detail plugin writers shouldn't care about. - # bot_data(:key) can be used to retrieve a particular data set. - # This method is intended for data retrieval, and if the retrieved - # data is modified directly there is no guarantee the changes will - # be saved back. Use #set_bot_data() for that. - # - def bot_data(key=nil) - return self.botuser.data if key.nil? - return self.botuser.data[key] - end - - # This method is used to store bot-specific data for the receiver. - # If no block is passed, _value_ is stored for the key _key_; - # if a block is passed, it will be called with the previous - # _key_ value as parameter, and its return value will be stored - # as the new value. If _value_ is present in the block form, it - # will be used to initialize _key_ if it's missing - # - def set_bot_data(key,value=nil,&block) - if not block_given? - self.botuser.data[key]=value - Irc::Bot::Auth.manager.set_changed - return value - end - if value and not bot_data.has_key?(key) - set_bot_data(key, value) - end - r = value - begin - r = yield bot_data(key) - ensure - Irc::Bot::Auth.manager.set_changed - end - return r - end end end diff --git a/lib/rbot/core/userdata.rb b/lib/rbot/core/userdata.rb new file mode 100644 index 00000000..84524c0a --- /dev/null +++ b/lib/rbot/core/userdata.rb @@ -0,0 +1,130 @@ +#-- vim:sw=2:et +#++ +# +# :title: rbot user data management from IRC +# +# Author:: Giuseppe "Oblomov" Bilotta +# Copyright:: (C) 2006,2007 Giuseppe Bilotta +# License:: GPL v2 + +module ::Irc + class User + # Retrive Bot data associated with the receiver. This method is + # intended for data retrieval only. See #set_bot_data() if you + # need to alter User data. + # + def bot_data(key=nil) + Irc::Utils.bot.plugins['userdata'].get_data(self,key) + end + + # This method is used to store Bot data associated with the + # receiver. If no block is passed, _value_ is stored for the key + # _key_; if a block is passed, it will be called with the previous + # _key_ value as parameter, and its return value will be stored as + # the new value. If _value_ is present in the block form, it will + # be used to initialize _key_ if it's missing + # + def set_bot_data(key, value=nil, &block) + Irc::Utils.bot.plugins['userdata'].set_data(self, key, value, &block) + end + end +end + +# User data is stored in registries indexed by BotUser +# name and Irc::User nick. This core module takes care +# of handling its usage. +# +class UserDataModule < CoreBotModule + + def initialize + super + @ircuser = @registry.sub_registry('ircuser') + @botuser = @registry.sub_registry('botuser') + end + + def get_data_hash(user) + iu = user.to_irc_user + bu = iu.botuser + + ih = @ircuser[iu.nick] || {} + + if bu.transient? or bu == Irc::Bot::Auth.defaultbotuser + return ih + else + bh = @botuser[bu.username] || {} + return ih.merge! bh + end + end + + def get_data(user, key=nil) + h = get_data_hash(user) + debug h + return h if key.nil? + return h[key] + end + + def set_data(user, key, value=nil, &block) + h = get_data_hash(user) + debug h + + ret = value + + if not block_given? + h[key] = value + else + if value and not h.has_key?(key) + h[key] = value + end + ret = yield h[key] + end + debug ret + + iu = user.to_irc_user + bu = iu.botuser + + if bu.transient? or bu == Irc::Bot::Auth.defaultbotuser + @ircuser[iu.nick] = h + else + @botuser[bu.username] = h + end + return ret + end + + def handle_get(m, params) + user = m.server.get_user(params[:nick]) || m.source + key = params[:key].intern + data = get_data(user, key) + if data + m.reply (_("%{key} data for %{user}: %{data}") % { + :key => key, + :user => user.nick, + :data => data + }) + else + m.reply (_("sorry, no %{key} data for %{user}") % { + :key => key, + :user => user.nick, + }) + end + end + + ### TODO FIXME not yet: are we going to allow non-string + ### values for data? if so, this can't work ... + # + # def handle_set(m, params) + # user = m.server.get_user(params[:nick]) || m.source + # key = params[:key].intern + # data = params[:data].to_s + # end + +end + +plugin = UserDataModule.new + +plugin.map "get [:nick's] :key [data]", :action => 'handle_get' +plugin.map "get :key [data] [for :nick]", :action => 'handle_get' +plugin.map "get :key [data] [of :nick]", :action => 'handle_get' + +# plugin.map "set [:nick's] :key [data] to :data", :action => handle_get +# plugin.map "set :key [data] [for :nick] to :data", :action => handle_get +# plugin.map "set :key [data] [of :nick] to :data", :action => handle_get -- cgit v1.2.3