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
|
# coding: utf-8
# This file is a part of VK4XMPP transport
# © simpleApps, 2013 — 2016.
"""
Module purpose is to handle presences from groupchats
"""
from __main__ import *
from __main__ import _
def handleChatErrors(source, prs):
"""
Handles error presences from groupchats
Args:
source: the source jid
prs: the xmpp.Presence object
"""
# todo: leave on 401, 403, 405
# and rejoin timer on 404, 503
destination = prs.getTo().getStripped()
error = prs.getErrorCode()
status = prs.getStatusCode()
nick = prs.getFrom().getResource()
jid = prs.getJid()
errorType = prs.getTagAttr("error", "type")
user = Chat.getUserObject(source)
if user and source in getattr(user, "chats", {}):
chat = user.chats[source]
if chat.creation_failed:
raise xmpp.NodeProcessed()
if error == "409" and errorType == "cancel":
id = vk2xmpp(destination)
if id in chat.users:
nick += "."
if not chat.created and id == TransportID:
chat.users[id]["name"] = nick
chat.create(user)
else:
joinChat(source, nick, destination)
if status == "303":
if jid == user.source:
chat.owner_nickname = prs.getNick()
runDatabaseQuery("update groupchats where jid=? set nick=?",
(source, chat.owner_nickname), set=True)
elif error or status:
logger.debug("groupchats: presence error (error #%s, status #%s) "
"from source %s (jid: %s)" % (error, status, source, user.source if user else "unknown"))
raise xmpp.NodeProcessed()
def handleChatPresences(source, prs):
"""
Makes the old users leave
Args:
source: stanza source
prs: xmpp.Presence object
"""
jid = prs.getJid() or ""
if "@" in jid:
user = Chat.getUserObject(source)
if user and source in getattr(user, "chats", {}):
chat = user.chats[source]
if jid.split("@")[1] == TransportID and chat.created:
id = vk2xmpp(jid)
if id != TransportID and id not in chat.users.keys():
if (time.gmtime().tm_mon, time.gmtime().tm_mday) == (4, 1):
setAffiliation(source, "outcast", jid, reason=_("Get the hell outta here!"))
else:
leaveChat(source, jid)
if (prs.getRole(), prs.getAffiliation()) == ("moderator", "owner"):
if jid != TransportID:
runDatabaseQuery("update groupchats set owner=? where jid=?", (source, jid), set=True)
if chat.isUpdateRequired():
updateLastUsed(chat)
# TODO: don't rewrite it every time we get a presence
if jid.split("/")[0] == user.source:
chat.owner_nickname = prs.getFrom().getResource()
runDatabaseQuery("update groupchats set nick=? where jid=? ", (chat.owner_nickname, source), set=True)
raise xmpp.NodeProcessed()
elif user and prs.getType() != "unavailable":
chat = createChat(user, source)
chat.invited = True # assume the user's joined themselves
@utils.safe
def presence_handler(cl, prs):
"""
xmpppy presence callback
Args:
cl: the xmpp.Client object
prs: the xmpp.Presence object
"""
source = prs.getFrom().getStripped()
status = prs.getStatus()
if status or prs.getType() == "error":
handleChatErrors(source, prs)
handleChatPresences(source, prs) # It won't be called if handleChatErrors was called in the first time
MOD_TYPE = "presence"
MOD_HANDLERS = ((presence_handler, "", "", True),)
MOD_FEATURES = []
|