info.py 8.15 KB
Newer Older
Svetlana Tkachenko's avatar
gplv3    
Svetlana Tkachenko committed
1
2
3
4
5
#    guppy Copyright (C) 2010-2011 guppy team members.
#
#    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
#    This is free software, and you are welcome to redistribute it
#    under certain conditions; type `show c' for details.
6
7
8
9
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
10
#
11
12
13
14
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
15
#
16
17
18
19
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#  MA 02110-1301, USA.
Svetlana Tkachenko's avatar
gplv3    
Svetlana Tkachenko committed
20

FurryHead's avatar
FurryHead committed
21
import os, re
Svetlana Tkachenko's avatar
Svetlana Tkachenko committed
22
import configparser
FurryHead's avatar
FurryHead committed
23

24

FurryHead's avatar
FurryHead committed
25
26
@plugin
class Info(object):
Svetlana Tkachenko's avatar
Svetlana Tkachenko committed
27
    """Infobot. Use 'learn X as Y' and 'what is X'"""
FurryHead's avatar
FurryHead committed
28
    def __init__(self, server):
29
        self.require_auth = False
FurryHead's avatar
FurryHead committed
30
        self.server = server
31
32
33
34
        if 'infochar' in self.server.config:                     ##N# Sorry, this 
            self.plugin_trigger = self.server.config["infochar"] ##N# masterpiece is
        else:                                                    ##N# for backward
            self.plugin_trigger = "~"                            ##N# compatibility.
35
        self.server.pluginManager.loadPlugin("Auth")
36
        server.handle("message", self.handle_message)
auscompgeek's avatar
auscompgeek committed
37
        self.commands = ["what", "who", "learn", "forget", "fulldb"]
38
        self.server.handle("command", self.handle_command, self.commands)
39
        self.dbfile = self.server.config["confdir"] + "info.cfg"
FurryHead's avatar
FurryHead committed
40
        self.infodb = {}
41
        self.badchars = re.compile("[?]")
42

Svetlana Tkachenko's avatar
Svetlana Tkachenko committed
43
        self.configParser = configparser.RawConfigParser()
FurryHead's avatar
FurryHead committed
44
        if os.path.isfile(self.dbfile):
45
            self.configParser.read(self.dbfile)
46
            for k, v in self.configParser.items(self.server.config["network"]):
FurryHead's avatar
FurryHead committed
47
                self.infodb[k] = v
48

49
    def destroy(self):
Svetlana Tkachenko's avatar
Svetlana Tkachenko committed
50
        self.configParser = configparser.RawConfigParser()
51

52
53
        if os.path.isfile(self.dbfile):
            self.configParser.read(self.dbfile)
54

55
56
57
58
        fh = open(self.dbfile, "w")
        network = self.server.config["network"]
        if not self.configParser.has_section(network):
            self.configParser.add_section(network)
59

60
61
        for k, v in list(self.infodb.items()):
            self.configParser.set(network, k, v)
62

63
        self.configParser.write(fh)
FurryHead's avatar
FurryHead committed
64
        fh.close()
65

FurryHead's avatar
FurryHead committed
66
    def getInfo(self, key):
67
        for k, v in list(self.infodb.items()):
FurryHead's avatar
FurryHead committed
68
            if k.lower() == key.lower():
69
                return k, v
FurryHead's avatar
FurryHead committed
70

71
        return [None, None]
72

73
    def handle_message(self, channel, nick, message):
74
75
        """
        Handle messages not prefixed by comchar: react to things like
76
77
78
79
        <bob> !ask
        <bot> Ask your question, include all the details.
        <bot> !ask @ newbit
        <bot> newbie: Ask your question, include all the details.
80
        """
81
        message = message.strip()
82
83
84
85
        if message == "":              # empty message
            return
        if message[0] != self.plugin_trigger:  # message does not start with our trigger
            return
86
        message = message[1:].strip()  # work on the stuff after the trigger
87
88
        if message == "":              # ignore empty messages
            return
89
90
91
92
93
94
95
        if message.find("@") == -1:    # no nick handle
            key = message.strip()
            nick = ""
        else:                          # there is a nick handle
            list = message.split("@")
            key = list[0].strip()
            nick = list[1].strip()
