Beispiel #1
0
    def method(self, method, args=None, force=False, notoken=False):
        """
		This is a duplicate function of self.engine.method
		Needed to handle errors properly exactly in __main__
		Args:
			method: a VK API method
			args: method arguments
			force: whether to force execution (ignore self.online and captcha)
			notoken: whether to cut the token from the request
		Returns:
			The method execution result
		See library/vkapi.py for more information about exceptions
		"""
        args = args or {}
        result = {}
        self.methods += 1
        Stats["method"] += 1
        if not self.engine.captcha and (self.online or force):
            try:
                result = self.engine.method(method, args, notoken=notoken)
            except (api.InternalServerError, api.AccessDenied) as e:
                if force:
                    raise

            except api.CaptchaNeeded as e:
                executeHandlers("evt04", (self.source, self.engine.captcha))
                self.online = False

            except api.NetworkNotFound as e:
                self.online = False

            except api.NotAllowed as e:
                if self.engine.lastMethod[0] == "messages.send":
                    sendMessage(
                        self.source, vk2xmpp(args.get("user_id", TransportID)),
                        _("You're not allowed to perform this action."))

            except api.VkApiError as e:
                # There are several types of VkApiError
                # But the user definitely must be removed.
                # The question is: how?
                # Should we completely exterminate them or just remove?
                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.":
                    roster = True
                elif m == "User authorization failed: invalid access_token.":
                    sendMessage(self.source, TransportID,
                                m + " Please, register again")
                utils.runThread(removeUser, (self.source, roster))
                logger.error("VK: apiError %s (jid: %s)", m, self.source)
                self.online = False
            else:
                return result
            logger.error(
                "VK: error %s occurred while executing"
                " method(%s) (%s) (jid: %s)", e.__class__.__name__, method,
                e.message, self.source)
            return result
Beispiel #2
0
	def initialize(self, force=False, send=True, resource=None, first=False):
		"""
		Initializes user after the connection has been completed
		Args:
			force: force sending subscription presence
			send: whether to send the init presence
			resource: add resource in self.resources to prevent unneeded stanza sending
			first: whether to initialize the user for the first time (during registration)
		"""
		logger.debug("User: beginning user initialization (jid: %s)", self.source)
		Users[self.source] = self
		if not self.friends:
			self.friends = self.vk.getFriends()
		if force or not self.rosterSet:
			logger.debug("User: sending subscription presence with force:%s (jid: %s)",
				force, self.source)
			import rostermanager
			rostermanager.Roster.checkRosterx(self, resource)
		if send:
			self.sendInitPresence()
		if resource:
			self.resources.add(resource)
		utils.runThread(self.vk.getUserPreferences)
		if first:
			self.sendMessages(True, filter_="unread")
		else:
			self.sendMessages(True)
		Poll.add(self)
		utils.runThread(executeHandlers, ("evt05", (self,)))
Beispiel #3
0
	def initialize(self, force=False, send=True, resource=None):
		"""
		Initializes user after self.connect() is done:
			1. Receives friends list and set 'em to self.friends
			2. If #1 is done and roster is not yet set (self.rosterSet)
				then sends a subscription presence
			3. Calls sendInitPresnece() if parameter send is True
			4. Adds resource if resource parameter exists
		Parameters:
			force: force sending subscription presence
			send: needed to know if need to send init presence or not
			resource: add resource in self.resources to prevent unneeded stanza sending
		"""
		logger.debug("User: called init for user %s", self.source)
		Transport[self.source] = self
		if not self.friends:
			self.friends = self.vk.getFriends()
		if self.friends and not self.rosterSet or force:
			logger.debug("User: sending subscription presence with force:%s (jid: %s)",
				force, self.source)
			import rostermanager
			rostermanager.Roster.checkRosterx(self, resource)
		if send:
			self.sendInitPresence()
		if resource:
			self.resources.add(resource)
		utils.runThread(self.vk.getUserID)
		Poll.add(self)
		self.sendMessages(True)
		utils.runThread(executeHandlers, ("evt05", (self,)))
