2021-05-15 19:29:44 +08:00
< ? php
namespace App\Repositories ;
2022-07-19 14:15:35 +08:00
use App\Exceptions\InsufficientPermissionException ;
2021-06-03 21:13:59 +08:00
use App\Exceptions\NexusException ;
2021-05-15 19:29:44 +08:00
use App\Models\AudioCodec ;
use App\Models\Category ;
2022-05-05 22:19:48 +08:00
use App\Models\Claim ;
2021-05-15 19:29:44 +08:00
use App\Models\Codec ;
2021-06-21 02:01:26 +08:00
use App\Models\HitAndRun ;
2021-05-15 19:29:44 +08:00
use App\Models\Media ;
2021-06-21 02:01:26 +08:00
use App\Models\Message ;
2021-05-16 14:44:02 +08:00
use App\Models\Peer ;
2021-05-15 19:29:44 +08:00
use App\Models\Processing ;
2021-06-21 19:56:25 +08:00
use App\Models\SearchBox ;
use App\Models\Setting ;
2021-05-17 00:10:15 +08:00
use App\Models\Snatch ;
2021-05-15 19:29:44 +08:00
use App\Models\Source ;
2022-06-15 15:43:33 +08:00
use App\Models\StaffMessage ;
2021-05-15 19:29:44 +08:00
use App\Models\Standard ;
use App\Models\Team ;
use App\Models\Torrent ;
2022-06-15 15:43:33 +08:00
use App\Models\TorrentOperationLog ;
2021-06-03 21:13:59 +08:00
use App\Models\TorrentSecret ;
2022-07-19 14:15:35 +08:00
use App\Models\TorrentTag ;
2021-05-15 19:29:44 +08:00
use App\Models\User ;
2021-06-21 02:01:26 +08:00
use Carbon\Carbon ;
2021-06-02 19:01:28 +08:00
use Hashids\Hashids ;
2021-05-15 19:29:44 +08:00
use Illuminate\Database\Eloquent\Builder ;
2022-07-19 14:15:35 +08:00
use Illuminate\Support\Arr ;
use Illuminate\Support\Facades\Auth ;
2022-09-12 22:02:57 +08:00
use Illuminate\Support\Facades\DB ;
2021-06-03 21:13:59 +08:00
use Illuminate\Support\Str ;
2022-03-31 16:28:08 +08:00
use Nexus\Database\NexusDB ;
2021-05-15 19:29:44 +08:00
class TorrentRepository extends BaseRepository
{
/**
* fetch torrent list
*
* @ param array $params
* @ return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*/
2022-03-04 16:16:56 +08:00
public function getList ( array $params , User $user )
2021-05-15 19:29:44 +08:00
{
$query = Torrent :: query ();
if ( ! empty ( $params [ 'category' ])) {
$query -> where ( 'category' , $params [ 'category' ]);
}
if ( ! empty ( $params [ 'source' ])) {
$query -> where ( 'source' , $params [ 'source' ]);
}
if ( ! empty ( $params [ 'medium' ])) {
$query -> where ( 'medium' , $params [ 'medium' ]);
}
if ( ! empty ( $params [ 'codec' ])) {
$query -> where ( 'codec' , $params [ 'codec' ]);
}
if ( ! empty ( $params [ 'audio_codec' ])) {
$query -> where ( 'audiocodec' , $params [ 'audio_codec' ]);
}
if ( ! empty ( $params [ 'standard' ])) {
$query -> where ( 'standard' , $params [ 'standard' ]);
}
if ( ! empty ( $params [ 'processing' ])) {
$query -> where ( 'processing' , $params [ 'processing' ]);
}
if ( ! empty ( $params [ 'team' ])) {
$query -> where ( 'team' , $params [ 'team' ]);
}
if ( ! empty ( $params [ 'owner' ])) {
$query -> where ( 'owner' , $params [ 'owner' ]);
}
if ( ! empty ( $params [ 'visible' ])) {
$query -> where ( 'visible' , $params [ 'visible' ]);
}
if ( ! empty ( $params [ 'query' ])) {
$query -> where ( function ( Builder $query ) use ( $params ) {
$query -> where ( 'name' , 'like' , " % { $params [ 'query' ] } % " )
-> orWhere ( 'small_descr' , 'like' , " % { $params [ 'query' ] } % " );
});
}
2022-02-21 22:51:42 +08:00
if ( ! empty ( $params [ 'category_mode' ])) {
$query -> whereHas ( 'basic_category' , function ( Builder $query ) use ( $params ) {
$query -> where ( 'mode' , $params [ 'category_mode' ]);
});
}
2022-02-28 23:20:42 +08:00
$query = $this -> handleGetListSort ( $query , $params );
2021-05-15 19:29:44 +08:00
2022-03-13 21:45:48 +08:00
$with = [ 'user' , 'tags' ];
2022-02-28 23:20:42 +08:00
$torrents = $query -> with ( $with ) -> paginate ();
2022-03-04 16:16:56 +08:00
$userArr = $user -> toArray ();
2022-07-19 14:15:35 +08:00
foreach ( $torrents as & $item ) {
2022-03-04 16:16:56 +08:00
$item -> download_url = $this -> getDownloadUrl ( $item -> id , $userArr );
}
2021-05-15 19:29:44 +08:00
return $torrents ;
}
2022-03-04 16:16:56 +08:00
public function getDetail ( $id , User $user )
{
2022-03-30 15:37:11 +08:00
$with = [
'user' , 'basic_audio_codec' , 'basic_category' , 'basic_codec' , 'basic_media' , 'basic_source' , 'basic_standard' , 'basic_team' ,
2022-07-19 14:15:35 +08:00
'thanks' => function ( $query ) use ( $user ) {
$query -> where ( 'userid' , $user -> id );
},
'reward_logs' => function ( $query ) use ( $user ) {
$query -> where ( 'userid' , $user -> id );
},
2022-03-30 15:37:11 +08:00
];
$result = Torrent :: query () -> with ( $with ) -> withCount ([ 'peers' , 'thank_users' , 'reward_logs' ]) -> visible () -> findOrFail ( $id );
2022-03-04 16:16:56 +08:00
$result -> download_url = $this -> getDownloadUrl ( $id , $user -> toArray ());
return $result ;
}
private function getDownloadUrl ( $id , array $user ) : string
{
return sprintf (
'%s/download.php?downhash=%s|%s' ,
getSchemeAndHttpHost (), $user [ 'id' ], $this -> encryptDownHash ( $id , $user )
);
}
2022-02-28 23:20:42 +08:00
private function handleGetListSort ( Builder $query , array $params )
{
if ( empty ( $params [ 'sort_field' ]) && empty ( $params [ 'sort_type' ])) {
//the default torrent list sort
return $query -> orderBy ( 'pos_state' , 'desc' ) -> orderBy ( 'id' , 'desc' );
}
list ( $sortField , $sortType ) = $this -> getSortFieldAndType ( $params );
return $query -> orderBy ( $sortField , $sortType );
}
2021-06-21 19:56:25 +08:00
public function getSearchBox ( $id = null )
2021-05-15 19:29:44 +08:00
{
2021-06-21 19:56:25 +08:00
if ( is_null ( $id )) {
$id = Setting :: get ( 'main.browsecat' );
}
$searchBox = SearchBox :: query () -> findOrFail ( $id );
$category = $searchBox -> categories () -> orderBy ( 'sort_index' ) -> orderBy ( 'id' ) -> get ();
2021-05-15 19:29:44 +08:00
$modalRows = [];
2021-06-21 19:56:25 +08:00
$modalRows [] = $categoryFormatted = $this -> formatRow ( Category :: getLabelName (), $category , 'category' );
if ( $searchBox -> showsubcat ) {
if ( $searchBox -> showsource ) {
$source = Source :: query () -> orderBy ( 'sort_index' ) -> orderBy ( 'id' ) -> get ();
$modalRows [] = $this -> formatRow ( Source :: getLabelName (), $source , 'source' );
}
if ( $searchBox -> showmedia ) {
$media = Media :: query () -> orderBy ( 'sort_index' ) -> orderBy ( 'id' ) -> get ();
$modalRows [] = $this -> formatRow ( Media :: getLabelName (), $media , 'medium' );
}
if ( $searchBox -> showcodec ) {
$codec = Codec :: query () -> orderBy ( 'sort_index' ) -> orderBy ( 'id' ) -> get ();
$modalRows [] = $this -> formatRow ( Codec :: getLabelName (), $codec , 'codec' );
}
if ( $searchBox -> showstandard ) {
$standard = Standard :: query () -> orderBy ( 'sort_index' ) -> orderBy ( 'id' ) -> get ();
$modalRows [] = $this -> formatRow ( Standard :: getLabelName (), $standard , 'standard' );
}
if ( $searchBox -> showprocessing ) {
$processing = Processing :: query () -> orderBy ( 'sort_index' ) -> orderBy ( 'id' ) -> get ();
$modalRows [] = $this -> formatRow ( Processing :: getLabelName (), $processing , 'processing' );
}
if ( $searchBox -> showteam ) {
$team = Team :: query () -> orderBy ( 'sort_index' ) -> orderBy ( 'id' ) -> get ();
$modalRows [] = $this -> formatRow ( Team :: getLabelName (), $team , 'team' );
}
if ( $searchBox -> showaudiocodec ) {
$audioCodec = AudioCodec :: query () -> orderBy ( 'sort_index' ) -> orderBy ( 'id' ) -> get ();
$modalRows [] = $this -> formatRow ( AudioCodec :: getLabelName (), $audioCodec , 'audio_codec' );
}
}
2021-05-15 19:29:44 +08:00
$results = [];
$categories = $categoryFormatted [ 'rows' ];
$categories [ 0 ][ 'active' ] = 1 ;
$results [ 'categories' ] = $categories ;
$results [ 'modal_rows' ] = $modalRows ;
return $results ;
}
private function formatRow ( $header , $items , $name )
{
$result [ 'header' ] = $header ;
$result [ 'rows' ][] = [
2021-06-21 19:56:25 +08:00
'label' => 'All' ,
2021-05-15 19:29:44 +08:00
'value' => 0 ,
'name' => $name ,
'active' => 1 ,
];
foreach ( $items as $value ) {
$item = [
'label' => $value -> name ,
'value' => $value -> id ,
'name' => $name ,
'active' => 0 ,
];
$result [ 'rows' ][] = $item ;
}
return $result ;
}
2021-05-16 14:44:02 +08:00
public function listPeers ( $torrentId )
{
$seederList = $leecherList = collect ();
2022-04-18 19:07:35 +08:00
$peers = Peer :: query ()
-> where ( 'torrent' , $torrentId )
-> groupBy ( 'peer_id' )
-> with ([ 'user' , 'relative_torrent' ])
-> get ()
2022-07-19 14:15:35 +08:00
-> groupBy ( 'seeder' );
2021-05-16 14:44:02 +08:00
if ( $peers -> has ( Peer :: SEEDER_YES )) {
$seederList = $peers -> get ( Peer :: SEEDER_YES ) -> sort ( function ( $a , $b ) {
$x = $a -> uploaded ;
$y = $b -> uploaded ;
if ( $x == $y )
return 0 ;
if ( $x < $y )
return 1 ;
return - 1 ;
});
$seederList = $this -> formatPeers ( $seederList );
}
if ( $peers -> has ( Peer :: SEEDER_NO )) {
$leecherList = $peers -> get ( Peer :: SEEDER_NO ) -> sort ( function ( $a , $b ) {
$x = $a -> to_go ;
$y = $b -> to_go ;
if ( $x == $y )
return 0 ;
if ( $x < $y )
return - 1 ;
return 1 ;
});
$leecherList = $this -> formatPeers ( $leecherList );
}
return [
'seeder_list' => $seederList ,
'leecher_list' => $leecherList ,
];
}
2021-05-17 00:10:15 +08:00
public function getPeerUploadSpeed ( $peer ) : string
2021-05-16 14:44:02 +08:00
{
$diff = $peer -> uploaded - $peer -> uploadoffset ;
$seconds = max ( 1 , $peer -> started -> diffInSeconds ( $peer -> last_action ));
return mksize ( $diff / $seconds ) . '/s' ;
}
2021-05-17 00:10:15 +08:00
public function getPeerDownloadSpeed ( $peer ) : string
2021-05-16 14:44:02 +08:00
{
$diff = $peer -> downloaded - $peer -> downloadoffset ;
if ( $peer -> isSeeder ()) {
$seconds = max ( 1 , $peer -> started -> diffInSeconds ( $peer -> finishedat ));
} else {
$seconds = max ( 1 , $peer -> started -> diffInSeconds ( $peer -> last_action ));
}
return mksize ( $diff / $seconds ) . '/s' ;
}
public function getDownloadProgress ( $peer ) : string
{
return sprintf ( " %.2f%% " , 100 * ( 1 - ( $peer -> to_go / $peer -> relative_torrent -> size )));
}
public function getShareRatio ( $peer )
{
if ( $peer -> downloaded ) {
$ratio = floor (( $peer -> uploaded / $peer -> downloaded ) * 1000 ) / 1000 ;
} elseif ( $peer -> uploaded ) {
//@todo 读语言文件
$ratio = '无限' ;
} else {
$ratio = '---' ;
}
return $ratio ;
}
private function formatPeers ( $peers )
{
foreach ( $peers as & $item ) {
2021-05-17 00:10:15 +08:00
$item -> upload_text = sprintf ( '%s@%s' , mksize ( $item -> uploaded ), $this -> getPeerUploadSpeed ( $item ));
$item -> download_text = sprintf ( '%s@%s' , mksize ( $item -> downloaded ), $this -> getPeerDownloadSpeed ( $item ));
2021-05-16 14:44:02 +08:00
$item -> download_progress = $this -> getDownloadProgress ( $item );
$item -> share_ratio = $this -> getShareRatio ( $item );
2021-05-17 00:38:42 +08:00
$item -> connect_time_total = $item -> started -> diffForHumans ();
$item -> last_action_human = $item -> last_action -> diffForHumans ();
2021-05-16 14:44:02 +08:00
$item -> agent_human = htmlspecialchars ( get_agent ( $item -> peer_id , $item -> agent ));
}
return $peers ;
}
2021-05-17 00:10:15 +08:00
public function listSnatches ( $torrentId )
{
$snatches = Snatch :: query ()
-> where ( 'torrentid' , $torrentId )
2021-05-17 00:38:42 +08:00
-> where ( 'finished' , Snatch :: FINISHED_YES )
2021-05-17 00:10:15 +08:00
-> with ([ 'user' ])
-> orderBy ( 'completedat' , 'desc' )
2021-05-17 00:56:23 +08:00
-> paginate ();
2021-05-17 00:10:15 +08:00
return $snatches ;
}
public function getSnatchUploadSpeed ( $snatch )
{
if ( $snatch -> seedtime <= 0 ) {
2022-07-19 14:15:35 +08:00
$speed = mksize ( 0 );
2021-05-17 00:44:35 +08:00
} else {
$speed = mksize ( $snatch -> uploaded / ( $snatch -> seedtime + $snatch -> leechtime ));
2021-05-17 00:10:15 +08:00
}
2021-05-17 00:44:35 +08:00
return " $speed /s " ;
2021-05-17 00:10:15 +08:00
}
public function getSnatchDownloadSpeed ( $snatch )
{
if ( $snatch -> leechtime <= 0 ) {
2021-05-17 00:44:35 +08:00
$speed = mksize ( 0 );
} else {
$speed = mksize ( $snatch -> downloaded / $snatch -> leechtime );
2021-05-17 00:10:15 +08:00
}
2021-05-17 00:44:35 +08:00
return " $speed /s " ;
2021-05-17 00:10:15 +08:00
}
2021-06-02 08:44:22 +08:00
public function encryptDownHash ( $id , $user ) : string
2021-06-02 19:01:28 +08:00
{
$key = $this -> getEncryptDownHashKey ( $user );
return ( new Hashids ( $key )) -> encode ( $id );
}
public function decryptDownHash ( $downHash , $user )
{
$key = $this -> getEncryptDownHashKey ( $user );
return ( new Hashids ( $key )) -> decode ( $downHash );
}
private function getEncryptDownHashKey ( $user )
2021-06-01 23:33:28 +08:00
{
2022-03-04 16:16:56 +08:00
if ( $user instanceof User ) {
$user = $user -> toArray ();
}
2021-06-02 08:44:22 +08:00
if ( ! is_array ( $user ) || empty ( $user [ 'passkey' ]) || empty ( $user [ 'id' ])) {
$user = User :: query () -> findOrFail ( intval ( $user ), [ 'id' , 'passkey' ]) -> toArray ();
}
//down hash is relative to user passkey
2021-06-02 19:01:28 +08:00
return md5 ( $user [ 'passkey' ] . date ( 'Ymd' ) . $user [ 'id' ]);
2021-06-01 23:33:28 +08:00
}
2021-06-03 21:13:59 +08:00
public function getTrackerReportAuthKey ( $id , $uid , $initializeIfNotExists = false ) : string
2021-06-03 03:04:24 +08:00
{
2021-06-03 21:13:59 +08:00
$key = $this -> getTrackerReportAuthKeySecret ( $id , $uid , $initializeIfNotExists );
$hash = ( new Hashids ( $key )) -> encode ( date ( 'Ymd' ));
return sprintf ( '%s|%s|%s' , $id , $uid , $hash );
2021-06-03 03:04:24 +08:00
}
2021-06-03 21:13:59 +08:00
/**
* check tracker report authkey
* if valid , the result will be the date the key generate , else if will be empty string
*
* @ date 2021 / 6 / 3
* @ time 20 : 29
* @ param $authKey
* @ return array
* @ throws NexusException
*/
public function checkTrackerReportAuthKey ( $authKey )
2021-06-03 03:04:24 +08:00
{
2021-06-03 21:13:59 +08:00
$arr = explode ( '|' , $authKey );
if ( count ( $arr ) != 3 ) {
throw new NexusException ( 'Invalid authkey' );
}
$id = $arr [ 0 ];
$uid = $arr [ 1 ];
$hash = $arr [ 2 ];
$key = $this -> getTrackerReportAuthKeySecret ( $id , $uid );
return ( new Hashids ( $key )) -> decode ( $hash );
2021-06-03 03:04:24 +08:00
}
2021-06-03 21:13:59 +08:00
private function getTrackerReportAuthKeySecret ( $id , $uid , $initializeIfNotExists = false )
2021-06-03 03:04:24 +08:00
{
2022-04-06 21:32:57 +08:00
$secret = TorrentSecret :: query ()
-> where ( 'uid' , $uid )
-> whereIn ( 'torrent_id' , [ 0 , $id ])
-> orderBy ( 'torrent_id' , 'desc' )
-> orderBy ( 'id' , 'desc' )
-> first ();
2021-06-03 21:13:59 +08:00
if ( $secret ) {
return $secret -> secret ;
2021-06-03 03:04:24 +08:00
}
2021-06-03 21:13:59 +08:00
if ( $initializeIfNotExists ) {
$insert = [
'uid' => $uid ,
'torrent_id' => 0 ,
'secret' => Str :: random (),
];
2022-04-06 21:32:57 +08:00
do_log ( " [INSERT_TORRENT_SECRET] " . json_encode ( $insert ));
2021-06-03 21:13:59 +08:00
TorrentSecret :: query () -> insert ( $insert );
return $insert [ 'secret' ];
}
throw new NexusException ( 'No valid report secret, please re-download this torrent.' );
}
/**
* reset user tracker report authkey secret
*
* @ param $uid
* @ param int $torrentId
* @ return string
* @ todo wrap with transaction
*
* @ date 2021 / 6 / 3
* @ time 20 : 15
*/
2021-06-21 02:01:26 +08:00
public function resetTrackerReportAuthKeySecret ( $uid , $torrentId = 0 ) : string
2021-06-03 21:13:59 +08:00
{
$insert = [
'uid' => $uid ,
'secret' => Str :: random (),
'torrent_id' => $torrentId ,
];
if ( $torrentId > 0 ) {
return TorrentSecret :: query () -> insert ( $insert );
}
TorrentSecret :: query () -> where ( 'uid' , $uid ) -> delete ();
TorrentSecret :: query () -> insert ( $insert );
return $insert [ 'secret' ];
2021-06-03 03:04:24 +08:00
}
2022-06-15 15:43:33 +08:00
public function buildApprovalModal ( $user , $torrentId )
{
$user = $this -> getUser ( $user );
2022-08-20 21:07:29 +08:00
user_can ( 'torrent-approval' , true );
2022-06-15 15:43:33 +08:00
$torrent = Torrent :: query () -> findOrFail ( $torrentId , [ 'id' , 'approval_status' , 'banned' ]);
$radios = [];
foreach ( Torrent :: $approvalStatus as $key => $value ) {
if ( $torrent -> approval_status == $key ) {
$checked = " checked " ;
} else {
$checked = " " ;
}
$radios [] = sprintf (
'<label><input type="radio" name="params[approval_status]" value="%s"%s>%s</label>' ,
$key , $checked , nexus_trans ( " torrent.approval.status_text. $key " )
);
}
$id = " torrent-approval " ;
$rows = [];
$rowStyle = " display: flex; padding: 10px; align-items: center " ;
$labelStyle = " width: 80px " ;
$formId = " $id -form " ;
$rows [] = sprintf (
'<div class="%s-row" style="%s"><div style="%s">%s: </div><div>%s</div></div>' ,
2022-07-19 14:15:35 +08:00
$id , $rowStyle , $labelStyle , nexus_trans ( 'torrent.approval.status_label' ), implode ( '' , $radios )
2022-06-15 15:43:33 +08:00
);
$rows [] = sprintf (
'<div class="%s-row" style="%s"><div style="%s">%s: </div><div><textarea name="params[comment]" rows="4" cols="40"></textarea></div></div>' ,
$id , $rowStyle , $labelStyle , nexus_trans ( 'torrent.approval.comment_label' )
);
$rows [] = sprintf ( '<input type="hidden" name="params[torrent_id]" value="%s" />' , $torrent -> id );
$html = sprintf ( '<div id="%s-box" style="padding: 15px 30px"><form id="%s">%s</form></div>' , $id , $formId , implode ( '' , $rows ));
return [
'id' => $id ,
'form_id' => $formId ,
'title' => nexus_trans ( 'torrent.approval.modal_title' ),
'content' => $html ,
];
}
public function approval ( $user , array $params ) : array
{
$user = $this -> getUser ( $user );
2022-08-20 21:07:29 +08:00
user_can ( 'torrent-approval' , true );
2022-06-15 15:43:33 +08:00
$torrent = Torrent :: query () -> findOrFail ( $params [ 'torrent_id' ], [ 'id' , 'banned' , 'approval_status' , 'visible' , 'owner' ]);
2022-06-27 13:22:16 +08:00
$lastLog = TorrentOperationLog :: query ()
-> where ( 'torrent_id' , $params [ 'torrent_id' ])
-> where ( 'uid' , $user -> id )
-> orderBy ( 'id' , 'desc' )
-> first ();
if ( $torrent -> approval_status == $params [ 'approval_status' ] && $lastLog && $lastLog -> comment == $params [ 'comment' ]) {
2022-06-15 15:43:33 +08:00
//No change
return $params ;
}
2022-06-16 02:04:32 +08:00
$torrentUpdate = $torrentOperationLog = [];
2022-06-15 15:43:33 +08:00
$torrentUpdate [ 'approval_status' ] = $params [ 'approval_status' ];
2022-06-18 23:17:34 +08:00
$notifyUser = false ;
2022-06-15 15:43:33 +08:00
if ( $params [ 'approval_status' ] == Torrent :: APPROVAL_STATUS_ALLOW ) {
$torrentUpdate [ 'banned' ] = 'no' ;
$torrentUpdate [ 'visible' ] = 'yes' ;
if ( $torrent -> approval_status != $params [ 'approval_status' ]) {
$torrentOperationLog [ 'action_type' ] = TorrentOperationLog :: ACTION_TYPE_APPROVAL_ALLOW ;
}
2022-06-18 23:17:34 +08:00
if ( $torrent -> approval_status == Torrent :: APPROVAL_STATUS_DENY ) {
$notifyUser = true ;
}
2022-06-15 15:43:33 +08:00
} elseif ( $params [ 'approval_status' ] == Torrent :: APPROVAL_STATUS_DENY ) {
$torrentUpdate [ 'banned' ] = 'yes' ;
$torrentUpdate [ 'visible' ] = 'no' ;
2022-06-27 13:22:16 +08:00
//Deny, record and notify all the time
$torrentOperationLog [ 'action_type' ] = TorrentOperationLog :: ACTION_TYPE_APPROVAL_DENY ;
$notifyUser = true ;
2022-06-15 15:43:33 +08:00
} elseif ( $params [ 'approval_status' ] == Torrent :: APPROVAL_STATUS_NONE ) {
2022-06-16 01:40:06 +08:00
$torrentUpdate [ 'banned' ] = 'no' ;
$torrentUpdate [ 'visible' ] = 'yes' ;
2022-06-15 15:43:33 +08:00
if ( $torrent -> approval_status != $params [ 'approval_status' ]) {
$torrentOperationLog [ 'action_type' ] = TorrentOperationLog :: ACTION_TYPE_APPROVAL_NONE ;
}
2022-06-18 23:17:34 +08:00
if ( $torrent -> approval_status == Torrent :: APPROVAL_STATUS_DENY ) {
$notifyUser = true ;
}
2022-06-15 15:43:33 +08:00
} else {
throw new \InvalidArgumentException ( " Invalid approval_status: " . $params [ 'approval_status' ]);
}
if ( isset ( $torrentOperationLog [ 'action_type' ])) {
$torrentOperationLog [ 'uid' ] = $user -> id ;
$torrentOperationLog [ 'torrent_id' ] = $torrent -> id ;
$torrentOperationLog [ 'comment' ] = $params [ 'comment' ] ? ? '' ;
}
2022-06-18 23:17:34 +08:00
NexusDB :: transaction ( function () use ( $torrent , $torrentOperationLog , $torrentUpdate , $notifyUser ) {
2022-06-16 02:04:32 +08:00
$log = " torrent: " . $torrent -> id ;
2022-06-15 15:43:33 +08:00
if ( ! empty ( $torrentUpdate )) {
2022-07-03 14:00:07 +08:00
$log .= " , [UPDATE_TORRENT]: " . nexus_json_encode ( $torrentUpdate );
2022-06-15 15:43:33 +08:00
$torrent -> update ( $torrentUpdate );
}
if ( ! empty ( $torrentOperationLog )) {
2022-07-03 14:00:07 +08:00
$log .= " , [ADD_TORRENT_OPERATION_LOG]: " . nexus_json_encode ( $torrentOperationLog );
2022-06-18 23:17:34 +08:00
TorrentOperationLog :: add ( $torrentOperationLog , $notifyUser );
2022-06-15 15:43:33 +08:00
}
do_log ( $log );
});
return $params ;
}
2022-06-24 14:55:10 +08:00
public function renderApprovalStatus ( $approvalStatus , $show = null ) : string
{
if ( $show === null ) {
$show = $this -> shouldShowApprovalStatusIcon ( $approvalStatus );
}
if ( $show ) {
return sprintf (
'<span style="margin-left: 6px" title="%s">%s</span>' ,
nexus_trans ( " torrent.approval.status_text. $approvalStatus " ),
\App\Models\Torrent :: $approvalStatus [ $approvalStatus ][ 'icon' ]
);
}
return '' ;
}
public function shouldShowApprovalStatusIcon ( $approvalStatus ) : bool
{
if ( get_setting ( 'torrent.approval_status_icon_enabled' ) == 'yes' ) {
//启用审核状态图标,肯定显示
return true ;
}
if (
$approvalStatus != \App\Models\Torrent :: APPROVAL_STATUS_ALLOW
&& get_setting ( 'torrent.approval_status_none_visible' ) == 'no'
) {
//不启用审核状态图标,尽量不显示。在种子不是审核通过状态,而审核不通过又不能被用户看到时,显示
return true ;
}
return false ;
}
2022-09-12 22:02:57 +08:00
public function syncTags ( $id , array $tagIdArr = [], $remove = true )
2022-07-19 14:15:35 +08:00
{
2022-08-20 21:07:29 +08:00
user_can ( 'torrentmanage' , true );
2022-07-19 14:15:35 +08:00
$idArr = Arr :: wrap ( $id );
2022-09-12 22:02:57 +08:00
return NexusDB :: transaction ( function () use ( $idArr , $tagIdArr , $remove ) {
$sql = " insert into torrent_tags (torrent_id, tag_id, created_at, updated_at) values " ;
2022-07-19 14:15:35 +08:00
$time = now () -> toDateTimeString ();
2022-09-12 22:02:57 +08:00
$values = [];
2022-07-19 14:15:35 +08:00
foreach ( $idArr as $torrentId ) {
foreach ( $tagIdArr as $tagId ) {
2022-09-12 22:02:57 +08:00
$values [] = sprintf ( " (%s, %s, '%s', '%s') " , $torrentId , $tagId , $time , $time );
2022-07-19 14:15:35 +08:00
}
}
2022-09-12 22:02:57 +08:00
$sql .= implode ( ', ' , $values ) . " on duplicate key update updated_at = values(updated_at) " ;
if ( $remove ) {
TorrentTag :: query () -> whereIn ( 'torrent_id' , $idArr ) -> delete ();
2022-07-19 14:15:35 +08:00
}
2022-09-12 22:02:57 +08:00
if ( ! empty ( $values )) {
DB :: insert ( $sql );
}
return count ( $values );
2022-07-19 14:15:35 +08:00
});
}
2022-09-18 03:33:13 +08:00
public function setPosState ( $id , $posState , $posStateUntil = null ) : int
2022-07-19 14:15:35 +08:00
{
2022-08-20 21:07:29 +08:00
user_can ( 'torrentsticky' , true );
2022-09-18 03:33:13 +08:00
if ( $posState == Torrent :: POS_STATE_STICKY_NONE ) {
$posStateUntil = null ;
}
if ( $posStateUntil && Carbon :: parse ( $posStateUntil ) -> lte ( now ())) {
$posState = Torrent :: POS_STATE_STICKY_NONE ;
$posStateUntil = null ;
}
$update = [
'pos_state' => $posState ,
'pos_state_until' => $posStateUntil ,
];
2022-07-19 14:15:35 +08:00
$idArr = Arr :: wrap ( $id );
2022-09-18 03:33:13 +08:00
return Torrent :: query () -> whereIn ( 'id' , $idArr ) -> update ( $update );
2022-07-19 14:15:35 +08:00
}
2022-10-02 21:14:11 +08:00
public function setPickType ( $id , $pickType ) : int
{
user_can ( 'torrentmanage' , true );
if ( ! isset ( Torrent :: $pickTypes [ $pickType ])) {
throw new \InvalidArgumentException ( " Invalid pickType: $pickType " );
}
$update = [
'picktype' => $pickType ,
'picktime' => now (),
];
$idArr = Arr :: wrap ( $id );
return Torrent :: query () -> whereIn ( 'id' , $idArr ) -> update ( $update );
}
public function setHr ( $id , $hrStatus ) : int
{
user_can ( 'torrentmanage' , true );
if ( ! isset ( Torrent :: $hrStatus [ $hrStatus ])) {
throw new \InvalidArgumentException ( " Invalid hrStatus: $hrStatus " );
}
$update = [
'hr' => $hrStatus ,
];
$idArr = Arr :: wrap ( $id );
return Torrent :: query () -> whereIn ( 'id' , $idArr ) -> update ( $update );
}
public function setSpState ( $id , $spState , $promotionTimeType , $promotionUntil = null ) : int
{
user_can ( 'torrentonpromotion' , true );
if ( ! isset ( Torrent :: $promotionTypes [ $spState ])) {
throw new \InvalidArgumentException ( " Invalid spState: $spState " );
}
if ( ! isset ( Torrent :: $promotionTimeTypes [ $promotionTimeType ])) {
throw new \InvalidArgumentException ( " Invalid promotionTimeType: $promotionTimeType " );
}
if ( in_array ( $promotionTimeType , [ Torrent :: PROMOTION_TIME_TYPE_GLOBAL , Torrent :: PROMOTION_TIME_TYPE_PERMANENT ])) {
$promotionUntil = null ;
} elseif ( ! $promotionUntil || Carbon :: parse ( $promotionUntil ) -> lte ( now ())) {
throw new \InvalidArgumentException ( " Invalid promotionUntil: $promotionUntil " );
}
$update = [
'sp_state' => $spState ,
'promotion_time_type' => $promotionTimeType ,
'promotion_until' => $promotionUntil ,
];
$idArr = Arr :: wrap ( $id );
return Torrent :: query () -> whereIn ( 'id' , $idArr ) -> update ( $update );
}
2022-09-05 01:46:38 +08:00
public function buildUploadFieldInput ( $name , $value , $noteText , $btnText ) : string
{
$btn = $note = '' ;
if ( $btnText ) {
$btn = '<div><input type="button" class="nexus-action-btn" value="' . $btnText . '"></div>' ;
}
if ( $noteText ) {
$note = '<span class="medium">' . $noteText . '</span>' ;
}
$input = <<< HTML
< div class = " nexus-input-box " style = " display: flex " >
< div style = " display: flex;flex-direction: column;flex-grow: 1 " >
2022-09-06 21:37:47 +08:00
< input type = " text " id = " $name " name = " $name " value = " { $value } " >
2022-09-05 01:46:38 +08:00
$note
</ div >
$btn
</ div >
HTML ;
return $input ;
}
2023-02-01 10:58:01 +08:00
public function removeDuplicateSnatch ()
{
$size = 2000 ;
$stickyPromotionExists = NexusDB :: hasTable ( '' );
while ( true ) {
$snatchRes = NexusDB :: select ( " select userid, torrentid, group_concat(id) as ids from snatched group by userid, torrentid having(count(*)) > 1 limit $size " );
if ( empty ( $snatchRes )) {
break ;
}
do_log ( " [DELETE_DUPLICATED_SNATCH], count: " . count ( $snatchRes ));
foreach ( $snatchRes as $snatchRow ) {
$torrentId = $snatchRow [ 'torrentid' ];
$userId = $snatchRow [ 'userid' ];
$idArr = explode ( ',' , $snatchRow [ 'ids' ]);
sort ( $idArr , SORT_NUMERIC );
$remainId = array_pop ( $idArr );
$delIdStr = implode ( ',' , $idArr );
do_log ( " [DELETE_DUPLICATED_SNATCH], torrent: $torrentId , user: $userId , snatchIdStr: $delIdStr " );
NexusDB :: statement ( " delete from snatched where id in ( $delIdStr ) " );
NexusDB :: statement ( " update claims set snatched_id = $remainId where torrent_id = $torrentId and uid = $userId " );
}
}
}
2021-05-15 19:29:44 +08:00
}