diff --git a/README.md b/README.md index 9ada66c3455e6e16b19ed981d0c31cf2edfb8338..1454200d6404724513ec14bd6d6571356353ee70 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Rocket Chat Client Device Server Allows to send textual messages to a Rocket Chat Private Group. It is based on the rocket-python Python library. +Python Dependencies: requests, urllib3. It needs 2 DB properties: - Host : the RocketChat host to be used; diff --git a/RocketChat.py b/RocketChat.py new file mode 100755 index 0000000000000000000000000000000000000000..06f3212764bbfb0f07ed1a7160d18dd948ee323f --- /dev/null +++ b/RocketChat.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- + + +# ############################################################################ +# license : +# ============================================================================ +# +# File : RocketChat.py +# +# Project : RocketChat client +# +# This file is part of Tango device class. +# +# Tango is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Tango is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Tango. If not, see <http://www.gnu.org/licenses/>. +# +# +# $Author : sci.comp$ +# +# $Revision : $ +# +# $Date : $ +# +# $HeadUrl : $ +# ============================================================================ +# This file is generated by POGO +# (Program Obviously used to Generate tango Object) +# ############################################################################ + +__all__ = ["RocketChat", "RocketChatClass", "main"] + +__docformat__ = 'restructuredtext' + +import PyTango +import sys +# Add additional import +#----- PROTECTED REGION ID(RocketChat.additionnal_import) ENABLED START -----# +from rocketChatLib import rocketChat + +#----- PROTECTED REGION END -----# // RocketChat.additionnal_import + +# Device States Description +# No states for this device + + +class RocketChat (PyTango.Device_4Impl): + """RocketChat mmessage client""" + + # -------- Add you global variables here -------------------------- + #----- PROTECTED REGION ID(RocketChat.global_variables) ENABLED START -----# + + #----- PROTECTED REGION END -----# // RocketChat.global_variables + + def __init__(self, cl, name): + PyTango.Device_4Impl.__init__(self,cl,name) + self.debug_stream("In __init__()") + RocketChat.init_device(self) + #----- PROTECTED REGION ID(RocketChat.__init__) ENABLED START -----# + try: + with open(self.AuthenticationFile) as fp: + self.usrname = fp.readline().strip() + self.pwd = fp.readline().strip() + except: + self.set_state(PyTango.DevState.FAULT) + self.set_status("Unable to load authentication file") + return + self.chat = rocketChat(self.usrname,self.pwd,self.Host) + if self.chat.api is None: + self.set_state(PyTango.DevState.FAULT) + self.set_status("Unable to connect to %s" % self.Host) + return + try: + self.chat.Login() + self.set_state(PyTango.DevState.ON) + except: + self.set_state(PyTango.DevState.ALARM) + self.set_status("Unable to login on %s" % self.Host) + #----- PROTECTED REGION END -----# // RocketChat.__init__ + + def delete_device(self): + self.debug_stream("In delete_device()") + #----- PROTECTED REGION ID(RocketChat.delete_device) ENABLED START -----# + + #----- PROTECTED REGION END -----# // RocketChat.delete_device + + def init_device(self): + self.debug_stream("In init_device()") + self.get_device_properties(self.get_device_class()) + #----- PROTECTED REGION ID(RocketChat.init_device) ENABLED START -----# + + #----- PROTECTED REGION END -----# // RocketChat.init_device + + def always_executed_hook(self): + self.debug_stream("In always_excuted_hook()") + #----- PROTECTED REGION ID(RocketChat.always_executed_hook) ENABLED START -----# + + #----- PROTECTED REGION END -----# // RocketChat.always_executed_hook + + # ------------------------------------------------------------------------- + # RocketChat read/write attribute methods + # ------------------------------------------------------------------------- + + + + + def read_attr_hardware(self, data): + self.debug_stream("In read_attr_hardware()") + #----- PROTECTED REGION ID(RocketChat.read_attr_hardware) ENABLED START -----# + + #----- PROTECTED REGION END -----# // RocketChat.read_attr_hardware + + + # ------------------------------------------------------------------------- + # RocketChat command methods + # ------------------------------------------------------------------------- + + def SendMessage(self, argin): + """ + :param argin: [private_group_name,message] + :type argin: PyTango.DevVarStringArray + """ + self.debug_stream("In SendMessage()") + #----- PROTECTED REGION ID(RocketChat.SendMessage) ENABLED START -----# + dest = argin[0] + txt = argin[1] + self.chat.SendMessage(txt,dest) + #----- PROTECTED REGION END -----# // RocketChat.SendMessage + + + #----- PROTECTED REGION ID(RocketChat.programmer_methods) ENABLED START -----# + + #----- PROTECTED REGION END -----# // RocketChat.programmer_methods + +class RocketChatClass(PyTango.DeviceClass): + # -------- Add you global class variables here -------------------------- + #----- PROTECTED REGION ID(RocketChat.global_class_variables) ENABLED START -----# + + #----- PROTECTED REGION END -----# // RocketChat.global_class_variables + + + # Class Properties + class_property_list = { + } + + + # Device Properties + device_property_list = { + 'AuthenticationFile': + [PyTango.DevString, + "Full path of the file containing the authentication info.\nThe file should contain 2 lines:\nUSRNAME\nPASSWORD", + ["/opt/rocketchat.auth"] ], + 'Host': + [PyTango.DevString, + "Rocket chat server url", + ["https://rocket.chat"] ], + } + + + # Command definitions + cmd_list = { + 'SendMessage': + [[PyTango.DevVarStringArray, "[private_group_name,message]"], + [PyTango.DevVoid, "none"]], + } + + + # Attribute definitions + attr_list = { + } + + +def main(): + try: + py = PyTango.Util(sys.argv) + py.add_class(RocketChatClass, RocketChat, 'RocketChat') + #----- PROTECTED REGION ID(RocketChat.add_classes) ENABLED START -----# + + #----- PROTECTED REGION END -----# // RocketChat.add_classes + + U = PyTango.Util.instance() + U.server_init() + U.server_run() + + except PyTango.DevFailed as e: + print ('-------> Received a DevFailed exception:', e) + except Exception as e: + print ('-------> An unforeseen exception occured....', e) + +if __name__ == '__main__': + main() diff --git a/RocketChat.xmi b/RocketChat.xmi new file mode 100644 index 0000000000000000000000000000000000000000..229f17594dc0f32eb2a1690cd8f7c8ca1b72c72e --- /dev/null +++ b/RocketChat.xmi @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="ASCII"?> +<pogoDsl:PogoSystem xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pogoDsl="http://www.esrf.fr/tango/pogo/PogoDsl"> + <classes name="RocketChat" pogoRevision="9.4"> + <description description="RocketChat mmessage client" title="RocketChat client" sourcePath="/store/home/roberto/devel/TWINMIC/servers/RocketChat" language="Python" filestogenerate="XMI file,Code files,Protected Regions" license="GPL" copyright="" hasMandatoryProperty="false" hasConcreteProperty="true" hasAbstractCommand="false" hasAbstractAttribute="false"> + <inheritances classname="Device_Impl" sourcePath=""/> + <identification contact="at elettra.eu - sci.comp" author="sci.comp" emailDomain="elettra.eu" classFamily="Communication" siteSpecific="" platform="All Platforms" bus="Ethernet" manufacturer="Rocket.Chat" reference=""/> + </description> + <deviceProperties name="AuthenticationFile" description="Full path of the file containing the authentication info.
The file should contain 2 lines:
USRNAME
PASSWORD"> + <type xsi:type="pogoDsl:StringType"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <DefaultPropValue>/opt/rocketchat.auth</DefaultPropValue> + </deviceProperties> + <deviceProperties name="Host" description="Rocket chat server url"> + <type xsi:type="pogoDsl:StringType"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <DefaultPropValue>https://rocket.chat</DefaultPropValue> + </deviceProperties> + <commands name="State" description="This command gets the device state (stored in its device_state data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0"> + <argin description="none"> + <type xsi:type="pogoDsl:VoidType"/> + </argin> + <argout description="Device state"> + <type xsi:type="pogoDsl:StateType"/> + </argout> + <status abstract="true" inherited="true" concrete="true"/> + </commands> + <commands name="Status" description="This command gets the device status (stored in its device_status data member) and returns it to the caller." execMethod="dev_status" displayLevel="OPERATOR" polledPeriod="0"> + <argin description="none"> + <type xsi:type="pogoDsl:VoidType"/> + </argin> + <argout description="Device status"> + <type xsi:type="pogoDsl:ConstStringType"/> + </argout> + <status abstract="true" inherited="true" concrete="true"/> + </commands> + <commands name="SendMessage" description="" execMethod="send_message" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false"> + <argin description="[private_group_name,message]"> + <type xsi:type="pogoDsl:StringArrayType"/> + </argin> + <argout description=""> + <type xsi:type="pogoDsl:VoidType"/> + </argout> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + </commands> + <preferences docHome="./doc_html" makefileHome="/usr/share/pogo/preferences"/> + </classes> +</pogoDsl:PogoSystem> diff --git a/rocketChatLib.py b/rocketChatLib.py new file mode 100644 index 0000000000000000000000000000000000000000..1b8465b2b818f55cac0b6b9a2582829a27b94782 --- /dev/null +++ b/rocketChatLib.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +#pip install --user rocket-python + +import subprocess,time,sys +import datetime +from rocketchat.api import RocketChatAPI +from rocketchat.calls.base import RocketChatBase +import requests +from xml.etree import ElementTree as ET +from xml.dom import minidom +from urllib import unquote + + +class rocketPrivateRoomHistory(RocketChatBase): + endpoint = '/api/v1/groups.history' + + def build_endpoint(self, **kwargs): + endpointUrl = '{endpoint}?roomId={room_id}'.format( + endpoint=self.endpoint, + room_id=kwargs.get('room_id') + ) + if 'latest' in kwargs: + endpointUrl += '&latest=%s' % kwargs.get('latest') + if 'oldest' in kwargs: + endpointUrl += '&oldest=%s' % kwargs.get('oldest') + if 'count' in kwargs: + endpointUrl += '&count=%s' % kwargs.get('count') + if 'unreads' in kwargs: + endpointUrl += '&unreads=%s' % kwargs.get('unreads') + return endpointUrl + + def post_response(self, result): + return result + + +class rocketDownloader(RocketChatBase): + def call(self, *args, **kwargs): + fileurl = kwargs.get('url', None) + timeout = kwargs.get('timeout', None) + self.method = 'get' + url = '{domain}{endpoint}'.format( + domain=self.settings['domain'], + endpoint= fileurl+ '/?download' + ) + result = requests.request(method=self.method, url=url, + data=self.build_payload(**kwargs), + headers=self.headers, timeout=timeout, + files=self.build_files(**kwargs)) + request_data = { + 'url': url, + 'method': self.method, + 'payload': self.build_payload(**kwargs), + 'headers': self.headers, + 'files': self.files + } + result.raise_for_status() + self.logoff() + try: + return result + except Exception as e: + print ('RESTful {classname} call failed. {message}'.format( + classname=self.__class__.__name__, message=e)) + raise e + + +class rocketChat: + def __init__(self, usrname, pwd, host): + try: + self.chat_settings = {} + self.chat_settings['username'] = usrname + self.chat_settings['password'] = pwd + self.chat_settings['domain'] = host + self.api = RocketChatAPI(settings = self.chat_settings) + except: + self.api = None + + def Login(self): + dummybase = RocketChatBase(self.api.settings) + + def SendMessage(self, txt, dest): + self.api.send_message(str(txt), dest) + + + def SendFile(self, filepath, dest, mimeType='text/plain', descr = '', txt = ''): + if not dest.startswith('@'): + dest = self.api.get_room_id(str(dest)) + else: + print 'Not available at the moment' + return + self.api.upload_file(room_id=dest,file=str(filepath),description=str(descr),message=str(txt), mime_type=str(mimeType)) + + + def ExportMessages(self, channelName, count_in = 20): + if not channelName.startswith('@'): + dest = self.api.get_room_id(channelName) + else: + print 'Not available at the moment' + return + #print self.api.get_room_history(room_id=dest,oldest='n/a',latest='now') + return rocketPrivateRoomHistory(self.api.settings).call(room_id=dest,count=str(count_in)) + + + def DownloadFile(self, url_in): + filename = url_in.split('/')[-2] + '_' + url_in.split('/')[-1] + pic_url = self.chat_settings['domain'] + '/' + url_in + '/?download' + response = rocketDownloader(self.api.settings).call(url=url_in) + with open(unquote(filename).decode('utf8'), 'wb') as handle: + if not response.ok: + print response + for block in response.iter_content(1024): + if not block: + break + handle.write(block) + return filename + diff --git a/rocketchat/__init__.py b/rocketchat/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/rocketchat/api.py b/rocketchat/api.py new file mode 100644 index 0000000000000000000000000000000000000000..3103a1c9c7cc955ff277c0118298402205c3f23e --- /dev/null +++ b/rocketchat/api.py @@ -0,0 +1,310 @@ +from rocketchat.calls.chat.send_message import SendMessage +from rocketchat.calls.channels.get_public_rooms import GetPublicRooms +from rocketchat.calls.groups.get_private_rooms import GetPrivateRooms +from rocketchat.calls.channels.get_room_info import GetRoomInfo +from rocketchat.calls.groups.get_private_room_info import GetPrivateRoomInfo +from rocketchat.calls.groups.get_room_id import GetRoomId +from rocketchat.calls.groups.set_room_topic import SetRoomTopic +from rocketchat.calls.channels.get_history import GetRoomHistory +from rocketchat.calls.groups.get_private_room_history import GetPrivateRoomHistory +from rocketchat.calls.channels.create_public_room import CreatePublicRoom +from rocketchat.calls.channels.delete_public_room import DeletePublicRoom +from rocketchat.calls.auth.get_me import GetMe +from rocketchat.calls.users.get_users import GetUsers +from rocketchat.calls.users.get_user_info import GetUserInfo +from rocketchat.calls.users.create_user import CreateUser +from rocketchat.calls.users.delete_user import DeleteUser +from rocketchat.calls.groups.upload_file import UploadFile +from rocketchat.calls.im.create_room import CreateImRoom +from rocketchat.calls.im.open_room import OpenImRoom +from rocketchat.calls.im.close_room import CloseImRoom +from rocketchat.calls.im.get_rooms import GetImRooms +from rocketchat.calls.im.get_history import GetImRoomHistory +from datetime import datetime + + +class RocketChatAPI(object): + settings = None + + def __init__(self, settings=None, *args, **kwargs): + if settings: + self.settings = settings + else: + raise NotImplementedError('You must pass in settings for RocketChat') + + def send_message(self, message, room_id, **kwargs): + """ + Send a message to a given room + """ + return SendMessage(settings=self.settings, **kwargs).call( + message=message, + room_id=room_id, + **kwargs + ) + + def get_private_rooms(self, **kwargs): + """ + Get a listing of all private rooms with their names and IDs + """ + return GetPrivateRooms(settings=self.settings, **kwargs).call(**kwargs) + + def get_private_room_history(self, room_id, oldest=None, **kwargs): + """ + Get various history of specific private group in this case private + + :param room_id: + :param kwargs: + :return: + """ + return GetPrivateRoomHistory(settings=self.settings, **kwargs).call( + room_id=room_id, + oldest=oldest, + **kwargs + ) + + def get_public_rooms(self, **kwargs): + """ + Get a listing of all public rooms with their names and IDs + """ + return GetPublicRooms(settings=self.settings, **kwargs).call(**kwargs) + + def get_room_info(self, room_id, **kwargs): + """ + Get various information about a specific channel/room + + :param room_id: + :param kwargs: + :return: + """ + return GetRoomInfo(settings=self.settings, **kwargs).call( + room_id=room_id, + **kwargs + ) + + def upload_file(self, room_id, description, file, message, mime_type='text/plain', **kwargs): + """ + Upload file to room + :param room_id: + :param description: + :param file: + :param kwargs: + :return: + """ + return UploadFile(settings=self.settings, **kwargs).call( + room_id=room_id, + description=description, + file=file, + message=message, + mime_type=mime_type, + **kwargs + ) + + def get_private_room_info(self, room_id, **kwargs): + """ + Get various information about a specific private group + + :param room_id: + :param kwargs: + :return: + """ + return GetPrivateRoomInfo(settings=self.settings, **kwargs).call( + room_id=room_id, + **kwargs + ) + + def get_room_id(self, room_name, **kwargs): + """ + Get room ID + :param room_name: + :param kwargs: + :return: + """ + return GetRoomId(settings=self.settings, **kwargs).call( + room_name=room_name, + **kwargs + ) + + def get_room_history( + self, + room_id, + oldest=None, + latest=datetime.now(), + inclusive=False, + count=20, + unreads=False, + **kwargs + ): + """ + Get various history of specific channel/room + + :param room_id: + :param kwargs: + :return: + """ + return GetRoomHistory(settings=self.settings, **kwargs).call( + room_id=room_id, + oldest=oldest, + latest=latest, + inclusive=inclusive, + count=count, + unreads=unreads, + **kwargs + ) + + def create_public_room(self, name, **kwargs): + """ + Create room with given name + :param name: Room name + :param kwargs: + members: The users to add to the channel when it is created. + Optional; Ex.: ["rocket.cat"], Default: [] + read_only: Set if the channel is read only or not. + Optional; Ex.: True, Default: False + :return: + """ + return CreatePublicRoom(settings=self.settings, **kwargs).call(name=name, **kwargs) + + def delete_public_room(self, room_id, **kwargs): + """ + Delete room with given ID + :param room_id: Room ID + :param kwargs: + :return: + """ + return DeletePublicRoom(settings=self.settings, **kwargs).call(room_id=room_id, **kwargs) + + def get_my_info(self, **kwargs): + return GetMe(settings=self.settings, **kwargs).call(**kwargs) + + def get_users(self, **kwargs): + """ + Gets all of the users in the system and their information + :param kwargs: + :return: + """ + return GetUsers(settings=self.settings, **kwargs).call(**kwargs) + + def get_user_info(self, user_id, **kwargs): + """ + Retrieves information about a user, + the result is only limited to what the callee has access to view. + :param user_id: + :param kwargs: + :return: + """ + return GetUserInfo(settings=self.settings, **kwargs).call( + user_id=user_id, + **kwargs + ) + + def create_user(self, email, name, password, username, **kwargs): + """ + Create user + :param email: E-mail + :param name: Full name + :param password: Password + :param username: Username + :param kwargs: + active: + roles: + join_default_channels: + require_password_change: + send_welcome_email: + verified: + custom_fields: + :return: + """ + return CreateUser(settings=self.settings, **kwargs).call( + email=email, + name=name, + password=password, + username=username, + **kwargs + ) + + def delete_user(self, user_id, **kwargs): + """ + Delete user + :param user_id: User ID + :param kwargs: + :return: + """ + return DeleteUser(settings=self.settings, **kwargs).call(user_id=user_id, **kwargs) + + def set_room_topic(self, room_id, topic, **kwargs): + return SetRoomTopic(settings=self.settings, **kwargs).call( + room_id=room_id, + topic=topic, + **kwargs + ) + + def create_im_room(self, username, **kwargs): + """ + Create direct message room with user + + :param username: + :return: + """ + return CreateImRoom(settings=self.settings, **kwargs).call( + username=username, + **kwargs + ) + + def open_im_room(self, room_id, **kwargs): + """ + Open direct message room + + :param room_id: + :return: + """ + return OpenImRoom(settings=self.settings, **kwargs).call( + room_id=room_id, + **kwargs + ) + + def close_im_room(self, room_id, **kwargs): + """ + Close direct message room + + :param room_id: + :return: + """ + return CloseImRoom(settings=self.settings, **kwargs).call( + room_id=room_id, + **kwargs + ) + + def get_im_rooms(self, **kwargs): + """ + Get direct message rooms + + :return: + """ + return GetImRooms(settings=self.settings, **kwargs).call(**kwargs) + + def get_im_room_history( + self, + room_id, + oldest=None, + latest=datetime.now(), + inclusive=False, + count=20, + unreads=False, + **kwargs + ): + """ + Get various history of specific direct message room + + :param room_id: + :param kwargs: + :return: + """ + return GetImRoomHistory(settings=self.settings, **kwargs).call( + room_id=room_id, + oldest=oldest, + latest=latest, + inclusive=inclusive, + count=count, + unreads=unreads, + **kwargs + ) diff --git a/rocketchat/calls/__init__.py b/rocketchat/calls/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/rocketchat/calls/auth/__init__.py b/rocketchat/calls/auth/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/rocketchat/calls/auth/get_me.py b/rocketchat/calls/auth/get_me.py new file mode 100644 index 0000000000000000000000000000000000000000..f4f413a65134654766595d29b8027879df464466 --- /dev/null +++ b/rocketchat/calls/auth/get_me.py @@ -0,0 +1,15 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetMe(RocketChatBase): + endpoint = '/api/v1/me' + + def build_endpoint(self, **kwargs): + return self.endpoint + + def post_response(self, result): + return result diff --git a/rocketchat/calls/base.py b/rocketchat/calls/base.py new file mode 100644 index 0000000000000000000000000000000000000000..c76960ef5d102acdca45ccee79e432da13e8c426 --- /dev/null +++ b/rocketchat/calls/base.py @@ -0,0 +1,134 @@ +import logging +import pprint +import requests + + +logger = logging.getLogger(__name__) + + +class RocketChatBase(object): + settings = None + endpoint = None + headers = {} + method = 'get' + auth_token = None + auth_user_id = None + files = None + + def __init__(self, settings=None, *args, **kwargs): + self.settings = settings + + # Prepare for a call by fetching an Auth Token + self.set_auth_token() + self.set_auth_headers() + + def set_auth_token(self): + if self.settings.get('token') and self.settings.get('user_id'): + self.auth_token = self.settings.get('token') + self.auth_user_id = self.settings.get('user_id') + return + + url = '{domain}/api/v1/login'.format( + domain=self.settings['domain'] + ) + response = requests.post(url, + data={'user': self.settings['username'], + 'password': self.settings['password']}) + + try: + self.auth_token = response.json()['data']['authToken'] + self.auth_user_id = response.json()['data']['userId'] + except KeyError: + response.raise_for_status() + + def set_auth_headers(self): + self.headers['X-Auth-Token'] = self.auth_token + self.headers['X-User-Id'] = self.auth_user_id + + def logoff(self): + url = '{domain}/api/v1/logout'.format( + domain=self.settings['domain'] + ) + requests.get(url, headers=self.headers) + + def post_response(self, result): + return result + + def build_endpoint(self, **kwargs): + """ + Build the endpoint for the user given some kwargs + from the initial calling. + + :return: + """ + + raise NotImplementedError() + + def build_payload(self, **kwargs): + """ + Build a payload dict that will be passed directly to the + endpoint. If you need to pass this as plain text or whatever + you'll need to the dumping here. + + :return: + """ + + return None + + def build_files(self, **kwargs): + """ + Build files + :param kwargs: + :return: + """ + return None + + def call(self, *args, **kwargs): + """ + + :param args: + :param kwargs: + :return: + """ + + timeout = kwargs.get('timeout', None) + url = '{domain}{endpoint}'.format( + domain=self.settings['domain'], + endpoint=self.build_endpoint(**kwargs) + ) + + result = requests.request(method=self.method, url=url, + data=self.build_payload(**kwargs), + headers=self.headers, timeout=timeout, + files=self.build_files(**kwargs)) + + request_data = { + 'url': url, + 'method': self.method, + 'payload': self.build_payload(**kwargs), + 'headers': self.headers, + 'files': self.files + } + + logger.debug('API Request - {request}'.format( + request=pprint.pformat(request_data) + )) + + result.raise_for_status() + self.logoff() + + try: + logger.debug('API Response - {data}'.format( + data=pprint.pformat(result.json()) + )) + return self.post_response(result.json()) + + except Exception as e: + logger.error('RESTful {classname} call failed. {message}'.format( + classname=self.__class__.__name__, message=e), + exc_info=True) + raise e + + +class PostMixin(object): + method = 'post' diff --git a/rocketchat/calls/channels/__init__.py b/rocketchat/calls/channels/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/rocketchat/calls/channels/create_public_room.py b/rocketchat/calls/channels/create_public_room.py new file mode 100644 index 0000000000000000000000000000000000000000..419069b634982ede20c9bb3f3dfbe0dfaa058e44 --- /dev/null +++ b/rocketchat/calls/channels/create_public_room.py @@ -0,0 +1,23 @@ +import logging +import json + +from rocketchat.calls.base import PostMixin, RocketChatBase + +logger = logging.getLogger(__name__) + + +class CreatePublicRoom(PostMixin, RocketChatBase): + endpoint = '/api/v1/channels.create' + + def build_endpoint(self, **kwargs): + return self.endpoint + + def build_payload(self, **kwargs): + return json.dumps({ + 'name': kwargs.get('name'), + 'members': kwargs.get('members', []), + 'readOnly': kwargs.get('read_only', False) + }) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/channels/delete_public_room.py b/rocketchat/calls/channels/delete_public_room.py new file mode 100644 index 0000000000000000000000000000000000000000..b12c62a9a88571949f6bb92e714466cc1dc47fc2 --- /dev/null +++ b/rocketchat/calls/channels/delete_public_room.py @@ -0,0 +1,21 @@ +import logging +import json + +from rocketchat.calls.base import PostMixin, RocketChatBase + +logger = logging.getLogger(__name__) + + +class DeletePublicRoom(PostMixin, RocketChatBase): + endpoint = '/api/v1/channels.delete' + + def build_endpoint(self, **kwargs): + return self.endpoint + + def build_payload(self, **kwargs): + return json.dumps({ + 'roomId': kwargs.get('room_id') + }) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/channels/get_history.py b/rocketchat/calls/channels/get_history.py new file mode 100644 index 0000000000000000000000000000000000000000..01b91c784b0900ec49d2462cffd1936a0d170b17 --- /dev/null +++ b/rocketchat/calls/channels/get_history.py @@ -0,0 +1,24 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetRoomHistory(RocketChatBase): + endpoint = '/api/v1/channels.history' + + def build_endpoint(self, **kwargs): + return '{endpoint}?roomId={room_id}&oldest={oldest}&inclusive={inclusive}'\ + '&count={count}&unreads={unreads}&latest={latest}'.format( + endpoint=self.endpoint, + oldest=kwargs.get('oldest'), + room_id=kwargs.get('room_id'), + inclusive=kwargs.get('inclusive'), + count=kwargs.get('count'), + unreads=kwargs.get('unreads'), + latest=kwargs.get('latest') + ) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/channels/get_public_rooms.py b/rocketchat/calls/channels/get_public_rooms.py new file mode 100644 index 0000000000000000000000000000000000000000..67b6031499777b070aa96ccb4639cd7cee8471a9 --- /dev/null +++ b/rocketchat/calls/channels/get_public_rooms.py @@ -0,0 +1,31 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetPublicRooms(RocketChatBase): + endpoint = '/api/v1/channels.list' + + def build_endpoint(self): + return self.endpoint + + def post_response(self, result): + rooms = [] + + try: + _rooms = result.get('channels') + + for room in _rooms: + room_dict = {} + room_dict['name'] = room.get('name') + room_dict['id'] = room.get('_id') + rooms.append(room_dict) + + except Exception as e: + logger.error('Exception in fetching public rooms {e}'.format( + e=e + ), exc_info=True) + + return rooms diff --git a/rocketchat/calls/channels/get_room_info.py b/rocketchat/calls/channels/get_room_info.py new file mode 100644 index 0000000000000000000000000000000000000000..e5418419787671c81a8e93a3a84bc7b95f74b31e --- /dev/null +++ b/rocketchat/calls/channels/get_room_info.py @@ -0,0 +1,18 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetRoomInfo(RocketChatBase): + endpoint = '/api/v1/channels.info' + + def build_endpoint(self, **kwargs): + return '{endpoint}?roomId={room_id}'.format( + endpoint=self.endpoint, + room_id=kwargs.get('room_id') + ) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/chat/__init__.py b/rocketchat/calls/chat/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/rocketchat/calls/chat/send_message.py b/rocketchat/calls/chat/send_message.py new file mode 100644 index 0000000000000000000000000000000000000000..3180dc1c7c20906d39a9d5978f835fe802693c9a --- /dev/null +++ b/rocketchat/calls/chat/send_message.py @@ -0,0 +1,11 @@ +from rocketchat.calls.base import PostMixin, RocketChatBase + + +class SendMessage(PostMixin, RocketChatBase): + endpoint = '/api/v1/chat.postMessage' + + def build_endpoint(self, **kwargs): + return self.endpoint + + def build_payload(self, **kwargs): + return {'text': kwargs.get('message'), 'roomId': kwargs.get('room_id')} diff --git a/rocketchat/calls/groups/__init__.py b/rocketchat/calls/groups/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/rocketchat/calls/groups/get_private_room_history.py b/rocketchat/calls/groups/get_private_room_history.py new file mode 100644 index 0000000000000000000000000000000000000000..ffb80b5cc0a20572bda2ced67ea9f632a14703e9 --- /dev/null +++ b/rocketchat/calls/groups/get_private_room_history.py @@ -0,0 +1,25 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetPrivateRoomHistory(RocketChatBase): + endpoint = '/api/v1/groups.history' + + def build_endpoint(self, **kwargs): + if 'oldest' in kwargs: + return '{endpoint}?roomId={room_id}&oldest={oldest}'.format( + endpoint=self.endpoint, + oldest=kwargs.get('oldest'), + room_id=kwargs.get('room_id') + ) + else: + return '{endpoint}?roomId={room_id}'.format( + endpoint=self.endpoint, + room_id=kwargs.get('room_id') + ) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/groups/get_private_room_info.py b/rocketchat/calls/groups/get_private_room_info.py new file mode 100644 index 0000000000000000000000000000000000000000..8fc0c63f1461ac4f4899c79a92aa068ba1012729 --- /dev/null +++ b/rocketchat/calls/groups/get_private_room_info.py @@ -0,0 +1,18 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetPrivateRoomInfo(RocketChatBase): + endpoint = '/api/v1/groups.info' + + def build_endpoint(self, **kwargs): + return '{endpoint}?roomId={room_id}'.format( + endpoint=self.endpoint, + room_id=kwargs.get('room_id') + ) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/groups/get_private_rooms.py b/rocketchat/calls/groups/get_private_rooms.py new file mode 100644 index 0000000000000000000000000000000000000000..5f649bc09bc80867dc23c77ae40b00d3c7f5c151 --- /dev/null +++ b/rocketchat/calls/groups/get_private_rooms.py @@ -0,0 +1,31 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetPrivateRooms(RocketChatBase): + endpoint = '/api/v1/groups.list' + + def build_endpoint(self): + return self.endpoint + + def post_response(self, result): + rooms = [] + + try: + _rooms = result.get('groups') + + for room in _rooms: + room_dict = {} + room_dict['name'] = room.get('name') + room_dict['id'] = room.get('_id') + rooms.append(room_dict) + + except Exception as e: + logger.error('Exception in fetching private rooms {e}'.format( + e=e + ), exc_info=True) + + return rooms diff --git a/rocketchat/calls/groups/get_room_id.py b/rocketchat/calls/groups/get_room_id.py new file mode 100644 index 0000000000000000000000000000000000000000..a956ec8fdc9ff75be9c416a439299859e3b45b39 --- /dev/null +++ b/rocketchat/calls/groups/get_room_id.py @@ -0,0 +1,20 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetRoomId(RocketChatBase): + endpoint = '/api/v1/groups.info' + + def build_endpoint(self, **kwargs): + + return '{endpoint}?roomName={room_name}'.format( + endpoint=self.endpoint, + room_name=kwargs.get('room_name') + ) + + def post_response(self, result): + # print(result['group']['_id']) + return result['group']['_id'] diff --git a/rocketchat/calls/groups/set_room_topic.py b/rocketchat/calls/groups/set_room_topic.py new file mode 100644 index 0000000000000000000000000000000000000000..76dcaab69a4a8277aa3ce9866895316424a26477 --- /dev/null +++ b/rocketchat/calls/groups/set_room_topic.py @@ -0,0 +1,21 @@ +import logging + +from rocketchat.calls.base import PostMixin, RocketChatBase + +logger = logging.getLogger(__name__) + + +class SetRoomTopic(PostMixin, RocketChatBase): + endpoint = '/api/v1/groups.setTopic' + + def build_endpoint(self, **kwargs): + return self.endpoint + + def build_payload(self, **kwargs): + return { + 'topic': kwargs.get('topic'), + 'roomId': kwargs.get('room_id') + } + + def post_response(self, result): + return result['success'] diff --git a/rocketchat/calls/groups/upload_file.py b/rocketchat/calls/groups/upload_file.py new file mode 100644 index 0000000000000000000000000000000000000000..0ec611e14bf360e8303fc9e1166eb6684d750e55 --- /dev/null +++ b/rocketchat/calls/groups/upload_file.py @@ -0,0 +1,23 @@ +import logging + +from rocketchat.calls.base import RocketChatBase, PostMixin, logger +logger.setLevel(logging.DEBUG) + + +class UploadFile(PostMixin, RocketChatBase): + endpoint = '/api/v1/rooms.upload' + + def build_endpoint(self, **kwargs): + return '{endpoint}/{room_id}'.format(endpoint=self.endpoint, + room_id=kwargs.get('room_id')) + + def build_files(self, **kwargs): + return {'file': (kwargs.get('file'), + open(kwargs.get('file'), 'rb'), + kwargs.get('mime_type'))} + + def build_payload(self, **kwargs): + return {'description': kwargs.get('description'), 'msg': kwargs.get('message')} + + def post_response(self, result): + return result diff --git a/rocketchat/calls/im/__init__.py b/rocketchat/calls/im/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/rocketchat/calls/im/close_room.py b/rocketchat/calls/im/close_room.py new file mode 100644 index 0000000000000000000000000000000000000000..1423217ed4caf4cb6c606a3880e871c6c24b2a3d --- /dev/null +++ b/rocketchat/calls/im/close_room.py @@ -0,0 +1,19 @@ +import json +import logging + +from rocketchat.calls.base import PostMixin, RocketChatBase + +logger = logging.getLogger(__name__) + + +class CloseImRoom(PostMixin, RocketChatBase): + endpoint = "/api/v1/im.create" + + def build_endpoint(self, **kwargs): + return self.endpoint + + def build_payload(self, **kwargs): + return json.dumps({"roomId": kwargs.get("room_id")}) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/im/create_room.py b/rocketchat/calls/im/create_room.py new file mode 100644 index 0000000000000000000000000000000000000000..17af901e2d74b8f6371929a00b43d30ce8040b21 --- /dev/null +++ b/rocketchat/calls/im/create_room.py @@ -0,0 +1,34 @@ +import json +import logging + +from rocketchat.calls.base import PostMixin, RocketChatBase + +logger = logging.getLogger(__name__) + + +class CreateImRoom(PostMixin, RocketChatBase): + endpoint = "/api/v1/im.create" + + def build_endpoint(self, **kwargs): + return self.endpoint + + def build_payload(self, **kwargs): + return json.dumps({"username": kwargs.get("username")}) + + def post_response(self, result): + try: + _room = result.get('room') + room_dict = dict() + room_dict['id'] = _room.get('_id') + + for username in _room.get("usernames"): + if username != self.settings["username"]: + room_dict['username'] = username + break + + except Exception as e: + logger.error('Exception in creating im rooms {e}'.format( + e=e + ), exc_info=True) + + return room_dict diff --git a/rocketchat/calls/im/get_history.py b/rocketchat/calls/im/get_history.py new file mode 100644 index 0000000000000000000000000000000000000000..8535b9d6354e2212889dea3fa34c98b18292e756 --- /dev/null +++ b/rocketchat/calls/im/get_history.py @@ -0,0 +1,47 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetImRoomHistory(RocketChatBase): + endpoint = '/api/v1/im.history' + + def build_endpoint(self, **kwargs): + return '{endpoint}?roomId={room_id}&oldest={oldest}&inclusive={inclusive}'\ + '&count={count}&unreads={unreads}&latest={latest}'.format( + endpoint=self.endpoint, + oldest=kwargs.get('oldest'), + room_id=kwargs.get('room_id'), + inclusive=kwargs.get('inclusive'), + count=kwargs.get('count'), + unreads=kwargs.get('unreads'), + latest=kwargs.get('latest') + ) + + def post_response(self, result): + messages = [] + + try: + _messages = result.get('messages') + + for msg in _messages: + msg_dict = dict() + msg_dict['msg'] = msg.get('msg') + msg_dict['room_id'] = msg.get('rid') + msg_dict['ts'] = msg.get('ts') + msg_dict['user'] = { + 'id': msg.get('u', {}).get('_id'), + 'username': msg.get('u', {}).get('username'), + } + msg_dict['id'] = msg.get('_id') + + messages.append(msg_dict) + + except Exception as e: + logger.error('Exception in fetching direct message rooms {e}'.format( + e=e + ), exc_info=True) + + return messages diff --git a/rocketchat/calls/im/get_rooms.py b/rocketchat/calls/im/get_rooms.py new file mode 100644 index 0000000000000000000000000000000000000000..1f9236b9b34e853894deef5e99223db5db686872 --- /dev/null +++ b/rocketchat/calls/im/get_rooms.py @@ -0,0 +1,39 @@ +import logging + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetImRooms(RocketChatBase): + endpoint = "/api/v1/im.list" + + def build_endpoint(self): + return self.endpoint + + def post_response(self, result): + rooms = [] + + try: + _rooms = result.get("ims") + + for room in _rooms: + if not room.get("usernames"): + continue + + for username in room.get("usernames"): + if username != self.settings["username"]: + break + + room_dict = {} + room_dict["username"] = username + room_dict["id"] = room.get("_id") + rooms.append(room_dict) + + except Exception as e: + logger.error( + "Exception in fetching im rooms {e}".format(e=e), + exc_info=True, + ) + + return rooms diff --git a/rocketchat/calls/im/open_room.py b/rocketchat/calls/im/open_room.py new file mode 100644 index 0000000000000000000000000000000000000000..88957c058f220c00d68acc05659ec7887abf2853 --- /dev/null +++ b/rocketchat/calls/im/open_room.py @@ -0,0 +1,19 @@ +import json +import logging + +from rocketchat.calls.base import PostMixin, RocketChatBase + +logger = logging.getLogger(__name__) + + +class OpenImRoom(PostMixin, RocketChatBase): + endpoint = "/api/v1/im.create" + + def build_endpoint(self, **kwargs): + return self.endpoint + + def build_payload(self, **kwargs): + return json.dumps({"roomId": kwargs.get("room_id")}) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/users/__init__.py b/rocketchat/calls/users/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/rocketchat/calls/users/create_user.py b/rocketchat/calls/users/create_user.py new file mode 100644 index 0000000000000000000000000000000000000000..43c7e8580c927a68db6f102cd98db01215689731 --- /dev/null +++ b/rocketchat/calls/users/create_user.py @@ -0,0 +1,31 @@ +import logging +import json + +from rocketchat.calls.base import PostMixin, RocketChatBase + +logger = logging.getLogger(__name__) + + +class CreateUser(PostMixin, RocketChatBase): + endpoint = '/api/v1/users.create' + + def build_endpoint(self, **kwargs): + return self.endpoint + + def build_payload(self, **kwargs): + return json.dumps({ + 'email': kwargs.get('email'), + 'name': kwargs.get('name'), + 'password': kwargs.get('password'), + 'username': kwargs.get('username'), + 'active': kwargs.get('active', True), + 'roles': kwargs.get('roles', ['user']), + 'joinDefaultChannels': kwargs.get('join_default_channels', True), + 'requirePasswordChange': kwargs.get('require_password_change', False), + 'sendWelcomeEmail': kwargs.get('send_welcome_email', False), + 'verified': kwargs.get('verified', False), + 'customFields': kwargs.get('customFields', {}) + }) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/users/delete_user.py b/rocketchat/calls/users/delete_user.py new file mode 100644 index 0000000000000000000000000000000000000000..b25455bb57197552216e627f08e09ce1868f4fb2 --- /dev/null +++ b/rocketchat/calls/users/delete_user.py @@ -0,0 +1,21 @@ +import logging +import json + +from rocketchat.calls.base import PostMixin, RocketChatBase + +logger = logging.getLogger(__name__) + + +class DeleteUser(PostMixin, RocketChatBase): + endpoint = '/api/v1/users.delete' + + def build_endpoint(self, **kwargs): + return self.endpoint + + def build_payload(self, **kwargs): + return json.dumps({ + 'userId': kwargs.get('user_id') + }) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/users/get_user_info.py b/rocketchat/calls/users/get_user_info.py new file mode 100644 index 0000000000000000000000000000000000000000..d056df1fd179dc1665232d55dc8e1134f3f32c94 --- /dev/null +++ b/rocketchat/calls/users/get_user_info.py @@ -0,0 +1,19 @@ +import logging + + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetUserInfo(RocketChatBase): + endpoint = '/api/v1/users.info' + + def build_endpoint(self, **kwargs): + return '{endpoint}?userId={room_id}'.format( + endpoint=self.endpoint, + room_id=kwargs.get('user_id') + ) + + def post_response(self, result): + return result diff --git a/rocketchat/calls/users/get_users.py b/rocketchat/calls/users/get_users.py new file mode 100644 index 0000000000000000000000000000000000000000..bcc51c23d3ce9048f95054ecab21e42e9412ded9 --- /dev/null +++ b/rocketchat/calls/users/get_users.py @@ -0,0 +1,37 @@ +import logging + + +from rocketchat.calls.base import RocketChatBase + +logger = logging.getLogger(__name__) + + +class GetUsers(RocketChatBase): + endpoint = '/api/v1/users.list' + + def build_endpoint(self): + return self.endpoint + + def post_response(self, result): + users = [] + + try: + _users = result.get('users') + + for user in _users: + user_dict = dict() + user_dict['name'] = user.get('name') + user_dict['emails'] = [email['address'] for email in user.get('emails')] + user_dict['username'] = user.get('username') + user_dict['type'] = user.get('type') + user_dict['status'] = user.get('status') + user_dict['roles'] = user.get('roles') + user_dict['id'] = user.get('_id') + users.append(user_dict) + + except Exception as e: + logger.error('Exception in fetching public rooms {e}'.format( + e=e + ), exc_info=True) + + return users