modal show global

This commit is contained in:
xiaomlove
2022-08-10 17:38:05 +08:00
parent 72b80887a4
commit e9b141fc00
34 changed files with 1106 additions and 175 deletions

View File

@@ -86,14 +86,9 @@ class Test extends Command
*/ */
public function handle() public function handle()
{ {
add_filter('ttt', function ($d) { $a = Carbon::parse('2022-08-06 23:08:03');
$d[] = 100; $b = $a->clone()->addHours(1);
return $d; dd($a, $b);
});
$a = [];
$a[] = '1';
$a = apply_filter('ttt', $a);
dd($a);
} }

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Console;
trait ExecuteCommandTrait
{
protected function executeCommand($command)
{
$this->info("Running $command ...");
$result = exec($command, $output, $result_code);
do_log(sprintf('command: %s, result_code: %s, output: %s, result: %s', $command, $result_code, json_encode($output), $result));
if ($result_code != 0) {
throw new \RuntimeException(json_encode($output));
}
}
}

View File

@@ -24,6 +24,7 @@ class BonusLogs extends NexusModel
const BUSINESS_TYPE_GIFT_TO_SOMEONE = 10; const BUSINESS_TYPE_GIFT_TO_SOMEONE = 10;
const BUSINESS_TYPE_NO_AD = 11; const BUSINESS_TYPE_NO_AD = 11;
const BUSINESS_TYPE_GIFT_TO_LOW_SHARE_RATIO = 12; const BUSINESS_TYPE_GIFT_TO_LOW_SHARE_RATIO = 12;
const BUSINESS_TYPE_LUCKY_DRAW = 13;
public static array $businessTypes = [ public static array $businessTypes = [
self::BUSINESS_TYPE_CANCEL_HIT_AND_RUN => ['text' => 'Cancel H&R'], self::BUSINESS_TYPE_CANCEL_HIT_AND_RUN => ['text' => 'Cancel H&R'],
@@ -38,6 +39,7 @@ class BonusLogs extends NexusModel
self::BUSINESS_TYPE_GIFT_TO_SOMEONE => ['text' => 'Gift to someone'], self::BUSINESS_TYPE_GIFT_TO_SOMEONE => ['text' => 'Gift to someone'],
self::BUSINESS_TYPE_NO_AD => ['text' => 'No ad'], self::BUSINESS_TYPE_NO_AD => ['text' => 'No ad'],
self::BUSINESS_TYPE_GIFT_TO_LOW_SHARE_RATIO => ['text' => 'Gift to low share ratio'], self::BUSINESS_TYPE_GIFT_TO_LOW_SHARE_RATIO => ['text' => 'Gift to low share ratio'],
self::BUSINESS_TYPE_LUCKY_DRAW => ['text' => 'Lucky draw'],
]; ];
public static function getBonusForCancelHitAndRun() public static function getBonusForCancelHitAndRun()

View File

@@ -23,7 +23,7 @@ class NexusModel extends Model
*/ */
protected function serializeDate(\DateTimeInterface $date) protected function serializeDate(\DateTimeInterface $date)
{ {
return $date->format($this->dateFormat ?: 'Y-m-d H:i'); return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
} }
/** /**

View File

@@ -135,7 +135,7 @@ class User extends Authenticatable implements FilamentUser, HasName
*/ */
protected function serializeDate(\DateTimeInterface $date): string protected function serializeDate(\DateTimeInterface $date): string
{ {
return $date->format($this->dateFormat ?: 'Y-m-d H:i'); return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
} }
/** /**
@@ -146,7 +146,7 @@ class User extends Authenticatable implements FilamentUser, HasName
protected $fillable = [ protected $fillable = [
'username', 'email', 'passhash', 'secret', 'stylesheet', 'editsecret', 'added', 'modcomment', 'enabled', 'status', 'username', 'email', 'passhash', 'secret', 'stylesheet', 'editsecret', 'added', 'modcomment', 'enabled', 'status',
'leechwarn', 'leechwarnuntil', 'page', 'class', 'uploaded', 'downloaded', 'clientselect', 'showclienterror', 'last_home', 'leechwarn', 'leechwarnuntil', 'page', 'class', 'uploaded', 'downloaded', 'clientselect', 'showclienterror', 'last_home',
'seedbonus', 'bonuscomment', 'downloadpos', 'vip_added', 'vip_until', 'title', 'seedbonus', 'bonuscomment', 'downloadpos', 'vip_added', 'vip_until', 'title', 'invites', 'attendance_card',
]; ];
/** /**
@@ -439,6 +439,16 @@ class User extends Authenticatable implements FilamentUser, HasName
return $this->hasMany(PollAnswer::class, 'userid'); return $this->hasMany(PollAnswer::class, 'userid');
} }
public function metas()
{
return $this->hasMany(UserMeta::class, 'uid');
}
public function usernameChangeLogs()
{
return $this->hasMany(UsernameChangeLog::class, 'uid');
}
public function getAvatarAttribute($value) public function getAvatarAttribute($value)
{ {
if ($value) { if ($value) {

30
app/Models/UserMeta.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
namespace App\Models;
class UserMeta extends NexusModel
{
protected $fillable = ['uid', 'meta_key', 'meta_value', 'status', 'deadline'];
public $timestamps = true;
const STATUS_NORMAL = 0;
const META_KEY_PERSONALIZED_USERNAME = 'PERSONALIZED_USERNAME';
const META_KEY_CHANGE_USERNAME = 'CHANGE_USERNAME';
protected $appends = ['meta_key_text'];
public function getMetaKeyTextAttribute()
{
return nexus_trans('label.user_meta.meta_keys.' . $this->meta_key) ?? '';
}
public static function consumeBenefit($uid, $metaKey)
{
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Models;
class UsernameChangeLog extends NexusModel
{
protected $fillable = ['uid', 'username_old', 'username_new', ];
public $timestamps = true;
public function user()
{
return $this->belongsTo(User::class, 'uid');
}
}

View File

@@ -73,7 +73,7 @@ class SeedBoxRepository extends BaseRepository
} }
$params['version'] = $ipEnd->getVersion(); $params['version'] = $ipEnd->getVersion();
} else { } else {
throw new \InvalidArgumentException("Require ip or ip_begin + ip_end"); throw new \InvalidArgumentException(nexus_trans('label.seed_box_record.ip_help'));
} }
return $params; return $params;

View File

@@ -10,8 +10,10 @@ use App\Models\Message;
use App\Models\Setting; use App\Models\Setting;
use App\Models\User; use App\Models\User;
use App\Models\UserBanLog; use App\Models\UserBanLog;
use App\Models\UserMeta;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Nexus\Database\NexusDB; use Nexus\Database\NexusDB;
@@ -82,12 +84,12 @@ class UserRepository extends BaseRepository
} }
$username = $params['username']; $username = $params['username'];
if (!validusername($username)) { if (!validusername($username)) {
throw new \InvalidArgumentException("Innvalid username: $username"); throw new \InvalidArgumentException("Invalid username: $username");
} }
$email = htmlspecialchars(trim($params['email'])); $email = htmlspecialchars(trim($params['email']));
$email = safe_email($email); $email = safe_email($email);
if (!check_email($email)) { if (!check_email($email)) {
throw new \InvalidArgumentException("Innvalid email: $email"); throw new \InvalidArgumentException("Invalid email: $email");
} }
if (User::query()->where('email', $email)->exists()) { if (User::query()->where('email', $email)->exists()) {
throw new \InvalidArgumentException("The email address: $email is already in use"); throw new \InvalidArgumentException("The email address: $email is already in use");
@@ -96,7 +98,7 @@ class UserRepository extends BaseRepository
throw new \InvalidArgumentException("The username: $username is already in use"); throw new \InvalidArgumentException("The username: $username is already in use");
} }
if (mb_strlen($password) < 6 || mb_strlen($password) > 40) { if (mb_strlen($password) < 6 || mb_strlen($password) > 40) {
throw new \InvalidArgumentException("Innvalid password: $password, it should be more than 6 character and less than 40 character"); throw new \InvalidArgumentException("Invalid password: $password, it should be more than 6 character and less than 40 character");
} }
$class = !empty($params['class']) ? intval($params['class']) : User::CLASS_USER; $class = !empty($params['class']) ? intval($params['class']) : User::CLASS_USER;
if (!isset(User::$classes[$class])) { if (!isset(User::$classes[$class])) {
@@ -365,10 +367,64 @@ class UserRepository extends BaseRepository
private function clearCache(User $user) private function clearCache(User $user)
{ {
\Nexus\Database\NexusDB::cache_del("user_{$user->id}_content"); clear_user_cache($user->id, $user->passkey);
\Nexus\Database\NexusDB::cache_del('user_passkey_'.$user->passkey.'_content'); }
public function listMetas($uid, $metaKeys = [], $valid = true)
{
$query = UserMeta::query()->where('uid', $uid);
if (!empty($metaKeys)) {
$query->whereIn('meta_key', Arr::wrap($metaKeys));
}
if ($valid) {
$query->where('status', 0)->where(function (Builder $query) {
$query->whereNull('deadline')->orWhere('deadline', '>=', now());
});
}
return $query->get()->groupBy('meta_key');
}
public function consumeBenefit($uid, array $params): bool
{
$metaKey = $params['meta_key'];
$records = $this->listMetas($uid, $metaKey);
if (!$records->has($metaKey)) {
throw new \RuntimeException("User do not has this metaKey: $metaKey");
}
/** @var UserMeta $meta */
$meta = $records->get($metaKey)->first();
$user = User::query()->findOrFail($uid, User::$commonFields);
if ($metaKey == UserMeta::META_KEY_CHANGE_USERNAME) {
NexusDB::transaction(function () use ($user, $meta, $params) {
$this->changeUsername($user, $params['username']);
$meta->delete();
clear_user_cache($user->id, $user->passkey);
});
return true;
}
throw new \InvalidArgumentException("Invalid meta_key: $metaKey");
}
private function changeUsername(User $user, $newUsername): bool
{
if ($user->username == $newUsername) {
throw new \RuntimeException("New username can not be the same with current username !");
}
if (!validusername($newUsername)) {
throw new \InvalidArgumentException("Invalid username, length must between 4 and 20 characters");
}
if (User::query()->where('username', $newUsername)->where('id', '!=', $user->id)->exists()) {
throw new \RuntimeException("Username: $newUsername already exists !");
}
NexusDB::transaction(function () use ($user, $newUsername) {
$oldUsername = $user->username;
$user->usernameChangeLogs()->create(['username_old' => $oldUsername, 'username_new' => $newUsername]);
$user->username = $newUsername;
$user->save();
});
return true;
} }
} }

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('user_metas', function (Blueprint $table) {
$table->id();
$table->integer('uid')->index();
$table->string('meta_key')->index();
$table->integer('status')->default(0);
$table->dateTime('deadline')->nullable();
$table->text('meta_value')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_metas');
}
};

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('username_change_logs', function (Blueprint $table) {
$table->id();
$table->integer('uid');
$table->string('username_old');
$table->string('username_new');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('username_change_logs');
}
};

