Initialize seen database *before* we call super
[six.git] / plugins / scribe.rb
blob6dab50ad12cc494fb7cd40eb7aa41e259a27b4f5
2 # Scribe plugin for CyBot, which passes around notes.
5 class Scribe < PluginBase
7   def initialize(*args)
8     @brief_help = 'Passes notes between people.'
9     @notes = {}
10     super(*args)
11     @user_watch = method(:user_watch)
12     $user.user_watch_hooks << @user_watch
13   end
15   def unregister
16     $user.user_watch_hooks.delete @user_watch
17     @user_watch = nil
18   end
20   def user_watch(seen_or_lost, irc, user_nick)
21     if seen_or_lost
22       if (n = @notes[sn = irc.server.name]) and (un = n[user_nick]) and !un.empty?
23         count = 0
24         un.each do |n|
25           if !n[3]
26             n[3] = true
27             count += 1
28           end
29         end
30         if count > 0
31           irc.from.notice("You have #{un.length} unread notes (#{count} of which I haven't told you about before). Use the 'notes' command to list them.")
32         end
33       end
34     end
35   end
37   # Load/save database.
38   def load
39     begin
40       Dir[file_name('*.notes')].each do |n|
41         Kernel.puts "Note file: #{n}"
42         bn = File.basename(n)
43         i = bn.rindex ?.
44         @notes[bn[0...i]] = YAML.load_file(n)
45       end
46     rescue Exception => e
47       Kernel.puts e.message
48       Kernel.puts e.backtrace.join("\n")
49     end
50   end
51   def save
52     begin
53       @notes.each do |k,v|
54         open_file("#{k}.notes", 'w') do |f|
55           f.puts "# CyBot scribe plugin: Notes for server '#{k}'"
56           YAML.dump(v, f)
57           f.puts ''
58         end
59       end
60     rescue Exception => e
61       Kernel.puts e.message
62       Kernel.puts e.backtrace.join("\n")
63     end
64   end
66   # Send a new note or read your next note.
67   # Usages:
68   # note              Read the next unread note for you.
69   # note <num>        Read note number <num>.
70   # note <to> <text>  Write a new note to someone.
71   #
72   def cmd_note(irc, line)
73     u = $user.get_nick(irc) or return
74     nu = IRC::Address.normalize(u)
75     n = @notes[sn = irc.server.name] || (@notes[sn] = {})
76     now = Time.now.to_i
77     if !line or line.empty?
78       if (e = n[nu]) and !e.empty?
79         from, date, txt = e.shift
80         n.delete(nu) if e.empty?
81         irc.reply "From #{from}, sent #{seconds_to_s(now - date, irc)} ago: #{txt}"
82       else
83         irc.reply "You have no unread notes."
84       end
85     else
86       to, txt = line.split(' ', 2)
87       if txt
88         if (t = $user.get_data(to, sn))
89           nto = IRC::Address.normalize(to)
90           nl = n[nto] || (n[nto] = [])
91           if (announced = $user.get_nick(to, sn))
92             as = (nn = irc.from.nick) == u ? '' : " (as #{nn.capitalize})"
93             irc.server.notice(to, "#{u.capitalize}#{as} has sent you a note. Use 'notes' to list your unread notes.")
94           end
95           nl << [u, now, txt, announced ? true : false]
96           irc.reply "Ok, note to #{to} added."
97         else
98           irc.reply "No such user, #{to}."
99         end
100       else
101         if !(e = n[nu]) or e.empty?
102           irc.reply "You have no unread notes."
103         else
104           begin
105             i = Integer(to)
106             if i >= 1 and i <= e.length
107               from, date, txt = e[i - 1]
108               irc.reply "Note #{i} from #{from}, sent #{seconds_to_s(now - date, irc)} ago: #{txt}"
109             else
110               irc.reply "Note number out of range. You have #{e.length} unread notes."
111             end
112           rescue ArgumentError
113             irc.reply "USAGE: note <number>"
114           end
115         end
116       end
117     end
118   end
119   help :note, "Use 'note <nick> <message>' to send a note, or 'note' to read and remove your next available note.  You can also type 'note <n>' to read (wihtout removing) note number <n>.  Use the 'notes' command to get a list."
121   # List unread notes.
122   def cmd_notes(irc, line)
123     u = $user.get_nick(irc) or return
124     if (s = @notes[irc.server.name]) and (s = s[IRC::Address.normalize(u)]) and !s.empty?
125       i = 0
126       irc.reply "You have the following notes: #{s.map do |e|
127         i += 1
128         "[#{i}] #{e[0]} (#{seconds_to_s(Time.now.to_i - e[1], irc)} ago)"
129       end.join(', ')}"
130     else
131       irc.reply "You have no unread notes."
132     end
133   end
134   help :notes, 'Displays a list of your currently unread notes.'