core: restart on SIGHUP
[rbot] / lib / rbot / core / unicode.rb
1 #-- vim:sw=4:et
2 #++
3 #
4 # :title: Unicode plugin
5 #
6 # Author:: jsn (Dmitry Kim) <dmitry dot kim at gmail dot org>
7 #
8 # This plugin adds unicode-awareness to rbot. When it's loaded, all the
9 # character strings inside of rbot are assumed to be in proper utf-8
10 # encoding. The plugin takes care of translation to/from utf-8 on server IO,
11 # if necessary (translation charsets are configurable).
12
13 require 'iconv'
14
15 class UnicodePlugin < CoreBotModule
16     Config.register Config::BooleanValue.new(
17     'encoding.enable', :default => true,
18     :desc => "Support for non-ascii charsets",
19     :on_change => Proc.new { |bot, v| reconfigure_filter(bot) })
20
21     Config.register Config::ArrayValue.new(
22     'encoding.charsets', :default => ['utf-8', 'cp1252', 'iso-8859-15'],
23     :desc => "Ordered list of iconv(3) charsets the bot should try",
24     :on_change => Proc.new { |bot, v| reconfigure_filter(bot) })
25
26     class UnicodeFilter
27         def initialize(oenc, *iencs)
28             o = oenc.dup
29             o += '//ignore' if !o.include?('/')
30             i = iencs[0].dup
31             # i += '//ignore' if !i.include?('/')
32             @iencs = iencs.dup
33             @iconvs = @iencs.map { |_| Iconv.new('utf-8', _) }
34             debug "*** o = #{o}, i = #{i}, iencs = #{iencs.inspect}"
35             @default_in = Iconv.new('utf-8//ignore', i)
36             @default_out = Iconv.new(o, 'utf-8//ignore')
37         end
38
39         def in(data)
40             rv = nil
41             @iconvs.each_with_index { |ic, idx|
42                 begin
43                     debug "trying #{@iencs[idx]}"
44                     rv = ic.iconv(data)
45                     break
46                 rescue
47                 end
48             }
49
50             rv = @default_in.iconv(data) if !rv
51             debug ">> #{rv.inspect}"
52             return rv
53         end
54
55         def out(data)
56             rv = @default_out.iconv(data) rescue data # XXX: yeah, i know :/
57             debug "<< #{rv}"
58             rv
59         end
60     end
61
62
63     def initialize(*a)
64         super
65         @old_kcode = $KCODE
66         self.class.reconfigure_filter(@bot)
67     end
68
69     def cleanup
70         debug "cleaning up encodings"
71         @bot.socket.filter = nil
72         $KCODE = @old_kcode
73         super
74     end
75
76     def UnicodePlugin.reconfigure_filter(bot)
77         debug "configuring encodings"
78         enable = bot.config['encoding.enable']
79         if not enable
80             bot.socket.filter = nil
81             $KCODE = @old_kcode
82             return
83         end
84         charsets = bot.config['encoding.charsets']
85         charsets = ['utf-8'] if charsets.empty?
86         bot.socket.filter = UnicodeFilter.new(charsets[0], *charsets)
87         $KCODE = 'u'
88     end
89 end
90
91 UnicodePlugin.new