Beispiel #4
0
    def initialize(self, force=False, send=True, resource=None, first=False):
        """
		Initializes user after the connection has been completed
		Args:
			force: force sending subscription presence
			send: whether to send the init presence
			resource: add resource in self.resources to prevent unneeded stanza sending
			first: whether to initialize the user for the first time (during registration)
		"""
        logger.debug("User: beginning user initialization (jid: %s)",
                     self.source)
        Users[self.source] = self
        if not self.friends:
            self.friends = self.vk.getFriends()
        if force or not self.rosterSet:
            logger.debug(
                "User: sending subscription presence with force:%s (jid: %s)",
                force, self.source)
            import rostermanager
            rostermanager.Roster.checkRosterx(self, resource)
        if send:
            self.sendInitPresence()
        if resource:
            self.resources.add(resource)
        utils.runThread(self.vk.getUserPreferences)
        if first:
            self.sendMessages(True, filter_="unread")
        else:
            self.sendMessages(True)
        Poll.add(self)
        utils.runThread(executeHandlers, ("evt05", (self, )))
Beispiel #5
0
	def method(self, method, args=None, force=False, notoken=False):
		"""
		This is a duplicate function of self.engine.method
		Needed to handle errors properly exactly in __main__
		Args:
			method: a VK API method
			args: method arguments
			force: whether to force execution (ignore self.online and captcha)
			notoken: whether to cut the token from the request
		Returns:
			The method execution result
		See library/vkapi.py for more information about exceptions
		"""
		args = args or {}
		result = {}
		self.methods += 1
		Stats["method"] += 1
		if not self.engine.captcha and (self.online or force):
			try:
				result = self.engine.method(method, args, notoken=notoken)
			except (api.InternalServerError, api.AccessDenied) as e:
				if force:
					raise

			except api.CaptchaNeeded as e:
				executeHandlers("evt04", (self.source, self.engine.captcha))
				self.online = False

			except api.NetworkNotFound as e:
				self.online = False

			except api.NotAllowed as e:
				if self.engine.lastMethod[0] == "messages.send":
					sendMessage(self.source,
						vk2xmpp(args.get("user_id", TransportID)),
						_("You're not allowed to perform this action."))

			except api.VkApiError as e:
				# There are several types of VkApiError
				# But the user definitely must be removed.
				# The question is: how?
				# Should we completely exterminate them or just remove?
				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.":
					roster = True
				elif m == "User authorization failed: invalid access_token.":
					sendMessage(self.source, TransportID,
						m + " Please, register again")
				utils.runThread(removeUser, (self.source, roster))
				logger.error("VK: apiError %s (jid: %s)", m, self.source)
				self.online = False
			else:
				return result
			logger.error("VK: error %s occurred while executing"
				" method(%s) (%s) (jid: %s)",
				e.__class__.__name__, method, e.message, self.source)
			return result
Beispiel #6
0
	def method(self, method, args=None, force=False):
		"""
		This is a duplicate function of self.engine.method
		Needed to handle errors properly exactly in __main__
		Parameters:
			method: obviously VK API method
			args: method aruments
			nodecode: decode flag (make json.loads or not)
			force: says that method will be executed even the captcha and not online
		See library/vkapi.py for more information about exceptions
		Returns method execution result
		"""
		args = args or {}
		result = {}
		Stats["method"] += 1
		if not self.engine.captcha and (self.online or force):
			try:
				result = self.engine.method(method, args)
			except (api.InternalServerError, api.AccessDenied) as e:
				if force:
					raise

			except api.CaptchaNeeded as e:
				executeHandlers("evt04", (self, self.engine.captcha["img"]))
				self.online = False

			except api.NetworkNotFound as e:
				self.online = False

			except api.NotAllowed as e:
				if self.engine.lastMethod[0] == "messages.send":
					sendMessage(Component, self.source,
						vk2xmpp(args.get("user_id", TransportID)),
						_("You're not allowed to perform this action."))

			except api.VkApiError as e:
				# There are several types of VkApiError
				# But the user defenitely must be removed.
				# The question is: how?
				# Are they should be completely exterminated or just removed?
				roster = False
				m = e.message
				# Probably should be done in vkapi.py by status codes
				if m == "User authorization failed: user revoke access for this token.":
					roster = True
				elif m == "User authorization failed: invalid access_token.":
					sendMessage(Component, self.source, TransportID,
						m + " Please, register again")
				utils.runThread(removeUser, (self.source, roster))
				logger.error("VK: apiError %s (jid: %s)", m, self.source)
				self.online = False
			else:
				return result
			logger.error("VK: error %s occurred while executing"
				" method(%s) (%s) (jid: %s)",
				e.__class__.__name__, method, e.message, self.source)
			return result
Beispiel #7
0
	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 watcher (jid: %s)" % user.source)
		utils.runThread(cls.__initPoll, (user,), "__initPoll-%s" % user.source)
