Beispiel #1
0
def send_msg(server_name, username, password, room_id, msg):
    client = MatrixClient(server_name)
    client.login(username=username, password=password)
    room = client.join_room(room_id)

    room.send_text(msg)
    client.logout()
def sendFunc(msgStr):
    # try to send a message (msgStr) via matrix protocol
    try:
        # try to read the updated credentials from a file received using previous function
        try:
            with open('updts.txt') as updts:
                updates = updts.read()
            decryptedDic = dcryptFunc(updates)
            martixServer = decryptedDic['martixServer']
            username = decryptedDic['username']
            password = decryptedDic['password']
            roomAddr = decryptedDic['roomAddr']
            client = MatrixClient(martixServer)
            token = client.login(username=username, password=password)
            room = client.join_room(roomAddr)
            room.send_text(msgStr)
            client.logoout()
        # if reading from file failed, probably due to file not being available,
        # connect to matrix server using hardcoded credentials
        except:
            client = MatrixClient("https://matrix.org")
            token = client.login(username="******",
                                 password="******")
            room = client.join_room(
                "Your_matrix_room_id")  # find it in room's advanced settings
            room.send_text(msgStr)
            client.logoout()
    # if matrix network was not available, like the time it got hacked on April, 2019(!)
    # send the message via Dropbox
    except:
        dropIt(msgStr)
def process_jenkins_request():
    check_token('X-Jenkins-Token')
    msgtype = get_msg_type()
    room = get_a_room()
    jenkins_event = request.headers.get("X-Jenkins-Event")

    if jenkins_event == "Post Build Hook":
        try:
            client = MatrixClient(cfg["matrix"]["server"])
            client.login(username=cfg["matrix"]["username"],
                         password=cfg["matrix"]["password"])

            room = client.join_room(room_id_or_alias=room)
        except MatrixRequestError as e:
            return matrix_error(e)

        def extract_change_message(change):
            change_message = next(iter_first_line(change["message"]), "")
            if len(change_message) > 0:
                htimestamp = datetime.fromtimestamp(
                    change['timestamp'] / 1000).strftime("%d. %b %y %H:%M")
                return f"{shorten(change_message)} " \
                    f"({shorten(change['commitId'], 7, appendix='')}) " \
                    f"by {change['author']} " \
                    f"at {htimestamp}"
            else:
                return shorten(json.dumps(change), appendix="...}")

        build_name = request.json["displayName"]
        project_name = request.json["project"]["fullDisplayName"]
        result_type = request.json["result"]["type"]
        result_color = request.json["result"]["color"]
        change_messages = list(
            map(extract_change_message, request.json["changes"]))
        html_changes = "\n".join(
            (f"  <li>{msg}</li>" for msg in change_messages))
        text_changes = "\n".join((f"- {msg}" for msg in change_messages))
        try:
            room.send_html(
                f"<p><strong>Build {build_name} on project {project_name} complete: "
                f"<font color=\"{result_color}\">{result_type}</font></strong>, "
                f"{len(change_messages)} commits</p>\n"
                "" + (f"<ul>\n{html_changes}\n</ul>\n"
                      if len(change_messages) > 0 else ""),
                body=
                f"**Build {build_name} on project {project_name} complete: {result_type}**, "
                f"{len(change_messages)} commits\n"
                "" + (f"{text_changes}\n" if len(change_messages) > 0 else ""),
                msgtype=msgtype)
        except MatrixRequestError as e:
            return matrix_error(e)

    # see Flask.make_response, this is interpreted as (body, status)
    return "", 204
Beispiel #4
0
class Matrix(object):
    def __init__(self, main):
        self.main = main
        self.login = login

        self.client = MatrixClient(address, encryption=encryption)
        self.client.login(login, passwd, device_id=device_id)

        self.rooms = []
        self.room_data = {}

        for room_id, room in self.client.get_rooms().items():
            self.main.system(f'add matrix room {room_id}')
            self.rooms.append(room_id)
            self.room_data[room_id] = {
                'history': [],
                'last_read': 0,
                'name': room.name or room_id,
                'topic': room.topic or '',
            }
            for event in room.events:
                if event['type'] == 'm.room.message':
                    self.room_data[room_id]['history'].append(
                        self.event_to_history(event))
            if chan in room.aliases:
                self.main.active_room_idx = len(self.rooms) - 1
                self.main.active_account_idx = 1
            room.add_listener(self.listener)
        self.client.start_listener_thread()

    def __str__(self):
        return f'Matrix {self.login}'

    def event_to_history(self, event):
        self.add_sender(event['sender'])
        return datetime.fromtimestamp(
            event['origin_server_ts'] /
            1000), event['sender'], event['content']['body']

    def add_sender(self, sender):
        if sender not in self.main.users:
            self.main.users[sender] = self.client.api.get_display_name(sender)

    def listener(self, room, event):
        if event['type'] == 'm.room.message':
            history = self.room_data[room.room_id]['history']
            history.append(self.event_to_history(event))
            if self.main.account == self and room.room_id == self.main.room_id:
                self.main.update_text(history)
        else:
            self.main.system(str(event))

    def send(self, text, room_id):
        self.client.rooms[room_id].send_text(text)
