786 lines
26 KiB
Python
Executable File
786 lines
26 KiB
Python
Executable File
#!/usr/bin/env -S uv run
|
|
# /// script
|
|
# requires-python = ">=3.13"
|
|
# dependencies = [
|
|
# "paramiko",
|
|
# "psycopg",
|
|
# ]
|
|
# ///
|
|
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/LegalPorno.2024.AngeloGodshakOriginal.Eden.Ivy.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/LegalPorno.24.07.13.Daniela.Garcia.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Bang.Rammed.24.10.03.Dan.Dangler.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/LegalPorno.2024.AngeloGodshackOriginal.Claudia.Macc.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/EvilAngel.22.05.29.Kitana.Montana.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/MySistersHotFriend.24.11.29.Anya.Olsen.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/CheatingSis.25.01.23.Kylie.Rocket.Property.Of.Stepbro.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/NFBusty.23.12.12.Hailey.Rose.And.Octavia.Red.Christmas.Party.Passion.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/SexArt.25.02.05.Leya.Desantis.Perfect.Man.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/TrueAnal.24.06.19.Katrina.Colt.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/AmericanDaydreams.23.07.03.Graycee.Baybee.XXX.1080p.HEVC.x265.PRT.mkv"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Slayed.25.03.04.Sonya.Blaze.And.Ellie.Luna.Tiny.Cutie.Is.Obsessed.With.Eating.Her.Hot.BFFs.Pussy.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/MYLFSeeker.25.02.08.Kelly.Caprice.Since.You.Became.My.Stepmom.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/JulesJordan.25.02.26.Emma.Hix.Sinful.Kitty.Gapes.After.A.Hard.Anal.Pounding.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/SexArt.23.08.04.Kelly.Collins.And.Milena.Ray.Rising.Passion.XXX.1080p.HEVC.x265.PRT.mkv"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/JulesJordan.25.03.02.Melissa.Stratton.Craves.Every.Inch.Of.Manuel.Ferraras.Fat.Cock.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Tushy.24.12.15.Agatha.Vega.And.Eve.Sweet.Long.Con.Part.3.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/DirtyAuditions.24.11.01.Alexa.Chains.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Deeper.24.09.12.Amber.Moore.Cucked.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Hegre.25.01.14.Anna.L.Gynecology.Photography.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Bang.Rammed.24.12.26.Brenna.Mckenna.And.Chanel.Camryn.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BlackedRaw.24.08.19.Cherry.Candle.Fiery.Red-head.Cherry.Drops.BF.For.His.Thick.BBC.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/AmericanDaydreams.23.09.09.Chloe.Amour.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BrattySis.24.08.23.Chloe.Temple.Stop.Staring.At.It.And.Fuck.It.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Luxure.23.03.10.Clara.Mia.And.Mary.Popiense.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BrazzersExxtra.23.10.19.Elisa.Calvi.Big.Milky.Breakfast.Tits.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/RoccoSiffredi.24.01.11.Elisa.Calvi.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/SheLovesBlack.22.10.27.Elisa.Calvi.Cougar.Hospitality.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/MyGirlfriendsBustyFriend.24.07.09.Ellie.Nova.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/SpankMonster.24.02.14.Ellie.Nova.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Private.25.01.23.Eva.Generosi.Cum.In.My.Ass.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BlackedRaw.22.12.20.Gianna.Dior.And.Kylie.Rocket.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BlackedRaw.22.12.20.Gianna.Dior.And.Kylie.Rocket.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BangBrosClips.22.09.13.Graycee.Baybee.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/TushyRaw.24.12.31.Graycee.Baybee.Anal.Crazy.Blonde.Gapes.Wide.Open.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/MySistersHotFriend.24.12.02.Hailey.Rose.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/AnalOnly.24.12.12.Isabel.Love.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/EvilAngel.23.09.22.Jena.Larose.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/EvilAngel.24.05.27.Katie.Kush.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/DirtyAuditions.23.12.25.Katrina.Colt.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/JulesJordan.22.12.18.Katrina.Colt.Is.A.Big.Black.Cock.Slut.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Swallowed.24.12.16.Ashley.Alexander.And.Katrina.Colt.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BlackedRaw.25.02.15.Kelly.Collins.And.Zazie.Skymm.Kelly.And.Blonde.BFF.Prowl.For.BBC.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Blacked.22.07.09.Kylie.Rocket.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/TrueAnal.24.11.27.Lilith.Grace.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Joymii.23.02.15.Mary.Popiense.Surprise.Visit.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/TeenFidelity.E475.Mary.Popiense.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/NubileFilms.23.02.05.Molly.Little.A.Touch.Down.Here.Wins.The.Game.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/LittleCaprice-Dreams.23.11.17.Nata.Ocean.Nasstyx.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/ClubSweethearts.24.02.09.Princess.Alice.Hardcore.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/AnalOnly.24.12.04.Raven.Lane.And.Cassidy.Luxe.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{
|
|
"file_path": "/mnt/box/files/_raw/prt/LegalPorno.23.11.15.Rebel.Rhyder.Interracial.Fisting.Gangbang.Wet.4on1.BBC.DAP.Gapes.ButtRose.Pee.Drink.Shower.Squirt.Creampie.Swallow.GIO2595.XXX.1080p.HEVC.x265.PRT.mp4"
|
|
},
|
|
{
|
|
"file_path": "/mnt/box/files/_raw/prt/PissVids.23.07.21.Rebel.Rhyder.Blackended.Wet.DAP.Rough.Sex.Big.Gapes.Pee.Cocktail.Pee.Drink.Pee.Shower.Creampie.Cum.In.Mouth.GIO2512.XXX.1080p.HEVC.x265.PRT.mp4"
|
|
},
|
|
{
|
|
"file_path": "/mnt/box/files/_raw/prt/PissVids.23.02.08.Masked.Vs.Rebel.Rhyder.Wet.4on1.BBC.ATM.DAP.No.Pussy.Gapes.ButtRose.Pee.Drink.Squirt.Cum.In.Mouth.Swallow.GIO2330.XXX.1080p.HEVC.x265.PRT.mp4"
|
|
},
|
|
{
|
|
"file_path": "/mnt/box/files/_raw/prt/PissVids.23.06.18.Rebel.Rhyder.The.Loan.Re-Payment.Wet.5on1.Rough.Sex.ATM.DAP.Gapes.Pee.Drink.Pee.Shower.Cum.In.Mouth.Swallow.GIO2514.XXX.1080p.HEVC.x265.PRT.mp4"
|
|
},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BrazzersExxtra.24.10.10.Ryan.Reid.Face.Fucking.The.Slutty.Sitter.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BrazzersExxtra.25.01.27.Ryan.Reid.Horny.House.Sitter.Hits.The.Jackpot.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/Private.22.06.14.Sata.Jones.Anal.Debut.XXX.1080p.HEVC.x265.PRT.mkv"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/EvilAngel.24.11.05.Scarlet.Chase.Latex.Gloves.Fist.And.Jerk.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/BangBrosClips.24.12.03.Shalina.Devine.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/AllAnal.24.12.07.Selena.Love.And.Stella.Luxx.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/TrueAnal.24.08.24.Tessa.Thomas.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/EvilAngel.25.02.10.Willow.Ryder.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/ThePOVGod.24.12.13.Willow.Ryder.Fuckin.With.The.Best.XXX.720p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/FamilyXXX.24.01.05.Ellie.Nova.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/JaxSlayher.24.01.11.Ellie.Nova.XXX.1080p.HEVC.x265.PRT.mp4"},
|
|
{"file_path": "/mnt/box/files/_raw/prt/POVMasters.24.09.23.Lina.Love.XXX.720p.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<people>.+) - (?P<title>.+) --? (?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()
|