import os
import sys
import argparse
from urllib.parse import urlparse
from dotenv import load_dotenv
from atproto import Client, models
from atproto_client.exceptions import BadRequestError

# Load environment variables from .env file
load_dotenv()

# Initialize the client
client = Client()

# Login using credentials from .env file
client.login(os.getenv('BSKY_HANDLE'), os.getenv('BSKY_PASSWORD'))

def extract_post_info(url):
    parsed_url = urlparse(url)
    path_parts = parsed_url.path.split('/')
    if len(path_parts) < 4 or path_parts[1] != 'profile':
        raise ValueError("Invalid Bluesky post URL")
    return path_parts[2], path_parts[4]

def get_author_did(handle):
    try:
        profile = client.app.bsky.actor.get_profile({'actor': handle})
        return profile.did
    except Exception as e:
        print(f"Error getting author DID: {e}")
        return None

def get_likes(uri, cursor=None):
    try:
        response = client.app.bsky.feed.get_likes({'uri': uri, 'cursor': cursor})
        return response
    except BadRequestError as e:
        print(f"Error: {e}")
        return None

def block_user(did, dry_run=False):
    try:
        if not dry_run:
            #client.app.bsky.graph.block({'subject': did})
            print(f"Blocked user: {did}")
        else:
            print(f"Would block user: {did}")
    except Exception as e:
        print(f"Error blocking user {did}: {e}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Fetch likes for a Bluesky post and optionally block users.")
    parser.add_argument("post_url", help="URL of the Bluesky post")
    parser.add_argument("--block", action="store_true", help="Block all users who liked the post")
    parser.add_argument("--dry-run", action="store_true", help="Show what would be done without actually blocking users")
    args = parser.parse_args()

    try:
        author_handle, post_rkey = extract_post_info(args.post_url)
    except ValueError as e:
        print(f"Error: {e}")
        sys.exit(1)

    author_did = get_author_did(author_handle)
    if not author_did:
        print("Could not fetch author's DID. Exiting.")
        sys.exit(1)

    post_uri = f"at://{author_did}/app.bsky.feed.post/{post_rkey}"
    print(f"Post URI: {post_uri}")

    all_likes = []
    cursor = None

    while True:
        response = get_likes(post_uri, cursor)
        if response is None:
            break
        all_likes.extend(response.likes)
        
        if response.cursor:
            cursor = response.cursor
        else:
            break

    print("\nUsers who liked the post:")
    for like in all_likes:
        print(f"User: {like.actor.handle}")

    print(f"\nTotal likes: {len(all_likes)}")

    if args.block:
        print("\nBlocking users:")
        for like in all_likes:
            block_user(like.actor.did, args.dry_run)

    if args.dry_run:
        print("\nThis was a dry run. No users were actually blocked.")
        
## Just list likes:
# python script.py <post_url>

## List likes and block users:
# python script.py <post_url> --block

## List likes and simulate blocking (dry run):
# python script.py <post_url> --block --dry-run
Powered by Codespace