diff options
-rw-r--r-- | extensions/attachments.py | 4 | ||||
-rw-r--r-- | extensions/captcha_forms.py | 36 | ||||
-rw-r--r-- | extensions/groupchats.py | 104 | ||||
-rw-r--r-- | gateway.py | 126 | ||||
-rw-r--r-- | handlers/IQ.py | 4 | ||||
-rw-r--r-- | handlers/Message.py | 26 | ||||
-rw-r--r-- | handlers/Presence.py | 3 | ||||
-rw-r--r-- | library/utils.py | 15 | ||||
-rw-r--r-- | library/vkapi.py | 12 | ||||
-rw-r--r-- | library/webtools.py | 35 |
10 files changed, 186 insertions, 179 deletions
diff --git a/extensions/attachments.py b/extensions/attachments.py index abf3e2d..3ee4aca 100644 --- a/extensions/attachments.py +++ b/extensions/attachments.py @@ -25,6 +25,10 @@ def parseAttachments(self, msg): elif key == "video": body += "\nVideo: http://vk.com/video%(owner_id)s_%(vid)s — %(title)s" elif key == "audio": + for _key in ("performer", "title"): + if att[key].has_key(_key): + att[key][_key] = uHTML(att[key][_key]) + url = searchlink % urllib.quote(str("%(performer)s %(title)s" % att[key])) att[key]["url"] = url body += "\nAudio: %(performer)s — %(title)s — %(url)s" diff --git a/extensions/captcha_forms.py b/extensions/captcha_forms.py new file mode 100644 index 0000000..05536b6 --- /dev/null +++ b/extensions/captcha_forms.py @@ -0,0 +1,36 @@ +# coding: utf-8 +# This file is a part of VK4XMPP transport + +from hashlib import sha1 + +def captchaSend(self): + logger.debug("VKLogin: sending message with captcha to %s" % self.source) + body = _("WARNING: VK sent captcha to you." + " Please, go to %s and enter text from image to chat." + " Example: !captcha my_captcha_key. Tnx") % self.engine.captcha["img"] + msg = xmpp.Message(self.source, body, "chat", frm = TransportID) + x = msg.setTag("x", namespace=xmpp.NS_OOB) + x.setTagData("url", self.engine.captcha["img"]) + captcha = msg.setTag("captcha", namespace=xmpp.NS_CAPTCHA) + image = vCardGetPhoto(self.engine.captcha["img"], False) + 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"}, + {"var": "from", "value": TransportID, "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])])]}]) + 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) + else: + logger.critical("VKLogin: can't add captcha image to message url:%s" % self.engine.captcha["img"]) + Sender(Component, msg) + Presence = xmpp.protocol.Presence(self.source, frm=TransportID) + Presence.setStatus(body) + Presence.setShow("xa") + Sender(Component, Presence) + +Handlers["evt04"].append(captchaSend)
\ No newline at end of file diff --git a/extensions/groupchats.py b/extensions/groupchats.py index ba37696..c5eb202 100644 --- a/extensions/groupchats.py +++ b/extensions/groupchats.py @@ -25,31 +25,27 @@ def inviteUser(chat, jidTo, jidFrom, name): invite.addChild(node=x) Sender(Component, invite) -def buildConfigForm(form=None, type="sumbit", fields=[]): - form = form or xmpp.DataForm(type) - for key in fields: - field = form.setField(key["var"], key.get("value"), key.get("type")) - return form ## TODO: Set chatroom's name -def groupchatSetConfig(chat, jidFrom, exterminate=False): - iq = xmpp.Iq("set", to=chat, frm=jidFrom, xmlns="jabber:component:accept") +def chatSetConfig(chat, jidFrom, exterminate=False): + iq = xmpp.Iq("set", to=chat, frm=jidFrom) query = iq.addChild("query", namespace=xmpp.NS_MUC_OWNER) if exterminate: query.addChild("destroy") else: - form = buildConfigForm(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": "1"}, {"var": "muc#roomconfig_whois", "value": "anyone"}]) query.addChild(node=form) Sender(Component, iq) -def groupchatPresence(chat, name, jidFrom, type=None): +def chatPresence(chat, name, jidFrom, type=None): prs = xmpp.Presence("%s/%s" % (chat, name), type, frm=jidFrom) + prs.setTag("c", {"node": "http://simpleapps.ru/caps/vk4xmpp", "ver": Revision}, xmpp.NS_CAPS) Sender(Component, prs) -def groupchatMessage(chat, text, jidFrom, subj=None, timestamp=0): +def chatMessage(chat, text, jidFrom, subj=None, timestamp=0): message = xmpp.Message(chat, typ="groupchat") if timestamp: timestamp = time.gmtime(timestamp) @@ -61,90 +57,96 @@ def groupchatMessage(chat, text, jidFrom, subj=None, timestamp=0): message.setFrom(jidFrom) Sender(Component, message) -def handleChatMessages(self, msg): +def outgoungChatMessageHandler(self, msg): if msg.has_key("chat_id"): idFrom = msg["uid"] owner = msg["admin_id"] _owner = vk2xmpp(owner) - chatID = "%s_chat#%s" % (self.UserID, msg["chat_id"]) ## Maybe better to use owner id for chat + chatID = "%s_chat#%s" % (self.UserID, msg["chat_id"]) chat = "%s@%s" % (chatID, ConferenceServer) - users = msg["chat_active"].split(",") ## Why chat owner isn't in a chat? It may cause problems. Or not? + users = msg["chat_active"].split(",") users.append(self.UserID) if not users: ## is it possible? logger.debug("groupchats: all users exterminated in chat: %s" % chat) if chat in self.chatUsers: - groupchatPresence(chat, self.getUserData(owner)["name"], vk2xmpp(self.UserID), "unavailable") + chatPresence(chat, self.getUserData(owner)["name"], vk2xmpp(self.UserID), "unavailable") del self.chatUsers[chat] - return None # Maybe true? + return None if chat not in self.chatUsers: logger.debug("groupchats: creating %s. Users: %s; owner: %s" % (chat, msg["chat_active"], owner)) self.chatUsers[chat] = [] for usr in (owner, self.UserID): - groupchatPresence(chat, self.getUserData(usr)["name"], vk2xmpp(usr)) - groupchatSetConfig(chat, _owner) + chatPresence(chat, self.getUserData(usr)["name"], vk2xmpp(usr)) + chatSetConfig(chat, _owner) member(chat, self.source, _owner) - inviteUser(chat, self.source, _owner, self.getUserData(owner)["name"]) ## TODO: Handle WHO invited me. Yes, i know that it'll be never happen. But maybe someone another do it for himself? You're welcome! - groupchatMessage(chat, msg["title"], _owner, True, msg["date"]) + inviteUser(chat, self.source, _owner, self.getUserData(owner)["name"]) + chatMessage(chat, msg["title"], _owner, True, msg["date"]) - for user in users: ## BURN IT! + for user in users: if not user in self.chatUsers[chat]: logger.debug("groupchats: user %s has joined the chat %s" % (user, chat)) self.chatUsers[chat].append(user) uName = self.getUserData(user)["name"] user = vk2xmpp(user) member(chat, user, _owner) - groupchatPresence(chat, uName, user) + chatPresence(chat, uName, user) - for user in self.chatUsers[chat]: ## BURN IT MORE! + for user in self.chatUsers[chat]: if not user in users: logger.debug("groupchats: user %s has left the chat %s" % (user, chat)) self.chatUsers[chat].remove(user) uName = self.getUserData(user)["name"] - groupchatPresence(chat, uName, vk2xmpp(user), "unavailable") - - # This code will not work because function can be called only at message in chat - if not self.chatUsers[chat]: # Impossible - logger.debug("groupchats: %s would be exterminated right now!" % chat) - groupchatSetConfig(chat, _owner, exterminate=True) # EXTERMINATE!!! + chatPresence(chat, uName, vk2xmpp(user), "unavailable") body = escape("", uHTML(msg["body"])) body += parseAttachments(self, msg) body += parseForwardMessages(self, msg) if body: - groupchatMessage(chat, body, vk2xmpp(idFrom), None, msg["date"]) + chatMessage(chat, body, vk2xmpp(idFrom), None, msg["date"]) return None return "" -def incomingGroupchatMessageHandler(msg): +def incomingChatMessageHandler(msg): if msg.getType() == "groupchat": body = msg.getBody() - jidToStr = msg.getTo().getStripped() - jidFromStr = msg.getFrom().getStripped() - xTag = msg.getTag("x", {"xmlns": "http://jabber.org/protocol/muc#user"}) - if xTag and xTag.getTagAttr("status", "code") == "100": + destination = msg.getTo().getStripped() + source = msg.getFrom().getStripped() + html = msg.getTag("html") + x = msg.getTag("x", {"xmlns": "http://jabber.org/protocol/muc#user"}) + + if x and x.getTagAttr("status", "code") == "100": raise xmpp.NodeProcessed() if not msg.getTimestamp() and body: - Node, Domain = jidFromStr.split("@") + Node, Domain = source.split("@") if Domain == ConferenceServer: - jidToStr = vk2xmpp(jidToStr) - if jidToStr in jidToID: - jid = jidToID[jidToStr] - user = Transport[jid] - user.msg(body, Node.split("#")[1], "chat_id") - - -## TODO: -##def onShutdown(): -## for user in Transport.values(): -## if user.chatUsers -## + destination = vk2xmpp(destination) + if destination in jidToID: + jid = jidToID[destination] + if jid in Transport: + user = Transport[jid] + if html and html.getTag("body"): ## XHTML-IM! + logger.debug("groupchats: fetched xhtml image from %s" % source) + try: + xhtml = xhtmlParse(user, html, source, source, "chat_id") + except Exception: + xhtml = False + if xhtml: + raise xmpp.NodeProcessed() + user.msg(body, Node.split("#")[1], "chat_id") + + +def chatDestroy(user): + chats = user.vk.method("execute.getChats") + for chat in chats: + chatSetConfig("%s_chat#%s@%s" % (user.UserID, chat["chat_id"], ConferenceServer), vk2xmpp(chat["admin_id"]), True) if ConferenceServer: TransportFeatures.append(xmpp.NS_GROUPCHAT) - Handlers["msg01"].append(handleChatMessages) - Handlers["msg02"].append(incomingGroupchatMessageHandler) -## Handlers["shutdown"] TODO + Handlers["msg01"].append(outgoungChatMessageHandler) + Handlers["msg02"].append(incomingChatMessageHandler) + Handlers["evt03"].append(chatDestroy) + else: - del incomingGroupchatMessageHandler, handleChatMessages, inviteUser, groupchatPresence, groupchatMessage + del incomingChatMessageHandler, outgoungChatMessageHandler, inviteUser, chatPresence, chatMessage @@ -17,8 +17,6 @@ import sys import threading import time -from hashlib import sha1 - core = getattr(sys.modules["__main__"], "__file__", None) if core: core = os.path.abspath(core) @@ -31,6 +29,7 @@ reload(sys).setdefaultencoding("utf-8") import vkapi as api import xmpp +import utils from itypes import Database from webtools import * @@ -116,7 +115,7 @@ loggerHandler.setFormatter(Formatter) logger.addHandler(loggerHandler) def gatewayRev(): - revNumber, rev = 163, 0 # 0. means testing. + revNumber, rev = 167, 0 # 0. means testing. shell = os.popen("git describe --always && git log --pretty=format:''").readlines() if shell: revNumber, rev = len(shell), shell[0] @@ -126,8 +125,14 @@ OS = "{0} {2:.16} [{4}]".format(*os.uname()) Python = "{0} {1}.{2}.{3}".format(sys.subversion[0], *sys.version_info) Revision = gatewayRev() +## Events (not finished yet so not sorted): +## 01 - start +## 02 - shutdown +## 03 - user deletion +## 04 - captcha Handlers = {"msg01": [], "msg02": [], - "evt01": [], "evt02": []} + "evt01": [], "evt02": [], + "evt03": [], "evt04": []} Stats = {"msgin": 0, ## from vk "msgout": 0} ## to vk @@ -139,7 +144,7 @@ def initDatabase(filename): db.commit() return True -def executeFunction(handler, list = ()): +def execute(handler, list = ()): try: handler(*list) except SystemExit: @@ -147,6 +152,11 @@ def executeFunction(handler, list = ()): except Exception: crashLog(handler.func_name) +## TODO: execute threaded handlers +def executeHandlers(type, list = ()): + for handler in Handlers[type]: + execute(handler, list) + def startThr(thr, number = 0): if number > 2: raise RuntimeError("exit") @@ -156,7 +166,7 @@ def startThr(thr, number = 0): startThr(thr, (number + 1)) def threadRun(func, args = (), name = None): - thr = threading.Thread(target = executeFunction, args = (func, args), name = name or func.func_name) + thr = threading.Thread(target = execute, args = (func, args), name = name or func.func_name) try: thr.start() except threading.ThreadError: @@ -167,34 +177,10 @@ def threadRun(func, args = (), name = None): badChars = [x for x in xrange(32) if x not in (9, 10, 13)] + [57003, 65535] escape = re.compile("|".join(unichr(x) for x in badChars), re.IGNORECASE | re.UNICODE | re.DOTALL).sub +msgSort = lambda msgOne, msgTwo: msgOne.get("mid", 0) - msgTwo.get("mid", 0) require = lambda name: os.path.exists("extensions/%s.py" % name) -def deleteUser(user, roster = False, semph = Semaphore): - logger.debug("User: deleting user %s from db." % user.source) - with Database(DatabaseFile, semph) as db: ## WARNING: this may cause main thread lock - db("delete from users where jid=?", (user.source,)) - db.commit() - user.existsInDB = False - friends = getattr(user, "friends") - if roster and friends: - logger.debug("User: deleting me from %s roster" % user.source) - for id in friends.keys(): - jid = vk2xmpp(id) - sendPresence(user.source, jid, "unsubscribe") - sendPresence(user.source, jid, "unsubscribed") - - elif roster: - sendPresence(user.source, TransportID, "unsubscribe") - sendPresence(user.source, TransportID, "unsubscribed") - - vk = getattr(user, "vk") or user - if user.source in Transport: - vk.Online = False - del Transport[user.source] - Poll.remove(user) - - class VKLogin(object): def __init__(self, number, password = None, source = None): @@ -286,14 +272,14 @@ class VKLogin(object): if self.engine.lastMethod[0] == "messages.send": msgSend(Component, self.source, _("You're not allowed to perform this action."), vk2xmpp(args.get("user_id", TransportID))) except api.VkApiError as e: - db = False + roster = False if e.message == "User authorization failed: user revoke access for this token.": logger.critical("VKLogin: %s" % e.message) - db = True + roster = True elif e.message == "User authorization failed: invalid access_token.": msgSend(Component, self.source, _(e.message + " Please, register again"), TransportID) try: - deleteUser(Transport.get(self.source, self), db) + deleteUser(Transport.get(self.source, self), roster, False) except KeyError: pass @@ -306,38 +292,7 @@ class VKLogin(object): def captchaChallenge(self): if self.engine.captcha: - logger.debug("VKLogin: sending message with captcha to %s" % self.source) - body = _("WARNING: VK sent captcha to you." - " Please, go to %s and enter text from image to chat." - " Example: !captcha my_captcha_key. Tnx") % self.engine.captcha["img"] - msg = xmpp.Message(self.source, body, "chat", frm = TransportID) - xTag = msg.setTag("x", {}, xmpp.NS_OOB) - xTag.setTagData("url", self.engine.captcha["img"]) - cTag = msg.setTag("captcha", {}, xmpp.NS_CAPTCHA) - imgData = vCardGetPhoto(self.engine.captcha["img"], False) - if imgData: - imgHash = sha1(imgData).hexdigest() - imgEncoded = imgData.encode("base64") - form = xmpp.DataForm("form") - form.setField("FORM_TYPE", xmpp.NS_CAPTCHA, "hidden") - form.setField("from", TransportID, "hidden") - field = form.setField("ocr") - field.setLabel(_("Enter shown text")) -## field.delAttr("type") - field.setPayload([xmpp.Node("required"), - xmpp.Node("media", {"xmlns": xmpp.NS_MEDIA}, - [xmpp.Node("uri", {"type": "image/jpg"}, - ["cid:sha1+%s@bob.xmpp.org" % imgHash])])]) - cTag.addChild(node=form) - obTag = msg.setTag("data", {"cid": "sha1+%s@bob.xmpp.org" % imgHash, "type": "image/jpg", "max-age": "0"}, xmpp.NS_URN_OOB) - obTag.setData(imgEncoded) - else: - logger.critical("VKLogin: can't add captcha image to message url:%s" % self.engine.captcha["img"]) - Sender(Component, msg) - Presence = xmpp.protocol.Presence(self.source, frm = TransportID) - Presence.setStatus(body) - Presence.setShow("xa") - Sender(Component, Presence) + executeHandlers("evt04", (self,)) else: logger.error("VKLogin: captchaChallenge called without captcha for user %s" % self.source) @@ -369,7 +324,6 @@ class VKLogin(object): values["last_message_id"] = lastMsgID return self.method("messages.get", values) - def sendPresence(target, source, pType = None, nick = None, reason = None, caps = None): Presence = xmpp.Presence(target, pType, frm = source, status = reason) if nick: @@ -407,7 +361,7 @@ class User(object): logger.debug("User: %s exists in db. Have to use it." % self.source) self.existsInDB = True self.source, self.username, self.token, self.lastMsgID, self.rosterSet = desc - elif self.password or self.token: ## Warning: this may work wrong. If user exists in db we shouldn't delete him, we just should replace his token + elif self.password or self.token: logger.debug("User: %s exists in db. Record would be deleted." % self.source) threadRun(deleteUser, (self,)) @@ -520,7 +474,6 @@ class User(object): else: data = data.pop() data["name"] = escape("", u"%s %s" % (data.pop("first_name"), data.pop("last_name"))) - return data def sendMessages(self, init=False): @@ -616,7 +569,7 @@ class User(object): if not friends: logger.error("updateFriends: no friends received (user: %s)." % self.source) return None - if friends and set(friends) != set(self.friends): + if friends: for uid in friends: if uid not in self.friends: self.rosterSubscribe({uid: friends[uid]}) @@ -635,7 +588,30 @@ class User(object): except Exception: crashLog("tryAgain") -msgSort = lambda msgOne, msgTwo: msgOne.get("mid", 0) - msgTwo.get("mid", 0) +def deleteUser(user, roster = False, semph = Semaphore): + logger.debug("User: deleting user %s from db." % user.source) + with Database(DatabaseFile, semph) as db: ## WARNING: this may cause main thread lock + db("delete from users where jid=?", (user.source,)) + db.commit() + user.existsInDB = False + friends = getattr(user, "friends", {}) + if roster and friends: + logger.debug("User: deleting me from %s roster" % user.source) + for id in friends.keys(): + jid = vk2xmpp(id) + sendPresence(user.source, jid, "unsubscribe") + sendPresence(user.source, jid, "unsubscribed") + + elif roster: + sendPresence(user.source, TransportID, "unsubscribe") + sendPresence(user.source, TransportID, "unsubscribed") + executeHandlers("evt03", (user,)) + + vk = getattr(user, "vk", user) + if user.source in Transport: + vk.Online = False + del Transport[user.source] + Poll.remove(user) def Sender(cl, stanza): try: @@ -697,6 +673,8 @@ def userTyping(target, instance, typ = "composing"): message.setTag(typ, namespace = xmpp.NS_CHATSTATES) Sender(Component, message) + +## TODO: make it as extension def watcherMsg(text): for jid in WatcherList: msgSend(Component, jid, text, TransportID) @@ -710,8 +688,7 @@ def disconnectHandler(crash = True): Component.disconnect() except (NameError, AttributeError): pass - for event in Handlers["evt02"]: - event() + executeHandlers("evt02") Print("Reconnecting...") time.sleep(5) os.execl(sys.executable, sys.executable, *sys.argv) @@ -887,8 +864,7 @@ def exit(signal = None, frame = None): user.sendOutPresence(user.source, status) Print("." * len(user.friends), False) Print("\n") - for event in Handlers["evt02"]: - event() + executeHandlers("evt02") try: os.remove(pidFile) except OSError: diff --git a/handlers/IQ.py b/handlers/IQ.py index 85df324..bb0b738 100644 --- a/handlers/IQ.py +++ b/handlers/IQ.py @@ -42,7 +42,6 @@ def iqHandler(cl, iq): if jidTo == TransportID: Sender(cl, iq.buildReply("result")) - raise xmpp.NodeProcessed() def iqBuildError(stanza, error = None, text = None): if not error: @@ -177,7 +176,6 @@ def iqUptimeHandler(cl, iq): result.setTag("query", {"seconds": str(uptime)}, xmpp.NS_LAST) result.setTagData("query", IDentifier["name"]) Sender(cl, result) - raise xmpp.NodeProcessed() def iqVersionHandler(cl, iq): iType = iq.getType() @@ -189,7 +187,6 @@ def iqVersionHandler(cl, iq): Query.setTagData("version", Revision) Query.setTagData("os", "%s / %s" % (OS, Python)) Sender(cl, result) - raise xmpp.NodeProcessed() sDict = { "users/total": "users", @@ -263,7 +260,6 @@ def iqDiscoHandler(cl, iq): result.setQueryPayload(QueryPayload) Sender(cl, result) - raise xmpp.NodeProcessed() def iqGatewayHandler(cl, iq): jidTo = iq.getTo() diff --git a/handlers/Message.py b/handlers/Message.py index e99e8c6..955ae92 100644 --- a/handlers/Message.py +++ b/handlers/Message.py @@ -14,8 +14,17 @@ def msgRecieved(msg, jidFrom, jidTo): answer.setID(msg.getID()) return answer -def sendPhoto(user, data, type, address): +def sendPhoto(user, data, type, address, mType): mask = user.vk.method("account.getAppPermissions") + + if mType == "chat_id": + address = address.split("@")[0].split("#")[1] + send = False + else: + destination = address + address = vk2xmpp(address) + send = True + if address == TransportID: answer = _("Are you kidding me?") elif mask: @@ -30,7 +39,8 @@ def sendPhoto(user, data, type, address): photo = user.vk.method("photos.saveMessagesPhoto", response)[0] id = photo["id"] - user.msg("", vk2xmpp(address), more = {"attachment": id}) + + user.msg("", address, mType, {"attachment": id}) logger.debug("sendPhoto: image was successfully sent by user %s" % user.source) answer = _("Your image was successfully sent.") else: @@ -38,12 +48,13 @@ def sendPhoto(user, data, type, address): " Seems you haven't enough permissions. Your token should be updated, register again.") else: answer = _("Something went wrong. We are so sorry.") - msgSend(Component, user.source, answer, address, timestamp = 1) + if send: + msgSend(Component, user.source, answer, destination, timestamp = 1) -def xhtmlParse(user, html, source, destination): +def xhtmlParse(user, html, source, destination, mType = "user_id"): body = html.getTag("body") if body: - ## TODO: Maybe would be better if use regular expressions? + ## TODO: Maybe would be better use regular expressions? src = body.getTagAttr("img", "src") raw_data = src.split("data:")[1] mime_type = raw_data.split(";")[0] @@ -52,9 +63,9 @@ def xhtmlParse(user, html, source, destination): try: data = urllib.unquote(data).decode("base64") except Exception: - logger.error("msgHandler: fetched wrong xhtml image from %s" % source) + logger.error("xhmtlParse: fetched wrong xhtml image from %s" % source) return False - threadRun(sendPhoto, (user, data, mime_type, destination)) + threadRun(sendPhoto, (user, data, mime_type, destination, mType)) return True def msgHandler(cl, msg): @@ -136,7 +147,6 @@ def captchaAccept(cl, args, jidTo, source): answer = _("Captcha valid.") Poll.add(user) Presence = xmpp.protocol.Presence(source, frm = TransportID) - #Presence.setStatus("") # is it needed? Presence.setShow("available") Sender(Component, Presence) user.tryAgain() diff --git a/handlers/Presence.py b/handlers/Presence.py index 8d008c7..f0aba07 100644 --- a/handlers/Presence.py +++ b/handlers/Presence.py @@ -2,6 +2,7 @@ # This file is a part of VK4XMPP transport # © simpleApps, 2013 — 2014. + def prsHandler(cl, prs): pType = prs.getType() jidFrom = prs.getFrom() @@ -60,7 +61,7 @@ def prsHandler(cl, prs): db("select jid,username from users where jid=?", (source,)) data = db.fetchone() if data: - logger.debug("User %s found in db" % source) + logger.debug("User %s has been found in db" % source) jid, phone = data Transport[jid] = user = User((phone, None), jid) try: diff --git a/library/utils.py b/library/utils.py new file mode 100644 index 0000000..3fe87e2 --- /dev/null +++ b/library/utils.py @@ -0,0 +1,15 @@ +# coding: utf-8 +# This file is a part of VK4XMPP transport +# © simpleApps, 2014. + +import xmpp + +def buildDataForm(form=None, type="submit", fields=[]): + form = form or xmpp.DataForm(type) + for key in fields: + field = form.setField(key["var"], key.get("value"), key.get("type")) + if key.get("payload"): + field.setPayload(key["payload"]) + if key.get("label"): + field.setLabel(key["label"]) + return form
\ No newline at end of file diff --git a/library/vkapi.py b/library/vkapi.py index 41be1e8..86902e1 100644 --- a/library/vkapi.py +++ b/library/vkapi.py @@ -115,13 +115,13 @@ class RequestProcessor(object): request = urllib2.Request(url, data, headers) return request - @attemptTo(5, tuple, urllib2.URLError, ssl.SSLError, socket.timeout) + @attemptTo(5, tuple, urllib2.URLError, ssl.SSLError, socket.timeout, httplib.BadStatusLine) def post(self, url, data="", urlencode=True): resp = self.open(self.request(url, data, urlencode=urlencode)) body = resp.read() return (body, resp) - @attemptTo(5, tuple, urllib2.URLError, ssl.SSLError, socket.timeout) + @attemptTo(5, tuple, urllib2.URLError, ssl.SSLError, socket.timeout, httplib.BadStatusLine) def get(self, url, query={}): if query: url += "?%s" % urllib.urlencode(query) @@ -246,7 +246,7 @@ class APIBinding: if (self.last.pop() - self.last.pop(0)) < 1.1: time.sleep(0.3) - response = self.RIP.post(url, values) # Next func should handle NetworkNotFound + response = self.RIP.post(url, values) if response and not nodecode: body, response = response if body: @@ -281,14 +281,14 @@ class APIBinding: raise VkApiError("Logged out") elif eCode == 7: # not allowed raise NotAllowed() - elif eCode == 9: # ???? - return {} elif eCode == 10: # internal server error raise InternalServerError() - if eCode == 14: # captcha + elif eCode == 14: # captcha if "captcha_sid" in error: self.captcha = {"sid": error["captcha_sid"], "img": error["captcha_img"]} raise CaptchaNeeded() + elif eCode in (1, 9, 100): ## 1 is an unknown error / 100 is wrong method or parameters loss + return {"error": eCode} raise VkApiError(body["error"]) def retry(self): diff --git a/library/webtools.py b/library/webtools.py index d4dc6e8..eb986b0 100644 --- a/library/webtools.py +++ b/library/webtools.py @@ -3,9 +3,7 @@ # BlackSmith-bot module. # © simpleApps, 21.05.2012. -import urllib, urllib2, re - -## HTML Unescape and <br> tag replace. +import re import htmlentitydefs edefs = dict() @@ -41,25 +39,6 @@ def uHTML(data): data = re.sub("</?br */?>", "\n", data) return data -# TODO: remove this function -def regexp(reg, string, findall = 1): - reg = re.compile(reg, re.IGNORECASE | re.DOTALL) - if findall: - reg = reg.findall(string) - else: - return reg.search(string) - return reg - -## Get HTML tag. -def getTagData(tag, data, close_tag = 0): - if not close_tag: - close_tag = tag - pattern = re.compile("<%(tag)s.*?>(.*?)</%(close_tag)s>" % vars(), flags = re.DOTALL | re.IGNORECASE) - tagData = pattern.search(data) - if tagData: - tagData = tagData.group(1) - return tagData or " " - def getTagArg(tag, argv, data, close_tag = 0): if not close_tag: close_tag = tag @@ -68,15 +47,3 @@ def getTagArg(tag, argv, data, close_tag = 0): if tagData: tagData = tagData.group(1) return tagData or " " - -def stripTags(data, subBy = str(), pattern = "<[^<>]+>"): - pattern = re.compile(pattern) - return pattern.sub(subBy, data) - -## Format size. -def byteFormat(size): - if size < 1024: return '%sb' % int(size) - for t in ('kB','MB','GB'): - size = size / 1024.0 - if size < 1024: break - return '%.2f%s' % (size,t) |