diff options
author | John Smith <mrdoctorwho@gmail.com> | 2017-03-14 16:17:04 +0300 |
---|---|---|
committer | John Smith <mrdoctorwho@gmail.com> | 2017-03-14 16:17:04 +0300 |
commit | 26a9ce51183269acacbf4cdb7cf91d06682985ab (patch) | |
tree | 67304b96f7335392b9fe35582f5e1f6eae294d63 | |
parent | f6bf2b50a9391b685b9e59d4996ba72565923a6e (diff) |
Make the gateway work for communitiesgroups
-rw-r--r-- | extensions/attachments.py | 6 | ||||
-rw-r--r-- | extensions/forwarded_messages.py | 2 | ||||
-rw-r--r-- | extensions/groupchats.py | 556 | ||||
-rw-r--r-- | extensions/interpreter.py | 5 | ||||
-rw-r--r-- | extensions/subscribe_on_message.py | 17 | ||||
-rw-r--r-- | extensions/user_nickname.py | 2 | ||||
-rw-r--r-- | gateway.py | 28 | ||||
-rw-r--r-- | library/forms.py | 4 | ||||
-rw-r--r-- | modules/mod_groupchat_msg.py | 65 | ||||
-rw-r--r-- | modules/mod_groupchat_prs.py | 111 | ||||
-rw-r--r-- | modules/mod_iq_register.py | 3 |
11 files changed, 39 insertions, 760 deletions
diff --git a/extensions/attachments.py b/extensions/attachments.py index 16400de..f925e1e 100644 --- a/extensions/attachments.py +++ b/extensions/attachments.py @@ -47,9 +47,9 @@ def parseAttachments(self, msg, spacer=""): if self.settings.parse_wall: tid = current.get("to_id", 1) if tid > 0: - name = "%s's" % self.vk.getUserData(tid)["name"] + name = "%s's" % self.vk.getUserData(tid, notoken=True)["name"] else: - name = "“%s”" % self.vk.getGroupData(tid)["name"] + name = "“%s”" % self.vk.getGroupData(tid, notoken=True)["name"] body += "Post on %s wall:\n" % name 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" @@ -79,7 +79,7 @@ def parseAttachments(self, msg, spacer=""): elif type == "wall_reply": # 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["name"] = self.vk.getUserData(current["uid"], notoken=True)["name"] current["text"] = uhtml(compile_eol.sub("\n" + spacer, current["text"])) current["url"] = WALL_COMMENT_LINK % current diff --git a/extensions/forwarded_messages.py b/extensions/forwarded_messages.py index 43148b6..24c3fa8 100644 --- a/extensions/forwarded_messages.py +++ b/extensions/forwarded_messages.py @@ -22,7 +22,7 @@ def parseForwardedMessages(self, msg, depth=0): 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") - name = self.vk.getUserData(source)["name"] + name = self.vk.getUserData(source, notoken=True)["name"] body += "\n%s[%s] <%s> %s" % (spacer + BASE_SPACER, date, name, fwdBody) body += parseAttachments(self, fwd, spacer + (BASE_SPACER * 2)) if depth < MAXIMUM_FORWARD_DEPTH: diff --git a/extensions/groupchats.py b/extensions/groupchats.py deleted file mode 100644 index 454e935..0000000 --- a/extensions/groupchats.py +++ /dev/null @@ -1,556 +0,0 @@ -# coding: utf-8 -# This file is a part of VK4XMPP transport -# © simpleApps, 2013 — 2015. -# File contains parts of code from -# BlackSmith mark.1 XMPP Bot, © simpleApps 2011 — 2014. - -# Installation: -# The extension requires up to 2 fields in the main config: -# 1. ConferenceServer - the address of your (or not yours?) conference server -# Bear in mind that there can be limits on the jabber server for conference per jid. Read the wiki for more details. -# 2. CHAT_LIFETIME_LIMIT - the limit of the time after that user considered inactive and will be removed. -# Time must be formatted as text and contain the time variable measurement. -# For example: CHAT_LIFETIME_LIMIT = "28y09M21d" means chat will be removed after 28 years 9 Months 21 days from now -# You can wheter ignore or use any of these chars: smdMy. -# Used chars: s for seconds, m for minutes, d for days, M for months, y for years. The number MUST contain 2 digits as well. -# Note: if you won't set the field, plugin won't remove any chat, but still will be gathering statistics. - - -""" -Handles VK Multi-Dialogs -Implements XEP-0045: Multi-User Chat (over an exsisting chat) -Note: This file contains only outgoing-specific stuff (vk->xmpp) -along with the Chat class and other useful functions -The code which handles incoming stuff (xmpp->vk) is placed in the following modules: -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'") - - -def setAffiliation(chat, afl, jid, jidFrom=TransportID, reason=None): - """ - Set user affiliation in a chat. - Parameters: - * chat - the chat to set affiliation in - * afl - the affiliation to set to - * jid - the user's jid whose affiliation needs to be changed - * jidFrom - the chat's owner jid (or anyone who can set users roles) - * reason - special reason - """ - stanza = xmpp.Iq("set", to=chat, frm=jidFrom) - query = xmpp.Node("query", {"xmlns": xmpp.NS_MUC_ADMIN}) - arole = query.addChild("item", {"jid": jid, "affiliation": afl}) - if reason: - arole.setTagData("reason", reason) - stanza.addChild(node=query) - sender(Component, stanza) - - -def inviteUser(chat, jidTo, jidFrom, name): - """ - Invite user to a chat. - Parameters: - * chat - the chat to invite to - * jidTo - the user's jid who needs to be invited - * jidFrom - the inviter's jid - * name - the inviter's name - """ - invite = xmpp.Message(to=chat, frm=jidFrom) - x = xmpp.Node("x", {"xmlns": xmpp.NS_MUC_USER}) - inv = x.addChild("invite", {"to": jidTo}) - inv.setTagData("reason", _("You're invited by user «%s»") % name) - invite.addChild(node=x) - sender(Component, invite) - - -def joinChat(chat, name, jidFrom, status=None): - """ - Join a chat. - Parameters: - * chat - the chat to join in - * name - nickname - * jidFrom - jid which will be displayed when joined - * status - special status - """ - prs = xmpp.Presence("%s/%s" % (chat, name), frm=jidFrom, status=status) - prs.setTag("c", {"node": TRANSPORT_CAPS_HASH, "ver": hash, "hash": "sha-1"}, - xmpp.NS_CAPS) - sender(Component, prs) - - -def leaveChat(chat, jidFrom, reason=None): - """ - Leave chat. - Parameters: - * chat - chat to leave from - * jidFrom - jid to leave with - * reason - special reason - """ - prs = xmpp.Presence(chat, "unavailable", frm=jidFrom, status=reason) - sender(Component, prs) - - -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) - message.setTimestamp(time.strftime("%Y%m%dT%H:%M:%S", timestamp)) - if not subj: - message.setBody(text) - else: - message.setSubject(text) - message.setFrom(jidFrom) - executeHandlers("msg03g", (message, chat, jidFrom)) - sender(Component, message) - - -def setChatConfig(chat, jidFrom, exterminate=False, cb=None, args={}): - """ - Sets the chat config - """ - iq = xmpp.Iq("set", to=chat, frm=jidFrom) - query = iq.addChild("query", namespace=xmpp.NS_MUC_OWNER) - if exterminate: - query.addChild("destroy") - else: - 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"}, - {"var": "muc#roomconfig_whois", "value": "anyone"}], - type="submit") - query.addChild(node=form) - sender(Component, iq, cb, args) - - -def handleOutgoingChatMessage(user, vkChat): - """ - Handles outging VK messages and sends them to XMPP - """ - if "chat_id" in vkChat: - # check if the groupchats support enabled in user's settings - if not user.settings.groupchats: - return None - - if not hasattr(user, "chats"): - user.chats = {} - - # 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 - - 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"].split(",")) - if not chat.created: - if chat.creation_failed: - return None - # 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(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 - """ - def __init__(self): - self.created = False - self.invited = False - self.initialized = False - self.exists = False - 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, subject, date, users=[]): - """ - Assigns an id and other needed attributes to the class object - Args: - owner: owner's id (str) - id: chat's id (int) - jid: chat's jid (str) - subject: chat's subject - date: the chat creation date - users: dictionary of ids, id: {"name": nickname, "jid": jid} - """ - self.id = id - self.jid = jid - self.owner = owner - self.raw_users = users - self.subject = subject - self.creation_date = date - self.initialized = True - - def create(self, user): - """ - 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) - 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) - else: - 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 subject from their name. - joinChat(self.jid, name, TransportID, "Lost in time.") - setChatConfig(self.jid, TransportID, False, self.onConfigSet, {"user": user}) - - def initialize(self, user, chat): - """ - Initializes chat object: - 1) requests users list if required - 2) makes them members - 3) invites the user - 4) sets the chat subject - Parameters: - chat: chat's jid - """ - if not self.raw_users: - 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) - utils.runThread(self.initialize, (user, chat), delay=10) - return False - self.raw_users = vkChat.get("users") - - name = "@%s" % TransportID - 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) - self.invited = True - 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 user lists to prevent losing of any of them - """ - 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) - if users: - all_users = users.get("users", []) - old_users = self.users.keys() - buddies = all_users + old_users - if TransportID in buddies: - buddies.remove(TransportID) - if userObject.vk.getUserID() in buddies: - buddies.remove(userObject.vk.getUserID()) - - for user in buddies: - jid = vk2xmpp(user) - if user not in old_users: - logger.debug("groupchats: user %s has joined the chat %s (jid: %s)", - user, self.jid, userObject.source) - name = userObject.vk.getUserData(user)["name"] - self.users[int(user)] = {"name": name, "jid": jid} - setAffiliation(self.jid, "member", jid) - joinChat(self.jid, name, jid) - - elif user not in all_users: - logger.debug("groupchats: user %s has left the chat %s (jid: %s)", - user, self.jid, userObject.source) - leaveChat(self.jid, jid) - del self.users[user] - - 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 - """ - chat = stanza.getFrom().getStripped() - if xmpp.isResultNode(stanza): - self.created = True - logger.debug("groupchats: stanza \"result\" received from %s, " - "continuing initialization (jid: %s)", chat, user.source) - utils.execute(self.initialize, (user, chat)) - else: - logger.error("groupchats: couldn't set room %s config, the answer is: %s (jid: %s)", - chat, str(stanza), user.source) - self.creation_failed = True - - # 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): - """ - Handle incoming (VK -> XMPP) messages - """ - if self.created: - self.update(user, vkChat) - body = escape("", uhtml(vkChat["body"])) - body += parseAttachments(user, vkChat) - body += parseForwardedMessages(user, vkChat) - if body: - 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): - """ - Get vk chat by id - """ - chat = user.vk.method("messages.getChat", {"chat_id": id}) - if not chat: - raise RuntimeError("Unable to get a chat!") - return chat - - @classmethod - def getParts(cls, source): - """ - Split the source and return required parts - """ - node, domain = source.split("@") - if "_chat#" in node: - creator, id = node.split("_chat#") - else: - return (None, None, None) - return (int(creator), int(id), domain) - - @classmethod - def getUserObject(cls, source): - """ - Gets user object by chat jid - """ - user = None - jid = None - creator, id, domain = cls.getParts(source) - if domain == ConferenceServer and creator: - jid = cls.getJIDByID(id) - if not jid: - jid = runDatabaseQuery("select user from groupchats where jid=?", (source,), many=False) - if jid: - jid = jid[0] - if jid and jid in Users: - user = Users[jid] - return user - - @staticmethod - def getJIDByID(id): - for key, value in Users.iteritems(): - if key == id: - return value - return None - - -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=[]): - """ - Calls a Dalek for exterminate the chat - 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) - 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) - - if user and not chats: - chats = runDatabaseQuery("select jid, owner, user from groupchats where user=?", (user.source,)) - - # current chats - userChats = getattr(user, "chats", []) - for (jid, owner, source) in chats: - server = owner - if "@" in owner: - 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) - 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) - - -def initChatsTable(): - """ - Initializes database if it doesn't exist - """ - def checkColumns(): - """ - Checks and adds additional column(s) into the groupchats table - """ - info = runDatabaseQuery("pragma table_info(groupchats)") - names = [col[1] for col in info] - if "nick" not in names: - logger.warning("groupchats: adding \"nick\" column to groupchats table") - runDatabaseQuery("alter table groupchats add column nick text", set=True) - - runDatabaseQuery("create table if not exists groupchats " - "(jid text, owner text," - "user text, last_used integer, nick text)", set=True) - checkColumns() - return True - - -def cleanTheChatsUp(): - """ - Calls Dalek(s) to exterminate inactive users or their chats, whatever they catch - """ - chats = runDatabaseQuery("select jid, owner, last_used, user from groupchats") - result = [] - 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) - if result: - exterminateChats(chats=result) - utils.runThread(cleanTheChatsUp, delay=CHAT_CLEANUP_DELAY) - - -def initChatExtension(): - """ - Initializes the extension" - """ - global mod_xhtml - try: - import mod_xhtml - except ImportError: - mod_xhtml = None - if initChatsTable(): - if isdef("CHAT_LIFETIME_LIMIT"): - cleanTheChatsUp() - else: - logger.warning("not starting chats cleaner because CHAT_LIFETIME_LIMIT is not set") - - -if isdef("ConferenceServer") and ConferenceServer: - # G is for Groupchats. That's it. - Handlers["msg03g"] = [] - - 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} - - TRANSPORT_SETTINGS["destroy_on_leave"] = {"label": "Destroy groupchat if user leaves it", "value": 0} - - TransportFeatures.add(xmpp.NS_GROUPCHAT) - registerHandler("msg01", handleOutgoingChatMessage) - registerHandler("evt01", initChatExtension) - registerHandler("evt03", exterminateChats) - logger.info("extension groupchats is loaded") - -else: - del setAffiliation, inviteUser, joinChat, leaveChat, \ - handleOutgoingChatMessage, chatMessage, Chat, \ - exterminateChats, cleanTheChatsUp, initChatExtension diff --git a/extensions/interpreter.py b/extensions/interpreter.py index 1c20fd9..0ce5694 100644 --- a/extensions/interpreter.py +++ b/extensions/interpreter.py @@ -2,6 +2,7 @@ # This file is a part of VK4XMPP transport # © simpleApps, 2015. +import traceback def interpreter_msg02(msg): body = msg.getBody() @@ -19,14 +20,14 @@ def interpreter_msg02(msg): try: result = unicode(eval(args)) except Exception: - result = returnExc() + result = traceback.format_exc() sendMessage(source, destination, result) elif text == "!exec" and args and source in ADMIN_JIDS: try: exec (unicode(args + "\n"), globals()) except Exception: - result = returnExc() + result = traceback.format_exc() else: result = "Done." sendMessage(source, destination, result) diff --git a/extensions/subscribe_on_message.py b/extensions/subscribe_on_message.py new file mode 100644 index 0000000..62b1073 --- /dev/null +++ b/extensions/subscribe_on_message.py @@ -0,0 +1,17 @@ +# coding: utf-8 +# This file is a part of VK4XMPP transport +# © simpleApps, 2017. + + +known_sources = [] # TODO: database + +def subscribe_msg03(msg, destination, source): + if source not in known_sources and destination in Users: + user = Users[destination] + id = vk2xmpp(source) + data = user.vk.getUserData(id, notoken=True) + dict = {id: {"name":data.get("name", "Anonymous User")}} + user.sendSubPresence(dict) + known_sources.append(source) + +registerHandler("msg03", subscribe_msg03)
\ No newline at end of file diff --git a/extensions/user_nickname.py b/extensions/user_nickname.py index e13a43b..308606b 100644 --- a/extensions/user_nickname.py +++ b/extensions/user_nickname.py @@ -15,7 +15,7 @@ def add_username(stanza, user, uid): key = "name" if user.settings.use_nicknames: key = "screen_name" - name = user.vk.getUserData(uid)[key] + name = user.vk.getUserData(uid, notoken=True)[key] else: name = IDENTIFIER["name"] stanza.setTag("nick", namespace=xmpp.NS_NICK) @@ -286,8 +286,6 @@ class VK(object): """ logger.debug("VK going to authenticate (jid: %s)", self.source) self.engine = api.APIBinding(self.token, DEBUG_API, self.source) - if not self.checkToken(): - raise api.TokenError("The token is invalid (jid: %s, token: %s)" % (self.source, self.token)) self.online = True return True @@ -370,14 +368,15 @@ class VK(object): roster = False m = e.message # TODO: Make new exceptions for each of the conditions below - if m == "User authorization failed: user revoke access for this token.": + if m.endswith("user revoke access for this token."): roster = True - elif m == "User authorization failed: invalid access_token.": + elif m.endswith("invalid access_token."): sendMessage(self.source, TransportID, - m + " Please, register again") - utils.runThread(removeUser, (self.source, roster)) + m11 + " Please, register again") + # don't do this for now +# utils.runThread(removeUser, (self.source, roster)) +# self.online = False logger.error("VK: apiError %s (jid: %s)", m, self.source) - self.online = False else: return result logger.error("VK: error %s occurred while executing" @@ -393,7 +392,6 @@ class VK(object): self.online = False logger.debug("VK: user %s has left", self.source) executeHandlers("evt06", (self,)) - self.setOffline() def setOffline(self): """ @@ -491,7 +489,7 @@ class VK(object): return self.permissions @utils.cache - def getGroupData(self, gid, fields=None): + def getGroupData(self, gid, fields=None, **kwargs): """ Gets group data (only name so far) Args: @@ -501,13 +499,12 @@ class VK(object): The group information """ fields = fields or ["name"] - data = self.method("groups.getById", {"group_id": abs(gid), "fields": str.join(",", fields)}) + data = self.method("groups.getById", {"group_id": abs(gid), "fields": str.join(",", fields)}, **kwargs) if data: data = data[0] return data - @utils.cache - def getUserData(self, uid, fields=None): + def getUserData(self, uid, fields=None, **kwargs): """ Gets user data. Such as name, photo, etc Args: @@ -521,7 +518,7 @@ class VK(object): if user and uid in user.friends: return user.friends[uid] fields = ["screen_name"] - data = self.method("users.get", {"user_ids": uid, "fields": str.join(",", fields)}) + data = self.method("users.get", {"user_ids": uid, "fields": str.join(",", fields)}, **kwargs) if data: data = data[0] data["name"] = self.formatName(data) @@ -768,10 +765,6 @@ class User(object): Takes a corresponding action if any difference found """ if (cTime - self.last_udate) > 300 and not self.vk.engine.captcha: - if self.settings.keep_online: - self.vk.setOnline() - else: - self.vk.setOffline() self.last_udate = cTime friends = self.vk.getFriends() if not friends: @@ -905,7 +898,6 @@ def updateCron(): for user in Users.values(): cTime = time.time() user.updateTypingUsers(cTime) - user.updateFriends(cTime) time.sleep(2) def calcStats(): diff --git a/library/forms.py b/library/forms.py index 2791969..049b9a6 100644 --- a/library/forms.py +++ b/library/forms.py @@ -9,8 +9,8 @@ class Forms: @classmethod def getSimpleForm(cls): form = [] - form.append({"var": "link", "type": "text-single", - "label": _("Autorization page"), "value": URL_ACCEPT_APP}) + # form.append({"var": "link", "type": "text-single", + # "label": _("Autorization page"), "value": URL_ACCEPT_APP}) form.append({"var": "password", "type": "text-private", "label": _("Access-token"), "desc": _("Enter the access token")}) diff --git a/modules/mod_groupchat_msg.py b/modules/mod_groupchat_msg.py deleted file mode 100644 index 0257b97..0000000 --- a/modules/mod_groupchat_msg.py +++ /dev/null @@ -1,65 +0,0 @@ -# coding: utf-8 -# This file is a part of VK4XMPP transport -# © simpleApps, 2013 — 2015. - -""" -Module purpose is to handle messages from groupchats -""" - -from __main__ import * - - -def incoming_message_handler(cl, msg): - """ - Handles incoming (xmpp) messages and sends them to VK - """ - if msg.getType() == "groupchat": - body = msg.getBody() - destination = msg.getTo().getStripped() - nick = msg.getFrom().getResource() - source = msg.getFrom().getStripped() - if mod_xhtml: - html = msg.getTag("html") - else: - html = None - - x = msg.getTag("x", {"xmlns": xmpp.NS_MUC_USER}) - if x and x.getTagAttr("status", "code") == "100": - raise xmpp.NodeProcessed() - - if not msg.getTimestamp() and body and destination == TransportID: - user = Chat.getUserObject(source) - creator, id, domain = Chat.getParts(source) - owner_nickname = None - if user: - if source in getattr(user, "chats", {}): - owner_nickname = user.chats[source].owner_nickname - if not owner_nickname: - owner_nickname = runDatabaseQuery("select nick from groupchats where jid=?", - (source,), many=False)[0] - # None of “normal” clients will send messages with timestamp - # If we do (as we set in force_vk_date_group), then the message received from a user - # If we don't and nick (as in settings) is tied to the chat, then we can determine who sent the message - send = (nick == owner_nickname) - chat = createChat(user, source) - chat.invited = True # the user has joined themselves, so we don't need to invite them - if html and html.getTag("body"): - logger.debug("groupchats: fetched xhtml image (jid: %s)" % source) - try: - mod_xhtml.parseXHTML(user, html, source, source, "chat_id") - except Exception: - pass - else: - # Don't send a message if there's an image - raise xmpp.NodeProcessed() - if send: - with user.sync: - user.vk.sendMessage(body, id, "chat_id") - if chat.isUpdateRequired(): - updateLastUsed(chat) - raise xmpp.NodeProcessed() - - -MOD_TYPE = "message" -MOD_HANDLERS = ((incoming_message_handler, "", "", False),) -MOD_FEATURES = [] diff --git a/modules/mod_groupchat_prs.py b/modules/mod_groupchat_prs.py deleted file mode 100644 index 88486b6..0000000 --- a/modules/mod_groupchat_prs.py +++ /dev/null @@ -1,111 +0,0 @@ -# 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, _("I am not welcomed here")) - - 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 = [] diff --git a/modules/mod_iq_register.py b/modules/mod_iq_register.py index fa5092e..239a72c 100644 --- a/modules/mod_iq_register.py +++ b/modules/mod_iq_register.py @@ -92,7 +92,8 @@ def register_handler(cl, iq): def sendRegisterForm(cl, iq): logger.debug("Send registration form to user (jid: %s)", iq.getFrom().getStripped()) - form = utils.buildDataForm(fields=forms.Forms.getComlicatedForm(), data=[_("Fill the fields below")]) + form = utils.buildDataForm(fields=forms.Forms.getSimpleForm(), data=[_("Fill the fields below")]) + form.setTag("next") result = iq.buildReply("result") result.setQueryPayload([form]) sender(cl, result) |