mirror of
https://github.com/RSS-Bridge/rss-bridge.git
synced 2024-11-22 01:25:28 +03:00
951092eef3
$ composer require --dev friendsofphp/php-cs-fixer $ echo >.php-cs-fixer.dist.php "<?php $finder = PhpCsFixer\Finder::create() ->in(__DIR__); $rules = [ '@PSR12' => true, // '@PSR12:risky' => true, '@PHP74Migration' => true, // '@PHP74Migration:risky' => true, // buggy, duplicates existing comment sometimes 'no_break_comment' => false, 'array_syntax' => true, 'lowercase_static_reference' => true, 'visibility_required' => false, // Too much noise 'binary_operator_spaces' => false, 'heredoc_indentation' => false, 'trailing_comma_in_multiline' => false, ]; $config = new PhpCsFixer\Config(); return $config ->setRules($rules) // ->setRiskyAllowed(true) ->setFinder($finder); " $ vendor/bin/php-cs-fixer --version PHP CS Fixer 3.8.0 BerSzcz against war! by Fabien Potencier and Dariusz Ruminski. PHP runtime: 8.1.7 $ vendor/bin/php-cs-fixer fix $ rm .php-cs-fixer.cache $ vendor/bin/php-cs-fixer fix
193 lines
6 KiB
PHP
193 lines
6 KiB
PHP
<?php
|
|
|
|
class ShanaprojectBridge extends BridgeAbstract
|
|
{
|
|
const MAINTAINER = 'logmanoriginal';
|
|
const NAME = 'Shanaproject Bridge';
|
|
const URI = 'https://www.shanaproject.com';
|
|
const DESCRIPTION = 'Returns a list of anime from the current Season Anime List';
|
|
const PARAMETERS = [
|
|
[
|
|
'min_episodes' => [
|
|
'name' => 'Minimum Episodes',
|
|
'type' => 'number',
|
|
'title' => 'Minimum number of episodes before including in feed',
|
|
'defaultValue' => 0,
|
|
],
|
|
'min_total_episodes' => [
|
|
'name' => 'Minimum Total Episodes',
|
|
'type' => 'number',
|
|
'title' => 'Minimum total number of episodes before including in feed',
|
|
'defaultValue' => 0,
|
|
],
|
|
'require_banner' => [
|
|
'name' => 'Require Banner',
|
|
'type' => 'checkbox',
|
|
'title' => 'Only include anime with custom banner image',
|
|
'defaultValue' => false,
|
|
],
|
|
],
|
|
];
|
|
|
|
private $uri;
|
|
|
|
public function getURI()
|
|
{
|
|
return $this->uri ?? parent::getURI();
|
|
}
|
|
|
|
public function collectData()
|
|
{
|
|
$html = $this->loadSeasonAnimeList();
|
|
|
|
$animes = $html->find('div.header_display_box_info')
|
|
or returnServerError('Could not find anime headers!');
|
|
|
|
$min_episodes = $this->getInput('min_episodes') ?: 0;
|
|
$min_total_episodes = $this->getInput('min_total_episodes') ?: 0;
|
|
|
|
foreach ($animes as $anime) {
|
|
[
|
|
$episodes_released,
|
|
/* of */,
|
|
$episodes_total
|
|
] = explode(' ', $this->extractAnimeEpisodeInformation($anime));
|
|
|
|
// Skip if not enough episodes yet
|
|
if ($episodes_released < $min_episodes) {
|
|
continue;
|
|
}
|
|
|
|
// Skip if too many episodes in total
|
|
if ($episodes_total !== '?' && $episodes_total < $min_total_episodes) {
|
|
continue;
|
|
}
|
|
|
|
// Skip if https://static.shanaproject.com/no-art.jpg
|
|
if (
|
|
$this->getInput('require_banner')
|
|
&& strpos($this->extractAnimeBackgroundImage($anime), 'no-art') !== false
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
$this->items[] = [
|
|
'title' => $this->extractAnimeTitle($anime),
|
|
'author' => $this->extractAnimeAuthor($anime),
|
|
'uri' => $this->extractAnimeUri($anime),
|
|
'timestamp' => $this->extractAnimeTimestamp($anime),
|
|
'content' => $this->buildAnimeContent($anime),
|
|
];
|
|
}
|
|
}
|
|
|
|
// Returns an html object for the Season Anime List (latest season)
|
|
private function loadSeasonAnimeList()
|
|
{
|
|
$html = getSimpleHTMLDOM(self::URI . '/seasons');
|
|
|
|
$html = defaultLinkTo($html, self::URI . '/seasons');
|
|
|
|
$season = $html->find('div.follows_menu > a', 1)
|
|
or returnServerError('Could not find \'Season Anime List\'!');
|
|
|
|
$html = getSimpleHTMLDOM($season->href);
|
|
|
|
$this->uri = $season->href;
|
|
|
|
$html = defaultLinkTo($html, $season->href);
|
|
|
|
return $html;
|
|
}
|
|
|
|
// Extracts the anime title
|
|
private function extractAnimeTitle($anime)
|
|
{
|
|
$title = $anime->find('a', 0)
|
|
or returnServerError('Could not find anime title!');
|
|
return trim($title->innertext);
|
|
}
|
|
|
|
// Extracts the anime URI
|
|
private function extractAnimeUri($anime)
|
|
{
|
|
$uri = $anime->find('a', 0)
|
|
or returnServerError('Could not find anime URI!');
|
|
return $uri->href;
|
|
}
|
|
|
|
// Extracts the anime release date (timestamp)
|
|
private function extractAnimeTimestamp($anime)
|
|
{
|
|
$timestamp = $anime->find('span.header_info_block', 1);
|
|
|
|
if (!$timestamp) {
|
|
return null;
|
|
}
|
|
|
|
return strtotime($timestamp->innertext);
|
|
}
|
|
|
|
// Extracts the anime studio name (author)
|
|
private function extractAnimeAuthor($anime)
|
|
{
|
|
$author = $anime->find('span.header_info_block', 2);
|
|
|
|
if (!$author) {
|
|
return null; // Sometimes the studio is unknown, so leave empty
|
|
}
|
|
|
|
return trim($author->innertext);
|
|
}
|
|
|
|
// Extracts the episode information (x of y released)
|
|
private function extractAnimeEpisodeInformation($anime)
|
|
{
|
|
$episode = $anime->find('div.header_info_episode', 0)
|
|
or returnServerError('Could not find anime episode information!');
|
|
|
|
$retVal = preg_replace('/\r|\n/', ' ', $episode->plaintext);
|
|
$retVal = preg_replace('/\s+/', ' ', $retVal);
|
|
|
|
return $retVal;
|
|
}
|
|
|
|
// Extracts the background image
|
|
private function extractAnimeBackgroundImage($anime)
|
|
{
|
|
// Getting the picture is a little bit tricky as it is part of the style.
|
|
// Luckily the style is part of the parent div :)
|
|
|
|
if (preg_match('/url\(\/\/([^\)]+)\)/i', $anime->parent->style, $matches)) {
|
|
return $matches[1];
|
|
}
|
|
|
|
returnServerError('Could not extract background image!');
|
|
}
|
|
|
|
// Builds an URI to search for a specific anime (subber is left empty)
|
|
private function buildAnimeSearchUri($anime)
|
|
{
|
|
return self::URI
|
|
. '/search/?title='
|
|
. urlencode($this->extractAnimeTitle($anime))
|
|
. '&subber=';
|
|
}
|
|
|
|
// Builds the content string for a given anime
|
|
private function buildAnimeContent($anime)
|
|
{
|
|
// We'll use a template string to place our contents
|
|
return '<a href="'
|
|
. $this->extractAnimeUri($anime)
|
|
. '"><img src="http://'
|
|
. $this->extractAnimeBackgroundImage($anime)
|
|
. '" alt="'
|
|
. htmlspecialchars($this->extractAnimeTitle($anime))
|
|
. '" style="border: 1px solid black"></a><br><p>'
|
|
. $this->extractAnimeEpisodeInformation($anime)
|
|
. '</p><br><p><a href="'
|
|
. $this->buildAnimeSearchUri($anime)
|
|
. '">Search episodes</a></p>';
|
|
}
|
|
}
|