from datetime import timezone from atproto import Client import datetime from telegram import Bot import asyncio client = Client() handle = '' password = '' client.login(handle, password) BOT_TOKEN = '' CHAT_ID = '' def get_follows(recursive=False): """Fetch the list of people you are currently following.""" follows = [] limit = 100 if recursive else 1 response = client.get_follows(handle, None, limit) follows.extend(response.follows) while recursive and response.cursor: response = client.get_follows(handle, response.cursor, 100) follows.extend(response.follows) return follows def get_last_post_date(user): """Fetch the date of the last post of a user.""" response = client.get_author_feed(user.handle) if len(response.feed) > 0: return datetime.datetime.fromisoformat(response.feed[0].post.indexed_at) return None def is_inactive(user, days=15): fifteen_days_ago = datetime.datetime.now(timezone.utc) - datetime.timedelta(days=days) last_post_day = get_last_post_date(user) return last_post_day is None or last_post_day < fifteen_days_ago def action_on_users(follows, days, repost, dry=True): """Identify users to unfollow based on posting activity.""" for user in follows: if is_inactive(user, days): if not dry: unfollow(user,days) async def send_message(user,days): bot = Bot(token=BOT_TOKEN) await bot.send_message(chat_id=CHAT_ID, text=f"Unfollow {user.display_name} ({user.handle}): {days} days inactive.") def unfollow(user,days): """Unfollow users.""" client.delete_follow(user.viewer.following) asyncio.run(send_message(user,days)) def main(recursive=False, dry=False, prod=False, days=15, repost=0.8): follows = get_follows(recursive) action_on_users(follows, days, repost, not prod) if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(description="Unfollow inactive users.") parser.add_argument('--dry', action='store_true', help="Full run, dry unfollow.") parser.add_argument('--prod', action='store_true', help="Full run. Actually unfollow.") parser.add_argument('--days', type=int, default=15, help="Number of days of inactivity to consider for unfollowing.") args = parser.parse_args() recursive = args.prod or args.dry dry = args.dry prod = args.prod main(recursive, dry, prod, args.days)