Beispiel #5
0
def test_enable_encryption():
    pytest.importorskip('olm')
    client = MatrixClient(HOSTNAME, encryption=True)

    login_path = HOSTNAME + MATRIX_V2_API_PATH + "/login"
    responses.add(responses.POST, login_path,
                  json=response_examples.example_success_login_response)

    upload_path = HOSTNAME + MATRIX_V2_API_PATH + '/keys/upload'
    responses.add(responses.POST, upload_path, body='{"one_time_key_counts": {}}')

    client.login("@example:localhost", "password", sync=False)

    assert client.olm_device
Beispiel #6
0
    def __init__(self, server, username, password, rooms, nick=None):
        client = MatrixClient(server)
        self.viewer_url = server.strip('/') + "/_matrix/media/v1/download/"

        try:
            client.login(username, password, sync=False)
        except MatrixRequestError as e:
            if e.code == 403:
                logger.error("403 Bad username or password.")
                sys.exit(4)
            else:
                logger.error("{} Check your server details are correct.".format(e))
                sys.exit(2)
        except MissingSchema as e:
            logger.error("{} Bad URL format.".format(e))
            sys.exit(3)

        self.username = client.user_id
        logger.info("logged in as: {}".format(self.username))

        if nick is not None:
            u = client.get_user(client.user_id)
            logger.info("Setting display name to {}".format(nick))
            try:
                u.set_display_name(nick)
            except MatrixRequestError as e:
                logger.error("Fail to set display name: error = {}".format(e))

        self.joined_rooms = {}
        self.room_id_to_alias = {}
        self.displaynames = {}

        for room_id_alias in rooms:
            try:
                room = client.join_room(room_id_alias)
            except MatrixRequestError as e:
                if e.code == 400:
                    logger.error("400 Room ID/Alias in the wrong format")
                    sys.exit(11)
                else:
                    logger.error("{} Couldn't find room {}".format(e, room_id_alias))
                    sys.exit(12)
            logger.info("Joined room {}".format(room_id_alias))
            self.joined_rooms[room_id_alias] = room
            self.room_id_to_alias[room.room_id] = room_id_alias
            room.add_listener(self.on_message)

        self.client = client
        self.bot_msg_pattern = config['matrix'].get('bot_msg_pattern', None)
Beispiel #7
0
def connect(host, user_id, password):
    global client
    try:
        client = MatrixClient(host, encryption=True, restore_device_id=True)
        client.login(username=user_id, password=password, sync=False)
        #client.start_listener_thread(timeout_ms=30000, exception_handler=None)
        #client.bad_sync_timeout_limit = 0
        #client.start_listener_thread()
        #client.should_listen=30000
        client.add_key_forward_listener(
            lambda x: writetolog('got new keys' + x))
    except:
        logging.exception('')
        quit()
    return (client)
def example(host, user, password, token):
    """run the example."""
    client = None
    try:
        if token:
            print('token login')
            client = MatrixClient(host, token=token)
        else:
            print('password login')
            client = MatrixClient(host)
            token = client.login(user, password)
            print('got token: %s' % token)
    except MatrixRequestError as e:
        print(e)
        if e.code == 403:
            print("Bad username or password")
            exit(2)
        elif e.code == 401:
            print("Bad username or token")
            exit(3)
        else:
            print("Verify server details.")
            exit(4)
    except MissingSchema as e:
        print(e)
        print("Bad formatting of URL.")
        exit(5)
    except InvalidSchema as e:
        print(e)
        print("Invalid URL schema")
        exit(6)
    print("is in rooms")
    for room_id, room in client.get_rooms().items():
        print(room_id)
Beispiel #9
0
class Matrix:
    def __init__(self):
        logger.info('logging in to Matrix as %s', config.matrix.username)

        self._client = MatrixClient(config.matrix.server)
        self._token = self._client.login(username=config.matrix.username, password=config.matrix.password, sync=False)
        self._api = MatrixHttpApi(config.matrix.server, self._token)

    def send_text(self, room_id, text):
        self._api.send_message(room_id, text)

    def send_notice_html(self, room_id, text):
        content = dict(
            body=text,
            format='org.matrix.custom.html',
            formatted_body=text,
            msgtype=MsgType.NOTICE
        )

        self._api.send_message_event(room_id, event_type='m.room.message', content=content)

    def send_text_html(self, room_id, text):
        content = dict(
            body=text,
            format='org.matrix.custom.html',
            formatted_body=text,
            msgtype=MsgType.TEXT
        )

        self._api.send_message_event(room_id, event_type='m.room.message', content=content)

    def send_notice(self, room_id, text):
        self._api.send_notice(room_id, text)
Beispiel #10
0
class Logger:
    address: str
    port: int
    token: str
    room: dict

    def __init__(self, *args, **kwargs):
        self.address, self.port = args[0]
        _room_name = args[1]
        _room = LOGGER[_room_name]
        if 'username' not in kwargs:
            kwargs.update({'username': _room["user"]})
        if 'password' not in kwargs:
            kwargs.update({'password': _room["password"]})
        try:
            # TODO: Make also dynamic
            self._client = MatrixClient(f"http://localhost:8008")
            self.token = self._client.login(**kwargs)
            self.room = self._client.join_room(_room_name)
        except MatrixHttpLibError as matrix_error:
            logging.error(matrix_error)

    def log(self, message):
        # TODO: Allow reconnection with room name as param
        if not self.token:
            logging.error(
                f"MatrixClient was not properly intialized. No log can be done"
            )
            return
        logging.info(f"Sending {message} to {self.room}")
        self.room.send_text(message)