Beispiel #8
0
	def processPollResult(self, opener):
		"""
		Processes poll result
		Retur codes:
			0: need to reinit poll (add user to the poll buffer)
			1: all is fine (request again)
			-1: just continue iteration, ignoring this user
				(user won't be added for the next iteration)
		"""
		if DEBUG_POLL:
			logger.debug("longpoll: processing result (jid: %s)", self.source)

		if self.vk.engine.captcha:
			return -1

		data = None
		try:
			data = opener.read()
			data = json.loads(data)
		except (ValueError, httplib.BadStatusLine, socket.error):
			return 1

		if not data:
			logger.error("longpoll: no data. Gonna request again")
			return 1

		if "failed" in data:
			logger.debug("longpoll: failed. Searching for a new server (jid: %s)",
				self.source)
			return 0

		self.vk.pollConfig["ts"] = data["ts"]
		for evt in data.get("updates", ()):
			typ = evt.pop(0)

			if typ == 4:  # new message
				utils.runThread(self.sendMessages, name="sendMessages-%s" % self.source)

			elif typ == 8:  # user has joined
				if not self.settings.i_am_ghost:
					uid = abs(evt[0])
					key = "name"
					if self.settings.use_nicknames:
						key = "screen_name"
					sendPresence(self.source, vk2xmpp(uid),
						nick=self.vk.getUserData(uid)[key], caps=True)

			elif typ == 9:  # user has left
				uid = abs(evt[0])
				sendPresence(self.source, vk2xmpp(uid), "unavailable")

			elif typ == 61:  # user is typing
				if evt[0] not in self.typing:
					sendMessage(Component, self.source, vk2xmpp(evt[0]), typ="composing")
				self.typing[evt[0]] = time.time()
		return 1
Beispiel #9
0
	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)
