Closed sujay1599 closed 5 days ago
Still needs to be tested
default View context 12:10 Here is the scrape.py code you provided, formatted in Markdown for clarity. I've also made minor adjustments to improve readability and maintainability.
scrape.py copy python
import json import logging import random import os from time import sleep from datetime import datetime from rich.console import Console from utils import update_status, read_status, random_sleep, sleep_with_progress_bar from default_comments import DEFAULT_COMMENTS
console = Console()
def perform_human_actions(client, tags): """Perform human-like actions such as liking, following, and commenting on random media.""" if not tags: console.print(f"[bold bright_red]No tags provided for human-like actions.[/bold bright_red]") return
random_tag = random.choice(tags)
console.print(f"[bold yellow]Performing human-like actions on tag: {random_tag}[/bold yellow]")
actions = [
lambda tag: client.hashtag_medias_recent_v1(tag, amount=10),
lambda tag: client.hashtag_medias_top_v1(tag, amount=9),
lambda tag: client.hashtag_medias_top(tag, amount=9)
]
try:
action = random.choice(actions)
medias = action(random_tag)
if medias:
console.print(f"[bold yellow]Media found using {action.__name__}.[/bold yellow]")
media = random.choice(medias)
media_id = media.pk
# Randomly like or unlike media
if random.random() < 0.5:
if client.media_likers(media_id).usernames:
client.media_unlike(media_id)
console.print(f"[bold yellow]Unliked random media: {media_id} from tag: {random_tag}.[/bold yellow]")
else:
client.media_like(media_id)
console.print(f"[bold yellow]Liked random media: {media_id} from tag: {random_tag}.[/bold yellow]")
else:
client.media_like(media_id)
console.print(f"[bold yellow]Liked random media: {media_id} from tag: {random_tag}.[/bold yellow]")
# Random follow/unfollow
if random.random() < 0.1:
user_to_follow = media.user.pk
if client.user_following(client.user_id).get(user_to_follow):
client.user_unfollow(user_to_follow)
console.print(f"[bold yellow]Unfollowed user: {user_to_follow}.[/bold yellow]")
else:
client.user_follow(user_to_follow)
console.print(f"[bold yellow]Followed user: {user_to_follow}.[/bold yellow]")
# Random comments
if random.random() < 0.1:
comment_text = random.choice(DEFAULT_COMMENTS)
client.media_comment(media_id, comment_text)
console.print(f"[bold yellow]Commented on media: {media_id} with text: {comment_text}.[/bold yellow]")
# Randomly view stories
if random.random() < 0.1:
stories = client.user_stories(user_to_follow)
if stories:
story_to_view = random.choice(stories)
client.story_seen(story_to_view.id)
console.print(f"[bold yellow]Viewed story: {story_to_view.id}.[/bold yellow]")
sleep_time = random.uniform(5, 15)
console.print(f"[bold yellow]Sleeping for {sleep_time:.2f} seconds to mimic human behavior.[/bold yellow]")
sleep(sleep_time)
else:
console.print(f"[bold bright_red]No media found for tag: {random_tag}.[/bold bright_red]")
except Exception as e:
console.print(f"[bold red]Failed to perform human-like actions: {e}.[/bold red]")
logging.error(f"Failed to perform human-like actions: {e}")
def scrape_reels(client, profile, num_reels, last_scrape_time, uploaded_reels, scraped_reels, tags): """Scrape reels from the provided Instagram profile.""" user_id = client.user_id_from_username(profile) reels = [] new_scraped_reels = set(scraped_reels) # Initialize as a set to avoid duplicates
for reel in client.user_clips(user_id, amount=num_reels):
reel_id_str = str(reel.pk) # Ensure reel_id is treated as a string
profile_reel_id = f"{profile}_{reel_id_str}"
if profile_reel_id in uploaded_reels or profile_reel_id in new_scraped_reels:
continue
try:
media_path = client.clip_download(reel.pk, folder='downloads')
if media_path:
description_path = os.path.join('downloads', f'{reel_id_str}.txt')
with open(description_path, 'w', encoding='utf-8') as f:
f.write(reel.caption_text or '')
reels.append(reel)
new_scraped_reels.add(profile_reel_id) # Add to the set
# Perform human-like actions occasionally (1% of the time)
if random.random() < 0.01:
perform_human_actions(client, tags)
console.print(f"[bold bright_green]Scraped and saved reel: {profile_reel_id}.[/bold bright_green]")
sleep_time = random_sleep(10, 60, action="next reel scrape", profile_reel_id=profile_reel_id)
console.print(f"[bold bright_green]Sleeping for {sleep_time:.2f} seconds before next reel scrape.[/bold bright_green]")
sleep_with_progress_bar(sleep_time)
# Update status after each reel is scraped, avoiding duplicates
status = read_status()
if profile_reel_id not in status['reels_scraped']:
status['reels_scraped'].append(profile_reel_id)
update_status(last_scrape_time=datetime.now().timestamp(), reels_scraped=list(new_scraped_reels))
except Exception as e:
console.print(f"[bold red]Failed to scrape or save reel {profile_reel_id}: {e}.[/bold red]")
logging.error(f"Failed to scrape or save reel {profile_reel_id}: {e}")
return list(new_scraped_reels) # Convert set to list for return
def display_version_info(): """Display version info of the script.""" try: with open('version.txt', 'r') as f: version_info = json.load(f)
console.print("="*80)
console.print(f"Created by: {version_info['created_by']}")
console.print(f"Program: {version_info['program_name']}")
console.print(f"Version: {version_info['version']}")
console.print(f"Working as of: {version_info['working_as_of']}")
console.print("="*80)
except (FileNotFoundError, KeyError):
console.print("="*80)
console.print("Created by: Sujay1599")
console.print("Program: InstagramTheftyScraperPosterHuman")
console.print("Version: Unknown version")
console.print("Working as of: Unknown date")
console.print("="*80)
if name == "main": display_version_info() Key Features of the Code Human Actions: The perform_human_actions function simulates human-like behavior by performing actions such as liking, following, and commenting on media related to selected tags.
Reel Scraping: The scrape_reels function retrieves reels from a specified Instagram profile, including error handling and logging.
Version Display: The display_version_info function outputs the version of the script and other relevant information, loading details from a version.txt file.
Error Handling: The code includes comprehensive error handling to catch exceptions and log errors for debugging purposes.
Summary This scrape.py script provides essential functionality for interacting with the Instagram API, including scraping reels and simulating human-like actions. The use of logging and console output helps monitor the script's operations and catch potential issues. You can integrate this file into your existing project structure for a complete Instagram automation solution.
AI Provider : Workik View context my upload.py is as such: import os import logging import random import time from datetime import datetime, timedelta from time import sleep import subprocess from rich.console import Console from utils import random_sleep, update_status, read_status, log_random_upload_times, sleep_with_progress_bar from scrape import perform_human_actions from default_descriptions import DEFAULT_DESCRIPTIONS from auth import relogin # Import the relogin function console = Console() def build_description(original_description, use_original, custom_description, use_hashtags, hashtags_list, give_credit, profile_username): """Build the description for the reel, including hashtags and credit to the original profile.""" description = random.choice(DEFAULT_DESCRIPTIONS) if not original_description else ( original_description if use_original else custom_description or random.choice(DEFAULT_DESCRIPTIONS) ) if use_hashtags: description += f"\n{hashtags_list}" if give_credit: description += f"\nTaken from: @{profile_username}" return description def load_uploaded_reels(log_filename): """Load reels that have already been uploaded from the log file.""" uploaded_reels = set() if os.path.exists(log_filename): with open(log_filename, 'r') as log_file: uploaded_reels = set(line.strip() for line in log_file) return uploaded_reels def upload_reels_with_new_descriptions(client, config, unuploaded_reels, uploaded_reels, log_filename, session_file): """Upload reels with new descriptions, handling re-login if necessary.""" if not unuploaded_reels: console.print("[bold bright_red]No new reels to upload[/bold bright_red]") return for reel_file in unuploaded_reels: reel_id = reelfile.split('')[1].split('.')[0] profile_username = reelfile.split('')[0] media_path = os.path.join('downloads', reel_file) description_path = os.path.join('downloads', f'{reel_id}.txt') console.print(f"[bold bright_green]Preparing to upload reel {reel_id} from profile {profile_username}[/bold bright_green]") if not os.path.exists(media_path) or f"{profileusername}{reel_id}" in uploaded_reels: console.print(f"[bold bright_red]Media file {media_path} not found or already uploaded. Skipping upload for reel: {reel_id}[/bold bright_red]") continue original_description = read_description(description_path, reel_id) # Safely get configurations with default values new_description = build_description( original_description, config.get('description', {}).get('use_original', False), config.get('description', {}).get('custom_description', ''), config.get('hashtags', {}).get('use_hashtags', False), config.get('hashtags', {}).get('hashtags_list', ''), config.get('credit', {}).get('give_credit', False), profile_username ) logging.debug(f"Built new description for reel {reel_id}") # Attempt to upload the reel if not upload_reel(client, config, media_path, new_description, profile_username, reel_id, log_filename, session_file): continue # Optional story upload if config.get('uploading', {}).get('add_to_story', False): upload_to_story(client, media_path, new_description, profile_username, reel_id, config.get('uploading', {}).get('upload_interval_minutes', 10)) # Update the uploaded reels log update_uploaded_reels(log_filename, profile_username, reel_id) # Perform random wait perform_random_wait(client, config, profile_username, reel_id) def read_description(description_path, reel_id): """Read the original description from the description file.""" if os.path.exists(description_path): with open(description_path, 'r', encoding='utf-8') as f: logging.debug(f"Read original description for reel {reel_id}") return f.read() return "" def upload_reel(client, config, media_path, new_description, profile_username, reel_id, log_filename, session_file, retries=3): """Attempt to upload the reel, with retry logic in case of failure.""" for attempt in range(retries): try: client.clip_upload(media_path, new_description) console.print(f"[bold bright_green]Uploaded reel: {profileusername}{reel_id} with description:\n{new_description}[/bold bright_green]") # Update the uploaded reels in the status status = read_status() if 'reels_uploaded' not in status: status['reels_uploaded'] = [] status['reels_uploaded'].append(f"{profileusername}{reel_id}") update_status( last_upload_time=time.time(), next_upload_time=time.time() + config['uploading']['upload_interval_minutes'] 60, reels_uploaded=status['reels_uploaded'] # Update reels_uploaded in status.json ) # Log the uploaded reel in the log file update_uploaded_reels(log_filename, profile_username, reel_id) # Call the dashboard to display current status console.print("[bold blue3]Displaying dashboard after upload[/bold blue3]") subprocess.run(["python", "dashboard.py"]) return True except Exception as e: console.print(f"[bold bright_red]Failed to upload reel {reel_id}: {e}[/bold bright_red]") if '400' in str(e) and attempt < retries - 1: # Retry if it's a session issue console.print("[bold yellow]Re-login required, attempting to re-login...[/bold yellow]") relogin(client, config['instagram']['original_username'], config['instagram']['password'], session_file) continue # Retry the upload after re-login else: console.print(f"[bold red]Max retries exceeded or unknown error occurred for reel {reel_id}. Skipping upload.[/bold red]") break return False def upload_to_story(client, media_path, new_description, profile_username, reel_id, upload_interval_minutes): """Upload a reel to the Instagram story.""" try: console.print(f"[bold bright_green]Preparing to upload reel {reel_id} to story[/bold bright_green]") story_wait_time = random_sleep(60, 180, action="story upload", profile_reel_id=f"{profileusername}{reel_id}") console.print(f"[bold blue3]Waited for {story_wait_time:.2f} seconds before uploading reel {reel_id} to story[/bold blue3]") client.video_upload_to_story(media_path, new_description) console.print(f"[bold bright_green]Added reel: {profileusername}{reel_id} to story[/bold bright_green]") except Exception as e: console.print(f"[bold bright_red]Failed to add reel {reel_id} to story: {e}[/bold bright_red]") console.print("[bold blue3]Displaying dashboard after story upload[/bold blue3]") subprocess.run(["python", "dashboard.py"]) def update_uploaded_reels(log_filename, profile_username, reel_id): """Log uploaded reels to the log file.""" with open(log_filename, 'a') as log_file: log_file.write(f"{profileusername}{reel_id}\n") logging.debug(f"Logged uploaded reel {profileusername}{reel_id} to {log_filename}") def perform_random_wait(client, config, profile_username, reel_id): """Perform random wait between uploads and human-like actions.""" sleep_time = random_sleep(10, 60, action="next upload", profile_reel_id=f"{profileusername}{reel_id}") sleep_with_progress_bar(sleep_time) log_random_upload_times(sleep_time, f"{profileusername}{reel_id}") next_upload_time = datetime.now() + timedelta(minutes=config.get('uploading', {}).get('upload_interval_minutes', 10)) console.print(f"[bold blue3]Next upload at: {next_upload_time.strftime('%Y-%m-%d %H:%M:%S')}[/bold blue3]") console.print(f"[bold blue3]Waiting for {config.get('uploading', {}).get('upload_interval_minutes', 10)} minutes before next upload[/bold blue3]") total_wait_time = config.get('uploading', {}).get('upload_interval_minutes', 10) 60 elapsed_time = 0 while elapsed_time < total_wait_time: remaining_time = total_wait_time - elapsed_time interval = min(remaining_time, random.uniform(90, 545)) sleep_with_progress_bar(interval) elapsed_time += interval if random.random() < 0.01: console.print("[bold yellow]Performing human-like actions during wait time[/bold yellow]") perform_human_actions(client, config.get('custom_tags', [])) next_upload_time = datetime.now() + timedelta(seconds=remaining_time - interval) console.print(f"[bold yellow]Next upload at: {next_upload_time.strftime('%Y-%m-%d %H:%M:%S')}[/bold yellow]") elapsed_minutes = elapsed_time // 60 console.print(f"[bold yellow]Waiting for {config.get('uploading', {}).get('upload_interval_minutes', 10) - elapsed_minutes} minutes before next upload[/bold yellow]") else: elapsed_minutes = elapsed_time // 60 console.print(f"[bold blue3]Waiting for {config.get('uploading', {}).get('upload_interval_minutes', 10) - elapsed_minutes} minutes before next upload[/bold blue3]") console.print(f"[bold blue3]Next upload at {(datetime.now() + timedelta(seconds=total_wait_time - elapsed_time)).strftime('%Y-%m-%d %H:%M:%S')}[/bold blue3]") def get_unuploaded_reels(downloads_dir, scraped_reels, uploaded_reels): """Get the list of reels that have not been uploaded yet.""" unuploaded_reels = [] for filename in os.listdir(downloads_dir): if filename.endswith('.mp4'): reelid = filename.split('')[1].split('.')[0] reelkey = f"{filename.split('')[0]}_{reel_id}" if reel_key not in uploaded_reels and reel_key not in scraped_reels: unuploaded_reels.append(filename) console.print(f"[bold bright_green]Found {len(unuploaded_reels)} unuploaded reels[/bold bright_green]") return unuploaded_reels Regenerate 12:10 default View context 12:11 Here's the upload.py code you provided, formatted in Markdown for better readability. I've also made a few minor adjustments for clarity.
upload.py copy python
import os import logging import random import time from datetime import datetime, timedelta from time import sleep import subprocess from rich.console import Console from utils import random_sleep, update_status, read_status, log_random_upload_times, sleep_with_progress_bar from scrape import perform_human_actions from default_descriptions import DEFAULT_DESCRIPTIONS from auth import relogin # Import the relogin function
console = Console()
def build_description(original_description, use_original, custom_description, use_hashtags, hashtags_list, give_credit, profile_username): """Build the description for the reel, including hashtags and credit to the original profile.""" description = random.choice(DEFAULT_DESCRIPTIONS) if not original_description else ( original_description if use_original else custom_description or random.choice(DEFAULT_DESCRIPTIONS) )
if use_hashtags:
description += f"\n{hashtags_list}"
if give_credit:
description += f"\nTaken from: @{profile_username}"
return description
def load_uploaded_reels(log_filename): """Load reels that have already been uploaded from the log file.""" uploaded_reels = set() if os.path.exists(log_filename): with open(log_filename, 'r') as log_file: uploaded_reels = set(line.strip() for line in log_file) return uploaded_reels
def upload_reels_with_new_descriptions(client, config, unuploaded_reels, uploaded_reels, log_filename, session_file): """Upload reels with new descriptions, handling re-login if necessary.""" if not unuploaded_reels: console.print("[bold bright_red]No new reels to upload[/bold bright_red]") return
for reel_file in unuploaded_reels:
reel_id = reel_file.split('_')[1].split('.')[0]
profile_username = reel_file.split('_')[0]
media_path = os.path.join('downloads', reel_file)
description_path = os.path.join('downloads', f'{reel_id}.txt')
console.print(f"[bold bright_green]Preparing to upload reel {reel_id} from profile {profile_username}[/bold bright_green]")
if not os.path.exists(media_path) or f"{profile_username}_{reel_id}" in uploaded_reels:
console.print(f"[bold bright_red]Media file {media_path} not found or already uploaded. Skipping upload for reel: {reel_id}[/bold bright_red]")
continue
original_description = read_description(description_path, reel_id)
# Safely get configurations with default values
new_description = build_description(
original_description,
config.get('description', {}).get('use_original', False),
config.get('description', {}).get('custom_description', ''),
config.get('hashtags', {}).get('use_hashtags', False),
config.get('hashtags', {}).get('hashtags_list', ''),
config.get('credit', {}).get('give_credit', False),
profile_username
)
logging.debug(f"Built new description for reel {reel_id}")
# Attempt to upload the reel
if not upload_reel(client, config, media_path, new_description, profile_username, reel_id, log_filename, session_file):
continue
# Optional story upload
if config.get('uploading', {}).get('add_to_story', False):
upload_to_story(client, media_path, new_description, profile_username, reel_id, config.get('uploading', {}).get('upload_interval_minutes', 10))
# Update the uploaded reels log
update_uploaded_reels(log_filename, profile_username, reel_id)
# Perform random wait
perform_random_wait(client, config, profile_username, reel_id)
def read_description(description_path, reel_id): """Read the original description from the description file.""" if os.path.exists(description_path): with open(description_path, 'r', encoding='utf-8') as f: logging.debug(f"Read original description for reel {reel_id}") return f.read() return ""
def upload_reel(client, config, media_path, new_description, profile_username, reel_id, log_filename, session_file, retries=3): """Attempt to upload the reel, with retry logic in case of failure.""" for attempt in range(retries): try: client.clip_upload(media_path, new_description) console.print(f"[bold bright_green]Uploaded reel: {profileusername}{reel_id} with description:\n{new_description}[/bold bright_green]")
# Update the uploaded reels in the status
status = read_status()
if 'reels_uploaded' not in status:
status['reels_uploaded'] = []
status['reels_uploaded'].append(f"{profile_username}_{reel_id}")
update_status(
last_upload_time=time.time(),
next_upload_time=time.time() + config['uploading']['upload_interval_minutes'] * 60,
reels_uploaded=status['reels_uploaded'] # Update reels_uploaded in status.json
)
# Log the uploaded reel in the log file
update_uploaded_reels(log_filename, profile_username, reel_id)
# Call the dashboard to display current status
console.print("[bold blue3]Displaying dashboard after upload[/bold blue3]")
subprocess.run(["python", "dashboard.py"])
return True
except Exception as e:
console.print(f"[bold bright_red]Failed to upload reel {reel_id}: {e}[/bold bright_red]")
if '400' in str(e) and attempt < retries - 1: # Retry if it's a session issue
console.print("[bold yellow]Re-login required, attempting to re-login...[/bold yellow]")
relogin(client, config['instagram']['original_username'], config['instagram']['password'], session_file)
continue # Retry the upload after re-login
else:
console.print(f"[bold red]Max retries exceeded or unknown error occurred for reel {reel_id}. Skipping upload.[/bold red]")
break
return False
def upload_to_story(client, media_path, new_description, profile_username, reel_id, upload_interval_minutes): """Upload a reel to the Instagram story.""" try: console.print(f"[bold bright_green]Preparing to upload reel {reel_id} to story[/bold bright_green]") story_wait_time = random_sleep(60, 180, action="story upload", profile_reel_id=f"{profileusername}{reel_id}") console.print(f"[bold blue3]Waited for {story_wait_time:.2f} seconds before uploading reel {reel_id} to story[/bold blue3]") client.video_upload_to_story(media_path, new_description) console.print(f"[bold bright_green]Added reel: {profileusername}{reel_id} to story[/bold bright_green]") except Exception as e: console.print(f"[bold bright_red]Failed to add reel {reel_id} to story: {e}[/bold bright_red]") console.print("[bold blue3]Displaying dashboard after story upload[/bold blue3]") subprocess.run(["python", "dashboard.py"])
def update_uploaded_reels(log_filename, profile_username, reel_id): """Log uploaded reels to the log file.""" with open(log_filename, 'a') as log_file: log_file.write(f"{profileusername}{reel_id}\n") logging.debug(f"Logged uploaded reel {profileusername}{reel_id} to {log_filename}")
def perform_random_wait(client, config, profile_username, reel_id): """Perform random wait between uploads and human-like actions.""" sleep_time = random_sleep(10, 60, action="next upload", profile_reel_id=f"{profileusername}{reel_id}") sleep_with_progress_bar(sleep_time) log_random_upload_times(sleep_time, f"{profileusername}{reel_id}")
next_upload_time = datetime.now() + timedelta(minutes=config.get('uploading', {}).get('upload_interval_minutes', 10))
console.print(f"[bold blue3]Next upload at: {next_upload_time.strftime('%Y-%m-%d %H:%M:%S')}[/bold blue3]")
console.print(f"[bold blue3]Waiting for {config.get('uploading', {}).get('upload_interval_minutes', 10)} minutes before next upload[/bold blue3]")
total_wait_time = config.get('uploading', {}).get('upload_interval_minutes', 10) * 60
elapsed_time = 0
while elapsed_time < total_wait_time:
remaining_time = total_wait_time - elapsed_time
interval = min(remaining_time, random.uniform(90, 545))
sleep_with_progress_bar(interval)
elapsed_time += interval
if random.random() < 0.01:
console.print("[bold yellow]Performing human-like actions during wait time[/bold yellow]")
perform_human_actions(client, config.get('custom_tags', []))
next_upload_time = datetime.now() + timedelta(seconds=remaining_time - interval)
console.print(f"[bold yellow]Next upload at: {next_upload_time.strftime('%Y-%m-%d %H:%M:%S')}[/bold yellow]")
elapsed_minutes = elapsed_time // 60
console.print(f"[bold yellow]Waiting for {config.get('uploading', {}).get('upload_interval_minutes', 10) - elapsed_minutes} minutes before next upload[/bold yellow]")
else:
elapsed_minutes = elapsed_time // 60
console.print(f"[bold blue3]Waiting for {config.get('uploading', {}).get('upload_interval_minutes', 10) - elapsed_minutes} minutes before next upload[/bold blue3]")
console.print(f"[bold blue3]Next upload at {(datetime.now() + timedelta(seconds=total_wait_time - elapsed_time)).strftime('%Y-%m-%d %H:%M:%S')}[/bold blue3]")
def get_unuploaded_reels(downloads_dir, scraped_reels, uploaded_reels): """Get the list of reels that have not been uploaded yet.""" unuploaded_reels = [] for filename in os.listdir(downloads_dir): if filename.endswith('.mp4'): reelid = filename.split('')[1].split('.')[0] reelkey = f"{filename.split('')[0]}_{reel_id}" if reel_key not in uploaded_reels and reel_key not in scraped_reels: unuploaded_reels.append(filename) console.print(f"[bold bright_green]Found {len(unuploaded_reels)} unuploaded reels[/bold bright_green]") return unuploaded_reels Key Features of the Code Description Building: The build_description function creates a description for the reel, including optional hashtags and credit to the original poster.
Upload Management: The upload_reels_with_new_descriptions function manages the upload process, ensuring that reels are uploaded with appropriate descriptions and handling re-logins as necessary.
Story Uploading: The upload_to_story function allows for optional uploading of reels to Instagram stories.
Logging: The update_uploaded_reels function logs successfully uploaded reels to a specified log file.
Randomized Waits: The perform_random_wait function includes logic to wait between uploads, with random intervals to mimic human behavior.
Unuploaded Reel Detection: The get_unuploaded_reels function identifies reels that have not yet been uploaded based on existing logs.
Summary This upload.py script is designed to handle the uploading of Instagram reels effectively, supporting both standard uploads and story uploads. It also includes comprehensive logging and randomization to enhance the automation process. You can integrate this script into your existing project structure for a complete Instagram automation solution.
AI Provider : Workik View context how to make andocker so it runs Regenerate 12:14 default View context 12:15 To create a Docker container for your Instagram automation application, you'll need to write a Dockerfile that specifies how to build the container, as well as a docker-compose.yml file to manage the application. Below, I provide the necessary files and instructions, formatted in Markdown.
Step 1: Create a Dockerfile Create a file named Dockerfile in the root directory of your project. This file will define the environment for your application.
copy dockerfile
FROM python:3.9-slim
ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt
COPY . /app/
CMD ["python", "main.py"] Step 2: Create a docker-compose.yml File Create a file named docker-compose.yml in the same directory. This file simplifies running your Docker container.
copy yaml
version: '3.8'
services: instagram-bot: build: . volumes:
PYTHONUNBUFFERED=1 restart: unless-stopped Step 3: Create a requirements.txt Ensure you have a requirements.txt file in your project root with all the necessary dependencies listed. If you don't have one already, here’s an example based on your code:
copy plaintext
instagrapi moviepy Pillow imageio imageio-ffmpeg cryptography pycryptodomex python-dotenv rich tqdm proglog certifi chardet decorator idna numpy setuptools wheel typing-extensions urllib3 PyYAML requests PySocks Step 4: Build and Run the Docker Container Open a terminal and navigate to the directory where your Dockerfile and docker-compose.yml are located. Run the following command to build and start your Docker container:
copy bash
docker-compose up --build Step 5: Accessing the Application Once the container is up and running, your application will execute the main.py script. You can interact with it via the terminal.
Stopping the Application To stop the application, you can use:
copy bash
docker-compose down Summary This setup allows you to run your Instagram automation application in a Docker container, ensuring that all dependencies are managed and that your application runs in a consistent environment. The use of volumes ensures that downloaded files and session information persist even if the container is stopped or removed.
To create a Docker container for your Instagram automation application, you'll need to write a Dockerfile that specifies how to build the container, as well as a docker-compose.yml file to manage the application. Below, I provide the necessary files and instructions, formatted in Markdown.
Step 1: Create a Dockerfile Create a file named Dockerfile in the root directory of your project. This file will define the environment for your application.
copy dockerfile
FROM python:3.9-slim
ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt
COPY . /app/
CMD ["python", "main.py"] Step 2: Create a docker-compose.yml File Create a file named docker-compose.yml in the same directory. This file simplifies running your Docker container.
copy yaml
version: '3.8'
services: instagram-bot: build: . volumes:
PYTHONUNBUFFERED=1 restart: unless-stopped Step 3: Create a requirements.txt Ensure you have a requirements.txt file in your project root with all the necessary dependencies listed. If you don't have one already, here’s an example based on your code:
copy plaintext
instagrapi moviepy Pillow imageio imageio-ffmpeg cryptography pycryptodomex python-dotenv rich tqdm proglog certifi chardet decorator idna numpy setuptools wheel typing-extensions urllib3 PyYAML requests PySocks Step 4: Build and Run the Docker Container Open a terminal and navigate to the directory where your Dockerfile and docker-compose.yml are located. Run the following command to build and start your Docker container:
copy bash
docker-compose up --build Step 5: Accessing the Application Once the container is up and running, your application will execute the main.py script. You can interact with it via the terminal.
Stopping the Application To stop the application, you can use:
copy bash
docker-compose down Summary This setup allows you to run your Instagram automation application in a Docker container, ensuring that all dependencies are managed and that your application runs in a consistent environment. The use of volumes ensures that downloaded files and session information persist even if the container is stopped or removed.
AI Provider : Workik View context give me in copy n paste formart Regenerate 12:21 default View context 12:21 Sure! Below is the complete setup in a copy-and-paste format, formatted in Markdown.
Step 1: Create a Dockerfile Create a file named Dockerfile in the root directory of your project and copy the following content:
copy dockerfile
FROM python:3.9-slim
ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt
COPY . /app/
CMD ["python", "main.py"] Step 2: Create a docker-compose.yml File Create a file named docker-compose.yml in the same directory and copy the following content:
copy yaml
version: '3.8'
services: instagram-bot: build: . volumes:
PYTHONUNBUFFERED=1 restart: unless-stopped Step 3: Create a requirements.txt File Ensure you have a requirements.txt file in your project root with the following content:
copy plaintext
instagrapi moviepy Pillow imageio imageio-ffmpeg cryptography pycryptodomex python-dotenv rich tqdm proglog certifi chardet decorator idna numpy setuptools wheel typing-extensions urllib3 PyYAML requests PySocks Step 4: Build and Run the Docker Container Open a terminal and navigate to the directory where your Dockerfile and docker-compose.yml are located. Run the following command to build and start your Docker container:
copy bash
docker-compose up --build Step 5: Accessing the Application Once the container is up and running, your application will execute the main.py script. You can interact with it via the terminal.
Stopping the Application To stop the application, you can use:
copy bash
docker-compose down This setup allows you to run your Instagram automation application in a Docker container. Simply copy the provided sections into their respective files, and you will be ready to build and run your application.
Files moved to 2fa_dev
2fa workin progress
console = Console()
Set up logging
logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' )
Signal handler to catch keyboard interrupts
def signal_handler(sig, frame): console.print("\n[bold red]KeyboardInterrupt detected! Exiting gracefully...[/bold red]") sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
Ensure the downloads directory exists
downloads_dir = 'downloads' if not os.path.exists(downloads_dir): os.makedirs(downloads_dir) logging.info(f"Created directory: {downloads_dir}")
Initialize files
if not os.path.exists('status.json'): initialize_status_file() logging.info("Initialized status file")
if not os.path.exists('random-upload-times.json'): initialize_json_file('random-upload-times.json', default=[]) logging.info("Created new random-upload-times.json file")
if not os.path.exists('random-waits.json'): initialize_json_file('random-waits.json', default=[]) logging.info("Created new random-waits.json file")
Load configuration
try: last_username = input("Enter Instagram username for the session: ") config = load_config(last_username) logging.info(f"Loaded configuration for user: {last_username}") except FileNotFoundError as e: console.print(f"[bold red]Error: {e}. Make sure to run config_setup.py first to generate the configuration file.[/bold red]") sys.exit(1)
Validate configuration
required_scraping_keys = ['profiles', 'num_reels', 'scrape_interval_minutes'] for key in required_scraping_keys: if key not in config['scraping']: logging.error(f"Missing required configuration key: scraping.{key}") exit(1)
Decrypt Instagram credentials
INSTAGRAM_USERNAME, INSTAGRAM_PASSWORD = decrypt_credentials(config) logging.info("Decrypted Instagram credentials")
Initialize Instagram client
cl = Client() cl.delay_range = [2, 5] # Set delay range to mimic human behavior
Set proxy if available in configuration
proxy = config.get('proxy') if proxy: cl.set_proxy(proxy)
Perform initial login
session_file = os.path.join('user_sessions', f"{INSTAGRAM_USERNAME}_session.json") perform_login(cl, INSTAGRAM_USERNAME, INSTAGRAM_PASSWORD, session_file) update_session_file(cl, session_file) logging.info("Logged in to Instagram")
Inject cookies for public requests (if needed)
inject_cookies(cl, session_file)
def handle_rate_limit(client, func, *args, *kwargs): """Handle rate limits and re-login if needed, with exponential backoff.""" retries = 5 for attempt in range(retries): try: return func(args, kwargs) except Exception as e: if '429' in str(e) or 'login_required' in str(e): sleep_time = min(2 attempt, 3000) console.print(f"Rate limit or login required. Retrying in {sleep_time} seconds...") time_sleep(sleep_time) relogin(client, INSTAGRAM_USERNAME, INSTAGRAM_PASSWORD, session_file) else: logging.error(f"Error: {e}") raise e raise Exception("Max retries exceeded")
Main loop
def main(): try: display_version_info() # Display version control information
if name == "main": main()
import json import logging import random import os from time import sleep from datetime import datetime from rich.console import Console from utils import update_status, read_status, random_sleep, sleep_with_progress_bar from default_comments import DEFAULT_COMMENTS
console = Console()
def perform_human_actions(client, tags): """Perform human-like actions such as liking, following, and commenting on random media.""" if not tags: console.print(f"[bold bright_red]No tags provided for human-like actions.[/bold bright_red]") return
def scrape_reels(client, profile, num_reels, last_scrape_time, uploaded_reels, scraped_reels, tags): """Scrape reels from the provided Instagram profile.""" user_id = client.user_id_from_username(profile) reels = [] new_scraped_reels = set(scraped_reels) # Initialize as a set to avoid duplicates
def display_version_info(): """Display version info of the script.""" try: with open('version.txt', 'r') as f: version_info = json.load(f)
if name == "main": display_version_info()
import os import logging import random import time from datetime import datetime, timedelta from time import sleep import subprocess from rich.console import Console from utils import random_sleep, update_status, read_status, log_random_upload_times, sleep_with_progress_bar from scrape import perform_human_actions from default_descriptions import DEFAULT_DESCRIPTIONS from auth import relogin # Import the relogin function
console = Console()
def build_description(original_description, use_original, custom_description, use_hashtags, hashtags_list, give_credit, profile_username): """Build the description for the reel, including hashtags and credit to the original profile.""" description = random.choice(DEFAULT_DESCRIPTIONS) if not original_description else ( original_description if use_original else custom_description or random.choice(DEFAULT_DESCRIPTIONS) )
def load_uploaded_reels(log_filename): """Load reels that have already been uploaded from the log file.""" uploaded_reels = set() if os.path.exists(log_filename): with open(log_filename, 'r') as log_file: uploaded_reels = set(line.strip() for line in log_file) return uploaded_reels
def upload_reels_with_new_descriptions(client, config, unuploaded_reels, uploaded_reels, log_filename, session_file): """Upload reels with new descriptions, handling re-login if necessary.""" if not unuploaded_reels: console.print("[bold bright_red]No new reels to upload[/bold bright_red]") return
def read_description(description_path, reel_id): """Read the original description from the description file.""" if os.path.exists(description_path): with open(description_path, 'r', encoding='utf-8') as f: logging.debug(f"Read original description for reel {reel_id}") return f.read() return ""
def upload_reel(client, config, media_path, new_description, profile_username, reel_id, log_filename, session_file, retries=3): """Attempt to upload the reel, with retry logic in case of failure.""" for attempt in range(retries): try: client.clip_upload(media_path, new_description) console.print(f"[bold bright_green]Uploaded reel: {profileusername}{reel_id} with description:\n{new_description}[/bold bright_green]")
def upload_to_story(client, media_path, new_description, profile_username, reel_id, upload_interval_minutes): """Upload a reel to the Instagram story.""" try: console.print(f"[bold bright_green]Preparing to upload reel {reel_id} to story[/bold bright_green]") story_wait_time = random_sleep(60, 180, action="story upload", profile_reel_id=f"{profileusername}{reel_id}") console.print(f"[bold blue3]Waited for {story_wait_time:.2f} seconds before uploading reel {reel_id} to story[/bold blue3]") client.video_upload_to_story(media_path, new_description) console.print(f"[bold bright_green]Added reel: {profileusername}{reel_id} to story[/bold bright_green]") except Exception as e: console.print(f"[bold bright_red]Failed to add reel {reel_id} to story: {e}[/bold bright_red]") console.print("[bold blue3]Displaying dashboard after story upload[/bold blue3]") subprocess.run(["python", "dashboard.py"])
def update_uploaded_reels(log_filename, profile_username, reel_id): """Log uploaded reels to the log file.""" with open(log_filename, 'a') as log_file: log_file.write(f"{profileusername}{reel_id}\n") logging.debug(f"Logged uploaded reel {profileusername}{reel_id} to {log_filename}")
def perform_random_wait(client, config, profile_username, reel_id): """Perform random wait between uploads and human-like actions.""" sleep_time = random_sleep(10, 60, action="next upload", profile_reel_id=f"{profileusername}{reel_id}") sleep_with_progress_bar(sleep_time) log_random_upload_times(sleep_time, f"{profileusername}{reel_id}")
def get_unuploaded_reels(downloads_dir, scraped_reels, uploaded_reels): """Get the list of reels that have not been uploaded yet.""" unuploaded_reels = [] for filename in os.listdir(downloads_dir): if filename.endswith('.mp4'): reelid = filename.split('')[1].split('.')[0] reelkey = f"{filename.split('')[0]}_{reel_id}" if reel_key not in uploaded_reels and reel_key not in scraped_reels: unuploaded_reels.append(filename) console.print(f"[bold bright_green]Found {len(unuploaded_reels)} unuploaded reels[/bold bright_green]") return unuploaded_reels