Logo Pastebin.fr
Pastebin

Retrouvez, créez et partagez vos snippets en temps réel.

iphone

import os
import subprocess
import shutil
import time
import hashlib
import ctypes
from datetime import datetime, timedelta
from concurrent.futures import ThreadPoolExecutor

# --- CONFIGURATION ---

mobile_file_search_exe = r"D:\stockage\temp\nircmd\MobileFileSearch.exe"
final_folder = r"F:\android\photo\camera"
temp_folder = r"F:\android\temp_photos"
photo_extensions = ('.mov', '.jpg', '.jpeg', '.png', '.heic', '.dng', '.aae', '.mp4', '.m4v')
sync_history_file = os.path.join(final_folder, "sync_history.txt")
last_sync_file = os.path.join(final_folder, "last_sync.txt")

# --- ANTI-VEILLE WINDOWS ---

def prevent_sleep():
    ctypes.windll.kernel32.SetThreadExecutionState(0x80000000 | 0x00000001 | 0x00000002)

def allow_sleep():
    ctypes.windll.kernel32.SetThreadExecutionState(0x80000000)

# --- DATE DE DERNIÈRE SYNC ---

def get_last_sync_date():
    if os.path.exists(last_sync_file):
        try:
            with open(last_sync_file, "r") as f:
                return datetime.strptime(f.read().strip(), "%Y-%m-%d %H:%M:%S")
        except:
            pass
    return datetime.now() - timedelta(days=30)

