Module: tooter

Create a Tooter object that toots stuff

Tooter

Bases: Mastodon

Source code in mastoscore/tooter.py
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
class Tooter(Mastodon):
    credentials: dict = {}
    hostname: str = ''
    files: dict = {}

    def __init__(self, config, phase: str, server: str = ''):
        self.debug = config.getint(phase, 'debug')
        self.logger = logging.getLogger('tooter')
        logging.basicConfig(format='%(levelname)s\t%(message)s')
        self.logger.setLevel(self.debug)

        if server != "":
            self.logger.debug(f"Connecting to {server} anonymously")
            super().__init__(
                user_agent="mastoscore",
                debug_requests=False,
                feature_set="pleroma",
                request_timeout=10,
                api_base_url=server,
            )
            self.logger.info(f"Connected to {self.api_base_url} (anonymous)")
        else:
            self.cred_file = config.get(phase, 'cred_file')
            self.name = config.get(phase, 'botusername')
            self.acct = self.name
            self.logger.debug(
                f"Logging into {self.name} from {self.cred_file}")
            super().__init__(
                access_token=self.cred_file,
                user_agent="mastoscore",
                debug_requests=False,
                feature_set="pleroma",
                request_timeout=10,
            )
            account = self.me()
            self.id = account['id']
            self.logger.info(
                f"Logged in as {account.username} on {self.api_base_url} (uid {account.id})")

    def check_toot_ages(self, tootlist, interval=datetime.timedelta):
        returnlist = []
        oldest_date = datetime.datetime.utcnow() - interval
        for toot in tootlist:
            tootdate = toot['created_at']
            if tootdate > oldest_date.astimezone(datetime.timezone.utc):
                returnlist.append(toot)
        return returnlist

    def search_hashtag(self, hashtag=str, interval=datetime.timedelta, max=2000):
        ''' Given a hashtag, search the public timeline for that hashtag. Return only
            the toots that are in the given interval. E.g., if interval is 7 days,
            count back 7 days from right now, and return only toots on the hashtag
            since that moment.
        '''
        toots = []
        # According to https://docs.joinmastodon.org/methods/timelines/#tag
        # max page size, by default, is 40
        if max < 40:
            pagesize = max
        else:
            pagesize = 40
        page = self.timeline_hashtag(hashtag, limit=pagesize)
        # page = self.timeline_public(limit=pagesize)
        if len(page) == 0:
            self.logger.debug(f"No toots found for hashtag: {hashtag}")
            return toots

        # Keep fetching toots until we get to one that is older than the interval
        # or we get to the end.
        while (len(page) > 0 and len(toots) < max):
            # check to see if we have reached the oldest allowable toot
            toots_to_keep = self.check_toot_ages(page, interval)
            toots = toots + toots_to_keep
            self.logger.info(
                f"Added {len(toots_to_keep)} more toots, {len(toots)} total")
            # if the check ages function returns fewer than we sent to it
            # we have hit the end of the list of toots
            if len(toots_to_keep) < len(page):
                self.logger.debug("stopping due to age")
                return toots
            self.logger.debug(f"Requesting {pagesize} more toots")
            page = self.fetch_next(page)
            # According to https://docs.joinmastodon.org/api/rate-limits/#per-ip
            # the rate limit is 300 calls in 5 minutes. If we have 2000 toots we have
            # to fetch in pages of 40, that's 50 API calls + some authentication calls
            if len(toots) > max:
                # process what we just got and stop
                toots_to_keep = self.check_toot_ages(page, interval)
                toots = toots + toots_to_keep
                self.logger.debug(
                    f"More than {max} toots. (We got {len(toots)}). Stopping")
                break
        return toots

search_hashtag(hashtag=str, interval=datetime.timedelta, max=2000)

Given a hashtag, search the public timeline for that hashtag. Return only the toots that are in the given interval. E.g., if interval is 7 days, count back 7 days from right now, and return only toots on the hashtag since that moment.

Source code in mastoscore/tooter.py
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
def search_hashtag(self, hashtag=str, interval=datetime.timedelta, max=2000):
    ''' Given a hashtag, search the public timeline for that hashtag. Return only
        the toots that are in the given interval. E.g., if interval is 7 days,
        count back 7 days from right now, and return only toots on the hashtag
        since that moment.
    '''
    toots = []
    # According to https://docs.joinmastodon.org/methods/timelines/#tag
    # max page size, by default, is 40
    if max < 40:
        pagesize = max
    else:
        pagesize = 40
    page = self.timeline_hashtag(hashtag, limit=pagesize)
    # page = self.timeline_public(limit=pagesize)
    if len(page) == 0:
        self.logger.debug(f"No toots found for hashtag: {hashtag}")
        return toots

    # Keep fetching toots until we get to one that is older than the interval
    # or we get to the end.
    while (len(page) > 0 and len(toots) < max):
        # check to see if we have reached the oldest allowable toot
        toots_to_keep = self.check_toot_ages(page, interval)
        toots = toots + toots_to_keep
        self.logger.info(
            f"Added {len(toots_to_keep)} more toots, {len(toots)} total")
        # if the check ages function returns fewer than we sent to it
        # we have hit the end of the list of toots
        if len(toots_to_keep) < len(page):
            self.logger.debug("stopping due to age")
            return toots
        self.logger.debug(f"Requesting {pagesize} more toots")
        page = self.fetch_next(page)
        # According to https://docs.joinmastodon.org/api/rate-limits/#per-ip
        # the rate limit is 300 calls in 5 minutes. If we have 2000 toots we have
        # to fetch in pages of 40, that's 50 API calls + some authentication calls
        if len(toots) > max:
            # process what we just got and stop
            toots_to_keep = self.check_toot_ages(page, interval)
            toots = toots + toots_to_keep
            self.logger.debug(
                f"More than {max} toots. (We got {len(toots)}). Stopping")
            break
    return toots