View File

@@ -1,6 +1,6 @@
<?php <?php
defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.7.20'); defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.7.21');
defined('RELEASE_DATE') || define('RELEASE_DATE', '2022-08-05'); defined('RELEASE_DATE') || define('RELEASE_DATE', '2022-08-10');
defined('IN_TRACKER') || define('IN_TRACKER', false); defined('IN_TRACKER') || define('IN_TRACKER', false);
defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP"); defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP");
defined('NEXUSPHPURL') || define("NEXUSPHPURL","https://nexusphp.org"); defined('NEXUSPHPURL') || define("NEXUSPHPURL","https://nexusphp.org");

View File

@@ -1933,9 +1933,17 @@ function get_user_row($id)
static $neededColumns = array('id', 'noad', 'class', 'enabled', 'privacy', 'avatar', 'signature', 'uploaded', 'downloaded', 'last_access', 'username', 'donor', 'donoruntil', 'leechwarn', 'warned', 'title'); static $neededColumns = array('id', 'noad', 'class', 'enabled', 'privacy', 'avatar', 'signature', 'uploaded', 'downloaded', 'last_access', 'username', 'donor', 'donoruntil', 'leechwarn', 'warned', 'title');
$cacheKey = 'user_'.$id.'_content'; $cacheKey = 'user_'.$id.'_content';
$row = \Nexus\Database\NexusDB::remember($cacheKey, 900, function () use ($id, $neededColumns) { $row = \Nexus\Database\NexusDB::remember($cacheKey, 900, function () use ($id, $neededColumns) {
$user = \App\Models\User::query()->find($id, $neededColumns); $user = \App\Models\User::query()->with(['wearing_medals'])->find($id, $neededColumns);
if ($user) { if ($user) {
return $user->toArray(); $userRep = new \App\Repositories\UserRepository();
$metas = $userRep->listMetas($id, \App\Models\UserMeta::META_KEY_PERSONALIZED_USERNAME);
$arr = $user->toArray();
if ($metas->isNotEmpty()) {
$arr['__is_rainbow'] = 1;
} else {
$arr['__is_rainbow'] = 0;
}
return $arr;
} }
return null; return null;
}); });
@@ -2907,6 +2915,7 @@ jQuery(document).ready(function(){
</script> </script>
JS; JS;
print($js); print($js);
print('<img id="nexus-preview" style="display: none; position: absolute" src="" />');
print("</body></html>"); print("</body></html>");
//echo replacePngTags(ob_get_clean()); //echo replacePngTags(ob_get_clean());
@@ -3151,7 +3160,7 @@ function commenttable($rows, $type, $parent_id, $review = false)
$uidArr = array_unique(array_column($rows, 'user')); $uidArr = array_unique(array_column($rows, 'user'));
$neededColumns = array('id', 'noad', 'class', 'enabled', 'privacy', 'avatar', 'signature', 'uploaded', 'downloaded', 'last_access', 'username', 'donor', 'leechwarn', 'warned', 'title'); $neededColumns = array('id', 'noad', 'class', 'enabled', 'privacy', 'avatar', 'signature', 'uploaded', 'downloaded', 'last_access', 'username', 'donor', 'leechwarn', 'warned', 'title');
$userInfoArr = \App\Models\User::query()->with(['wearing_medals'])->find($uidArr, $neededColumns)->keyBy('id'); $userInfoArr = \App\Models\User::query()->find($uidArr, $neededColumns)->keyBy('id');
foreach ($rows as $row) foreach ($rows as $row)
{ {
@@ -3166,7 +3175,7 @@ function commenttable($rows, $type, $parent_id, $review = false)
} }
} }
print("<div style=\"margin-top: 8pt; margin-bottom: 8pt;\"><table id=\"cid".$row["id"]."\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\"><tr><td class=\"embedded\" width=\"99%\">#" . $row["id"] . "&nbsp;&nbsp;<font color=\"gray\">".$lang_functions['text_by']."</font>"); print("<div style=\"margin-top: 8pt; margin-bottom: 8pt;\"><table id=\"cid".$row["id"]."\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\"><tr><td class=\"embedded\" width=\"99%\">#" . $row["id"] . "&nbsp;&nbsp;<font color=\"gray\">".$lang_functions['text_by']."</font>");
print(build_medal_image($userInfo->wearing_medals, 20) . get_username($row["user"],false,true,true,false,false,true)); print(get_username($row["user"],false,true,true,false,false,true));
print("&nbsp;&nbsp;<font color=\"gray\">".$lang_functions['text_at']."</font>".gettime($row["added"]). print("&nbsp;&nbsp;<font color=\"gray\">".$lang_functions['text_at']."</font>".gettime($row["added"]).
($row["editedby"] && get_user_class() >= $commanage_class ? " - [<a href=\"comment.php?action=vieworiginal&amp;cid=".$row['id']."&amp;type=".$type."\">".$lang_functions['text_view_original']."</a>]" : "") . "</td><td class=\"embedded nowrap\" width=\"1%\"><a href=\"#top\"><img class=\"top\" src=\"pic/trans.gif\" alt=\"Top\" title=\"Top\" /></a>&nbsp;&nbsp;</td></tr></table></div>"); ($row["editedby"] && get_user_class() >= $commanage_class ? " - [<a href=\"comment.php?action=vieworiginal&amp;cid=".$row['id']."&amp;type=".$type."\">".$lang_functions['text_view_original']."</a>]" : "") . "</td><td class=\"embedded nowrap\" width=\"1%\"><a href=\"#top\"><img class=\"top\" src=\"pic/trans.gif\" alt=\"Top\" title=\"Top\" /></a>&nbsp;&nbsp;</td></tr></table></div>");
$avatar = ($CURUSER["avatars"] == "yes" ? htmlspecialchars(trim($userRow["avatar"])) : ""); $avatar = ($CURUSER["avatars"] == "yes" ? htmlspecialchars(trim($userRow["avatar"])) : "");
@@ -3420,7 +3429,7 @@ $torrent_tooltip = [];
foreach ($rows as $row) foreach ($rows as $row)
{ {
$id = $row["id"]; $id = $row["id"];
$sphighlight = get_torrent_bg_color($row['sp_state'], $row['pos_state']); $sphighlight = get_torrent_bg_color($row['sp_state'], $row['pos_state'], $row);
print("<tr" . $sphighlight . ">\n"); print("<tr" . $sphighlight . ">\n");
print("<td class=\"rowfollow nowrap\" valign=\"middle\" style='padding: 0px'>"); print("<td class=\"rowfollow nowrap\" valign=\"middle\" style='padding: 0px'>");
@@ -3696,19 +3705,44 @@ function get_username($id, $big = false, $link = true, $bold = true, $target = f
$disabledpic = "disabled"; $disabledpic = "disabled";
$style = "style='margin-left: 2pt'"; $style = "style='margin-left: 2pt'";
} }
$pics = $arr["donor"] == "yes" && ($arr['donoruntil'] === null || $arr['donoruntil'] < '1970' || $arr['donoruntil'] >= date('Y-m-d H:i:s')) ? "<img class=\"".$donorpic."\" src=\"pic/trans.gif\" alt=\"Donor\" ".$style." />" : ""; $pics = $arr["donor"] == "yes" && ($arr['donoruntil'] === null || $arr['donoruntil'] < '1970' || $arr['donoruntil'] >= date('Y-m-d H:i:s')) ? "<img class=\"".$donorpic."\" src=\"/pic/trans.gif\" alt=\"Donor\" ".$style." />" : "";
if ($arr["enabled"] == "yes") if ($arr["enabled"] == "yes")
$pics .= ($arr["leechwarn"] == "yes" ? "<img class=\"".$leechwarnpic."\" src=\"pic/trans.gif\" alt=\"Leechwarned\" ".$style." />" : "") . ($arr["warned"] == "yes" ? "<img class=\"".$warnedpic."\" src=\"pic/trans.gif\" alt=\"Warned\" ".$style." />" : ""); $pics .= ($arr["leechwarn"] == "yes" ? "<img class=\"".$leechwarnpic."\" src=\"/pic/trans.gif\" alt=\"Leechwarned\" ".$style." />" : "") . ($arr["warned"] == "yes" ? "<img class=\"".$warnedpic."\" src=\"/pic/trans.gif\" alt=\"Warned\" ".$style." />" : "");
else else
$pics .= "<img class=\"".$disabledpic."\" src=\"pic/trans.gif\" alt=\"Disabled\" ".$style." />\n"; $pics .= "<img class=\"".$disabledpic."\" src=\"/pic/trans.gif\" alt=\"Disabled\" ".$style." />\n";
//Rainbow effect
$username = $arr['username'];
$rainbow = "";
$hasSetRainbow = false;
if (isset($arr['__is_rainbow']) && $arr['__is_rainbow']) {
$rainbow = ' class="rainbow"';
}
if ($underline) {
$hasSetRainbow = true;
$username = "<u{$rainbow}>{$username}</u>";
}
if ($bold) {
if ($hasSetRainbow) {
$username = "<b>{$username}</b>";
} else {
$username = "<b{$rainbow}>{$username}</b>";
}
}
// $username = ($underline == true ? "<u>" . $arr['username'] . "</u>" : $arr['username']);
// $username = ($bold == true ? "<b>" . $username . "</b>" : $username);
//medal
$medalHtml = '';
foreach ($arr['wearing_medals'] as $medal) {
$medalHtml .= sprintf('<img src="%s" title="%s" class="preview" style="vertical-align: middle;max-height: 16px;max-width: 16px;margin-right: 2px"/>', $medal['image_large'], $medal['name']);
}
$username = ($underline == true ? "<u>" . $arr['username'] . "</u>" : $arr['username']);
$username = ($bold == true ? "<b>" . $username . "</b>" : $username);
$href = getSchemeAndHttpHost() . "/userdetails.php?id=$id"; $href = getSchemeAndHttpHost() . "/userdetails.php?id=$id";
$username = ($link == true ? "<a ". $link_ext . " href=\"" . $href . "\"" . ($target == true ? " target=\"_blank\"" : "") . " class='". get_user_class_name($arr['class'],true) . "_Name'>" . $username . "</a>" : $username) . $pics . ($withtitle == true ? " (" . ($arr['title'] == "" ? get_user_class_name($arr['class'],false,true,true) : "<span class='".get_user_class_name($arr['class'],true) . "_Name'><b>".htmlspecialchars($arr['title'])) . "</b></span>)" : ""); $username = ($link == true ? "<a ". $link_ext . " href=\"" . $href . "\"" . ($target == true ? " target=\"_blank\"" : "") . " class='". get_user_class_name($arr['class'],true) . "_Name'>" . $username . "</a>" : $username) . $pics . ($withtitle == true ? " (" . ($arr['title'] == "" ? get_user_class_name($arr['class'],false,true,true) : "<span class='".get_user_class_name($arr['class'],true) . "_Name'><b>".htmlspecialchars($arr['title'])) . "</b></span>)" : "");
$username = "<span class=\"nowrap\">" . ( $bracket == true ? "(" . $username . ")" : $username) . "</span>"; $username = "<span class=\"nowrap\">$medalHtml" . ( $bracket == true ? "(" . $username . ")" : $username) . "</span>";
} }
else else
{ {
@@ -3791,11 +3825,15 @@ function validusername($username)
// The following characters are allowed in user names // The following characters are allowed in user names
$allowedchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; $allowedchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$length = strlen($username);
for ($i = 0; $i < strlen($username); ++$i) for ($i = 0; $i < $length; ++$i)
if (strpos($allowedchars, $username[$i]) === false) if (strpos($allowedchars, $username[$i]) === false)
return false; return false;
if ($length < 4 || $length > 20) {
return false;
}
return true; return true;
} }
@@ -4171,7 +4209,7 @@ function get_second_icon($row) //for CHDBits
} }
} }
function get_torrent_bg_color($promotion = 1, $posState = "") function get_torrent_bg_color($promotion = 1, $posState = "", array $torrent = [])
{ {
global $CURUSER; global $CURUSER;
$sphighlight = null; $sphighlight = null;
@@ -4214,7 +4252,7 @@ function get_torrent_bg_color($promotion = 1, $posState = "")
$sphighlight = sprintf(' style="background-color: %s"', $torrentSettings['sticky_second_level_background_color']); $sphighlight = sprintf(' style="background-color: %s"', $torrentSettings['sticky_second_level_background_color']);
} }
} }
return (string)$sphighlight; return apply_filter('torrent_background_color', (string)$sphighlight, $torrent);
} }
function get_torrent_promotion_append($promotion = 1,$forcemode = "",$showtimeleft = false, $added = "", $promotionTimeType = 0, $promotionUntil = '', $ignoreGlobal = false){ function get_torrent_promotion_append($promotion = 1,$forcemode = "",$showtimeleft = false, $added = "", $promotionTimeType = 0, $promotionUntil = '', $ignoreGlobal = false){
@@ -5615,7 +5653,7 @@ function build_medal_image(\Illuminate\Support\Collection $medals, $maxHeight =
$wrapBefore = '<div style="display: inline;">'; $wrapBefore = '<div style="display: inline;">';
$wrapAfter = '</div>'; $wrapAfter = '</div>';
foreach ($medals as $medal) { foreach ($medals as $medal) {
$html = sprintf('<div style="display: inline"><img src="%s" title="%s" style="max-height: %spx"/>', $medal->image_large, $medal->name, $maxHeight); $html = sprintf('<div style="display: inline"><img src="%s" title="%s" class="preview" style="max-height: %spx"/>', $medal->image_large, $medal->name, $maxHeight);
if ($withActions) { if ($withActions) {
$checked = ''; $checked = '';
if ($medal->pivot->status == \App\Models\UserMedal::STATUS_WEARING) { if ($medal->pivot->status == \App\Models\UserMedal::STATUS_WEARING) {

View File

@@ -602,40 +602,7 @@ function format_datetime($datetime, $format = 'Y-m-d H:i')
function nexus_trans($key, $replace = [], $locale = null) function nexus_trans($key, $replace = [], $locale = null)
{ {
if (!IN_NEXUS) { return \Nexus\Nexus::trans($key, $replace, $locale);
return trans($key, $replace, $locale);
}
static $translations;
if (!$locale) {
$lang = get_langfolder_cookie();
$locale = \App\Http\Middleware\Locale::$languageMaps[$lang] ?? 'en';
}
if (is_null($translations)) {
$langDir = ROOT_PATH . 'resources/lang/';
$files = glob($langDir . '*/*');
foreach ($files as $file) {
$values = require $file;
$setKey = substr($file, strlen($langDir));
if (substr($setKey, -4) == '.php') {
$setKey = substr($setKey, 0, -4);
}
$setKey = str_replace('/', '.', $setKey);
arr_set($translations, $setKey, $values);
}
}
$getKey = $locale . "." . $key;
$result = arr_get($translations, $getKey);
if (empty($result) && $locale != 'en') {
do_log("original getKey: $getKey can not get any translations", 'error');
$getKey = "en." . $key;
$result = arr_get($translations, $getKey);
}
if (!empty($replace)) {
$search = array_map(function ($value) {return ":$value";}, array_keys($replace));
$result = str_replace($search, array_values($replace), $result);
}
do_log("key: $key, replace: " . nexus_json_encode($replace) . ", locale: $locale, getKey: $getKey, result: $result", 'debug');
return $result;
} }
function isRunningInConsole(): bool function isRunningInConsole(): bool
@@ -903,3 +870,11 @@ function getDataTraffic(array $torrent, array $queries, array $user, $peer, $sna
do_log("$log, result: " . json_encode($result), 'info'); do_log("$log, result: " . json_encode($result), 'info');
return $result; return $result;
} }
function clear_user_cache($uid, $passkey = '')
{
\Nexus\Database\NexusDB::cache_del("user_{$uid}_content");
if ($passkey) {
\Nexus\Database\NexusDB::cache_del('user_passkey_'.$passkey.'_content');
}
}

View File

@@ -152,5 +152,8 @@ $lang_userdetails = array
'text_donoruntil_note' => "时间格式为'年年年年-月月-日日 时时:分分:秒秒'。留空永久有效。", 'text_donoruntil_note' => "时间格式为'年年年年-月月-日日 时时:分分:秒秒'。留空永久有效。",
'change_field_value_migrated' => '修改请到管理后台操作', 'change_field_value_migrated' => '修改请到管理后台操作',
'sure_to_remove_leech_warn' => '确定要清除此吸血警告吗?', 'sure_to_remove_leech_warn' => '确定要清除此吸血警告吗?',
'row_user_props' => '道具',
'meta_key_change_username_username' => '新用户名',
'consume' => '使用',
); );
?> ?>

View File

@@ -25,6 +25,10 @@ final class Nexus
private static array $appendFooters = []; private static array $appendFooters = [];
private static array $translationNamespaces = [];
private static array $translations = [];
const PLATFORM_USER = 'user'; const PLATFORM_USER = 'user';
const PLATFORM_ADMIN = 'admin'; const PLATFORM_ADMIN = 'admin';
const PLATFORM_TRACKER = 'tracker'; const PLATFORM_TRACKER = 'tracker';
@@ -266,6 +270,87 @@ final class Nexus
return self::$appendFooters; return self::$appendFooters;
} }
public static function addTranslationNamespace($path, $namespace)
{
if (empty($namespace)) {
throw new \InvalidArgumentException("namespace can not be empty");
}
self::$translationNamespaces[$namespace] = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
public static function trans($key, $replace = [], $locale = null)
{
if (!IN_NEXUS) {
return trans($key, $replace, $locale);
}
if (empty(self::$translations)) {
//load from default lang dir
$langDir = ROOT_PATH . 'resources/lang/';
self::loadTranslations($langDir);
//load from namespace
foreach (self::$translationNamespaces as $namespace => $path) {
self::loadTranslations($path, $namespace);
}
}
return self::getTranslation($key, $replace, $locale);
}
private static function loadTranslations($path, $namespace = null)
{
$files = glob($path . '*/*');
foreach ($files as $file) {
if (!is_file($file)) {
continue;
}
if (!is_readable($file)) {
do_log("[TRANSLATION_FILE_NOT_READABLE], $file");
}
$values = require $file;
$setKey = substr($file, strlen($path));
if (substr($setKey, -4) == '.php') {
$setKey = substr($setKey, 0, -4);
}
$setKey = str_replace('/', '.', $setKey);
if ($namespace !== null) {
$setKey = "$namespace.$setKey";
}
// do_log("path: $path, namespace: $namespace, file: $file, setKey: $setKey", 'debug');
arr_set(self::$translations, $setKey, $values);
}
}
private static function getTranslation($key, $replace = [], $locale = null)
{
if (!$locale) {
$lang = get_langfolder_cookie();
$locale = \App\Http\Middleware\Locale::$languageMaps[$lang] ?? 'en';
}
$getKey = self::getTranslationGetKey($key, $locale);
$result = arr_get(self::$translations, $getKey);
if (empty($result) && $locale != 'en') {
do_log("original getKey: $getKey can not get any translations", 'error');
$getKey = self::getTranslationGetKey($key, 'en');
$result = arr_get(self::$translations, $getKey);
}
if (!empty($replace)) {
$search = array_map(function ($value) {return ":$value";}, array_keys($replace));
$result = str_replace($search, array_values($replace), $result);
}
do_log("key: $key, replace: " . nexus_json_encode($replace) . ", locale: $locale, getKey: $getKey, result: $result", 'debug');
return $result;
}
private static function getTranslationGetKey($key, $locale): string
{
$namespace = strstr($key, '::', true);
if ($namespace !== false) {
$getKey = sprintf('%s.%s.%s', $namespace, $locale, substr($key, strlen($namespace) + 2));
} else {
$getKey = $locale . "." . $key;
}
// do_log("key: $key, locale: $locale, namespace: $namespace, getKey: $getKey", 'debug');
return $getKey;
}
} }

View File

@@ -36,8 +36,6 @@ class Plugin
$className = str_replace('ServiceProvider', 'Repository', $provider); $className = str_replace('ServiceProvider', 'Repository', $provider);
if (class_exists($className)) { if (class_exists($className)) {
call_user_func([new $className, 'boot']); call_user_func([new $className, 'boot']);
} else {
do_log("Plugin: $className not exists.", "error");
} }
} }
} }

