mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-24 20:17:24 +08:00
[api] torrents add tags + promotion + pick
This commit is contained in:
@@ -20,6 +20,22 @@
|
|||||||
<el-input type="password" v-model="formData.password_confirmation" placeholder=""></el-input>
|
<el-input type="password" v-model="formData.password_confirmation" placeholder=""></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="UID" prop="id">
|
||||||
|
<el-input v-model="formData.id" type="number" placeholder=""></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Class" prop="class">
|
||||||
|
<el-select v-model="formData.class" filterable clearable>
|
||||||
|
<el-option
|
||||||
|
v-for="(item, index) in userClasses"
|
||||||
|
:key="index"
|
||||||
|
:label="item"
|
||||||
|
:value="index"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -47,11 +63,14 @@ export default {
|
|||||||
const { id } = route.query
|
const { id } = route.query
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
id: id,
|
id: id,
|
||||||
|
userClasses: [],
|
||||||
formData: {
|
formData: {
|
||||||
username: '',
|
username: '',
|
||||||
email: '',
|
email: '',
|
||||||
password: '',
|
password: '',
|
||||||
password_confirmation: '',
|
password_confirmation: '',
|
||||||
|
id: '',
|
||||||
|
class: ''
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
username: [
|
username: [
|
||||||
@@ -68,8 +87,8 @@ export default {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
onMounted( () => {
|
onMounted( async () => {
|
||||||
|
await listAllClass()
|
||||||
})
|
})
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
|
||||||
@@ -83,6 +102,12 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const listAllClass = async () => {
|
||||||
|
let res = await api.listClass()
|
||||||
|
state.userClasses = res.data
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...toRefs(state),
|
...toRefs(state),
|
||||||
formRef,
|
formRef,
|
||||||
|
|||||||
@@ -33,9 +33,16 @@ class TorrentResource extends JsonResource
|
|||||||
'seeders' => $this->seeders,
|
'seeders' => $this->seeders,
|
||||||
'times_completed' => $this->times_completed,
|
'times_completed' => $this->times_completed,
|
||||||
'numfiles' => $this->numfiles,
|
'numfiles' => $this->numfiles,
|
||||||
|
'sp_state' => $this->sp_state,
|
||||||
|
'sp_state_real' => $this->sp_state_real,
|
||||||
|
'sp_state_real_text' => $this->spStateRealText,
|
||||||
|
'hr' => $this->hr,
|
||||||
|
'pick_type' => $this->picktype,
|
||||||
|
'pick_time' => $this->picktime,
|
||||||
'download_url' => $this->download_url,
|
'download_url' => $this->download_url,
|
||||||
'user' => new UserResource($this->whenLoaded('user')),
|
'user' => new UserResource($this->whenLoaded('user')),
|
||||||
'basic_category' => new CategoryResource($this->whenLoaded('basic_category')),
|
'basic_category' => new CategoryResource($this->whenLoaded('basic_category')),
|
||||||
|
'tags' => TagResource::collection($this->whenLoaded('tags')),
|
||||||
];
|
];
|
||||||
$descriptionArr = format_description($this->descr);
|
$descriptionArr = format_description($this->descr);
|
||||||
$out['cover'] = get_image_from_description($descriptionArr, true);
|
$out['cover'] = get_image_from_description($descriptionArr, true);
|
||||||
|
|||||||
+60
-2
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Repositories\TagRepository;
|
||||||
|
|
||||||
class Torrent extends NexusModel
|
class Torrent extends NexusModel
|
||||||
{
|
{
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@@ -9,9 +11,11 @@ class Torrent extends NexusModel
|
|||||||
'category', 'source', 'medium', 'codec', 'standard', 'processing', 'team', 'audiocodec',
|
'category', 'source', 'medium', 'codec', 'standard', 'processing', 'team', 'audiocodec',
|
||||||
'size', 'added', 'type', 'numfiles', 'owner', 'nfo', 'sp_state', 'promotion_time_type',
|
'size', 'added', 'type', 'numfiles', 'owner', 'nfo', 'sp_state', 'promotion_time_type',
|
||||||
'promotion_until', 'anonymous', 'url', 'pos_state', 'cache_stamp', 'picktype', 'picktime',
|
'promotion_until', 'anonymous', 'url', 'pos_state', 'cache_stamp', 'picktype', 'picktime',
|
||||||
'last_reseed', 'pt_gen', 'tags', 'technical_info'
|
'last_reseed', 'pt_gen', 'technical_info'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private static $globalPromotionState;
|
||||||
|
|
||||||
const VISIBLE_YES = 'yes';
|
const VISIBLE_YES = 'yes';
|
||||||
const VISIBLE_NO = 'no';
|
const VISIBLE_NO = 'no';
|
||||||
|
|
||||||
@@ -49,6 +53,59 @@ class Torrent extends NexusModel
|
|||||||
self::HR_YES => ['text' => 'YES'],
|
self::HR_YES => ['text' => 'YES'],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const PROMOTION_NORMAL = 1;
|
||||||
|
const PROMOTION_FREE = 2;
|
||||||
|
const PROMOTION_TWO_TIMES_UP = 3;
|
||||||
|
const PROMOTION_FREE_TWO_TIMES_UP = 4;
|
||||||
|
const PROMOTION_HALF_DOWN = 5;
|
||||||
|
const PROMOTION_HALF_DOWN_TWO_TIMES_UP = 6;
|
||||||
|
const PROMOTION_ONE_THIRD_DOWN = 7;
|
||||||
|
|
||||||
|
public static $promotionTypes = [
|
||||||
|
self::PROMOTION_NORMAL => ['text' => 'Normal', 'up_multiplier' => 1, 'down_multiplier' => 1],
|
||||||
|
self::PROMOTION_FREE => ['text' => 'Free', 'up_multiplier' => 1, 'down_multiplier' => 0],
|
||||||
|
self::PROMOTION_TWO_TIMES_UP => ['text' => '2X', 'up_multiplier' => 2, 'down_multiplier' => 1],
|
||||||
|
self::PROMOTION_FREE_TWO_TIMES_UP => ['text' => '2X Free', 'up_multiplier' => 2, 'down_multiplier' => 0],
|
||||||
|
self::PROMOTION_HALF_DOWN => ['text' => '50%', 'up_multiplier' => 1, 'down_multiplier' => 0.5],
|
||||||
|
self::PROMOTION_HALF_DOWN_TWO_TIMES_UP => ['text' => '2X 50%', 'up_multiplier' => 2, 'down_multiplier' => 0.5],
|
||||||
|
self::PROMOTION_ONE_THIRD_DOWN => ['text' => '30%', 'up_multiplier' => 1, 'down_multiplier' => 0.3],
|
||||||
|
];
|
||||||
|
|
||||||
|
public function getSpStateRealTextAttribute()
|
||||||
|
{
|
||||||
|
$spStateReal = $this->sp_state_real;
|
||||||
|
return self::$promotionTypes[$spStateReal]['text'] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSpStateRealAttribute()
|
||||||
|
{
|
||||||
|
$spState = $this->sp_state;
|
||||||
|
$global = self::getGlobalPromotionState();
|
||||||
|
$log = sprintf('torrent: %s sp_state: %s, global sp state: %s', $this->id, $spState, $global);
|
||||||
|
if ($global != self::PROMOTION_NORMAL) {
|
||||||
|
$spState = $global;
|
||||||
|
$log .= sprintf(", global != %s, set sp_state to global: %s", self::PROMOTION_NORMAL, $global);
|
||||||
|
}
|
||||||
|
if (!isset(self::$promotionTypes[$spState])) {
|
||||||
|
$log .= ", but now sp_state: $spState, is invalid, reset to: " . self::PROMOTION_NORMAL;
|
||||||
|
$spState = self::PROMOTION_NORMAL;
|
||||||
|
}
|
||||||
|
do_log($log, 'debug');
|
||||||
|
return $spState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getGlobalPromotionState()
|
||||||
|
{
|
||||||
|
if (is_null(self::$globalPromotionState)) {
|
||||||
|
$result = TorrentState::query()->first(['global_sp_state']);
|
||||||
|
if (!$result) {
|
||||||
|
do_log("global sp state no value", 'error');
|
||||||
|
}
|
||||||
|
self::$globalPromotionState = $result->global_sp_state ?? false;
|
||||||
|
}
|
||||||
|
return self::$globalPromotionState;
|
||||||
|
}
|
||||||
|
|
||||||
public function getHrAttribute(): string
|
public function getHrAttribute(): string
|
||||||
{
|
{
|
||||||
$hrMode = Setting::get('hr.mode');
|
$hrMode = Setting::get('hr.mode');
|
||||||
@@ -208,6 +265,7 @@ class Torrent extends NexusModel
|
|||||||
|
|
||||||
public function tags(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
public function tags(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Tag::class, 'torrent_tags', 'torrent_id', 'tag_id');
|
return $this->belongsToMany(Tag::class, 'torrent_tags', 'torrent_id', 'tag_id')
|
||||||
|
->orderByRaw(sprintf("field(`tags`.`id`,%s)", TagRepository::getOrderByFieldIdString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
|
||||||
|
class TorrentState extends NexusModel
|
||||||
|
{
|
||||||
|
public $incrementing = false;
|
||||||
|
|
||||||
|
protected $table = 'torrents_state';
|
||||||
|
}
|
||||||
+1
-1
@@ -116,7 +116,7 @@ class User extends Authenticatable
|
|||||||
*/
|
*/
|
||||||
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'
|
'leechwarn', 'leechwarnuntil', 'page', 'class'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ use Nexus\Database\NexusDB;
|
|||||||
|
|
||||||
class TagRepository extends BaseRepository
|
class TagRepository extends BaseRepository
|
||||||
{
|
{
|
||||||
|
private static $orderByFieldIdString;
|
||||||
|
|
||||||
public function getList(array $params)
|
public function getList(array $params)
|
||||||
{
|
{
|
||||||
$query = $this->createBasicQuery();
|
$query = $this->createBasicQuery();
|
||||||
@@ -41,7 +43,7 @@ class TagRepository extends BaseRepository
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createBasicQuery()
|
public static function createBasicQuery()
|
||||||
{
|
{
|
||||||
return Tag::query()->orderBy('priority', 'desc')->orderBy('id', 'desc');
|
return Tag::query()->orderBy('priority', 'desc')->orderBy('id', 'desc');
|
||||||
}
|
}
|
||||||
@@ -127,5 +129,14 @@ class TagRepository extends BaseRepository
|
|||||||
return count($values);
|
return count($values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getOrderByFieldIdString()
|
||||||
|
{
|
||||||
|
if (is_null(self::$orderByFieldIdString)) {
|
||||||
|
$results = self::createBasicQuery()->get(['id']);
|
||||||
|
self::$orderByFieldIdString = $results->isEmpty() ? '0' : $results->implode('id', ',');
|
||||||
|
}
|
||||||
|
return self::$orderByFieldIdString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class TorrentRepository extends BaseRepository
|
|||||||
|
|
||||||
$query = $this->handleGetListSort($query, $params);
|
$query = $this->handleGetListSort($query, $params);
|
||||||
|
|
||||||
$with = ['user'];
|
$with = ['user', 'tags'];
|
||||||
$torrents = $query->with($with)->paginate();
|
$torrents = $query->with($with)->paginate();
|
||||||
$userArr = $user->toArray();
|
$userArr = $user->toArray();
|
||||||
foreach($torrents as &$item) {
|
foreach($torrents as &$item) {
|
||||||
|
|||||||
@@ -66,27 +66,61 @@ class UserRepository extends BaseRepository
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create user
|
||||||
|
*
|
||||||
|
* @param array $params must: username, email, password, password_confirmation. optional: id, class
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
public function store(array $params)
|
public function store(array $params)
|
||||||
{
|
{
|
||||||
$password = $params['password'];
|
$password = $params['password'];
|
||||||
if ($password != $params['password_confirmation']) {
|
if ($password != $params['password_confirmation']) {
|
||||||
throw new \InvalidArgumentException("password confirmation != password");
|
throw new \InvalidArgumentException("password confirmation != password");
|
||||||
}
|
}
|
||||||
|
$username = $params['username'];
|
||||||
|
if (!validusername($username)) {
|
||||||
|
throw new \InvalidArgumentException("Innvalid username: $username");
|
||||||
|
}
|
||||||
|
$email = htmlspecialchars(trim($params['email']));
|
||||||
|
$email = safe_email($email);
|
||||||
|
if (!check_email($email)) {
|
||||||
|
throw new \InvalidArgumentException("Innvalid email: $email");
|
||||||
|
}
|
||||||
|
if (User::query()->where('email', $email)->exists()) {
|
||||||
|
throw new \InvalidArgumentException("The email address: $email is already in use");
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
$class = !empty($params['class']) ? intval($params['class']) : User::CLASS_USER;
|
||||||
|
if (!isset(User::$classes[$class])) {
|
||||||
|
throw new \InvalidArgumentException("Invalid user class: $class");
|
||||||
|
}
|
||||||
$setting = Setting::get('main');
|
$setting = Setting::get('main');
|
||||||
$secret = mksecret();
|
$secret = mksecret();
|
||||||
$passhash = md5($secret . $password . $secret);
|
$passhash = md5($secret . $password . $secret);
|
||||||
$data = [
|
$data = [
|
||||||
'username' => $params['username'],
|
'username' => $username,
|
||||||
'email' => $params['email'],
|
'email' => $email,
|
||||||
'secret' => $secret,
|
'secret' => $secret,
|
||||||
'editsecret' => '',
|
'editsecret' => '',
|
||||||
'passhash' => $passhash,
|
'passhash' => $passhash,
|
||||||
'stylesheet' => $setting['defstylesheet'],
|
'stylesheet' => $setting['defstylesheet'],
|
||||||
'added' => now()->toDateTimeString(),
|
'added' => now()->toDateTimeString(),
|
||||||
'status' => User::STATUS_CONFIRMED,
|
'status' => User::STATUS_CONFIRMED,
|
||||||
|
'class' => $class
|
||||||
];
|
];
|
||||||
$user = User::query()->create($data);
|
$user = new User($data);
|
||||||
|
if ($params['id']) {
|
||||||
|
if (User::query()->where('id', $params['id'])->exists()) {
|
||||||
|
throw new \InvalidArgumentException("uid: {$params['id']} already exists.");
|
||||||
|
}
|
||||||
|
do_log("[CREATE_USER], specific id: " . $params['id']);
|
||||||
|
$user->id = $params['id'];
|
||||||
|
}
|
||||||
|
$user->save();
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class CreateUsersTable extends Migration
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Schema::create('users', function (Blueprint $table) {
|
Schema::create('users', function (Blueprint $table) {
|
||||||
$table->increments('id');
|
$table->id('id')->startingValue(10001);
|
||||||
$table->string('username', 40)->default('')->unique('username');
|
$table->string('username', 40)->default('')->unique('username');
|
||||||
$table->string('passhash', 32)->default('');
|
$table->string('passhash', 32)->default('');
|
||||||
$table->binary('secret');
|
$table->binary('secret');
|
||||||
@@ -133,6 +133,7 @@ class CreateUsersTable extends Migration
|
|||||||
$table->enum('showfb', ['yes', 'no'])->default('yes');
|
$table->enum('showfb', ['yes', 'no'])->default('yes');
|
||||||
$table->string('page')->nullable()->default('');
|
$table->string('page')->nullable()->default('');
|
||||||
$table->index(['status', 'added'], 'status_added');
|
$table->index(['status', 'added'], 'status_added');
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,9 @@ function user_to_peasant($down_floor_gb, $minratio){
|
|||||||
function ban_user_with_leech_warning_expired()
|
function ban_user_with_leech_warning_expired()
|
||||||
{
|
{
|
||||||
$dt = date("Y-m-d H:i:s"); // take date time
|
$dt = date("Y-m-d H:i:s"); // take date time
|
||||||
|
// VIP or above won't effect
|
||||||
$results = \App\Models\User::query()
|
$results = \App\Models\User::query()
|
||||||
|
->where('class', '<', \App\Models\User::CLASS_VIP)
|
||||||
->where('enabled', \App\Models\User::ENABLED_YES)
|
->where('enabled', \App\Models\User::ENABLED_YES)
|
||||||
->where('leechwarn', 'yes')
|
->where('leechwarn', 'yes')
|
||||||
->where('leechwarnuntil', '<', $dt)
|
->where('leechwarnuntil', '<', $dt)
|
||||||
|
|||||||
+12
-32
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Nexus\Install;
|
namespace Nexus\Install;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Repositories\UserRepository;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Nexus\Database\NexusDB;
|
use Nexus\Database\NexusDB;
|
||||||
|
|
||||||
@@ -384,44 +386,22 @@ class Install
|
|||||||
|
|
||||||
public function createAdministrator($username, $email, $password, $confirmPassword)
|
public function createAdministrator($username, $email, $password, $confirmPassword)
|
||||||
{
|
{
|
||||||
$count = get_row_count('users', 'where class = 16');
|
$class = User::CLASS_STAFF_LEADER;
|
||||||
|
$count = get_row_count('users', 'where class = ' . $class);
|
||||||
if ($count > 0) {
|
if ($count > 0) {
|
||||||
throw new \InvalidArgumentException("Administrator already exists");
|
throw new \InvalidArgumentException("Administrator already exists");
|
||||||
}
|
}
|
||||||
if (!validusername($username)) {
|
$data = [
|
||||||
throw new \InvalidArgumentException("Innvalid username: $username");
|
|
||||||
}
|
|
||||||
$email = htmlspecialchars(trim($email));
|
|
||||||
$email = safe_email($email);
|
|
||||||
if (!check_email($email)) {
|
|
||||||
throw new \InvalidArgumentException("Innvalid email: $email");
|
|
||||||
}
|
|
||||||
$res = sql_query("SELECT id FROM users WHERE email=" . sqlesc($email));
|
|
||||||
$arr = mysql_fetch_row($res);
|
|
||||||
if ($arr) {
|
|
||||||
throw new \InvalidArgumentException("The email address: $email is already in use");
|
|
||||||
}
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
if ($password != $confirmPassword) {
|
|
||||||
throw new \InvalidArgumentException("confirmPassword: $confirmPassword != password");
|
|
||||||
}
|
|
||||||
$setting = get_setting('main');
|
|
||||||
$secret = mksecret();
|
|
||||||
$passhash = md5($secret . $password . $secret);
|
|
||||||
$insert = [
|
|
||||||
'username' => $username,
|
'username' => $username,
|
||||||
'passhash' => $passhash,
|
|
||||||
'secret' => $secret,
|
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
'stylesheet' => $setting['defstylesheet'],
|
'password' => $password,
|
||||||
'class' => 16,
|
'password_confirmation' => $confirmPassword,
|
||||||
'status' => 'confirmed',
|
'class' => $class,
|
||||||
'added' => date('Y-m-d H:i:s'),
|
'id' => 1,
|
||||||
];
|
];
|
||||||
$this->doLog("[CREATE ADMINISTRATOR] " . json_encode($insert));
|
$user = (new UserRepository())->store($data);
|
||||||
return NexusDB::insert('users', $insert);
|
$this->doLog("[CREATE ADMINISTRATOR] " . $user->toJson());
|
||||||
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createEnvFile($data, $scene = 'install')
|
public function createEnvFile($data, $scene = 'install')
|
||||||
|
|||||||
Reference in New Issue
Block a user