def main(): @RTMClient.run_on(event='message') def handle(web_client=None, data=None, **kwargs): print(f'Message data: {data}') if __should_handle(user=data.get('user'), text=data.get('text')): handle_message(data, web_client) global __web_client __web_client = WebClient(token=__slack_token) __rtm_client = RTMClient(token=__slack_token) __rtm_future = None while True: try: __rtm_future = __rtm_client.start() print("Learning bot is connected!") break except Exception: print( "Failed to connect to Slack; retrying in 5 seconds\n\n\n\n\n" ) time.sleep(5) asyncio.gather(__rtm_future, schedule_monitor())
def __init__(self): logging.basicConfig( level=os.environ.get("LOGLEVEL", "DEBUG"), format= '%(asctime)s - %(name)s:%(lineno)d - %(levelname)s - %(message)s', ) self.__log = logging.getLogger(type(self).__name__) self.__log.info("Starting Moonbeam") self.__config = self.__load_config(prefix="Moonbeam") if 'BOT_TOKEN' not in self.__config: raise RuntimeError("BOT_TOKEN not found in config") self.__web_client = WebClient(self.__config['BOT_TOKEN']) self.__rtm_client = RTMClient( token=self.__config.get("BOT_TOKEN"), ping_interval=30, auto_reconnect=True, ) self.__trigger_words = [] self.__plugins = [] self.__load_plugins() self.__rtm_client.run_on(event='message')(self.__process_message) self.__rtm_client.run_on(event='user_typing')(self.__process_typing) self.__rtm_client.run_on(event='reaction_added')( self.__process_reaction_added) self.__rtm_client.run_on(event='reaction_removed')( self.__process_reaction_removed) self.__rtm_client.start()
def serve_forever(self): self.sc = RTMClient(token=self.token, proxy=self.proxies) @RTMClient.run_on(event="open") def get_bot_identity(**payload): self.bot_identifier = SlackPerson(payload["web_client"], payload["data"]["self"]["id"]) # only hook up the message callback once we have our identity set. self._setup_slack_callbacks() # log.info('Verifying authentication token') # self.auth = self.api_call("auth.test", raise_errors=False) # if not self.auth['ok']: # raise SlackAPIResponseError(error=f"Couldn't authenticate with Slack. Server said: {self.auth['error']}") # log.debug("Token accepted") log.info("Connecting to Slack real-time-messaging API") self.sc.start() # Inject bot identity to alternative prefixes self.update_alternate_prefixes() try: while True: sleep(1) except KeyboardInterrupt: log.info("Interrupt received, shutting down..") return True except Exception: log.exception("Error reading from RTM stream:") finally: log.debug("Triggering disconnect callback") self.disconnect_callback()
def _register_plugin_actions(self, plugin_class, metadata, cls_instance, fn_name, fn, class_help): fq_fn_name = "{}.{}".format(plugin_class, fn_name) if fn.__doc__: self._help['human'][class_help][ fq_fn_name] = self._parse_human_help(fn.__doc__) for action, config in metadata['plugin_actions'].items(): if action == 'process': event_type = config['event_type'] RTMClient.on(event=event_type, callback=callable_with_sanitized_event(fn)) if action == 'respond_to' or action == 'listen_to': for regex in config['regex']: event_handler = { 'class': cls_instance, 'class_name': plugin_class, 'function': fn, 'regex': regex } key = "{}-{}".format(fq_fn_name, regex.pattern) self._plugin_actions[action][key] = event_handler self._help['robot'][class_help].append( self._parse_robot_help(regex, action)) if action == 'schedule': Scheduler.get_instance().add_job(fq_fn_name, trigger='cron', args=[cls_instance], id=fq_fn_name, replace_existing=True, **config) if action == 'route': for route_config in config: bottle.route(**route_config)(fn)
def test_02(self): logger = FoxylibLogger.func_level2logger(self.test_02, logging.DEBUG) loop = asyncio.get_event_loop() rtm_client = RTMClient(token=FoxylibSlack.xoxb_token(), run_async=True, loop=loop) async def inf_loop(): logger = logging.getLogger() while 1: try: logger.info("Ping Pong! I'm alive") await asyncio.sleep(900) except asyncio.CancelledError: break tasks = asyncio.gather(rtm_client.start(), inf_loop()) def callback(signum, frame): tasks.cancel() logger.warning("Cancelling tasks...") # loop.add_signal_handler(signal.SIGINT, callback) signal.signal(signal.SIGINT, callback) signal.signal(signal.SIGTERM, callback) try: loop.run_until_complete(tasks) except asyncio.CancelledError as e: logger.error(e) finally: logger.info("Quitting... Bye!")
def connect(self): ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE self.client = RTMClient(token=self.token, ssl=ssl_context) self.client.run_on(event='message')(self.GetMessage) self.client.start()
def run(): import asyncio rtm_client = RTMClient(token=os.environ["SLACK_API_TOKEN"], run_async=True) loop = asyncio.get_event_loop() loop.set_debug(True) loop.run_until_complete(rtm_client.start())
class RTMClient(Singleton): @wraps(SlackRTMClient.__init__) def __init__(self, token, *args, **kwargs): super().__init__() self._client = SlackRTMClient(token=token, run_async=True, loop=asyncio.get_running_loop(), *args, **kwargs) old_os_name = os.name os.name = 'nt' self._client.start() os.name = old_os_name @classmethod @wraps(SlackRTMClient.__init__) def start(cls, token, *args, **kwargs): return cls.instantiate(token, *args, **kwargs)._client @classmethod async def stop(cls): await cls.instance()._client.async_stop() @classmethod def on(cls, event): def decorator(callback): @SlackRTMClient.run_on(event=event) @wraps(callback) async def wrapper(**payload): await callback(**payload) return wrapper return decorator
def __init__(self): # this is the same environment variable that postgres uses, so you only # need to pass it once to compose self.db = db.PGDriver(password=os.environ["POSTGRES_PASSWORD"]) self.userid = None slack_token = os.environ["SLACK_BOT_USER_TOKEN"] self.rtm_client = RTMClient(token=slack_token)
def __init__(self): slack_token = os.environ["SLACK_BDD_API_TOKEN"] self.rtm_client = RTMClient(token=slack_token) self.rtm_client.on(event="message", callback=self.listen) self.rtm_thread = threading.Thread(name="rtm_client", target=self.rtm_client.start) self.rtm_thread.start()
async def test_issue_611(self): channel_id = os.environ[SLACK_SDK_TEST_RTM_TEST_CHANNEL_ID] text = "This message was sent by <https://slack.dev/python-slackclient/|python-slackclient>! (test_issue_611)" self.message_count, self.reaction_count = 0, 0 async def process_messages(**payload): self.logger.info(payload) if "subtype" in payload["data"] and payload["data"][ "subtype"] == "message_replied": return # skip self.message_count += 1 raise Exception("something is wrong!" ) # This causes the termination of the process async def process_reactions(**payload): self.logger.info(payload) self.reaction_count += 1 rtm = RTMClient(token=self.bot_token, run_async=True) RTMClient.on(event='message', callback=process_messages) RTMClient.on(event='reaction_added', callback=process_reactions) web_client = WebClient(token=self.bot_token, run_async=True) message = await web_client.chat_postMessage(channel=channel_id, text=text) ts = message["ts"] await asyncio.sleep(3) # intentionally not waiting here rtm.start() try: await asyncio.sleep(3) first_reaction = await web_client.reactions_add(channel=channel_id, timestamp=ts, name="eyes") self.assertFalse("error" in first_reaction) await asyncio.sleep(2) should_be_ignored = await web_client.chat_postMessage( channel=channel_id, text="Hello?", thread_ts=ts) self.assertFalse("error" in should_be_ignored) await asyncio.sleep(2) second_reaction = await web_client.reactions_add( channel=channel_id, timestamp=ts, name="tada") self.assertFalse("error" in second_reaction) await asyncio.sleep(2) self.assertEqual(self.message_count, 1) self.assertEqual(self.reaction_count, 2) finally: if not rtm._stopped: rtm.stop()
def main(): flags.mark_flag_as_required('customer') CUSTOMER_NAME = FLAGS.customer customer_codes ,msg_queue = cfg.read_config() rtm_client = RTMClient(token=customer_codes['customer1']) print(f'logging {FLAGS.customer}:{customer_codes["customer1"]}') rtm_client.start()
async def slack_main(): loop = asyncio.get_event_loop() rtm_client = RTMClient(token=FoxylibSlack.xoxb_token(), run_async=True, loop=loop) executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) await asyncio.gather( loop.run_in_executor(executor, partial(sync_loop, rtm_client)), rtm_client.start() )
def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) task = asyncio.ensure_future(self.mock_server(), loop=self.loop) self.loop.run_until_complete(asyncio.wait_for(task, 0.1)) self.client = RTMClient(token=FoxylibSlack.xoxb_token(), loop=self.loop, auto_reconnect=False)
def __init__(self, token): self._slack_reader = RTMClient(token=token) self._slack_reader.start() self.client = WebClient(token=token) self._username_cache = {} self._channel_name_cache = {} self._logger = logging.getLogger('Transport') self.events = []
def run(self): self._running = True asyncio.set_event_loop(self._loop) rtm_client = RTMClient(token=SLACK_TOKEN) # rtm_client.start() does not like being run in a thread, # so just do the parts of it that work in a thread manually.... future = asyncio.ensure_future(rtm_client._connect_and_read(), loop=self._loop) self._loop.run_until_complete(future) return
def main(): @RTMClient.run_on(event='message') def handle(**kwargs): data = kwargs['data'] text = data['text'] if data['user'] != __self_user_id and len(text) is not 0 and text.startswith('!'): command.runCommand(kwargs) rtm_client = RTMClient(token=__slack_token) rtm_client.start()
def slack_bot(self): print('\033[0;32m' + "[!] Starting slack bot!\033[0m") try: self.slack_data['text'] = 'Ready for action!' requests.post(url='https://slack.com/api/chat.postMessage', data=self.slack_data) rtm_client = RTMClient(token=os.environ.get('SLACK_BOT_TOKEN')) rtm_client.start() except: pass
def connect(self, loop): asyncio.set_event_loop(loop) ssl_context = ssl_lib.create_default_context(cafile=certifi.where()) self._slack_rtm = RTMClient(token=self._token, ssl=ssl_context, run_async=True, loop=loop) self._slack_rtm.run_on(event="message")(self.get_message) loop.run_until_complete(self._slack_rtm.start())
def __init__(self, name: str, pattern: str, remarks_location: str, **kwargs): self.name = name self.pattern = pattern self.remarks_location = remarks_location self.slack_id = None self._rtm_client = RTMClient(**kwargs) self.slack_client = WebClient(**kwargs) self.remarks = self.get_file_contents()
def start_work(retries=0): try: rtm_client = RTMClient(token=os.environ["SLACKBOT_API_TOKEN"], auto_reconnect=True) rtm_client.start() except Exception as e: print(f'main loop crash {e}, try to restart, attempt {retries}') if retries == 3: raise e time.sleep(retries * 15) start_work(retries + 1)
def add_listener2rtm_client(cls, rtm_client, *, event: str, callback: Callable): # reference: RTMClient.on if isinstance(callback, list): for cb in callback: RTMClient._validate_callback(cb) previous_callbacks = rtm_client._callbacks[event] RTMClient._callbacks[event] = list(set(previous_callbacks + callback)) else: RTMClient._validate_callback(callback) rtm_client._callbacks[event].append(callback)
async def test_issue_530_async(self): try: rtm_client = RTMClient(token="I am not a token", run_async=True) await rtm_client.start() self.fail("Raising an error here was expected") except Exception as e: self.assertEqual( "The request to the Slack API failed.\n" "The server responded with: {'ok': False, 'error': 'invalid_auth'}", str(e)) finally: if not rtm_client._stopped: rtm_client.stop()
def __init__(self, token, external_functions=None): self.token = token self.external_functions = external_functions or self.DEFAULT_EXT_FUNCS self.web_client = WebClient(token=self.token) self.rtm_client = RTMClient(token=self.token) self.bot_id = self._connect() self.bot_id_text = f'<@{self.bot_id}>' # Decorate the message handler self.rtm_client.run_on(event='message')(self._message_handler)
def __init__(self, token, channel, cache): """ Constructor :param token: Authentification token for bot :param channel: Name of the channel where the bot is hosted :param cache: Location where to cache data """ # Bot mention detection self._self_mention = None self._channel = channel self._bot_id = None # Commands self._keywords = [] self._authors = [] self._known_cmd = { 'help': (self._help_callback, ''), 'list_keywords': (self._list_keyords_callback, ''), 'add_keywords': (self._add_keyords_callback, 'List of space separated keywords ' 'to add'), 'run_daily_arxiv_search': (self._run_daily_arxiv_search, '') } # Arxiv wrapper self._cache_folder = cache self._arxiv_cfg = _join(self._cache_folder, 'arxiv.cfg') if not _exists(self._arxiv_cfg): # cs.CV: Compute Vision # cs.AI: Artificial Inteligence # cs.LG: Machine learning # stat.ML: Machine learning # cs.GR: Graphics self._arxiv = ArxivParser( category=['cs.CV', 'cs.AI', 'cs.LG', 'stat.ML', 'cs.GR']) self._arxiv.save_config(self._arxiv_cfg) else: self._arxiv = ArxivParser.from_config(self._arxiv_cfg) # Reload authors/keywords self._load_config(self._cache_folder) # Create client, define message callback + start service # run aynchronously # https://github.com/slackapi/python-slackclient/blob/master/tutorial/PythOnBoardingBot/async_app.py # https://stackoverflow.com/questions/56539228 # Start Slack client + scheduler for daily research loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) self.client = RTMClient(token=token, run_async=True, loop=loop) self.client.on(event='open', callback=self.open_callback) self.client.on(event='message', callback=self.message_callback) loop.run_until_complete( asyncio.gather(self._daily_scheduler(token), self.client.start())) loop.close()
async def test_issue_558(self): channel_id = os.environ[SLACK_SDK_TEST_RTM_TEST_CHANNEL_ID] text = "This message was sent by <https://slack.dev/python-slackclient/|python-slackclient>! (test_issue_558)" self.message_count, self.reaction_count = 0, 0 async def process_messages(**payload): self.logger.debug(payload) self.message_count += 1 await asyncio.sleep(10) # this used to block all other handlers async def process_reactions(**payload): self.logger.debug(payload) self.reaction_count += 1 rtm = RTMClient(token=self.bot_token, run_async=True) RTMClient.on(event='message', callback=process_messages) RTMClient.on(event='reaction_added', callback=process_reactions) web_client = WebClient(token=self.bot_token, run_async=True) message = await web_client.chat_postMessage(channel=channel_id, text=text) self.assertFalse("error" in message) ts = message["ts"] await asyncio.sleep(3) # intentionally not waiting here rtm.start() await asyncio.sleep(3) try: first_reaction = await web_client.reactions_add(channel=channel_id, timestamp=ts, name="eyes") self.assertFalse("error" in first_reaction) await asyncio.sleep(2) message = await web_client.chat_postMessage(channel=channel_id, text=text) self.assertFalse("error" in message) # used to start blocking here # This reaction_add event won't be handled due to a bug second_reaction = await web_client.reactions_add( channel=channel_id, timestamp=ts, name="tada") self.assertFalse("error" in second_reaction) await asyncio.sleep(2) self.assertEqual(self.message_count, 1) self.assertEqual(self.reaction_count, 2) # used to fail finally: if not rtm._stopped: rtm.stop()
def __init__( self, *, token: str, ) -> None: self._webclient = WebClient( token=token, run_async=True, ) self._rtm_client = RTMClient( token=token, run_async=True, )
def run_bot(): token = os.environ.get('SLACKBOT_TOKEN') report_url = os.environ.get('SLACKBOT_REPORT_URL') rtm_client = RTMClient(token=token) web_client = WebClient(token=token) global metrics metrics = None global channels channels = { u['id']: u['name'] for u in web_client.channels_list()['channels'] } global users users = {u['id']: u['name'] for u in web_client.users_list()['members']} if report_url: # Reports are enabled, so start reporting thread global last_run last_run = None metrics = defaultdict(int) class ReportingThread(threading.Thread): def run(self): while True: curr_min = datetime.utcnow().minute global last_run global metrics if last_run == curr_min: sleep(5) continue last_run = curr_min if not metrics: continue try: metrics = json.dumps(metrics) resp = post(url=report_url, json=dict(text=metrics)) resp.raise_for_status() except Exception as exc: print(exc) metrics = defaultdict(int) reporting = ReportingThread(name='Reporting Thread') reporting.start() while True: try: rtm_client.start() except Exception as exc: logging.error('Exception during rtm_client.start', exc)
class TestRTMClient(unittest.TestCase): """Runs integration tests with real Slack API https://github.com/slackapi/python-slackclient/issues/605 """ def setUp(self): self.logger = logging.getLogger(__name__) self.bot_token = os.environ[SLACK_SDK_TEST_CLASSIC_APP_BOT_TOKEN] self.channel_id = os.environ[SLACK_SDK_TEST_RTM_TEST_CHANNEL_ID] self.rtm_client = RTMClient(token=self.bot_token, run_async=False) def tearDown(self): # Reset the decorators by @RTMClient.run_on RTMClient._callbacks = collections.defaultdict(list) @pytest.mark.skipif(condition=is_not_specified(), reason="still unfixed") def test_issue_605(self): self.text = "This message was sent to verify issue #605" self.called = False @RTMClient.run_on(event="message") def process_messages(**payload): self.logger.info(payload) self.called = True def connect(): self.logger.debug("Starting RTM Client...") self.rtm_client.start() t = threading.Thread(target=connect) t.setDaemon(True) try: t.start() self.assertFalse(self.called) time.sleep(3) self.web_client = WebClient( token=self.bot_token, run_async=False, loop=asyncio.new_event_loop( ), # TODO: this doesn't work without this ) new_message = self.web_client.chat_postMessage( channel=self.channel_id, text=self.text) self.assertFalse("error" in new_message) time.sleep(5) self.assertTrue(self.called) finally: t.join(.3)
def __init__(self, bot_user_token, bot_id=None): self.name = BOT_NAME self.bot_id = bot_id if not self.bot_id: # Read the bot's id by calling auth.test response = WebClient(token=bot_user_token).api_call('auth.test') self.bot_id = response['user_id'] logger.info(f'My bot_id is {self.bot_id}') # Create an instance of the RTM client self.sc = RTMClient(token=bot_user_token, run_async=True) # Connect our callback events to the RTM client RTMClient.run_on(event="hello")(self.on_hello) RTMClient.run_on(event="message")(self.on_message) RTMClient.run_on(event="goodbye")(self.on_goodbye) # startup our client event loop self.future = self.sc.start() self.bot_start = dt.now() self.msg_lock = Lock() self.at_bot = f'<@{self.bot_id}>' self.comic_history = [] logger.info("Created new SlackClient Instance") self.xkcd = XkcdApi()