View File

@@ -116,3 +116,10 @@ function removeHitAndRun($params)
$rep = new \App\Repositories\BonusRepository(); $rep = new \App\Repositories\BonusRepository();
return $rep->consumeToCancelHitAndRun($CURUSER['id'], $params['id']); return $rep->consumeToCancelHitAndRun($CURUSER['id'], $params['id']);
} }
function consumeBenefit($params)
{
global $CURUSER;
$rep = new \App\Repositories\UserRepository();
return $rep->consumeBenefit($CURUSER['id'], $params);
}

View File

@@ -37,7 +37,7 @@ if (!$row) {
permissiondenied(); permissiondenied();
} else { } else {
$row = apply_filter('torrent_detail', $row); $row = apply_filter('torrent_detail', $row);
$owner = \App\Models\User::query()->with(['wearing_medals'])->find($row['owner']); $owner = \App\Models\User::query()->find($row['owner']);
if (!$owner) { if (!$owner) {
$owner = \App\Models\User::defaultUser(); $owner = \App\Models\User::defaultUser();
} }
@@ -104,10 +104,10 @@ if (!$row) {
if (get_user_class() < $viewanonymous_class) if (get_user_class() < $viewanonymous_class)
$uprow = "<i>".$lang_details['text_anonymous']."</i>"; $uprow = "<i>".$lang_details['text_anonymous']."</i>";
else else
$uprow = "<i>".$lang_details['text_anonymous']."</i> (" . build_medal_image($owner->wearing_medals, 20) . get_username($row['owner'], false, true, true, false, false, true) . ")"; $uprow = "<i>".$lang_details['text_anonymous']."</i> (" . get_username($row['owner'], false, true, true, false, false, true) . ")";
} }
else { else {
$uprow = (isset($row['owner']) ? build_medal_image($owner->wearing_medals, 20) . get_username($row['owner'], false, true, true, false, false, true) : "<i>".$lang_details['text_unknown']."</i>"); $uprow = (isset($row['owner']) ? get_username($row['owner'], false, true, true, false, false, true) : "<i>".$lang_details['text_unknown']."</i>");
} }
if ($CURUSER["id"] == $row["owner"]) if ($CURUSER["id"] == $row["owner"])

