text align tag + update/edit get desc + rating improve

This commit is contained in:
xiaomlove
2022-04-14 00:52:28 +08:00
parent d2a87ccda0
commit 9759c09320
44 changed files with 541 additions and 122 deletions
+9 -5
View File
@@ -36,6 +36,7 @@ use Illuminate\Support\Facades\Storage;
use JeroenG\Explorer\Domain\Syntax\Matching;
use JeroenG\Explorer\Infrastructure\Scout\ElasticEngine;
use Nexus\Database\NexusDB;
use Nexus\Imdb\Imdb;
use Rhilip\Bencode\Bencode;
class Test extends Command
@@ -118,14 +119,17 @@ class Test extends Command
// $r = $searchRep->deleteBookmark(1);
// $r = $searchRep->addBookmark(1);
$rep = new AttendanceRepository();
$uid = 1;
$attendance = $rep->getAttendance($uid);
// $rep = new AttendanceRepository();
// $uid = 1;
// $attendance = $rep->getAttendance($uid);
// $r = $rep->migrateAttendanceLogs($uid);
// $r = $rep->getContinuousDays($attendance);
$r = $rep->getContinuousPoints(11);
dd($r);
// $r = $rep->getContinuousPoints(11);
$url = 'https://www.imdb.com/title/tt4574334/?ref_=vp_vi_tt';
$imdb = new Imdb();
$rating = $imdb->getRating($url);
dd($rating);
}
+10
View File
@@ -4,9 +4,19 @@ namespace App\Models;
class Language extends NexusModel
{
const DEFAULT_ENABLED = ['en', 'chs', 'cht'];
protected $table = 'language';
protected $fillable = [
'lang_name', 'site_lang_folder',
];
public static function listEnabled($withoutCache = false)
{
if ($withoutCache) {
return Setting::getFromDb('main.site_language_enabled', self::DEFAULT_ENABLED);
}
return Setting::get('main.site_language_enabled', self::DEFAULT_ENABLED);
}
}
+2 -1
View File
@@ -25,7 +25,8 @@ class Torrent extends NexusModel
const BANNED_NO = 'no';
protected $casts = [
'added' => 'datetime'
'added' => 'datetime',
'pt_gen' => 'array',
];
public static $commentFields = [
+1 -3
View File
@@ -288,14 +288,12 @@ class class_cache_redis {
if (!$this->getIsEnabled()) {
return 0;
}
$this->redis->del($Key);
if ($AllLang){
$langfolder_array = $this->getLanguageFolderArray();
foreach($langfolder_array as $lf)
$this->redis->del($lf."_".$Key);
}
else {
$this->redis->del($Key);
}
}
function getCacheReadTimes() {
+2 -2
View File
@@ -1,6 +1,6 @@
<?php
defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.7.1');
defined('RELEASE_DATE') || define('RELEASE_DATE', '2022-04-12');
defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.7.2');
defined('RELEASE_DATE') || define('RELEASE_DATE', '2022-04-14');
defined('IN_TRACKER') || define('IN_TRACKER', true);
defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP");
defined('NEXUSPHPURL') || define("NEXUSPHPURL","https://nexusphp.org");
+75 -53
View File
@@ -6,9 +6,10 @@ function get_langfolder_cookie()
return $deflang;
} else {
$langfolder_array = get_langfolder_list();
$enabled = \App\Models\Language::listEnabled();
foreach($langfolder_array as $lf)
{
if($lf == $_COOKIE["c_lang_folder"])
if($lf == $_COOKIE["c_lang_folder"] && in_array($lf, $enabled))
return $_COOKIE["c_lang_folder"];
}
return $deflang;
@@ -278,20 +279,14 @@ function formatSpoiler($content, $title = '', $defaultCollapsed = true): string
'<div><div><div class="spoiler-title" title="%s">%s</div></div><div class="%s"><pre>%s</pre></div></div>',
$lang_functions['spoiler_expand_collapse'], $title, $contentClass, $content
);
$js = <<<JS
jQuery('.spoiler-title').on('click', function () {
let content = jQuery(this).parent().next();
if (content.hasClass('collapse')) {
content.height(content[0].scrollHeight).removeClass('collapse')
} else {
content.height(0).addClass('collapse')
}
})
JS;
\Nexus\Nexus::js($js, 'footer', false, 'spoiler');
return addTempCode($HTML);
}
function formatTextAlign($text, $align): string
{
return addTempCode(sprintf('<div style="text-align: %s">%s</div>', $align, $text));
}
function format_urls($text, $newWindow = false) {
// return preg_replace("/((https?|ftp|gopher|news|telnet|mms|rtsp):\/\/[^()\[\]<>\s]+)/ei", "formatUrl('\\1', ".($newWindow==true ? 1 : 0).", '', 'faqlink')", $text);
return preg_replace_callback("/((https?|ftp|gopher|news|telnet|mms|rtsp):\/\/[^()\[\]<>\s]+)/i", function ($matches) use ($newWindow) {
@@ -340,12 +335,12 @@ function format_comment($text, $strip_html = true, $xssclean = false, $newtab =
if ($enableimage) {
// $s = preg_replace("/\[img\]([^\<\r\n\"']+?)\[\/img\]/ei", "formatImg('\\1',".$imageresizer.",".$image_max_width.",".$image_max_height.")", $s, $imagenum, $imgReplaceCount);
$s = preg_replace_callback("/\[img\]([^\<\r\n\"']+?)\[\/img\]/i", function ($matches) use ($imageresizer, $image_max_width, $image_max_height) {
return formatImg($matches[1],".$imageresizer.",".$image_max_width.",".$image_max_height.");
return formatImg($matches[1],$imageresizer,$image_max_width,$image_max_height);
}, $s, $imagenum, $imgReplaceCount);
// $s = preg_replace("/\[img=([^\<\r\n\"']+?)\]/ei", "formatImg('\\1',".$imageresizer.",".$image_max_width.",".$image_max_height.")", $s, ($imagenum != -1 ? max($imagenum-$imgReplaceCount, 0) : -1));
$s = preg_replace_callback("/\[img=([^\<\r\n\"']+?)\]/i", function ($matches) use ($imageresizer, $image_max_width, $image_max_height) {
return formatImg($matches[1],".$imageresizer.",".$image_max_width.",".$image_max_height.");
return formatImg($matches[1],$imageresizer,$image_max_width,$image_max_height);
}, $s, ($imagenum != -1 ? max($imagenum-$imgReplaceCount, 0) : -1));
} else {
$s = preg_replace("/\[img\]([^\<\r\n\"']+?)\[\/img\]/i", '', $s, -1);
@@ -380,12 +375,6 @@ function format_comment($text, $strip_html = true, $xssclean = false, $newtab =
return formatYoutube($matches[4], $matches[2], $matches[3]);
}, $s);
}
//[spoiler=What happens to the hero?]The hero dies at the end![/spoiler]
if (str_contains($s, '[spoiler')) {
$s = preg_replace_callback("/\[spoiler(=(.*))?\](.*)\[\/spoiler\]/isU", function ($matches) {
return formatSpoiler($matches[3], $matches[2], nexus()->getScript() != 'preview');
}, $s);
}
// [url=http://www.example.com]Text[/url]
if ($adid) {
@@ -406,6 +395,22 @@ function format_comment($text, $strip_html = true, $xssclean = false, $newtab =
return formatUrl($matches[1], ".($newtab==true ? 1 : 0).", '', 'faqlink');
}, $s);
// [left]Left text[/left]
$s = preg_replace_callback("/\[left\](.*)\[\/left\]/isU", function ($matches) {
return formatTextAlign($matches[1], 'left');
}, $s);
// [center]Center text[/center]
$s = preg_replace_callback("/\[center\](.*)\[\/center\]/isU", function ($matches) {
return formatTextAlign($matches[1], 'center');
}, $s);
// [right]Right text[/right]
$s = preg_replace_callback("/\[right\](.*)\[\/right\]/isU", function ($matches) {
return formatTextAlign($matches[1], 'right');
}, $s);
$s = format_urls($s, $newtab);
// Quotes
if (strpos($s,"[quote") !== false && strpos($s,"[/quote]") !== false) { //format_quote is kind of slow. Better check if [quote] exists beforehand
@@ -417,6 +422,14 @@ function format_comment($text, $strip_html = true, $xssclean = false, $newtab =
$smile = get_smile($matches[1]);
return $smile ? '<img src="'.$smile.'" alt="[em' . $matches[1] . ']" />' : '[em' . $matches[1] . ']';
}, $s);
//[spoiler=What happens to the hero?]The hero dies at the end![/spoiler]
if (str_contains($s, '[spoiler')) {
$s = preg_replace_callback("/\[spoiler(=(.*))?\](.*)\[\/spoiler\]/isU", function ($matches) {
return formatSpoiler($matches[3], $matches[2], nexus()->getScript() != 'preview');
}, $s);
}
reset($tempCode);
$j = $i = 0;
while(count($tempCode) || $j > 5) {
@@ -1139,8 +1152,15 @@ function get_external_tr($imdb_url = "")
{
global $lang_functions;
global $showextinfo;
if ($showextinfo['imdb'] != 'yes') {
return '';
}
$ptGen = new Nexus\PTGen\PTGen();
$imdbNumber = parse_imdb_id($imdb_url);
($showextinfo['imdb'] == 'yes' ? tr($lang_functions['row_imdb_url'], "<input type=\"text\" style=\"width: 99%;\" name=\"url\" value=\"".($imdbNumber ? "http://www.imdb.com/title/tt".parse_imdb_id($imdb_url) : "")."\" /><br /><font class=\"medium\">".$lang_functions['text_imdb_url_note']."</font>", 1) : "");
$y = $ptGen->buildInput("url", $imdbNumber ? "http://www.imdb.com/title/tt".parse_imdb_id($imdb_url) : "", $lang_functions['text_imdb_url_note'], $lang_functions['pt_gen_get_description']);
return tr($lang_functions['row_imdb_url'], $y, 1);
// ($showextinfo['imdb'] == 'yes' ? tr($lang_functions['row_imdb_url'], "<input type=\"text\" style=\"width: 99%;\" name=\"url\" value=\"".($imdbNumber ? "http://www.imdb.com/title/tt".parse_imdb_id($imdb_url) : "")."\" /><br /><font class=\"medium\">".$lang_functions['text_imdb_url_note']."</font>", 1) : "");
}
function get_torrent_extinfo_identifier($torrentid)
@@ -2431,19 +2451,19 @@ if ($CURUSER){
}
?>
<link rel="alternate" type="application/rss+xml" title="Latest Torrents" href="torrentrss.php" />
<script type="text/javascript" src="curtain_imageresizer.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="ajaxbasic.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="common.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="domLib.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="domTT.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="domTT_drag.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="fadomatic.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="js/curtain_imageresizer.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="js/ajaxbasic.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="js/common.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="js/domLib.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="js/domTT.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="js/domTT_drag.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="js/fadomatic.js<?php echo $cssupdatedate?>"></script>
<?php
foreach (\Nexus\Nexus::getAppendHeaders() as $value) {
print($value);
}
?>
<script type="text/javascript" src="jquery-1.12.4.min.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript" src="js/jquery-1.12.4.min.js<?php echo $cssupdatedate?>"></script>
<script type="text/javascript">jQuery.noConflict();</script>
</head>
<body>
@@ -2770,15 +2790,16 @@ function stdfoot() {
foreach (\Nexus\Nexus::getAppendFooters() as $value) {
print($value);
}
$backToTop = <<<TOTOP
<script type="application/javascript" src="/vendor/jquery-goup-1.1.3/jquery.goup.min.js"></script>
$js = <<<JS
<script type="application/javascript" src="js/nexus.js"></script>
<script type="application/javascript" src="vendor/jquery-goup-1.1.3/jquery.goup.min.js"></script>
<script>
jQuery(document).ready(function(){
jQuery.goup();
jQuery.goup()
});
</script>
TOTOP;
print($backToTop);
JS;
print($js);
print("</body></html>");
//echo replacePngTags(ob_get_clean());
@@ -3094,16 +3115,24 @@ function searchbox_item_list($table = "sources"){
return $ret;
}
function langlist($type) {
function langlist($type, $enabled = null) {
global $Cache;
if (!$ret = $Cache->get_value($type.'_lang_list')){
$ret = array();
$res = sql_query("SELECT id, lang_name, flagpic, site_lang_folder FROM language WHERE ". $type ."=1 ORDER BY site_lang DESC, id ASC");
while ($row = mysql_fetch_array($res))
$ret[] = $row;
$Cache->cache_value($type.'_lang_list', $ret, 152800);
}
return $ret;
$cacheKey = $type.'_lang_list';
return \Nexus\Database\NexusDB::remember($cacheKey, 600, function () use ($type, $enabled) {
$query = \App\Models\Language::query()->where($type, 1);
if ($enabled !== null) {
$query->whereIn('site_lang_folder', \App\Models\Language::listEnabled(true));
}
return $query->get()->toArray();
});
// if (!$ret = $Cache->get_value($type.'_lang_list')){
// $ret = array();
// $res = sql_query("SELECT id, lang_name, flagpic, site_lang_folder FROM language WHERE ". $type ."=1 ORDER BY site_lang DESC, id ASC");
// while ($row = mysql_fetch_array($res))
// $ret[] = $row;
// $Cache->cache_value($type.'_lang_list', $ret, 152800);
// }
// return $ret;
}
function linkcolor($num) {
@@ -3169,11 +3198,6 @@ function torrenttable($rows, $variant = "torrent") {
global $torrentmanage_class, $smalldescription_main, $enabletooltip_tweak;
global $CURLANGDIR;
$setting = get_setting('main');
$enablePtGen = $setting['enable_pt_gen_system'] == 'yes';
$enableImdb = $setting['showimdbinfo'] == 'yes';
$ptGen = new Nexus\PTGen\PTGen();
$imdb = new Nexus\Imdb\Imdb();
$torrent = new Nexus\Torrent\Torrent();
$torrentIdArr = array_column($rows, 'id');
$torrentSeedingLeechingStatus = $torrent->listLeechingSeedingStatus($CURUSER['id'], $torrentIdArr);
@@ -3406,11 +3430,9 @@ foreach ($rows as $row)
echo $torrent->renderProgressBar($torrentSeedingLeechingStatus[$row['id']]['active_status'], $torrentSeedingLeechingStatus[$row['id']]['progress']);
}
print("</td>");
if ($enablePtGen && !empty($row['pt_gen'])) {
echo $ptGen->renderTorrentsPageAverageRating(json_decode($row['pt_gen'], true));
} elseif ($enableImdb) {
echo $imdb->renderTorrentsPageAverageRating($row['url']);
}
echo $torrent->renderTorrentsPageAverageRating($row);
$act = "";
if ($CURUSER["dlicon"] != 'no' && $CURUSER["downloadpos"] != "no")
$act .= "<a href=\"download.php?id=".$id."\"><img class=\"download\" src=\"pic/trans.gif\" style='padding-bottom: 2px;' alt=\"download\" title=\"".$lang_functions['title_download_torrent']."\" /></a>" ;
+1
View File
@@ -322,6 +322,7 @@ $lang_functions = array
'text_seed_points' => '做种积分',
'spoiler_expand_collapse' => '点击展开/收缩',
'spoiler_default_title' => '折叠内容',
'pt_gen_get_description' => '获取简介',
);
?>
+3
View File
@@ -736,6 +736,9 @@ $lang_settings = array
'text_attendance_continuous_add_rules' => '请请从小到大添加规则',
'row_attendance_card' => '购买补签卡',
'text_attendance_card_note' => "个魔力值,如果他需要购买一张补签卡。默认'" . \App\Models\BonusLogs::DEFAULT_BONUS_BUY_ATTENDANCE_CARD . "'。",
'row_site_language_enabled' => '站点启用语言',
'text_site_language_enabled_note' => '选择站点启用的语言',
'keep_at_least_one' => '至少保留一个',
);
?>
+15
View File
@@ -133,6 +133,21 @@ $lang_tags = array
'text_spoiler_description' => '在页面插入可展开/收缩的内容',
'text_spoiler_syntax' => '[spoiler=标题]这是被折叠的内容[/spoiler]',
'text_spoiler_example' => '[spoiler=英雄最后的结局怎么样了?]英雄最后死掉了![/spoiler]',
'text_left' => '靠左对齐',
'text_left_description' => '在页面插入靠左对齐的内容',
'text_left_syntax' => '[left]这是靠左对齐的内容[/left]',
'text_left_example' => '[left]这是靠左对齐的内容[/left]',
'text_center' => '居中对齐',
'text_center_description' => '在页面插入居中对齐的内容',
'text_center_syntax' => '[center]这是居中对齐的内容[/center]',
'text_center_example' => '[center]这是居中对齐的内容[/center]',
'text_right' => '靠右对齐',
'text_right_description' => '在页面插入靠右对齐的内容',
'text_right_syntax' => '[right]这是靠右对齐的内容[/right]',
'text_right_example' => '[right]这是靠右对齐的内容[/right]',
);
?>
+1
View File
@@ -323,6 +323,7 @@ $lang_functions = array
'text_seed_points' => '做種積分',
'spoiler_expand_collapse' => '點擊展開/收縮',
'spoiler_default_title' => '折疊內容',
'pt_gen_get_description' => '獲取簡介',
);
?>
+3
View File
@@ -735,6 +735,9 @@ $lang_settings = array
'text_attendance_continuous_add_rules' => '請請從小到大添加規則',
'row_attendance_card' => '購買補簽卡',
'text_attendance_card_note' => "個魔力值,如果他需要購買一張補簽卡。默認'" . \App\Models\BonusLogs::DEFAULT_BONUS_BUY_ATTENDANCE_CARD . "'。",
'row_site_language_enabled' => '站點啟用語言',
'text_site_language_enabled_note' => '選擇站點啟用的語言',
'keep_at_least_one' => '至少保留一個',
);
?>
+15
View File
@@ -134,6 +134,21 @@ $lang_tags = array
'text_spoiler_syntax' => '[spoiler=標題]這是被折疊的內容[/spoiler]',
'text_spoiler_example' => '[spoiler=英雄最後的結局怎麽樣了?]英雄最後死掉了![/spoiler]',
'text_left' => '靠左對齊',
'text_left_description' => '在頁面插入靠左對齊的內容',
'text_left_syntax' => '[left]這是靠左對齊的內容[/left]',
'text_left_example' => '[left]這是靠左對齊的內容[/left]',
'text_center' => '居中對齊',
'text_center_description' => '在頁面插入居中對齊的內容',
'text_center_syntax' => '[center]這是居中對齊的內容[/center]',
'text_center_example' => '[center]這是居中對齊的內容[/center]',
'text_right' => '靠右對齊',
'text_right_description' => '在頁面插入靠右對齊的內容',
'text_right_syntax' => '[right]這是靠右對齊的內容[/right]',
'text_right_example' => '[right]這是靠右對齊的內容[/right]',
);
?>
+1
View File
@@ -324,6 +324,7 @@ $lang_functions = array
'text_seed_points' => 'Seed points',
'spoiler_expand_collapse' => 'Click to expand/collapse',
'spoiler_default_title' => 'Collapse content',
'pt_gen_get_description' => 'Get desc',
);
?>
+3
View File
@@ -735,6 +735,9 @@ $lang_settings = array
'text_attendance_continuous_add_rules' => 'Please add rules from lowest to highest',
'row_attendance_card' => 'Buy attendance card',
'text_attendance_card_note' => "bonus points to buy a attendance card. Default'" . \App\Models\BonusLogs::DEFAULT_BONUS_BUY_ATTENDANCE_CARD . "'.",
'row_site_language_enabled' => 'Site enabled language',
'text_site_language_enabled_note' => 'Select site enabled language',
'keep_at_least_one' => 'Keep at least one',
);
?>
+15
View File
@@ -133,6 +133,21 @@ $lang_tags = array
'text_spoiler_description' => 'Insert expandable/collapsible content on the page',
'text_spoiler_syntax' => '[spoiler=title]This is the folded content[/spoiler]',
'text_spoiler_example' => '[spoiler=What happened to the final ending of the hero?]The hero died last![/spoiler]',
'text_left' => 'Text align left',
'text_left_description' => 'Insert left-justified content on the page',
'text_left_syntax' => '[left]This is the left-aligned content[/left]',
'text_left_example' => '[left]This is the left-aligned content[/left]',
'text_center' => 'Text align center',
'text_center_description' => 'Insert center-justified content on the page',
'text_center_syntax' => '[center]This is the center-aligned content[/center]',
'text_center_example' => '[center]This is the center-aligned content[/center]',
'text_right' => 'Text align right',
'text_right_description' => 'Insert right-justified content on the page',
'text_right_syntax' => '[right]This is the right-aligned content[/right]',
'text_right_example' => '[right]This is the right-aligned content[/right]',
);
?>
+2 -2
View File
@@ -276,10 +276,10 @@ class NexusDB
$result = $Cache->get_value($key);
if ($result === false) {
$result = $callback();
do_log("cache miss [$key]" );
do_log("cache miss [$key]", 'debug');
$Cache->cache_value($key, $result, $ttl);
} else {
do_log("cache hit [$key]");
do_log("cache hit [$key]", 'debug');
}
return $result;
} else {
+7 -2
View File
@@ -262,7 +262,12 @@ class Imdb
}
public function renderTorrentsPageAverageRating($imdbId)
public function renderTorrentsPageAverageRating($imdbId): string
{
return $this->getPtGen()->buildRatingSpan([PTGen::SITE_IMDB => $this->getRating($imdbId)]);
}
public function getRating($imdbId): float|string
{
$imdbId = parse_imdb_id($imdbId);
$defaultRating = $rating = 'N/A';
@@ -273,7 +278,7 @@ class Imdb
if (!is_numeric($rating)) {
$rating = $defaultRating;
}
return $this->getPtGen()->buildRatingSpan([PTGen::SITE_IMDB => $rating]);
return $rating;
}
public function getPtGen()
+9 -2
View File
@@ -128,7 +128,7 @@ class Install
public function listRequirementTableRows()
{
$gdInfo = function_exists('gd_info') ? gd_info() : [];
$extensions = ['ctype', 'fileinfo', 'json', 'mbstring', 'openssl', 'pdo_mysql', 'tokenizer', 'xml', 'mysqli', 'bcmath', 'redis', 'gd', 'pcntl', 'sockets', 'posix'];
$extensions = ['ctype', 'fileinfo', 'json', 'mbstring', 'openssl', 'pdo_mysql', 'tokenizer', 'xml', 'mysqli', 'bcmath', 'redis', 'gd', 'sockets', 'posix'];
$tableRows = [];
$tableRows[] = [
'label' => 'PHP version',
@@ -140,10 +140,17 @@ class Install
$tableRows[] = [
'label' => "PHP extension $extension",
'required' => 'enabled',
'current' => extension_loaded($extension),
'current' => (int)extension_loaded($extension),
'result' => $this->yesOrNo(extension_loaded($extension)),
];
}
$tableRows[] = [
'label' => 'PHP extension pcntl',
'required' => 'true',
'current' => (int)extension_loaded($extension),
'result' => "If 'current' showing 0, make sure it's on php -m",
];
$tableRows[] = [
'label' => 'PHP extension gd JPEG Support',
'required' => 'true',
+1
View File
@@ -88,6 +88,7 @@ return array (
'pt_gen_api_point' => '',
'enable_pt_gen_system' => 'no',
'enable_technical_info' => 'no',
'site_language_enabled' => \App\Models\Language::DEFAULT_ENABLED,
),
'smtp' =>
array (
+161 -31
View File
@@ -8,8 +8,10 @@
*/
namespace Nexus\PTGen;
use App\Models\Torrent;
use GuzzleHttp\Client;
use Illuminate\Support\Str;
use Nexus\Imdb\Imdb;
class PTGen
{
@@ -19,16 +21,18 @@ class PTGen
const SITE_IMDB = 'imdb';
const SITE_BANGUMI = 'bangumi';
private static $validSites = [
public static array $validSites = [
self::SITE_IMDB => [
'url_pattern' => '/(?:https?:\/\/)?(?:www\.)?imdb\.com\/title\/(tt\d+)\/?/',
'home_page' => 'https://www.imdb.com/',
'rating_average_img' => 'pic/imdb2.png',
'rating_pattern_in_desc' => "/IMDb评分.*([\d\.]+)\//isU",
],
self::SITE_DOUBAN => [
'url_pattern' => '/(?:https?:\/\/)?(?:(?:movie|www)\.)?douban\.com\/(?:subject|movie)\/(\d+)\/?/',
'home_page' => 'https://www.douban.com/',
'rating_average_img' => 'pic/douban2.png',
'rating_pattern_in_desc' => "/豆瓣评分.*([\d\.]+)\//isU",
],
self::SITE_BANGUMI => [
'url_pattern' => '/(?:https?:\/\/)?(?:bgm\.tv|bangumi\.tv|chii\.in)\/subject\/(\d+)\/?/',
@@ -51,7 +55,7 @@ class PTGen
public function setApiPoint(string $apiPoint)
{
$this->apiPoint = $apiPoint;
$this->apiPoint = trim($apiPoint);
}
public function generate(string $url, bool $withoutCache = false): array
@@ -63,7 +67,7 @@ class PTGen
} else {
$targetUrl .= "?";
}
$targetUrl .= sprintf('site=%s&sid=%s', $parsed['site'] , $parsed['id']);
$targetUrl .= sprintf('site=%s&sid=%s&url=%s', $parsed['site'] , $parsed['id'], urlencode($parsed['url']));
return $this->request($targetUrl, $withoutCache);
}
@@ -81,24 +85,39 @@ class PTGen
throw new PTGenException("invalid url: $url");
}
private function buildDetailsPageTableRow($torrentId, $ptGenArr, $site)
private function buildDetailsPageTableRow($torrentId, $ptGenArr, $site): string
{
global $lang_details;
$ptGenFormatted = $ptGenArr['format'];
if ($this->isRawPTGen($ptGenArr)) {
$ptGenFormatted = $ptGenArr['format'];
} elseif ($this->isIyuu($ptGenArr)) {
$ptGenFormatted = $ptGenArr['data']['format'];
} else {
do_log("Invalid pt gen data", 'error');
return '';
}
$poster = '';
if (!empty($ptGenArr['poster'])) {
$poster = $ptGenArr['poster'];
} elseif (preg_match('/\[img\](.*)\[\/img\]/iU', $ptGenFormatted, $matches)) {
$poster = $matches[1];
}
if ($poster) {
$prefix = sprintf("[img]%s[/img]\n", $poster);
$ptGenFormatted = mb_substr($ptGenFormatted, mb_strlen($prefix, 'utf-8') + 1);
}
$ptGenFormatted = format_comment($ptGenFormatted);
$ptGenFormatted .= sprintf(
'%s%s%s<a href="retriver.php?id=%s&type=1&siteid=%s">%s</a>',
$lang_details['text_information_updated_at'], !empty($ptGenArr['generate_at']) ? date('Y-m-d H:i:s', intval($ptGenArr['generate_at'] / 1000)) : '', $lang_details['text_might_be_outdated'],
'%s %s%s<a href="retriver.php?id=%s&type=1&siteid=%s">%s</a>',
$lang_details['text_information_updated_at'], $ptGenArr['__updated_at'], $lang_details['text_might_be_outdated'],
$torrentId, $site, $lang_details['text_here_to_update']
);
$titleShowOrHide = $lang_details['title_show_or_hide'] ?? '';
$id = 'pt-gen-' . $site;
$posterHtml = "";
if ($poster) {
$posterHtml = sprintf('<div id="poster%s"><img src="%s" width="105" onclick="Preview(this);" title="%s"', $id, $poster, $titleShowOrHide);
}
$html = <<<HTML
<tr>
<td class="rowhead">
@@ -108,9 +127,7 @@ class PTGen
PT-Gen-{$site}
</span>
</a>
<div id="poster{$id}">
<img src="{$poster}" width="105" onclick="Preview(this);" alt="poster" />
</div>
$posterHtml
</td>
<td class="rowfollow" align="left">
<div id="k{$id}">
@@ -156,14 +173,16 @@ HTML;
do_log("$logPrefix, $msg");
throw new PTGenException($msg);
}
if (!isset($bodyArr['success']) || !$bodyArr['success']) {
if ($this->isRawPTGen($bodyArr) || $this->isIyuu($bodyArr)) {
$Cache->cache_value($cacheKey, $bodyArr, 24 * 3600);
do_log("$logPrefix, success get from api point, use time: " . (microtime(true) - $begin));
$bodyArr['__updated_at'] = now()->toDateTimeString();
return $bodyArr;
} else {
$msg = "error: " . $bodyArr['error'] ?? '';
do_log("$logPrefix, response: $bodyString");
throw new PTGenException($msg);
}
$Cache->cache_value($cacheKey, $bodyArr, 24 * 3600);
do_log("$logPrefix, success get from api point, use time: " . (microtime(true) - $begin));
return $bodyArr;
}
public function deleteApiPointResultCache($url)
@@ -185,12 +204,30 @@ HTML;
foreach (self::$validSites as $site => $info) {
$value = $ptGen[$site]['link'] ?? '';
$x = $lang_functions["row_pt_gen_{$site}_url"];
$y = "<input type=\"text\" style=\"width: 650px;\" name=\"pt_gen[{$site}][link]\" value=\"{$value}\" /><br /><font class=\"medium\">".$lang_functions["text_pt_gen_{$site}_url_note"]."</font>";
$y = $this->buildInput("pt_gen[{$site}][link]", $value, $lang_functions["text_pt_gen_{$site}_url_note"], $lang_functions['pt_gen_get_description']);
$html .= tr($x, $y, 1);
}
return $html;
}
public function buildInput($name, $value, $note, $btnText): string
{
$btn = '';
if ($this->apiPoint != '') {
$btn = '<div><input type="button" class="btn-get-pt-gen" value="'.$btnText.'"></div>';
}
$input = <<<HTML
<div style="display: flex">
<div style="display: flex;flex-direction: column;flex-grow: 1">
<input type="text" name="$name" value="{$value}" data-pt-gen="$name">
<span class="medium">{$note}</span>
</div>
$btn
</div>
HTML;
return $input;
}
public function renderDetailsPageDescription($torrentId, $torrentPtGenArr): array
{
$html = '';
@@ -233,21 +270,7 @@ HTML;
return ['json_arr' => $jsonArr, 'html' => $html, 'update' => $update];
}
public function renderTorrentsPageAverageRating($ptGenData)
{
$siteIdAndRating = [];
$ptGenData = (array)$ptGenData;
foreach (self::$validSites as $site => $info) {
$rating = $ptGenData[$site]['data']["{$site}_rating_average"] ?? '';
if (empty($rating)) {
continue;
}
$siteIdAndRating[$site] = $rating;
}
return $this->buildRatingSpan($siteIdAndRating);
}
public function buildRatingSpan(array $siteIdAndRating)
public function buildRatingSpan(array $siteIdAndRating): string
{
$result = '<td class="embedded" style="text-align: right; width: 40px;padding: 4px"><div style="display: flex;flex-direction: column">';
$count = 1;
@@ -275,12 +298,119 @@ HTML;
return $result;
}
public function getRatingIcon($siteId, $rating)
public function getRatingIcon($siteId, $rating): string
{
if (is_numeric($rating)) {
$rating = number_format($rating, 1);
}
$result = sprintf(
'<div style="display: flex;align-content: center;justify-content: space-between;padding: 2px 0"><img src="%s" alt="%s" title="%s" style="max-width: 16px;max-height: 16px"/><span>%s</span></div>',
self::$validSites[$siteId]['rating_average_img'], $siteId, $siteId, $rating
);
return $result;
}
public function isRawPTGen(array $bodyArr): bool
{
return isset($bodyArr['success']) && $bodyArr['success'];
}
public function isIyuu(array $bodyArr): bool
{
return isset($bodyArr['ret']) && $bodyArr['ret'] == 200;
}
public function listRatings(array $ptGenData, string $imdbLink, string $desc = ''): array
{
$results = [];
$log = "";
//First, get from PTGen
foreach (self::$validSites as $site => $info) {
if (!isset($ptGenData[$site]['data'])) {
continue;
}
$data = $ptGenData[$site]['data'];
$log .= ", handling site: $site";
$rating = '';
if (isset($data['__rating'])) {
//__rating is new add
$rating = $data['__rating'];
$log .= ", from __rating";
} else {
// from original structure fetch
if ($this->isRawPTGen($data)) {
$log .= ", isRawPTGen";
$rating = $data["{$site}_rating_average"] ?? '';
} elseif ($this->isIyuu($data)) {
$log .= ", isIyuu";
$pattern = $info['rating_pattern_in_desc'] ?? null;
if ($pattern && preg_match($pattern,$data['data']['format'], $matches)) {
$rating = $matches[1];
}
}
}
if (!empty($rating)) {
$results[$site] = $rating;
$log .= ", get rating: $rating";
} else {
$log .= ", can't get rating";
}
}
//Second, imdb can get from imdb api
if (!isset($results[self::SITE_IMDB]) && !empty($imdbLink)) {
$imdb = new Imdb();
$imdbRating = $imdb->getRating($imdbLink);
$results[self::SITE_IMDB] = $imdbRating;
$log .= ", again 'imdb' from: $imdbLink} -> $imdbRating";
}
//Otherwise, get from desc
if (!empty($desc)) {
foreach (self::$validSites as $site => $info) {
if (isset($results[$site])) {
continue;
}
if (empty($info['rating_pattern_in_desc'])) {
continue;
}
$pattern = $info['rating_pattern_in_desc'];
$log .= ", at last, trying to get '$site' from desc with pattern: $pattern";
if (preg_match($pattern, $desc, $matches)) {
$log .= ", get " . $matches[1];
$results[$site] = $matches[1];
} else {
$log .= ", not match";
}
}
}
do_log($log);
return $results;
}
public function updateTorrentPtGen(array $torrentInfo, $siteId = null)
{
$ptGenInfo = json_decode($torrentInfo['pt_gen'], true);
foreach (self::$validSites as $site => $siteConfig) {
if ($siteId !== null && $siteId != $site) {
//If specific, only update it
continue;
}
if (empty($ptGenInfo[$site]['link'])) {
do_log("site: $site no link...");
continue;
}
try {
$response = $this->generate($ptGenInfo[$site]['link'], true);
$ptGenInfo[$site]['data'] = $response;
} catch (\Exception $exception) {
do_log("site: $site can not be updated: " . $exception->getMessage(), 'error');
}
}
$siteIdAndRating = $this->listRatings($ptGenInfo, $torrentInfo['url'], $torrentInfo['descr']);
foreach ($siteIdAndRating as $key => $value) {
$ptGenInfo[$key]['data']["__rating"] = $value;
}
Torrent::query()->where('id', $torrentInfo['id'])->update(['pt_gen' => $ptGenInfo]);
return $ptGenInfo;
}
}
+19 -1
View File
@@ -2,7 +2,10 @@
namespace Nexus\Torrent;
use App\Models\Setting;
use Nexus\Database\NexusDB;
use Nexus\Imdb\Imdb;
use Nexus\PTGen\PTGen;
class Torrent
{
@@ -49,7 +52,7 @@ class Torrent
return $snatchedList;
}
public function renderProgressBar($activeStatus, $progress)
public function renderProgressBar($activeStatus, $progress): string
{
$color = '#aaa';
if ($activeStatus == 'seeding') {
@@ -64,4 +67,19 @@ class Torrent
);
return $result;
}
public function renderTorrentsPageAverageRating(array $torrentInfo): string
{
static $ptGen;
if (is_null($ptGen)) {
$ptGen = new PTGen();
}
$ptGenInfo = json_decode($torrentInfo['pt_gen'], true);
$log = "torrent: " . $torrentInfo['id'];
$siteIdAndRating = $ptGen->listRatings($ptGenInfo, $torrentInfo['url']);
$log .= "siteIdAndRating: " . json_encode($siteIdAndRating);
do_log($log);
return $ptGen->buildRatingSpan($siteIdAndRating);
}
}
+13
View File
@@ -34,3 +34,16 @@ function attendanceRetroactive($params)
return $rep->retroactive($CURUSER['id'], $params['timestamp']);
}
function getPtGen($params)
{
$rep = new Nexus\PTGen\PTGen();
$result = $rep->generate($params['url']);
if ($rep->isRawPTGen($result)) {
return $result['format'];
} elseif ($rep->isIyuu($result)) {
return $result['data']['format'];
} else {
return '';
}
}
+2 -2
View File
@@ -207,7 +207,7 @@ if (!$row) {
{
$thenumbers = $imdb_id;
$Cache->new_page('imdb_id_'.$thenumbers.'_large', 1296000, true);
$Cache->new_page('imdb_id_'.$thenumbers.'_large', 3600*24, true);
if (!$Cache->get_page()){
switch ($imdb->getCacheStatus($imdb_id))
{
@@ -225,7 +225,7 @@ if (!$row) {
if (($photo_url = $movie->photo() ) != FALSE)
$smallth = "<img src=\"".$photo_url. "\" width=\"105\" onclick=\"Preview(this);\" alt=\"poster\" />";
else
$smallth = "<img src=\"pic/nophoto.gif\" alt=\"no poster\" />";
$smallth = "<img src=\"pic/imdb_pic/nophoto.gif\" alt=\"no poster\" />";
$autodata = $imdb->renderDetailsPageDescription($row['id'], $imdb_id);
$cache_time = $imdb->getCachedAt($imdb_id);
+2
View File
@@ -267,6 +267,8 @@ jQuery(function($){
</script>
EOT;
}
\Nexus\Nexus::js('vendor/jquery-loading/jquery.loading.min.js', 'footer', true);
\Nexus\Nexus::js('js/ptgen.js', 'footer', true);
stdfoot();
function getAddedTimeOption($timeStamp, $addSeconds) {
$timeStamp += $addSeconds;
View File
View File
View File
View File
View File
View File
View File
+10
View File
@@ -0,0 +1,10 @@
;
jQuery('.spoiler-title').on('click', function () {
let content = jQuery(this).parent().next();
if (content.hasClass('collapse')) {
content.height(content[0].scrollHeight).removeClass('collapse')
} else {
content.height(0).addClass('collapse')
}
});
+22
View File
@@ -0,0 +1,22 @@
jQuery('.btn-get-pt-gen').on('click', function () {
let input = jQuery(this).closest('td').find('[data-pt-gen]')
let value = input.val().trim()
if (value == '') {
return
}
let params = {
action: 'getPtGen',
params: {url: value}
}
jQuery('body').loading({
stoppable: false
});
jQuery.post('ajax.php', params, function (response) {
jQuery('body').loading('stop');
if (response.ret != 0) {
alert(response.msg)
return
}
doInsert(response.data, '', false)
}, 'json')
})
View File
+6 -3
View File
@@ -6,10 +6,14 @@ $langid = intval($_GET['sitelanguage'] ?? 0);
if ($langid)
{
$lang_folder = validlang($langid);
$enabled = \App\Models\Language::listEnabled();
if (!in_array($lang_folder, $enabled)) {
nexus_redirect(getBaseUrl());
}
if(get_langfolder_cookie() != $lang_folder)
{
set_langfolder_cookie($lang_folder);
header("Location: " . $_SERVER['REQUEST_URI']);
nexus_redirect($_SERVER['REQUEST_URI']);
}
}
require_once(get_langfile_path("", false, $CURLANGDIR));
@@ -20,8 +24,7 @@ stdhead($lang_login['head_login']);
$s = "<select name=\"sitelanguage\" onchange='submit()'>\n";
$langs = langlist("site_lang");
$langs = langlist("site_lang", true);
foreach ($langs as $row)
{
if ($row["site_lang_folder"] == get_langfolder_cookie()) $se = "selected=\"selected\""; else $se = "";
+5 -9
View File
@@ -12,7 +12,7 @@ $siteid = $_GET["siteid"] ?? 0; // 1 for IMDb
if (!isset($id) || !$id || !is_numeric($id) || !isset($type) || !$type || !is_numeric($type) || !isset($siteid) || !$siteid)
die();
$r = sql_query("SELECT id, url, pt_gen from torrents WHERE id = " . sqlesc($id)) or sqlerr(__FILE__, __LINE__);
$r = sql_query("SELECT * from torrents WHERE id = " . sqlesc($id)) or sqlerr(__FILE__, __LINE__);
if(mysql_num_rows($r) != 1)
die();
@@ -20,7 +20,7 @@ $row = mysql_fetch_assoc($r);
switch ($siteid)
{
case 1 :
case 1 :
{
$imdb_id = parse_imdb_id($row["url"]);
if ($imdb_id)
@@ -41,7 +41,7 @@ switch ($siteid)
$log = $e->getMessage() . ", trace: " . $e->getTraceAsString();
do_log($log, 'error');
}
header("Location: " . get_protocol_prefix() . "$BASEURL/details.php?id=".htmlspecialchars($id));
nexus_redirect(getSchemeAndHttpHost() . "/details.php?id=$id");
}
break;
}
@@ -49,18 +49,14 @@ switch ($siteid)
case \Nexus\PTGen\PTGen::SITE_DOUBAN:
case \Nexus\PTGen\PTGen::SITE_BANGUMI:
{
$ptGenInfo = json_decode($row['pt_gen'], true);
$link = $ptGenInfo[$siteid]['link'];
$ptGen = new \Nexus\PTGen\PTGen();
try {
$result = $ptGen->generate($link, true);
$ptGenInfo[$siteid]['data'] = $result;
sql_query(sprintf("update torrents set pt_gen = %s where id = %s", sqlesc(json_encode($ptGenInfo)), $id)) or sqlerr(__FILE__, __LINE__);
$ptGen->updateTorrentPtGen($row, $siteid);
} catch (\Exception $e) {
$log = $e->getMessage() . ", trace: " . $e->getTraceAsString();
do_log($log, 'error');
}
header("Location: " . get_protocol_prefix() . "$BASEURL/details.php?id=".htmlspecialchars($id));
nexus_redirect(getSchemeAndHttpHost() . "/details.php?id=$id");
break;
}
default :
+43 -4
View File
@@ -41,7 +41,7 @@ if ($action == 'savesettings_main') // save main
'showpolls','showstats','showlastxtorrents', 'showtrackerload','showshoutbox','showfunbox','showoffer','sptime','showhelpbox','enablebitbucket',
'smalldescription','altname','extforum','extforumurl','defaultlang','defstylesheet', 'donation','spsct','browsecat','specialcat','waitsystem',
'maxdlsystem','bitbucket','torrentnameprefix', 'showforumstats','verification','invite_count','invite_timeout', 'seeding_leeching_time_calc_start',
'startsubid', 'logo', 'showlastxforumposts', 'enable_technical_info'
'startsubid', 'logo', 'showlastxforumposts', 'enable_technical_info', 'site_language_enabled'
);
GetVar($validConfig);
$MAIN = [];
@@ -54,6 +54,7 @@ if ($action == 'savesettings_main') // save main
$Cache->delete_value('stats_users', true);
$Cache->delete_value('stats_torrents', true);
$Cache->delete_value('peers_count', true);
$Cache->delete_value('site_lang_lang_list', true);
$actiontime = date("F j, Y, g:i a");
write_log("Tracker MAIN settings updated by {$CURUSER['username']}. $actiontime",'mod');
go_back();
@@ -710,11 +711,49 @@ elseif ($action == 'mainsettings') // main settings
tr($lang_settings['row_torrents_category_mode'], $bcatlist."<br />".$lang_settings['text_torrents_category_mode_note'], 1);
// if (THISTRACKER == "HDStar")
tr($lang_settings['row_special_category_mode'], $scatlist."<br />".$lang_settings['text_special_category_mode_note'], 1);
$res = sql_query("SELECT * FROM language WHERE site_lang=1") or sqlerr(__FILE__, __LINE__);
$allSiteLanguages = \App\Models\Language::query()->where('site_lang', 1)->get();
$allEnabled = \App\Models\Language::listEnabled(true);
$langlist = "";
foreach ($allSiteLanguages as $lang) {
$langlist .= sprintf('<label><input type="checkbox" name="site_language_enabled[]" value="%s"%s/>%s</label>&nbsp;', $lang->site_lang_folder, in_array($lang->site_lang_folder, $allEnabled) ? " checked" : "", $lang->lang_name);
}
tr($lang_settings['row_site_language_enabled'], $langlist."<br />".$lang_settings['text_site_language_enabled_note'], 1);
$langlist = "";
while($array = mysql_fetch_array($res))
$langlist .= "<input type=radio name=defaultlang value='".$array['site_lang_folder']."'".($MAIN["defaultlang"] == $array['site_lang_folder'] ? " checked" : "").">".$array['lang_name']."&nbsp;";
foreach ($allSiteLanguages as $lang) {
$langlist .= sprintf(
'<label><input type="radio" name="defaultlang" value="%s"%s%s/>%s</label>&nbsp;',
$lang->site_lang_folder,
$MAIN["defaultlang"] == $lang->site_lang_folder ? " checked" : "",
!in_array($lang->site_lang_folder, $allEnabled) ? " disabled" : "",
$lang->lang_name
);
}
tr($lang_settings['row_default_site_language'], $langlist."<br />".$lang_settings['text_default_site_language_note'], 1);
$changeDefaultLangJs = <<<JS
let msg = "{$lang_settings['keep_at_least_one']}"
jQuery('input[name="site_language_enabled[]"]').on("change", function () {
let enabledCount = jQuery('input[name="site_language_enabled[]"]:checked').length
if (enabledCount == 0 && !this.checked) {
alert(msg)
this.checked = true
return
}
let target = jQuery('input[name="defaultlang"][value="' + this.value +'"]')
if (this.checked) {
target.prop("disabled", false);
} else {
target.prop("disabled", true);
if (target.is(":checked")) {
target.prop("checked", false)
jQuery('input[name="defaultlang"]:enabled:first').prop("checked", true)
}
}
})
JS;
\Nexus\Nexus::js($changeDefaultLangJs, 'footer', false);
$res = sql_query("SELECT * FROM stylesheets ORDER BY name") or sqlerr(__FILE__, __LINE__);
$csslist = "<select name=defstylesheet>";
while($array = mysql_fetch_array($res))
+6 -2
View File
@@ -6,10 +6,14 @@ $langid = intval($_GET['sitelanguage'] ?? 0);
if ($langid)
{
$lang_folder = validlang($langid);
$enabled = \App\Models\Language::listEnabled();
if (!in_array($lang_folder, $enabled)) {
nexus_redirect(getBaseUrl());
}
if(get_langfolder_cookie() != $lang_folder)
{
set_langfolder_cookie($lang_folder);
header("Location: " . $_SERVER['REQUEST_URI']);
nexus_redirect($_SERVER['REQUEST_URI']);
}
}
require_once(get_langfile_path("", false, $CURLANGDIR));
@@ -48,7 +52,7 @@ else {
$s = "<select name=\"sitelanguage\" onchange='submit()'>\n";
$langs = langlist("site_lang");
$langs = langlist("site_lang", true);
foreach ($langs as $row)
{
+24
View File
@@ -187,6 +187,30 @@ insert_tag(
""
);
insert_tag(
$lang_tags['text_left'],
$lang_tags['text_left_description'],
$lang_tags['text_left_syntax'],
$lang_tags['text_left_example'],
""
);
insert_tag(
$lang_tags['text_center'],
$lang_tags['text_center_description'],
$lang_tags['text_center_syntax'],
$lang_tags['text_center_example'],
""
);
insert_tag(
$lang_tags['text_right'],
$lang_tags['text_right_description'],
$lang_tags['text_right_syntax'],
$lang_tags['text_right_example'],
""
);
insert_tag(
$lang_tags['text_flash'],
$lang_tags['text_flash_description'],
+2
View File
@@ -162,4 +162,6 @@ stdhead($lang_upload['head_upload']);
</table>
</form>
<?php
\Nexus\Nexus::js('vendor/jquery-loading/jquery.loading.min.js', 'footer', true);
\Nexus\Nexus::js('js/ptgen.js', 'footer', true);
stdfoot();
+50
View File
@@ -0,0 +1,50 @@
# jquery-loading
[![Build Status](https://travis-ci.org/CarlosBonetti/jquery-loading.svg)](https://travis-ci.org/CarlosBonetti/jquery-loading)
Add and manipulate loading states of any element on the page.
[Docs and Demos](http://carlosbonetti.github.io/jquery-loading/).
## Getting started
Install it, using [npm](https://www.npmjs.com/):
```sh
$ npm install --save jquery-easy-loading
```
Include it:
```html
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="jquery.loading.js"></script>
```
Use it:
```javascript
$("#some-element").loading();
```
Visit [the website](http://carlosbonetti.github.io/jquery-loading/) for full list of options, methods and customization.
## Contributing to this project
Install dependencies once:
```
$ yarn install
```
Then build the project (generates `dist/` files):
```
$ yarn build
```
Run all tests with:
```
$ yarn test
```
File diff suppressed because one or more lines are too long