Ejemplo n.º 1
0
	def serve_once(self):
		self.driver = Driver({
			'scheme': self._scheme,
			'url': self.url,
			'port': self._port,
			'verify': not self.insecure,
			'timeout': self.timeout,
			'login_id': self._login,
			'password': self._password,
			'token': self._personal_access_token,
			'mfa_token': self._mfa_token
		})
		self.driver.login()

		self.teamid = self.driver.teams.get_team_by_name(name=self.team)['id']
		userid = self.driver.users.get_user(user_id='me')['id']

		self.token = self.driver.client.token

		self.bot_identifier = MattermostPerson(self.driver, userid=userid, teamid=self.teamid)

		# noinspection PyBroadException
		try:
			loop = self.driver.init_websocket(event_handler=self.mattermost_event_handler)
			self.reset_reconnection_count()
			loop.run_forever()
		except KeyboardInterrupt:
			log.info("Interrupt received, shutting down..")
			return True
		except Exception:
			log.exception("Error reading from RTM stream:")
		finally:
			log.debug("Triggering disconnect callback")
			self.disconnect_callback()
Ejemplo n.º 2
0
	def build_identifier(self, txtrep):
		"""
		Convert a textual representation into a :class:`~MattermostPerson` or :class:`~MattermostRoom`

		Supports strings with the following formats::

			@username
			~channelname
			channelid
		"""
		txtrep = txtrep.strip()
		if txtrep.startswith('~'):
			# Channel
			channelid = self.channelname_to_channelid(txtrep[1:])
			if channelid is not None:
				return MattermostRoom(channelid=channelid, teamid=self.teamid, bot=self)
		else:
			# Assuming either a channelid or a username
			if txtrep.startswith('@'):
				# Username
				userid = self.username_to_userid(txtrep[1:])
			else:
				# Channelid
				userid = txtrep

			if userid is not None:
				return MattermostPerson(
					self.driver,
					userid=userid,
					channelid=self.get_direct_channel(self.userid, userid)['id'],
					teamid=self.teamid
				)
		raise Exception(
			'Invalid or unsupported Mattermost identifier: %s' % txtrep
		)
Ejemplo n.º 3
0
	def _status_change_event_handler(self, message):
		"""Event handler for the 'presence_change' event"""
		idd = MattermostPerson(self.driver, message['data']['user_id'])
		status = message['data']['status']
		if status == 'online':
			status = ONLINE
		elif status == 'away':
			status = AWAY
		else:
			log.error(
				"It appears the Mattermost API changed, I received an unknown status type %s" % status
			)
			status = ONLINE
		self.callback_presence(Presence(identifier=idd, status=status))