96
97
98
        if key == "":                  # ignore empty keys
            return
        k, v = self.getInfo(key)       # actually get the factoid
99
100
101
102
103
        if k is not None and v is not None:
            if nick == "":
                self.server.doMessage(channel, "%s is %s" % (k, v))
            else:
                self.server.doMessage(channel, "%s: %s is %s" % (nick, k, v))
104
        else:  # tell the user in private that there is no such factoid (in-channel is annoying)
105
            self.server.doNotice(nick, "I don't know what " + key + " is.")
106

107
    def handle_command(self, channel, user, cmd, args, info_silent=False):
108

109
        def learn():
110
111
            if len(args) < 1:
                if not info_silent:
FurryHead's avatar
FurryHead committed
112
                    self.server.doMessage(channel, "...what should I learn?")
113
                return
114

115
116
            ####for i in range(0, len(args)):                   ##N# Useless because it strips 
            ####    args[i] = self.badchars.sub("", args[i])    #### the '?'' in the factoids.
117

118
119
120
            tmp = " ".join(args)
            ind = tmp.find(" as ")
            size = 4
121
            if ind == -1:
122
123
124
125
                ind = tmp.find(" as: ")
                size = 5
                if ind == -1:
                    if not info_silent:
FurryHead's avatar
FurryHead committed
126
127
                        self.server.doMessage(channel, "...what should I learn " + tmp + " as?")
                    return
128

129
            val = tmp[ind + size:]
130
131
            key = tmp[0:ind]
            key = key.replace("\t", "")
132
            k, v = self.getInfo(key)
133
134
135
136
            if k is not None and v is not None:
                if not info_silent:
                    self.server.doMessage(channel, "I already know what " + k + " is.")
                return
137

138
139
            self.infodb[key] = val
            if not info_silent:
FurryHead's avatar
FurryHead committed
140
                self.server.doMessage(channel, "Ok, I learned what " + key + " is.")
141
142

        def forget():
143
144
            if len(args) < 1:
                if not info_silent:
FurryHead's avatar
FurryHead committed
145
                    self.server.doMessage(channel, "...what should I forget?")
146
                return
147

148
149
            ####for i in range(0, len(args)):                   ##N# If not commented out it's not
            ####    args[i] = self.badchars.sub("", args[i])    ##N# possible to delete factoids with '?'
150

151
            key = " ".join(args).strip(" ")
152
            if key in self.infodb:
153
                del self.infodb[key]
154
                self.server.doMessage(channel, "Ok, I forgot what " + key + " is.")
155
            else:
156
                self.server.doMessage(channel, "Sorry, I don't know what " + key + " is.")
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
        if cmd == "what" or cmd == "who":
            for i in range(0, len(args)):
                args[i] = self.badchars.sub("", args[i])

            ind = 0
            for i in range(0, len(args)):
                if args[i] == "is" or args[i] == "are" or args[i] == "a" or args[i] == "an" or args[i] == "":
                    ind += 1
                else:
                    break

            nargs = []
            for i in range(ind, len(args)):
                if args[i] != "":
                    nargs.append(args[i])

            args = nargs

            if len(args) < 1:
                if not info_silent:
                    self.server.doMessage(channel, "...what should I tell you about?")
                return

            tmp = " ".join(args)
181
            k, v = self.getInfo(tmp)
182
183
184
185
186
187
188
189
190
191
192
193
194
195

            if k is not None and v is not None:
                self.server.doMessage(channel, user + ": " + k + ": " + v)
            else:
                if not info_silent:
                    self.server.doMessage(channel, user + ", I don't know what " + tmp + " is.")

        elif cmd == "learn":
            if not self.require_auth:
                learn()
            else:
                if self.server.getPlugin("auth").isMod(user):
                    learn()
                else:
196
                    self.server.doMessage(channel, user + ": You are not authorized to use this function. ")
197
198
199
200
201
202
203
204

        elif cmd == "forget":
            if not self.require_auth:
                forget()
            else:
                if self.server.getPlugin("auth").isMod(user):
                        forget()
                else:
205
                    self.server.doMessage(channel, user + ": You are not authorized to use this function. ")
206

207
        elif cmd == "fulldb":
208
            self.server.doMessage(channel, user + ": My database contains (separated by '|'): " + " | ".join(list(self.infodb.keys())))
209
210