From f6eef5dc73e492b42f18288074de1d85ed1d9bc9 Mon Sep 17 00:00:00 2001 From: Cathy Hu Date: Fri, 17 Jul 2020 23:36:14 +0200 Subject: [PATCH] [twitter] Add start, stop, status REST endpoints --- kibicara/platforms/twitter/bot.py | 31 +++++++++++++++++++--------- kibicara/platforms/twitter/model.py | 3 ++- kibicara/platforms/twitter/webapi.py | 25 +++++++++++++++++++++- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/kibicara/platforms/twitter/bot.py b/kibicara/platforms/twitter/bot.py index c1448ed..9ad7afb 100644 --- a/kibicara/platforms/twitter/bot.py +++ b/kibicara/platforms/twitter/bot.py @@ -7,7 +7,7 @@ from kibicara.config import config from kibicara.platformapi import Censor, Message, Spawner from kibicara.platforms.twitter.model import Twitter from logging import getLogger -from peony import PeonyClient +from peony import PeonyClient, exceptions logger = getLogger(__name__) @@ -17,18 +17,21 @@ class TwitterBot(Censor): def __init__(self, twitter_model): super().__init__(twitter_model.hood) self.twitter_model = twitter_model - self.client = PeonyClient( - consumer_key=config['twitter']['consumer_key'], - consumer_secret=config['twitter']['consumer_secret'], - access_token=twitter_model.access_token, - access_token_secret=twitter_model.access_token_secret, - ) + self.enabled = self.twitter_model.enabled self.polling_interval_sec = 60 self.mentions_since_id = self.twitter_model.mentions_since_id self.dms_since_id = self.twitter_model.dms_since_id async def run(self): - if self.twitter_model.successful_verified: + try: + if not self.twitter_model.verified: + raise ValueError('Oauth Handshake not completed') + self.client = PeonyClient( + consumer_key=config['twitter']['consumer_key'], + consumer_secret=config['twitter']['consumer_secret'], + access_token=self.twitter_model.access_token, + access_token_secret=self.twitter_model.access_token_secret, + ) if self.twitter_model.mentions_since_id is None: logger.debug('since_id is None in model, fetch newest mention id') await self._poll_mentions() @@ -37,8 +40,16 @@ class TwitterBot(Censor): await self._poll_direct_messages() logger.debug('Starting Twitter bot: %s' % self.twitter_model.__dict__) await gather(self.poll(), self.push()) - else: - logger.debug('Twitter Bot not started: Oauth Handshake not completed') + except CancelledError: + logger.debug(f'Bot {self.twitter_model.hood.name} received Cancellation.') + raise + except exceptions.Unauthorized: + logger.debug(f'Bot {self.twitter_model.hood.name} has invalid auth token.') + await self.twitter_model.update(enabled=False) + self.enabled = self.twitter_model.enabled + raise + finally: + logger.debug(f'Bot {self.twitter_model.hood.name} stopped.') async def poll(self): while True: diff --git a/kibicara/platforms/twitter/model.py b/kibicara/platforms/twitter/model.py index 592f4c8..37f10fa 100644 --- a/kibicara/platforms/twitter/model.py +++ b/kibicara/platforms/twitter/model.py @@ -13,7 +13,8 @@ class Twitter(Model): mentions_since_id: Integer(allow_null=True) = None access_token: Text() access_token_secret: Text() - successful_verified: Boolean() = False + verified: Boolean() = False + enabled: Boolean() = False class Mapping(Mapping): table_name = 'twitterbots' diff --git a/kibicara/platforms/twitter/webapi.py b/kibicara/platforms/twitter/webapi.py index 37b0a09..2a880be 100644 --- a/kibicara/platforms/twitter/webapi.py +++ b/kibicara/platforms/twitter/webapi.py @@ -43,8 +43,30 @@ async def twitter_delete(twitter=Depends(get_twitter)): await twitter.delete() +@router.get('/{twitter_id}/status', status_code=status.HTTP_200_OK) +async def twitter_status(twitter=Depends(get_twitter)): + return {'status': spawner.get(twitter).status.name} + + +@router.post('/{twitter_id}/start', status_code=status.HTTP_200_OK) +async def twitter_start(twitter=Depends(get_twitter)): + await twitter.update(enabled=True) + spawner.get(twitter).start() + return {} + + +@router.post('/{twitter_id}/stop', status_code=status.HTTP_200_OK) +async def twitter_stop(twitter=Depends(get_twitter)): + await twitter.update(enabled=False) + spawner.get(twitter).stop() + return {} + + @router.post('/', status_code=status.HTTP_201_CREATED) async def twitter_create(response: Response, hood=Depends(get_hood)): + """ + `https://api.twitter.com/oauth/authorize?oauth_token=` + """ try: request_token = await get_oauth_token( config['twitter']['consumer_key'], @@ -78,7 +100,8 @@ async def twitter_read_callback(oauth_token: str, oauth_verifier: str): await twitter.update( access_token=access_token['oauth_token'], access_token_secret=access_token['oauth_token_secret'], - successful_verified=True, + verified=True, + enabled=True, ) spawner.start(twitter) return []