Add unfollow.py
This commit is contained in:
+77
@@ -0,0 +1,77 @@
|
|||||||
|
from datetime import timezone
|
||||||
|
from atproto import Client
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from telegram import Bot
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
client = Client()
|
||||||
|
handle = '<YOUR-HANDLE>'
|
||||||
|
password = '<YOUR-APP-PASSWORD>'
|
||||||
|
client.login(handle, password)
|
||||||
|
|
||||||
|
BOT_TOKEN = '<YOUR-BOT-TOKEN>'
|
||||||
|
CHAT_ID = '<YOUR-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)
|
||||||
Reference in New Issue
Block a user