diff --git a/tootapalooza/cli.py b/tootapalooza/cli.py index d7a806d..e6cc332 100644 --- a/tootapalooza/cli.py +++ b/tootapalooza/cli.py @@ -28,11 +28,12 @@ class Tooter(Mastodon): def __init__(self, name: str): cred_dict = self.credentials[name] - self.name = name + self.acct = 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' + self.cred_file = f'.tootapalooza-usercred-{self.acct}.env' super().__init__(client_id=self.client_id) @@ -41,7 +42,7 @@ class Tooter(Mastodon): self.password, to_file=self.cred_file ) - + self.id = self.me()['id'] @classmethod def load_credentials(cls, file: str) -> None: as_dict = toml.load(file) @@ -85,11 +86,26 @@ class Tooter(Mastodon): return(message) + def read_timeline(self, *timeline_args, **timeline_kwargs) -> list: + """Reads the given timeline (just a wrapper for self.timeline()) but + also updates the read marker for the timeline.""" + result = self.timeline(*timeline_args, **timeline_kwargs) + # try to get timeline from kwargs. if not passed as keyword, try to + # get as positional. if no positional args were passed, try to get + # as keyword again. + try: + timeline_name = timeline_kwargs.get('timeline',timeline_args[0]) + except IndexError: + timeline_name = timeline_kwargs['timeline'] + if( len(result) > 0 and not args.dry_run ): + self.markers_set([timeline_name], [result[-1].id]) + return result + def toot_tagged_public(self) -> int: """Get a random message, pick a small number of words in it to hashtag. Then toot it publicly.""" if( args.debug ): - print(f"{self.name} toot_tagged_public") + print(f"{self.acct} toot_tagged_public") rawmessage = self.new_message().split() numtaggable = sum(1 for word in rawmessage if len(word) > 3) # Pick a small number of words to tag, but not greater than the @@ -108,7 +124,7 @@ class Tooter(Mastodon): print(f"tagged toot message: \"{message}\"") else: if( args.debug ): - print(f"{self.name} tagged toots \"{message}\"") + print(f"{self.acct} tagged toots \"{message}\"") self.toot(message) return 0 @@ -116,13 +132,13 @@ class Tooter(Mastodon): def toot_plain_public(self) -> int: """Toot a random message.""" if( args.debug ): - print(f"{self.name} toot_plain_public") + print(f"{self.acct} toot_plain_public") message = self.new_message() if( args.dry_run ): print(f"toot message: \"{message}\"") else: if( args.debug ): - print(f"{self.name} toots \"{message}\"") + print(f"{self.acct} toots \"{message}\"") self.toot(message) return 0 @@ -134,36 +150,35 @@ class Tooter(Mastodon): print(f"toot unlisted message: \"{message}\"") else: if( args.debug ): - print(f"{self.name} toots unlisted \"{message}\"") + print(f"{self.acct} toots unlisted \"{message}\"") self.status_post( message, visibility='private' ) return( 0 ) def reply_random_local(self) -> int: if( args.debug ): - print(f"{self.name} reply_random_local") + print(f"{self.acct} reply_random_local") return(self._reply_random('local')) def reply_random_home(self) -> int: if( args.debug ): - print(f"{self.name} reply_random_home") + print(f"{self.acct} reply_random_home") return(self._reply_random('home')) def reply_random_public(self) -> int: if( args.debug ): - print(f"{self.name} reply_random_public") + print(f"{self.acct} reply_random_public") return(self._reply_random('public')) def _reply_random(self, timeline: str) -> int: - """Read the given timeline, pick a post at random, reply to it. - Updates the read marker for that timeline.""" + """Read the given timeline, pick a post at random, reply to it.""" chunk_size = 20 max_posts = 100 timeline_list = [] while( len(timeline_list) < max_posts ): - posts_received = self.timeline(timeline=timeline, limit=chunk_size) + posts_received = self.read_timeline(timeline=timeline, limit=chunk_size) if( len(posts_received) == 0 ): break timeline_list.extend(posts_received) @@ -172,28 +187,26 @@ class Tooter(Mastodon): message = self.new_message() if( args.dry_run ): - print(f"{self.name} replied to {timeline} {reply_post.id}") + print(f"{self.acct} replied to {timeline} {reply_post.id}") else: if( args.debug ): - print(f"{self.name} replied to {reply_post.account.acct} {reply_post.uri}") - self.markers_set([timeline], [reply_post.id]) + print(f"{self.acct} replied to {reply_post.account.acct} {reply_post.uri}") self.status_post( message, in_reply_to_id=reply_post.id, visibility='public' ) def follow_random_local(self) -> int: if( args.debug ): - print(f"{self.name} follow_random_local") + print(f"{self.acct} follow_random_local") - acctdict = self.me() - followlist = self.account_following(id=acctdict.id) + followlist = self.account_following(id=self.id) followed_people = {account.acct for account in followlist} # This does outersection on sets. It's the set of all users we know about # (from the users.toml file) minus ourselves and anyone we already follow - potentials = set(self.credentials) ^ {self.name} ^ followed_people + potentials = set(self.credentials) ^ {self.acct} ^ followed_people follow_target = random.choice(list(potentials)) target_dict = self.account_lookup(follow_target) if( args.dry_run ): - print(f"{self.name} will follow {follow_target} (id: {target_dict.id})") + print(f"{self.acct} will follow {follow_target} (id: {target_dict.id})") else: self.account_follow(target_dict.id) @@ -201,50 +214,80 @@ class Tooter(Mastodon): def unfollow_random(self) -> int: if( args.debug ): - print(f"{self.name} unfollow_random") + print(f"{self.acct} unfollow_random") + followlist = self.account_following(id=self.id) + unfollowee = random.choice(followlist) + if( len(followlist) == 0 ): + if( args.debug ): + print(f"{self.acct} can't unfollow! Not following anyone.") + return( 0 ) + if( args.dry_run ): + print(f"{self.acct} unfollows {unfollowee.acct} (id: {unfollowee.id})") + else: + self.account_unfollow(unfollowee.id) + return( 0 ) def boost_random_local(self) -> int: if( args.debug ): - print(f"{self.name} boost_random_local") + print(f"{self.acct} boost_random_local") return( 0 ) def favourite_random_local(self) -> int: if( args.debug ): - print(f"{self.name} favourite_random_local") - return( 0 ) + print(f"{self.acct} favourite_random_local") + return( self._favourite( timeline='local') ) - def favourite(self) -> int: + def favourite_random_public(self) -> int: if( args.debug ): - print(f"{self.name} favourite") - return( 0 ) - - def federated_favourite(self) -> int: + print(f"{self.acct} favourite_random_public") + return( self._favourite( timeline='public') ) + + def favourite_random_home(self) -> int: if( args.debug ): - print(f"{self.name} federated_favourite") + print(f"{self.acct} favourite_random_home") + return( self._favourite( timeline='home') ) + + def _favourite(self, timeline: str) -> int: + if( args.debug ): + print(f"{self.acct} favourite") + + chunk_size = 20 + timeline_list = self.read_timeline(timeline=timeline, limit=chunk_size) + if( len(timeline_list) == 0 ): + return( 1 ) + + fav_post = random.choice(timeline_list) + if( args.dry_run): + print(f"{self.acct} favourites {fav_post.id}") + else: + if( args.debug ): + print(f"{self.acct} favourites {fav_post.id}") + self.status_favourite(id=fav_post.id) + return( 0 ) - + def report_random_local(self) -> int: if( args.debug ): - print(f"{self.name} report_random_local") + print(f"{self.acct} report_random_local") return( 0 ) def random_interaction(self): """Choose one possible interaction according to the weights, and do it.""" interactions = { - self.reply_random_local: 0, - self.reply_random_home: 0, - self.reply_random_public: 0, - self.follow_random_local: 1, - self.unfollow_random: 0, - self.toot_plain_public: 0, - self.toot_tagged_public: 0, - self.toot_plain_unlisted: 0, - self.boost_random_local: 0, - self.favourite_random_local: 0, - self.favourite: 0, - self.federated_favourite: 0, - self.report_random_local: 0 + self.reply_random_local: 1, + self.reply_random_home: 1, + self.reply_random_public: 1, + self.follow_random_local: 1, + self.unfollow_random: 0, + self.toot_plain_public: 1, + self.toot_tagged_public: 1, + self.toot_plain_unlisted: 1, + self.boost_random_local: 0, + self.favourite_random_local: 1, + self.favourite_random_home: 1, + self.favourite_random_public: 1, + self.report_random_local: 0 } chosen = random.choices(population=list(interactions.keys()), weights=list(interactions.values()))[0]