diff options
author | John Smith <mrdoctorwho@gmail.com> | 2016-12-25 19:43:07 +0300 |
---|---|---|
committer | John Smith <mrdoctorwho@gmail.com> | 2016-12-25 19:43:07 +0300 |
commit | f8a0a94f6e9862de981b48b9c501a6f6f21a6d4d (patch) | |
tree | c9314e1c776cad1aea00cd19606d0dbff35491ee /extensions | |
parent | 3f8ddcd7131889ba1a006ca11c8ae7e339e6fcd9 (diff) | |
parent | 77e8b33ce1360bfe78cd1fa2d67c8010c0256ce2 (diff) |
Merge branch 'testing'
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/alive_keeper.py | 2 | ||||
-rw-r--r-- | extensions/attachments.py | 36 | ||||
-rw-r--r-- | extensions/avatar_hash.py | 6 | ||||
-rw-r--r-- | extensions/captcha_forms.py | 34 | ||||
-rw-r--r-- | extensions/forwarded_messages.py | 3 | ||||
-rw-r--r-- | extensions/groupchats.py | 227 | ||||
-rw-r--r-- | extensions/interpreter.py | 4 | ||||
-rw-r--r-- | extensions/status-from-vk.py | 4 | ||||
-rw-r--r-- | extensions/status-to-vk.py | 4 | ||||
-rw-r--r-- | extensions/sticker.py | 2 | ||||
-rw-r--r-- | extensions/typing_reader.py | 4 | ||||
-rw-r--r-- | extensions/user_activity.py | 5 | ||||
-rw-r--r-- | extensions/user_nickname.py | 8 |
13 files changed, 199 insertions, 140 deletions
diff --git a/extensions/alive_keeper.py b/extensions/alive_keeper.py index 9d064b1..5deace0 100644 --- a/extensions/alive_keeper.py +++ b/extensions/alive_keeper.py @@ -5,7 +5,7 @@ # Add a field named ALIVE_KEEPER_ENABLED in the main config file and set it's value to True in order to enable the keeper. """ -Makes the transport ping itself, so it can detect connection hang +Makes the transport ping itself, so it can detect if the connection hanged It's also can be useful for Openfire administrators in case if the transport suddenly disconnects """ diff --git a/extensions/attachments.py b/extensions/attachments.py index ac5305b..16400de 100644 --- a/extensions/attachments.py +++ b/extensions/attachments.py @@ -1,23 +1,24 @@ # coding: utf-8 # This file is a part of VK4XMPP transport -# © simpleApps, 2013 — 2015. +# © simpleApps, 2013 — 2016. import urllib from printer import * VK_AUDIO_SEARCH_LINK = "https://vk.com/search?c[q]=%s&c[section]=audio" -WALL_LINK = "https://vk.com/wall%(owner_id)s_%(post_id)s" - +WALL_LINK = "https://vk.com/wall%(to_id)s_%(id)s" +WALL_COMMENT_LINK = "https://vk.com/wall%(owner_id)s_%(post_id)s?w=wall%(owner_id)s3_%(post_id)s" +PHOTO_SIZES = ("src_xxxbig", "src_xxbig", "src_xbig", "src_big", "src", "url", "src_small") +STICKER_SIZES = ("photo_256", "photo_128", "photo_64") GLOBAL_USER_SETTINGS["parse_wall"] = {"value": 0, "label": "Parse wall attachments"} - # The attachments that don't require any special movements SIMPLE_ATTACHMENTS = {"doc": "Document: “%(title)s” — %(url)s", "link": "URL: %(title)s — %(url)s", "poll": "Poll: %(question)s", "page": "Page: %(title)s — %(view_url)s", - "video": "Video: %(title)s (%(description)s, %(views)d views) — https://vk.com/video%(owner_id)s_%(id)s"} # TODO: Add duration + "video": "Video: %(title)s (%(description)s, %(views)d views) — https://vk.com/video%(owner_id)s_%(vid)s"} # TODO: Add duration & fix empty desc def parseAttachments(self, msg, spacer=""): @@ -50,14 +51,14 @@ def parseAttachments(self, msg, spacer=""): else: name = "“%s”" % self.vk.getGroupData(tid)["name"] body += "Post on %s wall:\n" % name - if current.get("text"): - body += spacer + uhtml(current["text"].replace("\n", "\n" + spacer)) + "\n" - body += spacer + parseAttachments(self, current, spacer) + "\n" + spacer + "\n" + if current.get("text") or current.get("copy_text"): + body += spacer + uhtml(compile_eol.sub("\n" + spacer, current["text"] or current.get("copy_text"))) + "\n" + if current.get("attachments"): + body += spacer + parseAttachments(self, current, spacer) + "\n" + spacer + "\n" body += spacer + ("Wall: %s" % WALL_LINK % current) elif type == "photo": - keys = ("photo_2560", "photo_1280", "photo_807", "photo_604", "photo_130", "photo_75") - for key in keys: + for key in PHOTO_SIZES: if key in current: body += "Photo: %s" % current[key] # No new line needed if we have just one photo and no text break @@ -70,17 +71,18 @@ def parseAttachments(self, msg, spacer=""): body += "Audio: %(artist)s — “%(title)s“ (%(time)s min) — %(url)s" % current elif type == "sticker": - keys = ("photo_256", "photo_128", "photo_64") - for key in keys: + for key in STICKER_SIZES: if key in current: body += "Sticker: %s" % current[key] break elif type == "wall_reply": - current["name"] = self.vk.getUserData(current["from_id"])["name"] # TODO: What if it's a community? from_id will be negative. - # TODO: Remove "[idxxx|Name]," from the text - current["text"] = uhtml(current["text"].replace("\n", "\n" + spacer)) - current["url"] = WALL_LINK % current + # TODO: What if it's a community? from_id will be negative. + # TODO: Remove "[idxxx|Name]," from the text or make it a link if XHTML is allowed + current["name"] = self.vk.getUserData(current["uid"])["name"] + current["text"] = uhtml(compile_eol.sub("\n" + spacer, current["text"])) + current["url"] = WALL_COMMENT_LINK % current + body += "Commentary to the post on a wall:\n" body += spacer + "<%(name)s> %(text)s\n" % current body += spacer + "Post URL: %(url)s" % current @@ -93,4 +95,4 @@ def parseAttachments(self, msg, spacer=""): result += body return result -registerHandler("msg01", parseAttachments) +registerHandler("msg01", parseAttachments)
\ No newline at end of file diff --git a/extensions/avatar_hash.py b/extensions/avatar_hash.py index 85b0ca0..3e62946 100644 --- a/extensions/avatar_hash.py +++ b/extensions/avatar_hash.py @@ -42,7 +42,7 @@ class AvatarHash(object): return data def sendPhotoRequest(self, user, uids): - data = user.vk.method("execute.getPhotos_new", + data = user.vk.method("execute.getPhotos", {"users": self.join(uids), "size": PhotoSize}) or [] return data @@ -85,8 +85,8 @@ class AvatarHash(object): def addPresenceHash(prs, destination, source): - if destination in Transport and not prs.getType(): - user = Transport[destination] + if destination in Users and not prs.getType(): + user = Users[destination] if user.settings.avatar_hash: x = prs.setTag("x", namespace=xmpp.NS_VCARD_UPDATE) uid = vk2xmpp(source) diff --git a/extensions/captcha_forms.py b/extensions/captcha_forms.py index 20600c4..b701dec 100644 --- a/extensions/captcha_forms.py +++ b/extensions/captcha_forms.py @@ -8,12 +8,15 @@ from hashlib import sha1 Implements XEP-0158: CAPTCHA Forms """ -def sendCaptcha(user, url): - logger.debug("VK: sending message with captcha to %s", user.source) + +def sendCaptcha(vk, url): + logger.debug("VK: sending message with captcha to %s", vk.source) body = _("WARNING: VK has sent you a CAPTCHA." - " Please, follow %s and enter the text shown on the image to the chat." - " Example: !captcha my_captcha_key. Tnx") % url - msg = xmpp.Message(user.source, body, "chat", frm=TransportID) + " Please, follow the link: %s and enter the text shown on the image to the chat." + " Example: !captcha my_captcha_key." + "\nWarning: don't use Firefox to open the link.") % url + msg = xmpp.Message(vk.source, body, "chat", frm=TransportID) + msg.setID(vk.engine.captcha["sid"]) x = msg.setTag("x", namespace=xmpp.NS_OOB) x.setTagData("url", url) captcha = msg.setTag("captcha", namespace=xmpp.NS_CAPTCHA) @@ -21,22 +24,25 @@ def sendCaptcha(user, url): if image: hash = sha1(image).hexdigest() encoded = image.encode("base64") - form = utils.buildDataForm(type="form", fields=[{"var": "FORM_TYPE", "value": xmpp.NS_CAPTCHA, "type": "hidden"}, + form = utils.buildDataForm(type="form", fields=[ + {"var": "FORM_TYPE", "value": xmpp.NS_CAPTCHA, "type": "hidden"}, {"var": "from", "value": TransportID, "type": "hidden"}, + {"var": "challenge", "value": msg.getID(), "type": "hidden"}, {"var": "ocr", "label": _("Enter shown text"), "payload": [xmpp.Node("required"), - xmpp.Node("media", {"xmlns": xmpp.NS_MEDIA}, - [xmpp.Node("uri", {"type": "image/jpg"}, - ["cid:sha1+%s@bob.xmpp.org" % hash] - ) - ]) - ]} - ]) + xmpp.Node("media", {"xmlns": xmpp.NS_MEDIA}, + [xmpp.Node("uri", {"type": "image/jpg"}, + ["cid:sha1+%s@bob.xmpp.org" % hash] + ) + ]) + ]} + ] + ) captcha.addChild(node=form) oob = msg.setTag("data", {"cid": "sha1+%s@bob.xmpp.org" % hash, "type": "image/jpg", "max-age": "0"}, xmpp.NS_URN_OOB) oob.setData(encoded) sender(Component, msg) - sendPresence(user.source, TransportID, show="xa", reason=body, hash=USER_CAPS_HASH) + sendPresence(vk.source, TransportID, show="xa", reason=body, hash=USER_CAPS_HASH) TransportFeatures.update({xmpp.NS_OOB, xmpp.NS_MEDIA, diff --git a/extensions/forwarded_messages.py b/extensions/forwarded_messages.py index efb67d8..43148b6 100644 --- a/extensions/forwarded_messages.py +++ b/extensions/forwarded_messages.py @@ -9,6 +9,7 @@ if not require("attachments"): BASE_SPACER = chr(32) + unichr(183) + chr(32) + def parseForwardedMessages(self, msg, depth=0): body = "" if msg.has_key("fwd_messages"): @@ -17,7 +18,7 @@ def parseForwardedMessages(self, msg, depth=0): body += _("Forwarded messages:") fwd_messages = sorted(msg["fwd_messages"], sortMsg) for fwd in fwd_messages: - source = fwd["user_id"] + source = fwd["uid"] date = fwd["date"] fwdBody = escape("", uhtml(compile_eol.sub("\n" + spacer + BASE_SPACER, fwd["body"]))) date = datetime.fromtimestamp(date).strftime("%d.%m.%Y %H:%M:%S") diff --git a/extensions/groupchats.py b/extensions/groupchats.py index cb680e7..454e935 100644 --- a/extensions/groupchats.py +++ b/extensions/groupchats.py @@ -26,6 +26,9 @@ mod_groupchat_prs for presence handling mod_groupchat_msg for message handling """ +MAX_UPDATE_DELAY = 3600 # 1 hour +CHAT_CLEANUP_DELAY = 86400 # 24 hours + if not require("attachments") or not require("forwarded_messages"): raise AssertionError("extension 'groupchats' requires 'forwarded_messages' and 'attachments'") @@ -94,6 +97,9 @@ def leaveChat(chat, jidFrom, reason=None): def chatMessage(chat, text, jidFrom, subj=None, timestamp=0): + """ + Sends a message to the chat + """ message = xmpp.Message(chat, typ="groupchat") if timestamp: timestamp = time.gmtime(timestamp) @@ -116,8 +122,8 @@ def setChatConfig(chat, jidFrom, exterminate=False, cb=None, args={}): if exterminate: query.addChild("destroy") else: - form = utils.buildDataForm(fields=[{"var": "FORM_TYPE", "type": "hidden", - "value": xmpp.NS_MUC_ROOMCONFIG}, + form = utils.buildDataForm(fields=[ + {"var": "FORM_TYPE", "type": "hidden", "value": xmpp.NS_MUC_ROOMCONFIG}, {"var": "muc#roomconfig_membersonly", "type": "boolean", "value": "1"}, {"var": "muc#roomconfig_publicroom", "type": "boolean", "value": "0"}, {"var": "muc#roomconfig_persistentroom", "type": "boolean", "value": "1"}, @@ -126,44 +132,61 @@ def setChatConfig(chat, jidFrom, exterminate=False, cb=None, args={}): query.addChild(node=form) sender(Component, iq, cb, args) -def handleOutgoingChatMessage(self, vkChat): + +def handleOutgoingChatMessage(user, vkChat): """ Handles outging VK messages and sends them to XMPP """ - if vkChat.has_key("chat_id"): - if not self.settings.groupchats: + if "chat_id" in vkChat: + # check if the groupchats support enabled in user's settings + if not user.settings.groupchats: return None - owner = vkChat.get("admin_id", "1") - chatID = vkChat["chat_id"] - chatJID = "%s_chat#%s@%s" % (self.vk.userID, chatID, ConferenceServer) - if not hasattr(self, "chats"): - self.chats = {} + if not hasattr(user, "chats"): + user.chats = {} - if not self.vk.userID: - logger.warning("groupchats: we didn't receive user id, trying again after 10 seconds (jid: %s)" % self.source) - self.vk.getUserID() - utils.runThread(handleOutgoingChatMessage, (self, vkChat), delay=10) + # TODO: make this happen in the kernel, so we don't need to check it here + if not user.vk.userID: + logger.warning("groupchats: we didn't receive user id, trying again after 10 seconds (jid: %s)", user.source) + user.vk.getUserID() + utils.runThread(handleOutgoingChatMessage, (user, vkChat), delay=10) return None - if chatJID not in self.chats: - chat = self.chats[chatJID] = Chat() - else: - chat = self.chats[chatJID] + owner = vkChat.get("admin_id", "1") + chatID = vkChat["chat_id"] + chatJID = "%s_chat#%s@%s" % (user.vk.userID, chatID, ConferenceServer) + chat = createChat(user, chatJID) if not chat.initialized: - chat.init(owner, chatID, chatJID, vkChat["title"], vkChat["date"], vkChat["chat_active"]) + chat.init(owner, chatID, chatJID, vkChat["title"], vkChat["date"], vkChat["chat_active"].split(",")) if not chat.created: if chat.creation_failed: return None - chat.create(self) # we can add self, vkChat to the create() function to prevent losing or messing up the messages + # we can add user, vkChat to the create() method to prevent losing or messing up the messages + chat.create(user) # read the comments above the handleMessage function if not chat.created: time.sleep(1.5) - chat.handleMessage(self, vkChat) + chat.handleMessage(user, vkChat) return None return "" +def createChat(user, source): + """ + Creates a chat + Args: + user: the User object + source: the chat's jid + """ + if not hasattr(user, "chats"): + user.chats = {} + if source in user.chats: + chat = user.chats[source] + else: + user.chats[source] = chat = Chat() + return chat + + class Chat(object): """ Class used to handle multi-user dialogs @@ -173,27 +196,34 @@ class Chat(object): self.invited = False self.initialized = False self.exists = False - self.owner_nickname = None self.creation_failed = False + self.owner_nickname = None + self.source = None + self.jid = None + self.owner = None + self.subject = None + self.creation_date = None + self.id = 0 + self.last_update = 0 + self.raw_users = {} self.users = {} - def init(self, owner, id, jid, topic, date, users=[]): + def init(self, owner, id, jid, subject, date, users=[]): """ Assigns an id and other needed attributes to the class object - Not obvious attributes: + Args: + owner: owner's id (str) id: chat's id (int) jid: chat's jid (str) - owner: owner's id (str) + subject: chat's subject + date: the chat creation date users: dictionary of ids, id: {"name": nickname, "jid": jid} - raw_users: vk id's (list of str or int, hell knows) - topic: chat's topic - creation_date: hell knows """ self.id = id self.jid = jid self.owner = owner self.raw_users = users - self.topic = topic + self.subject = subject self.creation_date = date self.initialized = True @@ -201,22 +231,22 @@ class Chat(object): """ Creates a chat, joins it and sets the config """ - logger.debug("groupchats: creating %s. Users: %s; owner: %s (jid: %s)" % - (self.jid, self.raw_users, self.owner, user.source)) + logger.debug("groupchats: creating %s. Users: %s; owner: %s (jid: %s)", + self.jid, self.raw_users, self.owner, user.source) exists = runDatabaseQuery("select user from groupchats where jid=?", (self.jid,), many=True) if exists: self.exists = True - logger.debug("groupchats: groupchat %s exists in the database (jid: %s)" % - (self.jid, user.source)) + logger.debug("groupchats: groupchat %s exists in the database (jid: %s)", + self.jid, user.source) else: - logger.debug("groupchats: groupchat %s will be added to the database (jid: %s)" % - (self.jid, user.source)) + logger.debug("groupchats: groupchat %s will be added to the database (jid: %s)", + self.jid, user.source) runDatabaseQuery("insert into groupchats (jid, owner, user, last_used) values (?,?,?,?)", (self.jid, TransportID, user.source, time.time()), True) name = user.vk.getUserData(self.owner)["name"] self.users[TransportID] = {"name": name, "jid": TransportID} - # We join to the chat with the room owner's name to set the room topic from their name. + # We join to the chat with the room owner's name to set the room subject from their name. joinChat(self.jid, name, TransportID, "Lost in time.") setChatConfig(self.jid, TransportID, False, self.onConfigSet, {"user": user}) @@ -226,15 +256,15 @@ class Chat(object): 1) requests users list if required 2) makes them members 3) invites the user - 4) sets the chat topic + 4) sets the chat subject Parameters: chat: chat's jid """ if not self.raw_users: - vkChat = self.getVKChat(user, self.id) + vkChat = self.getVKChat(user, self.id) # getting the chat users if not vkChat and not self.invited: - logger.error("groupchats: damn vk didn't answer to the chat list"\ - "request, starting timer to try again (jid: %s)" % user.source) + logger.error("groupchats: damn vk didn't answer to the chat list " + "request, starting timer to try again (jid: %s)", user.source) utils.runThread(self.initialize, (user, chat), delay=10) return False self.raw_users = vkChat.get("users") @@ -243,18 +273,18 @@ class Chat(object): setAffiliation(chat, "member", user.source) if not self.invited: inviteUser(chat, user.source, TransportID, user.vk.getUserData(self.owner)["name"]) - logger.debug("groupchats: user has been invited to chat %s (jid: %s)" % (chat, user.source)) + logger.debug("groupchats: user has been invited to chat %s (jid: %s)", chat, user.source) self.invited = True - chatMessage(chat, self.topic, TransportID, True, self.creation_date) + self.setSubject(self.subject, self.creation_date) joinChat(chat, name, TransportID, "Lost in time.") # let's rename ourselves self.users[TransportID] = {"name": name, "jid": TransportID} def update(self, userObject, vkChat): """ Updates chat users and sends messages - Uses two users list to prevent losing anyone + Uses two user lists to prevent losing of any of them """ - all_users = vkChat["chat_active"] + all_users = vkChat["chat_active"].split(",") all_users = [int(user) for user in all_users if user] if userObject.settings.show_all_chat_users: users = self.getVKChat(userObject, self.id) @@ -283,12 +313,19 @@ class Chat(object): leaveChat(self.jid, jid) del self.users[user] - topic = vkChat["title"] - if topic and topic != self.topic: - chatMessage(self.jid, topic, TransportID, True) - self.topic = topic + subject = vkChat["title"] + if subject and subject != self.subject: + self.setSubject(subject) self.raw_users = all_users + + def setSubject(self, subject, date=None): + """ + Changes the chat subject + """ + chatMessage(self.jid, subject, TransportID, True, date) + self.subject = subject + def onConfigSet(self, cl, stanza, user): """ A callback which called after attempt to create the chat @@ -296,7 +333,7 @@ class Chat(object): chat = stanza.getFrom().getStripped() if xmpp.isResultNode(stanza): self.created = True - logger.debug("groupchats: stanza \"result\" received from %s,"\ + logger.debug("groupchats: stanza \"result\" received from %s, " "continuing initialization (jid: %s)", chat, user.source) utils.execute(self.initialize, (user, chat)) else: @@ -304,7 +341,7 @@ class Chat(object): chat, str(stanza), user.source) self.creation_failed = True - # here is a possibility to get messed up if many messages were sent before we created the chat + # there's a possibility to mess up here if many messages were sent before we created the chat # we have to send the messages immendiately as soon as possible, so delay can mess the messages up def handleMessage(self, user, vkChat, retry=True): """ @@ -316,21 +353,33 @@ class Chat(object): body += parseAttachments(user, vkChat) body += parseForwardedMessages(user, vkChat) if body: - date = 0 - if user.settings.force_vk_date_group: - date = vkChat["date"] - chatMessage(self.jid, body, vk2xmpp(vkChat["user_id"]), None, date) + chatMessage(self.jid, body, vk2xmpp(vkChat["uid"]), None) else: source = "unknown" userObject = self.getUserObject(self.jid) if userObject: source = userObject.source + # todo: FULL leave on error and try to create the chat again logger.warning("groupchats: chat %s wasn't created well, so trying to create it again (jid: %s)", self.jid, source) logger.warning("groupchats: is there any groupchat limit on the server?") if retry: # TODO: We repeat it twice on each message. We shouldn't. self.handleMessage(user, vkChat, False) + def isUpdateRequired(self): + """ + Tells whether it's required to update the chat's last_used time + Returns: + True if required + """ + if not self.source: + return False + if not self.last_update: + return True + if (time.time() - self.last_update) > MAX_UPDATE_DELAY: + return True + return False + @api.attemptTo(3, dict, RuntimeError) def getVKChat(cls, user, id): """ @@ -367,24 +416,25 @@ class Chat(object): jid = runDatabaseQuery("select user from groupchats where jid=?", (source,), many=False) if jid: jid = jid[0] - if jid and jid in Transport: - user = Transport[jid] + if jid and jid in Users: + user = Users[jid] return user @staticmethod def getJIDByID(id): - for key, value in Transport.iteritems(): + for key, value in Users.iteritems(): if key == id: return value return None -def createFakeChat(user, source): - if not hasattr(user, "chats"): - user.chats = {} - if source not in user.chats: - user.chats[source] = chat = Chat() - chat.invited = True # the user has joined themselves and we don't need to intvite them +def updateLastUsed(chat): + """ + Updates the last_used field in the database + Args: + chat: the Chat object + """ + runDatabaseQuery("update groupchats set last_used=? where jid=?", (time.time(), chat.source), set=True) def exterminateChats(user=None, chats=[]): @@ -393,33 +443,40 @@ def exterminateChats(user=None, chats=[]): The chats argument must be a list of tuples """ def exterminated(cl, stanza, jid): + """ + The callback that's being called when the stanza we sent's got an answer + Args: + cl: the xmpp.Client object + stanza: the result stanza + jid: the jid stanza's sent from (?) + """ chat = stanza.getFrom().getStripped() if xmpp.isResultNode(stanza): - logger.debug("groupchats: target exterminated! Yay! target:%s (jid: %s)" % (chat, jid)) + logger.debug("groupchats: target exterminated! Yay! target:%s (jid: %s)", chat, jid) else: logger.debug("groupchats: explain! Explain! " - "The chat wasn't exterminated! Target: %s (jid: %s)" % (chat, jid)) - logger.error("groupchats: got stanza: %s (jid: %s)" % (str(stanza), jid)) + "The chat wasn't exterminated! Target: %s (jid: %s)", chat, jid) + logger.error("groupchats: got stanza: %s (jid: %s)", str(stanza), jid) - if user: + if user and not chats: chats = runDatabaseQuery("select jid, owner, user from groupchats where user=?", (user.source,)) - source = user.source - userChats = getattr(user, "chats", {}) - else: - userChats = [] + # current chats + userChats = getattr(user, "chats", []) for (jid, owner, source) in chats: - _owner = owner + server = owner if "@" in owner: - _owner = owner.split("@")[1] - if _owner != TransportID: - logger.warning("Warning: Was the transport moved from other domain? Groupchat %s deletion skipped.", jid) - else: + server = owner.split("@")[1] + if server == TransportID: joinChat(jid, "Dalek", owner, "Exterminate!") - logger.debug("groupchats: going to exterminate %s, owner:%s (jid: %s)" % (jid, owner, source)) + logger.debug("groupchats: going to exterminate %s, owner:%s (jid: %s)", jid, owner, source) setChatConfig(jid, owner, True, exterminated, {"jid": jid}) + # remove the chat from current if jid in userChats: del userChats[jid] + else: + # if we try to send from another jid with prosody, we'll be killed + logger.warning("Warning: Was the transport moved from other domain? Groupchat %s deletion skipped.", jid) runDatabaseQuery("delete from groupchats where jid=?", (jid,), set=True) @@ -453,10 +510,10 @@ def cleanTheChatsUp(): for (jid, owner, last_used, user) in chats: if (time.time() - last_used) >= utils.TimeMachine(CHAT_LIFETIME_LIMIT): result.append((jid, owner, user)) - logger.debug("groupchats: time for %s expired (jid: %s)" % (jid, user)) + logger.debug("groupchats: time for %s expired (jid: %s)", jid, user) if result: exterminateChats(chats=result) - utils.runThread(cleanTheChatsUp, delay=(60*60*24)) + utils.runThread(cleanTheChatsUp, delay=CHAT_CLEANUP_DELAY) def initChatExtension(): @@ -479,23 +536,15 @@ if isdef("ConferenceServer") and ConferenceServer: # G is for Groupchats. That's it. Handlers["msg03g"] = [] - GLOBAL_USER_SETTINGS["groupchats"] = {"label": "Handle groupchats", + GLOBAL_USER_SETTINGS["groupchats"] = {"label": "Handle groupchats", "desc": "If set, transport would create xmpp-chatrooms for VK Multi-Dialogs", "value": 1} GLOBAL_USER_SETTINGS["show_all_chat_users"] = {"label": "Show all chat users", "desc": "If set, transport will show ALL users in a conference", "value": 0} - GLOBAL_USER_SETTINGS["tie_chat_to_nickname"] = {"label": "Tie chat to my nickname (tip: enable timestamp for groupchats)", - "desc": "If set, your messages will be sent only from your nickname\n"\ - "(there is no way to determine whether message was sent\nfrom you or from the transport, so this setting might help,\nbut"\ - " there's one problem comes up: you wouldn't be able to send messages until the chat is initialized). " - "\nChat initializes when first message received after transport's boot", "value": 1} - - GLOBAL_USER_SETTINGS["force_vk_date_group"] = {"label": "Force VK timestamp for groupchat messages", "value": 1} - TRANSPORT_SETTINGS["destroy_on_leave"] = {"label": "Destroy groupchat if user leaves it", "value": 0} - TransportFeatures.add(xmpp.NS_MUC) + TransportFeatures.add(xmpp.NS_GROUPCHAT) registerHandler("msg01", handleOutgoingChatMessage) registerHandler("evt01", initChatExtension) registerHandler("evt03", exterminateChats) diff --git a/extensions/interpreter.py b/extensions/interpreter.py index e8e899a..1c20fd9 100644 --- a/extensions/interpreter.py +++ b/extensions/interpreter.py @@ -13,8 +13,8 @@ def interpreter_msg02(msg): if len(raw) > 1: text, args = raw args = args.strip() - if source in Transport: - user = Transport[source] + if source in Users: + user = Users[source] if text == "!eval" and args and source in ADMIN_JIDS: try: result = unicode(eval(args)) diff --git a/extensions/status-from-vk.py b/extensions/status-from-vk.py index 54ad4c7..6ad2f0f 100644 --- a/extensions/status-from-vk.py +++ b/extensions/status-from-vk.py @@ -15,8 +15,8 @@ def statusfromvk_evt07(user): def statusfromvk_prs02(prs, destination, source): - if source != TransportID and destination in Transport: - user = Transport[destination] + if source != TransportID and destination in Users: + user = Users[destination] if user.settings.status_from_vk and not prs.getType(): id = vk2xmpp(source) if id in user.friends and user.friends[id].get("status"): diff --git a/extensions/status-to-vk.py b/extensions/status-to-vk.py index d9743f4..a66b594 100644 --- a/extensions/status-to-vk.py +++ b/extensions/status-to-vk.py @@ -11,9 +11,9 @@ VK_ACCESS += 1024 GLOBAL_USER_SETTINGS["status_to_vk"] = {"label": "Publish my status in VK", "value": 0} def statustovk_prs01(source, prs, retry=3): - if source in Transport and prs.getType() in ("available", None): + if source in Users and prs.getType() in ("available", None): if prs.getTo() == TransportID: - user = Transport[source] + user = Users[source] if user.settings.status_to_vk: mask = user.vk.method("account.getAppPermissions") or 0 if mask: diff --git a/extensions/sticker.py b/extensions/sticker.py index 442874e..c4f58b4 100644 --- a/extensions/sticker.py +++ b/extensions/sticker.py @@ -40,7 +40,7 @@ def sendSticker(msg, destination, source): if msg.getType() == "groupchat": user = Chat.getUserObject(destination) else: - user = Transport.get(destination) + user = Users.get(destination) if user and user.settings.send_stickers: url = sticker_url.search(body) if url: diff --git a/extensions/typing_reader.py b/extensions/typing_reader.py index 626cf7f..7dafff0 100644 --- a/extensions/typing_reader.py +++ b/extensions/typing_reader.py @@ -7,8 +7,8 @@ GLOBAL_USER_SETTINGS["typingreader"] = {"label": "Mark my messages as read when def typingreader_watch(msg): jidFrom = msg.getFrom() source = jidFrom.getStripped() - if msg.getType() == "chat" and source in Transport: - user = Transport[source] + if msg.getType() == "chat" and source in Users: + user = Users[source] if user.settings.typingreader: if (user.lastMsgID > user.lastMarkedMessage) and msg.getTag("composing"): user.vk.method("messages.markAsRead", {"message_ids": str(user.lastMsgID)}) diff --git a/extensions/user_activity.py b/extensions/user_activity.py index 12c372d..22823b6 100644 --- a/extensions/user_activity.py +++ b/extensions/user_activity.py @@ -39,7 +39,7 @@ def user_activity_remove(): LA = utils.TimeMachine(USER_LIFETIME_LIMIT) for (jid, date) in users: if (time.time() - date) >= LA: - if jid not in Transport: + if jid not in Users: runDatabaseQuery("delete from users where jid=?", (jid,), set=True) runDatabaseQuery("delete from last_activity where jid=?", (jid,)) settings = "%s/%s" % (settingsDir, jid) @@ -54,12 +54,13 @@ def user_activity_remove(): " Relogin or you'll be exterminated.") % LA, LA) utils.runThread(user_activity_remove, delay=(60*60*24)) + # A dirty hack to add seen users in stats def calcStats(): """ Returns count(*) from users database """ - countOnline = len(Transport) + countOnline = len(Users) countTotal = runDatabaseQuery("select count(*) from users", many=False)[0] countSeen = runDatabaseQuery("select count(*) from last_activity where date >=?", (startTime,), many=False)[0] return [countTotal, countSeen, countOnline] diff --git a/extensions/user_nickname.py b/extensions/user_nickname.py index 5b18cfb..e13a43b 100644 --- a/extensions/user_nickname.py +++ b/extensions/user_nickname.py @@ -23,8 +23,8 @@ def add_username(stanza, user, uid): def add_nickname_msg03(msg, destination, source): - if destination in Transport and source != TransportID: # That would be strange if user wasn't in Transport - user = Transport[destination] + if destination in Users and source != TransportID: # That would be strange if user wasn't in Transport + user = Users[destination] if user.settings.add_nicknames_msg: uid = vk2xmpp(source) strangers = getattr(user, "strangers", set([])) @@ -35,8 +35,8 @@ def add_nickname_msg03(msg, destination, source): def add_nickname_prs02(prs, destination, source): - if destination in Transport and not prs.getType(): - user = Transport[destination] + if destination in Users and not prs.getType(): + user = Users[destination] uid = vk2xmpp(source) if uid in user.friends and user.settings.add_nicknames_prs: add_username(prs, user, uid) |