diff --git a/tootapalooza/cli.py b/tootapalooza/cli.py index 1f07da0..8aa2c9f 100644 --- a/tootapalooza/cli.py +++ b/tootapalooza/cli.py @@ -16,21 +16,25 @@ import argparse import sys from pathlib import Path import random +import re + +args=None class Tooter(Mastodon): credentials: dict = {} - hostname: str = '' - files: dict = {} - client_id: str = '.tootapalooza.env' + hostname : str = '' + files : dict = {} + client_id : str = '.tootapalooza.env' def __init__(self, name: str): - self.name = name - cred_dict = self.credentials[self.name] - self.username = cred_dict['addr'] - self.password = cred_dict['pass'] - self.cred_file = f'.tootapalooza-usercred-{self.name}.env' + cred_dict = self.credentials[name] + self.name = name + self.username = cred_dict['addr'] + self.password = cred_dict['pass'] + self.displayname = cred_dict['name'] + self.cred_file = f'.tootapalooza-usercred-{self.name}.env' - super().__init__(client_id=self.client_id, api_base_url=self.hostname) + super().__init__(client_id=self.client_id) self.log_in( self.username, @@ -41,10 +45,6 @@ class Tooter(Mastodon): @classmethod def load_credentials(cls, file: str) -> None: as_dict = toml.load(file) - try: - cls.hostname = as_dict.pop('host') - except KeyError: - raise KeyError('must provide a hostname') for username, fields in as_dict.items(): if not isinstance(fields, dict): raise TypeError(f'{username} has no key/value pairs') @@ -62,50 +62,6 @@ class Tooter(Mastodon): with item.open('r') as f: cls.files[f.name] = f.readlines() - -def check_public_timeline(tooter: Tooter): - """Do one run. Connect to the database, connect to the server, get the public timeline. - Look at users and check to see if any are potential impersonators. Then exit.""" - - # Here's the idea: pick a chunk_size. Ask the server for that many toots off the public - # timeline. As long as the server gives us as many as we asked for, keep trying. - # as soon as we get less than we asked for, quit. - # - # XXX Not sure about rate-limiting - # - chunk_size = 20 - max_posts = 1000 - timeline_list = [] - userid_list = {} - total = 0 - calls = 0 - domain_def = tooter.hostname.split('/')[2] - while total < max_posts: - timeline_list = tooter.timeline(timeline='public', limit=chunk_size) - calls += 1 - for post in timeline_list: - userid = post.account.acct - name_and_domain = userid.split('@', 1) - username = name_and_domain[0] - - if len(name_and_domain) == 2: - domain = name_and_domain[1] - else: - # if there is no domain, then it's a local account - domain = domain_def - userid_list[userid] = (username, domain, - post.account.display_name, post.account.bot, post.url) - - posts_indexed = len(timeline_list) - if posts_indexed == 0: - # We got fewer than we asked for. Drop out of the loop. - break - total += posts_indexed - - # Ok, we got them all, time to insert - return (f'{calls} calls to get {total} posts,' - +f' {len(userid_list)} users processed') - def daemon_main(tooter: Tooter): """Run from a command line.""" @@ -117,35 +73,40 @@ def once(tooter: Tooter): """Run from a command line.""" # message = check_public_timeline(tooter) message = f'{tooter.name} says hi!' - tooter.toot( - # random sentence... - random.choice( - # from a random line... - random.choice( - # from a random file... - random.choice( - list(tooter.files.values()) - ) - ) - # stripped and split on full stops... - .strip().split('.') - ) - # and of weird punctuation - .strip() - ) + sourcefile = random.choice(list(Tooter.files.values())) + startline = random.randint(0,len(sourcefile)) + sourceline = '' + i=0 + while(len(sourceline) < 400 and startline+i < len(sourcefile)): + sourceline=sourceline+sourcefile[startline+i] + i+=1 + + tootline = re.search( '((\s|\S){,400})\.', sourceline ) + if( tootline ): + message=tootline.group(0).strip() + else: + message=sourceline.strip() + + if( args.dry_run ): + print(f"toot message: \"{message}\"") + else: + tooter.toot(message) return 0 def main(): + global args parser = argparse.ArgumentParser( description='Randomly interact with a Mastodon timeline.') parser.add_argument( '-d', '--debug', action='store_true', help='Enable debugging messages.') parser.add_argument( '-o', '--once', action='store_true', help='Run once and exit. Default is to run as a daemon.') + parser.add_argument( '-n', '--dry-run', action='store_true', + help='Don\'t toot. Just show what would be done.') parser.add_argument( '-D', '--directory', default='text', - help='Change directory to source files from.') + help='Directory with text source files for toot bodies.') parser.add_argument( 'file', type=argparse.FileType('r'), - help='Change file to source users from.') + help='TOML file with user credentials (see server-util/README.md).') args = parser.parse_args() p = Path(args.directory)