View File

@@ -667,7 +667,7 @@ if ($action == "viewtopic")
$uidArr = array_keys($uidArr); $uidArr = array_keys($uidArr);
unset($arr); unset($arr);
$neededColumns = array('id', 'noad', 'class', 'enabled', 'privacy', 'avatar', 'signature', 'uploaded', 'downloaded', 'last_access', 'username', 'donor', 'leechwarn', 'warned', 'title'); $neededColumns = array('id', 'noad', 'class', 'enabled', 'privacy', 'avatar', 'signature', 'uploaded', 'downloaded', 'last_access', 'username', 'donor', 'leechwarn', 'warned', 'title');
$userInfoArr = \App\Models\User::query()->with(['wearing_medals'])->find($uidArr, $neededColumns)->keyBy('id'); $userInfoArr = \App\Models\User::query()->find($uidArr, $neededColumns)->keyBy('id');
$pn = 0; $pn = 0;
$lpr = get_last_read_post_id($topicid); $lpr = get_last_read_post_id($topicid);
if ($Advertisement->enable_ad()) if ($Advertisement->enable_ad())
@@ -708,7 +708,7 @@ if ($action == "viewtopic")
$avatar = ($CURUSER["avatars"] == "yes" ? htmlspecialchars($arr2["avatar"]) : ""); $avatar = ($CURUSER["avatars"] == "yes" ? htmlspecialchars($arr2["avatar"]) : "");
$uclass = get_user_class_image($arr2["class"]); $uclass = get_user_class_image($arr2["class"]);
$by = build_medal_image($userInfo->wearing_medals, 20) . get_username($posterid,false,true,true,false,false,true); $by = get_username($posterid,false,true,true,false,false,true);
if (!$avatar) if (!$avatar)
$avatar = "pic/default_avatar.png"; $avatar = "pic/default_avatar.png";

