Add ImportReleasesCommand and a generation script

To import your local albums!
This commit is contained in:
dece 2023-10-01 15:17:46 +02:00
parent 0c17bbbc4c
commit 2b1da5098b
2 changed files with 143 additions and 0 deletions

39
scripts/gen-releases-csv.py Executable file
View file

@ -0,0 +1,39 @@
#!/usr/bin/env python3
"""Generate a CSV usable with the import:releases command from a directory.
This script assumes your have the same format for your release directories as
me, which is "Artist/Year - Release".
"""
import argparse
import csv
import os
import re
release_re = re.compile(r"(?P<year>\d{4})[\d\.]*(?: -)? (?P<title>.+)")
argparser = argparse.ArgumentParser()
argparser.add_argument('directory', help='directory to explore')
args = argparser.parse_args()
root = args.directory
with open('releases.csv', 'w', newline='') as output_file:
csv_writer = csv.writer(output_file)
for artist in os.listdir(root):
artist_dir = os.path.join(root, artist)
if not os.path.isdir(artist_dir):
continue
for release in os.listdir(os.path.join(root, artist)):
release_dir = os.path.join(artist_dir, release)
if not os.path.isdir(release_dir):
continue
match = release_re.match(release)
if not match:
continue
match_dict = match.groupdict()
csv_writer.writerow([
artist,
match_dict["title"],
match_dict["year"],
])

View file

@ -0,0 +1,104 @@
<?php
namespace App\Command;
use App\Entity\Artist;
use App\Entity\Release;
use App\Repository\ArtistRepository;
use App\Repository\ReleaseRepository;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(
name: 'import:releases',
description: 'Import releases from a CSV file.',
)]
class ImportReleasesCommand extends Command
{
public function __construct(
protected EntityManagerInterface $entityManager,
protected ArtistRepository $artistRepository,
protected ReleaseRepository $releaseRepository,
protected UserRepository $userRepository,
)
{
parent::__construct();
}
protected function configure(): void
{
$this
->addArgument('username', InputArgument::REQUIRED, 'Owner username')
->addArgument('csv', InputArgument::REQUIRED, 'CSV file')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$csvFilename = $input->getArgument('csv');
$ownerName = $input->getArgument('username');
$owner = $this->userRepository->findOneBy(['username' => $ownerName]);
if (!$owner) {
$io->error("No user with the username $ownerName.");
return Command::FAILURE;
}
$numNewArtists = 0;
$numNewReleases = 0;
$numSkippedReleases = 0;
$csvFile = fopen($csvFilename, 'r');
while (($row = fgetcsv($csvFile)) !== false) {
$numCols = count($row);
if ($numCols < 2) {
$io->error('Skipping row with less than two columns: ' . json_encode($row));
continue;
}
$artistName = $row[0];
$title = $row[1];
$artist = $this->artistRepository->findOneBy(['name' => $artistName]);
if (!$artist) {
$artist = new Artist();
$artist->setName($artistName);
$this->entityManager->persist($artist);
$this->entityManager->flush();
$numNewArtists++;
}
$releaseExists = false;
foreach ($artist->getReleases() as $artistRelease) {
if ($artistRelease->getTitle() === $title) {
$releaseExists = true;
break;
}
}
if (!$releaseExists) {
$release = new Release();
$release->setTitle($title);
$release->setOwner($owner);
$release->addArtist($artist);
$this->entityManager->persist($release);
$this->entityManager->flush();
$numNewReleases++;
} else {
$numSkippedReleases++;
}
}
fclose($csvFile);
$io->success(
'Import successful:'
. " $numNewArtists new artists,"
. " $numNewReleases new releases ($numSkippedReleases skipped)."
);
return Command::SUCCESS;
}
}