-
Notifications
You must be signed in to change notification settings - Fork 2
/
bot.py
152 lines (131 loc) · 5.75 KB
/
bot.py
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from google.appengine.api import xmpp
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import memcache
from google.appengine.ext import db
from google.appengine.api import users
import os
import re
import datetime
from xml.sax.saxutils import escape
class ChatUser(db.Model):
jid = db.StringProperty(required=True)
nick = db.StringProperty(required=True)
status = db.StringProperty(required=True)
timezone = db.StringProperty()
created_at = db.DateTimeProperty()
class MessageLog(db.Model):
from_jid = db.StringProperty()
nick = db.StringProperty()
body = db.TextProperty()
created_at = db.DateTimeProperty()
class XMPPHandler(webapp.RequestHandler):
def post(self):
message = xmpp.Message(self.request.POST)
stripped_jid = message.sender.partition('/')[0]
short_nick = stripped_jid.split('@')[0]
# Is this a user that we know about? If not then add this user to our user list
from_user = db.GqlQuery("SELECT * FROM ChatUser WHERE jid = :1", stripped_jid).get()
if from_user == None:
from_user = ChatUser(jid = stripped_jid, nick = short_nick, status = 'online', created_at = datetime.datetime.now()).put()
message.reply("Welcome to Panoptibot, komrade!")
message.reply("commands are /hist, /nick [new nick name], /who, /timezone, /add [jabber id], /remove [nick] /img [url]")
message.reply("Source code at: http://github.com/conorh/panoptibot-gae/")
message.reply("")
message.reply("Remeber to set your nickname with /nick")
self.process_message(message, from_user)
def update_users_status(self):
all_users = ChatUser.all().fetch(100)
for user in all_users:
if user.status != 'quiet':
if xmpp.get_presence(user.jid):
user.status = 'online'
else:
user.status = 'offline'
user.put()
return all_users
def output_history(self, messages, from_user):
reply = ""
for m in messages:
reply += m.created_at.strftime("%I:%M%p UTC") + " " + m.nick + ": " + m.body + "\n"
return reply
def html_message(self, from_user, body, escape_message=True):
if(escape_message):
body = escape(body)
reply = "<body>" + escape(from_user.nick) + ": " + body + "</body>"
reply += "<html xmlns='http://jabber.org/protocol/xhtml-im'><body xmlns='http://www.w3.org/1999/xhtml'>"
reply += "<strong>" + escape(from_user.nick) + ":</strong> " + body
reply += "</body></html>"
return reply
def send_to_all(self, from_user, message, escape_message=True, html_message=True):
all_users = self.update_users_status()
jids = [user.jid for user in all_users if user.status == 'online' and user.jid != from_user.jid]
if len(jids) > 0:
if html_message:
reply = self.html_message(from_user, message, escape_message)
elif escape_message:
reply = escape(message)
else:
reply = message
xmpp.send_message(jids, reply, None, xmpp.MESSAGE_TYPE_CHAT, html_message)
def process_message(self, message, from_user):
reply = None
# message starts with a / and has the format '/command option'
match = re.match(r"(\/\w+)(?:\s|$)(.*)", message.body)
if not match:
MessageLog(nick = from_user.nick, from_jid = message.sender, body = message.body, created_at = datetime.datetime.now()).put()
self.send_to_all(from_user, message.body)
return
command = match.group(1)
if command == "/add":
jid = match.group(2)
xmpp.send_invite(jid)
reply = "Sent invitation to " + jid
elif command == "/remove":
user = ChatUser.gql("WHERE nick = :1", match.group(2)).get()
if user != None:
user.delete()
reply = "Removed user"
else:
reply = "User not found"
elif command == "/help":
reply = "commands are /who /hist, /quiet /resume, /nick [new nick name], /who, /add [jabber id], /remove [nick] /img [url]"
elif command == "/h" or command == "/hist" or command == "/history":
history = MessageLog.gql("ORDER BY created_at DESC").fetch(20)
reply = self.output_history(history, from_user)
elif command == "/img":
MessageLog(nick = from_user.nick, from_jid = message.sender, body = message.body, created_at = datetime.datetime.now()).put()
self.send_to_all(from_user, "<img src='" + match.group(2) + "'/>", False)
elif command == "/n" or command == "/nick" or command == "/nickname":
self.send_to_all(from_user, "Changed nickname to" + match.group(2))
from_user.nick = match.group(2)
from_user.put()
reply = "nickname set to " + from_user.nick
elif command == "/w" or command == "/who":
reply = "User Statuses:\n"
for user in self.update_users_status():
reply += " " + user.nick + ": " + user.status + " (" + user.jid + ")\n"
elif command == "/q" or command == "/quiet":
from_user.status = 'quiet'
from_user.put()
reply = "Your status has been set to quiet. You will no longer receive messages from the bot until you /resume"
elif command == "/r" or command == "/resume":
from_user.status = 'online'
from_user.put()
reply = "You will start receiving messages from the bot again."
elif command == "/s" or command == "/search":
reply = "Not implemented yet"
#messages = MessageLog.search(match.group(2))
#reply = self.output_history(messages, from_user)
elif command == "/timezone":
new_zone = tz_helper.timezone(match.group(2))
elif command == "/ver":
reply = "0.1"
else:
reply = "Unknown command"
message.reply(escape(reply))
application = webapp.WSGIApplication([('/_ah/xmpp/message/chat/', XMPPHandler)], debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()