View File

@@ -152,6 +152,11 @@ if ($showshoutbox_main == "yes") {
print("</form></td></tr></table>"); print("</form></td></tr></table>");
} }
// ------------- end: shoutbox ------------------// // ------------- end: shoutbox ------------------//
$extraModules = [];
$extraModules = apply_filter('nexus_home_module', $extraModules);
print implode('', $extraModules);
// ------------- start: latest forum posts ------------------// // ------------- start: latest forum posts ------------------//
if ($showlastxforumposts_main == "yes" && $CURUSER) if ($showlastxforumposts_main == "yes" && $CURUSER)

205
public/js/jquery-easing.js vendored Normal file
View File

@@ -0,0 +1,205 @@
/*
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
*
* Uses the built in easing capabilities added In jQuery 1.1
* to offer multiple easing options
*
* TERMS OF USE - jQuery Easing
*
* Open source under the BSD License.
*
* Copyright © 2008 George McGinley Smith
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the author nor the names of contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];
jQuery.extend( jQuery.easing,
{
def: 'easeOutQuad',
swing: function (x, t, b, c, d) {
//alert(jQuery.easing.default);
return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
},
easeInQuad: function (x, t, b, c, d) {
return c*(t/=d)*t + b;
},
easeOutQuad: function (x, t, b, c, d) {
return -c *(t/=d)*(t-2) + b;
},
easeInOutQuad: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t + b;
return -c/2 * ((--t)*(t-2) - 1) + b;
},
easeInCubic: function (x, t, b, c, d) {
return c*(t/=d)*t*t + b;
},
easeOutCubic: function (x, t, b, c, d) {
return c*((t=t/d-1)*t*t + 1) + b;
},
easeInOutCubic: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t + b;
return c/2*((t-=2)*t*t + 2) + b;
},
easeInQuart: function (x, t, b, c, d) {
return c*(t/=d)*t*t*t + b;
},
easeOutQuart: function (x, t, b, c, d) {
return -c * ((t=t/d-1)*t*t*t - 1) + b;
},
easeInOutQuart: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
return -c/2 * ((t-=2)*t*t*t - 2) + b;
},
easeInQuint: function (x, t, b, c, d) {
return c*(t/=d)*t*t*t*t + b;
},
easeOutQuint: function (x, t, b, c, d) {
return c*((t=t/d-1)*t*t*t*t + 1) + b;
},
easeInOutQuint: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
return c/2*((t-=2)*t*t*t*t + 2) + b;
},
easeInSine: function (x, t, b, c, d) {
return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
},
easeOutSine: function (x, t, b, c, d) {
return c * Math.sin(t/d * (Math.PI/2)) + b;
},
easeInOutSine: function (x, t, b, c, d) {
return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
},
easeInExpo: function (x, t, b, c, d) {
return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
},
easeOutExpo: function (x, t, b, c, d) {
return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
},
easeInOutExpo: function (x, t, b, c, d) {
if (t==0) return b;
if (t==d) return b+c;
if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
},
easeInCirc: function (x, t, b, c, d) {
return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
},
easeOutCirc: function (x, t, b, c, d) {
return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
},
easeInOutCirc: function (x, t, b, c, d) {
if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
},
easeInElastic: function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
},
easeOutElastic: function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
},
easeInOutElastic: function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
},
easeInBack: function (x, t, b, c, d, s) {
if (s == undefined) s = 1.70158;
return c*(t/=d)*t*((s+1)*t - s) + b;
},
easeOutBack: function (x, t, b, c, d, s) {
if (s == undefined) s = 1.70158;
return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
},
easeInOutBack: function (x, t, b, c, d, s) {
if (s == undefined) s = 1.70158;
if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
},
easeInBounce: function (x, t, b, c, d) {
return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
},
easeOutBounce: function (x, t, b, c, d) {
if ((t/=d) < (1/2.75)) {
return c*(7.5625*t*t) + b;
} else if (t < (2/2.75)) {
return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
} else if (t < (2.5/2.75)) {
return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
} else {
return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
}
},
easeInOutBounce: function (x, t, b, c, d) {
if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
}
});
/*
*
* TERMS OF USE - EASING EQUATIONS
*
* Open source under the BSD License.
*
* Copyright © 2001 Robert Penner
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* Neither the name of the author nor the names of contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

339
public/js/jquery-rotate.js vendored Normal file
View File

@@ -0,0 +1,339 @@
// VERSION: 2.3 LAST UPDATE: 11.07.2013
/*
* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
*
* Made by Wilq32, wilq32@gmail.com, Wroclaw, Poland, 01.2009
* Website: http://jqueryrotate.com
*/
(function($) {
var supportedCSS,supportedCSSOrigin, styles=document.getElementsByTagName("head")[0].style,toCheck="transformProperty WebkitTransform OTransform msTransform MozTransform".split(" ");
for (var a = 0; a < toCheck.length; a++) if (styles[toCheck[a]] !== undefined) { supportedCSS = toCheck[a]; }
if (supportedCSS) {
supportedCSSOrigin = supportedCSS.replace(/[tT]ransform/,"TransformOrigin");
if (supportedCSSOrigin[0] == "T") supportedCSSOrigin[0] = "t";
}
// Bad eval to preven google closure to remove it from code o_O
eval('IE = "v"=="\v"');
jQuery.fn.extend({
rotate:function(parameters)
{
if (this.length===0||typeof parameters=="undefined") return;
if (typeof parameters=="number") parameters={angle:parameters};
var returned=[];
for (var i=0,i0=this.length;i<i0;i++)
{
var element=this.get(i);
if (!element.Wilq32 || !element.Wilq32.PhotoEffect) {
var paramClone = $.extend(true, {}, parameters);
var newRotObject = new Wilq32.PhotoEffect(element,paramClone)._rootObj;
returned.push($(newRotObject));
}
else {
element.Wilq32.PhotoEffect._handleRotation(parameters);
}
}
return returned;
},
getRotateAngle: function(){
var ret = [0];
for (var i=0,i0=this.length;i<i0;i++)
{
var element=this.get(i);
if (element.Wilq32 && element.Wilq32.PhotoEffect) {
ret[i] = element.Wilq32.PhotoEffect._angle;
}
}
return ret;
},
stopRotate: function(){
for (var i=0,i0=this.length;i<i0;i++)
{
var element=this.get(i);
if (element.Wilq32 && element.Wilq32.PhotoEffect) {
clearTimeout(element.Wilq32.PhotoEffect._timer);
}
}
}
});
// Library agnostic interface
Wilq32=window.Wilq32||{};
Wilq32.PhotoEffect=(function(){
if (supportedCSS) {
return function(img,parameters){
img.Wilq32 = {
PhotoEffect: this
};
this._img = this._rootObj = this._eventObj = img;
this._handleRotation(parameters);
}
} else {
return function(img,parameters) {
this._img = img;
this._onLoadDelegate = [parameters];
this._rootObj=document.createElement('span');
this._rootObj.style.display="inline-block";
this._rootObj.Wilq32 =
{
PhotoEffect: this
};
img.parentNode.insertBefore(this._rootObj,img);
if (img.complete) {
this._Loader();
} else {
var self=this;
// TODO: Remove jQuery dependency
jQuery(this._img).bind("load", function(){ self._Loader(); });
}
}
}
})();
Wilq32.PhotoEffect.prototype = {
_setupParameters : function (parameters){
this._parameters = this._parameters || {};
if (typeof this._angle !== "number") { this._angle = 0 ; }
if (typeof parameters.angle==="number") { this._angle = parameters.angle; }
this._parameters.animateTo = (typeof parameters.animateTo === "number") ? (parameters.animateTo) : (this._angle);
this._parameters.step = parameters.step || this._parameters.step || null;
this._parameters.easing = parameters.easing || this._parameters.easing || this._defaultEasing;
this._parameters.duration = 'duration' in parameters ? parameters.duration : parameters.duration || this._parameters.duration || 1000;
this._parameters.callback = parameters.callback || this._parameters.callback || this._emptyFunction;
this._parameters.center = parameters.center || this._parameters.center || ["50%","50%"];
if (typeof this._parameters.center[0] == "string") {
this._rotationCenterX = (parseInt(this._parameters.center[0],10) / 100) * this._imgWidth * this._aspectW;
} else {
this._rotationCenterX = this._parameters.center[0];
}
if (typeof this._parameters.center[1] == "string") {
this._rotationCenterY = (parseInt(this._parameters.center[1],10) / 100) * this._imgHeight * this._aspectH;
} else {
this._rotationCenterY = this._parameters.center[1];
}
if (parameters.bind && parameters.bind != this._parameters.bind) { this._BindEvents(parameters.bind); }
},
_emptyFunction: function(){},
_defaultEasing: function (x, t, b, c, d) { return -c * ((t=t/d-1)*t*t*t - 1) + b },
_handleRotation : function(parameters, dontcheck){
if (!supportedCSS && !this._img.complete && !dontcheck) {
this._onLoadDelegate.push(parameters);
return;
}
this._setupParameters(parameters);
if (this._angle==this._parameters.animateTo) {
this._rotate(this._angle);
}
else {
this._animateStart();
}
},
_BindEvents:function(events){
if (events && this._eventObj)
{
// Unbinding previous Events
if (this._parameters.bind){
var oldEvents = this._parameters.bind;
for (var a in oldEvents) if (oldEvents.hasOwnProperty(a))
// TODO: Remove jQuery dependency
jQuery(this._eventObj).unbind(a,oldEvents[a]);
}
this._parameters.bind = events;
for (var a in events) if (events.hasOwnProperty(a))
// TODO: Remove jQuery dependency
jQuery(this._eventObj).bind(a,events[a]);
}
},
_Loader:(function()
{
if (IE)
return function() {
var width=this._img.width;
var height=this._img.height;
this._imgWidth = width;
this._imgHeight = height;
this._img.parentNode.removeChild(this._img);
this._vimage = this.createVMLNode('image');
this._vimage.src=this._img.src;
this._vimage.style.height=height+"px";
this._vimage.style.width=width+"px";
this._vimage.style.position="absolute"; // FIXES IE PROBLEM - its only rendered if its on absolute position!
this._vimage.style.top = "0px";
this._vimage.style.left = "0px";
this._aspectW = this._aspectH = 1;
/* Group minifying a small 1px precision problem when rotating object */
this._container = this.createVMLNode('group');
this._container.style.width=width;
this._container.style.height=height;
this._container.style.position="absolute";
this._container.style.top="0px";
this._container.style.left="0px";
this._container.setAttribute('coordsize',width-1+','+(height-1)); // This -1, -1 trying to fix ugly problem with small displacement on IE
this._container.appendChild(this._vimage);
this._rootObj.appendChild(this._container);
this._rootObj.style.position="relative"; // FIXES IE PROBLEM
this._rootObj.style.width=width+"px";
this._rootObj.style.height=height+"px";
this._rootObj.setAttribute('id',this._img.getAttribute('id'));
this._rootObj.className=this._img.className;
this._eventObj = this._rootObj;
var parameters;
while (parameters = this._onLoadDelegate.shift()) {
this._handleRotation(parameters, true);
}
}
else return function () {
this._rootObj.setAttribute('id',this._img.getAttribute('id'));
this._rootObj.className=this._img.className;
this._imgWidth=this._img.naturalWidth;
this._imgHeight=this._img.naturalHeight;
var _widthMax=Math.sqrt((this._imgHeight)*(this._imgHeight) + (this._imgWidth) * (this._imgWidth));
this._width = _widthMax * 3;
this._height = _widthMax * 3;
this._aspectW = this._img.offsetWidth/this._img.naturalWidth;
this._aspectH = this._img.offsetHeight/this._img.naturalHeight;
this._img.parentNode.removeChild(this._img);
this._canvas=document.createElement('canvas');
this._canvas.setAttribute('width',this._width);
this._canvas.style.position="relative";
this._canvas.style.left = -this._img.height * this._aspectW + "px";
this._canvas.style.top = -this._img.width * this._aspectH + "px";
this._canvas.Wilq32 = this._rootObj.Wilq32;
this._rootObj.appendChild(this._canvas);
this._rootObj.style.width=this._img.width*this._aspectW+"px";
this._rootObj.style.height=this._img.height*this._aspectH+"px";
this._eventObj = this._canvas;
this._cnv=this._canvas.getContext('2d');
var parameters;
while (parameters = this._onLoadDelegate.shift()) {
this._handleRotation(parameters, true);
}
}
})(),
_animateStart:function()
{
if (this._timer) {
clearTimeout(this._timer);
}
this._animateStartTime = +new Date;
this._animateStartAngle = this._angle;
this._animate();
},
_animate:function()
{
var actualTime = +new Date;
var checkEnd = actualTime - this._animateStartTime > this._parameters.duration;
// TODO: Bug for animatedGif for static rotation ? (to test)
if (checkEnd && !this._parameters.animatedGif)
{
clearTimeout(this._timer);
}
else
{
if (this._canvas||this._vimage||this._img) {
var angle = this._parameters.easing(0, actualTime - this._animateStartTime, this._animateStartAngle, this._parameters.animateTo - this._animateStartAngle, this._parameters.duration);
this._rotate((~~(angle*10))/10);
}
if (this._parameters.step) {
this._parameters.step(this._angle);
}
var self = this;
this._timer = setTimeout(function()
{
self._animate.call(self);
}, 10);
}
// To fix Bug that prevents using recursive function in callback I moved this function to back
if (this._parameters.callback && checkEnd){
this._angle = this._parameters.animateTo;
this._rotate(this._angle);
this._parameters.callback.call(this._rootObj);
}
},
_rotate : (function()
{
var rad = Math.PI/180;
if (IE)
return function(angle)
{
this._angle = angle;
this._container.style.rotation=(angle%360)+"deg";
this._vimage.style.top = -(this._rotationCenterY - this._imgHeight/2) + "px";
this._vimage.style.left = -(this._rotationCenterX - this._imgWidth/2) + "px";
this._container.style.top = this._rotationCenterY - this._imgHeight/2 + "px";
this._container.style.left = this._rotationCenterX - this._imgWidth/2 + "px";
}
else if (supportedCSS)
return function(angle){
this._angle = angle;
this._img.style[supportedCSS]="rotate("+(angle%360)+"deg)";
this._img.style[supportedCSSOrigin]=this._parameters.center.join(" ");
}
else
return function(angle)
{
this._angle = angle;
angle=(angle%360)* rad;
// clear canvas
this._canvas.width = this._width;//+this._widthAdd;
this._canvas.height = this._height;//+this._heightAdd;
// REMEMBER: all drawings are read from backwards.. so first function is translate, then rotate, then translate, translate..
this._cnv.translate(this._imgWidth*this._aspectW,this._imgHeight*this._aspectH); // at least center image on screen
this._cnv.translate(this._rotationCenterX,this._rotationCenterY); // we move image back to its orginal
this._cnv.rotate(angle); // rotate image
this._cnv.translate(-this._rotationCenterX,-this._rotationCenterY); // move image to its center, so we can rotate around its center
this._cnv.scale(this._aspectW,this._aspectH); // SCALE - if needed ;)
this._cnv.drawImage(this._img, 0, 0); // First - we draw image
}
})()
}
if (IE)
{
Wilq32.PhotoEffect.prototype.createVMLNode=(function(){
document.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
try {
!document.namespaces.rvml && document.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
return function (tagName) {
return document.createElement('<rvml:' + tagName + ' class="rvml">');
};
} catch (e) {
return function (tagName) {
return document.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
};
}
})();
}
})(jQuery);

