예제 #1
0
 def save_data(self, trigger, entry) -> bool:
     """
     Post a new toot to Mastodon
     :param trigger: current trigger
     :param entry: data from Feeds
     :return: boolean
     """
     status = False
     # check if we have a 'good' title
     content = str("{title} {link}").format(title=entry.title,
                                            link=entry.link)
     # if not then use the content
     content = self.set_mastodon_content(content)
     status = False
     try:
         toot_api = MastodonAPI(access_token='yeoboseyo_clientcred.secret',
                                api_base_url=settings.MASTODON_INSTANCE)
         status = True
     except ValueError as e:
         logger.error(e)
         status = False
     try:
         toot_api.toot(content)
         status = True
     except Exception:
         status = False
     return status
예제 #2
0
    def auth(self, request):
        """
            get the auth of the services
            :param request: contains the current session
            :type request: dict
            :rtype: dict
        """
        # create app
        redirect_uris = '%s://%s%s' % (request.scheme, request.get_host(),
                                       reverse('mastodon_callback'))
        us = UserService.objects.get(user=request.user, name='ServiceMastodon')
        client_id, client_secret = MastodonAPI.create_app(
            client_name="TriggerHappy",
            api_base_url=us.host,
            redirect_uris=redirect_uris)

        us.client_id = client_id
        us.client_secret = client_secret
        us.save()

        us = UserService.objects.get(user=request.user, name='ServiceMastodon')
        # get the token by logging in
        mastodon = MastodonAPI(client_id=client_id,
                               client_secret=client_secret,
                               api_base_url=us.host)
        token = mastodon.log_in(username=us.username, password=us.password)
        us.token = token
        us.save()
        return self.callback_url(request)
예제 #3
0
 def callback_url(self, request):
     us = UserService.objects.get(user=request.user, name='ServiceMastodon')
     mastodon = MastodonAPI(client_id=us.client_id,
                            client_secret=us.client_secret,
                            access_token=us.token,
                            api_base_url=us.host)
     redirect_uris = '%s://%s%s' % (request.scheme, request.get_host(),
                                    reverse('mastodon_callback'))
     return mastodon.auth_request_url(redirect_uris=redirect_uris)
예제 #4
0
    def save_data(self, trigger_id, **data):
        """
            get the data from the service

            :param trigger_id: id of the trigger
            :params data, dict
            :rtype: dict
        """
        title, content = super(ServiceMastodon,
                               self).save_data(trigger_id, **data)

        # check if we have a 'good' title
        if self.title_or_content(title):

            content = str("{title} {link}").format(title=title,
                                                   link=data.get('link'))
            content += self.get_tags(trigger_id)
        # if not then use the content
        else:
            content += " " + data.get('link')
            content += " " + self.get_tags(trigger_id)

        content = self.set_mastodon_content(content)

        us = UserService.objects.get(user=self.user,
                                     token=self.token,
                                     name='ServiceMastodon')

        try:
            toot_api = MastodonAPI(client_id=us.client_id,
                                   client_secret=us.client_secret,
                                   access_token=self.token,
                                   api_base_url=us.host)
        except ValueError as e:
            logger.error(e)
            status = False
            update_result(trigger_id, msg=e, status=status)

        media_ids = None
        try:
            if settings.DJANGO_TH['sharing_media']:
                # do we have a media in the content ?
                content, media = self.media_in_content(content)
                if media:
                    # upload the media first
                    media_ids = toot_api.media_post(media_file=media)
                    media_ids = [media_ids]

            toot_api.status_post(content, media_ids=media_ids)

            status = True
        except Exception as inst:
            logger.critical("Mastodon ERR {}".format(inst))
            status = False
            update_result(trigger_id, msg=inst, status=status)
        return status
예제 #5
0
 def __init__(self,
              logger: Logger,
              client_id: str,
              client_secret: str,
              access_token: str,
              api_base_url: str,
              reply_everyone: bool = False):
     self.logger = logger
     self.api = MastodonAPI(client_id, client_secret, access_token,
                            api_base_url)
     self.myself = self.api.account_verify_credentials()
     self.reply_everyone = reply_everyone
     self._cached = dict()
예제 #6
0
    def save_data(self, trigger_id, **data):
        """
            get the data from the service

            :param trigger_id: id of the trigger
            :params data, dict
            :rtype: dict
        """
        title, content = super(ServiceMastodon, self).save_data(
            trigger_id, **data)

        if self.title_or_content(title):

            content = str("{title} {link}").format(
                title=title, link=data.get('link'))

        content += self.get_tags(trigger_id)

        content = self.set_mastodon_content(content)

        us = UserService.objects.get(user=self.user,
                                     token=self.token,
                                     name='ServiceMastodon')

        try:
            toot_api = MastodonAPI(
                    client_id=us.client_id,
                    client_secret=us.client_secret,
                    access_token=self.token,
                    api_base_url=us.host
            )
        except ValueError as e:
            logger.error(e)
            update_result(trigger_id, msg=e, status=False)

        try:
            toot_api.toot(content)
            status = True
        except Exception as inst:
            logger.critical("Mastodon ERR {}".format(inst))
            update_result(trigger_id, msg=inst, status=False)
            status = False

        return status
