HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //proc/self/root/mnt/onedrive/openclaw/organize_onedrive.py
#!/usr/bin/env python3
"""
OneDrive Datei-Organisierer
===========================
Kopiert alle Dateien aus /mnt/onedrive in eine strukturierte Ordnerhierarchie.

Ausführen wenn:
1. Alle Dateien lokal verfügbar sind (OneDrive "Immer auf diesem Gerät behalten")
   ODER
2. Direkt mit rclone (empfohlen für Cloud-Only Dateien)

Verwendung:
  python3 organize_onedrive.py --rclone    # Nutzt rclone copy direkt
  python3 organize_onedrive.py --local     # Kopiert vom lokalen Mount
"""

import os
import shutil
import subprocess
import re
import argparse
from collections import defaultdict

SOURCE = "/mnt/onedrive"
DEST = "/mnt/onedrive_write/Organisiert"

# GPuG-Themen nach Lehrplan+ Bayern
GPUG_TOPICS = {
    "Weimarer_Republik": ["weimarer", "weimar", "novemberrevolution", "ruhraufstand", 
                          "vertrag von versailles", "völkerbund", "reparation", 
                          "weltwirtschaftskrise", "krisenjahre", "wrv", "goldene 20er"],
    "Nationalsozialismus_2Weltkrieg": ["nationalsozialismus", "ns-", "hitler", "nazi", 
                                        "mussolini", "faschismus", "zweiter weltkrieg", 
                                        "2. weltkrieg", "stauffenberg", "widerstand"],
    "Internationale_Beziehungen": ["internationale beziehungen", "nato", "friedensordnung",
                                    "nachkriegskonferenz", "europäische einigung"],
    "Wahlen_Parteien_Demokratie": ["parteien", "wahl", "wahlen", "csu", "spd", "fdp",
                                    "grüne", "ödp", "freie wähler", "demokratie"],
    "Politische_Theorie_Grundlagen": ["hobbes", "locke", "rousseau", "montesquieu", 
                                        "utopia", "vertragstheorie", "vertragslehre"],
    "Menschenrechte_Grundrechte": ["menschenrecht", "grundrecht", "freiheitsrecht"]
}

# Deutsch-Themen
DEUTSCH_TOPICS = {
    "Fokus_Epik": ["charakterisierung", "inhaltsangabe", "epik", "roman", "kurzgeschichte",
                   "erzähl", "22 bahnen", "perfect storm", "horváth", "wiener wald"],
    "Fokus_Drama": ["drama", "dramat", "theater", "brecht", "arturo ui", "faust",
                    "terror von schirach", "physiker", "dürrenmatt", "klassisches drama"],
    "Fokus_Sachtext": ["sachtext", "kommentar", "erörterung", "argument", "synthese",
                       "diskussion", "polemisch", "digitales lesen", "erörter"],
    "Lyrik": ["lyrik", "gedicht", "poesie", "metrik", "verse", "reim", "liebeslyrik"],
    "Grundwissen_Sprache": ["grundwissen", "grammatik", "konjunktiv", "indirekte rede",
                            "kommasetzung", "stilmittel", "rhetorisch", "textsorten"],
    "Literaturgeschichte": ["epoche", "literaturgeschichte", "barock", "aufklärung",
                            "klassik", "romantik", "realismus", "expressionismus"]
}

def detect_file_type(name, path):
    name_lower = name.lower()
    if any(x in name_lower for x in ["klausur", "test", "prüfung", "abitur", "vorabitur"]):
        return "Klausuren"
    if any(x in path.lower() for x in ["abgabe", "portfolio", "feedback"]):
        return "Schülerarbeiten"
    if any(x in name_lower for x in ["quartalsplan", "jahresplan", "lernplan"]):
        return "Organisatorisches"
    if any(x in name_lower for x in ["feedbackbogen", "bewertungsbogen", "korrekturbogen"]):
        return "Bewertungshilfen"
    if name_lower.endswith((".mp4", ".mov")):
        return "Lernvideos"
    if name_lower.endswith((".jpg", ".jpeg", ".png")):
        return "Bilder"
    return "Material"