def save_last_sync_date():
    with open(last_sync_file, "w") as f:
        f.write(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

# --- FONCTIONS UTILITAIRES ---

def get_file_hash(filepath):
    hasher = hashlib.md5()
    try:
        with open(filepath, 'rb') as f:
            data = f.read(1024 * 1024)
            if data:
                hasher.update(data)
        return hasher.hexdigest()
    except:
        return None

def load_sync_history():
    history = set()
    if os.path.exists(sync_history_file):
        try:
            with open(sync_history_file, "r", encoding="utf-8") as f:
                for line in f:
                    history.add(line.strip())
        except:
            pass
    return history

def save_sync_history(history):
    try:
        with open(sync_history_file, "w", encoding="utf-8") as f:
            for entry in sorted(history):
                f.write(entry + "\n")
    except:
        pass

def get_file_signature(filepath):
    try:
        name = os.path.basename(filepath)
        size = os.path.getsize(filepath)
        file_hash = get_file_hash(filepath)
        return f"{name}|{size}|{file_hash}"
    except:
        return None

def get_all_temp_files():
    if not os.path.exists(temp_folder):
        return []
    
    all_files = []
    for root, dirs, files in os.walk(temp_folder):
        for f in files:
            if f.lower().endswith(photo_extensions):
                all_files.append(os.path.join(root, f))
    return all_files

def cleanup_temp():
    if os.path.exists(temp_folder):
        try:
            shutil.rmtree(temp_folder)
        except:
            pass
    os.makedirs(temp_folder, exist_ok=True)

def check_iphone_connected():
    try:
        result = subprocess.run(
            ['wmic', 'path', 'Win32_PnPEntity', 'where',
             "Caption like '%Apple%' or Caption like '%iPhone%'",
             'get', 'Caption'],
            capture_output=True, text=True, timeout=5,
            creationflags=subprocess.CREATE_NO_WINDOW
        )
        return 'iPhone' in result.stdout or 'Apple Mobile' in result.stdout
    except:
        return False

# --- TRANSFERT PARALLÈLE ---

def copy_file_worker(args):
    source_file, final_dir, history = args
    file_name = os.path.basename(source_file)
    
    try:
        signature = get_file_signature(source_file)
        
        if signature and signature in history:
            os.remove(source_file)
            return ("skip", file_name)
        
        dest_path = os.path.join(final_dir, file_name)
        
        if os.path.exists(dest_path):
            base, ext = os.path.splitext(file_name)
            counter = 1
            while os.path.exists(dest_path):
                dest_path = os.path.join(final_dir, f"{base}_{counter}{ext}")
                counter += 1
        
        shutil.move(source_file, dest_path)
        return ("ok", file_name, signature)
        
    except Exception as e:
        return ("error", file_name, str(e))

def sync_photos(temp_dir, final_dir):
    os.makedirs(final_dir, exist_ok=True)
    
    files = get_all_temp_files()
    if not files:
        return 0
    
    history = load_sync_history()
    copied = 0
    skipped = 0
    
    print(f"\n📁 Traitement de {len(files)} fichiers (8 threads)...")
    
    tasks = [(f, final_dir, history) for f in files]
    
    with ThreadPoolExecutor(max_workers=8) as executor:
        results = list(executor.map(copy_file_worker, tasks))
    
    for result in results:
        if result[0] == "ok":
            history.add(result[2])
            copied += 1
            print(f"✅ {result[1]}")
        elif result[0] == "skip":
            skipped += 1
    
    save_sync_history(history)
    
    if copied > 0 or skipped > 0:
        print(f"\n📊 {copied} copiés, {skipped} ignorés")
    
    return copied

# --- MODES DE RECHERCHE ---

def wait_for_files(timeout=60, stable_seconds=3):
    last_count = 0
    stable_time = 0
    
    for _ in range(timeout):
        files = get_all_temp_files()
        count = len(files)
        
        if count > 0:
            if count == last_count:
                stable_time += 1
                if stable_time >= stable_seconds:
                    print(f"✅ {count} fichiers prêts")
                    return True
            else:
                stable_time = 0
                print(f"\r   📥 {count} fichiers...", end="", flush=True)
        
        last_count = count
        time.sleep(1)
    
    print()
    return len(get_all_temp_files()) > 0

def launch_search_ultra():
    """
    Mode ULTRA-RAPIDE : 
    - Uniquement *.JPG
    - 30 jours max
    """
    cleanup_temp()
    
    try:
        cmd = [
            mobile_file_search_exe,
            "/ScanSubfolders", "1",
            "/ModifiedTime.FindMode", "6",
            "/ModifiedTime.LastXX", "30",
            "/CopyFiles.Folder", temp_folder,
            "/CopyFiles.PreserveTime", "1",
            "/CopyFiles",
            "/Wildcard", "*.JPG"
        ]
        
        print("⚡ Scan ULTRA-RAPIDE (30 jours, *.JPG uniquement)...")
        
        subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=90,
            creationflags=subprocess.CREATE_NO_WINDOW
        )
        
        return wait_for_files(timeout=45, stable_seconds=2)
        
    except subprocess.TimeoutExpired:
        print("⏱️  Timeout")
        return len(get_all_temp_files()) > 0
    except Exception as e:
        print(f"❌ Erreur: {e}")
        return False

def launch_search_complet():
    """
    Mode COMPLET :
    - TOUS les fichiers
    - TOUTE la période (365 jours)
    """
    cleanup_temp()
    
    try:
        cmd = [
            mobile_file_search_exe,
            "/ScanSubfolders", "1",
            "/ModifiedTime.FindMode", "6",
            "/ModifiedTime.LastXX", "365",
            "/CopyFiles.Folder", temp_folder,
            "/CopyFiles.PreserveTime", "1",
            "/CopyFiles"
            # Pas de /Wildcard = tout copier
        ]
        
        print("🔎 Scan COMPLET (365 jours, TOUS fichiers)...")
        
        subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=600,
            creationflags=subprocess.CREATE_NO_WINDOW
        )
        
        return wait_for_files(timeout=120, stable_seconds=5)
        
    except subprocess.TimeoutExpired:
        print("⏱️  Timeout")
        return len(get_all_temp_files()) > 0
    except Exception as e:
        print(f"❌ Erreur: {e}")
        return False

# --- MAIN ---