예제 #7
0
    def check(self, request, user):
        """
        check if the service is well configured
        :return: Boolean
        """
        redirect_uris = '%s://%s%s' % (request.scheme, request.get_host(),
                                       reverse('mastodon_callback'))
        us = UserService.objects.get(user=user, name='ServiceMastodon')
        client_id, client_secret = MastodonAPI.create_app(
            client_name="TriggerHappy",
            api_base_url=us.host,
            redirect_uris=redirect_uris)

        # get the token by logging in
        mastodon = MastodonAPI(client_id=client_id,
                               client_secret=client_secret,
                               api_base_url=us.host)
        try:
            mastodon.log_in(username=us.username, password=us.password)
            return True
        except MastodonIllegalArgumentError as e:
            return e
예제 #8
0
    def read_data(self, **kwargs):
        """
            get the data from the service

            :param kwargs: contain keyword args : trigger_id at least
            :type kwargs: dict
            :rtype: list
        """
        now = arrow.utcnow().to(settings.TIME_ZONE)
        my_toots = []
        search = {}
        since_id = None
        trigger_id = kwargs['trigger_id']
        date_triggered = arrow.get(kwargs['date_triggered'])

        def _get_toots(toot_api, toot_obj, search):
            """
                get the toots from mastodon and return the filters to use

                :param toot_obj: from Mastodon model
                :param search: filter used for MastodonAPI.search()
                :type toot_obj: Object ServiceMastodon
                :type search: dict
                :return: the filter named search, the toots
                :rtype: list
            """
            max_id = 0 if toot_obj.max_id is None else toot_obj.max_id
            since_id = 0 if toot_obj.since_id is None else toot_obj.since_id
            # get the toots for a given tag
            statuses = ''

            if toot_obj.tag:
                search['q'] = toot_obj.tag
                # do a search
                statuses = toot_api.search(**search)
                # just return the content of te statuses array
                statuses = statuses['statuses']

            # get the tweets from a given user
            elif toot_obj.tooter:
                search['id'] = toot_obj.tooter
                # call the user timeline and get his toot
                if toot_obj.fav:
                    statuses = toot_api.favourites(max_id=max_id,
                                                   since_id=since_id)
                else:
                    user_id = toot_api.account_search(q=toot_obj.tooter)
                    statuses = toot_api.account_statuses(
                        id=user_id[0]['id'],
                        max_id=toot_obj.max_id,
                        since_id=toot_obj.since_id)

            return search, statuses

        if self.token is not None:
            kw = {
                'app_label': 'th_mastodon',
                'model_name': 'Mastodon',
                'trigger_id': trigger_id
            }
            toot_obj = super(ServiceMastodon, self).read_data(**kw)

            us = UserService.objects.get(token=self.token,
                                         name='ServiceMastodon')
            try:
                toot_api = MastodonAPI(
                    client_id=us.client_id,
                    client_secret=us.client_secret,
                    access_token=self.token,
                    api_base_url=us.host,
                )
            except ValueError as e:
                logger.error(e)
                update_result(trigger_id, msg=e, status=False)

            if toot_obj.since_id is not None and toot_obj.since_id > 0:
                since_id = toot_obj.since_id
                search = {'since_id': toot_obj.since_id}

            # first request to Mastodon
            search, statuses = _get_toots(toot_api, toot_obj, search)

            if len(statuses) > 0:
                newest = None
                for status in statuses:
                    if newest is None:
                        newest = True
                        # first query ; get the max id
                        search['max_id'] = max_id = status['id']

                since_id = search['since_id'] = statuses[-1]['id'] - 1

                search, statuses = _get_toots(toot_api, toot_obj, search)

                newest = None
                if len(statuses) > 0:
                    my_toots = []
                    for s in statuses:
                        if newest is None:
                            newest = True
                            max_id = s['id'] - 1
                        toot_name = s['account']['username']
                        # get the text of the tweet + url to this one

                        title = _('Toot from <a href="{}">@{}</a>'.format(
                            us.host, toot_name))

                        my_date = arrow.get(s['created_at']).to(
                            settings.TIME_ZONE)
                        published = arrow.get(my_date).to(settings.TIME_ZONE)
                        if date_triggered is not None and \
                           published is not None and \
                           now >= published >= date_triggered:
                            my_toots.append({
                                'title': title,
                                'content': s['content'],
                                'link': s['url'],
                                'my_date': my_date
                            })
                            # digester
                            self.send_digest_event(trigger_id, title, s['url'])
                    cache.set('th_mastodon_' + str(trigger_id), my_toots)
                    Mastodon.objects.filter(trigger_id=trigger_id).update(
                        since_id=since_id, max_id=max_id)
        return my_toots
