Add base url config

This commit is contained in:
Max Nuding 2023-07-04 11:22:34 +02:00
parent 52bc3105fd
commit d53391ef5a
Signed by: phlaym
GPG Key ID: A06651BAB6777237
8 changed files with 148 additions and 100 deletions

View File

@ -1,4 +1,9 @@
{ {
"com.thorlaksson.phpcs.formatOnSave" : true,
"com.thorlaksson.phpcs.runOnChange" : "onSave",
"com.thorlaksson.phpcs.standard" : "PSR2",
"prettier.default-config.tabWidth" : 4,
"prettier.format-on-save" : "Disable",
"workspace.art_style" : 0, "workspace.art_style" : 0,
"workspace.name" : "PhotoPrismUpload", "workspace.name" : "PhotoPrismUpload",
"workspace.preview_type" : "custom", "workspace.preview_type" : "custom",

33
composer.lock generated
View File

@ -8,16 +8,16 @@
"packages": [ "packages": [
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "2.5.0", "version": "2.9.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Seldaek/monolog.git", "url": "https://github.com/Seldaek/monolog.git",
"reference": "4192345e260f1d51b365536199744b987e160edc" "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/4192345e260f1d51b365536199744b987e160edc", "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1",
"reference": "4192345e260f1d51b365536199744b987e160edc", "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -30,18 +30,22 @@
"require-dev": { "require-dev": {
"aws/aws-sdk-php": "^2.4.9 || ^3.0", "aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev", "doctrine/couchdb": "~1.0@dev",
"elasticsearch/elasticsearch": "^7", "elasticsearch/elasticsearch": "^7 || ^8",
"graylog2/gelf-php": "^1.4.2", "ext-json": "*",
"graylog2/gelf-php": "^1.4.2 || ^2@dev",
"guzzlehttp/guzzle": "^7.4",
"guzzlehttp/psr7": "^2.2",
"mongodb/mongodb": "^1.8", "mongodb/mongodb": "^1.8",
"php-amqplib/php-amqplib": "~2.4 || ^3", "php-amqplib/php-amqplib": "~2.4 || ^3",
"php-console/php-console": "^3.1.3", "phpspec/prophecy": "^1.15",
"phpspec/prophecy": "^1.6.1",
"phpstan/phpstan": "^0.12.91", "phpstan/phpstan": "^0.12.91",
"phpunit/phpunit": "^8.5", "phpunit/phpunit": "^8.5.14",
"predis/predis": "^1.1", "predis/predis": "^1.1 || ^2.0",
"rollbar/rollbar": "^1.3 || ^2 || ^3", "rollbar/rollbar": "^1.3 || ^2 || ^3",
"ruflin/elastica": ">=0.90@dev", "ruflin/elastica": "^7",
"swiftmailer/swiftmailer": "^5.3|^6.0" "swiftmailer/swiftmailer": "^5.3|^6.0",
"symfony/mailer": "^5.4 || ^6",
"symfony/mime": "^5.4 || ^6"
}, },
"suggest": { "suggest": {
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
@ -56,7 +60,6 @@
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
"mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
"php-console/php-console": "Allow sending log messages to Google Chrome",
"rollbar/rollbar": "Allow sending log messages to Rollbar", "rollbar/rollbar": "Allow sending log messages to Rollbar",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server" "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
}, },
@ -91,7 +94,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/Seldaek/monolog/issues", "issues": "https://github.com/Seldaek/monolog/issues",
"source": "https://github.com/Seldaek/monolog/tree/2.5.0" "source": "https://github.com/Seldaek/monolog/tree/2.9.1"
}, },
"funding": [ "funding": [
{ {
@ -103,7 +106,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-04-08T15:43:54+00:00" "time": "2023-02-06T13:44:46+00:00"
}, },
{ {
"name": "psr/log", "name": "psr/log",

View File

@ -2,8 +2,9 @@
return [ return [
'username' => '', 'username' => '',
'password' => '' 'password' => '',
'noAlbumToken' => '', 'noAlbumToken' => '',
'fileUploadLimitMb' => 1024, 'fileUploadLimitMb' => 1024,
'maximumNumberOfFilesPerUpload' => 200 'maximumNumberOfFilesPerUpload' => 200,
'baseUrl' => 'https://rabenberger.photos',
]; ];

View File

@ -8,8 +8,9 @@ use PhotoPrismUpload\API\PhotoPrism;
use PhotoPrismUpload\Entities\Album; use PhotoPrismUpload\Entities\Album;
/** @var string $footer Footer text which links to the Gitea repo */ /** @var string $footer Footer text which links to the Gitea repo */
$footer = '<footer style="position: fixed;bottom: 0;left: 0;">' $footer =
.'<a href="/git/phlaym/photoprismupload">Ich bin Open Source</a></footer>'; '<footer style="position: fixed;bottom: 0;left: 0;">' .
'<a href="https://phlaym.net/git/phlaym/photoprismupload">Ich bin Open Source</a></footer>';
?> ?>
<html> <html>
<head> <head>
@ -105,9 +106,8 @@ $footer = '<footer style="position: fixed;bottom: 0;left: 0;">'
</head> </head>
<body> <body>
<?php <?php
/** @var array $config configuration options */ /** @var array $config configuration options */
$config = require(__DIR__ . '/config.php'); $config = require __DIR__ . '/config.php';
/** @var PhotoPrism $api API object to interface with PhotoPrism */ /** @var PhotoPrism $api API object to interface with PhotoPrism */
$api = new PhotoPrism($config); $api = new PhotoPrism($config);
@ -138,7 +138,10 @@ if (!isset($_POST['submit'])) {
} catch (\Exception $e) { } catch (\Exception $e) {
die('Fehler: ' . $footer . $e->getMessage() . '</body></html>'); die('Fehler: ' . $footer . $e->getMessage() . '</body></html>');
} }
if (empty($albums) && (empty($config['noAlbumToken']) || !in_array($config['noAlbumToken'], $tokens))) { if (empty($albums) &&
(empty($config['noAlbumToken']) ||
!in_array($config['noAlbumToken'], $tokens))
) {
die('Falscher Token' . $footer . '</body></html>'); die('Falscher Token' . $footer . '</body></html>');
} }
?> ?>
@ -155,17 +158,17 @@ if (!isset($_POST['submit'])) {
if ($album->token === $token) { if ($album->token === $token) {
$album_url = $album->getUrlPath() ?? '/'; $album_url = $album->getUrlPath() ?? '/';
} }
echo '<option value="' echo '<option value="' .
. $album->uid $album->uid .
. '"' '"' .
. $selected $selected .
. 'data-url=' 'data-url=' .
. ($album->getUrlPath() ?? '/') ($album->getUrlPath() ?? '/') .
. '>' '>' .
. $album->title $album->title .
. '</option>\n'; '</option>\n';
} }
$album_url = "https://photos.phlaym.net{$album_url}"; $album_url = "{$api->base_url}{$album_url}";
?> ?>
</select> </select>
<input multiple type="file" name="files[]" id="input" required/> <input multiple type="file" name="files[]" id="input" required/>
@ -176,7 +179,7 @@ if (!isset($_POST['submit'])) {
<progress id="fileProgress"></progress> <progress id="fileProgress"></progress>
<label for="totalProgress">Gesamt:</label> <label for="totalProgress">Gesamt:</label>
<progress max="0" value="0" id="totalProgress"></progress> <progress max="0" value="0" id="totalProgress"></progress>
<a href="<?=$album_url;?>" target="_blank" id="viewAlbum">Album ansehen</a> <a href="<?= $album_url ?>" target="_blank" id="viewAlbum">Album ansehen</a>
</div> </div>
<script> <script>
window.tooLarge = false; window.tooLarge = false;
@ -215,14 +218,14 @@ if (!isset($_POST['submit'])) {
albumInput.addEventListener('change', (event) => { albumInput.addEventListener('change', (event) => {
console.log(event); console.log(event);
albumAnchor.href = `https://photos.phlaym.net${albumInput.selectedOptions[0].dataset.url}`; albumAnchor.href = `<?=$api->base_url?>${albumInput.selectedOptions[0].dataset.url}`;
}); });
form.addEventListener('submit', async function(event) { form.addEventListener('submit', async function(event) {
event.preventDefault(); event.preventDefault();
const isInvalid = window.tooLarge || window.tooManyFiles; const isInvalid = window.tooLarge || window.tooManyFiles;
if (isInvalid) { if (isInvalid) {
console.error('Aborting upload! Too many fiels or fiels too large'); console.error('Aborting upload! Too many files or files too large');
return; return;
} }
errorDiv.innerText = ''; errorDiv.innerText = '';
@ -261,8 +264,10 @@ if (!isset($_POST['submit'])) {
let fileList = []; let fileList = [];
input.addEventListener('change', (event) => { input.addEventListener('change', (event) => {
const maxFileSize = <?=$config['fileUploadLimitMb'];?>; const maxFileSize = <?= $config['fileUploadLimitMb'] ?>;
const maxAmountOfFiles = <?=$config['maximumNumberOfFilesPerUpload'];?>; const maxAmountOfFiles = <?= $config[
'maximumNumberOfFilesPerUpload'
] ?>;
const errorDiv = document.getElementById('error'); const errorDiv = document.getElementById('error');
const totalProgress = document.getElementById('totalProgress'); const totalProgress = document.getElementById('totalProgress');
@ -321,8 +326,7 @@ if (!isset($_POST['submit'])) {
} }
}); });
</script> </script>
<?php <?php die($footer . '</body></html>');
die($footer . '</body></html>');
} }
try { try {
$api->uploadPhotos($_POST['album']); $api->uploadPhotos($_POST['album']);

View File

@ -93,7 +93,7 @@ try {
foreach ($photos as $photo) { foreach ($photos as $photo) {
$thumb = $photo->getThumbnailUrl();?> $thumb = $photo->getThumbnailUrl();?>
<div class="photowrapper"> <div class="photowrapper">
<img src="<?= $api->api_url.$thumb?>" id="<?= $photo->uid?>"> <img src="<?= $api->api_url.$thumb?>" id="<?= $photo->uid?>" loading="lazy" data-votes="<?=$vote_counts[$photo->uid]?>">
</div> </div>
<?php <?php
} }

View File

@ -45,16 +45,19 @@ class PhotoPrism
* *
* @return void * @return void
*/ */
public function __construct( public function __construct(array $config, ?string $log_path = null)
array $config, {
?string $log_path = null
) {
$this->api_url = $this->base_url.'/api/v1';
$this->config = $config; $this->config = $config;
if (empty($log_path)) { if (empty($log_path)) {
$log_path = __DIR__ . '/logs/log.log'; $log_path = __DIR__ . '/logs/log.log';
} }
LoggerFactory::addHandler(new RotatingFileHandler($log_path, 5, Logger::DEBUG, true)); if (isset($config['baseUrl'])) {
$this->base_url = $config['baseUrl'];
}
$this->api_url = $this->base_url . '/api/v1';
LoggerFactory::addHandler(
new RotatingFileHandler($log_path, 5, Logger::DEBUG, true)
);
$this->logger = LoggerFactory::create('PhotoPrismUpload'); $this->logger = LoggerFactory::create('PhotoPrismUpload');
if (isset($_SESSION['pp_sessionid'])) { if (isset($_SESSION['pp_sessionid'])) {
$this->session_id = $_SESSION['pp_sessionid']; $this->session_id = $_SESSION['pp_sessionid'];
@ -173,13 +176,18 @@ class PhotoPrism
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($output === false) { if ($output === false) {
throw new NetworkException("Error sending request to " . $url, 0); throw new NetworkException(
'Error sending request to ' . $url,
0
);
} }
if (empty($output) || $output === false) { if (empty($output) || $output === false) {
$e = new NetworkException("No answer from" . $url, 0); $e = new NetworkException('No answer from' . $url, 0);
$this->logger->error( $this->logger->error(
"Error sending request. No answer from server", 'Error sending request. No answer from server',
['Exception' => print_r($e, true)] [
'Exception' => print_r($e, true),
]
); );
throw $e; throw $e;
} }
@ -187,12 +195,20 @@ class PhotoPrism
throw new NetworkException('Unable to connect to API ' . $url); throw new NetworkException('Unable to connect to API ' . $url);
} }
if ($http_status >= 400) { if ($http_status >= 400) {
throw new NetworkException('Invalid response ' . $url . ': ' . $http_status); throw new NetworkException(
'Invalid response ' . $url . ': ' . $http_status
);
} }
$result = $this->parseHeaders($output); $result = $this->parseHeaders($output);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->logger->error("Error sending request", ['Exception' => print_r($e, true)]); $this->logger->error('Error sending request', [
throw new NetworkException("Error sending request to " . $url, 0, $e); 'Exception' => print_r($e, true),
]);
throw new NetworkException(
'Error sending request to ' . $url,
0,
$e
);
} }
return $result['content']; return $result['content'];
} }
@ -228,7 +244,12 @@ class PhotoPrism
$_SESSION['pp_sessionid'] = $this->session_id; $_SESSION['pp_sessionid'] = $this->session_id;
$_SESSION['pp_preview_token'] = $this->preview_token; $_SESSION['pp_preview_token'] = $this->preview_token;
$_SESSION['pp_download_token'] = $this->download_token; $_SESSION['pp_download_token'] = $this->download_token;
$this->logger->debug('Session ID: ' . $this->session_id . ', preview token: ' . $this->preview_token); $this->logger->debug(
'Session ID: ' .
$this->session_id .
', preview token: ' .
$this->preview_token
);
} }
/** /**
@ -245,19 +266,16 @@ class PhotoPrism
$data = [ $data = [
'count' => $count, 'count' => $count,
'offset' => $offset, 'offset' => $offset,
'type' => 'album' 'type' => 'album',
]; ];
$res = $this->makeRequest('GET', '/albums', $data, 'text/plain'); $res = $this->makeRequest('GET', '/albums', $data, 'text/plain');
$response = json_decode($res, true); $response = json_decode($res, true);
if (!empty($response['error'])) { if (!empty($response['error'])) {
throw new NetworkException($response['error']); throw new NetworkException($response['error']);
} }
$albums = array_map( $albums = array_map(function ($entry) {
function ($entry) {
return new Album($entry); return new Album($entry);
}, }, $response);
$response
);
$this->logger->debug('Albums' . json_encode($albums)); $this->logger->debug('Albums' . json_encode($albums));
return $albums; return $albums;
} }
@ -271,8 +289,11 @@ class PhotoPrism
* @param int $offset -Number of albums to skip * @param int $offset -Number of albums to skip
* @return Album[] * @return Album[]
*/ */
public function getAlbumsByTokens(array $tokens, int $count = 1000, int $offset = 0): array public function getAlbumsByTokens(
{ array $tokens,
int $count = 1000,
int $offset = 0
): array {
$this->logger->debug('getAlbumsByToken'); $this->logger->debug('getAlbumsByToken');
$albums = $this->getAlbums($count, $offset); $albums = $this->getAlbums($count, $offset);
$visibleAlbums = []; $visibleAlbums = [];
@ -282,7 +303,9 @@ class PhotoPrism
if ($token != null && in_array($album->token, $tokens)) { if ($token != null && in_array($album->token, $tokens)) {
$visibleAlbums[] = $album; $visibleAlbums[] = $album;
} else { } else {
$this->logger->debug('Skipping album without access: ' . $album->title); $this->logger->debug(
'Skipping album without access: ' . $album->title
);
} }
} }
@ -321,13 +344,13 @@ class PhotoPrism
{ {
$uid = is_string($album) ? $album : $album->uid; $uid = is_string($album) ? $album : $album->uid;
$res = $this->makeRequest('GET', '/albums/' . $uid . '/links'); $res = $this->makeRequest('GET', '/albums/' . $uid . '/links');
$this->logger->debug('Token response: ' . $res);
/** @var array $response */ /** @var array $response */
$response = json_decode($res, true)[0]; $response = json_decode($res, true)[0];
if (!empty($response['error'])) { if (!empty($response['error'])) {
throw new NetworkException($response['error']); throw new NetworkException($response['error']);
} }
$this->logger->debug('Token response: ' . $res); if (!array_key_exists('Token', $response)) {
if (!in_array('Token', $response)) {
return null; return null;
} }
return $response['Token']; return $response['Token'];
@ -348,10 +371,19 @@ class PhotoPrism
$file_tmpname = $_FILES['files']['tmp_name'][$key]; $file_tmpname = $_FILES['files']['tmp_name'][$key];
$this->logger->info('Uploading ' . $file_tmpname . ' to ' . $url); $this->logger->info('Uploading ' . $file_tmpname . ' to ' . $url);
$filename = basename($_FILES['files']['name'][$key]); $filename = basename($_FILES['files']['name'][$key]);
$cFile = curl_file_create($file_tmpname, $_FILES['files']['type'][$key], $filename); $cFile = curl_file_create(
$file_tmpname,
$_FILES['files']['type'][$key],
$filename
);
$data = ['files' => $cFile]; $data = ['files' => $cFile];
$res = $this->makeRequest('POST', $url, $data, 'multipart/form-data'); $res = $this->makeRequest(
'POST',
$url,
$data,
'multipart/form-data'
);
$this->logger->info('Upload result: ' . $res); $this->logger->info('Upload result: ' . $res);
} }
@ -359,7 +391,7 @@ class PhotoPrism
/** @var string[] $albums */ /** @var string[] $albums */
$albums = empty($album) ? [] : [$album]; $albums = empty($album) ? [] : [$album];
$import_data = ["move" => true, "albums" => $albums]; $import_data = ['move' => true, 'albums' => $albums];
$res = $this->makeRequest('POST', $import_url, $import_data); $res = $this->makeRequest('POST', $import_url, $import_data);
$this->logger->info('Import result: ' . $res); $this->logger->info('Import result: ' . $res);
} }
@ -373,13 +405,16 @@ class PhotoPrism
* @param int $offset - Offset for paging * @param int $offset - Offset for paging
* @return Photo[] - Photos in the album * @return Photo[] - Photos in the album
*/ */
public function getAlbumPhotos(Album $album, int $count = 60, int $offset = 0): array public function getAlbumPhotos(
{ Album $album,
int $count = 60,
int $offset = 0
): array {
$this->logger->debug('getAlbumPhotos'); $this->logger->debug('getAlbumPhotos');
$data = [ $data = [
'album' => $album->uid, 'album' => $album->uid,
'count' => $count, 'count' => $count,
'offset' => $offset 'offset' => $offset,
]; ];
$res = $this->makeRequest('GET', '/photos', $data, 'text/plain'); $res = $this->makeRequest('GET', '/photos', $data, 'text/plain');
$response = json_decode($res, true); $response = json_decode($res, true);
@ -387,17 +422,14 @@ class PhotoPrism
throw new NetworkException($response['error']); throw new NetworkException($response['error']);
} }
$this->logger->debug('getAlbumPhotos response'); $this->logger->debug('getAlbumPhotos response');
$photos = array_map( $photos = array_map(function ($entry) {
function ($entry) {
$photo = new Photo($entry); $photo = new Photo($entry);
$photo->thumbnail_token = $this->preview_token; $photo->thumbnail_token = $this->preview_token;
return $photo; return $photo;
}, }, $response);
$response
);
$this->logger->info('Got photos:' . json_encode($photos)); $this->logger->info('Got photos:' . json_encode($photos));
$photos = array_filter($photos, function ($obj) { $photos = array_filter($photos, function ($obj) {
static $idList = array(); static $idList = [];
if (in_array($obj->uid, $idList)) { if (in_array($obj->uid, $idList)) {
return false; return false;
} }

View File

@ -2,6 +2,7 @@
namespace PhotoPrismUpload\Entities; namespace PhotoPrismUpload\Entities;
use PhotoPrismUpload\API\LoggerFactory; use PhotoPrismUpload\API\LoggerFactory;
use Psr\Log\LoggerInterface;
/** A PhotoPrism Album */ /** A PhotoPrism Album */
class Album class Album
@ -18,6 +19,9 @@ class Album
/** @var string|null $token Secret token of the album. Needs to be set by the API */ /** @var string|null $token Secret token of the album. Needs to be set by the API */
public ?string $token = null; public ?string $token = null;
/** @var LoggerInterface $logger Logger object */
protected LoggerInterface $logger;
/** /**
* Creates a new album from the api response * Creates a new album from the api response
* *
@ -25,9 +29,8 @@ class Album
* *
* @return void * @return void
*/ */
public function __construct( public function __construct(array $response)
array $response {
) {
$this->uid = $response['UID']; $this->uid = $response['UID'];
$this->slug = $response['Slug']; $this->slug = $response['Slug'];
$this->title = $response['Title']; $this->title = $response['Title'];

View File

@ -83,7 +83,7 @@ try {
foreach ($photos as $photo) { foreach ($photos as $photo) {
$thumb = $photo->getThumbnailUrl();?> $thumb = $photo->getThumbnailUrl();?>
<div class="photowrapper"> <div class="photowrapper">
<img src="<?= $api->api_url.$thumb?>" id="<?= $photo->uid?>"> <img src="<?= $api->api_url.$thumb?>" id="<?= $photo->uid?>" loading="lazy">
<div class="votewrapper"> <div class="votewrapper">
<button value="1" onclick="vote(this)" class="voteButton" data-uid="<?= $photo->uid?>" disabled> <button value="1" onclick="vote(this)" class="voteButton" data-uid="<?= $photo->uid?>" disabled>
👍 Dafür 👍 Dafür