def matrix_connect():
    global log
    global lock

    client = MatrixClient(conf.matrix_server)
    try:
        token = client.login(username=conf.matrix_username,
                             password=conf.matrix_password,
                             device_id=conf.matrix_device_id)
    except MatrixRequestError as e:
        log.error(e)
        log.debug(e)
        if e.code == 403:
            log.error("Bad username or password.")
            return None
        else:
            log.error("Check your sever details are correct.")
            return None
    except MatrixHttpLibError as e:
        log.error(e)
        return None
    except MissingSchema as e:
        log.error("Bad URL format.")
        log.error(e)
        log.debug(e)
        return None
    except:
        log.error("unknown error at client.login()")
        return None
    return client
def process_gitlab_request():
    check_token('X-Gitlab-Token')
    msgtype = get_msg_type()
    room = get_a_room()
    gitlab_event = request.headers.get("X-Gitlab-Event")

    if gitlab_event == "Push Hook":
        try:
            client = MatrixClient(cfg["matrix"]["server"])
            client.login(username=cfg["matrix"]["username"],
                         password=cfg["matrix"]["password"])

            room = client.join_room(room_id_or_alias=room)
        except MatrixRequestError as e:
            return matrix_error(e)

        def sort_commits_by_time(commits):
            return sorted(commits, key=lambda commit: commit["timestamp"])

        def extract_commit_info(commit):
            msg = shorten(
                next(iter_first_line(commit["message"]),
                     "$EMPTY_COMMIT_MESSAGE - impossibruh"))
            url = commit["url"]
            return msg, url

        username = request.json["user_name"]
        commit_messages = list(
            map(extract_commit_message,
                sort_commits_by_time(request.json["commits"])))
        project_name = request.json["project"]["name"]
        html_commits = "\n".join((f'  <li><a href="{url}">{msg}</a></li>'
                                  for (msg, url) in commit_messages))
        text_commits = "\n".join(
            (f"- [{msg}]({url})" for (msg, url) in commit_messages))
        try:
            room.send_html(
                f"<strong>{username} pushed {len(commit_messages)} commits to {project_name}</strong><br>\n"
                f"<ul>\n{html_commits}\n</ul>\n",
                body=
                f"{username} pushed {len(commit_messages)} commits to {project_name}\n{text_commits}\n",
                msgtype=msgtype)
        except MatrixRequestError as e:
            return matrix_error(e)

    # see Flask.make_response, this is interpreted as (body, status)
    return "", 204
Beispiel #13
0
def run_module():
    module_args = dict(
        msg_plain=dict(type='str', required=True),
        msg_html=dict(type='str', required=True),
        room_id=dict(type='str', required=True),
        hs_url=dict(type='str', required=True),
        token=dict(type='str', required=False, no_log=True),
        user_id=dict(type='str', required=False),
        password=dict(type='str', required=False, no_log=True),
    )

    result = dict(changed=False, message='')

    module = AnsibleModule(argument_spec=module_args,
                           mutually_exclusive=[['password', 'token']],
                           required_one_of=[['password', 'token']],
                           required_together=[['user_id', 'password']],
                           supports_check_mode=True)

    if not matrix_found:
        module.fail_json(
            msg=
            "Python 'matrix-client' module is required. Install via: $ pip install matrix-client"
        )

    if module.check_mode:
        return result

    # create a client object
    client = MatrixClient(module.params['hs_url'])
    if module.params['token'] is not None:
        client.api.token = module.params['token']
    else:
        client.login(module.params['user_id'],
                     module.params['password'],
                     sync=False)

    # make sure we are in a given room and return a room object for it
    room = client.join_room(module.params['room_id'])
    # send an html formatted messages
    room.send_html(module.params['msg_html'], module.params['msg_plain'])

    module.exit_json(**result)
Beispiel #14
0
 def __init__(self):
     print("Initializing client...")
     client = MatrixClient("https://matrix.org")
     print("Loggin in...")
     token = client.login(credentials["login"], credentials["password"])
     print("Reinitializing client")
     self.client = MatrixClient("https://matrix.org",
                                token=token,
                                user_id="@isbur:matrix.org")
     print("Entering the room...")
     self.room = client.join_room("!BeLEKkRmKBJzNOdqxB:matrix.org")
Beispiel #15
0
class Cmatrix:
    def __init__(self, _serverUrl, _username, _pass, _roomId):
        self.matrixClient = MatrixClient(_serverUrl)
        self.token = self.matrixClient.login(username=_username,
                                             password=_pass)
        self.api = MatrixHttpApi(_serverUrl, token=self.token)
        self.roomId = _roomId

    def sendMessage(self, message):
        response = self.api.send_message(self.roomId, message)
        return response
Beispiel #16
0
def get_token(config):
    """Returns a login token.
    """
    loginargs = {}
    client = MatrixClient(
        "https://{0}:{1}".format(config['homeserver'], int(config['port'])),
        **loginargs)
    token = client.login(username=config['username'],
                         password=config['password'],
                         device_id='zabbixbot')
    logging.info("Authenticated, add the following to your config:\ntoken: %s",
                 token)
    return token
