diff options
author | John Smith <mrdoctorwho@gmail.com> | 2016-11-02 08:33:43 +0300 |
---|---|---|
committer | John Smith <mrdoctorwho@gmail.com> | 2016-11-02 08:33:43 +0300 |
commit | bbc960130ad0e7550feaed76d4121e269731494f (patch) | |
tree | a2dae5eb308b4415fb10e342eb463f279c8f6216 | |
parent | 32b5e6b62974177edb961a65f296d6555d3b191b (diff) |
Code cleanup, fix NameError in groupchats
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | Config_example.txt | 10 | ||||
-rw-r--r-- | extensions/groupchats.py | 4 | ||||
-rw-r--r-- | gateway.py | 3 | ||||
-rw-r--r-- | library/longpoll.py | 134 | ||||
-rw-r--r-- | library/settings.py | 15 | ||||
-rw-r--r-- | library/vkapi.py | 26 |
7 files changed, 107 insertions, 90 deletions
@@ -5,6 +5,9 @@ pidFile.txt # exclude custom users.db names *users.db vk4xmpp.log +vk4xmpp.db +vk4xmpp.sqlite +vk4xmpp.pid # exclude log file created after init.d/vk4xmpp start gateway.log gateway_v5.0.py @@ -12,4 +15,4 @@ gateway_v5.0.py .*project # exclude ~ bak files *~ -/.settings
+/.settings diff --git a/Config_example.txt b/Config_example.txt index dbf8e15..138d697 100644 --- a/Config_example.txt +++ b/Config_example.txt @@ -72,19 +72,19 @@ URL_VCARD_NO_IMAGE = "https://raw.githubusercontent.com/mrDoctorWho/vk4xmpp/mast THREAD_STACK_SIZE = 0 # Database file (anything you like). -DatabaseFile = "/var/lib/vk4xmpp/vk4xmpp.db" +DatabaseFile = "vk4xmpp.sqlite" # File to store PID in. -pidFile = "/run/vk4xmpp/vk4xmpp.pid" +pidFile = "vk4xmpp.pid" # Log file. -logFile = "/var/log/vk4xmpp/vk4xmpp.log" +logFile = "vk4xmpp.log" # Directory where transport will write crash logs. -crashDir = "/var/log/vk4xmpp/crash" +crashDir = "crash" # Directory for users settings. -settingsDir = "/var/lib/vk4xmpp/settings" +settingsDir = "settings" # Stanza send interval (in seconds). STANZA_SEND_INTERVAL = 0.03125 diff --git a/extensions/groupchats.py b/extensions/groupchats.py index 467748d..28bbd26 100644 --- a/extensions/groupchats.py +++ b/extensions/groupchats.py @@ -144,7 +144,7 @@ def handleOutgoingChatMessage(user, vkChat): # 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)" % self.source) + 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 @@ -164,7 +164,7 @@ def handleOutgoingChatMessage(user, vkChat): if not chat.created: if chat.creation_failed: return None - # 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() function to prevent losing or messing up the messages chat.create(user) # read the comments above the handleMessage function if not chat.created: @@ -311,8 +311,7 @@ class VK(object): """ if not self.pollInitialized: raise api.LongPollError("The Poll wasn't initialized yet") - opener = api.AsyncHTTPRequest.getOpener(self.pollServer, self.pollConfig) - return opener + return api.AsyncHTTPRequest.getOpener(self.pollServer, self.pollConfig) def method(self, method, args=None, force=False, notoken=False): """ diff --git a/library/longpoll.py b/library/longpoll.py index 3470323..7970feb 100644 --- a/library/longpoll.py +++ b/library/longpoll.py @@ -1,11 +1,8 @@ # coding: utf-8 -# © simpleApps, 2014 — 2015. +# © simpleApps, 2014 — 2016. -# Big THANKS to AlKogrun who made it possible -# to write a single-threaded longpoll client - -__authors__ = ("AlKorgun <alkorgun@gmail.com>", "mrDoctorWho <mrdoctorwho@gmail.com>") -__version__ = "2.2.1" +__authors__ = ("Al Korgun <alkorgun@gmail.com>", "John Smith <mrdoctorwho@gmail.com>") +__version__ = "2.2.2" __license__ = "MIT" """ @@ -24,6 +21,7 @@ LONGPOLL_RETRY_COUNT = 10 LONGPOLL_RETRY_TIMEOUT = 10 +# TODO: make it an abstract, to reuse in Steampunk class Poll(object): """ Class used to handle longpoll @@ -31,6 +29,7 @@ class Poll(object): __list = {} __buff = set() __lock = threading.Lock() + clear = staticmethod(__list.clear) @classmethod def __add(cls, user): @@ -39,24 +38,18 @@ class Poll(object): Adds user in buffer on error occurred Adds user in self.__list if no errors """ - if DEBUG_POLL: - logger.debug("longpoll: really adding user to poll (jid: %s)", user.source) - opener = user.vk.makePoll() - if DEBUG_POLL: - logger.debug("longpoll: user has been added to poll (jid: %s)", user.source) - cls.__list[opener.sock] = (user, opener) - return opener - - @classmethod - def __addToBuff(cls, user): - """ - Adds user to the list of "bad" users - The list is mostly contain users whose poll - request was failed for some reasons - """ - cls.__buff.add(user) - logger.debug("longpoll: adding user to the init buffer (jid: %s)", user.source) - utils.runThread(cls.__initPoll, (user,), "__initPoll-%s" % user.source) + if user.source in Transport: + # in case the new instance was created + user = Transport[user.source] + opener = user.vk.makePoll() + if DEBUG_POLL: + logger.debug("longpoll: user has been added to poll (jid: %s)", user.source) + if opener: + cls.__list[opener.sock] = (user, opener) + return opener + logger.warning("longpoll: got null opener! (jid: %s)", user.source) + cls.__addToBuffer(user) + return None @classmethod def add(cls, some_user): @@ -68,52 +61,77 @@ class Poll(object): with cls.__lock: if some_user in cls.__buff: return None + # check if someone tries to add an already existing user for sock, (user, opener) in cls.__list.iteritems(): if some_user == user: break else: try: cls.__add(some_user) - except Exception as e: - if not isinstance(e, api.LongPollError): - crashLog("poll.add") + except api.LongPollError: logger.error("longpoll: failed to make poll (jid: %s)", some_user.source) - cls.__addToBuff(some_user) + cls.__addToBuffer(some_user) + except Exception: + crashLog("poll.add") - clear = staticmethod(__list.clear) + @classmethod + def __addToBuffer(cls, user): + """ + Adds user to the list of "bad" users + The list is mostly contain users whose poll + request was failed for some reasons + Args: + user: the user object + """ + cls.__buff.add(user) + logger.debug("longpoll: adding user to the init buffer (jid: %s)", user.source) + utils.runThread(cls.handleUser, (user,), "handleBuffer-%s" % user.source) + + @classmethod + def __removeFromBuffer(cls, user): + """ + Instantly removes a user from the buffer + Args: + user: the user object + """ + if user in cls.__buff: + cls.__buff.remove(user) + + @classmethod + def removeFromBuffer(cls, user): + """ + Removes a user from the buffer + Args: + user: the user object + """ + with cls.__lock: + cls.__removeFromBuffer(user) @classmethod - def __initPoll(cls, user): + def handleUser(cls, user): """ - Tries to reinitialize poll if needed in 10 times (each 10 seconds) - As soon as poll initialized user will be removed from buffer + Tries to reinitialize poll for LONGPOLL_RETRY_COUNT every LONGPOLL_RETRY_TIMEOUT seconds + As soon as poll is initialized the user will be removed from buffer + Args: + user: the user object """ - for x in xrange(LONGPOLL_RETRY_COUNT): - if user.source not in Transport: + for i in xrange(LONGPOLL_RETRY_COUNT): + if user.source in Transport: + user = Transport[user.source] # we might have a new instance here + if user.vk.initPoll(): + with cls.__lock: + logger.debug("longpoll: successfully initialized longpoll (jid: %s)", user.source) + cls.__add(user) + cls.__removeFromBuffer(user) + break + else: logger.debug("longpoll: while we were wasting our time" ", the user has left (jid: %s)", user.source) - with cls.__lock: - if user in cls.__buff: - cls.__buff.remove(user) + cls.removeFromBuffer(user) return None - - if Transport[user.source].vk.initPoll(): - with cls.__lock: - logger.debug("longpoll: successfully initialized longpoll" - " (jid: %s)", user.source) - if user not in cls.__buff: - return None - cls.__buff.remove(user) - # Check if user still in transport when we finally came down here - if user.source in Transport: - cls.__add(Transport[user.source]) - break time.sleep(LONGPOLL_RETRY_TIMEOUT) else: - with cls.__lock: - if user not in cls.__buff: - return None - cls.__buff.remove(user) + cls.removeFromBuffer(user) logger.error("longpoll: failed to add user to poll in 10 retries" " (jid: %s)", user.source) @@ -121,8 +139,7 @@ class Poll(object): def process(cls): """ Processes poll sockets by select.select() - As soon as socket will be ready to be read - will be called user.processPollResult() function + As soon as socket will be ready for reading, user.processPollResult() is called Read processPollResult.__doc__ to learn more about status codes """ while ALIVE: @@ -153,12 +170,8 @@ class Poll(object): except KeyError: continue - # Check if user is still in the memory + # Update the user instance user = Transport.get(user.source) - # Check if the user haven't left yet - if not hasattr(user, "vk") or not user.vk.online: - continue - utils.runThread(cls.processResult, (user, opener), "poll.processResult-%s" % user.source) @@ -191,4 +204,3 @@ class Poll(object): user.vk.pollInitialized = False cls.add(user) - diff --git a/library/settings.py b/library/settings.py index 6e9524a..893753a 100644 --- a/library/settings.py +++ b/library/settings.py @@ -1,12 +1,12 @@ # coding: utf-8 # This file is a part of VK4XMPP transport -# © simpleApps, 2015. +# © simpleApps, 2015 — 2016. """ Provides a way to manage user's and transport's settings """ -__author__ = "mrDoctorWho <mrdoctorwho@gmail.com>" +__author__ = "John Smith <mrdoctorwho@gmail.com>" from __main__ import settingsDir, rFile, wFile from copy import deepcopy @@ -19,8 +19,8 @@ GLOBAL_USER_SETTINGS = {"keep_online": {"label": "Keep my status online", "use_nicknames": {"label": "Use nicknames instead of real names", "value": 0}} -TRANSPORT_SETTINGS = {"send_unavailable": {"label": "Send unavailable from " \ - "friends when user logs off", +TRANSPORT_SETTINGS = {"send_unavailable": {"label": "Send unavailable from " + "friends when a user logs off", "value": 0}} @@ -38,7 +38,7 @@ class Settings(object): self.settings = deepcopy(GLOBAL_USER_SETTINGS) else: self.settings = TRANSPORT_SETTINGS - userSettings = eval(rFile(self.filename)) or {} + userSettings = eval(rFile(self.filename)) or {} # TODO: json for key, values in userSettings.iteritems(): if key in self.settings: self.settings[key]["value"] = values["value"] @@ -62,10 +62,7 @@ class Settings(object): return self.settings[attr]["value"] elif not hasattr(self, attr): return False - elif not self.settings.has_key(attr): - return False - else: - return object.__getattribute__(self, attr) + return object.__getattribute__(self, attr) def exterminate(self): """ diff --git a/library/vkapi.py b/library/vkapi.py index 86fc60f..3546684 100644 --- a/library/vkapi.py +++ b/library/vkapi.py @@ -78,7 +78,7 @@ def attemptTo(maxRetries, resultType, *errors): else: break else: - if hasattr(exc, "errno") and exc.errno == 101: + if getattr(exc, "errno", 0) == 101: raise NetworkNotFound() data = resultType() logger.warning("vkapi: Error %s occurred on executing %s(*%s, **%s)", @@ -96,10 +96,9 @@ def attemptTo(maxRetries, resultType, *errors): class AsyncHTTPRequest(httplib.HTTPSConnection): """ - A method to make asynchronous http request + A method to make asynchronous http requests Provides a way to get a socket object to use in select() """ - def __init__(self, url, data=None, headers=(), timeout=SOCKET_TIMEOUT): host = urllib.splithost(urllib.splittype(url)[1])[0] httplib.HTTPSConnection.__init__(self, host, timeout=timeout) @@ -125,9 +124,10 @@ class AsyncHTTPRequest(httplib.HTTPSConnection): self.close() @classmethod - def getOpener(cls, url, query={}): + def getOpener(cls, url, query=None): """ Opens a connection to url and returns AsyncHTTPRequest() object + Args: query a dict() of query parameters """ if query: url += "?%s" % urllib.urlencode(query) @@ -190,7 +190,7 @@ class RequestProcessor(object): return request @attemptTo(REQUEST_RETRIES, tuple, *ERRORS) - def post(self, url, data="", urlencode=True): + def post(self, url, data=None, urlencode=True): """ POST request """ @@ -198,9 +198,11 @@ class RequestProcessor(object): body = resp.read() return (body, resp) - def get(self, url, query={}): + def get(self, url, query=None): """ GET request + Args: + query: a dict() of query parameters """ if query: url += "?%s" % urllib.urlencode(query) @@ -287,7 +289,7 @@ class APIBinding(RequestProcessor): Translates VK errors to python exceptions Allows to make a password authorization """ - def __init__(self, token, debug=[], logline=""): + def __init__(self, token, debug=None, logline=""): self.token = token self.debug = debug self.last = [] @@ -301,9 +303,12 @@ class APIBinding(RequestProcessor): def method(self, method, values=None, notoken=False): """ Issues a VK method - Parameters: + Args: method: vk method values: method parameters + notoken: whether to cut the token out of the request + Returns: + The method execution result """ url = "https://api.vk.com/method/%s" % method values = values or {} @@ -379,6 +384,7 @@ class APIBinding(RequestProcessor): 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 self.timeout += 0.05 @@ -409,7 +415,7 @@ class APIBinding(RequestProcessor): class NetworkNotFound(Exception): """ - This happens in a very weird situations + This happens in very weird situations Happened just once at 10.01.2014 (vk.com was down) """ pass @@ -479,4 +485,4 @@ class ValidationRequired(VkApiError): Happens if VK thinks we're logging in from an unusual location """ - pass
\ No newline at end of file + pass |