-
Notifications
You must be signed in to change notification settings - Fork 0
/
following.py
112 lines (95 loc) · 4.03 KB
/
following.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import aiohttp
import asyncio
import time
import os
import logging
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Configuration
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
if not GITHUB_TOKEN:
raise ValueError("GitHub token not found. Please set it in the .env file.")
BASE_URL = 'https://api.github.com'
FOLLOW_URL = f'{BASE_URL}/user/following/'
RATE_LIMIT_URL = f'{BASE_URL}/rate_limit'
# Set up logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class GithubFollower:
def __init__(self, token):
self.token = token
self.headers = {
'Authorization': f'token {self.token}',
'Accept': 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28'
}
self.session = None
async def create_session(self):
self.session = aiohttp.ClientSession(headers=self.headers)
async def close_session(self):
if self.session:
await self.session.close()
async def check_rate_limit(self):
async with self.session.get(RATE_LIMIT_URL) as response:
if response.status == 200:
data = await response.json()
remaining = data['resources']['core']['remaining']
reset_time = data['resources']['core']['reset']
if remaining < 5:
wait_time = max(reset_time - time.time(), 0)
logger.info(f"Rate limit almost reached. Waiting for {wait_time:.2f} seconds.")
await asyncio.sleep(wait_time)
else:
logger.error(f"Failed to check rate limit: {response.status}")
async def follow_user(self, username):
await self.check_rate_limit()
# First, check if the user exists
user_url = f'{BASE_URL}/users/{username}'
async with self.session.get(user_url) as response:
if response.status != 200:
logger.warning(f"User {username} does not exist or is not accessible.")
return
# Check if already following
following_url = f'{BASE_URL}/user/following/{username}'
async with self.session.get(following_url) as response:
if response.status == 204:
logger.info(f"Already following {username}")
return
elif response.status != 404:
logger.error(f"Unexpected status when checking if following {username}: {response.status}")
return
# If not already following, attempt to follow
async with self.session.put(FOLLOW_URL + username) as response:
if response.status == 204:
logger.info(f'Successfully followed {username}')
else:
error_msg = await response.text()
logger.error(f'Failed to follow {username}: {error_msg}')
async def follow_users_from_file(self, file_path):
try:
with open(file_path, 'r') as file:
usernames = [line.strip() for line in file if line.strip()]
except FileNotFoundError:
logger.error(f"File not found: {file_path}")
return
for username in usernames:
await self.follow_user(username)
await asyncio.sleep(1) # Small delay between requests
async def follow_users_from_all_text_files(self, folder_path):
for root, dirs, files in os.walk(folder_path):
for file in files:
if file.endswith('.txt'):
file_path = os.path.join(root, file)
logger.info(f"Processing file: {file_path}")
await self.follow_users_from_file(file_path)
async def main():
follower = GithubFollower(GITHUB_TOKEN)
await follower.create_session()
try:
project_folder_path = './usernames/'
await follower.follow_users_from_all_text_files(project_folder_path)
finally:
await follower.close_session()
if __name__ == "__main__":
asyncio.run(main())