Beispiel #17
0
def notify(title,
           message,
           url,
           roomId,
           userId=None,
           token=None,
           password=None,
           retcode=None):

    client = MatrixClient(url)
    if password is not None:
        if userId is None:
            raise Exception("Must supply 'userid' when using 'password'")
        client.login(userId, password, sync=False)
    elif token is not None:
        client.api.token = token
    else:
        raise Exception("Must supply 'token' or 'password'")
    msg_plain = "**{}** {}".format(title, message)
    msg_html = "<b>{}</b> {}".format(title, message)
    room = client.join_room(roomId)
    room.send_html(msg_html, msg_plain)
Beispiel #18
0
class Bot:
    def __init__(self, homeserver, userID, password, ownerID,
                 dialogflow_project):
        self.ownerID = ownerID
        self.userID = userID
        self.client = MatrixClient(homeserver)

        token = self.client.login(username=userID, password=password)

        self.project = dialogflow_project
        rooms = self.client.get_rooms()
        for name, room in self.client.get_rooms().items():
            room.add_listener(self.onEvent)

    def report_mainloop_error(self):
        pass

    def run(self):
        self.client.add_invite_listener(self.accept_invite)
        while True:
            try:
                self.client.listen_forever()
            except KeyboardInterrupt:
                raise
            except:
                self.report_mainloop_error()

    def accept_invite(self, room_id, state):
        self.client.join_room(room_id)
        session_client = dialogflow.SessionsClient()
        session = session_client.session_path(self.project, room_id)
        query_input = dialogflow.types.QueryInput(
            event=dialogflow.types.EventInput(name='WELCOME',
                                              language_code='en'))

    def onEvent(self, room, event):
        if event['sender'] != self.userID:
            print("New event in room {} : {}".format(room, event))
            if event['type'] == "m.room.message" and event['content'][
                    'msgtype'] == "m.text":
                if event['sender'] == self.ownerID:  # admin commands
                    leaveCommand = re.match("!leave (.+)",
                                            event['content']['body'])
                    if leaveCommand:
                        self.client.get_rooms()[leaveCommand.group(1)].leave()
                response = detect_intent(self.project, room.room_id,
                                         event['content']['body'], 'en')
                print("Got DialogFlow response: {}".format(response))
                for message in response:
                    for text in message.text.text:
                        room.send_text("{}".format(text))
Beispiel #19
0
def main(host, username, password, room_id_alias):
    client = MatrixClient(host)

    try:
        client.login(username, password)
    except MatrixRequestError as e:
        print(e)
        if e.code == 403:
            print("Bad username or password.")
            sys.exit(4)
        else:
            print("Check your sever details are correct.")
            sys.exit(2)
    except MissingSchema as e:
        print("Bad URL format.")
        print(e)
        sys.exit(3)

    try:
        room = client.join_room(room_id_alias)
    except MatrixRequestError as e:
        print(e)
        if e.code == 400:
            print("Room ID/Alias in the wrong format")
            sys.exit(11)
        else:
            print("Couldn't find room.")
            sys.exit(12)

    room.add_listener(on_message)
    client.start_listener_thread()

    while True:
        msg = samples_common.get_input()
        if msg == "/quit":
            break
        else:
            room.send_text(msg)
Beispiel #20
0
def init():
    config = configparser.ConfigParser()
    config.read("tztipbot.cfg")
    homeserver = config.get("server", "host")
    print(f"homeserver={homeserver}")

    client = MatrixClient(homeserver)
    username = config.get("client", "username")
    password = config.get("client", "password")
    print(f"username={username}")

    token = client.login(username=username, password=password)
    print(f"token={token}")
    return client
Beispiel #21
0
def main():
    # connect to server and join room
    client = MatrixClient("https://matrix.org")
    token = client.login(username="******", password=os.environ['KLO_PW'])
    room = client.join_room("#klotest:matrix.org")

    # create FeatureHandler
    fh = FeatureHandler(room, client)
    # add features to FeatureHandler that are called when the specified command is posted in the Matrix room
    fh.add_feature("!echo", FeatureExamples.echo)
    fh.add_feature("!room", find_room)

    # run script until it's stopped manually
    while True:
        pass
def delete_all_devices():
    client = MatrixClient(conf.matrix_server)
    token = client.login(username=conf.matrix_username,
                         password=conf.matrix_password,
                         device_id=conf.matrix_device_id)
    response = client.api.get_devices()

    #print(response)
    devices = response["devices"]

    print("len(devices)=%d" % len(response["devices"]))
    #  sys.exit()

    device_list = []
    index = 0
    for device in response["devices"]:
        if device["device_id"] != conf.matrix_device_id:
            device_list.append(device["device_id"])
            index += 1
        #if index > 1000:
        #  break

    # stage1 - берём сессию:
    try:
        #response=client.api.delete_device(auth_body={"auth":{}},device_id=device["device_id"])
        response = client.api.delete_devices({"auth": {}},
                                             [device["device_id"]])
    except MatrixRequestError as e:
        if e.code == 401:
            print("response=", e.content)
            response_data = json.loads(e.content)
            session = response_data["session"]
    # stage2 передаём пароль:
    print("session=", session)

    auth_body = {}
    auth_body["type"] = "m.login.password"
    auth_body["session"] = session
    auth_body["user"] = conf.matrix_username
    auth_body["password"] = conf.matrix_password
    response = client.api.delete_devices(auth_body, device_list)
    return True