예제 #9
0
    def read_data(self, **kwargs):
        """
            get the data from the service

            :param kwargs: contain keyword args : trigger_id at least
            :type kwargs: dict
            :rtype: list
        """
        now = arrow.utcnow().to(settings.TIME_ZONE)
        my_toots = []
        search = {}
        since_id = None
        trigger_id = kwargs['trigger_id']
        date_triggered = arrow.get(kwargs['date_triggered'])

        def _get_toots(toot_api, toot_obj, search):
            """
                get the toots from mastodon and return the filters to use :
                search and count

                :param toot_obj: from Mastodon model
                :param search: filter used for MastodonAPI.search()
                :type toot_obj: Object
                :type search: dict
                :return: count that limit the quantity of tweet to retrieve,
                the filter named search, the tweets
                :rtype: list
            """

            # get the toots for a given tag
            statuses = ''
            count = 100
            if toot_obj.tag:
                count = 100
                search['count'] = count
                search['q'] = toot_obj.tag
                search['result_type'] = 'recent'
                # do a search
                statuses = toot_api.search(**search)
                # just return the content of te statuses array
                statuses = statuses['statuses']

            # get the tweets from a given user
            elif toot_obj.tooter:
                count = 200
                search['count'] = count
                search['username'] = toot_obj.tooter

                # call the user timeline and get his toot
                if toot_obj.fav:
                    count = 20
                    search['count'] = 20
                    statuses = toot_api.favourites(max_id=max_id,
                                                   since_id=since_id,
                                                   limit=count)
                else:
                    statuses = toot_api.account_statuses(
                        id=toot_obj.tooter,
                        max_id=max_id,
                        since_id=since_id,
                        limit=count)

            return count, search, statuses

        if self.token is not None:
            kw = {'app_label': 'th_mastodon', 'model_name': 'Mastodon',
                  'trigger_id': trigger_id}
            toot_obj = super(ServiceMastodon, self).read_data(**kw)

            us = UserService.objects.get(user=self.user,
                                         token=self.token,
                                         name='ServiceMastodon')
            try:
                toot_api = MastodonAPI(
                    client_id=us.client_id,
                    client_secret=us.client_secret,
                    access_token=self.token,
                    api_base_url=us.host
                )
            except ValueError as e:
                logger.error(e)
                update_result(trigger_id, msg=e, status=False)

            if toot_obj.since_id is not None and toot_obj.since_id > 0:
                since_id = toot_obj.since_id
                search = {'since_id': toot_obj.since_id}

            # first request to Mastodon
            count, search, statuses = _get_toots(toot_api, toot_obj, search)

            if len(statuses) > 0:
                newest = None
                for status in statuses:
                    if newest is None:
                        newest = True
                        # first query ; get the max id
                        search['max_id'] = max_id = status['id']

                since_id = search['since_id'] = statuses[-1]['id'] - 1

                count, search, statuses = _get_toots(toot_api, toot_obj,
                                                     search)

                newest = None
                if len(statuses) > 0:
                    my_toots = []
                    for s in statuses:
                        if newest is None:
                            newest = True
                            max_id = s['id'] - 1
                        toot_name = s['account']['username']
                        # get the text of the tweet + url to this one
                        if toot_obj.fav:
                            url = '{0}/api/v1/statuses/{1}'.format(
                                self.api_base_url, s['id'])
                            title = _('Toot Fav from @{}'.format(toot_name))
                        else:
                            url = '{0}/api/v1/accounts/{1}/statuses'.format(
                                self.api_base_url, s['id'])
                            title = _('Toot from @{}'.format(toot_name))
                        # Wed Aug 29 17:12:58 +0000 2012
                        my_date = arrow.get(s['created_at'],
                                            'ddd MMM DD HH:mm:ss Z YYYY')
                        published = arrow.get(my_date).to(settings.TIME_ZONE)
                        if date_triggered is not None and \
                           published is not None and \
                           now >= published >= date_triggered:
                            my_toots.append({'title': title,
                                             'content': s['content'],
                                             'link': url,
                                             'my_date': my_date})
                            # digester
                            self.send_digest_event(trigger_id, title, url)
                    cache.set('th_mastodon_' + str(trigger_id), my_toots)
                    Mastodon.objects.filter(trigger_id=trigger_id).update(
                        since_id=since_id,
                        max_id=max_id,
                        count=count)
        return my_toots