30
public/js/nexus.js vendored
View File

@@ -1,10 +1,22 @@
; jQuery(document).ready(function () {
jQuery('.spoiler-title').on('click', function () { jQuery('.spoiler-title').on('click', function () {
let content = jQuery(this).parent().next(); let content = jQuery(this).parent().next();
if (content.hasClass('collapse')) { if (content.hasClass('collapse')) {
content.height(content[0].scrollHeight).removeClass('collapse') content.height(content[0].scrollHeight).removeClass('collapse')
} else { } else {
content.height(0).addClass('collapse') content.height(0).addClass('collapse')
} }
}); })
var previewEle = jQuery('#nexus-preview')
jQuery("body").on("mouseover", ".preview", function (e) {
console.log(e)
let src = jQuery(this).attr("src")
if (src) {
previewEle.attr("src", src).css({"display": "block", "left": e.pageX + 5, "top": e.pageY + 5})
}
});
jQuery("body").on("mouseout", ".preview", function (e) {
previewEle.hide()
});
})

View File

@@ -5,6 +5,7 @@ loggedinorreturn();
if (get_user_class() < UC_ADMINISTRATOR) if (get_user_class() < UC_ADMINISTRATOR)
stderr("Sorry", "Access denied."); stderr("Sorry", "Access denied.");
stdhead("Mass PM", false); stdhead("Mass PM", false);
$classes = array_chunk(\App\Models\User::$classes, 4, true);
?> ?>
<table class=main width=737 border=0 cellspacing=0 cellpadding=0><tr><td class=embedded> <table class=main width=737 border=0 cellspacing=0 cellpadding=0><tr><td class=embedded>
<div align=center> <div align=center>
@@ -30,79 +31,15 @@ if ($_GET["sent"] == 1) {
<tr> <tr>
<td><b>Send to:</b><br /> <td><b>Send to:</b><br />
<table style="border: 0" width="100%" cellpadding="0" cellspacing="0"> <table style="border: 0" width="100%" cellpadding="0" cellspacing="0">
<tr> <?php
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="0"> foreach ($classes as $chunk) {
</td> printf('<tr>');
<td style="border: 0">Peasant</td> foreach ($chunk as $class => $info) {
printf('<td style="border: 0"><label><input type="checkbox" name="clases[]" value="%s" />%s</label></td>', $class, $info['text']);
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="1"> }
</td> printf('</tr>');
<td style="border: 0">User</td> }
?>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="2">
</td>
<td style="border: 0">Power User</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="3">
</td>
<td style="border: 0">Elite User</td>
</tr>
<tr>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="4">
</td>
<td style="border: 0">Crazy User</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="5">
</td>
<td style="border: 0">Insane User</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="6">
</td>
<td style="border: 0">Veteran User</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="7">
</td>
<td style="border: 0">Extreme User</td>
</tr>
<tr>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="8">
</td>
<td style="border: 0">Ultimate User</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="9">
</td>
<td style="border: 0">Nexus Master</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="10">
</td>
<td style="border: 0">VIP</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="11">
</td>
<td style="border: 0">Uploader</td>
</tr>
<tr>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="12">
</td>
<td style="border: 0">Moderator</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="13">
</td>
<td style="border: 0">Administrator</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="14">
</td>
<td style="border: 0">SysOp</td>
<td style="border: 0" width="20"><input type="checkbox" name="clases[]" value="15">
</td>
<td style="border: 0">Staff Leader</td>
<td style="border: 0">&nbsp;</td>
<td style="border: 0">&nbsp;</td>
</tr>
</table> </table>
</td> </td>
</tr> </tr>

View File

@@ -498,3 +498,35 @@ img.hitandrun {
.layui-layer { .layui-layer {
color: black; color: black;
} }
.layer-form {
padding: 10px 15px;
}
.layer-form .form-control-row input{
padding: 4px;
}
.layer-form .form-control-row .label{
margin-bottom: 4px;
}
.rainbow {
text-align: center;
text-decoration: underline;
/*font-size: 32px;*/
font-family: monospace;
/*letter-spacing: 5px;*/
background: linear-gradient(to right, #6666ff, #0099ff , #00ff00, #ff3399, #6666ff);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
animation: rainbow_animation 6s ease-in-out infinite;
background-size: 400% 100%;
}
@keyframes rainbow_animation {
0%,100% {
background-position: 0 0;
}
50% {
background-position: 100% 0;
}
}

View File

@@ -3,7 +3,7 @@ require "../include/bittorrent.php";
if ($_SERVER["REQUEST_METHOD"] != "POST") if ($_SERVER["REQUEST_METHOD"] != "POST")
stderr("Error", "Permission denied!"); stderr("Error", "Permission denied!");
dbconn(); dbconn();
loggedinorreturn(); loggedinorreturn();
if (get_user_class() < UC_ADMINISTRATOR) if (get_user_class() < UC_ADMINISTRATOR)
stderr("Sorry", "Permission denied."); stderr("Sorry", "Permission denied.");
@@ -25,10 +25,26 @@ if (is_array($updateset)) {
stderr("Error","Invalid Class"); stderr("Error","Invalid Class");
} }
$subject = trim($_POST['subject']); $subject = trim($_POST['subject']);
$query = sql_query("SELECT id FROM users WHERE class IN (".implode(",", $updateset).")"); $size = 10000;
while($dat=mysql_fetch_assoc($query)) $page = 1;
{ set_time_limit(300);
sql_query("INSERT INTO messages (sender, receiver, added, subject, msg) VALUES ($sender_id, {$dat['id']}, $dt, " . sqlesc($subject) .", " . sqlesc($msg) .")") or sqlerr(__FILE__,__LINE__); $classStr = implode(",", $updateset);
while (true) {
$msgValues = $idArr = [];
$offset = ($page - 1) * $size;
$query = sql_query("SELECT id FROM users WHERE class IN (".implode(",", $updateset).") and `enabled` = 'yes' and `status` = 'confirmed'");
while($dat=mysql_fetch_assoc($query))
{
$idArr[] = $dat['id'];
$msgValues[] = sprintf('(%s, %s, %s, %s, %s)', $sender_id, $dat['id'], $dt, sqlesc($subject), sqlesc($msg));
}
if (empty($idArr)) {
break;
}
$idStr = implode(', ', $idArr);
$sql = "INSERT INTO messages (sender, receiver, added, subject, msg) VALUES " . implode(', ', $msgValues);
sql_query($sql);
$page++;
} }
header("Refresh: 0; url=staffmess.php?sent=1"); header("Refresh: 0; url=staffmess.php?sent=1");

View File

@@ -29,6 +29,7 @@ if ($user["status"] == "pending")
stderr($lang_userdetails['std_sorry'], $lang_userdetails['std_user_not_confirmed']); stderr($lang_userdetails['std_sorry'], $lang_userdetails['std_user_not_confirmed']);
$userInfo = \App\Models\User::query()->with(['valid_medals'])->findOrFail($user['id']); $userInfo = \App\Models\User::query()->with(['valid_medals'])->findOrFail($user['id']);
$userRep = new \App\Repositories\UserRepository();
if ($user['added'] == "0000-00-00 00:00:00" || $user['added'] == null) if ($user['added'] == "0000-00-00 00:00:00" || $user['added'] == null)
$joindate = $lang_userdetails['text_not_available']; $joindate = $lang_userdetails['text_not_available'];
@@ -279,6 +280,14 @@ tr_small($lang_userdetails['row_donated'], "$".htmlspecialchars($user['donated']
if ($user["avatar"]) if ($user["avatar"])
tr_small($lang_userdetails['row_avatar'], return_avatar_image(htmlspecialchars(trim($user["avatar"]))), 1); tr_small($lang_userdetails['row_avatar'], return_avatar_image(htmlspecialchars(trim($user["avatar"]))), 1);
$uclass = get_user_class_image($user["class"]);
$utitle = get_user_class_name($user["class"],false,false,true);
$uclassImg = "<img alt=\"".get_user_class_name($user["class"],false,false,true)."\" title=\"".get_user_class_name($user["class"],false,false,true)."\" src=\"".$uclass."\" /> ".($user['title']!=="" ? "&nbsp;".htmlspecialchars(trim($user["title"]))."" : "");
if ($user['class'] == UC_VIP && !empty($user['vip_until']) && strtotime($user['vip_until'])) {
$uclassImg .= sprintf('%s: %s', $lang_userdetails['row_vip_until'], $user['vip_until']);
}
tr_small($lang_userdetails['row_class'], $uclassImg, 1);
if ($userInfo->valid_medals->isNotEmpty()) { if ($userInfo->valid_medals->isNotEmpty()) {
tr_small($lang_userdetails['row_medal'], build_medal_image($userInfo->valid_medals, 200, $CURUSER['id'] == $user['id']), 1); tr_small($lang_userdetails['row_medal'], build_medal_image($userInfo->valid_medals, 200, $CURUSER['id'] == $user['id']), 1);
$warnMedalJs = <<<JS $warnMedalJs = <<<JS
@@ -289,21 +298,63 @@ jQuery('input[type="checkbox"][name="medal_wearing_status"]').on("change", funct
console.log(response) console.log(response)
if (response.ret != 0) { if (response.ret != 0) {
input.prop("checked", !checked) input.prop("checked", !checked)
alert(response.msg) layer.alert(response.msg)
} }
}, 'json') }, 'json')
}) })
JS; JS;
\Nexus\Nexus::js($warnMedalJs, 'footer', false); \Nexus\Nexus::js($warnMedalJs, 'footer', false);
} }
//User meta
$uclass = get_user_class_image($user["class"]); $metas = $userRep->listMetas($CURUSER['id']);
$utitle = get_user_class_name($user["class"],false,false,true); $props = [];
$uclassImg = "<img alt=\"".get_user_class_name($user["class"],false,false,true)."\" title=\"".get_user_class_name($user["class"],false,false,true)."\" src=\"".$uclass."\" /> ".($user['title']!=="" ? "&nbsp;".htmlspecialchars(trim($user["title"]))."" : ""); $metaKey = \App\Models\UserMeta::META_KEY_CHANGE_USERNAME;
if ($user['class'] == UC_VIP && !empty($user['vip_until']) && strtotime($user['vip_until'])) { if ($metas->has($metaKey)) {
$uclassImg .= sprintf('%s: %s', $lang_userdetails['row_vip_until'], $user['vip_until']); $triggerId = "consume-$metaKey";
$changeUsernameCards = $metas->get($metaKey);
$cardName = $changeUsernameCards->first()->meta_key_text;
$props[] = sprintf(
'<div><strong>[%s]</strong>(%s)<input type="button" value="%s" id="%s"></div>',
$cardName, $changeUsernameCards->count(), $lang_userdetails['consume'], $triggerId
);
$consumeChangeUsernameForm = <<<HTML
<div class="layer-form">
<form id="layer-form-$metaKey">
<input type="hidden" name="params[meta_key]" value="$metaKey">
<div class="form-control-row">
<div class="label">{$lang_userdetails['meta_key_change_username_username']}</div>
<div class="field"><input type="text" name="params[username]"></div>
</div>
</form>
</div>
HTML;
$consumeChangeUsernameJs = <<<JS
jQuery('#{$triggerId}').on("click", function () {
layer.open({
type: 1,
title: "{$lang_userdetails['consume']} {$cardName}",
content: `$consumeChangeUsernameForm`,
btn: ['OK'],
btnAlign: 'c',
yes: function () {
let params = jQuery('#layer-form-{$metaKey}').serialize()
jQuery.post('ajax.php', params + "&action=consumeBenefit", function (response) {
console.log(response)
if (response.ret != 0) {
layer.alert(response.msg)
return
}
window.location.reload()
}, 'json')
}
})
})
JS;
\Nexus\Nexus::js($consumeChangeUsernameJs, 'footer', false);
}
if (!empty($props)) {
tr_small($lang_userdetails['row_user_props'], sprintf('<div style="display: inline">%s</div>', implode('&nbsp;|&nbsp;', $props)), 1);
} }
tr_small($lang_userdetails['row_class'], $uclassImg, 1);
tr_small($lang_userdetails['row_torrent_comment'], ($torrentcomments && ($user["id"] == $CURUSER["id"] || get_user_class() >= $viewhistory_class) ? "<a href=\"userhistory.php?action=viewcomments&amp;id=".$id."\" title=\"".$lang_userdetails['link_view_comments']."\">".$torrentcomments."</a>" : $torrentcomments), 1); tr_small($lang_userdetails['row_torrent_comment'], ($torrentcomments && ($user["id"] == $CURUSER["id"] || get_user_class() >= $viewhistory_class) ? "<a href=\"userhistory.php?action=viewcomments&amp;id=".$id."\" title=\"".$lang_userdetails['link_view_comments']."\">".$torrentcomments."</a>" : $torrentcomments), 1);

