import contextlib import hashlib import json import logging import re import sqlite3 import subprocess import typing from collections import Counter, defaultdict from pathlib import Path import paramiko import psycopg import psycopg.rows import ffmpeg VIDS_DIR = Path(r"/Volumes/FIVER/_ingress/") schema = """ create table if not exists videos( file_path text not null primary key, size_bytes int not null, hash_partial text not null, ffprobe json not null ); create table if not exists scan_state( file_path text not null primary key, stderr text ); """ def find_vids(root: Path): extensions = [".mkv", ".mp4"] for ext in extensions: for f in root.rglob(f"*{ext}"): yield f def hash_partial(f: Path) -> str: sha1 = hashlib.sha1() chunk_size = 1024 * 1024 * 10 # 10MB chunk size total_read = 0 with f.open("rb") as file: while chunk := file.read(chunk_size): total_read += len(chunk) sha1.update(chunk) break # Only reads the first 10MB return f"sha1:{total_read}:{sha1.hexdigest()}" @contextlib.contextmanager def connect_db_sqlite() -> typing.Generator[psycopg.Connection, typing.Any, typing.Any]: with sqlite3.connect("vids.sqlite3") as conn: conn.row_factory = sqlite3.Row conn.execute("PRAGMA foreign_keys = 1") yield conn @contextlib.contextmanager def connect_db() -> typing.Generator[psycopg.Connection, typing.Any, typing.Any]: with psycopg.connect("postgres://abdus:abdus@db.abdus.dev:5444/smut?sslmode=disable") as conn: conn.row_factory = psycopg.rows.dict_row yield conn def video_exists(con: psycopg.Connection, file_path: str) -> bool: stmt = con.execute( "select exists(select 1 from videos where file_path = %s) as exists", [file_path], ) row = stmt.fetchone() return row["exists"] def delete_video(con: psycopg.Connection, file_path: str) -> bool: con.execute("delete from videos where file_path = %s", [file_path]) def save_video( con: psycopg.Connection, category: str, file_path: str, ffprobe: dict, hash_partial: str, ): sql = """insert into videos(category, file_path, ffprobe, hash_partial) values (%s, %s, %s, %s);""" con.execute( sql, [ category, file_path, json.dumps(ffprobe), hash_partial, ], ) def save_error(con: psycopg.Connection, file_path: str, stderr: str): sql = """insert into scan_state(file_path, stderr) values (%s, %s) on conflict do nothing""" con.execute( sql, [ file_path, stderr, ], ) def scan_videos(): logging.basicConfig(format=logging.BASIC_FORMAT, level=logging.DEBUG) with connect_db() as con: # with con: # con.executescript(schema) all_vids = list(find_vids(VIDS_DIR)) for i, f in enumerate(all_vids): if "/_picks/" in str(f): continue progress = f"[{i+1}/{len(all_vids)}]" if f.is_dir(): continue file_path = str(f.absolute()) if video_exists(con, file_path=file_path): logging.debug(f"{progress} video already exists {f=}") continue logging.debug(f"probing {f=}") try: probed = ffmpeg.ffprobe(f) except subprocess.CalledProcessError as e: save_error(con, file_path=file_path, stderr=e.stderr) continue file_hash = hash_partial(f) save_video( category="downloaded.fiver", con=con, file_path=file_path, ffprobe=probed.__dict__, hash_partial=file_hash, ) logging.info(f"{progress} saved {f=}") con.commit() def clean_records(): all_vids = set(map(str, find_vids(VIDS_DIR))) with connect_db() as con: for row in con.execute("select file_path from videos"): file_path = row["file_path"] if file_path not in all_vids: delete_video(con, file_path=row["file_path"]) def unwanted(dry_run: bool): take = set( r""" aidra fox rachel starr abella danger sata jones octavia red paige owens lily lou cj miles arabelle raphael chloe amour erin everheart kenzie reeves alex grey alicia trece angel youngs angela white april olsen blake blossom brandy renee chantal demi sutra eden ivy ema karter emma hix gianna dior hazel moore jazmin luv jessy jey josephine jackson katsaros kira noir kitana lure kitana montana kristy black leal lia lin lily labeau liya silver maddy may nata ocean rebel rhyder rein savannah bond scarlett alexis scarlit scandal shalina simon kitty slimthick vic stratton tatum tommy king vanna bardot vic marie violet starr vittoria emily willis THUNDERCOCK lucky bee charlotte sins mandy muse skye blue alexis tae willow TRUEANAL ALLANAL avery cristy ANALONLY SWALLOWED kelly collins nicole black xxlayna marie katrina colt allie addison DIRTYAUDITIONS scarlet chase #sloppiest kiss liz ocean medusa nicole aria stacy bloom lara frost jamie jett brooklyn gray kimmy granger kelsey kane kay lovely ivy wolfe stefany kyler leo ahsoka lydia black renee rose emily jade anya olsen alexis crystal sybil megan rain charlotte sartre madison ivy maddy black gina valentina lacey jayne hailey rose graycee baybee katie kush lilu moon juis wild kylie rocket dolly dyson nichole saphir Octokuro reislin isabella de laa qween goddess INTHECRACK athenea rose daniela garcia kama oxi mina baby nicols jade amor daniela ortiz NYMPHO """.strip().splitlines(keepends=False) ) drop = set( r""" ADDICTED2GIRLS ASIANSEEPLOITED BANANAFEVER BBCPOVD BFFS # BRAZZERSEXXTRA BRIDE4K CHLOELAMOUR DRKINLA ETERNALDESIRE EVERYTHINGBUTT FAKEHOSTEL FAKEHUBORIGINALS FAKETAXI FAMILYSINNERS FEETISHPOV GIRLGIRLXXX GOTFILLED HOOKUPHOTSHOT HOWWOMENORGASM IMMORALLIVE IWANTCLIPS JACQUIEETMICHELTV JERKAOKE NICONICE NURUMASSAGE OHMYHOLES OYELOCA PASCALSSUBSLUTS SCHOOLOFCOCK SHOTHERFIRST SLIPPERYMASSAGE TABOOHEAT TEAMSKEETX WAXXXED WOODMANCASTINGX PISSVIDS LEGALPORNO ANALVIDS PORNBOX \btap\b alice xo alicia williams mona azar anna de ville baby kxtten bella rolland betzz charlie forde charlie red cheyla collins claudia garcia cory chase dani blue dellai eimy zoren emily pink gia dibella greta foss danielle renae harley king ivy maddox sasha rose olive glass katherin moore kristina grace kylie page larissa leite lily starfire lina arian luna legend luna rishi luna wolfs lya cutie margan lee marie berger marilyn johnson mia cheers monika fox moona snake nichole saphir nicole murkovski olivia sparkle polly petrova pornworld publicagent publicbang stacy cruz sussy sweet triple anal vanessa vega venera maxima victoria nyx whitney wright zirael rem """.lower() .strip() .splitlines(keepends=False) ) take_patterns = [re.compile(p.strip().replace(" ", "."), flags=re.I) for p in take if not p.strip().startswith("#")] drop_patterns = [re.compile(p.strip().replace(" ", "."), flags=re.I) for p in drop if not p.strip().startswith("#")] to_delete = set() with connect_db() as con: for row in con.execute("select file_path from videos where category = 'box'"): file_path = Path(row["file_path"]) text = re.sub(r"[.]+", " ", file_path.stem.lower()) if any(p.search(text) for p in drop_patterns): to_delete.add(file_path) if any(p.search(text) for p in take_patterns): to_delete.discard(file_path) for it in sorted(to_delete): print(it) return with connect_db() as con: for path in sorted(to_delete, key=str): try: print(path.stem) con.execute( "update videos set marked_for_deletion_at = now() where file_path = %s", [str(path)], ) if not dry_run: path.unlink() delete_video(con, file_path=str(path)) con.commit() except: pass print(len(to_delete)) def large_unwanted(): with connect_db() as con: for row in con.execute("select file_path from videos order by size_bytes desc limit 500"): file_path = Path(row["file_path"]) print(file_path) def list_studios(): re_studio = re.compile(r"^(.+?)\.\d+", flags=re.IGNORECASE) seen = defaultdict(int) with connect_db() as con: for row in con.execute("select file_path from videos"): file_path = Path(row["file_path"]) m = re_studio.search(file_path.stem.lower()) if m: seen[m.group(1)] += 1 for it, n in Counter(seen).most_common(20): print(it, n) def lower_resolutions(dry_run: bool): with connect_db() as con: for row in con.execute("""select file_path from videos where file_path like '%720p%';"""): file_path = Path(row["file_path"]) video_1080p_path = file_path.with_stem(file_path.stem.replace("720p", "1080p")) if video_exists(con, file_path=str(video_1080p_path)) and video_1080p_path.is_file(): print(file_path) if not dry_run: file_path.unlink() def dupes(): sql = """ with durationed as ( select v.*, json_extract(v.ffprobe, '$.duration_sec') as duration_sec from videos v ) select v.file_path, dupe.file_path from durationed v join durationed dupe on v.file_path != dupe.file_path and abs(dupe.duration_sec - v.duration_sec) < 3 where abs(dupe.size_bytes - v.size_bytes) < 3000000 """ with connect_db() as con: for row in con.execute(sql): print(row[0], row[1]) print() def different_format(dry_run: bool): sql = """ select file_path from videos where file_path like '%.mkv' """ with connect_db() as con: for row in con.execute(sql): mkv_path = Path(row["file_path"]) mp4_path = mkv_path.with_suffix(".mp4") if mkv_path.is_file() and mp4_path.is_file(): if abs(mp4_path.stat().st_size - mkv_path.stat().st_size) < 5_000_000: print(mkv_path) if not dry_run: mkv_path.unlink() def count_shared_words(a: str, b: str) -> int: a_words = set(re.split(r"[\s\-.]+", a.lower())) b_words = set(re.split(r"[\s\-.]+", b.lower())) return len(a_words.intersection(b_words)) def reencoded_self(dry_run: bool): sql = """ with durationed_v as ( select v.*, json_extract(v.ffprobe, '$.duration_sec') as duration_sec from videos v ), durationed_dl as ( select v.*, json_extract(v.ffprobe, '$.duration_sec') as duration_sec from downloaded_videos v ) select v.file_path, dlv.file_path from durationed_v v join durationed_dl dlv on abs(v.duration_sec - dlv.duration_sec) < 0.1 where dlv.file_path like '%/_reenc/%' """ with connect_db() as con: for row in con.execute(sql): v_path = Path(row[0]) dlv_path = Path(row[1]) if count_shared_words(v_path.stem, dlv_path.stem) < 2: continue print(v_path.name, dlv_path.name, sep="\n") if not dry_run: try: v_path.unlink() except: pass def local_duped(dry_run: bool): sql = """ with durationed_dl as ( select v.*, json_extract(v.ffprobe, '$.duration_sec') as duration_sec from downloaded_videos v ) select v.file_path, dupe.file_path from durationed_dl v join durationed_dl dupe on v.id != dupe.id and v.id > dupe.id and abs(dupe.duration_sec - v.duration_sec) < 0.1 and abs(dupe.size_bytes - v.size_bytes) < 3000000 """ root = Path(r"/Volumes/FIVER/_ingress/") with connect_db() as con: for row in con.execute(sql): a_path = Path(row[0]) b_path = Path(row[1]) if count_shared_words(a_path.stem, b_path.stem) < 6: continue # print(a_path.name, b_path.name, sep='\n') keep, remove = a_path, b_path if len(b_path.stem) > len(a_path.stem): keep, remove = b_path, a_path print(" # ", "matching", keep.name) print(" rm", f'"{remove}"') print() def delete_dupes(): rows = [] with connect_db() as con: for row in rows: file_path = Path(row["file_path"]) try: file_path.unlink() delete_video(con, file_path=row["file_path"]) con.commit() except: pass def save_suggested_names(): rows = [] with connect_db() as con: for row in rows: bandaid_path = Path(row["file_path"]) fiver_path = Path(row["fiver_path"]) if bandaid_path.stem == fiver_path.stem: continue if count_shared_words(bandaid_path.stem, fiver_path.stem) < 3: print("unsimilar", row) continue if bandaid_path.stem.count("--") == 3: better_stem = bandaid_path.stem else: better_stem = fiver_path.stem better_stem = re.sub(r"(\d{4})(\d{2})(\d{2})", r"\1-\2-\3", better_stem) if better_stem == fiver_path.stem: continue print(fiver_path.name, better_stem, sep="\n") con.execute( "update videos set suggested_filename = %s where file_path = %s", [better_stem, fiver_path.name], ) con.commit() def delete_remote_files(): rows = [ {"file_path": "/mnt/box/files/_raw/prt/5KPorn.24.10.02.Leya.Desantis.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/AllAnal.24.10.30.Aviana.Violet.And.Nicole.Aria.XXX.720p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/AllAnal.24.11.07.Khloe.Kingsley.And.Cherry.Kiss.XXX.720p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/AnalOnly.24.11.26.Aria.Sloane.And.Nicole.Doshi.XXX.720p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/AnalTherapyXXX.24.02.10.Willow.Ryder.Family.Competition.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/AngelsLove.23.07.29.Cherry.Candle.And.Stacy.Cruz.Hot.Juice.Is.Dripping.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BBCPie.20.05.31.Hazel.Moore.Morning.Wood.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BangBros18.24.06.16.Angel.Gostosa.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BangPOV.24.02.20.Justine.Jakobs.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/Blacked.22.10.29.Kay.Lovely.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BlacksOnBlondes.22.11.29.Hazel.Moore.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BlacksOnBlondes.24.11.22.Kylie.Rocket.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrattySis.22.06.10.Angel.Gostosa.Everyone.Wants.To.Fuck.My.Stepsister.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrattySis.23.06.23.Angel.Gostosa.My.Stepsister.Takes.Charge.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrattySis.24.05.10.Jade.Maris.And.Vanessa.Marie.Sharing.Stepbros.Bed.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrattySis.24.05.31.Renee.Rose.Nobody.Wants.To.Fuck.A.Virgin.Stepbro.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrattySis.24.07.26.Jade.Maris.And.Sera.Ryder.I.Want.To.Bone.My.Stepsister.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrazzersExxtra.24.08.21.Destiny.Mira.Cyclist.Sweat.Leads.To.Shower.Sex.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrazzersExxtra.24.10.20.Baby.Gemini.Dripping.Wet.Hookup.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrazzersExxtra.24.11.04.Nichole.Saphir.Tattooed.Bombshells.Gaping.Anal.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrazzersExxtra.24.11.20.Katie.Kush.And.Kelly.Caprice.Free.Use.Maid.Service.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/BrazzersExxtra.24.11.20.Kira.Noir.Secret.Goth.Camgirl.Roomie.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/CherryPimps.Busted.24.08.14.Lacey.Jayne.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/CrazyCollegeGFs.24.02.20.Destiny.Mira.Bunk.Banging.The.Handyman.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/Creampie-Angels.22.07.03.Nata.Ocean.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/CumSwappingSis.24.03.16.Jade.Maris.And.Liz.Jordan.Giving.Stepbro.Something.To.Do.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/DFXSoleMates.24.06.15.Angel.Gostosa.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/DatingMyStepson.24.10.03.Shalina.Devine.A.Game.Of.Dare.Always.Spices.Things.Up.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/DirtyAuditions.24.08.17.Kazumi.XXX.720p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/ElegantAngel.24.01.01.Hazel.Moore.A.Touch.Of.Class.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/ElegantAngel.24.11.29.Scarlett.Alexis.Stretch.My.Hole.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/EvilAngel.24.06.01.Chloe.Amour.XXX.1080p.HEVC.x265.PRT.mkv"}, {"file_path": "/mnt/box/files/_raw/prt/EvilAngel.24.11.01.Princess.Alice.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/FilthyTaboo.24.10.19.Kelly.Caprice.Unsatisfied.MILF.Gets.What.She.Craves.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/GirlGirlXXX.24.01.16.Kylie.Rocket.And.Melissa.Stratton.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/Hegre.24.10.22.Anna.L.Erotic.Goddess.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/HotwifeXXX.24.11.06.Willow.Ryder.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/InTheCrack.E1928.Lia.Lin.Provence.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/KarupsPC.20.04.01.Nata.Ocean.Horny.Housekeeper.XXX.1080p.HEVC.x265.PRT.mkv"}, { "file_path": "/mnt/box/files/_raw/prt/LegalPorno.23.11.10.Lady.Ana.Jureka.Del.Mar.Fisting.ATOGM.Double.Anal.Fist.Big.Gapes.Monster.ButtRose.Squirt.Creampie.Swallow.GIO2635.XXX.1080p.HEVC.x265.PRT.mkv" }, {"file_path": "/mnt/box/files/_raw/prt/LegalPorno.24.06.19.Kristy.Black.GIO2815.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/LegalPorno.24.10.02.Leila.Botwin.AH007.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/LegendaryX.24.01.11.Melissa.Stratton.And.Nicole.Doshi.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/LegendaryX.24.02.01.Chantal.Danielle.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/LilSis.24.05.17.Jade.Maris.Let.The.Games.Begin.Part.1.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/LittleCaprice-Dreams.24.11.09.Tiffany.Tatum.And.Nata.Ocean.Nasstyx.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/MilfBody.24.06.14.Kelly.Caprice.Kellys.New.Routine.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/MomIsHorny.23.12.29.Justine.Jakobs.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/MomXXX.24.11.05.Kiara.Lord.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/MomsTeachSex.23.11.24.Justine.Jakobs.Getting.Down.To.Business.XXX.1080p.HEVC.x265.PRT.mkv"}, {"file_path": "/mnt/box/files/_raw/prt/MrLuckyPOV.24.01.05.Gianna.Dior.And.Kazumi.Squirts.An.All.Star.Threesome.XXX.1080p.HEVC.x265.PRT.mkv"}, {"file_path": "/mnt/box/files/_raw/prt/MrLuckyPOV.24.01.05.Gianna.Dior.And.Kazumi.Squirts.An.All.Star.Threesome.XXX.1080p.HEVC.x265.PRT.mkv"}, {"file_path": "/mnt/box/files/_raw/prt/MySistersHotFriend.24.04.09.Willow.Ryder.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/NewSensations.24.11.16.Ellie.Nova.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/NubileFilms.23.10.17.Liz.Jordan.My.Roommate.Has.A.Crush.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/NubileFilms.23.11.20.Hailey.Rose.And.Jade.Maris.Happy.Birthday.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/NubileFilms.24.02.01.Liz.Jordan.February.2024.Fantasy.Of.The.Month.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/NubileFilms.24.03.01.Jade.Maris.March.2024.Fantasy.Of.The.Month.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/NubileFilms.24.12.01.Chloe.Temple.December.2024.Fantasy.Of.The.Month.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/Nubiles-Casting.24.10.28.Chanel.Camryn.Cast.Addison.Vodka.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/PascalsSubSluts.21.06.25.Rebel.Rhyder.Every.Inch.Every.Hole.XXX.1080p.HEVC.x265.PRT.mkv"}, {"file_path": "/mnt/box/files/_raw/prt/Passion-HD.24.04.03.Aria.Valencia.Good.Help.XXX.1080p.HEVC.x265.PRT.mp4"}, { "file_path": "/mnt/box/files/_raw/prt/PissVids.23.05.20.Juis.Wild.Black.Pee.1on1.BBC.ATM.Balls.Deep.No.Pussy.Rough.Sex.Gapes.Pee.Drink.Cum.In.Mouth.Swallow.GL836.XXX.1080p.HEVC.x265.PRT.mp4" }, {"file_path": "/mnt/box/files/_raw/prt/PornMegaLoad.24.07.18.Justine.Jakobs.Hardcore.40443.XXX.1080p.HEVC.x265.PRT.mkv"}, {"file_path": "/mnt/box/files/_raw/prt/PornPlus.24.10.18.Hailey.Rose.Naturally.Gifted.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/Private.23.11.18.Dolly.Dyson.Enjoys.An.Anal.Threesome.With.Mary.Popiense.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/Private.24.11.18.Lia.Lin.Gets.Horny.By.The.Pool.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/RKPrime.24.10.28.Octokuro.Fucking.After.The.Club.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/RickysRoom.23.03.09.Destiny.Mira.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/SexSelector.23.03.17.Graycee.Baybee.XXX.1080p.HEVC.x265.PRT.mkv"}, {"file_path": "/mnt/box/files/_raw/prt/StrapLez.23.08.17.Alexis.Crystal.And.Lilly.Bella.Everything.She.Wants.XXX.1080p.HEVC.x265.PRT.mkv"}, {"file_path": "/mnt/box/files/_raw/prt/StrapLez.24.11.14.Cherry.Candle.And.Lilly.Mays.Pleasure.Control.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/StrapLez.24.11.28.Alexis.Crystal.And.Mia.Trejsi.Rhythm.Of.Desire.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/TeensLoveHugeCocks.23.04.28.Kylie.Rocket.Influencers.Delight.XXX.1080p.HEVC.x265.PRT.mkv"}, {"file_path": "/mnt/box/files/_raw/prt/ThePOVGod.24.10.25.Willow.Ryder.The.Call.Of.That.Booty.XXX.1080p.HEVC.x265.PRT.mp4"}, {"file_path": "/mnt/box/files/_raw/prt/Tiny4K.23.02.02.Liz.Jordan.Ice.Cream.Treat.XXX.1080p.HEVC.x265.PRT.mp4"}, ] with connect_server("klein") as ssh, connect_db() as con: for row in rows: file_path = row["file_path"] try: print("deleting", file_path) ssh.exec_command(f'rm -rf "{file_path}"') delete_video(con, file_path=file_path) con.commit() except: pass @contextlib.contextmanager def connect_server(host: str) -> typing.Generator[paramiko.SSHClient, typing.Any, None]: config = paramiko.SSHConfig.from_path(str(Path(r"~/.ssh/config").expanduser())) key = paramiko.RSAKey.from_private_key_file(filename=str(Path(r"~/.ssh/id_rsa").expanduser())) target = config.lookup(host) ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_client.connect( hostname=target["hostname"], port=target.as_int("port"), username=target["user"], pkey=key, ) yield ssh_client ssh_client.close() def collect_all(): root = Path("/Volumes/FATBLUE/_backup/_vidz/_all") video_files = find_vids(root) # re_good = re.compile(r"(?P.+) - (?P.+) --? (?P<studio>\S+) (?P<date_year>\d{4})(?P<date_month>\d{2})(?P<date_day>\d{2})") # re_good = re.compile(r"(?P<people>.+) - (?P<title>.+) --? (?P<studio>\S+)") # re_good = re.compile(r"(?P<people>.+) - (?P<title>.+) --? (?P<date_year>\d{4})(?P<date_month>\d{2})(?P<date_day>\d{2})") re_good = re.compile(r"(?P<people>.+) - (?P<title>[^-]+) (?P<date_year>\d{4})(?P<date_month>\d{2})(?P<date_day>\d{2})") for f in sorted(video_files): m = re_good.search(f.stem) if not m: continue params = m.groupdict() title = params["title"] if " " not in title: print(f.stem, title, sep="\t\t") continue # better_name = f"{m['people']} -- @{m['studio']} -- {m['title']} -- {m['date_year']}-{m['date_month']}-{m['date_day']}" better_name = f"{m['people']} -- {m['title']} -- {m['date_year']}-{m['date_month']}-{m['date_day']}" # better_name = f"{m['people']} -- @{m['studio']} -- {m['title']}" print(f.stem, better_name, sep="\n") better_path = f.with_stem(better_name) f.rename(better_path) def clean_images(): from PIL import Image for img in Path(r"/Users/abdus/Downloads/temp/Ploy Tigerstam -- OnlyFans Leak").glob("*.jpg"): image = Image.open(img) width, height = image.size if width < 2000 or height < 2000: img.unlink() def main(): dry = True try: # clean_images() # collect_all() # save_suggested_names() # delete_remote_files() # transfer() # different_format(dry_run=dry) # local_duped(dry_run=dry) # reencoded_self(dry_run=dry) # dupes() # scan_videos() # list_studios() # lower_resolutions(dry_run=dry) # large_unwanted() unwanted(dry_run=dry) finally: pass # clean_records() if __name__ == "__main__": main()