mirror of
https://github.com/OPSnet/Gazelle.git
synced 2026-01-16 18:04:34 -05:00
revamp torrent log uploading
This commit is contained in:
@@ -2,94 +2,44 @@
|
||||
|
||||
namespace Gazelle\Json;
|
||||
|
||||
use Gazelle\File\RipLog;
|
||||
use Gazelle\File\RipLogHTML;
|
||||
use Gazelle\Logfile;
|
||||
use Gazelle\LogfileSummary;
|
||||
use OrpheusNET\Logchecker\Logchecker;
|
||||
|
||||
class AddLog extends \Gazelle\Json {
|
||||
public function __construct(
|
||||
protected \Gazelle\Torrent $torrent,
|
||||
protected \Gazelle\User $user,
|
||||
protected array $files,
|
||||
protected \Gazelle\Torrent $torrent,
|
||||
protected \Gazelle\User $user,
|
||||
protected \Gazelle\Manager\TorrentLog $torrentLogManager,
|
||||
protected \Gazelle\LogfileSummary $logfileSummary,
|
||||
) {}
|
||||
|
||||
public function payload(): ?array {
|
||||
$logfiles = [];
|
||||
if ($this->user->id() !== $this->torrent->uploaderId() && !$this->user->permitted('admin_add_log')) {
|
||||
$this->failure('Not the torrent owner or moderator');
|
||||
return null;
|
||||
}
|
||||
|
||||
$logfileSummary = new LogfileSummary;
|
||||
$ripFiler = new RipLog;
|
||||
$htmlFiler = new RipLogHTML;
|
||||
|
||||
$torrentId = $this->torrent->id();
|
||||
$logSummaries = [];
|
||||
for ($i = 0, $total = count($this->files['name']); $i < $total; $i++) {
|
||||
if (!$this->files['size'][$i]) {
|
||||
continue;
|
||||
}
|
||||
$logfile = new Logfile(
|
||||
$this->files['tmp_name'][$i],
|
||||
$this->files['name'][$i]
|
||||
);
|
||||
$logfiles[] = $logfile;
|
||||
$logfileSummary->add($logfile);
|
||||
|
||||
self::$db->prepared_query('
|
||||
INSERT INTO torrents_logs
|
||||
(TorrentID, Score, `Checksum`, FileName, Ripper, RipperVersion, `Language`, ChecksumState, LogcheckerVersion, Details)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
', $torrentId, $logfile->score(), $logfile->checksumStatus(), $logfile->filename(), $logfile->ripper(),
|
||||
$logfile->ripperVersion(), $logfile->language(), $logfile->checksumState(),
|
||||
Logchecker::getLogcheckerVersion(), $logfile->detailsAsString()
|
||||
);
|
||||
$logId = self::$db->inserted_id();
|
||||
$ripFiler->put($logfile->filepath(), [$torrentId, $logId]);
|
||||
$htmlFiler->put($logfile->text(), [$torrentId, $logId]);
|
||||
|
||||
$checkerVersion = Logchecker::getLogcheckerVersion();
|
||||
foreach($this->logfileSummary->all() as $logfile) {
|
||||
$this->torrentLogManager->create($this->torrent, $logfile, $checkerVersion);
|
||||
$logSummaries[] = [
|
||||
'score' => $logfile->score(),
|
||||
'checksum' => $logfile->checksumState(),
|
||||
'ripper' => $logfile->ripper(),
|
||||
'ripperVersion' => $logfile->ripperVersion(),
|
||||
'language' => $logfile->language(),
|
||||
'details' => $logfile->detailsAsString()
|
||||
'details' => $logfile->detailsAsString(),
|
||||
];
|
||||
}
|
||||
$this->torrent->updateLogScore($logfileSummary);
|
||||
|
||||
[$score, $checksum] = self::$db->row("
|
||||
SELECT min(CASE WHEN Adjusted = '1' THEN AdjustedScore ELSE Score END) AS Score,
|
||||
min(CASE WHEN Adjusted = '1' THEN AdjustedChecksum ELSE Checksum END) AS Checksum
|
||||
FROM torrents_logs
|
||||
WHERE TorrentID = ?
|
||||
GROUP BY TorrentID
|
||||
", $torrentId
|
||||
);
|
||||
|
||||
self::$db->prepared_query(
|
||||
'UPDATE torrents SET LogScore = ?, LogChecksum = ?, HasLogDB = ? WHERE ID = ?',
|
||||
$score, $checksum, '1', $torrentId
|
||||
);
|
||||
|
||||
$groupId = $this->torrent->groupId();
|
||||
self::$cache->delete_multi([
|
||||
"torrent_group_{$groupId}",
|
||||
"torrents_details_{$groupId}",
|
||||
sprintf(\Gazelle\TGroup::CACHE_KEY, $groupId),
|
||||
sprintf(\Gazelle\TGroup::CACHE_TLIST_KEY, $groupId),
|
||||
]);
|
||||
$this->torrent->modifyLogscore();
|
||||
$this->torrent->flush();
|
||||
|
||||
return [
|
||||
'torrentId' => $torrentId,
|
||||
'score' => $score,
|
||||
'checksum' => $checksum,
|
||||
'logcheckerVersion' => Logchecker::getLogcheckerVersion(),
|
||||
'logSummaries' => $logSummaries
|
||||
'torrentId' => $this->torrent->id(),
|
||||
'score' => $this->torrent->logScore(),
|
||||
'checksum' => $this->torrent->logChecksum(),
|
||||
'logcheckerVersion' => $checkerVersion,
|
||||
'logSummaries' => $logSummaries,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@ class Logfile {
|
||||
$checker = new Logchecker();
|
||||
$checker->newFile($this->filepath);
|
||||
$checker->parse();
|
||||
$this->score = max(0, $checker->getScore());
|
||||
$this->details = $checker->getDetails();
|
||||
$this->score = max(0, $checker->getScore());
|
||||
$this->details = $checker->getDetails();
|
||||
$this->checksumState = $checker->getChecksumState();
|
||||
$this->text = $checker->getLog();
|
||||
$this->ripper = $checker->getRipper() ?? '';
|
||||
$this->text = $checker->getLog();
|
||||
$this->ripper = $checker->getRipper() ?? '';
|
||||
$this->ripperVersion = $checker->getRipperVersion() ?? '';
|
||||
$this->language = $checker->getLanguage();
|
||||
$this->language = $checker->getLanguage();
|
||||
}
|
||||
|
||||
public function checksum() { return $this->checksumState === Checksum::CHECKSUM_OK; }
|
||||
|
||||
@@ -3,42 +3,39 @@
|
||||
namespace Gazelle;
|
||||
|
||||
class LogfileSummary {
|
||||
/** @var Logfile[] */
|
||||
protected $list;
|
||||
protected $allChecksum;
|
||||
protected $lowestScore;
|
||||
protected array $list;
|
||||
protected bool $allChecksum = true;
|
||||
protected int $lowestScore = 100;
|
||||
|
||||
public function __construct() {
|
||||
public function __construct(array $fileList = []) {
|
||||
$this->list = [];
|
||||
for ($n = 0, $end = count($fileList['error']); $n < $end; ++$n) {
|
||||
if ($fileList['error'][$n] == UPLOAD_ERR_OK) {
|
||||
$log = new Logfile($fileList['tmp_name'][$n], $fileList['name'][$n]);
|
||||
$this->allChecksum = $this->allChecksum && $log->checksum();
|
||||
$this->lowestScore = min($this->lowestScore, $log->score());
|
||||
$this->list[] = $log;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function add(Logfile $log) {
|
||||
$this->list[] = $log;
|
||||
$this->allChecksum = is_null($this->allChecksum)
|
||||
? $log->checksum()
|
||||
: $this->allChecksum && $log->checksum();
|
||||
$this->lowestScore = is_null($this->lowestScore)
|
||||
? $log->score()
|
||||
: min($this->lowestScore, $log->score());
|
||||
}
|
||||
|
||||
public function checksum() {
|
||||
public function checksum(): bool {
|
||||
return $this->allChecksum;
|
||||
}
|
||||
|
||||
public function checksumStatus() {
|
||||
public function checksumStatus(): string {
|
||||
return $this->allChecksum ? '1' : '0';
|
||||
}
|
||||
|
||||
public function overallScore() {
|
||||
public function overallScore(): int {
|
||||
return is_null($this->lowestScore) ? 0 : $this->lowestScore;
|
||||
}
|
||||
|
||||
public function all() {
|
||||
public function all(): array {
|
||||
return $this->list;
|
||||
}
|
||||
|
||||
public function count() {
|
||||
public function total(): int {
|
||||
return count($this->list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,27 +99,27 @@ class Torrent extends \Gazelle\BaseManager {
|
||||
}
|
||||
|
||||
public function create(
|
||||
int $tgroupId,
|
||||
int $userId,
|
||||
string $description,
|
||||
string $media,
|
||||
int $tgroupId,
|
||||
int $userId,
|
||||
string $description,
|
||||
string $media,
|
||||
?string $format,
|
||||
?string $encoding,
|
||||
string $infohash,
|
||||
string $filePath,
|
||||
array $fileList,
|
||||
int $size,
|
||||
bool $isScene,
|
||||
bool $isRemaster,
|
||||
?int $remasterYear,
|
||||
string $remasterTitle,
|
||||
string $remasterRecordLabel,
|
||||
string $remasterCatalogueNumber,
|
||||
int $logScore = 0,
|
||||
bool $hasChecksum = false,
|
||||
bool $hasCue = false,
|
||||
bool $hasLog = false,
|
||||
bool $hasLogInDB = false,
|
||||
string $infohash,
|
||||
string $filePath,
|
||||
array $fileList,
|
||||
int $size,
|
||||
bool $isScene,
|
||||
bool $isRemaster,
|
||||
?int $remasterYear,
|
||||
string $remasterTitle,
|
||||
string $remasterRecordLabel,
|
||||
string $remasterCatalogueNumber,
|
||||
int $logScore = 0,
|
||||
bool $hasChecksum = false,
|
||||
bool $hasCue = false,
|
||||
bool $hasLog = false,
|
||||
bool $hasLogInDB = false,
|
||||
): \Gazelle\Torrent {
|
||||
self::$db->prepared_query("
|
||||
INSERT INTO torrents (
|
||||
|
||||
@@ -3,9 +3,28 @@
|
||||
namespace Gazelle\Manager;
|
||||
|
||||
class TorrentLog extends \Gazelle\Base {
|
||||
public function __construct(
|
||||
protected \Gazelle\File\RipLog $ripFiler,
|
||||
protected \Gazelle\File\RipLogHTML $htmlFiler,
|
||||
) {}
|
||||
|
||||
public function create(\Gazelle\Torrent $torrent, \Gazelle\Logfile $logfile, string $checkerVersion): \Gazelle\TorrentLog {
|
||||
self::$db->prepared_query('
|
||||
INSERT INTO torrents_logs
|
||||
(TorrentID, Score, `Checksum`, FileName, Ripper, RipperVersion, `Language`, ChecksumState, Details, LogcheckerVersion)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
', $torrent->id(), $logfile->score(), $logfile->checksumStatus(), $logfile->filename(),
|
||||
$logfile->ripper(), $logfile->ripperVersion(), $logfile->language(), $logfile->checksumState(), $logfile->detailsAsString(),
|
||||
$checkerVersion
|
||||
);
|
||||
$logId = self::$db->inserted_id();
|
||||
$this->ripFiler->put($logfile->filepath(), [$torrent->id(), $logId]);
|
||||
$this->htmlFiler->put($logfile->text(), [$torrent->id(), $logId]);
|
||||
return $this->findById($torrent, $logId);
|
||||
}
|
||||
|
||||
public function findById(\Gazelle\Torrent $torrent, int $logId): ?\Gazelle\TorrentLog {
|
||||
$id = self::$db->scalar("
|
||||
$id = (int)self::$db->scalar("
|
||||
SELECT LogID FROM torrents_logs WHERE TorrentID = ? AND LogID = ?
|
||||
", $torrent->id(), $logId
|
||||
);
|
||||
|
||||
@@ -220,9 +220,9 @@ class Torrent extends TorrentAbstract {
|
||||
if (!$count) {
|
||||
self::$db->prepared_query("
|
||||
UPDATE torrents SET
|
||||
HasLogDB = '0',
|
||||
LogChecksum = '1',
|
||||
LogScore = 0
|
||||
HasLogDB = '0',
|
||||
LogChecksum = '0',
|
||||
LogScore = 0
|
||||
WHERE ID = ?
|
||||
", $this->id
|
||||
);
|
||||
@@ -231,21 +231,23 @@ class Torrent extends TorrentAbstract {
|
||||
UPDATE torrents AS t
|
||||
LEFT JOIN (
|
||||
SELECT TorrentID,
|
||||
min(CASE WHEN Adjusted = '1' OR AdjustedScore != Score THEN AdjustedScore ELSE Score END) AS Score,
|
||||
min(CASE WHEN Adjusted = '1' OR AdjustedChecksum != Checksum THEN AdjustedChecksum ELSE Checksum END) AS Checksum
|
||||
min(CASE WHEN Adjusted = '1' AND AdjustedScore != Score THEN AdjustedScore ELSE Score END) AS Score,
|
||||
min(CASE WHEN Adjusted = '1' AND AdjustedChecksum != Checksum THEN AdjustedChecksum ELSE Checksum END) AS Checksum
|
||||
FROM torrents_logs
|
||||
WHERE TorrentID = ?
|
||||
GROUP BY TorrentID
|
||||
) AS tl ON (t.ID = tl.TorrentID)
|
||||
SET
|
||||
t.HasLogDB = '1',
|
||||
t.LogScore = tl.Score,
|
||||
t.LogChecksum = tl.Checksum
|
||||
WHERE t.ID = ?
|
||||
", $this->id, $this->id
|
||||
);
|
||||
}
|
||||
$affected = self::$db->affected_rows();
|
||||
$this->flush();
|
||||
return self::$db->affected_rows();
|
||||
return $affected;
|
||||
}
|
||||
|
||||
public function rescoreLog(int $logId, \Gazelle\Logfile $logfile, string $version): int {
|
||||
@@ -265,21 +267,6 @@ class Torrent extends TorrentAbstract {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function updateLogScore(LogfileSummary $summary): int {
|
||||
self::$db->prepared_query("
|
||||
UPDATE torrents SET
|
||||
HasLogDB = '1',
|
||||
LogScore = ?,
|
||||
LogChecksum = ?
|
||||
WHERE ID = ?
|
||||
", $summary->overallScore(), $summary->checksumStatus(),
|
||||
$this->id
|
||||
);
|
||||
$this->flush();
|
||||
self::$cache->delete_value(sprintf(TGroup::CACHE_TLIST_KEY, $this->groupId()));
|
||||
return self::$db->affected_rows();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all logfiles attached to this upload
|
||||
*
|
||||
|
||||
@@ -10,7 +10,10 @@ abstract class TorrentAbstract extends BaseObject {
|
||||
protected User $viewer;
|
||||
|
||||
public function flush(): TorrentAbstract {
|
||||
self::$cache->delete_value(sprintf(self::CACHE_KEY, $this->id));
|
||||
self::$cache->delete_multi([
|
||||
sprintf(self::CACHE_KEY, $this->id),
|
||||
"torrent_download_{$this->id}",
|
||||
]);
|
||||
$this->group()->flush();
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ module.exports = defineConfig({
|
||||
supportFile: 'tests/cypress/support/e2e.{js,jsx,ts,tsx}',
|
||||
specPattern: 'tests/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
|
||||
video: false,
|
||||
screenshotOnRunFailure: false
|
||||
screenshotOnRunFailure: false,
|
||||
setupNodeEvents(on, config) {
|
||||
require('cypress-terminal-report/src/installLogsPrinter')(on);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"browser-sync": "^2.27.5",
|
||||
"browser-sync-webpack-plugin": "^2.2.2",
|
||||
"cypress": "^12.0.2",
|
||||
"cypress-terminal-report": "^5.0.2",
|
||||
"husky": "^8.0.1",
|
||||
"lint-staged": "^10.5.0",
|
||||
"stylelint": "^13.3.2",
|
||||
|
||||
@@ -4,10 +4,18 @@ $torrent = (new Gazelle\Manager\Torrent)->findById((int)($_GET['id'] ?? 0));
|
||||
if (is_null($torrent)) {
|
||||
json_error('bad parameters');
|
||||
}
|
||||
if ($torrent->uploaderId() != $Viewer->id() && !$Viewer->permitted('admin_add_log')) {
|
||||
json_error('Not your upload.');
|
||||
}
|
||||
if (empty($_FILES) || empty($_FILES['logfiles'])) {
|
||||
json_error('no log files uploaded');
|
||||
}
|
||||
|
||||
(new Gazelle\Json\AddLog($torrent, $Viewer, $_FILES['logfiles']))
|
||||
(new Gazelle\Json\AddLog(
|
||||
$torrent,
|
||||
$Viewer,
|
||||
new Gazelle\Manager\TorrentLog(new Gazelle\File\RipLog, new Gazelle\File\RipLogHTML),
|
||||
new Gazelle\LogfileSummary($_FILES['logfiles']),
|
||||
))
|
||||
->setVersion(1)
|
||||
->emit();
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<?php
|
||||
|
||||
if (isset($_FILES['log']) && is_uploaded_file($_FILES['log']['tmp_name'])) {
|
||||
$file = $_FILES['log'];
|
||||
$file = $_FILES['log'];
|
||||
$isPaste = false;
|
||||
} elseif (!empty($_POST["pastelog"])) {
|
||||
$fileTmp = tempnam('/tmp', 'log_');
|
||||
file_put_contents($fileTmp, $_POST["pastelog"]);
|
||||
$file = ['tmp_name' => $fileTmp, 'name' => $fileTmp];
|
||||
$file = [
|
||||
'tmp_name' => $fileTmp,
|
||||
'name' => $fileTmp
|
||||
];
|
||||
$isPaste = true;
|
||||
} else {
|
||||
json_error('no log file provided');
|
||||
@@ -17,13 +20,11 @@ if (isset($fileTmp)) {
|
||||
unlink($fileTmp);
|
||||
}
|
||||
|
||||
$response = [
|
||||
'ripper' => $logfile->ripper(),
|
||||
json_print('success', [
|
||||
'ripper' => $logfile->ripper(),
|
||||
'ripperVersion' => $logfile->ripperVersion(),
|
||||
'language' => $logfile->language(),
|
||||
'score' => $logfile->score(),
|
||||
'checksum' => $logfile->checksumState(),
|
||||
'issues' => $logfile->details(),
|
||||
];
|
||||
|
||||
json_print('success', $response);
|
||||
'language' => $logfile->language(),
|
||||
'score' => $logfile->score(),
|
||||
'checksum' => $logfile->checksumState(),
|
||||
'issues' => $logfile->details(),
|
||||
]);
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<?php
|
||||
|
||||
if (isset($_FILES['log']) && is_uploaded_file($_FILES['log']['tmp_name'])) {
|
||||
$file = $_FILES['log'];
|
||||
$file = $_FILES['log'];
|
||||
$isPaste = false;
|
||||
} elseif (!empty($_POST["pastelog"])) {
|
||||
$fileTmp = tempnam('/tmp', 'log_');
|
||||
file_put_contents($fileTmp, $_POST["pastelog"]);
|
||||
$file = ['tmp_name' => $fileTmp, 'name' => $fileTmp];
|
||||
$file = [
|
||||
'tmp_name' => $fileTmp,
|
||||
'name' => $fileTmp
|
||||
];
|
||||
$isPaste = true;
|
||||
} else {
|
||||
error('No log file uploaded or file is empty.');
|
||||
|
||||
@@ -15,37 +15,26 @@ if ($torrent->uploaderId() != $Viewer->id() && !$Viewer->permitted('admin_add_lo
|
||||
error('Not your upload.');
|
||||
}
|
||||
|
||||
// Some browsers will report an empty file when you submit, prune those out
|
||||
$_FILES['logfiles']['name'] = array_filter($_FILES['logfiles']['name'], fn($Name) => !empty($Name));
|
||||
if (count($_FILES['logfiles']['name']) == 0) {
|
||||
error("No logfiles uploaded.\n");
|
||||
}
|
||||
$action = in_array($_POST['from_action'], ['upload', 'update']) ? $_POST['from_action'] : 'upload';
|
||||
$logfileSummary = new Gazelle\LogfileSummary($_FILES['logfiles']);
|
||||
|
||||
$ripFiler = new Gazelle\File\RipLog;
|
||||
$ripFiler->remove([$torrent->id(), null]);
|
||||
if (!$logfileSummary->total()) {
|
||||
error("No logfiles uploaded.");
|
||||
} else {
|
||||
$ripFiler = new Gazelle\File\RipLog;
|
||||
$htmlFiler = new Gazelle\File\RipLogHTML;
|
||||
|
||||
$htmlFiler = new Gazelle\File\RipLogHTML;
|
||||
$htmlFiler->remove([$torrent->id(), null]);
|
||||
$torrent->removeLogDb();
|
||||
$ripFiler->remove([$torrent->id(), null]);
|
||||
$htmlFiler->remove([$torrent->id(), null]);
|
||||
$torrentLogManager = new Gazelle\Manager\TorrentLog($ripFiler, $htmlFiler);
|
||||
|
||||
$torrent->removeLogDb();
|
||||
|
||||
$logfileSummary = new Gazelle\LogfileSummary;
|
||||
foreach ($_FILES['logfiles']['name'] as $Pos => $File) {
|
||||
if (!$_FILES['logfiles']['size'][$Pos]) {
|
||||
break;
|
||||
$checkerVersion = Logchecker::getLogcheckerVersion();
|
||||
foreach($logfileSummary->all() as $logfile) {
|
||||
$torrentLogManager->create($torrent, $logfile, $checkerVersion);
|
||||
}
|
||||
$logfile = new Gazelle\Logfile(
|
||||
$_FILES['logfiles']['tmp_name'][$Pos],
|
||||
$_FILES['logfiles']['name'][$Pos]
|
||||
);
|
||||
$logfileSummary->add($logfile);
|
||||
$logId = $torrent->addLogDb($logfile, Logchecker::getLogcheckerVersion());
|
||||
|
||||
$ripFiler->put($logfile->filepath(), [$torrent->id(), $logId]);
|
||||
$htmlFiler->put($logfile->text(), [$torrent->id(), $logId]);
|
||||
$torrent->modifyLogscore();
|
||||
}
|
||||
$torrent->updateLogScore($logfileSummary);
|
||||
|
||||
echo $Twig->render('logchecker/result.twig', [
|
||||
'summary' => $logfileSummary->all(),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
authorize();
|
||||
if (!$Viewer->permitted('users_mod')) {
|
||||
error(403);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ $torrent = (new Gazelle\Manager\Torrent)->findById((int)($_GET['torrentid'] ?? 0
|
||||
if (is_null($torrent)) {
|
||||
error(404);
|
||||
}
|
||||
$tlog = (new Gazelle\Manager\TorrentLog)->findById($torrent, (int)($_GET['logid'] ?? 0));
|
||||
$tlog = (new Gazelle\Manager\TorrentLog(new Gazelle\File\RipLog, new Gazelle\File\RipLogHTML))->findById($torrent, (int)($_GET['logid'] ?? 0));
|
||||
if (is_null($tlog)) {
|
||||
error(404);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
authorize();
|
||||
if (!$Viewer->permitted('torrents_delete')) {
|
||||
error(403);
|
||||
}
|
||||
|
||||
@@ -47,16 +47,16 @@ if (isset($_POST['album_desc'])) {
|
||||
$Properties['GroupDescription'] = trim($_POST['album_desc']);
|
||||
}
|
||||
if ($Properties['Remastered']) {
|
||||
$Properties['UnknownRelease'] = isset($_POST['unknown']);
|
||||
$Properties['RemasterYear'] = isset($_POST['remaster_year']) ? (int)$_POST['remaster_year'] : null;
|
||||
$Properties['RemasterTitle'] = trim($_POST['remaster_title'] ?? '');
|
||||
$Properties['RemasterRecordLabel'] = trim($_POST['remaster_record_label'] ?? '');
|
||||
$Properties['UnknownRelease'] = isset($_POST['unknown']);
|
||||
$Properties['RemasterYear'] = isset($_POST['remaster_year']) ? (int)$_POST['remaster_year'] : null;
|
||||
$Properties['RemasterTitle'] = trim($_POST['remaster_title'] ?? '');
|
||||
$Properties['RemasterRecordLabel'] = trim($_POST['remaster_record_label'] ?? '');
|
||||
$Properties['RemasterCatalogueNumber'] = trim($_POST['remaster_catalogue_number'] ?? '');
|
||||
} else {
|
||||
$Properties['UnknownRelease'] = false;
|
||||
$Properties['RemasterYear'] = null;
|
||||
$Properties['RemasterTitle'] = '';
|
||||
$Properties['RemasterRecordLabel'] = '';
|
||||
$Properties['UnknownRelease'] = false;
|
||||
$Properties['RemasterYear'] = null;
|
||||
$Properties['RemasterTitle'] = '';
|
||||
$Properties['RemasterRecordLabel'] = '';
|
||||
$Properties['RemasterCatalogueNumber'] = '';
|
||||
}
|
||||
|
||||
@@ -199,42 +199,20 @@ foreach ($current as $key => $value) {
|
||||
}
|
||||
}
|
||||
|
||||
$logfileSummary = new Gazelle\LogfileSummary($_FILES['logfiles']);
|
||||
|
||||
//******************************************************************************//
|
||||
//--------------- Start database stuff -----------------------------------------//
|
||||
|
||||
$db->begin_transaction(); // It's all or nothing
|
||||
|
||||
// Some browsers will report an empty file when you submit, prune those out
|
||||
if (isset($_FILES['logfiles'])) {
|
||||
$_FILES['logfiles']['name'] = array_filter($_FILES['logfiles']['name'], fn($name) => !empty($name));
|
||||
|
||||
$logfileSummary = new Gazelle\LogfileSummary;
|
||||
$logfiles = [];
|
||||
if (count($_FILES['logfiles']['name']) > 0) {
|
||||
ini_set('upload_max_filesize', 1_000_000);
|
||||
$ripFiler = new Gazelle\File\RipLog;
|
||||
$htmlFiler = new Gazelle\File\RipLogHTML;
|
||||
foreach ($_FILES['logfiles']['name'] as $Pos => $File) {
|
||||
if (!$_FILES['logfiles']['size'][$Pos]) {
|
||||
continue;
|
||||
}
|
||||
$logfile = new Gazelle\Logfile(
|
||||
$_FILES['logfiles']['tmp_name'][$Pos],
|
||||
$_FILES['logfiles']['name'][$Pos]
|
||||
);
|
||||
$logfileSummary->add($logfile);
|
||||
|
||||
$db->prepared_query('
|
||||
INSERT INTO torrents_logs
|
||||
(TorrentID, Score, `Checksum`, FileName, Ripper, RipperVersion, `Language`, ChecksumState, LogcheckerVersion, Details)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
', $TorrentID, $logfile->score(), $logfile->checksumStatus(), $logfile->filename(), $logfile->ripper(),
|
||||
$logfile->ripperVersion(), $logfile->language(), $logfile->checksumState(),
|
||||
Logchecker::getLogcheckerVersion(), $logfile->detailsAsString()
|
||||
);
|
||||
$LogID = $db->inserted_id();
|
||||
$ripFiler->put($logfile->filepath(), [$TorrentID, $LogID]);
|
||||
$htmlFiler->put($logfile->text(), [$TorrentID, $LogID]);
|
||||
}
|
||||
$torrent->updateLogScore($logfileSummary);
|
||||
if ($logfileSummary->total()) {
|
||||
$torrentLogManager = new Gazelle\Manager\TorrentLog(new Gazelle\File\RipLog, new Gazelle\File\RipLogHTML);
|
||||
$checkerVersion = Logchecker::getLogcheckerVersion();
|
||||
foreach($logfileSummary->all() as $logfile) {
|
||||
$torrentLogManager->create($torrent, $logfile, $checkerVersion);
|
||||
}
|
||||
$torrent->modifyLogscore();
|
||||
}
|
||||
|
||||
// Update info for the torrent
|
||||
@@ -303,5 +281,4 @@ $changeLog = implode(', ', $change);
|
||||
. $Viewer->username() . " ($changeLog)");
|
||||
|
||||
$torrent->flush();
|
||||
$Cache->delete_value("torrent_download_$TorrentID");
|
||||
header("Location: " . $torrent->location());
|
||||
|
||||
@@ -24,18 +24,18 @@ $Properties['Title'] = isset($_POST['title']) ? trim($_POST['title']) : null;
|
||||
// Remastered is an Enum in the DB
|
||||
$Properties['Remastered'] = !empty($_POST['remaster']) ? '1' : '0';
|
||||
if ($Properties['Remastered'] || !empty($_POST['unknown'])) {
|
||||
$Properties['UnknownRelease'] = !empty($_POST['unknown']) ? 1 : 0;
|
||||
$Properties['RemasterYear'] = isset($_POST['remaster_year']) ? (int)$_POST['remaster_year'] : null;
|
||||
$_POST['remaster_year'] = $Properties['RemasterYear'];
|
||||
$Properties['RemasterTitle'] = trim($_POST['remaster_title'] ?? '');
|
||||
$Properties['RemasterRecordLabel'] = trim($_POST['remaster_record_label'] ?? '');
|
||||
$Properties['UnknownRelease'] = !empty($_POST['unknown']) ? 1 : 0;
|
||||
$Properties['RemasterYear'] = isset($_POST['remaster_year']) ? (int)$_POST['remaster_year'] : null;
|
||||
$_POST['remaster_year'] = $Properties['RemasterYear'];
|
||||
$Properties['RemasterTitle'] = trim($_POST['remaster_title'] ?? '');
|
||||
$Properties['RemasterRecordLabel'] = trim($_POST['remaster_record_label'] ?? '');
|
||||
$Properties['RemasterCatalogueNumber'] = trim($_POST['remaster_catalogue_number'] ?? '');
|
||||
}
|
||||
if (!$Properties['Remastered'] || $Properties['UnknownRelease']) {
|
||||
$Properties['UnknownRelease'] = 1;
|
||||
$Properties['RemasterYear'] = null;
|
||||
$Properties['RemasterTitle'] = '';
|
||||
$Properties['RemasterRecordLabel'] = '';
|
||||
$Properties['UnknownRelease'] = 1;
|
||||
$Properties['RemasterYear'] = null;
|
||||
$Properties['RemasterTitle'] = '';
|
||||
$Properties['RemasterRecordLabel'] = '';
|
||||
$Properties['RemasterCatalogueNumber'] = '';
|
||||
}
|
||||
$Properties['Year'] = isset($_POST['year']) ? (int)$_POST['year'] : null;
|
||||
@@ -472,24 +472,6 @@ if ($Err) {
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
//--------------- Start database stuff -----------------------------------------//
|
||||
|
||||
$logfileSummary = new Gazelle\LogfileSummary;
|
||||
if ($HasLog == '1' && isset($_FILES['logfiles'])) {
|
||||
foreach (array_keys($_FILES['logfiles']['error']) as $n) {
|
||||
if ($_FILES['logfiles']['error'][$n] == UPLOAD_ERR_OK) {
|
||||
$logfileSummary->add(
|
||||
new Gazelle\Logfile(
|
||||
$_FILES['logfiles']['tmp_name'][$n],
|
||||
$_FILES['logfiles']['name'][$n]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
$LogInDB = count($logfileSummary->all()) ? '1' : '0';
|
||||
|
||||
$tgroup = null;
|
||||
$NoRevision = false;
|
||||
if ($isMusicUpload) {
|
||||
@@ -527,7 +509,11 @@ $IsNewGroup = is_null($tgroup);
|
||||
//Needs to be here as it isn't set for add format until now
|
||||
$LogName .= $Properties['Title'];
|
||||
|
||||
//----- Start inserts
|
||||
$logfileSummary = new Gazelle\LogfileSummary($_FILES['logfiles']);
|
||||
$LogInDB = $logfileSummary->total() ? '1' : '0';
|
||||
|
||||
//******************************************************************************//
|
||||
//--------------- Start database stuff -----------------------------------------//
|
||||
|
||||
$Debug->set_flag('upload: database begin transaction');
|
||||
$db = Gazelle\DB::DB();
|
||||
@@ -613,58 +599,45 @@ $extraFile = [];
|
||||
$trackerUpdate = [];
|
||||
|
||||
foreach ($ExtraTorrentsInsert as $ExtraTorrent) {
|
||||
$db->prepared_query("
|
||||
INSERT INTO torrents
|
||||
(GroupID, UserID, Media, Format, Encoding,
|
||||
Remastered, RemasterYear, RemasterTitle, RemasterRecordLabel, RemasterCatalogueNumber,
|
||||
info_hash, FileCount, FileList, FilePath, Size, Description,
|
||||
Time, LogScore, HasLog, HasCue, FreeTorrent, FreeLeechType)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?,
|
||||
?, ?, ?, ?, ?,
|
||||
?, ?, ?, ?, ?, ?,
|
||||
now(), 0, '0', '0', '0', '0')
|
||||
", $GroupID, $Viewer->id(), $Properties['Media'], $ExtraTorrent['Format'], $ExtraTorrent['Encoding'],
|
||||
$Properties['Remastered'], $Properties['RemasterYear'], $Properties['RemasterTitle'], $Properties['RemasterRecordLabel'], $Properties['RemasterCatalogueNumber'],
|
||||
$ExtraTorrent['InfoHash'], $ExtraTorrent['NumFiles'], $ExtraTorrent['FileString'],
|
||||
$ExtraTorrent['FilePath'], $ExtraTorrent['TotalSize'], $ExtraTorrent['TorrentDescription']
|
||||
$torrentExtra = $torMan->create(
|
||||
tgroupId: $GroupID,
|
||||
userId: $Viewer->id(),
|
||||
description: $ExtraTorrent['TorrentDescription'],
|
||||
media: $Properties['Media'],
|
||||
format: $ExtraTorrent['Format'],
|
||||
encoding: $ExtraTorrent['Encoding'],
|
||||
infohash: $ExtraTorrent['InfoHash'],
|
||||
filePath: $ExtraTorrent['FilePath'],
|
||||
fileList: $ExtraTorrent['FileString'],
|
||||
size: $ExtraTorrent['TotalSize'],
|
||||
isScene: $Properties['Scene'],
|
||||
isRemaster: $Properties['Remastered'],
|
||||
remasterYear: $Properties['RemasterYear'],
|
||||
remasterTitle: $Properties['RemasterTitle'],
|
||||
remasterRecordLabel: $Properties['RemasterRecordLabel'],
|
||||
remasterCatalogueNumber: $Properties['RemasterCatalogueNumber'],
|
||||
);
|
||||
$ExtraTorrentID = $db->inserted_id();
|
||||
$db->prepared_query('
|
||||
INSERT INTO torrents_leech_stats (TorrentID)
|
||||
VALUES (?)
|
||||
', $ExtraTorrentID
|
||||
);
|
||||
$torrentExtra = new Gazelle\Torrent($ExtraTorrentID);
|
||||
|
||||
$torMan->flushFoldernameCache($ExtraTorrent['FilePath']);
|
||||
$folderCheck[] = $ExtraTorrent['FilePath'];
|
||||
$trackerUpdate[$ExtraTorrentID] = rawurlencode($ExtraTorrent['InfoHash']);
|
||||
$torMan->flushFoldernameCache($torrentExtra->path());
|
||||
$folderCheck[] = $torrentExtra->path();
|
||||
$trackerUpdate[$torrentExtra->id()] = rawurlencode($torrentExtra->infohash());
|
||||
$bonusTotal += $bonus->torrentValue($torrentExtra);
|
||||
|
||||
$extraFile[$ExtraTorrentID] = [
|
||||
$extraFile[$torrentExtra->id()] = [
|
||||
'payload' => $ExtraTorrent['TorEnc'],
|
||||
'size' => number_format($ExtraTorrent['TotalSize'] / (1024 * 1024), 2)
|
||||
'size' => number_format($torrentExtra->size() / (1024 * 1024), 2)
|
||||
];
|
||||
}
|
||||
|
||||
//******************************************************************************//
|
||||
//--------------- Write Files To Disk ------------------------------------------//
|
||||
|
||||
$ripFiler = new Gazelle\File\RipLog;
|
||||
$htmlFiler = new Gazelle\File\RipLogHTML;
|
||||
foreach($logfileSummary->all() as $logfile) {
|
||||
$db->prepared_query('
|
||||
INSERT INTO torrents_logs
|
||||
(TorrentID, Score, `Checksum`, FileName, Ripper, RipperVersion, `Language`, ChecksumState, LogcheckerVersion, Details)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
', $TorrentID, $logfile->score(), $logfile->checksumStatus(), $logfile->filename(),
|
||||
$logfile->ripper(), $logfile->ripperVersion(), $logfile->language(), $logfile->checksumState(),
|
||||
Logchecker::getLogcheckerVersion(), $logfile->detailsAsString()
|
||||
);
|
||||
$LogID = $db->inserted_id();
|
||||
$ripFiler->put($logfile->filepath(), [$TorrentID, $LogID]);
|
||||
$htmlFiler->put($logfile->text(), [$TorrentID, $LogID]);
|
||||
if ($logfileSummary->total()) {
|
||||
$torrentLogManager = new Gazelle\Manager\TorrentLog(new Gazelle\File\RipLog, new Gazelle\File\RipLogHTML);
|
||||
$checkerVersion = Logchecker::getLogcheckerVersion();
|
||||
foreach($logfileSummary->all() as $logfile) {
|
||||
$torrentLogManager->create($torrent, $logfile, $checkerVersion);
|
||||
}
|
||||
}
|
||||
|
||||
$log = new Gazelle\Log;
|
||||
@@ -675,7 +648,7 @@ $log->torrent($GroupID, $TorrentID, $Viewer->id(), 'uploaded ('.number_format($T
|
||||
foreach ($extraFile as $id => $info) {
|
||||
$torrentFiler->put($info['payload'], $id);
|
||||
$log->torrent($GroupID, $id, $Viewer->id(), "uploaded ({$info['size']} MiB)")
|
||||
->general("Torrent $ExtraTorrentID ($LogName) ({$info['size']} MiB) was uploaded by " . $Viewer->username());
|
||||
->general("Torrent $id ($LogName) ({$info['size']} MiB) was uploaded by " . $Viewer->username());
|
||||
}
|
||||
|
||||
$db->commit(); // We have a usable upload, any subsequent failures can be repaired ex post facto
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
{% if viewer.permitted('users_mod') %}
|
||||
<div style="padding: 10px; float: right"><a class="brackets" href="torrents.php?action=editlog&torrentid={{ id }}&logid={{ log.id }}">Edit Log</a>
|
||||
<a class="brackets" onclick="return confirm('Are you sure you want to deleted this log? There is NO undo!');"
|
||||
href="torrents.php?action=deletelog&torrentid={{ id }}&logid={{ log.id }}">Delete Log</a>
|
||||
href="torrents.php?action=deletelog&torrentid={{ id }}&logid={{ log.id }}&auth={{ viewer.auth }}">Delete Log</a>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -71,6 +71,6 @@
|
||||
{% else %}
|
||||
No logs found!
|
||||
{% if viewer.permitted('torrents_delete') %}
|
||||
<a class="brackets" href="torrents.php?action=removelogs&torrentid={{ id }}">Repair DB</a>
|
||||
<a class="brackets" href="torrents.php?action=removelogs&torrentid={{ id }}&auth={{ viewer.auth }}">Repair DB</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -31,7 +31,6 @@ describe('page loads as admin', () => {
|
||||
"/top10.php",
|
||||
"/torrents.php",
|
||||
"/torrents.php?action=advanced&artistname=doesnotexist",
|
||||
"/upload.php",
|
||||
"/user.php",
|
||||
"/user.php?id=1",
|
||||
"/user.php?action=edit&id=1",
|
||||
@@ -48,7 +47,7 @@ describe('page loads as admin', () => {
|
||||
})
|
||||
it(`should have a footer: ${url}`, () => {
|
||||
cy.visit(url);
|
||||
cy.contains(`Site and design © ${date.getFullYear()} Gazelle`);
|
||||
cy.ensureFooter();
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
describe('uploading torrent', () => {
|
||||
let date = new Date();
|
||||
let footer = `Site and design © ${date.getFullYear()} Gazelle`;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.loginUser();
|
||||
})
|
||||
|
||||
it('upload music torrent', () => {
|
||||
cy.visit('/upload.php');
|
||||
cy.ensureFooter();
|
||||
cy.get('#file').selectFile('tests/cypress/files/valid_torrent.torrent')
|
||||
cy.get("#categories").select('Music');
|
||||
cy.get("#releasetype").select('Album');
|
||||
@@ -41,11 +39,12 @@ describe('uploading torrent', () => {
|
||||
cy.contains('Some Artist');
|
||||
cy.contains('2022');
|
||||
cy.contains('Cool Test Label!');
|
||||
cy.contains(footer);
|
||||
cy.ensureFooter();
|
||||
})
|
||||
|
||||
it('upload torrent to existing group', () => {
|
||||
cy.visit('/upload.php');
|
||||
cy.ensureFooter();
|
||||
cy.get('#file').selectFile('tests/cypress/files/valid_torrent_2.torrent')
|
||||
cy.get("#categories").select('Music');
|
||||
cy.get("#releasetype").select('Album');
|
||||
@@ -76,6 +75,82 @@ describe('uploading torrent', () => {
|
||||
cy.contains('2022');
|
||||
cy.contains('Cool Test Label!');
|
||||
cy.contains('[CD / FLAC / Lossless / Log (100%)]');
|
||||
cy.contains(footer);
|
||||
cy.ensureFooter();
|
||||
})
|
||||
|
||||
it('re-attach log to upload', () => {
|
||||
// find torrent id
|
||||
cy.visit('/torrents.php?type=uploaded');
|
||||
cy.ensureFooter();
|
||||
|
||||
// bunch of callbacks have been flattened below
|
||||
cy.get('.group_info').contains('Log (100%)').first()
|
||||
.find('a[href*="torrents.php?"][href*="torrentid="]').first()
|
||||
.invoke('attr', 'href').then((torrent_url) => {
|
||||
let torrent_id = torrent_url.match(/[&?]torrentid=([0-9]+)/)[1];
|
||||
cy.visit(torrent_url);
|
||||
cy.ensureFooter();
|
||||
cy.get(`#torrent_${torrent_id}`).contains('View log').click();
|
||||
cy.get(`a[href*="view.php?type=riplog&id=${torrent_id}."]`).first()
|
||||
.invoke('attr', 'href').then((log_url) => {
|
||||
|
||||
let log_id = log_url.match(/&id=[0-9]+\.([0-9]+)/)[1];
|
||||
|
||||
// delete existing log
|
||||
cy.loginAdmin();
|
||||
cy.visit('/');
|
||||
cy.window()
|
||||
.then((window) => {
|
||||
cy.window().should('have.property', 'authkey')
|
||||
cy.visit('/torrents.php', {qs: {
|
||||
action: 'deletelog',
|
||||
torrentid: torrent_id,
|
||||
logid: log_id,
|
||||
auth: window.authkey
|
||||
}})
|
||||
});
|
||||
|
||||
cy.loginUser();
|
||||
// verify log was correctly removed
|
||||
cy.visit(torrent_url);
|
||||
cy.contains('Log (100%)').should('not.exist');
|
||||
cy.ensureFooter();
|
||||
// set up api token
|
||||
cy.visit('/user.php?action=token&do=generate',
|
||||
{method: 'POST', body: {token_name: 'test_reattach_log'}});
|
||||
cy.ensureFooter();
|
||||
|
||||
// upload log
|
||||
cy.get('.box2 > .pad > strong').invoke('text').then((api_key) => {
|
||||
cy.fixture('../files/valid_log_eac.log', 'binary').then( (log_bin) => {
|
||||
// File in binary format gets converted to blob so it can be sent as Form data
|
||||
const blob = Cypress.Blob.binaryStringToBlob(log_bin, 'application/octet-stream');
|
||||
const formData = new FormData();
|
||||
formData.append('logfiles[]', blob, 'eac.log');
|
||||
cy.request({
|
||||
url: '/ajax.php',
|
||||
qs: {action: 'add_log', id: torrent_id},
|
||||
method: 'POST',
|
||||
headers: {authorization: `token ${api_key}`,
|
||||
'content-type': 'multipart/form-data'},
|
||||
body: formData
|
||||
}).then( (response) => {
|
||||
// it's an ArrayBuffer but for some reason instanceof ArrayBuffer is false
|
||||
// and its stringifyed version is "{}"
|
||||
let body = typeof response.body === 'object' ?
|
||||
new TextDecoder().decode(response.body) : response.body;
|
||||
try {
|
||||
body = JSON.parse(body);
|
||||
} catch (e) {
|
||||
cy.logCli("bad response body: " + body);
|
||||
}
|
||||
expect(body).to.have.property('status', 'success');
|
||||
});
|
||||
})
|
||||
// verify
|
||||
cy.visit(torrent_url);
|
||||
cy.ensureFooter();
|
||||
cy.contains('Log (100%)');
|
||||
})})});
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
|
||||
const date = new Date();
|
||||
const footer = `Site and design © ${date.getFullYear()} Gazelle`;
|
||||
|
||||
Cypress.Commands.add('login', (username, password) => {
|
||||
// https://www.cypress.io/blog/2021/08/04/authenticate-faster-in-tests-cy-session-command/
|
||||
cy.session([username, password], () => {
|
||||
@@ -42,3 +45,15 @@ Cypress.Commands.add('loginAdmin', () => {
|
||||
Cypress.Commands.add('loginUser', () => {
|
||||
cy.login('user', 'password');
|
||||
})
|
||||
|
||||
Cypress.Commands.add('ensureFooter', () => {
|
||||
cy.contains(footer);
|
||||
})
|
||||
|
||||
Cypress.Commands.add('logCli', (msg) => {
|
||||
// somehow cypress-terminal-report doesn't pick up cy.log()
|
||||
Cypress.log({
|
||||
name: "logCli",
|
||||
message: msg
|
||||
});
|
||||
})
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
require('cypress-terminal-report/src/installLogsCollector')({
|
||||
xhr: {
|
||||
printHeaderData: true,
|
||||
printRequestData: true
|
||||
}
|
||||
});
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
Cypress.on('fail', (err, runnable) => {
|
||||
/**
|
||||
* add DOM html to error message
|
||||
|
||||
38
yarn.lock
38
yarn.lock
@@ -3098,6 +3098,16 @@ cyclist@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
||||
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
|
||||
|
||||
cypress-terminal-report@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cypress-terminal-report/-/cypress-terminal-report-5.0.2.tgz#923db46f06c4b32021c48da0177065ea1af2d999"
|
||||
integrity sha512-YJ6HODTvxKD0FYQX2p3f1DlBRcJcMJjRh3JWZZrBte4dQdnTuIElb4jPh3zbcqsV4MJ+QwF6XyJoXybZgg6kHg==
|
||||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
fs-extra "^10.1.0"
|
||||
semver "^7.3.5"
|
||||
tv4 "^1.3.0"
|
||||
|
||||
cypress@^12.0.2:
|
||||
version "12.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.0.2.tgz#0437abf9d97ad4a972ab554968d58211b0ce4ae5"
|
||||
@@ -4241,6 +4251,15 @@ fs-extra@3.0.1:
|
||||
jsonfile "^3.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
fs-extra@^10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
|
||||
integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-extra@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz"
|
||||
@@ -5852,6 +5871,13 @@ lru-cache@^5.1.1:
|
||||
dependencies:
|
||||
yallist "^3.0.2"
|
||||
|
||||
lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
make-dir@^1.0.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz"
|
||||
@@ -8124,6 +8150,13 @@ semver@^7.3.2:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
||||
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
||||
|
||||
semver@^7.3.5:
|
||||
version "7.3.8"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
|
||||
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
send@0.16.2:
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
|
||||
@@ -9247,6 +9280,11 @@ tunnel-agent@^0.6.0:
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
tv4@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/tv4/-/tv4-1.3.0.tgz#d020c846fadd50c855abb25ebaecc68fc10f7963"
|
||||
integrity sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==
|
||||
|
||||
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
version "0.14.5"
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||
|
||||
Reference in New Issue
Block a user