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.name" : "PhotoPrismUpload",
"workspace.preview_type" : "custom",

33
composer.lock generated
View File

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

View File

@ -1,9 +1,10 @@
<?php
return [
'username' => '',
'password' => ''
'noAlbumToken' => '',
'fileUploadLimitMb' => 1024,
'maximumNumberOfFilesPerUpload' => 200
'username' => '',
'password' => '',
'noAlbumToken' => '',
'fileUploadLimitMb' => 1024,
'maximumNumberOfFilesPerUpload' => 200,
'baseUrl' => 'https://rabenberger.photos',
];

View File

@ -8,8 +8,9 @@ use PhotoPrismUpload\API\PhotoPrism;
use PhotoPrismUpload\Entities\Album;
/** @var string $footer Footer text which links to the Gitea repo */
$footer = '<footer style="position: fixed;bottom: 0;left: 0;">'
.'<a href="/git/phlaym/photoprismupload">Ich bin Open Source</a></footer>';
$footer =
'<footer style="position: fixed;bottom: 0;left: 0;">' .
'<a href="https://phlaym.net/git/phlaym/photoprismupload">Ich bin Open Source</a></footer>';
?>
<html>
<head>
@ -105,9 +106,8 @@ $footer = '<footer style="position: fixed;bottom: 0;left: 0;">'
</head>
<body>
<?php
/** @var array $config configuration options */
$config = require(__DIR__ . '/config.php');
$config = require __DIR__ . '/config.php';
/** @var PhotoPrism $api API object to interface with PhotoPrism */
$api = new PhotoPrism($config);
@ -117,7 +117,7 @@ $albums = [];
try {
$api->login();
} catch (\Exception $e) {
die('Fehler: ' . $e->getMessage().$footer.'</body></html>');
die('Fehler: ' . $e->getMessage() . $footer . '</body></html>');
}
if (!isset($_POST['submit'])) {
@ -138,7 +138,10 @@ if (!isset($_POST['submit'])) {
} catch (\Exception $e) {
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>');
}
?>
@ -155,17 +158,17 @@ if (!isset($_POST['submit'])) {
if ($album->token === $token) {
$album_url = $album->getUrlPath() ?? '/';
}
echo '<option value="'
. $album->uid
. '"'
. $selected
. 'data-url='
. ($album->getUrlPath() ?? '/')
. '>'
. $album->title
. '</option>\n';
echo '<option value="' .
$album->uid .
'"' .
$selected .
'data-url=' .
($album->getUrlPath() ?? '/') .
'>' .
$album->title .
'</option>\n';
}
$album_url = "https://photos.phlaym.net{$album_url}";
$album_url = "{$api->base_url}{$album_url}";
?>
</select>
<input multiple type="file" name="files[]" id="input" required/>
@ -176,7 +179,7 @@ if (!isset($_POST['submit'])) {
<progress id="fileProgress"></progress>
<label for="totalProgress">Gesamt:</label>
<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>
<script>
window.tooLarge = false;
@ -215,14 +218,14 @@ if (!isset($_POST['submit'])) {
albumInput.addEventListener('change', (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) {
event.preventDefault();
const isInvalid = window.tooLarge || window.tooManyFiles;
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;
}
errorDiv.innerText = '';
@ -261,8 +264,10 @@ if (!isset($_POST['submit'])) {
let fileList = [];
input.addEventListener('change', (event) => {
const maxFileSize = <?=$config['fileUploadLimitMb'];?>;
const maxAmountOfFiles = <?=$config['maximumNumberOfFilesPerUpload'];?>;
const maxFileSize = <?= $config['fileUploadLimitMb'] ?>;
const maxAmountOfFiles = <?= $config[
'maximumNumberOfFilesPerUpload'
] ?>;
const errorDiv = document.getElementById('error');
const totalProgress = document.getElementById('totalProgress');
@ -321,13 +326,12 @@ if (!isset($_POST['submit'])) {
}
});
</script>
<?php
die($footer . '</body></html>');
<?php die($footer . '</body></html>');
}
try {
$api->uploadPhotos($_POST['album']);
} catch (\Exception $e) {
die('Fehler: ' . $footer . $e->getMessage() .'</body></html>');
die('Fehler: ' . $footer . $e->getMessage() . '</body></html>');
}
?>
Erfolg! <a href=".">Zurück</a>

View File

@ -93,7 +93,7 @@ try {
foreach ($photos as $photo) {
$thumb = $photo->getThumbnailUrl();?>
<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>
<?php
}

View File

@ -45,16 +45,19 @@ class PhotoPrism
*
* @return void
*/
public function __construct(
array $config,
?string $log_path = null
) {
$this->api_url = $this->base_url.'/api/v1';
public function __construct(array $config, ?string $log_path = null)
{
$this->config = $config;
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');
if (isset($_SESSION['pp_sessionid'])) {
$this->session_id = $_SESSION['pp_sessionid'];
@ -100,7 +103,7 @@ class PhotoPrism
if (count($header) < 2) {
continue;
}
list($k,$v) = $header;
list($k, $v) = $header;
$header_arr[$k] = $v;
}
return ['headers' => $header_arr, 'content' => $content];
@ -125,7 +128,7 @@ class PhotoPrism
array $data = [],
string $content_type = 'application/json'
): string {
$url = $this->api_url.$path;
$url = $this->api_url . $path;
$method = strtolower($method);
$query_data = [];
$headers = [];
@ -143,16 +146,16 @@ class PhotoPrism
$ch = curl_init();
if ($method === 'get' && !empty($query_data)) {
$url .= '?'.$query_data;
$url .= '?' . $query_data;
}
if ($method !== 'get') {
$headers[] = 'Content-Type: '.$content_type;
$headers[] = 'Content-Type: ' . $content_type;
}
if (!empty($this->session_id)) {
$headers[] = 'X-Session-Id: ' . $this->session_id;
}
$this->logger->info($method .' request to ' . $url);
$this->logger->info($method . ' request to ' . $url);
$this->logger->debug('Headers ' . json_encode($headers));
$this->logger->debug('postfields data ' . json_encode($data));
$this->logger->debug('postfields ' . json_encode($query_data));
@ -169,17 +172,22 @@ class PhotoPrism
}
$output = curl_exec($ch);
// $request = curl_getinfo($ch, CURLINFO_HEADER_OUT);
// $request = curl_getinfo($ch, CURLINFO_HEADER_OUT);
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
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) {
$e = new NetworkException("No answer from" . $url, 0);
$e = new NetworkException('No answer from' . $url, 0);
$this->logger->error(
"Error sending request. No answer from server",
['Exception' => print_r($e, true)]
'Error sending request. No answer from server',
[
'Exception' => print_r($e, true),
]
);
throw $e;
}
@ -187,12 +195,20 @@ class PhotoPrism
throw new NetworkException('Unable to connect to API ' . $url);
}
if ($http_status >= 400) {
throw new NetworkException('Invalid response ' . $url . ': ' . $http_status);
throw new NetworkException(
'Invalid response ' . $url . ': ' . $http_status
);
}
$result = $this->parseHeaders($output);
} catch (\Exception $e) {
$this->logger->error("Error sending request", ['Exception' => print_r($e, true)]);
throw new NetworkException("Error sending request to " . $url, 0, $e);
$this->logger->error('Error sending request', [
'Exception' => print_r($e, true),
]);
throw new NetworkException(
'Error sending request to ' . $url,
0,
$e
);
}
return $result['content'];
}
@ -228,7 +244,12 @@ class PhotoPrism
$_SESSION['pp_sessionid'] = $this->session_id;
$_SESSION['pp_preview_token'] = $this->preview_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 = [
'count' => $count,
'offset' => $offset,
'type' => 'album'
'type' => 'album',
];
$res = $this->makeRequest('GET', '/albums', $data, 'text/plain');
$response = json_decode($res, true);
if (!empty($response['error'])) {
throw new NetworkException($response['error']);
}
$albums = array_map(
function ($entry) {
return new Album($entry);
},
$response
);
$albums = array_map(function ($entry) {
return new Album($entry);
}, $response);
$this->logger->debug('Albums' . json_encode($albums));
return $albums;
}
@ -271,8 +289,11 @@ class PhotoPrism
* @param int $offset -Number of albums to skip
* @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');
$albums = $this->getAlbums($count, $offset);
$visibleAlbums = [];
@ -282,7 +303,9 @@ class PhotoPrism
if ($token != null && in_array($album->token, $tokens)) {
$visibleAlbums[] = $album;
} 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;
$res = $this->makeRequest('GET', '/albums/' . $uid . '/links');
$this->logger->debug('Token response: ' . $res);
/** @var array $response */
$response = json_decode($res, true)[0];
if (!empty($response['error'])) {
throw new NetworkException($response['error']);
}
$this->logger->debug('Token response: ' . $res);
if (!in_array('Token', $response)) {
if (!array_key_exists('Token', $response)) {
return null;
}
return $response['Token'];
@ -342,16 +365,25 @@ class PhotoPrism
public function uploadPhotos(?string $album = null): void
{
$path = time();
$url = '/upload/'.$path;
$import_url = '/import'.$url;
$url = '/upload/' . $path;
$import_url = '/import' . $url;
foreach (array_keys($_FILES['files']['tmp_name']) as $key) {
$file_tmpname = $_FILES['files']['tmp_name'][$key];
$this->logger->info('Uploading ' . $file_tmpname . ' to ' . $url);
$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];
$res = $this->makeRequest('POST', $url, $data, 'multipart/form-data');
$res = $this->makeRequest(
'POST',
$url,
$data,
'multipart/form-data'
);
$this->logger->info('Upload result: ' . $res);
}
@ -359,7 +391,7 @@ class PhotoPrism
/** @var string[] $albums */
$albums = empty($album) ? [] : [$album];
$import_data = ["move" => true, "albums" => $albums];
$import_data = ['move' => true, 'albums' => $albums];
$res = $this->makeRequest('POST', $import_url, $import_data);
$this->logger->info('Import result: ' . $res);
}
@ -373,13 +405,16 @@ class PhotoPrism
* @param int $offset - Offset for paging
* @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');
$data = [
'album' => $album->uid,
'count' => $count,
'offset' => $offset
'offset' => $offset,
];
$res = $this->makeRequest('GET', '/photos', $data, 'text/plain');
$response = json_decode($res, true);
@ -387,21 +422,18 @@ class PhotoPrism
throw new NetworkException($response['error']);
}
$this->logger->debug('getAlbumPhotos response');
$photos = array_map(
function ($entry) {
$photo = new Photo($entry);
$photo->thumbnail_token = $this->preview_token;
return $photo;
},
$response
);
$photos = array_map(function ($entry) {
$photo = new Photo($entry);
$photo->thumbnail_token = $this->preview_token;
return $photo;
}, $response);
$this->logger->info('Got photos:' . json_encode($photos));
$photos = array_filter($photos, function ($obj) {
static $idList = array();
static $idList = [];
if (in_array($obj->uid, $idList)) {
return false;
}
$idList []= $obj->uid;
$idList[] = $obj->uid;
return true;
});
$this->logger->info('unique photos:' . json_encode($photos));

View File

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

View File

@ -83,7 +83,7 @@ try {
foreach ($photos as $photo) {
$thumb = $photo->getThumbnailUrl();?>
<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">
<button value="1" onclick="vote(this)" class="voteButton" data-uid="<?= $photo->uid?>" disabled>
👍 Dafür