def delete_device():
    client = MatrixClient(conf.server)
    token = client.login(username=conf.username,
                         password=conf.password,
                         device_id=conf.device_id)
    response = client.api.get_devices()

    #print(response)
    devices = response["devices"]

    print("len(devices)=%d" % len(response["devices"]))
    print("len(device_list)=%d" % len(device_list))
    print("device_list=", device_list)

    for device in response["devices"]:
        if device["device_id"] != conf.device_id:
            #print(device)
            print("delete device: %s" % device["device_id"])

            # stage1 - берём сессию:
            try:
                #response=client.api.delete_device(auth_body={"auth":{}},device_id=device["device_id"])
                response = client.api.delete_devices({"auth": {}},
                                                     [device["device_id"]])
            except MatrixRequestError as e:
                if e.code == 401:
                    print("response=", e.content)
                    response_data = json.loads(e.content)
                    session = response_data["session"]
            # stage2 передаём пароль:
            print("session=", session)

            auth_body = {}
            auth_body["type"] = "m.login.password"
            auth_body["session"] = session
            auth_body["user"] = conf.username
            auth_body["password"] = conf.password
            response = client.api.delete_device(auth_body=auth_body,
                                                device_id=device["device_id"])
        # FIXME
        break
    return True
def edit_message():
    client = MatrixClient(conf.matrix_server)
    token = client.login(username=conf.matrix_username,
                         password=conf.matrix_password,
                         device_id=conf.matrix_device_id)
    room_id = "!XXXXX:corp.ru"
    print("send message")
    ret = client.api.send_message(room_id, "test")
    print("success send message")
    print("event_id=", ret["event_id"])
    print("edit message")
    ret = edit_matrix_message(client,
                              room_id,
                              ret["event_id"],
                              "test2",
                              msgtype="m.text")
    if ret is not None:
        print("success edit message")
    else:
        print("error edit message")
    return ret
Beispiel #25
0
def startup(config):
    if os.path.isfile(config):
        with open(config, "r") as cfg:
            conf = json.load(cfg)
            client = MatrixClient(
                conf["homeserver"], conf["token"],
                "@" + conf["username"] + ":" + conf["homeserver"])
            parkendd_server = conf["parkendd_server"]
    else:
        homeserver = input("homeserver: ")
        username = input("username: "******"password: "******"parkendd_server: ")
        client = MatrixClient(homeserver)
        token = client.login(username, password)
        with open(config, "w") as cfg:
            json.dump(
                {
                    "homeserver": homeserver,
                    "token": token,
                    "username": username,
                    "parkendd_server": parkendd_server
                }, cfg)
    return client, parkendd_server
# 4 - Bad username/password.


import sys
import samples_common  # Common bits used between samples

from matrix_client.client import MatrixClient
from matrix_client.api import MatrixRequestError
from requests.exceptions import MissingSchema

host, username, password = samples_common.get_user_details(sys.argv)

client = MatrixClient(host)

try:
    client.login(username, password)
except MatrixRequestError as e:
    print(e)
    if e.code == 403:
        print("Bad username or password.")
        sys.exit(4)
    else:
        print("Check your server details are correct.")
        sys.exit(2)
except MissingSchema as e:
    print("Bad URL format.")
    print(e)
    sys.exit(3)

if len(sys.argv) > 4:
    userid = sys.argv[4]