Ejemplo n.º 4
0
	def _message_event_handler(self, message):
		log.debug(message)
		data = message['data']

		# In some cases (direct messages) team_id is an empty string
		if data['team_id'] != '' and self.teamid != data['team_id']:
			log.info("Message came from another team ({}), ignoring...".format(data['team_id']))
			return

		broadcast = message['broadcast']

		if 'channel_id' in data:
			channelid = data['channel_id']
		elif 'channel_id' in broadcast:
			channelid = broadcast['channel_id']
		else:
			log.error("Couldn't find a channelid for event {}".format(message))
			return

		channel_type = data['channel_type']

		if channel_type != 'D':
			channel = data['channel_name']
		else:
			channel = channelid

		text = ''
		post_id = ''
		file_ids = None
		userid = None

		if 'post' in data:
			post = json.loads(data['post'])
			text = post['message']
			userid = post['user_id']
			if 'file_ids' in post:
				file_ids = post['file_ids']
			post_id = post['id']
			if 'type' in post and post['type'] == 'system_add_remove':
				log.info("Ignoring message from System")
				return

		if 'user_id' in data:
			userid = data['user_id']

		if not userid:
			log.error('No userid in event {}'.format(message))
			return

		mentions = []
		if 'mentions' in data:
			# TODO: Only user, not channel mentions are in here at the moment
			mentions = self.mentions_build_identifier(json.loads(data['mentions']))

		# Thread root post id
		root_id = post.get('root_id')
		if root_id is '':
			root_id = post_id

		msg = Message(
			text,
			extras={
				'id': post_id,
				'root_id': root_id,
				'mattermost_event': message,
				'url': '{scheme:s}://{domain:s}:{port:s}/{teamname:s}/pl/{postid:s}'.format(
					scheme=self.driver.options['scheme'],
					domain=self.driver.options['url'],
					port=str(self.driver.options['port']),
					teamname=self.team,
					postid=post_id
				)
			}
		)
		if file_ids:
			msg.extras['attachments'] = file_ids

		# TODO: Slack handles bots here, but I am not sure if bot users is a concept in mattermost
		if channel_type == 'D':
			msg.frm = MattermostPerson(self.driver, userid=userid, channelid=channelid, teamid=self.teamid)
			msg.to = MattermostPerson(
				self.driver, userid=self.bot_identifier.userid, channelid=channelid, teamid=self.teamid)
		elif channel_type == 'O' or channel_type == 'P':
			msg.frm = MattermostRoomOccupant(self.driver, userid=userid, channelid=channelid, teamid=self.teamid, bot=self)
			msg.to = MattermostRoom(channel, teamid=self.teamid, bot=self)
		else:
			log.warning('Unknown channel type \'{}\'! Unable to handle {}.'.format(
				channel_type,
				channel
			))
			return

		self.callback_message(msg)

		if mentions:
			self.callback_mention(msg, mentions)
    def _message_event_handler(self, message):
        log.debug(message)
        data = message["data"]

        # In some cases (direct messages) team_id is an empty string
        if data["team_id"] != "" and self.teamid != data["team_id"]:
            log.info("Message came from another team ({}), ignoring...".format(
                data["team_id"]))
            return

        broadcast = message["broadcast"]

        if "channel_id" in data:
            channelid = data["channel_id"]
        elif "channel_id" in broadcast:
            channelid = broadcast["channel_id"]
        else:
            log.error("Couldn't find a channelid for event {}".format(message))
            return

        channel_type = data["channel_type"]

        if channel_type != "D":
            channel = data["channel_name"]
        else:
            channel = channelid

        text = ""
        post_id = ""
        file_ids = None
        userid = None

        if "post" in data:
            post = json.loads(data["post"])
            text = post["message"]
            userid = post["user_id"]
            if "file_ids" in post:
                file_ids = post["file_ids"]
            post_id = post["id"]
            if "type" in post and post["type"] == "system_add_remove":
                log.info("Ignoring message from System")
                return

        if "user_id" in data:
            userid = data["user_id"]

        if not userid:
            log.error("No userid in event {}".format(message))
            return

        mentions = []
        if "mentions" in data:
            # TODO: Only user, not channel mentions are in here at the moment
            mentions = self.mentions_build_identifier(
                json.loads(data["mentions"]))

        # Thread root post id
        root_id = post.get("root_id", "")
        if root_id == "":
            root_id = post_id

        msg = Message(
            text,
            extras={
                "id":
                post_id,
                "root_id":
                root_id,
                "mattermost_event":
                message,
                "url":
                "{scheme:s}://{domain:s}:{port:s}/{teamname:s}/pl/{postid:s}".
                format(
                    scheme=self.driver.options["scheme"],
                    domain=self.driver.options["url"],
                    port=str(self.driver.options["port"]),
                    teamname=self.team,
                    postid=post_id,
                ),
            },
        )
        if file_ids:
            msg.extras["attachments"] = file_ids

        # TODO: Slack handles bots here, but I am not sure if bot users is a concept in mattermost
        if channel_type == "D":
            msg.frm = MattermostPerson(self.driver,
                                       userid=userid,
                                       channelid=channelid,
                                       teamid=self.teamid)
            msg.to = MattermostPerson(
                self.driver,
                userid=self.bot_identifier.userid,
                channelid=channelid,
                teamid=self.teamid,
            )
        elif channel_type == "O" or channel_type == "P":
            msg.frm = MattermostRoomOccupant(
                self.driver,
                userid=userid,
                channelid=channelid,
                teamid=self.teamid,
                bot=self,
            )
            msg.to = MattermostRoom(channel, teamid=self.teamid, bot=self)
        else:
            log.warning(
                "Unknown channel type '{}'! Unable to handle {}.".format(
                    channel_type, channel))
            return

        self.callback_message(msg)

        if mentions:
            self.callback_mention(msg, mentions)