-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
148 lines (117 loc) · 4.83 KB
/
main.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import os, sys, traceback
from instagrapi import Client
from datetime import datetime, timedelta
import schedule, time, logging, random
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()
# Instagram credentials
USERNAME = os.getenv('INSTAGRAM_USERNAME')
PASSWORD = os.getenv('INSTAGRAM_PASSWORD')
if not USERNAME or not PASSWORD:
logging.error('Username or password not found')
sys.exit('Username or password not found')
def exponential_backoff(attempt, max_delay=3600):
delay = min(30 * (2 ** attempt), max_delay)
time.sleep(delay + random.uniform(0, 10))
def login_user():
cl = Client()
cl.delay_range = [10, 30] # Increase delay to 10-30 seconds between requests
session_file = "session.json"
max_attempts = 5
for attempt in range(max_attempts):
try:
if os.path.exists(session_file):
session = cl.load_settings(session_file)
cl.set_settings(session)
cl.login(USERNAME, PASSWORD)
cl.get_timeline_feed() # Test if session is valid
else:
cl.login(USERNAME, PASSWORD)
logger.info("Successfully logged in")
return cl
except Exception as e:
logger.warning(f"Login attempt {attempt + 1} failed: {str(e)}")
if "Please wait a few minutes before you try again" in str(e):
exponential_backoff(attempt)
elif attempt == max_attempts - 1:
raise Exception("Max login attempts reached")
raise Exception("Couldn't login user")
def post_image(cl, image_path, caption):
max_attempts = 3
for attempt in range(max_attempts):
try:
cl.photo_upload(path=image_path, caption=caption)
logger.info(f"Posted image: {image_path}")
return
except Exception as e:
logger.error(f"Error uploading image (attempt {attempt + 1}): {str(e)}")
if "Please wait a few minutes before you try again" in str(e):
exponential_backoff(attempt)
elif attempt == max_attempts - 1:
raise
def generate_daily_schedule(image_folder, start_time):
images = os.listdir(image_folder)
schedule_times = []
current_time = start_time
for _ in images:
schedule_times.append(current_time.strftime("%H:%M"))
# Add a random interval between 30 minutes to 2 hours for the next post
interval = random.randint(30, 120)
current_time += timedelta(minutes=interval)
# If we've passed midnight, break the loop
if current_time.day != start_time.day:
break
return schedule_times
def schedule_and_post():
try:
cl = login_user()
image_folder = 'images'
images = os.listdir(image_folder)
if images:
image = images[0]
caption = os.path.splitext(image)[0] + "\n #midjourney #aiart #promptengineering #chaos #midjourneychaos"
image_path = os.path.join(image_folder, image)
post_image(cl, image_path, caption)
os.remove(image_path)
logger.info(f"Posted and removed image: {image_path}")
cl.dump_settings("session.json")
return True
else:
logger.info("No images left to post")
return False
except Exception as e:
logger.error(f"An error occurred: {str(e)}")
traceback.print_exc()
return False
# Calculate the start time (1 minute from now)
start_time = datetime.now() + timedelta(minutes=1)
# Generate the daily schedule
image_folder = 'images'
# Create the 'images' folder if it doesn't exist
if not os.path.exists(image_folder):
os.makedirs(image_folder)
print(f"Created folder: {image_folder}")
# Now proceed with listing images and generating the schedule
images = os.listdir(image_folder)
daily_schedule = generate_daily_schedule(image_folder, start_time)
images_to_post = len(images)
# Schedule the posting function to run at the calculated times
for post_time in daily_schedule:
schedule.every().day.at(post_time).do(schedule_and_post)
logger.info(f"Scheduled {len(daily_schedule)} posts starting at: {daily_schedule[0]}")
logger.info(f"Full schedule: {', '.join(daily_schedule)}")
# Keep the script running until all images are posted
while images_to_post > 0:
for job in schedule.jobs:
if job.should_run:
if job.run():
images_to_post -= 1
logger.info(f"Images left to post: {images_to_post}")
else:
logger.info("No more images to post. Exiting.")
images_to_post = 0
break
if images_to_post > 0:
time.sleep(60) # Check every minute
logger.info("All images have been posted. Script is ending.")