def categorize_file(filepath):
    path_lower = filepath.lower()
    name = os.path.basename(filepath)
    name_lower = name.lower()
    file_type = detect_file_type(name, filepath)
    
    fach = "Sonstiges"
    jahrgang = "Allgemein"
    thema = "Sonstige_Dokumente"
    
    # Vorklasse erkennen
    if "/vorklasse" in path_lower:
        jahrgang = "Vorklasse"
        if "/gpug" in path_lower or "/gepug" in path_lower:
            fach = "GPuG"
        else:
            fach = "Deutsch"
    
    # Klassenordner erkennen
    if not jahrgang or jahrgang == "Allgemein":
        if re.search(r"/11[gwsv12]", path_lower) or "/11/" in path_lower:
            jahrgang = "11_Klasse"
        elif "12" in path_lower:
            jahrgang = "12_Klasse"
    
    # GPuG-Themen
    for topic, keywords in GPUG_TOPICS.items():
        if any(kw in path_lower or kw in name_lower for kw in keywords):
            if fach != "Deutsch":
                fach = "GPuG"
                thema = topic
                break
    
    # Deutsch-Themen
    if fach == "Sonstiges":
        for topic, keywords in DEUTSCH_TOPICS.items():
            if any(kw in path_lower or kw in name_lower for kw in keywords):
                fach = "Deutsch"
                thema = topic
                break
    
    # Sonstiges
    if fach == "Sonstiges":
        if "exkursion" in path_lower:
            thema = "Exkursionen"
        elif "projekt" in path_lower:
            thema = "Projekte"
        elif "/deutschbücher" in path_lower:
            fach = "Deutsch"
            thema = "Lehrbücher"
    
    return fach, jahrgang, thema, file_type

def main(use_rclone=False):
    print("OneDrive Datei-Organisierer")
    print("=" * 50)
    
    # Alle Dateien sammeln
    print("Sammle Dateien...")
    file_map = defaultdict(list)
    
    for root, dirs, files in os.walk(SOURCE):
        for f in files:
            src_path = os.path.join(root, f)
            rel_path = os.path.relpath(src_path, SOURCE)
            
            if rel_path.startswith("Organisiert"):
                continue
            
            fach, jahrgang, thema, file_type = categorize_file(src_path)
            
            if fach == "Sonstiges":
                dest = f"{fach}/{thema}"
            elif file_type and file_type not in ["Material", "Bilder"]:
                dest = f"{fach}/{jahrgang}/{thema}/{file_type}"
            else:
                dest = f"{fach}/{jahrgang}/{thema}"
            
            file_map[dest].append((src_path, rel_path, f))
    
    total = sum(len(v) for v in file_map.values())
    print(f"{total} Dateien in {len(file_map)} Zielordnern")
    
    # Ordner erstellen
    print("Erstelle Ordnerstruktur...")
    for folder in file_map.keys():
        os.makedirs(f"{DEST}/{folder}", exist_ok=True)
    
    # Dateien kopieren
    print(f"Kopiere Dateien {'(mit rclone)' if use_rclone else '(lokal)'}...")
    copied = 0
    errors = 0
    
    for dest_folder, files in file_map.items():
        for src_path, rel_path, filename in files:
            dest_path = f"{DEST}/{dest_folder}/{filename}"
            
            # Namenskonflikt lösen
            if os.path.exists(dest_path):
                base, ext = os.path.splitext(filename)
                dest_path = f"{DEST}/{dest_folder}/{base}_{hash(rel_path) % 10000}{ext}"
            
            try:
                if use_rclone:
                    result = subprocess.run(
                        ["rclone", "copy", f"onedrive:{rel_path}", f"{DEST}/{dest_folder}"],
                        capture_output=True, timeout=120
                    )
                    if result.returncode == 0:
                        copied += 1
                    else:
                        errors += 1
                else:
                    shutil.copy2(src_path, dest_path)
                    copied += 1
                    
                if copied % 100 == 0:
                    print(f"  {copied}/{total} kopiert...")
            except Exception as e:
                errors += 1
    
    print(f"\n{'=' * 50}")
    print(f"FERTIG: {copied} kopiert, {errors} Fehler")
    print(f"Ziel: {DEST}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Organisiert OneDrive-Dateien")
    parser.add_argument("--rclone", action="store_true", help="Nutze rclone statt lokalem Mount")
    parser.add_argument("--local", action="store_true", help="Kopiere vom lokalen Mount")
    args = parser.parse_args()
    
    main(use_rclone=args.rclone)