diff options
author | John Smith <mrdoctorwho@helldev.net> | 2020-08-30 06:30:33 +0300 |
---|---|---|
committer | John Smith <mrdoctorwho@helldev.net> | 2020-08-30 06:30:33 +0300 |
commit | 656fdba28d372d7e37c81042823e9df07f77fa34 (patch) | |
tree | 52f7b509ca6298646d5f9340191dfbcc6d2f5bf4 | |
parent | d07c9705bd77af2f0f2a09579babf1ec09648550 (diff) |
Update to support API v5.120, introduce friends limit
This release is devoted to Alexey, who has supported us through the years. RIP.
-rw-r--r-- | Config_example.txt | 3 | ||||
-rw-r--r-- | extensions/.example.py | 19 | ||||
-rw-r--r-- | extensions/attachments.py | 75 | ||||
-rw-r--r-- | extensions/forwarded_messages.py | 16 | ||||
-rw-r--r-- | extensions/geo.py | 4 | ||||
-rw-r--r-- | extensions/groupchats.py | 14 | ||||
-rw-r--r-- | gateway.py | 90 | ||||
-rw-r--r-- | library/defaults.py | 3 | ||||
-rw-r--r-- | library/longpoll.py | 5 | ||||
-rw-r--r-- | library/vkapi.py | 57 |
10 files changed, 176 insertions, 110 deletions
diff --git a/Config_example.txt b/Config_example.txt index a74ec99..65b8adc 100644 --- a/Config_example.txt +++ b/Config_example.txt @@ -68,6 +68,9 @@ URL_VCARD_NO_IMAGE = "https://raw.githubusercontent.com/mrDoctorWho/vk4xmpp/mast # Old users will be able to update their registration. ALLOW_REGISTRATION = True +# Friends limit per user. +MAX_FRIENDS = 5000 + #! Danger zone. #! Change the settings below ONLY IF YOU KNOW WHAT ARE YOU DOING! DEFAULT VALUES ARE RECOMMENDED! # You were warned. diff --git a/extensions/.example.py b/extensions/.example.py index 81fb522..43b8759 100644 --- a/extensions/.example.py +++ b/extensions/.example.py @@ -3,7 +3,7 @@ # © simpleApps, 2014. # This plugin contain all vk4xmpp plugin's API features # Rename it to "example.py" if you wanna test it -# Please notice that plugins are working in globals() so names must be unique +# Please notice that plugins are working in globals() so variable and function names must be unique ## Events (not finished yet so not sorted): # 01 - transport's start (threaded), no args @@ -56,7 +56,7 @@ def evt04_handler(vk): Parameters: vk: VK class object """ - print "Look at this man, he've got a captcha: %s. This image: %s is not for robots" % (vk.source, vk.engine.captcha["img"]) + print "Look at this man, he's got a captcha: %s. This image: %s is not for robots" % (vk.source, vk.engine.captcha["img"]) registerHandler("evt04", evt04_handler) @@ -68,7 +68,7 @@ def evt05_handler(user): Parameters: user: User class object """ - print "Hey, look who come to see us: %s" % user.source + print "Hey, look who came to see us: %s" % user.source registerHandler("evt05", evt05_handler) @@ -119,11 +119,14 @@ def msg01_handler(user, message): Parameters: user: User class object message: single message json object - Return values: - None: the function itself should send a message - str type: transport's core will add returned string to existing body - """ - return "\nmsg01_handler is awesome" + Returns: + A tuple of (status, body) where status indicates what to do with the body. + List of statuses: + * MSG_SKIP: message will be skipped and execution of other handlers stopped + * MSG_APPEND: message body will be appended with returning body + * MSG_APPEND: message body will be prepended with returning body + """ + return (MSG_APPEND, "\nmsg01_handler is awesome") registerHandler("msg01", msg01_handler) diff --git a/extensions/attachments.py b/extensions/attachments.py index 3b65376..2cc6668 100644 --- a/extensions/attachments.py +++ b/extensions/attachments.py @@ -4,16 +4,18 @@ import re import urllib +import time from printer import * VK_AUDIO_SEARCH_LINK = "https://vk.com/search?c[q]=%s&c[section]=audio" 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" +WALL_COMMENT_LINK = "https://vk.com/wall%(owner_id)s_%(post_id)s?w=wall%(owner_id)s_%(post_id)s" -PHOTO_SIZES = ("photo_2560", "photo_1280", "photo_807", "photo_604", "photo_130", "photo_75") -STICKER_SIZES = ("photo_256", "photo_128", "photo_64") +PHOTO_SIZES = ("w", "z", "y", "x", "q", "p", "m", "o", "s") +STICKER_SIZES = (512, 352, 256, 128, 64) -ATTACHMENT_REGEX = re.compile(r"^(?P<type>Photo|Document|Sticker)\:\s(?P<name>“.+?”\s—\s)?(?P<url>http[s]?:\/\/[^\s]+)$", re.UNICODE) + +ATTACHMENT_REGEX = re.compile(r"^(?P<type>Photo|Document|Sticker|Audio message)\:\s(?P<name>“.+?”\s—\s)?(?P<url>http[s]?:\/\/[^\s]+)$", re.UNICODE) GLOBAL_USER_SETTINGS["parse_wall"] = {"value": 1, "label": "Parse wall attachments"} GLOBAL_USER_SETTINGS["make_oob"] = {"value": 1, "label": "Allow OOB for attachments", @@ -27,20 +29,24 @@ SIMPLE_ATTACHMENTS = {"doc": "Document: “%(title)s” — %(url)s", "page": "Page: %(title)s — %(view_url)s"} +timeFormat = lambda seconds: time.strftime('%H:%M:%S', time.gmtime(seconds)) + + def parseAttachments(self, msg, spacer=""): """ “parses” attachments from the json to a string """ - result = "" + result = (MSG_APPEND, "") + final_body = "" if "attachments" in msg: attachments = msg["attachments"] # Add new line and "Attachments" if there some text added - if msg.get("body") and len(attachments) > 1: - result += chr(10) + spacer + _("Attachments:") + if msg.get("text") and len(attachments) > 1: + final_body += chr(10) + spacer + _("Attachments:") if spacer: - result += "\n" - elif msg.get("body"): - result += "\n" + final_body += "\n" + elif msg.get("text"): + final_body += "\n" for num, attachment in enumerate(attachments): body = spacer @@ -62,26 +68,42 @@ def parseAttachments(self, msg, spacer=""): 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 + parseAttachments(self, current, spacer)[1] + "\n" + spacer + "\n" body += spacer + ("Wall: %s" % WALL_LINK % current) elif type == "photo": + sizes = current.get("sizes", []) + found = False 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 + for size in sizes: + if size.get("type") == key: + body += "Photo: %s" % size.get("url") # No new line needed if we have just one photo and no text + found = True + break + if found: break elif type == "audio": current["performer"] = uhtml(current.get("performer", "")) current["title"] = uhtml(current.get("title", "")) current["url"] = VK_AUDIO_SEARCH_LINK % urllib.quote(str("%(artist)s %(title)s" % current)) - current["time"] = current["duration"] / 60.0 + current["time"] = timeFormat(current["duration"]) body += "Audio: %(artist)s — “%(title)s“ (%(time)s min) — %(url)s" % current + elif type == "audio_message": + link = current.get("link_ogg") or current.get("link_mp3") + body += "Audio message: %s (%s)" % (link, timeFormat(current["duration"])) + elif type == "sticker": - for key in STICKER_SIZES: - if key in current: - body += "Sticker: %s" % current[key] + images = current.get("images", []) + found = False + for size in STICKER_SIZES: + for image in images: + if image.get("width") == size or image.get("height") == size: + body += "Sticker: %s" % image["url"] + found = True + break + if found: break elif type == "wall_reply": @@ -97,13 +119,12 @@ def parseAttachments(self, msg, spacer=""): elif type == "video": current["title"] = current.get("title", "Untitled") - current["desc"] = "" if current.get("description"): current["desc"] += uhtml(compile_eol.sub(" / ", "%(description)s, " % current)) current["desc"] += "%(views)d views" % current - current["time"] = "%d:%d" % (current["duration"] // 60, current["duration"] % 60) + current["time"] = timeFormat(current["duration"]) body += "Video: %(title)s (%(desc)s, %(time)s min) — https://vk.com/video%(owner_id)s_%(id)s" % current @@ -112,7 +133,8 @@ def parseAttachments(self, msg, spacer=""): else: body += "Unknown attachment: %s\n%s" % (type, str(current)) - result += body + final_body += body + result = (MSG_APPEND, final_body) return result @@ -127,19 +149,6 @@ def attachments_msg03(msg, destination, source): match = ATTACHMENT_REGEX.match(body.encode("utf-8")) if match: link = match.group("url") - typ = match.group("type") - name = match.group("name") - if link and name: - # shorten links only for audio messages - # todo: is there a better way to detect them? - # probably having "psv4." in the domain might - # be considered as private storage and hence shouldn't be downloaded by us - if typ == "Document" and ".ogg" in name: - try: - link = urllib.urlopen(link).url - except Exception: - crashLog("attachments_msg03") - logger.error("unable to fetch real url for link %s and (jid: %s)", (link, user.source)) oob = msg.setTag("x", namespace=xmpp.NS_OOB) oob.setTagData("url", link) msg.setBody(link) diff --git a/extensions/forwarded_messages.py b/extensions/forwarded_messages.py index f052ec7..20320fe 100644 --- a/extensions/forwarded_messages.py +++ b/extensions/forwarded_messages.py @@ -27,21 +27,23 @@ class TimezoneOffset(tzinfo): def parseForwardedMessages(self, msg, depth=0): body = "" - if "fwd_messages" in msg: + result = (MSG_APPEND, "") + if msg.get("fwd_messages"): spacer = BASE_SPACER * depth body = "\n" + spacer body += _("Forwarded messages:") fwd_messages = sorted(msg["fwd_messages"], sortMsg) for fwd in fwd_messages: - source = fwd["user_id"] - fwdBody = escape("", uhtml(compile_eol.sub("\n" + spacer + BASE_SPACER, fwd["body"]))) + source = fwd["from_id"] + fwdBody = escape("", uhtml(compile_eol.sub("\n" + spacer + BASE_SPACER, fwd["text"]))) date = getUserDate(self, fwd["date"]) name = self.vk.getName(source) body += "\n%s[%s] %s> %s" % (spacer + BASE_SPACER, date, name, fwdBody) - body += parseAttachments(self, fwd, spacer + (BASE_SPACER * 2)) + body += parseAttachments(self, fwd, spacer + (BASE_SPACER * 2))[1] if depth < MAXIMUM_FORWARD_DEPTH: - body += parseForwardedMessages(self, fwd, (depth + 1)) - return body + body += parseForwardedMessages(self, fwd, (depth + 1))[1] + result = (MSG_APPEND, body) + return result def getUserDate(user, timestamp): @@ -62,6 +64,6 @@ def getUserDate(user, timestamp): if not isdef("MAXIMUM_FORWARD_DEPTH"): - MAXIMUM_FORWARD_DEPTH = 29 + MAXIMUM_FORWARD_DEPTH = 33 registerHandler("msg01", parseForwardedMessages) diff --git a/extensions/geo.py b/extensions/geo.py index 9a2eb8e..928d2c0 100644 --- a/extensions/geo.py +++ b/extensions/geo.py @@ -8,6 +8,7 @@ GoogleMapLink = "https://maps.google.com/maps?q=%s" def TimeAndRelativeDimensionInSpace(self, machine): body = "" + result = (MSG_APPEND, "") if machine.has_key("geo"): t_machine = machine["geo"] place = t_machine.get("place") @@ -19,6 +20,7 @@ def TimeAndRelativeDimensionInSpace(self, machine): body += _("\nCity: %s\n") % place["city"] body += _("Coordinates: %s") % coordinates body += "\n%s — Google Maps" % GoogleMapLink % urllib.quote(t_machine["coordinates"]) - return body + result = (MSG_APPEND, body) + return result registerHandler("msg01", TimeAndRelativeDimensionInSpace) diff --git a/extensions/groupchats.py b/extensions/groupchats.py index ed6632f..9eaef8c 100644 --- a/extensions/groupchats.py +++ b/extensions/groupchats.py @@ -145,9 +145,9 @@ def handleOutgoingChatMessage(user, vkChat): Handles outging VK messages and sends them to XMPP """ # peer_id for newer APIs - chatID = vkChat.get("chat_id", 0) + chatID = vkChat.get("peer_id", 0) - MIN_CHAT_ID - if chatID: + if chatID > 0: # check if the groupchats support enabled in user's settings if not user.settings.groupchats: return None @@ -173,8 +173,8 @@ def handleOutgoingChatMessage(user, vkChat): if not chat.created: time.sleep(1.5) chat.handleMessage(user, vkChat) - return None - return "" + return (MSG_SKIP, "") + return (MSG_APPEND, "") def createChat(user, source): @@ -365,9 +365,9 @@ class Chat(object): """ if self.created: self.update(user, vkChat) - body = escape("", uhtml(vkChat["body"])) - body += parseAttachments(user, vkChat) - body += parseForwardedMessages(user, vkChat) + body = escape("", uhtml(vkChat["text"])) + body += parseAttachments(user, vkChat)[1] + body += parseForwardedMessages(user, vkChat)[1] if body: chatMessage(self.jid, body, vk2xmpp(vkChat["from_id"]), None) else: @@ -64,8 +64,6 @@ Config = args.config startTime = int(time.time()) -# not really required to be none, but the debugger requires them to be defined -# and, come on, this is much better, isn't it? DatabaseFile = None TransportID = None Host = None @@ -125,6 +123,17 @@ Stats = {"msgin": 0, # from vk MAX_MESSAGES_PER_REQUEST = 20 +# Status code that indicates what to do with returning body from plugins +MSG_SKIP = -1 +MSG_PREPEND = 0 +MSG_APPEND = 1 + +# Timeout after which user is considered paused typing +TYPING_TIMEOUT = 5 + +# Timeout for friends updating +FRIENDS_UPDATE_TIMEOUT = 300 + def runDatabaseQuery(query, args=(), set=False, many=True): """ @@ -194,7 +203,7 @@ def getGatewayRev(): """ Gets gateway revision using git or custom revision number """ - number, hash = 460, 0 + number, hash = 480, 0 shell = os.popen("git describe --always &" "& git log --pretty=format:''").readlines() if shell: @@ -433,8 +442,7 @@ class VK(object): del data["last_name"] return name - - def getFriends(self, fields=None): + def getFriends(self, fields=None, limit=MAX_FRIENDS): """ Executes the friends.get method and formats it in the key-value style Example: @@ -444,7 +452,7 @@ class VK(object): Which will be added in the result values """ fields = fields or self.friends_fields - raw = self.method("friends.get", {"fields": str.join(",", fields)}) or {} + raw = self.method("friends.get", {"fields": str.join(",", fields), "count": limit}) or {} raw = raw.get("items", {}) friends = {} for friend in raw: @@ -627,7 +635,7 @@ class VK(object): The result of sending the message """ Stats["msgout"] += 1 - values = {mType: id, "message": body, "type": 0} + values = {mType: id, "message": body, "type": 0, "random_id": int(time.time())} values.update(more) try: result = self.method("messages.send", values) @@ -807,18 +815,16 @@ class User(object): Sends messages from vk to xmpp and call message01 handlers Args: init: needed to know if function called at init (add time or not) - Plugins notice (msg01): - If plugin returns None then message will not be sent by transport's core, - it shall be sent by plugin itself - Otherwise, if plugin returns string, - the message will be sent by transport's core + messages: a list of pre-defined messages that would be handled and sent (w/o requesting new ones) + mid: last message id + uid: user id + filter_: what filter to use (all/unread) """ with self.sync: date = 0 if not messages: - messages = self.vk.getMessages(MAX_MESSAGES_PER_REQUEST, mid or self.lastMsgID+1, uid, filter_) - if not messages: - return None + messages = self.vk.getMessages(MAX_MESSAGES_PER_REQUEST, mid or self.lastMsgID, uid, filter_) + messages = sorted(messages, sortMsg) for message in messages: # check if message wasn't sent by our user @@ -826,27 +832,28 @@ class User(object): if self.lastMsgID >= message["id"]: continue Stats["msgin"] += 1 - frm = message["user_id"] + frm = message["from_id"] mid = message["id"] - if frm in self.typing: - del self.typing[frm] + self.removeTyping(frm) fromjid = vk2xmpp(frm) - body = message["body"] - body = uhtml(body) - iter = Handlers["msg01"].__iter__() - for func in iter: + body = uhtml(message["text"]) + iter_ = Handlers["msg01"].__iter__() + for func in iter_: try: - result = func(self, message) + status, data = func(self, message) except Exception: - result = "" + status, data = MSG_APPEND, "" crashLog("handle.%s" % func.__name__) - if result is None: - for func in iter: + # got ignore status, continuing execution + if status == MSG_SKIP: + for func in iter_: utils.execute(func, (self, message)) break - else: - body += result + elif status == MSG_APPEND: + body += data + elif status == MSG_PREPEND: + body = data + body else: if self.settings.force_vk_date or init: date = message["date"] @@ -854,9 +861,14 @@ class User(object): sendMessage(self.source, fromjid, escape("", body), date, mid=mid) if messages: newLastMsgID = messages[-1]["id"] - self.lastMsgID = newLastMsgID - runDatabaseQuery("update users set lastMsgID=? where jid=?", - (newLastMsgID, self.source), True) + if newLastMsgID > self.lastMsgID: + self.lastMsgID = newLastMsgID + runDatabaseQuery("update users set lastMsgID=? where jid=?", + (newLastMsgID, self.source), True) + + def removeTyping(self, frm): + if frm in self.typing: + del self.typing[frm] def updateTypingUsers(self, cTime): """ @@ -867,7 +879,7 @@ class User(object): """ with self.sync: for user, last in self.typing.items(): - if cTime - last > 7: + if cTime - last > TYPING_TIMEOUT: del self.typing[user] sendMessage(self.source, vk2xmpp(user), typ="paused") @@ -877,7 +889,7 @@ class User(object): Compares the current friends list to the new list Takes a corresponding action if any difference found """ - if (cTime - self.last_udate) > 300 and not self.vk.engine.captcha: + if (cTime - self.last_udate) > FRIENDS_UPDATE_TIMEOUT and not self.vk.engine.captcha: if self.settings.keep_online: self.vk.setOnline() else: @@ -954,6 +966,7 @@ def sendMessage(destination, source, body=None, timestamp=0, typ="active", mtype timestamp: message timestamp (XEP-0091) typ: xmpp chatstates type (XEP-0085) mtype: the message type + mid: message id """ msg = xmpp.Message(destination, body, mtype, frm=source) msg.setTag(typ, namespace=xmpp.NS_CHATSTATES) @@ -967,6 +980,14 @@ def sendMessage(destination, source, body=None, timestamp=0, typ="active", mtype def sendChatMarker(destination, source, mid, typ="displayed"): + """ + Sends a chat marker as per XEP-0333 + Args: + destination: to whom send the marker + source: from who send the marker + mid: which message id should be marked as read + typ: marker type (displayed by default) + """ msg = xmpp.Message(destination, typ="chat",frm=source) msg.setTag(typ, {"id": mid}, xmpp.NS_CHAT_MARKERS) sender(Component, msg) @@ -1026,6 +1047,7 @@ def updateCron(): user.updateFriends(cTime) time.sleep(2) + def calcStats(): """ Returns count(*) from users database @@ -1084,9 +1106,9 @@ def checkPID(): if os.path.exists(pidFile): old = rFile(pidFile) if old: - Print("#-# Killing the previous instance: ", False) old = int(old) if pid != old: + Print("#-# Killing the previous instance: ", False) try: os.kill(old, signal.SIGTERM) time.sleep(3) diff --git a/library/defaults.py b/library/defaults.py index 93a3f7f..5f40043 100644 --- a/library/defaults.py +++ b/library/defaults.py @@ -49,6 +49,9 @@ DefLang = "ru" AdditionalAbout = "" allowBePublic = True +# Max friends per user +MAX_FRIENDS = 5000 + # The features transport will advertise TransportFeatures = {xmpp.NS_DELAY, xmpp.NS_CHATSTATES, xmpp.NS_LAST, xmpp.NS_CHAT_MARKERS, xmpp.NS_OOB} diff --git a/library/longpoll.py b/library/longpoll.py index cd47df5..e62b1e0 100644 --- a/library/longpoll.py +++ b/library/longpoll.py @@ -116,8 +116,9 @@ def processPollResult(user, data): attachments = None if not out: if not attachments and not chat: - message = [{"out": 0, "user_id": uid, "id": mid, "date": date, "body": body}] - utils.runThread(user.sendMessages, (False, message, mid, uid), "sendMessages-%s" % user.source) + message = [{"out": 0, "from_id": uid, "id": mid, "date": date, "text": body}] + # we substract 1 from msg id b/c VK now has reverse history so we need to ask what happened before this exact message + utils.runThread(user.sendMessages, (False, message, mid - 1, uid), "sendMessages-%s" % user.source) elif typ == TYPE_MSG_READ_OUT: uid, mid = evt diff --git a/library/vkapi.py b/library/vkapi.py index c32284e..05188e0 100644 --- a/library/vkapi.py +++ b/library/vkapi.py @@ -31,7 +31,7 @@ APP_ID = 3789129 # VK APP scope SCOPE = 69638 # VK API VERSION -API_VERSION = "5.21" +API_VERSION = "5.120" socket.setdefaulttimeout(SOCKET_TIMEOUT) @@ -48,13 +48,28 @@ ERRORS = (httplib.BadStatusLine, METHOD_THROUGHPUT = 3.0 -# Trying to use faster library usjon instead of simplejson +# VK API error codes +UNKNOWN_ERROR = 1 +TOO_FAST_ERROR = 6 +FLOOD_CONTROL_ERROR = 9 +NOT_ALLOWED_ERROR = 7 +INTERNAL_SERVER_ERROR = 10 +RUNTIME_ERROR = 13 +CAPTCHA_NEEDED_ERROR = 14 +ACCESS_DENIED_ERROR = 15 +VALIDATION_REQUIRED_ERROR = 17 +WRONG_METHOD_OR_PARAM_ERROR = 100 + + +ERRNO_NETWORK_IS_UNREACHABLE = 101 +ERRNO_CONNECTION_RESET_BY_PEER = 104 + +# Try to use faster library usjon instead of simplejson try: import ujson as json - logger.debug("vkapi: using ujson instead of simplejson") except ImportError: import json - logger.warning("vkapi: ujson wasn't loaded, using simplejson instead") + def repeat(maxRetries, resultType, *errors): @@ -82,10 +97,11 @@ def repeat(maxRetries, resultType, *errors): else: break else: + logger.critical("network error: ") errno = getattr(exc, "errno", 0) - if errno == 101: + if errno == ERRNO_NETWORK_IS_UNREACHABLE: raise NetworkNotFound() - elif errno == 104: + elif errno == ERRNO_CONNECTION_RESET_BY_PEER: raise NetworkError() data = resultType() logger.warning("vkapi: Error %s occurred on executing %s(*%s, **%s)", @@ -101,6 +117,7 @@ def repeat(maxRetries, resultType, *errors): return decorator + class AsyncHTTPRequest(httplib.HTTPSConnection): """ A method to make asynchronous http requests @@ -294,7 +311,7 @@ class PasswordLogin(RequestProcessor): class APIBinding(RequestProcessor): """ Provides simple VK API binding - Translates VK errors to python exceptions + Converts VK errors to Python exceptions """ def __init__(self, token, debug=None, logline=""): self.token = token @@ -302,7 +319,7 @@ class APIBinding(RequestProcessor): self.last = [] self.captcha = {} self.lastMethod = () - self.delay = 1.00 + self.delay = 1.25 # to use it in logs without showing the token self.logline = logline RequestProcessor.__init__(self) @@ -311,7 +328,7 @@ class APIBinding(RequestProcessor): def __delay(self): """ Delaying method execution to prevent "too fast" errors from happening - Typically VK allows us execution of 3 methods per second. + Typically VK allows execution of 3 methods per second. """ self.last.append(time.time()) if len(self.last) > 2: @@ -321,7 +338,7 @@ class APIBinding(RequestProcessor): def method(self, method, values=None, notoken=False): """ - Issues a VK method + Executes a VK method Args: method: vk method values: method parameters @@ -378,30 +395,34 @@ class APIBinding(RequestProcessor): logger.error("vkapi: error occured on executing method" " (%s(%s), code: %s, msg: %s), (for: %s)" % (method, values, eCode, eMsg, self.logline)) - if eCode == 7: # not allowed + + if eCode == NOT_ALLOWED_ERROR: # not allowed raise NotAllowed(eMsg) - elif eCode == 10: # internal server error + elif eCode == INTERNAL_SERVER_ERROR: # internal server error raise InternalServerError(eMsg) - elif eCode == 13: # runtime error + elif eCode == RUNTIME_ERROR: # runtime error raise RuntimeError(eMsg) - elif eCode == 14: # captcha + elif eCode == CAPTCHA_NEEDED_ERROR: # captcha if "captcha_sid" in error: self.captcha = {"sid": error["captcha_sid"], "img": error["captcha_img"]} raise CaptchaNeeded() - elif eCode == 15: + elif eCode == ACCESS_DENIED_ERROR: raise AccessDenied(eMsg) - elif eCode == 17: + elif eCode == VALIDATION_REQUIRED_ERROR: raise ValidationRequired(eMsg) # 1 - unknown error / 100 - wrong method or parameters loss # todo: where we going we NEED constants - elif eCode in (1, 6, 9, 100): - if eCode in (6, 9): # 6 - too fast / 9 - flood control + elif eCode in (UNKNOWN_ERROR, + TOO_FAST_ERROR, + FLOOD_CONTROL_ERROR, + WRONG_METHOD_OR_PARAM_ERROR): + if eCode in (TOO_FAST_ERROR, FLOOD_CONTROL_ERROR): self.delay += 0.15 # logger doesn't seem to support %0.2f logger.warning("vkapi: got code %s, increasing timeout to %0.2f (for: %s)" % |