def main():
    os.makedirs(temp_folder, exist_ok=True)
    os.makedirs(final_folder, exist_ok=True)
    
    last_sync = get_last_sync_date()
    
    print(f"""
╔═══════════════════════════════════════════════════════════════════════╗
║                    📱 SYNCHRONISATION iPHONE → PC                     ║
╠═══════════════════════════════════════════════════════════════════════╣
║  📅 Dernière sync : {last_sync.strftime('%d/%m/%Y %H:%M'):<48} 
╠═══════════════════════════════════════════════════════════════════════╣
                                                                       
  [1]  ULTRA-RAPIDE                                                  
       Fichiers *.JPG uniquement                                      
       30 derniers jours                                              
       Très rapide pour sync quotidienne                              
                                                                       
  [2] 🔎 COMPLET                                                       
       TOUS les fichiers (JPG, HEIC, MOV, PNG, AAE...)               
       365 jours                                                      
       Plus lent, mais récupère tout                                  
                                                                       
╚═══════════════════════════════════════════════════════════════════════╝
    """)
    
    # Choix du mode
    while True:
        choice = input("    Votre choix [1/2] : ").strip()
        if choice in ('1', '2'):
            break
        print("     Tapez 1 ou 2")
    
    if choice == '1':
        mode_name = "ULTRA-RAPIDE"
        search_func = launch_search_ultra
    else:
        mode_name = "COMPLET"
        search_func = launch_search_complet
    
    print(f"\n     Mode {mode_name} sélectionné\n")
    
    # Vérifie iPhone
    print("🔌 Vérification iPhone...")
    
    if not check_iphone_connected():
        print("""
╔═══════════════════════════════════════════════════════════════════════╗
   iPHONE NON DÉTECTÉ !                                              
                                                                       
   Connectez l'iPhone en USB                                          
   Déverrouillez l'écran                                              
   Acceptez "Faire confiance à cet ordinateur"                        
╚═══════════════════════════════════════════════════════════════════════╝
        """)
        input("Appuyez sur Entrée quand prêt...")
        
        if not check_iphone_connected():
            print("❌ Abandon.")
            return
    
    print("📱 iPhone détecté !\n")
    
    prevent_sleep()
    total_copied = 0
    start_time = time.time()
    
    try:
        for attempt in range(1, 4):
            print(f"{'─'*60}")
            print(f"🔄 PASSE {attempt}/3")
            print(f"{'─'*60}")
            
            if not check_iphone_connected():
                print("⚠️  iPhone déconnecté !")
                input("   Reconnectez et appuyez Entrée...")
                if not check_iphone_connected():
                    break
            
            if search_func():
                copied = sync_photos(temp_folder, final_folder)
                total_copied += copied
                
                if copied == 0:
                    print("\n✅ Synchronisation complète !")
                    break
            else:
                if attempt < 3:
                    print("   Nouvelle tentative dans 3s...")
                    time.sleep(3)
        
        # Sauvegarde date
        if total_copied > 0:
            save_last_sync_date()
        
        # Durée
        elapsed = time.time() - start_time
        minutes = int(elapsed // 60)
        seconds = int(elapsed % 60)
        
        # Résumé
        print(f"""
╔═══════════════════════════════════════════════════════════════════════╗
║                         📊 RÉSUMÉ FINAL                               ║
╠═══════════════════════════════════════════════════════════════════════╣
║  Mode             : {mode_name:<47} 
  Fichiers copiés  : {total_copied:<47} 
  Durée            : {minutes}m {seconds}s{' ' * (44 - len(f"{minutes}m {seconds}s"))} 
  Destination      : {final_folder:<47} 
╚═══════════════════════════════════════════════════════════════════════╝
        """)
        
        if total_copied > 0:
            print("🎉 Vous pouvez déconnecter l'iPhone !")
        else:
            print("ℹ️  Aucun nouveau fichier.")
            
    finally:
        allow_sleep()
        cleanup_temp()

if __name__ == "__main__":
    main()

Créé il y a 4 semaines.

Rechercher un Pastebin

Aucun paste trouvé.