Beispiel #10
0
	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
		Read processPollResult.__doc__ to learn more about status codes
		"""
		while ALIVE:
			socks = cls.__list.keys()
			if not socks:
				time.sleep(0.02)
				continue
			try:
				ready, error = select.select(socks, [], socks, 2)[::2]
			except (select.error, socket.error) as e:
				logger.error("longpoll: %s" % (e.message))  # debug?

			for sock in error:
				with cls.__lock:
					# We will just re-add the user to poll
					# in case if anything weird happen to the socket
					try:
						cls.__add(cls.__list.pop(sock)[0])
					except KeyError:
						continue

			for sock in ready:
				with cls.__lock:
					try:
						user, opener = cls.__list.pop(sock)
					except KeyError:
						continue

					# Check if user is still in the memory
					user = Transport.get(user.source)
					if not user:
						continue
					# Check if the user haven't left yet
					if not user.vk.online:
						continue
					utils.runThread(cls.processResult, (user, opener),
						"poll.processResult-%s" % user.source)

			with cls.__lock:
				for sock, (user, opener) in cls.__list.items():
					if not user.vk.online:
						logger.debug("longpoll: user is not online, so removing their from poll"
							" (jid: %s)" % user.source)
						try:
							del cls.__list[sock]
						except KeyError:
							pass
Beispiel #11
0
def runMainActions():
	"""
	Running main actions to make transport work
	"""
	if allowBePublic:
		makeMeKnown()
	for num, event in enumerate(Handlers["evt01"]):
		utils.runThread(event, (), "extension-%d" % num)
	utils.runThread(Poll.process, (), "longPoll")
	utils.runThread(updateCron, (), "updateCron")
	import modulemanager
	Manager = modulemanager.ModuleManager
	Manager.load(Manager.list())
Beispiel #12
0
def runMainActions():
	"""
	Running the main actions to make the transport work
	"""
	for num, event in enumerate(Handlers["evt01"]):
		utils.runThread(event, name=("extension-%d" % num))
	utils.runThread(Poll.process, name="longPoll")
	utils.runThread(updateCron)
	import modulemanager
	Manager = modulemanager.ModuleManager
	Manager.load(Manager.list())
	global USER_CAPS_HASH, TRANSPORT_CAPS_HASH
	USER_CAPS_HASH = computeCapsHash(UserFeatures)
	TRANSPORT_CAPS_HASH = computeCapsHash(TransportFeatures)
Beispiel #13
0
def runMainActions():
	"""
	Runs the actions for the gateway to work well
	Initializes extensions, longpoll and modules
	Computes required hashes
	"""
	for num, event in enumerate(Handlers["evt01"]):
		utils.runThread(event, name=("extension-%d" % num))
	utils.runThread(Poll.process, name="longPoll")
	utils.runThread(updateCron)
	import modulemanager
	Manager = modulemanager.ModuleManager
	Manager.load(Manager.list())
	global USER_CAPS_HASH, TRANSPORT_CAPS_HASH
	USER_CAPS_HASH = computeCapsHash(UserFeatures)
	TRANSPORT_CAPS_HASH = computeCapsHash(TransportFeatures)
Beispiel #14
0
def runMainActions():
    """
	Runs the actions for the gateway to work well
	Initializes extensions, longpoll and modules
	Computes required hashes
	"""
    for num, event in enumerate(Handlers["evt01"]):
        utils.runThread(event, name=("extension-%d" % num))
    utils.runThread(Poll.process, name="longPoll")
    utils.runThread(updateCron)
    import modulemanager
    Manager = modulemanager.ModuleManager
    Manager.load(Manager.list())
    global USER_CAPS_HASH, TRANSPORT_CAPS_HASH
    USER_CAPS_HASH = computeCapsHash(UserFeatures)
    TRANSPORT_CAPS_HASH = computeCapsHash(TransportFeatures)
Beispiel #15
0
def processPollResult(user, data):
    """
	Processes a poll result
	Decides whether to send a chat/groupchat message or presence or just pass the iteration
	Args:
		user: the User object
		data: a valid json with poll result
	Returns:
		CODE_SKIP: just skip iteration, not adding the user to poll again
		CODE_FINE: add user for the next iteration
		CODE_ERROR: user should be added to the init buffer
	"""
    debug("longpoll: processing result (jid: %s)", user.source)

    retcode = CODE_FINE
    try:
        data = json.loads(data)
    except ValueError:
        logger.error("longpoll: no data. Gonna request again (jid: %s)",
                     user.source)
        retcode = CODE_ERROR
        return retcode

    if "failed" in data:
        logger.debug("longpoll: failed. Searching for a new server (jid: %s)",
                     user.source)
        retcode = CODE_ERROR
    else:
        user.vk.pollConfig["ts"] = data["ts"]
        for evt in data.get("updates", ()):
            typ = evt.pop(0)

            debug(
                "longpoll: got updates, processing event %s with arguments %s (jid: %s)",
                typ, str(evt), user.source)

            if typ == TYPE_MSG:  # new message
                message = None
                mid, flags, uid, date, subject, body, attachments = evt
                out = flags & FLAG_OUT
                chat = (uid > MIN_CHAT_UID
                        )  # a groupchat always has uid > 2000000000
                # there is no point to request messages if there's only a single emoji attachment
                # we actually only need to request for new messages if there are complex attachments in it (e.g. photos)
                if len(attachments) == 1 and "emoji" in attachments:
                    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 - 1, uid),
                                    "sendMessages-%s" % user.source)

            elif typ == TYPE_MSG_READ_OUT:
                uid, mid = evt
                cache = user.msgCacheByUser.get(uid)
                if cache:
                    xmppMID = cache["xmpp"]
                    cache.clear()
                    sendChatMarker(user.source, vk2xmpp(uid), xmppMID)

            elif typ == TYPE_PRS_IN:  # user has joined
                uid = abs(evt[0])
                sendPresence(user.source, vk2xmpp(uid), hash=USER_CAPS_HASH)

            elif typ == TYPE_PRS_OUT:  # user has left
                uid = abs(evt[0])
                sendPresence(user.source, vk2xmpp(uid), "unavailable")

            elif typ == TYPE_TYPING:  # user is typing
                uid = evt[0]
                if uid not in user.typing:
                    sendMessage(user.source, vk2xmpp(uid), typ="composing")
                user.typing[uid] = time.time()
            retcode = CODE_FINE
    return retcode
Beispiel #16
0
	def processPollResult(self, opener):
		"""
		Processes poll result
		Retur codes:
			0: need to reinit poll (add user to the poll buffer)
			1: all is fine (request again)
			-1: just continue iteration, ignoring this user
				(user won't be added for the next iteration)
		"""
		if DEBUG_POLL:
			logger.debug("longpoll: processing result (jid: %s)", self.source)

		if self.vk.engine.captcha:
			return -1

		data = None
		try:
			data = opener.read()
		except (httplib.BadStatusLine, socket.error, socket.timeout) as e:
			logger.warning("longpoll: got error `%s` (jid: %s)", e.__class__.__name__,
				self.source)
			return 0
		try:
			data = json.loads(data)
			if not data:
				raise ValueError()
		except ValueError:
			logger.error("longpoll: no data. Gonna request again (jid: %s)",
				self.source)
			return 1

		if "failed" in data:
			logger.debug("longpoll: failed. Searching for a new server (jid: %s)",
				self.source)
			return 0

		self.vk.pollConfig["ts"] = data["ts"]

		for evt in data.get("updates", ()):
			typ = evt.pop(0)

			if DEBUG_POLL:
				logger.debug("longpoll: got updates, processing event %s with arguments %s (jid: %s)", typ, str(evt), self.source)

			if typ == 4:  # new message
				if len(evt) == 7:
					message = None
					mid, flags, uid, date, subject, body, attachments = evt
					out = flags & 2 == 2
					chat = uid > 2000000000  # a groupchat always has uid > 2000000000
					if not out:
						if not attachments and not chat:
							message = [{"out": 0, "user_id": uid, "id": mid, "date": date, "body": body}]
						utils.runThread(self.sendMessages, (None, message), "sendMessages-%s" % self.source)
				else:
					logger.warning("longpoll: incorrect events number while trying to process arguments %s (jid: %s)", str(evt), self.source)

			elif typ == 8:  # user has joined
				uid = abs(evt[0])
				sendPresence(self.source, vk2xmpp(uid), hash=USER_CAPS_HASH)

			elif typ == 9:  # user has left
				uid = abs(evt[0])
				sendPresence(self.source, vk2xmpp(uid), "unavailable")

			elif typ == 61:  # user is typing
				if evt[0] not in self.typing:
					sendMessage(self.source, vk2xmpp(evt[0]), typ="composing")
				self.typing[evt[0]] = time.time()
		return 1
Beispiel #17
0
def processPollResult(user, data):
    """
	Processes a poll result
	Decides whether to send a chat/groupchat message or presence or just pass the iteration
	Args:
		user: the User object
		data: a valid json with poll result
	Returns:
		CODE_SKIP: just skip iteration, not adding the user to poll again
		CODE_FINE: add user for the next iteration
		CODE_ERROR: user should be added to the init buffer
	"""
    debug("longpoll: processing result (jid: %s)", user.source)

    retcode = CODE_FINE
    try:
        data = json.loads(data)
    except ValueError:
        logger.error("longpoll: no data. Gonna request again (jid: %s)",
                     user.source)
        retcode = CODE_ERROR
        return retcode

    if "failed" in data:
        logger.debug("longpoll: failed. Searching for a new server (jid: %s)",
                     user.source)
        retcode = CODE_ERROR
    else:
        user.vk.pollConfig["ts"] = data["ts"]
        for evt in data.get("updates", ()):
            typ = evt.pop(0)

            debug(
                "longpoll: got updates, processing event %s with arguments %s (jid: %s)",
                typ, str(evt), user.source)

            if typ == TYPE_MSG:  # new message
                if len(evt) == 7:
                    message = None
                    mid, flags, uid, date, subject, body, attachments = evt
                    out = flags & FLAG_OUT
                    chat = (uid > MIN_CHAT_UID
                            )  # a groupchat always has uid > 2000000000
                    if not out:
                        if not attachments and not chat:
                            message = [
                                1, {
                                    "out": 0,
                                    "uid": uid,
                                    "mid": mid,
                                    "date": date,
                                    "body": body
                                }
                            ]
                        utils.runThread(user.sendMessages, (None, message),
                                        "sendMessages-%s" % user.source)
                else:
                    logger.warning(
                        "longpoll: incorrect events number while trying to "
                        "process arguments %s (jid: %s)", str(evt),
                        user.source)

            elif typ == TYPE_PRS_IN:  # user has joined
                uid = abs(evt[0])
                sendPresence(user.source, vk2xmpp(uid), hash=USER_CAPS_HASH)

            elif typ == TYPE_PRS_OUT:  # user has left
                uid = abs(evt[0])
                sendPresence(user.source, vk2xmpp(uid), "unavailable")

            elif typ == TYPE_TYPING:  # user is typing
                uid = evt[0]
                if uid not in user.typing:
                    sendMessage(user.source, vk2xmpp(uid), typ="composing")
                user.typing[uid] = time.time()
            retcode = CODE_FINE
    return retcode