View File

@@ -0,0 +1,5 @@
<?php
return [
];

View File

@@ -192,7 +192,7 @@ return [
'ip' => 'IP(Block)', 'ip' => 'IP(Block)',
'ip_begin' => 'Begin IP', 'ip_begin' => 'Begin IP',
'ip_end' => 'End IP', 'ip_end' => 'End IP',
'ip_help' => 'Begin IP/End IP, IP(Block) Choose one', 'ip_help' => 'Fill in the begin IP + end IP, or IP (Block), not both',
'status' => 'Status', 'status' => 'Status',
], ],
'menu' => [ 'menu' => [
@@ -208,4 +208,10 @@ return [
'parent_id' => 'Parent', 'parent_id' => 'Parent',
'min_class' => 'Minimum visible class', 'min_class' => 'Minimum visible class',
], ],
'user_meta' => [
'meta_keys' => [
\App\Models\UserMeta::META_KEY_CHANGE_USERNAME => 'Name Change Card',
\App\Models\UserMeta::META_KEY_PERSONALIZED_USERNAME => 'Rainbow ID',
],
],
]; ];

View File

@@ -0,0 +1,5 @@
<?php
return [
];

View File

@@ -195,7 +195,7 @@ return [
'ip' => 'IP(段)', 'ip' => 'IP(段)',
'ip_begin' => '起始 IP', 'ip_begin' => '起始 IP',
'ip_end' => '结束 IP', 'ip_end' => '结束 IP',
'ip_help' => '起始 IP/结束 IPIP(段) 二选一', 'ip_help' => '填写起始 IP + 结束 IP,或 IP(段),不要同时填写',
'status' => '状态', 'status' => '状态',
], ],
'menu' => [ 'menu' => [
@@ -211,4 +211,10 @@ return [
'parent_id' => '父菜单', 'parent_id' => '父菜单',
'min_class' => '最低可见等级', 'min_class' => '最低可见等级',
], ],
'user_meta' => [
'meta_keys' => [
\App\Models\UserMeta::META_KEY_CHANGE_USERNAME => '更名卡',
\App\Models\UserMeta::META_KEY_PERSONALIZED_USERNAME => '彩虹 ID',
],
],
]; ];

View File

@@ -0,0 +1,5 @@
<?php
return [
];

View File

@@ -192,7 +192,7 @@ return [
'ip' => 'IP(段)', 'ip' => 'IP(段)',
'ip_begin' => '起始 IP', 'ip_begin' => '起始 IP',
'ip_end' => '結束 IP', 'ip_end' => '結束 IP',
'ip_help' => '起始 IP/結束 IPIP(段) 二選一', 'ip_help' => '填寫起始 IP + 結束 IP,或 IP(段),不要同時填寫',
'status' => '狀態', 'status' => '狀態',
], ],
'menu' => [ 'menu' => [
@@ -208,4 +208,10 @@ return [
'parent_id' => '父菜單', 'parent_id' => '父菜單',
'min_class' => '最低可見等級', 'min_class' => '最低可見等級',
], ],
'user_meta' => [
'meta_keys' => [
\App\Models\UserMeta::META_KEY_CHANGE_USERNAME => '更名卡',
\App\Models\UserMeta::META_KEY_PERSONALIZED_USERNAME => '彩虹 ID',
],
],
]; ];