Skip to content

Instantly share code, notes, and snippets.

@alexpaden
Created February 22, 2024 16:22
Show Gist options
  • Save alexpaden/ad5e399eabe16f534071bf23e610e882 to your computer and use it in GitHub Desktop.
Save alexpaden/ad5e399eabe16f534071bf23e610e882 to your computer and use it in GitHub Desktop.
farcaster x dune follow tool
import requests
from dune_client.client import DuneClient
from dune_client.query import QueryBase
import time
import random
FID = 533
NEYNAR_API_KEY = ""
DUNE_API_KEY = ""
SIGNER_UUID = ""
HEADERS = {'accept': 'application/json', 'api_key': NEYNAR_API_KEY}
dune_client = DuneClient(api_key=DUNE_API_KEY)
def run_dune_query(query_id):
query = QueryBase(name="Custom Query", query_id=query_id)
results = dune_client.run_query(query)
return [row['fid'] for row in results.result.rows]
def get_current_following_or_followers(url):
items = []
cursor = None
processed_cursors = set()
retries = 3
while True:
if cursor in processed_cursors:
break
if cursor:
url += f"&cursor={cursor}"
attempt = 0
while attempt < retries:
try:
response = requests.get(url, headers=HEADERS)
data = response.json()
if 'result' in data and 'users' in data['result']:
items.extend([user['fid'] for user in data['result']['users']])
if 'next' in data['result'] and 'cursor' in data['result']['next']:
processed_cursors.add(cursor)
cursor = data['result']['next']['cursor']
else:
return items
break
except requests.RequestException as e:
attempt += 1
time.sleep(1)
return items
def follow_or_unfollow_users(target_fids, follow=True):
action_url = 'https://api.neynar.com/v2/farcaster/user/follow'
for chunk in [target_fids[i:i + 100] for i in range(0, len(target_fids), 100)]:
if follow:
response = requests.post(action_url, headers={**HEADERS, 'content-type': 'application/json'}, json={"target_fids": chunk, "signer_uuid": SIGNER_UUID})
else:
response = requests.delete(action_url, headers={**HEADERS, 'content-type': 'application/json'}, json={"target_fids": chunk, "signer_uuid": SIGNER_UUID})
if response.status_code == 200:
print(f"Processed users with fids: {chunk}")
else:
print(f"Failed to process users with fids: {chunk}")
print(f"Response Code: {response.status_code}, Response Body: {response.text}")
time.sleep(random.randint(1, 45))
if __name__ == "__main__":
# include all fids from this query
main_query_id = 3431862
# remove all fids from these queries
exclude_queries = [3432442, 3432778]
# remove fids for current followers (via neynar for live, takes a while)
exclude_followers = False
action = 'unfollow'
main_fids = run_dune_query(main_query_id)
print(f"Initial FIDs count: {len(main_fids)}")
for query_id in exclude_queries:
exclude_fids = run_dune_query(query_id)
main_fids = [fid for fid in main_fids if fid not in exclude_fids]
print(f"FIDs count after excluding query {query_id}: {len(main_fids)}")
if exclude_followers:
current_followers_url = f'https://api.neynar.com/v1/farcaster/followers?fid={FID}&viewerFid={FID}&limit=150' # Updated to use FID variable
current_followers = get_current_following_or_followers(current_followers_url)
main_fids = [fid for fid in main_fids if fid not in current_followers]
print(f"FIDs count after excluding current followers: {len(main_fids)}")
follow_or_unfollow_users(main_fids, action == 'follow')
print(f"Action '{action}' completed on users: {len(main_fids)}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment