summaryrefslogtreecommitdiff
path: root/data/rbot/plugins/points.rb
blob: 34af9b5090d1ad4fd7bb076e7e0c8a3aced1fcfe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
class PointsPlugin < Plugin
  def initialize
    super

    # this plugin only wants to store ints!
    class << @registry
      def store(val)
        val.to_i
      end
      def restore(val)
        val.to_i
      end
    end
    @registry.set_default(0)

    # import if old file format found
    oldpoints = @bot.path 'points.rbot'
    if File.exist? oldpoints
      log "importing old points data"
      IO.foreach(oldpoints) do |line|
        if(line =~ /^(\S+)<=>([\d-]+)$/)
          item = $1
          points = $2.to_i
          @registry[item] = points
        end
      end
      File.delete oldpoints
    end
  end

  def stats(m, params)
    if (@registry.length)
      max = @registry.values.max || "zero"
      min = @registry.values.min || "zero"
      best = @registry.to_hash.key(max) || "nobody"
      worst = @registry.to_hash.key(min) || "nobody"
      m.reply "#{@registry.length} items. Best: #{best} (#{max}); Worst: #{worst} (#{min})"
    end
  end

  def dump(m, params)
    if (@registry.length)
      msg = "Points dump: "
      msg << @registry.to_hash.sort_by { |k, v| v }.reverse.
                       map { |k,v| "#{k}: #{v}" }.
                       join(", ")
      m.reply msg
    else
      m.reply "nobody has any points yet!"
    end
  end

  def points(m, params)
    thing = params[:key]
    thing = m.sourcenick unless thing
    thing = thing.to_s
    points = @registry[thing]
    if(points != 0)
      m.reply "points for #{thing}: #{@registry[thing]}"
    else
      m.reply "#{thing} has zero points"
    end
  end

  def setpoints(m, params)
    thing = (params[:key] || m.sourcenick).to_s
    @registry[thing] = params[:val].to_i
    points(m, params)
  end

  def help(plugin, topic="")
    "points module: Keeps track of internet points, infusing your pointless life with meaning. Listens to everyone's chat. <thing>++/<thing>-- => increase/decrease points for <thing>, points for <thing>? => show points for <thing>, pointstats => show best/worst, pointsdump => show everyone's points. Points are a community rating system - only in-channel messages can affect points and you cannot adjust your own."
  end

  def message(m)
    return unless m.public? && m.message.match(/\+\+|--/)
    arg = nil
    op = nil
    ac = Hash.new
    m.message.split.each_with_index do |tok, i|
      # ignore preceeding +/-
      if op && arg.nil?
        op = nil
      end
      tok.sub!(/[:,]$/, '') if i == 0
      catch :me_if_you_can do
        if m.channel.users[tok].nil?
          if tok =~ /^(.*[^-].*)(?:--)$/
            op, arg = '--', $1
            next
          elsif tok =~ /^(.*[^+].*)(?:\+\+)$/
            op, arg = '++', $1
            next
          end
        end

        if (tok =~ /^--+$/) || (tok =~ /^\+\++$/)
          op = tok.slice(0, 2)
        else
          arg = tok
        end
      end # catch

      if op && arg
        ac[arg] ||= 0
        ac[arg] += (op == '--' ? -1 : 1) unless arg.downcase == m.sourcenick.downcase
        op = arg = nil
      end
    end

    ac.each do |k, v|
      next if v == 0 or /--|\+\+/.match(k)
      # strip invisible formatting characters like bold or color codes
      k = k.gsub(FormattingRx, '')
      next if k.downcase == m.sourcenick.downcase
      @registry[k] += (v > 0 ? 1 : -1)
      m.reply @bot.lang.get("thanks") if k == @bot.nick && v > 0
      m.reply "#{k} now has #{@registry[k]} points!"
    end
  end
end

plugin = PointsPlugin.new

plugin.default_auth( 'edit', false )

plugin.map 'pointstats', :action => 'stats'
plugin.map 'points :key', :defaults => {:key => false}
plugin.map 'setpoints :key :val', :defaults => {:key => false}, :requirements => {:val => /^-?\d+$/}, :auth_path => 'edit::set!'
plugin.map 'points for :key'
plugin.map 'pointsdump', :action => 'dump'