783 lines
27 KiB
Python
783 lines
27 KiB
Python
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<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()
|