class TinyMatrixtBot():
    def __init__(self, path_config):
        signal.signal(signal.SIGHUP, self.on_signal)
        signal.signal(signal.SIGINT, self.on_signal)
        signal.signal(signal.SIGTERM, self.on_signal)

        self.config = configparser.ConfigParser()
        self.config.read(path_config)

        _path_current = os.path.dirname(os.path.realpath(__file__))

        self.enabled_scripts = self.config.get("tiny-matrix-bot",
                                               "enabled_scripts",
                                               fallback="").strip()

        self.path_lib = self.config.get("tiny-matrix-bot",
                                        "lib",
                                        fallback=os.path.join(
                                            _path_current, "scripts")).strip()
        logger.debug("path_lib = {}".format(self.path_lib))
        if os.access(self.path_lib, os.R_OK):
            self.scripts = self.load_scripts(self.path_lib)
        else:
            logger.error("{} not readable".format(self.path_lib))
            sys.exit(1)

        self.path_var = self.config.get("tiny-matrix-bot",
                                        "var",
                                        fallback=os.path.join(
                                            _path_current, "data")).strip()
        logger.debug("path_var = {}".format(self.path_var))
        if os.access(self.path_var, os.W_OK):
            os.chdir(self.path_var)
        else:
            logger.error("{} not writeable".format(self.path_var))
            sys.exit(1)

        self.path_run = self.config.get("tiny-matrix-bot",
                                        "run",
                                        fallback=os.path.join(
                                            _path_current, "sockets")).strip()
        if os.access(self.path_run, os.W_OK):
            logger.debug("path_run = {}".format(self.path_run))
        else:
            logger.debug("path_run = {}".format(self.path_run) +
                         " (not writeable, disabling sockets)")
            self.path_run = False

        self.inviter_whitelist = self.config.get("tiny-matrix-bot",
                                                 "inviter_whitelist",
                                                 fallback="").strip()

        self.connect()
        self.user = self.client.get_user(self.client.user_id)
        self.user.set_display_name(self.config.get("tiny-matrix-bot", "name"))

        for room_id in self.client.get_rooms():
            self.join_room(room_id)

        self.client.start_listener_thread(
            exception_handler=self.listener_exception_handler)
        self.client.add_invite_listener(self.on_invite)
        self.client.add_leave_listener(self.on_leave)

        while True:
            sleep(1)

    def connect(self):
        _host = self.config.get("tiny-matrix-bot", "host")
        _user = self.config.get("tiny-matrix-bot", "user")
        _pass = self.config.get("tiny-matrix-bot", "pass")
        try:
            self.client = MatrixClient(_host)
            self.client.login(username=_user, password=_pass, limit=0)
            logger.info("connected to {}".format(_host))
        except Exception:
            logger.warning("connection to {} failed".format(_host) +
                           ", retrying in 5 seconds...")
            sleep(5)
            self.connect()

    def listener_exception_handler(self, e):
        self.connect()

    def on_signal(self, signal, frame):
        if signal == 1:
            self.scripts = self.load_scripts(self.path_lib)
        elif signal in [2, 15]:
            self.client.logout()
            sys.exit(0)

    def load_scripts(self, path):
        _scripts = {}
        for _script in os.listdir(path):
            _script_path = os.path.join(path, _script)
            if self.enabled_scripts:
                if _script not in self.enabled_scripts:
                    continue
            if (not os.access(_script_path, os.R_OK)
                    or not os.access(_script_path, os.X_OK)):
                continue
            _regex = subprocess.Popen(
                [_script_path],
                env={
                    "CONFIG": "1"
                },
                stdout=subprocess.PIPE,
                universal_newlines=True).communicate()[0].strip()
            if not _regex:
                continue
            _scripts[_regex] = _script_path
            logger.info("script load {}".format(_script))
            logger.debug("script regex {}".format(_regex))
        return _scripts

    def on_invite(self, room_id, state):
        _sender = "someone"
        for _event in state["events"]:
            if _event["type"] != "m.room.join_rules":
                continue
            _sender = _event["sender"]
            break
        logger.info("invited to {} by {}".format(room_id, _sender))
        if self.inviter_whitelist:
            if not re.search(self.inviter_whitelist, _sender, re.IGNORECASE):
                logger.info(
                    "no whitelist match, ignoring invite from {}".format(
                        _sender))
                return
        self.join_room(room_id)

    def join_room(self, room_id):
        logger.info("join {}".format(room_id))
        _room = self.client.join_room(room_id)
        _room.add_listener(self.on_room_event)
        if self.path_run is not False:
            _thread = Thread(target=self.create_socket, args=(_room, ))
            _thread.daemon = True
            _thread.start()

    def create_socket(self, room):
        _socket_name = re.search("^!([a-z]+):", room.room_id,
                                 re.IGNORECASE).group(1)
        _socket_path = os.path.join(self.path_run, _socket_name)
        try:
            os.remove(_socket_path)
        except OSError:
            pass
        _socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        _socket.bind(_socket_path)
        _socket.listen(1)
        logger.info("socket bind {}".format(_socket_path))
        while True:
            _conn, _addr = _socket.accept()
            _recv = _conn.recv(4096).decode('utf-8').strip()
            logger.debug("socket recv {} {}".format(_socket_path, _recv))
            room.send_text(_recv)

    def on_leave(self, room_id, state):
        _sender = "someone"
        for _event in state["timeline"]["events"]:
            if not _event["membership"]:
                continue
            _sender = _event["sender"]
        logger.info("kicked from {} by {}".format(room_id, _sender))

    def on_room_event(self, room, event):
        if event["sender"] == self.client.user_id:
            return
        if event["type"] != "m.room.message":
            return
        if event["content"]["msgtype"] != "m.text":
            return
        _args = event["content"]["body"].strip()
        for _regex, _script in self.scripts.items():
            if not re.search(_regex, _args, re.IGNORECASE):
                continue
            self.run_script(room, event, [_script, _args])

    def run_script(self, room, event, args):
        logger.debug("script room_id {}".format(event["room_id"]))
        logger.debug("script sender {}".format(event["sender"]))
        logger.debug("script run {}".format(args))
        _script = subprocess.Popen(args,
                                   env={
                                       "MXROOMID": event["room_id"],
                                       "MXSENDER": event["sender"]
                                   },
                                   stdout=subprocess.PIPE,
                                   universal_newlines=True)
        _output = _script.communicate()[0].strip()
        if _script.returncode != 0:
            logger.debug("script exit {}".format(_script.returncode))
            return
        sleep(0.5)
        for _p in _output.split("\n\n"):
            for _l in _p.split("\n"):
                logger.debug("script output {}".format(_l))
            room.send_text(_p)
            sleep(0.8)
