Advertisement
Guest User

Bluesky atproto API scripts for fetching follower info & blocking from a blocklist

a guest
Dec 7th, 2024
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.99 KB | Source Code | 0 0
  1. #
  2. # Bluesky followers script -- writes a target account's followers (handle, display name, bio) to stdout in CSV form
  3. #
  4. import atproto
  5. import argparse
  6. import os
  7.  
  8. def clean_text(text):
  9.     if text is None:
  10.         return ""
  11.     text = ' '.join(text.splitlines())
  12.     text.replace("\"", " ")
  13.     return text
  14.  
  15. parser = argparse.ArgumentParser()
  16. parser.add_argument("--username", type=str, default=None, help="your Bsky account handle/did, if not present, tries env variable BSKY_USERNAME.")
  17. parser.add_argument("--pwd", type=str, default=None, help="your Bsky account password, if not present, tries env variable BSKY_PWD.")
  18. parser.add_argument("--target", type=str, default=None, help="returns CSV with followers of the target account (your account if absent)")
  19. args = parser.parse_args()
  20.  
  21. __username__ = args.username
  22. __pwd__ = args.pwd
  23. __targetacct__ = args.target
  24. if __username__ is None:
  25.     __username__ = os.environ.get('BSKY_USERNAME')
  26. if __pwd__ is None:    
  27.     __pwd__ = os.environ.get('BSKY_PWD')
  28.  
  29. if __targetacct__ is None:
  30.     __targetacct__ = __username__
  31.  
  32. if __username__ is None or __pwd__ is None:
  33.     print("please supply a Bluesky login via command line options or env flags")
  34.     exit(1)
  35.  
  36. client = atproto.Client()
  37. client.login(__username__, __pwd__)
  38.  
  39. crsr = None
  40. all_flwrs = []
  41.  
  42. while True:
  43.     data = client.get_followers(actor = __targetacct__, limit = 100, cursor = crsr)
  44.     flwrs = data.followers
  45.     if len(flwrs) == 0:
  46.         break
  47.     all_flwrs = all_flwrs + flwrs
  48.     crsr = data.cursor
  49.     if crsr is None:
  50.         break
  51.  
  52. for flwr in all_flwrs:
  53.     filter_display = clean_text(flwr.display_name)
  54.     filter_desc = clean_text(flwr.description)
  55.     print(f"{flwr.handle},\"{filter_display}\",\"{filter_desc}\"")
  56.  
  57. # <<<END FIRST SCRIPT>>>
  58. # Note that there is currently a 100 followers request/day rate limit in the API
  59.  
  60. #
  61. # Bluesky block script -- block users from a file list; you can provide a separate list of users to ignore
  62. #
  63. from atproto import Client, models
  64. import argparse
  65. import os
  66. import time
  67.  
  68. def handle_from_line(line):
  69.     if line.find(",") < 0:
  70.         return line
  71.     ss = line.split(",")
  72.     return ss[0]
  73.  
  74. parser = argparse.ArgumentParser()
  75. parser.add_argument("--username", type=str, default=None, help="your Bsky account handle/did, if not present, tries env variable BSKY_USERNAME.")
  76. parser.add_argument("--pwd", type=str, default=None, help="your Bsky account password, if not present, tries env variable BSKY_PWD.")
  77. parser.add_argument("--target", type=str, default=None, help="a file containing a list of bsky handles to block (CSV is fine, first field is taken)")
  78. parser.add_argument("--mercy", type=str, default=None, help="a file containing a list of bsky handles to show mercy to (CSV is fine, first field is taken)")
  79. args = parser.parse_args()
  80.  
  81. __username__ = args.username
  82. __pwd__ = args.pwd
  83. __target__ = args.target
  84. if __username__ is None:
  85.     __username__ = os.environ.get('BSKY_USERNAME')
  86. if __pwd__ is None:    
  87.     __pwd__ = os.environ.get('BSKY_PWD')
  88.  
  89. if __target__ is None:
  90.     print("please supply a target list of accounts to block")
  91.     exit(2)
  92.  
  93. if __username__ is None or __pwd__ is None:
  94.     print("please supply a Bluesky login via command line options or env flags")
  95.     exit(1)
  96.  
  97. client = Client()
  98. client.login(__username__, __pwd__)
  99.  
  100. mercy = []
  101. if args.mercy is not None:
  102.     with open(args.mercy, 'r') as mfile:
  103.         for line in mfile:
  104.             handle = handle_from_line(line)
  105.             mercy.append(handle)
  106.     print(f"{len(mercy)} handles found in the mercy list.")
  107. else:
  108.     input("No mercy list provided, you may break the script or press 'enter' to continue anyway.")
  109.  
  110. with open(__target__, 'r') as file:
  111.     for line in file:
  112.         handle = handle_from_line(line)
  113.         if any(handle == x for x in mercy):
  114.             print(f"*** handle {handle} found in the mercy list!")
  115.             continue
  116.         try:
  117.             did = client.resolve_handle(handle).did
  118.         except:
  119.             continue
  120.         if did is None:
  121.             continue
  122.         print(f"blocking {handle} -- {did}...")
  123.         block_record = models.AppBskyGraphBlock.Record(
  124.             subject=did,
  125.             created_at=client.get_current_time_iso()
  126.         )
  127.         uri = client.app.bsky.graph.block.create(client.me.did, block_record).uri
  128.         time.sleep(1)
  129.  
  130. # <<<END SECOND SCRIPT>>>
  131. # Note that there is a combined 5000 requests/hour rate limit on interactions (blocks, likes, skeets/re-skeets, etc.)
  132. # in the API. if you are active on bsky at the same time the block script is running, sleep(1) may be insufficient
  133. #
  134. # If you would like a script for the bluesky accounts a target account is following (rather than the
  135. # accounts following the target), it's exactly like the first script, except change the line:
  136. #
  137. #     data = client.get_followers(actor = __targetacct__, limit = 100, cursor = crsr)
  138. #
  139. # to:
  140. #
  141. #     data = client.get_follows(actor = __targetacct__, limit = 100, cursor = crsr)
  142. #
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement