sujay1599 / InstagramTheftyScraperPosterHuman

InstagramTheftyScraperPosterHuman is an advanced tool for automating the process of scraping, uploading, and managing Instagram reels. This tool builds upon previous versions, introducing several enhancements and new functionalities to improve automation, human-like interactions, and bot detection prevention.
MIT License
9 stars 2 forks source link

Create auth2.py #22

Closed sujay1599 closed 5 days ago

sujay1599 commented 2 weeks ago

2fa workin progress

  1. config_setup.py
import json
import yaml
import os
import logging
from cryptography.fernet import Fernet
import getpass
from instagrapi import Client
from rich.console import Console
from auth import perform_login, decrypt_credentials, generate_key, encrypt_credentials  

console = Console()

# Constants
SESSION_DIR = 'user_sessions'
CONFIG_DIR = 'configs'
KEY_FILE = 'key.key'  

# Set up logging
logging.basicConfig(
    filename="config_setup.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)

os.makedirs(SESSION_DIR, exist_ok=True)
os.makedirs(CONFIG_DIR, exist_ok=True)

console.print(f"[bold green]Created session and config directories if not present[/bold green]")

def load_or_generate_key():
    if os.path.exists(KEY_FILE):
        with open(KEY_FILE, 'rb') as key_file:
            return key_file.read()
    else:
        key = generate_key()
        with open(KEY_FILE, 'wb') as key_file:
            key_file.write(key)
        logging.info(f"Generated new encryption key: {KEY_FILE}")
        return key

def get_user_credentials():
    key = load_or_generate_key()
    while True:
        username = input('Enter Instagram username: ').encode()
        password = getpass.getpass('Enter Instagram password: ').encode()
        client = Client()
        session_file = os.path.join(SESSION_DIR, f"{username.decode()}_session.json")
        if perform_login(client, username.decode(), password.decode(), session_file):
            logging.info(f"Login successful for user: {username.decode()}")
            console.print("[bold green]Login successful![/bold green]")
            encrypted_username, encrypted_password = encrypt_credentials(username, password, key)
            return encrypted_username, encrypted_password, username.decode()
        else:
            console.print("[bold red]Login failed. Please try again.[/bold red]")
            logging.error(f"Login failed for user: {username.decode()}")

def create_config(encrypted_username, encrypted_password, key, username):
    return {
        'instagram': {
            'username': encrypted_username,
            'password': encrypted_password,
        },
        'key': key.decode(),
        'proxy': input('Enter proxy server address (leave blank if not using proxy): '),
    }

def save_config(config, username):
    filename = os.path.join(CONFIG_DIR, f"{username}_config.yaml")
    with open(filename, 'w') as file:
        yaml.dump(config, file)
    console.print(f"[bold green]Configuration saved to {filename}[/bold green]")
    logging.info(f"Configuration saved to {filename}")

def main():
    key = load_or_generate_key()
    encrypted_username, encrypted_password, username = get_user_credentials()
    config = create_config(encrypted_username, encrypted_password, key, username)
    save_config(config, username)

if __name__ == "__main__":
    main()
import json
import yaml
import os
import logging
from cryptography.fernet import Fernet
import getpass
from instagrapi import Client
from rich.console import Console
from auth import perform_login, decrypt_credentials, generate_key, encrypt_credentials  

console = Console()

# Constants
SESSION_DIR = 'user_sessions'
CONFIG_DIR = 'configs'
KEY_FILE = 'key.key'  

# Set up logging
logging.basicConfig(
    filename="config_setup.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)

os.makedirs(SESSION_DIR, exist_ok=True)
os.makedirs(CONFIG_DIR, exist_ok=True)

console.print(f"[bold green]Created session and config directories if not present[/bold green]")

def load_or_generate_key():
    if os.path.exists(KEY_FILE):
        with open(KEY_FILE, 'rb') as key_file:
            return key_file.read()
    else:
        key = generate_key()
        with open(KEY_FILE, 'wb') as key_file:
            key_file.write(key)
        logging.info(f"Generated new encryption key: {KEY_FILE}")
        return key

def get_user_credentials():
    key = load_or_generate_key()
    while True:
        username = input('Enter Instagram username: ').encode()
        password = getpass.getpass('Enter Instagram password: ').encode()
        client = Client()
        session_file = os.path.join(SESSION_DIR, f"{username.decode()}_session.json")
        if perform_login(client, username.decode(), password.decode(), session_file):
            logging.info(f"Login successful for user: {username.decode()}")
            console.print("[bold green]Login successful![/bold green]")
            encrypted_username, encrypted_password = encrypt_credentials(username, password, key)
            return encrypted_username, encrypted_password, username.decode()
        else:
            console.print("[bold red]Login failed. Please try again.[/bold red]")
            logging.error(f"Login failed for user: {username.decode()}")

def create_config(encrypted_username, encrypted_password, key, username):
    return {
        'instagram': {
            'username': encrypted_username,
            'password': encrypted_password,
        },
        'key': key.decode(),
        'proxy': input('Enter proxy server address (leave blank if not using proxy): '),
    }

def save_config(config, username):
    filename = os.path.join(CONFIG_DIR, f"{username}_config.yaml")
    with open(filename, 'w') as file:
        yaml.dump(config, file)
    console.print(f"[bold green]Configuration saved to {filename}[/bold green]")
    logging.info(f"Configuration saved to {filename}")

def main():
    key = load_or_generate_key()
    encrypted_username, encrypted_password, username = get_user_credentials()
    config = create_config(encrypted_username, encrypted_password, key, username)
    save_config(config, username)

if __name__ == "__main__":
    main()
  1. main.py
    
    import logging
    import os
    import random
    import time
    from time import sleep as time_sleep
    from config_setup import load_config
    from auth import perform_login, update_session_file, decrypt_credentials, relogin, Client, inject_cookies
    from scrape import scrape_reels, perform_human_actions, display_version_info
    from upload import upload_reels_with_new_descriptions, get_unuploaded_reels, load_uploaded_reels
    from utils import initialize_status_file, read_status, update_status, random_sleep, log_random_upload_times, log_random_waits, initialize_json_file, sleep_with_progress_bar, delete_old_reels
    import subprocess
    from rich.console import Console
    import signal
    import sys

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

    # Load status
    status = read_status()

    # Set initial values for the main loop
    last_upload_time = status.get('last_upload_time', 0)
    last_scrape_time = status.get('last_scrape_time', 0)
    reels_scraped = set(status.get('reels_scraped', []))  # Use set to ensure uniqueness

    # Define tags from the configuration
    tags = config.get('custom_tags', [])
    default_comments = config.get('comments', [])
    default_descriptions = config.get('description', {}).get('custom_descriptions', [])

    while True:
        current_time = time.time()

        # Check if it's time to scrape reels
        if current_time - last_scrape_time >= config['scraping']['scrape_interval_minutes'] * 60:
            try:
                profiles = config['scraping']['profiles'].split()
                uploaded_reels = load_uploaded_reels('upload_log.txt')
                for profile in profiles:
                    try:
                        scraped_reels = handle_rate_limit(cl, scrape_reels, cl, profile, config['scraping']['num_reels'], last_scrape_time, uploaded_reels, list(reels_scraped), tags)
                        reels_scraped.update(scraped_reels)  # Update set with new scraped reels
                        update_status(last_scrape_time=current_time, reels_scraped=list(reels_scraped))  # Convert back to list for JSON
                        logging.info("Updated status after scraping")
                    except Exception as e:
                        logging.error(f"Error scraping profile {profile}: {e}")
                        console.print(f"[bold red]Error scraping profile {profile}: {e}[/bold red]")

                console.print("[bold purple4]Finished scraping reels from profiles[/bold purple4]")
                console.print("[bold purple4]Displaying dashboard before waiting phase[/bold purple4]")
                subprocess.run(["python", "dashboard.py"])
            except Exception as e:
                logging.error(f"Error in scraping loop: {e}")
                console.print(f"[bold red]Error in scraping loop: {e}[/bold red]")

        # Check if it's time to upload reels
        uploaded_reels = load_uploaded_reels('upload_log.txt')
        unuploaded_reels = get_unuploaded_reels('downloads', list(reels_scraped), uploaded_reels)

        if current_time - last_upload_time >= config['uploading']['upload_interval_minutes'] * 60:
            try:
                handle_rate_limit(cl, upload_reels_with_new_descriptions, cl, config, unuploaded_reels, uploaded_reels, 'upload_log.txt', session_file)
                update_status(last_upload_time=current_time)
                console.print("[bold purple4]Finished uploading reels[/bold purple4]")

                # Randomly perform human-like actions
                if random.random() < 0.01:
                    perform_human_actions(cl, tags)

                console.print("[bold purple4]Displaying dashboard before waiting phase[/bold purple4]")
                subprocess.run(["python", "dashboard.py"])
            except Exception as e:
                logging.error(f"Error in upload loop: {e}")
                console.print(f"[bold red]Error in upload loop: {e}[/bold red]")

        # Randomly perform human-like actions during the waiting period
        if random.random() < 0.01:
            perform_human_actions(cl, tags)

        # Delete old reels based on the deletion interval
        try:
            delete_old_reels(config['deleting']['delete_interval_minutes'], config)
        except Exception as e:
            logging.error(f"Error in deletion process: {e}")
            console.print(f"[bold red]Error in deletion process: {e}[/bold red]")

        sleep_with_progress_bar(60)  # Sleep for 60 seconds
        logging.debug("Sleeping for 60 seconds before next iteration")

except KeyboardInterrupt:
    console.print("\n[bold red]Exiting program...[/bold red]")
except Exception as e:
    logging.error(f"Unexpected error: {e}")
    console.print(f"[bold red]Unexpected error: {e}[/bold red]")

if name == "main": main()


Scrape.py

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()


Upload.py

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

sujay1599 commented 2 weeks ago

Still needs to be tested

sujay1599 commented 2 weeks ago

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

Use the official Python image as a base

FROM python:3.9-slim

Set environment variables

ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1

Set working directory

WORKDIR /app

Copy the requirements file and install dependencies

COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt

Copy the entire application code into the container

COPY . /app/

Command to run the application

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:

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.

sujay1599 commented 2 weeks ago

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

Use the official Python image as a base

FROM python:3.9-slim

Set environment variables

ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1

Set working directory

WORKDIR /app

Copy the requirements file and install dependencies

COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt

Copy the entire application code into the container

COPY . /app/

Command to run the application

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:

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

Use the official Python image as a base

FROM python:3.9-slim

Set environment variables

ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1

Set working directory

WORKDIR /app

Copy the requirements file and install dependencies

COPY requirements.txt /app/ RUN pip install --no-cache-dir -r requirements.txt

Copy the entire application code into the container

COPY . /app/

Command to run the application

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:

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.

sujay1599 commented 5 days ago

Files moved to 2fa_dev