Beispiel #28
0
class MatrixEngine(object):
    chatapi = ''
    chatclient = ''
    chattoken = ''
    listener_thread_id = 0
    new_msg_queue = []
    new_msg_senders = []

    def __init__(self, host=bothost, user=botuser, pwd=botpwd, room=botroom):
        print("Logging to matrix server...")
        self.chatclient = MatrixClient(host)
        try:
            self.chattoken = self.chatclient.login(username=user,
                                                   password=pwd,
                                                   sync=True)
        except MatrixRequestError as e:
            print(e)
            if e.code == 403:
                print("Bad username or password.")
                sys.exit(4)
            else:
                print("Check your sever details are correct.")
                sys.exit(2)
        except MissingSchema as e:
            print("Bad URL format.")
            print(e)
            sys.exit(3)
        self.chatapi = MatrixHttpApi(host, self.chattoken)
        print("Login OK")

        ### handle messages
        print("Setting up listener")
        try:
            room = self.chatclient.join_room(room)
        except MatrixRequestError as e:
            print(e)
            if e.code == 400:
                print("Room ID/Alias in the wrong format")
                sys.exit(11)
            else:
                print("Couldn't find room.")
                sys.exit(12)

        room.add_listener(self.on_message)
        self.listener_thread_id = self.chatclient.start_listener_thread()
        print('Listener set.. OK!')

    def sendmsg(self, msg, chatid=botroom):
        room = self.chatclient.join_room(chatid)
        response = self.chatapi.send_message(chatid, msg)

    def sendhtml(self, msg, chatid=botroom):
        room = self.chatclient.join_room(chatid)
        room.send_html(msg)

    def create_room(self, alias):
        ex_room = matrix_mongo.matrix_chats.find_one({"alias": alias})
        if ex_room:
            room_id = ex_room['room_id']
            room = self.chatclient.join_room(room_id)
            room.invite_user(ebuser)
        else:
            try:
                aldt = datetime.datetime.strftime(datetime.datetime.now(),
                                                  '%Y%m%d%H%M%S')
                new_room = self.chatclient.create_room(alias=alias + "_" +
                                                       aldt,
                                                       is_public=False,
                                                       invitees=[ebuser])
                room_id = new_room.room_id
                dtime = datetime.datetime.strftime(datetime.datetime.now(),
                                                   '%Y-%m-%d %H:%M:%S')
                chatdata = {
                    "created_date": dtime,
                    "alias": alias,
                    "room_alias": alias + "_" + aldt,
                    "room_id": room_id,
                    "room_data": room
                }

                recordID = matrix_mongo.matrix_chats.insert_one(chatdata)
            except MatrixRequestError as e:
                print(str(e))

        return room_id

    def sendfile(self, filename, chatid=botroom):
        room = self.chatclient.join_room(chatid)

        with open(filename, 'rb') as datafile:
            data = datafile.read()
            uri = self.chatclient.upload(content=data,
                                         content_type='image/jpg')
            print(uri)
            filedate = datetime.datetime.strftime(datetime.datetime.now(),
                                                  '%Y-%m-%d %H:%M:%S')
            room.send_image(
                uri, filedate + '_' + filename.replace('/', '_') + '.jpg')

    def on_message(self, room, event):
        try:
            # Called when a message is recieved.
            if event['type'] == "m.room.member":
                if event['membership'] == "join":
                    # print("{0} joined".format(event['content']['displayname']))
                    dtime = datetime.datetime.strftime(datetime.datetime.now(),
                                                       '%Y-%m-%d %H:%M:%S')
                    print(dtime + " new user joined to the room ")
            elif event['type'] == "m.room.message":
                if event['content']['msgtype'] == "m.text":
                    # print("{0}: {1}".format(event['sender'], event['content']['body']))
                    dtime = datetime.datetime.strftime(datetime.datetime.now(),
                                                       '%Y-%m-%d %H:%M:%S')
                    print(dtime + "|  '" + event['content']['body'] +
                          "' msg received from " + event['sender'])
                    if event['sender'] != "@mybot:matrix.org":
                        self.new_msg_senders.append(event['sender'])
                        self.new_msg_queue.append(event['content']['body'])
            else:
                print('new event in room:' + event['type'])
        except Exception as e:
            print('error @ on_message: ' + str(e))

    def parsemsg(self):
        for i in range(len(self.new_msg_queue)):
            origMsg = self.new_msg_queue[i]
            sender = self.new_msg_senders[i]

            msg = origMsg.lower()

            print("PARSER:  '" + origMsg + "' msg received from " + sender)

            def doshit():
                print('shit done')

            if msg == "test":
                doshit()
            elif msg == "msg":
                sendmsg("your msg responded!")
            elif msg == "html":
                sendhtml("your <b>html</b>  message <h1>responded</h1>!")
            else:
                print("message not understood")

            self.new_msg_queue.remove(origMsg)
            self.new_msg_senders.remove(sender)
