Initial fresh commit
This commit is contained in:
43
Dockerfile
Normal file
43
Dockerfile
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Use a minimal base image with Perl
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# Set a working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install system dependencies and Perl
|
||||||
|
RUN apk update && \
|
||||||
|
apk add --no-cache \
|
||||||
|
perl \
|
||||||
|
perl-app-cpanminus \
|
||||||
|
perl-lwp-useragent-determined \
|
||||||
|
perl-io-socket-ssl \
|
||||||
|
perl-net-ssleay \
|
||||||
|
perl-lwp-protocol-https \
|
||||||
|
make \
|
||||||
|
gcc \
|
||||||
|
musl-dev \
|
||||||
|
curl && \
|
||||||
|
\
|
||||||
|
# Install required Perl modules via CPAN
|
||||||
|
cpanm --notest \
|
||||||
|
JSON::Tiny \
|
||||||
|
LWP::UserAgent \
|
||||||
|
LWP::Protocol::https \
|
||||||
|
Time::Duration \
|
||||||
|
URI::Escape \
|
||||||
|
Getopt::Std && \
|
||||||
|
\
|
||||||
|
# Clean up build dependencies and cache
|
||||||
|
apk del make gcc musl-dev && \
|
||||||
|
rm -rf /var/cache/apk/* /root/.cpanm
|
||||||
|
|
||||||
|
# Copy the Perl script into the container
|
||||||
|
COPY poller.pl /app/poller.pl
|
||||||
|
|
||||||
|
# Fix line endings and make the script executable
|
||||||
|
RUN sed -i 's/\r$//' /app/poller.pl && \
|
||||||
|
chmod +x /app/poller.pl
|
||||||
|
|
||||||
|
# Define the default command
|
||||||
|
# Using perl explicitly and forcing unbuffered output
|
||||||
|
CMD ["perl", "-u", "/app/poller.pl"]
|
39
docker-compose.yaml.example
Normal file
39
docker-compose.yaml.example
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
services:
|
||||||
|
lidarr:
|
||||||
|
image: lscr.io/linuxserver/lidarr:latest
|
||||||
|
container_name: lidarr
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=${TZ}
|
||||||
|
volumes:
|
||||||
|
- /path/to/lidarr/config:/config
|
||||||
|
- /path/to/data/:/data/
|
||||||
|
- path/to/downloads/:/downloads
|
||||||
|
ports:
|
||||||
|
- 8686:8686
|
||||||
|
networks:
|
||||||
|
example_network:
|
||||||
|
ipv4_address: 172.18.0.1
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
mbid-poller:
|
||||||
|
image: gitea.kansaigaijin.com/KansaiGaijin
|
||||||
|
container_name: mbid-poller
|
||||||
|
environment:
|
||||||
|
# Common: The URL for your Lidarr instance
|
||||||
|
- LIDARR_BASE=http://lidarr:8686
|
||||||
|
- MBID_API_URL= # OPTION 1: API URL (Current default, highest priority)
|
||||||
|
- MBID_JSON_FILE=/config/ids.json # OPTION 2: JSON File (To use, comment out MBID_API_URL and uncomment this lines)
|
||||||
|
- MBID_URL=https://musicbrainz.org/work/69755ab1-409e-3ad7-902f-3a839042799c # OPTION 3: Single ID/URL (To use, comment out the API URL and the JSON File lines)
|
||||||
|
volumes:
|
||||||
|
- ./ids.json:/config/ids.json:ro
|
||||||
|
networks:
|
||||||
|
example_network: # Same network as Lidarr
|
||||||
|
ipv4_address: 172.18.0.2
|
||||||
|
restart: "no" # Run once
|
||||||
|
command: ["/app/poller.pl"]
|
||||||
|
|
||||||
|
networks:
|
||||||
|
example_network:
|
||||||
|
external: true
|
4
ids.json
Normal file
4
ids.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
{"foreignId":"db92a151-1ac2-438b-bc43-b82e149ddd50"},
|
||||||
|
{"foreignId":"a6c6897a-7415-4f8d-b5a5-3a5e05f3be67"}
|
||||||
|
]
|
153
poller.pl
Normal file
153
poller.pl
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
# -*- Perl -*-
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use open qw(:std :encoding(UTF-8));
|
||||||
|
|
||||||
|
use Data::Dumper qw(Dumper);
|
||||||
|
use Getopt::Std;
|
||||||
|
use IO::Handle;
|
||||||
|
use JSON::Tiny qw(decode_json);
|
||||||
|
use LWP::UserAgent;
|
||||||
|
use Time::Duration;
|
||||||
|
use URI::Escape;
|
||||||
|
|
||||||
|
# --- Environment Variables ---
|
||||||
|
use constant LIDARR_BASE => $ENV{LIDARR_BASE} || 'http://localhost:8686';
|
||||||
|
|
||||||
|
# ANSI escape sequences
|
||||||
|
sub ERASE_EOL { return "\033[K"; }
|
||||||
|
sub CURSOR_BACK { return "\033[${_[0]}D"; }
|
||||||
|
sub STATUS { return $_[0] . ERASE_EOL . CURSOR_BACK(length($_[0])) }
|
||||||
|
|
||||||
|
getopts('bfhv');
|
||||||
|
|
||||||
|
my $fresh_result = defined $::opt_f ? $::opt_f : 0; # vs STALE
|
||||||
|
|
||||||
|
# Define the list of IDs to process
|
||||||
|
my @ids_to_process;
|
||||||
|
my $ua = new LWP::UserAgent; # Initialize LWP::UserAgent
|
||||||
|
my $json_content;
|
||||||
|
|
||||||
|
# --- Input Logic: Prioritized Checks ---
|
||||||
|
|
||||||
|
# 1. Check for API URL (Highest Priority)
|
||||||
|
if (my $api_url = $ENV{MBID_API_URL}) {
|
||||||
|
print STDERR "Fetching IDs from API URL: $api_url\n";
|
||||||
|
my $res = $ua->get($api_url);
|
||||||
|
unless ($res->is_success) {
|
||||||
|
die "FATAL: Failed to fetch data from API: " . $res->status_line . "\n";
|
||||||
|
}
|
||||||
|
$json_content = $res->content;
|
||||||
|
}
|
||||||
|
# 2. Check for JSON File (Second Priority)
|
||||||
|
elsif (my $json_file = $ENV{MBID_JSON_FILE}) {
|
||||||
|
print STDERR "Loading IDs from JSON file: $json_file\n";
|
||||||
|
open my $fh, '<:encoding(UTF-8)', $json_file or die "Could not open $json_file: $!";
|
||||||
|
$json_content = do { local $/; <$fh> };
|
||||||
|
close $fh;
|
||||||
|
}
|
||||||
|
# 3. Check for a single URL/ID (Lowest Priority)
|
||||||
|
elsif (my $single_url = $ENV{MBID_URL}) {
|
||||||
|
push @ids_to_process, $single_url;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
die "FATAL: Must set MBID_API_URL, MBID_JSON_FILE, OR MBID_URL.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# --- JSON Parsing Logic (Applies to API URL and JSON File) ---
|
||||||
|
if ($json_content) {
|
||||||
|
my $data;
|
||||||
|
eval {
|
||||||
|
$data = decode_json($json_content);
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
die "Error decoding JSON from source: $@\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extract the 'foreignId' from each object in the array
|
||||||
|
if (ref $data eq 'ARRAY') {
|
||||||
|
foreach my $item (@$data) {
|
||||||
|
if (ref $item eq 'HASH' && exists $item->{foreignId}) {
|
||||||
|
push @ids_to_process, $item->{foreignId};
|
||||||
|
} else {
|
||||||
|
warn "Skipping malformed item in input (missing 'foreignId').\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die "Input content was not a JSON array.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# --- Main Processing Loop ---
|
||||||
|
foreach my $id (@ids_to_process) {
|
||||||
|
chomp $id;
|
||||||
|
print "\n--- Processing: $id ---\n";
|
||||||
|
|
||||||
|
my $type = 'artist'; # Assuming 'foreignId' provides an artist MBID
|
||||||
|
|
||||||
|
my $json = ping_api($type, $id);
|
||||||
|
|
||||||
|
print "- add-to-lidarr: " .
|
||||||
|
LIDARR_BASE . "/add/search?term=" . uri_escape("lidarr:$id") . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
## subroutines (ping_api and validate remain the same as your original script)
|
||||||
|
|
||||||
|
sub ping_api {
|
||||||
|
my ($type, $id) = @_;
|
||||||
|
my $ua = new LWP::UserAgent;
|
||||||
|
my $start = time();
|
||||||
|
my $loops = 0;
|
||||||
|
my $api = "https://api.lidarr.audio/api/v0.4/$type/$id";
|
||||||
|
my $json;
|
||||||
|
|
||||||
|
print STDERR "Pinging $api\n";
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
$loops++;
|
||||||
|
print STDERR STATUS("- attempt $loops");
|
||||||
|
my $res = $ua->get($api);
|
||||||
|
my $status = $res->code;
|
||||||
|
if ($res->is_success) {
|
||||||
|
eval {
|
||||||
|
$json = decode_json($res->content);
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
chomp $@;
|
||||||
|
warn "Retrying: $@\n";
|
||||||
|
} elsif ($fresh_result and $res->header('cf-cache-status') eq 'STALE') {
|
||||||
|
$status .= ' STALE';
|
||||||
|
} else {
|
||||||
|
print STDERR ERASE_EOL;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print STDERR STATUS("- attempt $loops: $status");
|
||||||
|
sleep 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $elapsed = time() - $start;
|
||||||
|
print "- ready ($loops attempts, " . duration($elapsed) . ")\n"
|
||||||
|
if $loops > 1;
|
||||||
|
if ($type eq 'artist') {
|
||||||
|
print "- artist: " . $json->{artistname} . "\n";
|
||||||
|
} else {
|
||||||
|
print "- album: " . $json->{title} . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $json;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub validate {
|
||||||
|
my ($type, $json) = @_;
|
||||||
|
my @warnings;
|
||||||
|
if ($type eq 'artist') {
|
||||||
|
# make sure there are albums
|
||||||
|
unless (exists $json->{Albums} and scalar @{$json->{Albums}}) {
|
||||||
|
push(@warnings, 'no albums');
|
||||||
|
}
|
Reference in New Issue
Block a user