package Acme::Frobnitz;
use strict;
use warnings;
use IPC::System::Simple qw(capturex);
use Cwd qw(abs_path);
use File::Spec;
use File::stat;
use File::Basename;
use FindBin;
use POSIX qw(strftime);
our $VERSION = '0.03';
####
sub new {
my ($class) = @_;
return bless {}, $class;
}
sub _get_script_path {
my ($class, $script_name) = @_; # Resolve base directory dynamically
my $base_dir = abs_path("$FindBin::Bin/.."); # One level up from bin
my $script_path = File::Spec->catfile($base_dir, 'bin', $script_name);
unless (-x $script_path) {
die "Script $script_path does not exist or is not executable.\n";
}
return $script_path;
}
sub download {
my ($class, $hyperlink) = @_;
die "No hyperlink provided.\n" unless $hyperlink;
my $script_path = $class->_get_script_path("call_download.sh");
my $output;
eval {
$output = capturex("bash", $script_path, $hyperlink);
};
if ($@) {
die "Error executing $script_path with hyperlink $hyperlink: $@\n";
}
return $output;
}
##
##
use strict;
use warnings;
use Acme::Frobnitz;
my $frobnitz = Acme::Frobnitz->new();
# URL of the video to download
my $video_url = "https://www.instagram.com/p/DDa_FxsNtTe/";
# Step 1: Download the video
my $downloaded_file = $frobnitz->download($video_url);
print "Downloaded video to: $downloaded_file\n";
# Step 2: Verify the downloaded file
print "Verifying downloaded file...\n";
if ($frobnitz->verify_file($downloaded_file)) {
print "File verification successful.\n";
} else {
die "File verification failed. Aborting further processing.\n";
}
# Step 3: Add watermark to the downloaded video
my $final_file = $frobnitz->add_watermark($downloaded_file);
print "Final watermarked video is at: $final_file\n";
##
##
sub verify_file {
my ($class, $file_path) = @_;
die "File path not provided.\n" unless $file_path;
my $abs_path = abs_path($file_path) // $file_path;
if (-e $abs_path) {
print "File exists: $abs_path\n";
# File size
my $size = -s $abs_path;
print "File size: $size bytes\n";
# File permissions
my $permissions = sprintf "%04o", (stat($abs_path)->mode & 07777);
print "File permissions: $permissions\n";
# Last modified time
my $mtime = stat($abs_path)->mtime;
print "Last modified: ", strftime("%Y-%m-%d %H:%M:%S", localtime($mtime)), "\n";
# Owner and group
my $uid = stat($abs_path)->uid;
my $gid = stat($abs_path)->gid;
print "Owner UID: $uid, Group GID: $gid\n";
return 1; # Verification success
} else {
print "File does not exist: $abs_path\n";
my $dir = dirname($abs_path);
# Report directory details
print "Inspecting directory: $dir\n";
opendir my $dh, $dir or die "Cannot open directory $dir: $!\n";
my @files = readdir $dh;
closedir $dh;
print "Directory contents:\n";
foreach my $file (@files) {
next if $file =~ /^\.\.?\$/; # Skip . and ..
my $file_abs = File::Spec->catfile($dir, $file);
my $type = -d $file_abs ? 'DIR ' : 'FILE';
my $size = -s $file_abs // 'N/A';
print "$type - $file (Size: $size bytes)\n";
}
return 0; # Verification failed
}
}
##
##
(base) fritz@laptop:~/Desktop/Acme-Frobnitz-Snapshot$ ls
Acme-Frobnitz-Snapshot.tar.gz Dockerfile Makefile MYMETA.yml xt
bin ignore.txt Makefile.PL README
Changes lib MANIFEST requirements.txt
conf logs MYMETA.json t
(base) fritz@laptop:~/Desktop/Acme-Frobnitz-Snapshot$ perl Makefile.PL
WARNING: Setting ABSTRACT via file 'lib/Acme/Frobnitz.pm' failed
at /usr/share/perl/5.30/ExtUtils/MakeMaker.pm line 754.
...Q1) Why do I get this warning?
Generating a Unix-style Makefile
Writing Makefile for Acme::Frobnitz
Writing MYMETA.yml and MYMETA.json
(base) fritz@laptop:~/Desktop/Acme-Frobnitz-Snapshot$ make
cp lib/Acme/._Frobnitz.pm.bak blib/lib/Acme/._Frobnitz.pm.bak
cp lib/python_utils/watermarker2.py blib/lib/python_utils/watermarker2.py
cp lib/python_utils/__pycache__/watermarker2.cpython-39.pyc blib/lib/python_utils/__pycache__/watermarker2.cpython-39.pyc
cp lib/python_utils/__pycache__/watermarker2.cpython-313.pyc blib/lib/python_utils/__pycache__/watermarker2.cpython-313.pyc
...^^^I see all these little barnacle files now...
...in 3 lines we cross into python logging...
t/00-load.t ....... 1/? # Testing Acme::Frobnitz 0.03, Perl 5.030000, /usr/bin/perl
t/00-load.t ....... ok
t/13.download.t ... 1/? 2024-12-17 06:28:26,320 - __main__ - INFO - Attempting to create directory: E4B0-3FC22024-12-17/
2024-12-17 06:28:26,320 - __main__ - INFO - Directory created or already exists: E4B0-3FC22024-12-17/
2024-12-17 06:28:26,321 - __main__ - INFO - Entering function: mask_metadata
2024-12-17 06:28:26,321 - downloader5 - INFO - Masking metadata
2024-12-17 06:28:26,321 - downloader5 - INFO - Received parameters for metadata extraction:
2024-12-17 06:28:26,322 - downloader5 - INFO - download_path: E4B0-3FC22024-12-17/
...oh damn, that's the problem right there........................^^^^^^^^^^
##
##
2024-12-17 06:28:36,493 - __main__ - INFO - Entering function: create_original_filename
2024-12-17 06:28:36,494 - downloader5 - INFO - Generated original filename: E4B0-3FC22024-12-17/Rick_Astley_20091025.webm
2024-12-17 06:28:36,494 - __main__ - INFO - Entering function: download_video
2024-12-17 06:28:36,494 - downloader5 - INFO - Received parameters: download_video:
2024-12-17 06:28:36,494 - downloader5 - INFO - download_path: E4B0-3FC22024-12-17/
... again oops^^^ .....
2024-12-17 06:28:36,496 - downloader5 - INFO - video_title: Rick_Astley_-_Never_Gonna_Give_You_Up_(Official_Music_Video)
2024-12-17 06:28:36,496 - downloader5 - INFO - video_date: 20091025
...but here's the false positive:
2024-12-17 06:29:22,739 - downloader5 - INFO - Video download completed.
2024-12-17 06:29:22,742 - downloader5 - INFO - Download completed in 46.24 seconds
...this part is one of my favorites:
2024-12-17 06:29:22,742 - __main__ - INFO - Entering function: store_params_as_json
2024-12-17 06:29:22,743 - utilities1 - INFO - Params saved to JSON file: E4B0-3FC22024-12-17/Rick_Astley_20091025.json
2024-12-17 06:29:22,743 - __main__ - INFO - Returning original filename: E4B0-3FC22024-12-17/Rick_Astley_20091025.webm
t/13.download.t ... ok
...should have failed...
Result: PASS
(base) fritz@laptop:~/Desktop/Acme-Frobnitz-Snapshot$ sudo make install
[sudo] password for fritz:
Installing /usr/local/share/perl/5.30.0/Acme/Frobnitz.pm
...
##
##
(base) fritz@laptop:~/Desktop/Acme-Frobnitz-Snapshot$ perl -d bin/3.driver.pl
Loading DB routines from perl5db.pl version 1.55
Editor support available.
Enter h or 'h h' for help, or 'man perldebug' for more help.
main::(bin/3.driver.pl:5): my $frobnitz = Acme::Frobnitz->new();
DB<1>
##
##
DB<1> R
Warning: some settings and command-line options may be lost!
Loading DB routines from perl5db.pl version 1.55
Editor support available.
Enter h or 'h h' for help, or 'man perldebug' for more help.
main::(bin/3.driver.pl:5): my $frobnitz = Acme::Frobnitz->new();
DB<0> b 16
DB<1>
##
##
2024-12-17 07:10:09,829 - downloader5 - INFO - Video download completed.
2024-12-17 07:10:09,832 - downloader5 - INFO - Download completed in 9.76 seconds
2024-12-17 07:10:09,832 - __main__ - INFO - Entering function: store_params_as_json
...
Verifying downloaded file...
main::(bin/3.driver.pl:16): if ($frobnitz->verify_file($downloaded_file)) {
DB<1> s
Acme::Frobnitz::verify_file(/usr/local/share/perl/5.30.0/Acme/Frobnitz.pm:65):
65: my ($class, $file_path) = @_;
DB<1> v
62 }
63
64 sub verify_file {
65==> my ($class, $file_path) = @_;
66: die "File path not provided.\n" unless $file_path;
67
68: my $abs_path = abs_path($file_path) // $file_path;
69
70: if (-e $abs_path) {
71: print "File exists: $abs_path\n";
DB<1> s
Acme::Frobnitz::verify_file(/usr/local/share/perl/5.30.0/Acme/Frobnitz.pm:66):
66: die "File path not provided.\n" unless $file_path;
DB<1> s
Acme::Frobnitz::verify_file(/usr/local/share/perl/5.30.0/Acme/Frobnitz.pm:68):
68: my $abs_path = abs_path($file_path) // $file_path;
DB<1> s
Acme::Frobnitz::verify_file(/usr/local/share/perl/5.30.0/Acme/Frobnitz.pm:70):
70: if (-e $abs_path) {
DB<1> s
Unsuccessful stat on filename containing newline at /usr/local/share/perl/5.30.0/Acme/Frobnitz.pm line 70.
at /usr/local/share/perl/5.30.0/Acme/Frobnitz.pm line 70.
Acme::Frobnitz::verify_file(Acme::Frobnitz=HASH(0x5653a1900ad8), "2024-12-17 00:09:54 - Detected OS: Linux\x{a}2024-12-17 00:09:54 "...) called at bin/3.driver.pl line 16
Acme::Frobnitz::verify_file(/usr/local/share/perl/5.30.0/Acme/Frobnitz.pm:92):
92: print "File does not exist: $abs_path\n";
DB<1> p $abs_path
2024-12-17 00:09:54 - Detected OS: Linux
2024-12-17 00:09:54 - Ensuring Docker is running...
2024-12-17 00:09:54 - Docker is already running.
2024-12-17 00:09:54 - Loading configuration from /home/fritz/Desktop/Acme-Frobnitz-Snapshot/bin/../conf/app_config.json...
2024-12-17 00:09:54 - Target USB mount name from config: E4B0-3FC2
2024-12-17 00:09:54 - Detected USB mount point: /media/fritz/E4B0-3FC2
2024-12-17 00:09:54 - Attempting to create directory: /media/fritz/E4B0-3FC2/2024-12-17/
2024-12-17 00:09:54 - Directory created or already exists: /media/fritz/E4B0-3FC2/2024-12-17/
2024-12-17 00:09:54 - Docker image 'my_dl:latest' found.
2024-12-17 00:09:54 - Running Docker with the specified volume and config path...
2024-12-17 00:10:13 - File validation successful: [Instagram] Extracting URL: https://www.instagram.com/p/DDa_FxsNtTe/
Adding lib_path to sys.path: /app/bin/../lib/python_utils
[Instagram] DDa_FxsNtTe: Setting up session
[Instagram] DDa_FxsNtTe: Downloading JSON metadata
[Instagram] Extracting URL: https://www.instagram.com/p/DDa_FxsNtTe/
[Instagram] DDa_FxsNtTe: Setting up session
[Instagram] DDa_FxsNtTe: Downloading JSON metadata
[info] DDa_FxsNtTe: Downloading 1 format(s): dash-560108753314303v+dash-1118756702933936ad
[download] Destination: E4B0-3FC2/2024-12-17/Tim_Ballard_20241211.fdash-560108753314303v.mp4
[download] 100% of 37.69MiB in 00:00:07 at 5.24MiB/s:00
[download] Destination: E4B0-3FC2/2024-12-17/Tim_Ballard_20241211.fdash-1118756702933936ad.m4a
[download] 100% of 1.14MiB in 00:00:00 at 2.32MiB/s:00
[Merger] Merging formats into "E4B0-3FC2/2024-12-17/Tim_Ballard_20241211.mp4"
Deleting original file E4B0-3FC2/2024-12-17/Tim_Ballard_20241211.fdash-1118756702933936ad.m4a (pass -k to keep)
Deleting original file E4B0-3FC2/2024-12-17/Tim_Ballard_20241211.fdash-560108753314303v.mp4 (pass -k to keep)
E4B0-3FC2/2024-12-17/Tim_Ballard_20241211.mp4
DB<2>
##
##
# Start with a base image
FROM python:3.10-slim
# Set PYTHONPATH to include the python_utils directory
ENV PYTHONPATH="/app/lib/python_utils:/app/lib"
# Update apt repository and install necessary dependencies, including ffmpeg
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ffmpeg \
python3 \
python3-pip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# Set the working directory
WORKDIR /app
# Copy all files into the Docker image
COPY bin /app/bin
COPY lib /app/lib
COPY conf /app/conf
COPY requirements.txt /app/requirements.txt
COPY Dockerfile /app/Dockerfile
# Install Python dependencies
RUN pip3 install --upgrade pip && pip3 install -r requirements.txt --root-user-action=ignore
# Debug: List all files in /app and verify the content of lib/python_utils
RUN ls -la /app && ls -la /app/lib && ls -la /app/lib/python_utils
# Debug: Verify requirements.txt is in the container
RUN cat /app/requirements.txt
# Debug: Verify Python environment and MoviePy installation
RUN python3 -c "import sys; print(sys.version)"
RUN python3 -c "import site; print(site.getsitepackages())"
RUN python3 -c "import moviepy; print('MoviePy is correctly installed')"
##
##
original_filename=$(docker run --rm \
-e PYTHONPATH="/app/lib/python_utils:/app/lib" \
-v "$Config_Path":/app/conf/app_config.json \
-v "$usb_mount_point":"$usb_mount_point" \
my_dl python3 /app/bin/call_download.py "$1")