class matrix_utils_ext(object):

    __MODULE_NAME__ = "Matrix Bot"
    __VERSION__ = "v0.0.1a"

    __MAX_SERVICE__ = 32
    # Number of services that can be simultaneously installed.
    room_tuple = namedtuple("room_tuple", "room_addr listener")

    def __init__(self, config_path="config.json"):
        self.room_dic = {}
        self.services_sensitive_on_clock = set()
        self.is_timer_on = False
        self.is_on = False
        self.nb_current_service = 0
        self.service_list = {}
        # self.logger.setLevel(logging.DEBUG) ;
        try:
            with open(config_path) as f:
                self.config = json.loads(f.read())
        except IOError as e:
            print(e)
        self.login = self.config["login"]
        self.password = self.config["password"]
        module.config = self.config.copy()
        try:
            self.client = MatrixClient(self.config["host"])
            self.client.login(self.login, self.password)
        except MatrixRequestError as e:
            print(e)
            sys.exit()

    def add_service_to_room(self, room, service, message_on_start=None):
        ret = False
        if self.nb_current_service < matrix_utils_ext.__MAX_SERVICE__:
            if service.add_room(
                    room):  # if room has been added to the service correctly
                if service in self.service_list:
                    self.service_list[service] += 1
                else:
                    self.service_list[service] = 1
                ret = True
        else:
            #raise Exception("Maximum number of services ({}) reached".format(str(matrix_utils.__MAX_SERVICE__))) ;
            pass
        return ret

    def remove_service_from_room(self, room, service):
        ret = False
        if service.remove_room(room):
            ret = True
            # if service is not linked to any room, remove from service_list
            self.service_list[service] -= 1
            if self.service_list[service] == 0:
                del self.service_list[service]

        else:
            #raise Exception("Service {} does not exist in room {}.".format(service, room)) ;
            pass
        return ret

# TODO ; eventuellement vérifier si une room avec une même adresse n'existe pas ?

    def add_room(self, room_addr, message_on_start=""):
        room = self.client.join_room(room_addr)
        listener = room.add_listener(self.callback)
        self.room_dic[room] = matrix_utils_ext.room_tuple(
            room_addr, listener
        )  # (room object address, room_name (room address), listener object)
        if message_on_start:
            # Conversion to HTML format
            message_on_start = message_on_start.replace("\n", "<br>")
            message_on_start = message_on_start.replace("\t", "&emsp;")
            room.send_html(message_on_start, msgtype="m.notice")
        return room

    def remove_room(self, room):
        if not (room in self.room_dic):
            return False
        for service in service_list.keys():
            if (room in service.get_room_list()):
                # there are still some services linked to room.
                return False
        listener = self.room_dic[room].listener
        self.client.remove_listener(listener)
        room.leave()
        del self.room_dic[room]
        return True

    def callback(self, room, event):
        if event["type"] == "m.room.message":
            login = re.search("@[aA-zZ]+[0-9]*", event["sender"]).group(0)
            login = login[1:]
            tmp_log = "Event from " + bcolors.OKGREEN + self.room_dic[
                room].room_addr + bcolors.ENDC + " at " + str(
                    datetime.datetime.now()) + " by " + login
            print(tmp_log)
            text = str(event["content"]["body"])
            ## Stop Service Management
            if text == self.config["bot_down_cmd"]:
                self.exit()
            ## Otherwise, run services
            for service in self.service_list.keys():
                if (room in service.get_room_list()):
                    ret = service.run(text, login, room)
                    if ret:
                        for msg in ret:
                            # Conversion to HTML format
                            msg = msg.replace("\n", "<br>")
                            msg = msg.replace("\t", "&emsp;")
                            room.send_html(msg, msgtype="m.notice")

    def spawn(self):
        self.client.start_listener_thread(exception_handler=self.error_handle)
        self.is_on = True
        print(bcolors.OKGREEN +
              "\n---------------------------------------------------\n" +
              "---- Matrix Bot v0.0.1 ----------------------------\n" +
              "---------------------------------------------------\n" +
              bcolors.ENDC)
        while (self.is_on):
            time.sleep(0.5)

    def timer_callback(self, t):
        while (self.is_timer_on):
            if self.is_on:
                for service in self.service_list:
                    if service.is_clock_sensitive():
                        service.clock_update()
                        ret = service.run_on_clock()
                        if ret:
                            # Conversion to HTML format
                            ret = ret.replace("\n", "<br>")
                            ret = ret.replace("\t", "&emsp;")
                            for room in service.get_room_list():
                                room.send_html(ret, msgtype="m.notice")
            time.sleep(t)

    def start_timer(self, t=1):
        if not (self.is_timer_on):
            self.is_timer_on = True
            t1 = threading.Thread(target=self.timer_callback, args=(t, ))
            t1.start()

    def stop_timer(self):
        self.is_timer_on = False

    def exit(self):
        self.is_timer_on = False
        self.is_on = False
        for service in self.service_list:
            print("Module {} {} {} is shutting down.".format(
                bcolors.OKGREEN, service.module_name, bcolors.ENDC))
            tmp_msg = service.exit()
            if tmp_msg:
                for room in service.get_room_list():
                    room.send_text(tmp_msg)
        # for room in self.room_dic:
        # room.send_text(self.config["bot_stop_txt"]);
        sys.exit()

    def error_handle(self, err):
        print("Server is not {} responding {} ({}). Restarting ...".format(
            bcolors.FAIL, bcolors.ENDC, err))
        self.exit()
Beispiel #30
0
#!/usr/bin/env python3

import getpass

from matrix_client.client import MatrixClient

from greet_newcomers import get_gepetto

HOME = "https://matrix.laas.fr"
ROOM = "#gepetto:laas.fr"

if __name__ == "__main__":
    client = MatrixClient(HOME)
    client.login(username=getpass.getuser(), password=getpass.getpass())

    room = client.rooms[client.api.get_room_id(ROOM)]
    members = [
        m.user_id.split(":")[0][1:] for m in room.get_joined_members()
        if m.user_id.endswith(":laas.fr")
    ]

    for member in get_gepetto():
        print("v" if member in members else "x", member)