[H&R] basically

This commit is contained in:
xiaomlove
2021-06-21 02:01:26 +08:00
parent 45aba84111
commit d2a8f1a1a6
39 changed files with 966 additions and 74 deletions

View File

@@ -1,24 +1,32 @@
<template> <template>
<el-form :model="formData" :rules="rules" ref="formRef" label-width="250px" class="formData" size="mini"> <el-form :model="formData" :rules="rules" ref="formRef" label-width="250px" class="formData" size="mini">
<el-form-item label="Enabled" prop="hr.enabled"> <el-form-item label="Mode" prop="hr.mode">
<el-radio v-model="formData.hr.enabled" label="yes">Yes</el-radio> <el-radio v-model="formData.hr.mode" label="disabled">Disabled</el-radio>
<el-radio v-model="formData.hr.enabled" label="no">No</el-radio> <el-radio v-model="formData.hr.mode" label="manual">Manual</el-radio>
<el-radio v-model="formData.hr.mode" label="global">Global</el-radio>
<div class="nexus-help-text"> <div class="nexus-help-text">
Enable H&R or not. Set H&R mode.
</div>
</el-form-item>
<el-form-item label="Inspect time" prop="hr.inspect_time">
<el-input v-model="formData.hr.inspect_time" type="number"></el-input>
<div class="nexus-help-text">
Inspect time duration after download complete(Unit: Hour).
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="Seed time minimum" prop="hr.seed_time_minimum"> <el-form-item label="Seed time minimum" prop="hr.seed_time_minimum">
<el-input v-model="formData.hr.seed_time_minimum" type="number"></el-input> <el-input v-model="formData.hr.seed_time_minimum" type="number"></el-input>
<div class="nexus-help-text"> <div class="nexus-help-text">
Seed time minimum (Unit: Hour). Seed time minimum (Unit: Hour, must be less than Inspect time).
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="Ignore" prop="hr.ignore_when_ratio_reach"> <el-form-item label="Ignore" prop="hr.ignore_when_ratio_reach">
<el-input v-model="formData.hr.ignore_when_ratio_reach" type="number"></el-input> <el-input v-model="formData.hr.ignore_when_ratio_reach" type="number"></el-input>
<div class="nexus-help-text"> <div class="nexus-help-text">
When uploaded / torrent_size reach this value, this H&R will be ignored. When ratio reach this value, this H&R will be ignored.
</div> </div>
</el-form-item> </el-form-item>
@@ -56,7 +64,8 @@ export default {
allClasses: [], allClasses: [],
formData: { formData: {
hr: { hr: {
enabled: '', mode: '',
inspect_time: '',
seed_time_minimum: '', seed_time_minimum: '',
ignore_when_ratio_reach: '', ignore_when_ratio_reach: '',
ban_user_when_counts_reach: '', ban_user_when_counts_reach: '',

View File

@@ -0,0 +1,53 @@
<?php
namespace App\Console\Commands;
use App\Repositories\HitAndRunRepository;
use Illuminate\Console\Command;
class HitAndRunUpdateStatus extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'hr:update_status {--uid=} {--torrent_id=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Update H&R status, options: --uid, --torrent_id';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$uid = $this->option('uid');
$torrentId = $this->option('torrent_id');
$rep = new HitAndRunRepository();
$result = $rep->cronjobUpdateStatus($uid, $torrentId);
$log = sprintf(
'[%s], %s, uid: %s, torrentId: %s, result: %s',
REQUEST_ID, __METHOD__, $uid, $torrentId, var_export($result, true)
);
$this->info($log);
do_log($log);
return 0;
}
}

View File

@@ -6,7 +6,9 @@ use App\Models\Attendance;
use App\Models\Exam; use App\Models\Exam;
use App\Models\ExamProgress; use App\Models\ExamProgress;
use App\Models\ExamUser; use App\Models\ExamUser;
use App\Models\HitAndRun;
use App\Models\SearchBox; use App\Models\SearchBox;
use App\Models\Snatch;
use App\Models\User; use App\Models\User;
use App\Repositories\ExamRepository; use App\Repositories\ExamRepository;
use App\Repositories\SearchBoxRepository; use App\Repositories\SearchBoxRepository;
@@ -53,10 +55,11 @@ class Test extends Command
*/ */
public function handle() public function handle()
{ {
$time = '2021-06-16T04:03:35Z'; $user = User::query()->first();
$date = Carbon::parse($time); $user->update([
$date->tz = 'Asia/Shanghai'; 'page' => DB::raw('dddd')
dd($date->toDateTimeString()); ]);
dd(last_query());
} }
} }

27
app/Models/BonusLogs.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
namespace App\Models;
class BonusLogs extends NexusModel
{
protected $table = 'bonus_logs';
protected $fillable = ['uid', 'business_type', 'old_total_value', 'value', 'new_total_value', 'comment'];
const DEFAULT_BONUS_CANCEL_ONE_HIT_AND_RUN = 10000;
const BUSINESS_TYPE_CANCEL_HIT_AND_RUN = 1;
public static $businessTypes = [
self::BUSINESS_TYPE_CANCEL_HIT_AND_RUN => ['text' => 'Cancel H&R'],
];
public static function getBonusForCancelHitAndRun()
{
$result = Setting::get('bonus.cancel_hr');
return $result ?? self::DEFAULT_BONUS_CANCEL_ONE_HIT_AND_RUN;
}
}

View File

@@ -6,25 +6,73 @@ class HitAndRun extends NexusModel
{ {
protected $table = 'hit_and_runs'; protected $table = 'hit_and_runs';
protected $fillable = ['uid', 'peer_id', 'torrent_id', 'status', 'comment']; protected $fillable = ['uid', 'snatch_id', 'torrent_id', 'status', 'comment'];
public $timestamps = true; public $timestamps = true;
const STATUS_INSPECTING = 1; const STATUS_INSPECTING = 1;
const STATUS_PASSED = 2; const STATUS_REACHED = 2;
const STATUS_NOT_PASSED = 3; const STATUS_UNREACHED = 3;
const STATUS_CANCELED = 4; const STATUS_PARDONED = 4;
public static $status = [ public static $status = [
self::STATUS_INSPECTING => ['text' => '考察中'], self::STATUS_INSPECTING => ['text' => 'Inspecting'],
self::STATUS_PASSED => ['text' => '已通过'], self::STATUS_REACHED => ['text' => 'Reached'],
self::STATUS_NOT_PASSED => ['text' => '未通过'], self::STATUS_UNREACHED => ['text' => 'Unreached'],
self::STATUS_CANCELED => ['text' => '已取消'], self::STATUS_PARDONED => ['text' => 'Pardoned'],
];
const MODE_DISABLED = 'disabled';
const MODE_MANUAL = 'manual';
const MODE_GLOBAL = 'global';
public static $modes = [
self::MODE_DISABLED => ['text' => 'Disabled'],
self::MODE_MANUAL => ['text' => 'Manual'],
self::MODE_GLOBAL => ['text' => 'Global'],
]; ];
public function getStatusTextAttribute() public function getStatusTextAttribute()
{ {
return self::$status[$this->status] ?? ''; return nexus_trans('hr.status_' . $this->status);
}
public static function listStatus(): array
{
$result = self::$status;
foreach ($result as $key => &$value) {
$value['text'] = nexus_trans('hr.status_' . $key);
}
return $result;
}
public static function listModes(): array
{
$result = self::$modes;
foreach ($result as $key => &$value) {
$value['text'] = nexus_trans('hr.mode_' . $key);
}
return $result;
}
public static function getIsEnabled(): bool
{
return Setting::get('hr.mode') != self::MODE_DISABLED;
}
public function torrent(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Torrent::class, 'torrent_id');
}
public function snatch(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Snatch::class, 'snatched_id');
}
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(User::class, 'uid');
} }

View File

@@ -41,6 +41,31 @@ class Torrent extends NexusModel
self::POS_STATE_STICKY_FIRST => ['text' => 'Sticky first', 'icon_counts' => 2], self::POS_STATE_STICKY_FIRST => ['text' => 'Sticky first', 'icon_counts' => 2],
]; ];
const HR_YES = 1;
const HR_NO = 0;
public static $hrStatus = [
self::HR_NO => ['text' => 'NO'],
self::HR_YES => ['text' => 'YES'],
];
public function getHrAttribute(): string
{
$hrMode = Setting::get('hr.mode');
if ($hrMode == HitAndRun::MODE_GLOBAL) {
return self::HR_YES;
}
if ($hrMode == HitAndRun::MODE_DISABLED) {
return self::HR_NO;
}
return $this->getRawOriginal('hr');
}
public function getHrTextAttribute()
{
return self::$hrStatus[$this->hr] ?? '';
}
public static function getBasicInfo(): array public static function getBasicInfo(): array
{ {
$result = []; $result = [];

View File

@@ -108,7 +108,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' 'leechwarn', 'leechwarnuntil', 'page'
]; ];
/** /**
@@ -238,6 +238,11 @@ class User extends Authenticatable
'torrentid'); 'torrentid');
} }
public function hitAndRuns(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(HitAndRun::class, 'uid');
}
public function getAvatarAttribute($value) public function getAvatarAttribute($value)
{ {
if ($value) { if ($value) {
@@ -260,6 +265,7 @@ class User extends Authenticatable
//@todo how to do prepare bindings here ? //@todo how to do prepare bindings here ?
$modComment = addslashes($modComment); $modComment = addslashes($modComment);
$update['modcomment'] = DB::raw("concat_ws('\n', '$modComment', modcomment)"); $update['modcomment'] = DB::raw("concat_ws('\n', '$modComment', modcomment)");
do_log("update: " . json_encode($update) . ", modcomment: $modComment", 'notice');
return $this->update($update); return $this->update($update);
} }

View File

@@ -0,0 +1,68 @@
<?php
namespace App\Repositories;
use App\Models\BonusLogs;
use App\Models\HitAndRun;
use App\Models\Setting;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Query\Expression;
use Nexus\Database\NexusDB;
class BonusRepository extends BaseRepository
{
public function consumeToCancelHitAndRun($uid, $hitAndRunId)
{
$hitAndRunMode = Setting::get('hr.mode');
if ($hitAndRunMode == HitAndRun::MODE_DISABLED) {
throw new \LogicException("H&R not enabled.");
}
$user = User::query()->findOrFail($uid);
$hitAndRun = HitAndRun::query()->findOrFail($hitAndRunId);
if ($hitAndRun->uid != $uid) {
throw new \LogicException("H&R: $hitAndRunId not belongs to user: $uid.");
}
$requireBonus = BonusLogs::getBonusForCancelHitAndRun();
if ($user->seedbonus < $requireBonus) {
do_log("user: $uid, bonus: {$user->seedbonus} < requireBonus: $requireBonus", 'error');
throw new \LogicException("User bonus point not enough.");
}
$result = NexusDB::transaction(function () use ($user, $hitAndRun, $requireBonus) {
$oldUserBonus = $user->seedbonus;
$newUserBonus = bcsub($oldUserBonus, $requireBonus);
$log = "user: {$user->id}, hitAndRun: {$hitAndRun->id}, requireBonus: $requireBonus, oldUserBonus: $oldUserBonus, newUserBonus: $newUserBonus";
do_log($log);
$affectedRows = NexusDB::table($user->getTable())
->where('id', $user->id)
->where('seedbonus', $oldUserBonus)
->update(['seedbonus' => $newUserBonus]);
if ($affectedRows != 1) {
do_log("update user seedbonus affected rows != 1, query: " . last_query(), 'error');
throw new \RuntimeException("Update user seedbonus fail.");
}
$comment = nexus_trans('hr.bonus_cancel_comment', [
'now' => Carbon::now()->toDateTimeString(),
'bonus' => $requireBonus,
], $user->locale);
do_log("comment: $comment");
$hitAndRun->update([
'status' => HitAndRun::STATUS_PARDONED,
'comment' => new Expression("concat(comment, '\n$comment')"),
]);
$bonusLog = [
'business_type' => BonusLogs::BUSINESS_TYPE_CANCEL_HIT_AND_RUN,
'uid' => $user->id,
'old_total_value' => $oldUserBonus,
'value' => $requireBonus,
'new_total_value' => $newUserBonus,
'comment' => "$comment(H&R ID: {$hitAndRun->id})",
];
BonusLogs::query()->insert($bonusLog);
do_log("bonusLog: " . json_encode($bonusLog));
return true;
});
return $result;
}
}

View File

@@ -0,0 +1,239 @@
<?php
namespace App\Repositories;
use App\Models\HitAndRun;
use App\Models\Message;
use App\Models\Setting;
use App\Models\User;
use App\Models\UserBanLog;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class HitAndRunRepository extends BaseRepository
{
public function cronjobUpdateStatus($uid = null, $torrentId = null)
{
$size = 1000;
$page = 1;
$setting = Setting::get('hr');
if (empty($setting['mode'])) {
do_log("H&R not set.");
return false;
}
if ($setting['mode'] == HitAndRun::MODE_DISABLED) {
do_log("H&R mode is disabled.");
return false;
}
$query = HitAndRun::query()
->where('status', HitAndRun::STATUS_INSPECTING)
->where('created_at', '<', Carbon::now()->subHours($setting['inspect_time']))
->with([
'torrent' => function ($query) {$query->select(['id', 'size', 'name']);},
'snatch',
'user' => function ($query) {$query->select(['id', 'username', 'lang']);},
'user.language',
]);
if (!is_null($uid)) {
$query->where('uid', $uid);
}
if (!is_null($torrentId)) {
$query->where('torrent_id', $torrentId);
}
$successCounts = 0;
while (true) {
$logPrefix = "page: $page, size: $size";
$rows = $query->forPage($page, $size)->get();
do_log("$logPrefix, counts: " . $rows->count());
if ($rows->isEmpty()) {
do_log("$logPrefix, no more data..." . last_query());
break;
}
foreach ($rows as $row) {
$logPrefix = "[HANDLING] " . $row->toJson();
do_log($logPrefix);
if (!$row->user) {
do_log("$logPrefix, user not exists, skip!", 'error');
continue;
}
if (!$row->snatch) {
do_log("$logPrefix, snatch not exists, skip!", 'error');
continue;
}
if (!$row->torrent) {
do_log("$logPrefix, torrent not exists, skip!", 'error');
continue;
}
//check seed time
$targetSeedTime = $row->snatch->seedtime;
$requireSeedTime = bcmul($setting['seed_time_minimum'], 3600);
$locale = $row->user->locale;
do_log("targetSeedTime: $targetSeedTime, requireSeedTime: $requireSeedTime");
if ($targetSeedTime >= $requireSeedTime) {
$result = $this->reachedBySeedTime($row);
if ($result) {
$successCounts++;
}
continue;
}
//check share ratio
$targetShareRatio = bcdiv($row->snatch->uploaded, $row->torrent->size, 4);
$requireShareRatio = $setting['ignore_when_ratio_reach'];
do_log("targetShareRatio: $targetShareRatio, requireShareRatio: $requireShareRatio");
if ($targetShareRatio >= $requireShareRatio) {
$result = $this->reachedByShareRatio($row);
if ($result) {
$successCounts++;
}
continue;
}
//unreached
$result = $this->unreached($row);
if ($result) {
$successCounts++;
}
}
$page++;
}
do_log("[CRONJOB_UPDATE_HR_DONE]");
return $successCounts;
}
private function geReachedMessage(HitAndRun $hitAndRun): array
{
return [
'receiver' => $hitAndRun->uid,
'added' => Carbon::now()->toDateTimeString(),
'subject' => nexus_trans('hr.reached_message_subject', ['hit_and_run_id' => $hitAndRun->id], $hitAndRun->user->locale),
'msg' => nexus_trans('hr.reached_message_content', [
'completed_at' => $hitAndRun->snatch->completedat->toDateTimeString(),
'torrent_id' => $hitAndRun->torrent_id,
'torrent_name' => $hitAndRun->torrent->name,
], $hitAndRun->user->locale),
];
}
private function reachedByShareRatio(HitAndRun $hitAndRun): bool
{
do_log(__METHOD__);
$comment = nexus_trans('hr.reached_by_share_ratio_comment', [
'now' => Carbon::now()->toDateTimeString(),
'seed_time_minimum' => Setting::get('hr.seed_time_minimum'),
'seed_time' => bcdiv($hitAndRun->snatch->seedtime, 3600, 1),
'share_ratio' => get_hr_ratio($hitAndRun->snatch->uploaded, $hitAndRun->snatch->downloaded),
'ignore_when_ratio_reach' => Setting::get('hr.ignore_when_ratio_reach'),
], $hitAndRun->user->locale);
$update = [
'status' => HitAndRun::STATUS_REACHED,
'comment' => $comment
];
$affectedRows = DB::table($hitAndRun->getTable())
->where('id', $hitAndRun->id)
->where('status', HitAndRun::STATUS_INSPECTING)
->update($update);
do_log("[H&R_REACHED_BY_SHARE_RATIO], " . last_query() . ", affectedRows: $affectedRows");
if ($affectedRows != 1) {
do_log($hitAndRun->toJson() . ", [H&R_REACHED_BY_SHARE_RATIO], affectedRows != 1, skip!", 'notice');
return false;
}
$message = $this->geReachedMessage($hitAndRun);
Message::query()->insert($message);
return true;
}
private function reachedBySeedTime(HitAndRun $hitAndRun): bool
{
do_log(__METHOD__);
$comment = nexus_trans('hr.reached_by_seed_time_comment', [
'now' => Carbon::now()->toDateTimeString(),
'seed_time' => bcdiv($hitAndRun->snatch->seedtime, 3600, 1),
'seed_time_minimum' => Setting::get('hr.seed_time_minimum')
], $hitAndRun->user->locale);
$update = [
'status' => HitAndRun::STATUS_REACHED,
'comment' => $comment
];
$affectedRows = DB::table($hitAndRun->getTable())
->where('id', $hitAndRun->id)
->where('status', HitAndRun::STATUS_INSPECTING)
->update($update);
do_log("[H&R_REACHED_BY_SEED_TIME], " . last_query() . ", affectedRows: $affectedRows");
if ($affectedRows != 1) {
do_log($hitAndRun->toJson() . ", [H&R_REACHED_BY_SEED_TIME], affectedRows != 1, skip!", 'notice');
return false;
}
$message = $this->geReachedMessage($hitAndRun);
Message::query()->insert($message);
return true;
}
private function unreached(HitAndRun $hitAndRun): bool
{
do_log(__METHOD__);
$comment = nexus_trans('hr.unreached_comment', [
'now' => Carbon::now()->toDateTimeString(),
'seed_time' => bcdiv($hitAndRun->snatch->seedtime, 3600, 1),
'seed_time_minimum' => Setting::get('hr.seed_time_minimum'),
'share_ratio' => get_hr_ratio($hitAndRun->snatch->uploaded, $hitAndRun->snatch->downloaded),
'torrent_size' => mksize($hitAndRun->torrent->size),
'ignore_when_ratio_reach' => Setting::get('hr.ignore_when_ratio_reach')
], $hitAndRun->user->locale);
$update = [
'status' => HitAndRun::STATUS_UNREACHED,
'comment' => $comment
];
$affectedRows = DB::table($hitAndRun->getTable())
->where('id', $hitAndRun->id)
->where('status', HitAndRun::STATUS_INSPECTING)
->update($update);
do_log("[H&R_UNREACHED], " . last_query() . ", affectedRows: $affectedRows");
if ($affectedRows != 1) {
do_log($hitAndRun->toJson() . ", [H&R_UNREACHED], affectedRows != 1, skip!", 'notice');
return false;
}
$message = [
'receiver' => $hitAndRun->uid,
'added' => Carbon::now()->toDateTimeString(),
'subject' => nexus_trans('hr.unreached_message_subject', ['hit_and_run_id' => $hitAndRun->id], $hitAndRun->user->locale),
'msg' => nexus_trans('hr.unreached_message_content', [
'completed_at' => $hitAndRun->snatch->completedat->toDateTimeString(),
'torrent_id' => $hitAndRun->torrent_id,
'torrent_name' => $hitAndRun->torrent->name,
], $hitAndRun->user->locale),
];
Message::query()->insert($message);
//disable user
/** @var User $user */
$user = $hitAndRun->user;
$counts = $user->hitAndRuns()->where('status', HitAndRun::STATUS_UNREACHED)->count();
$disableCounts = Setting::get('hr.ban_user_when_counts_reach');
do_log("user: {$user->id}, H&R counts: $counts, disableCounts: $disableCounts", 'notice');
if ($counts >= $disableCounts) {
do_log("[DISABLE_USER_DUE_TO_H&R_UNREACHED]", 'notice');
$comment = nexus_trans('hr.unreached_disable_comment', [], $user->locale);
$user->updateWithModComment(['enabled' => User::ENABLED_NO], $comment);
$message = [
'receiver' => $hitAndRun->uid,
'added' => Carbon::now()->toDateTimeString(),
'subject' => $comment,
'msg' => nexus_trans('hr.unreached_disable_message_content', [
'ban_user_when_counts_reach' => Setting::get('hr.ban_user_when_counts_reach'),
], $hitAndRun->user->locale),
];
Message::query()->insert($message);
$userBanLog = [
'uid' => $user->id,
'username' => $user->username,
'reason' => $comment
];
UserBanLog::query()->insert($userBanLog);
}
return true;
}
}

View File

@@ -6,7 +6,9 @@ use App\Exceptions\NexusException;
use App\Models\AudioCodec; use App\Models\AudioCodec;
use App\Models\Category; use App\Models\Category;
use App\Models\Codec; use App\Models\Codec;
use App\Models\HitAndRun;
use App\Models\Media; use App\Models\Media;
use App\Models\Message;
use App\Models\Peer; use App\Models\Peer;
use App\Models\Processing; use App\Models\Processing;
use App\Models\Snatch; use App\Models\Snatch;
@@ -16,10 +18,9 @@ use App\Models\Team;
use App\Models\Torrent; use App\Models\Torrent;
use App\Models\TorrentSecret; use App\Models\TorrentSecret;
use App\Models\User; use App\Models\User;
use Carbon\Carbon;
use Hashids\Hashids; use Hashids\Hashids;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Seeder;
use Illuminate\Http\Request;
use Illuminate\Support\Str; use Illuminate\Support\Str;
class TorrentRepository extends BaseRepository class TorrentRepository extends BaseRepository
@@ -343,7 +344,7 @@ class TorrentRepository extends BaseRepository
* @date 2021/6/3 * @date 2021/6/3
* @time 20:15 * @time 20:15
*/ */
public function resetTrackerReportAuthKeySecret($uid, $torrentId = 0) public function resetTrackerReportAuthKeySecret($uid, $torrentId = 0): string
{ {
$insert = [ $insert = [
'uid' => $uid, 'uid' => $uid,
@@ -361,5 +362,4 @@ class TorrentRepository extends BaseRepository
} }
} }

View File

@@ -15,13 +15,14 @@ class CreateHitAndRunsTable extends Migration
{ {
Schema::create('hit_and_runs', function (Blueprint $table) { Schema::create('hit_and_runs', function (Blueprint $table) {
$table->id(); $table->id();
$table->integer('uid')->index(); $table->integer('uid');
$table->integer('peer_id')->unique(); $table->integer('torrent_id');
$table->integer('torrent_id')->index(); $table->integer('snatched_id')->unique();
$table->integer('status')->default(1); $table->integer('status')->default(1);
$table->string('comment')->default(''); $table->string('comment')->default('');
$table->timestamp('created_at')->useCurrent(); $table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate(); $table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
$table->unique(['uid', 'torrent_id']);
}); });
} }

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddHrToTorrentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('torrents', function (Blueprint $table) {
$table->tinyInteger('hr')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('torrents', function (Blueprint $table) {
$table->dropColumn('hr');
});
}
}

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBonusLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('bonus_logs', function (Blueprint $table) {
$table->id();
$table->integer('business_type')->default(0);
$table->integer('uid')->index();
$table->integer('old_total_value');
$table->integer('value');
$table->integer('new_total_value');
$table->string('comment')->nullable();
$table->timestamp('created_at')->useCurrent();
$table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('bonus_logs');
}
}

View File

@@ -1,5 +1,5 @@
<?php <?php
defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.6.0-beta10'); defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.6.0-beta12');
defined('RELEASE_DATE') || define('RELEASE_DATE', '2020-06-15'); defined('RELEASE_DATE') || define('RELEASE_DATE', '2020-06-15');
defined('IN_TRACKER') || define('IN_TRACKER', true); defined('IN_TRACKER') || define('IN_TRACKER', true);
defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP"); defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP");

View File

@@ -2477,7 +2477,8 @@ else {
[<a href="torrents.php?inclbookmarked=1&amp;allsec=1&amp;incldead=0"><?php echo $lang_functions['text_bookmarks'] ?></a>] [<a href="torrents.php?inclbookmarked=1&amp;allsec=1&amp;incldead=0"><?php echo $lang_functions['text_bookmarks'] ?></a>]
<font class = 'color_bonus'><?php echo $lang_functions['text_bonus'] ?></font>[<a href="mybonus.php"><?php echo $lang_functions['text_use'] ?></a>]: <?php echo number_format($CURUSER['seedbonus'], 1)?> <font class = 'color_bonus'><?php echo $lang_functions['text_bonus'] ?></font>[<a href="mybonus.php"><?php echo $lang_functions['text_use'] ?></a>]: <?php echo number_format($CURUSER['seedbonus'], 1)?>
<?php if($attendance){ printf('&nbsp;'.$lang_functions['text_attended'], $attendance['points']); }else{ printf(' <a href="attendance.php" class="faqlink">%s</a>', $lang_functions['text_attendance']);}?> <?php if($attendance){ printf('&nbsp;'.$lang_functions['text_attended'], $attendance['points']); }else{ printf(' <a href="attendance.php" class="faqlink">%s</a>', $lang_functions['text_attendance']);}?>
<font class = 'color_invite'><?php echo $lang_functions['text_invite'] ?></font>[<a href="invite.php?id=<?php echo $CURUSER['id']?>"><?php echo $lang_functions['text_send'] ?></a>]: <?php echo $CURUSER['invites']?><br /> <font class = 'color_invite'><?php echo $lang_functions['text_invite'] ?></font>[<a href="invite.php?id=<?php echo $CURUSER['id']?>"><?php echo $lang_functions['text_send'] ?></a>]: <?php echo $CURUSER['invites']?>
<?php if(get_setting('hr.mode') != \App\Models\HitAndRun::MODE_DISABLED) { ?><font class='color_bonus'>H&R: </font> <?php echo sprintf('[<a href="myhr.php">%s/%s</a>]', get_row_count('hit_and_runs', "where uid = {$CURUSER['id']} and status = 3"), get_setting('hr.ban_user_when_counts_reach'))?><?php }?><br />
<font class="color_ratio"><?php echo $lang_functions['text_ratio'] ?></font> <?php echo $ratio?> <font class="color_ratio"><?php echo $lang_functions['text_ratio'] ?></font> <?php echo $ratio?>
<font class='color_uploaded'><?php echo $lang_functions['text_uploaded'] ?></font> <?php echo mksize($CURUSER['uploaded'])?> <font class='color_uploaded'><?php echo $lang_functions['text_uploaded'] ?></font> <?php echo mksize($CURUSER['uploaded'])?>
<font class='color_downloaded'> <?php echo $lang_functions['text_downloaded'] ?></font> <?php echo mksize($CURUSER['downloaded'])?> <font class='color_downloaded'> <?php echo $lang_functions['text_downloaded'] ?></font> <?php echo mksize($CURUSER['downloaded'])?>
@@ -2528,12 +2529,6 @@ else {
} }
if ($msgalert) if ($msgalert)
{ {
function msgalert($url, $text, $bgcolor = "red")
{
print("<p><table border=\"0\" cellspacing=\"0\" cellpadding=\"10\"><tr><td style='border: none; padding: 10px; background: ".$bgcolor."'>\n");
print("<b><a href=\"".$url."\"><font color=\"white\">".$text."</font></a></b>");
print("</td></tr></table></p><br />");
}
if($CURUSER['leechwarn'] == 'yes') if($CURUSER['leechwarn'] == 'yes')
{ {
$kicktimeout = gettime($CURUSER['leechwarnuntil'], false, false, true); $kicktimeout = gettime($CURUSER['leechwarnuntil'], false, false, true);
@@ -2909,7 +2904,7 @@ function pager($rpp, $count, $href, $opts = array(), $pagename = "page") {
$start = $page * $rpp; $start = $page * $rpp;
$add_key_shortcut = key_shortcut($page,$pages-1); $add_key_shortcut = key_shortcut($page,$pages-1);
return array($pagertop, $pagerbottom, "LIMIT $start,$rpp"); return array($pagertop, $pagerbottom, "LIMIT $start,$rpp", $start, $rpp);
} }
function commenttable($rows, $type, $parent_id, $review = false) function commenttable($rows, $type, $parent_id, $review = false)
@@ -3247,7 +3242,9 @@ foreach ($rows as $row)
$stickyicon = ""; $stickyicon = "";
} }
$sp_torrent = get_torrent_promotion_append($row['sp_state'],"",true,$row["added"], $row['promotion_time_type'], $row['promotion_until']); $sp_torrent = get_torrent_promotion_append($row['sp_state'],"",true,$row["added"], $row['promotion_time_type'], $row['promotion_until']);
print("<td class=\"rowfollow\" width=\"100%\" align=\"left\"><table class=\"torrentname\" width=\"100%\"><tr" . $sphighlight . "><td class=\"embedded\">".$stickyicon."<a $short_torrent_name_alt $mouseovertorrent href=\"details.php?id=".$id."&amp;hit=1\"><b>".htmlspecialchars($dispname)."</b></a>" . $sp_torrent); $hrImg = get_hr_img($row);
print("<td class=\"rowfollow\" width=\"100%\" align=\"left\"><table class=\"torrentname\" width=\"100%\"><tr" . $sphighlight . "><td class=\"embedded\">".$stickyicon."<a $short_torrent_name_alt $mouseovertorrent href=\"details.php?id=".$id."&amp;hit=1\"><b>".htmlspecialchars($dispname)."</b></a>" . $sp_torrent . $hrImg);
$picked_torrent = ""; $picked_torrent = "";
if ($CURUSER['appendpicked'] != 'no'){ if ($CURUSER['appendpicked'] != 'no'){
if($row['picktype']=="hot") if($row['picktype']=="hot")
@@ -4116,6 +4113,17 @@ function get_torrent_promotion_append($promotion = 1,$forcemode = "",$showtimele
return $sp_torrent; return $sp_torrent;
} }
function get_hr_img(array $torrent)
{
$mode = get_setting('hr.mode');
$result = '';
if ($mode == \App\Models\HitAndRun::MODE_GLOBAL || ($mode == \App\Models\HitAndRun::MODE_MANUAL && isset($torrent['hr']) && $torrent['hr'] == \App\Models\Torrent::HR_YES)) {
$result = '<img class="hitandrun" src="pic/trans.gif" alt="H&R" title="H&R" />';
}
do_log("mode: $mode, result: $result");
return $result;
}
function get_user_id_from_name($username){ function get_user_id_from_name($username){
global $lang_functions; global $lang_functions;
$res = sql_query("SELECT id FROM users WHERE LOWER(username)=LOWER(" . sqlesc($username).")"); $res = sql_query("SELECT id FROM users WHERE LOWER(username)=LOWER(" . sqlesc($username).")");
@@ -5075,4 +5083,11 @@ function get_ip_location_from_geoip($ip)
]; ];
} }
function msgalert($url, $text, $bgcolor = "red")
{
print("<p><table border=\"0\" cellspacing=\"0\" cellpadding=\"10\"><tr><td style='border: none; padding: 10px; background: ".$bgcolor."'>\n");
print("<b><a href=\"".$url."\"><font color=\"white\">".$text."</font></a></b>");
print("</td></tr></table></p><br />");
}
?> ?>

View File

@@ -656,3 +656,22 @@ function get_tracker_schema_and_host(): array
do_log($log); do_log($log);
return compact('ssl_torrent', 'base_announce_url'); return compact('ssl_torrent', 'base_announce_url');
} }
function get_hr_ratio($uped, $downed)
{
if ($downed > 0) {
$ratio = $uped / $downed;
$color = get_ratio_color($ratio);
if ($ratio > 10000) $ratio = 'Inf.';
else
$ratio = number_format($ratio, 3);
if ($color)
$ratio = "<font color=\"" . $color . "\">" . $ratio . "</font>";
} elseif ($uped > 0)
$ratio = 'Inf.';
else
$ratio = "---";
return $ratio;
}

View File

@@ -122,7 +122,10 @@ $lang_mybonus = array
'bonus_amount_not_allowed_two' => "魔力值数量不允许。你每次只能赠送1000.0至50000.0个魔力值。", 'bonus_amount_not_allowed_two' => "魔力值数量不允许。你每次只能赠送1000.0至50000.0个魔力值。",
'bonus_ratio_not_allowed' => "分享率不符合要求只有分享率低于0.8的用户需要慈善帮助。", 'bonus_ratio_not_allowed' => "分享率不符合要求只有分享率低于0.8的用户需要慈善帮助。",
'std_no_users_need_charity' => "暂时没有需要慈善帮助的用户。", 'std_no_users_need_charity' => "暂时没有需要慈善帮助的用户。",
'text_success_charity' => "谢谢!感谢你的慷慨捐赠。" 'text_success_charity' => "谢谢!感谢你的慷慨捐赠。",
'text_cancel_hr_title' => 'H&R 消除',
'text_cancel_hr_label' => '输入要消除的 H&R ID',
'text_success_cancel_hr' => "成功消除了一个 H&R。",
); );
?> ?>

14
lang/chs/lang_myhr.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
$lang_myhr = [
'th_hr_id' => 'H&R ID',
'th_torrent_name' => '种子名称',
'th_uploaded' => '上传量',
'th_downloaded' => '下载量',
'th_share_ratio' => '分享率',
'th_seed_time_required' => '还需做种时间',
'th_completed_at' => '下载完成时间',
'th_ttl' => '剩余达标时间',
'th_comment' => '备注',
];

View File

@@ -712,6 +712,10 @@ $lang_settings = array
'text_sticky_second_level_background_color_note' => '二级置顶背景颜色,不设置则无背景色。', 'text_sticky_second_level_background_color_note' => '二级置顶背景颜色,不设置则无背景色。',
'row_download_support_passkey' => '支持 passkey 下载种子', 'row_download_support_passkey' => '支持 passkey 下载种子',
'text_download_support_passkey_note' => '是否支持通过 passkey 下载种子(同时也需要种子 ID。', 'text_download_support_passkey_note' => '是否支持通过 passkey 下载种子(同时也需要种子 ID。',
'row_torrent_hr' => '设定种子 H&R',
'text_torrent_hr_note' => '。将种子设置为参与 H&R 考察',
'row_cancel_hr' => '消除 H&R',
'text_cancel_hr_note' => "个魔力值,如果他需要消除一个 H&R。默认'10000'。",
); );
?> ?>

View File

@@ -122,7 +122,10 @@ $lang_mybonus = array
'bonus_amount_not_allowed_two' => "魔力值數量不允許。你每次只能贈送1000.0至50000.0個魔力值。", 'bonus_amount_not_allowed_two' => "魔力值數量不允許。你每次只能贈送1000.0至50000.0個魔力值。",
'bonus_ratio_not_allowed' => "分享率不符合要求只有分享率低于0.8的用戶需要慈善輔助說明。", 'bonus_ratio_not_allowed' => "分享率不符合要求只有分享率低于0.8的用戶需要慈善輔助說明。",
'std_no_users_need_charity' => "暫時沒有需要慈善輔助說明的用戶。", 'std_no_users_need_charity' => "暫時沒有需要慈善輔助說明的用戶。",
'text_success_charity' => "謝謝!感謝你的慷慨捐贈。" 'text_success_charity' => "謝謝!感謝你的慷慨捐贈。",
'text_cancel_hr_title' => 'H&R 消除',
'text_cancel_hr_label' => '輸入要消除的 H&R ID',
'text_success_cancel_hr' => "成功消除了一個 H&R。",
); );
?> ?>

View File

@@ -712,6 +712,10 @@ $lang_settings = array
'text_sticky_second_level_background_color_note' => '二級置頂背景顏色,不設置則無背景色。', 'text_sticky_second_level_background_color_note' => '二級置頂背景顏色,不設置則無背景色。',
'row_download_support_passkey' => '支持 passkey 下載種子', 'row_download_support_passkey' => '支持 passkey 下載種子',
'text_download_support_passkey_note' => '是否支持通過 passkey 下載種子(同時也需要種子 ID。', 'text_download_support_passkey_note' => '是否支持通過 passkey 下載種子(同時也需要種子 ID。',
'row_torrent_hr' => '設定種子 H&R',
'text_torrent_hr_note' => '。將種子設置為參與 H&R 考察',
'row_cancel_hr' => '消除 H&R',
'text_cancel_hr_note' => "個魔力值,如果他需要消除一個 H&R。默認'10000'。",
); );
?> ?>

View File

@@ -122,7 +122,10 @@ where<ul><li><b>A</b> is an intermediate variable</li><li><b>Ti</b> is the <b>i<
'bonus_amount_not_allowed_two' => "Bonus amount not allowed! You can only give away from 1000.0 to 50000.0 points every time.", 'bonus_amount_not_allowed_two' => "Bonus amount not allowed! You can only give away from 1000.0 to 50000.0 points every time.",
'bonus_ratio_not_allowed' => "Bonus ratio not allowed! Only users whose ratio below 0.8 need charity.", 'bonus_ratio_not_allowed' => "Bonus ratio not allowed! Only users whose ratio below 0.8 need charity.",
'std_no_users_need_charity' => "No users need charity at the moment.", 'std_no_users_need_charity' => "No users need charity at the moment.",
'text_success_charity' => "Thank you! Your generosity is appreciated." 'text_success_charity' => "Thank you! Your generosity is appreciated.",
'text_cancel_hr_title' => 'H&R cancel',
'text_cancel_hr_label' => 'Type in H&R ID:',
'text_success_cancel_hr' => "Success cancel one H&R.",
); );
?> ?>

View File

@@ -712,6 +712,10 @@ $lang_settings = array
'text_sticky_second_level_background_color_note' => 'Sticky second level bg color, it will be none if not set.', 'text_sticky_second_level_background_color_note' => 'Sticky second level bg color, it will be none if not set.',
'row_download_support_passkey' => 'Support download by passkey', 'row_download_support_passkey' => 'Support download by passkey',
'text_download_support_passkey_note' => 'Support download torrent file by passkey or not(also require torrent id).', 'text_download_support_passkey_note' => 'Support download torrent file by passkey or not(also require torrent id).',
'row_torrent_hr' => 'H&R',
'text_torrent_hr_note' => '.Set torrent join the H&R inspect',
'row_cancel_hr' => 'Cancel H&R',
'text_cancel_hr_note' => "bonus points to cancel one H&R。Default '10000'。",
); );
?> ?>

View File

@@ -10,6 +10,11 @@ class NexusDB
private static $instance; private static $instance;
/**
* @var \Illuminate\Database\Connection
*/
private static $eloquentConnection;
private $isConnected = false; private $isConnected = false;
private function __construct() private function __construct()
@@ -215,7 +220,7 @@ class NexusDB
$capsule->addConnection($config, $connectionName); $capsule->addConnection($config, $connectionName);
$capsule->setAsGlobal(); $capsule->setAsGlobal();
$capsule->bootEloquent(); $capsule->bootEloquent();
$connection = $capsule->getConnection($connectionName); $connection = self::$eloquentConnection = $capsule->getConnection($connectionName);
$connection->enableQueryLog(); $connection->enableQueryLog();
$connection->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); $connection->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
} }

View File

@@ -3,12 +3,15 @@
namespace Nexus\Install; namespace Nexus\Install;
use App\Models\Attendance; use App\Models\Attendance;
use App\Models\BonusLogs;
use App\Models\Category; use App\Models\Category;
use App\Models\Exam; use App\Models\Exam;
use App\Models\ExamUser; use App\Models\ExamUser;
use App\Models\Icon; use App\Models\Icon;
use App\Models\Setting; use App\Models\Setting;
use App\Models\User;
use App\Repositories\ExamRepository; use App\Repositories\ExamRepository;
use Carbon\Carbon;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Nexus\Database\NexusDB; use Nexus\Database\NexusDB;
@@ -56,6 +59,20 @@ class Update extends Install
return $data; return $data;
} }
private function addSetting($name, $value)
{
$attributes = [
'name' => $name,
];
$now = Carbon::now()->toDateTimeString();
$values = [
'value' => $value,
'created_at' => $now,
'updated_at' => $now,
];
return Setting::query()->firstOrCreate($attributes, $values);
}
public function runExtraQueries() public function runExtraQueries()
{ {
//custom field menu //custom field menu
@@ -111,6 +128,11 @@ class Update extends Install
if (WITH_LARAVEL && VERSION_NUMBER == '1.6.0-beta9' && NexusDB::schema()->hasColumn('attendance', 'total_days')) { if (WITH_LARAVEL && VERSION_NUMBER == '1.6.0-beta9' && NexusDB::schema()->hasColumn('attendance', 'total_days')) {
$this->migrateAttendance(); $this->migrateAttendance();
} }
if (WITH_LARAVEL && version_compare(VERSION_NUMBER, '1.6.0-beta12', '>=')) {
$this->addSetting('authority.torrent_hr', User::CLASS_ADMINISTRATOR);
$this->addSetting('bonus.cancel_hr', BonusLogs::DEFAULT_BONUS_CANCEL_ONE_HIT_AND_RUN);
}
} }
private function migrateAttendance() private function migrateAttendance()

View File

@@ -105,7 +105,7 @@ elseif ($az['showclienterror'] == 'yes'){
} }
// check torrent based on info_hash // check torrent based on info_hash
$checkTorrentSql = "SELECT id, owner, sp_state, seeders, leechers, UNIX_TIMESTAMP(added) AS ts, banned FROM torrents WHERE " . hash_where("info_hash", $info_hash); $checkTorrentSql = "SELECT id, owner, sp_state, seeders, leechers, UNIX_TIMESTAMP(added) AS ts, banned, hr FROM torrents WHERE " . hash_where("info_hash", $info_hash);
if (!$torrent = $Cache->get_value('torrent_hash_'.$info_hash.'_content')){ if (!$torrent = $Cache->get_value('torrent_hash_'.$info_hash.'_content')){
$res = sql_query($checkTorrentSql); $res = sql_query($checkTorrentSql);
$torrent = mysql_fetch_array($res); $torrent = mysql_fetch_array($res);
@@ -141,7 +141,12 @@ else $limit = "";
$announce_wait = 30; $announce_wait = 30;
$fields = "seeder, peer_id, ip, port, uploaded, downloaded, (".TIMENOW." - UNIX_TIMESTAMP(last_action)) AS announcetime, UNIX_TIMESTAMP(prev_action) AS prevts"; $fields = "seeder, peer_id, ip, port, uploaded, downloaded, (".TIMENOW." - UNIX_TIMESTAMP(last_action)) AS announcetime, UNIX_TIMESTAMP(prev_action) AS prevts";
$peerlistsql = "SELECT ".$fields." FROM peers WHERE torrent = ".$torrentid." AND connectable = 'yes' ".$only_leech_query.$limit; //$peerlistsql = "SELECT ".$fields." FROM peers WHERE torrent = ".$torrentid." AND connectable = 'yes' ".$only_leech_query.$limit;
/**
* return all peers,include connectable no
* @since 1.6.0-beta12
*/
$peerlistsql = "SELECT ".$fields." FROM peers WHERE torrent = " . $torrentid . $only_leech_query . $limit;
$res = sql_query($peerlistsql); $res = sql_query($peerlistsql);
$real_annnounce_interval = $announce_interval; $real_annnounce_interval = $announce_interval;
@@ -399,15 +404,30 @@ elseif(isset($self))
{ {
if ($seeder <> $self["seeder"]) if ($seeder <> $self["seeder"])
$updateset[] = ($seeder == "yes" ? "seeders = seeders + 1, leechers = leechers - 1" : "seeders = seeders - 1, leechers = leechers + 1"); $updateset[] = ($seeder == "yes" ? "seeders = seeders + 1, leechers = leechers - 1" : "seeders = seeders - 1, leechers = leechers + 1");
sql_query("UPDATE snatched SET uploaded = uploaded + $trueupthis, downloaded = downloaded + $truedownthis, to_go = $left, $announcetime, last_action = ".$dt." $finished_snatched WHERE torrentid = $torrentid AND userid = $userid") or err("SL Err 2"); $snatchInfo = \App\Models\Snatch::query()
->where('torrentid', $torrentid)
->where('userid', $userid)
->orderBy('id', 'desc')
->first();
if ($snatchInfo) {
sql_query("UPDATE snatched SET uploaded = uploaded + $trueupthis, downloaded = downloaded + $truedownthis, to_go = $left, $announcetime, last_action = ".$dt." $finished_snatched WHERE torrentid = $torrentid AND userid = $userid") or err("SL Err 2");
if ($event == "completed") {
$hrMode = get_setting('hr.mode');
if ($hrMode == \App\Models\HitAndRun::MODE_GLOBAL || ($hrMode == \App\Models\HitAndRun::MODE_MANUAL && $torrent['hr'] == \App\Models\Torrent::HR_YES)) {
$sql = "insert into hit_and_runs (uid, torrent_id, snatched_id) values ($userid, $torrentid, {$snatchInfo->id}) on duplicate key update updated_at = " . sqlesc(date('Y-m-d H:i:s'));
$affectedRows = sql_query($sql);
do_log("[INSERT_H&R], $sql, affectedRows: $affectedRows");
}
}
}
} }
} }
else else
{ {
if (strlen($ip) > 15) { if (strlen($ip) > 15) {
$sockres = @pfsockopen("tcp://[".$ip."]",$port,$errno,$errstr,5); $sockres = @pfsockopen("tcp://[".$ip."]",$port,$errno,$errstr,1);
} else { } else {
$sockres = @pfsockopen($ip, $port, $errno, $errstr, 5); $sockres = @pfsockopen($ip, $port, $errno, $errstr, 1);
} }
if (!$sockres) if (!$sockres)
{ {

View File

@@ -11,7 +11,7 @@ int_check($id);
if (!isset($id) || !$id) if (!isset($id) || !$id)
die(); die();
$res = sql_query("SELECT torrents.cache_stamp, torrents.sp_state, torrents.url, torrents.small_descr, torrents.seeders, torrents.banned, torrents.leechers, torrents.info_hash, torrents.filename, nfo, LENGTH(torrents.nfo) AS nfosz, torrents.last_action, torrents.name, torrents.owner, torrents.save_as, torrents.descr, torrents.visible, torrents.size, torrents.added, torrents.views, torrents.hits, torrents.times_completed, torrents.id, torrents.type, torrents.numfiles, torrents.anonymous, torrents.pt_gen, torrents.technical_info, $res = sql_query("SELECT torrents.cache_stamp, torrents.sp_state, torrents.url, torrents.small_descr, torrents.seeders, torrents.banned, torrents.leechers, torrents.info_hash, torrents.filename, nfo, LENGTH(torrents.nfo) AS nfosz, torrents.last_action, torrents.name, torrents.owner, torrents.save_as, torrents.descr, torrents.visible, torrents.size, torrents.added, torrents.views, torrents.hits, torrents.times_completed, torrents.id, torrents.type, torrents.numfiles, torrents.anonymous, torrents.pt_gen, torrents.technical_info, torrents.hr,
categories.name AS cat_name, categories.mode as search_box_id, sources.name AS source_name, media.name AS medium_name, codecs.name AS codec_name, standards.name AS standard_name, processings.name AS processing_name, teams.name AS team_name, audiocodecs.name AS audiocodec_name categories.name AS cat_name, categories.mode as search_box_id, sources.name AS source_name, media.name AS medium_name, codecs.name AS codec_name, standards.name AS standard_name, processings.name AS processing_name, teams.name AS team_name, audiocodecs.name AS audiocodec_name
FROM torrents LEFT JOIN categories ON torrents.category = categories.id FROM torrents LEFT JOIN categories ON torrents.category = categories.id
LEFT JOIN sources ON torrents.source = sources.id LEFT JOIN sources ON torrents.source = sources.id
@@ -66,8 +66,8 @@ if (!$row) {
print("<p><b>".$lang_details['text_go_back'] . "<a href=\"".htmlspecialchars($_GET["returnto"])."\">" . $lang_details['text_whence_you_came']."</a></b></p>"); print("<p><b>".$lang_details['text_go_back'] . "<a href=\"".htmlspecialchars($_GET["returnto"])."\">" . $lang_details['text_whence_you_came']."</a></b></p>");
} }
$sp_torrent = get_torrent_promotion_append($row['sp_state'],'word'); $sp_torrent = get_torrent_promotion_append($row['sp_state'],'word');
$hrImg = get_hr_img($row);
$s=htmlspecialchars($row["name"]).($sp_torrent ? "&nbsp;&nbsp;&nbsp;".$sp_torrent : ""); $s=htmlspecialchars($row["name"]).($sp_torrent ? "&nbsp;&nbsp;&nbsp;".$sp_torrent : "") . $hrImg;
print("<h1 align=\"center\" id=\"top\">".$s."</h1>\n"); print("<h1 align=\"center\" id=\"top\">".$s."</h1>\n");
print("<table width=\"97%\" cellspacing=\"0\" cellpadding=\"5\">\n"); print("<table width=\"97%\" cellspacing=\"0\" cellpadding=\"5\">\n");
@@ -281,7 +281,7 @@ if (!$row) {
if ($imdb_id) if ($imdb_id)
{ {
$where_area = " url = " . sqlesc((int)$imdb_id) ." AND torrents.id != ".sqlesc($id); $where_area = " url = " . sqlesc((int)$imdb_id) ." AND torrents.id != ".sqlesc($id);
$copies_res = sql_query("SELECT torrents.id, torrents.name, torrents.sp_state, torrents.size, torrents.added, torrents.seeders, torrents.leechers, categories.id AS catid, categories.name AS catname, categories.image AS catimage, sources.name AS source_name, media.name AS medium_name, codecs.name AS codec_name, standards.name AS standard_name, processings.name AS processing_name FROM torrents LEFT JOIN categories ON torrents.category=categories.id LEFT JOIN sources ON torrents.source = sources.id LEFT JOIN media ON torrents.medium = media.id LEFT JOIN codecs ON torrents.codec = codecs.id LEFT JOIN standards ON torrents.standard = standards.id LEFT JOIN processings ON torrents.processing = processings.id WHERE " . $where_area . " ORDER BY torrents.id DESC") or sqlerr(__FILE__, __LINE__); $copies_res = sql_query("SELECT torrents.id, torrents.name, torrents.sp_state, torrents.size, torrents.added, torrents.seeders, torrents.leechers, torrents.hr,categories.id AS catid, categories.name AS catname, categories.image AS catimage, sources.name AS source_name, media.name AS medium_name, codecs.name AS codec_name, standards.name AS standard_name, processings.name AS processing_name FROM torrents LEFT JOIN categories ON torrents.category=categories.id LEFT JOIN sources ON torrents.source = sources.id LEFT JOIN media ON torrents.medium = media.id LEFT JOIN codecs ON torrents.codec = codecs.id LEFT JOIN standards ON torrents.standard = standards.id LEFT JOIN processings ON torrents.processing = processings.id WHERE " . $where_area . " ORDER BY torrents.id DESC") or sqlerr(__FILE__, __LINE__);
$copies_count = mysql_num_rows($copies_res); $copies_count = mysql_num_rows($copies_res);
if($copies_count > 0) if($copies_count > 0)
@@ -311,8 +311,9 @@ if (!$row) {
$sphighlight = get_torrent_bg_color($copy_row['sp_state']); $sphighlight = get_torrent_bg_color($copy_row['sp_state']);
$sp_info = get_torrent_promotion_append($copy_row['sp_state']); $sp_info = get_torrent_promotion_append($copy_row['sp_state']);
$hrImg = get_hr_img($copy_row);
$s .= "<tr". $sphighlight."><td class=\"rowfollow nowrap\" valign=\"middle\" style='padding: 0px'>".return_category_image($copy_row["catid"], "torrents.php?allsec=1&amp;")."</td><td class=\"rowfollow\" align=\"left\"><a href=\"" . htmlspecialchars(get_protocol_prefix() . $BASEURL . "/details.php?id=" . $copy_row["id"]. "&hit=1")."\">" . $dispname ."</a>". $sp_info."</td>" . $s .= "<tr". $sphighlight."><td class=\"rowfollow nowrap\" valign=\"middle\" style='padding: 0px'>".return_category_image($copy_row["catid"], "torrents.php?allsec=1&amp;")."</td><td class=\"rowfollow\" align=\"left\"><a href=\"" . htmlspecialchars(get_protocol_prefix() . $BASEURL . "/details.php?id=" . $copy_row["id"]. "&hit=1")."\">" . $dispname ."</a>". $sp_info. $hrImg ."</td>" .
"<td class=\"rowfollow\" align=\"left\">" . rtrim(trim($other_source_info . $other_medium_info . $other_codec_info . $other_standard_info . $other_processing_info), ","). "</td>" . "<td class=\"rowfollow\" align=\"left\">" . rtrim(trim($other_source_info . $other_medium_info . $other_codec_info . $other_standard_info . $other_processing_info), ","). "</td>" .
"<td class=\"rowfollow\" align=\"center\">" . mksize($copy_row["size"]) . "</td>" . "<td class=\"rowfollow\" align=\"center\">" . mksize($copy_row["size"]) . "</td>" .
"<td class=\"rowfollow nowrap\" align=\"center\">" . str_replace("&nbsp;", "<br />", gettime($copy_row["added"],false)). "</td>" . "<td class=\"rowfollow nowrap\" align=\"center\">" . str_replace("&nbsp;", "<br />", gettime($copy_row["added"],false)). "</td>" .

View File

@@ -183,6 +183,11 @@ else {
} }
tr($lang_edit['row_pick'], $pickcontent, 1); tr($lang_edit['row_pick'], $pickcontent, 1);
} }
if (get_setting('hr.mode') == \App\Models\HitAndRun::MODE_MANUAL && get_user_class() >= get_setting('authority.torrent_hr')) {
$hrRadio = sprintf('<label><input type="radio" name="hr" value="0"%s />NO</label>', (string)$row['hr'] === '0' ? ' checked' : '');
$hrRadio .= sprintf('<label><input type="radio" name="hr" value="1"%s />YES</label>', (string)$row['hr'] === '1' ? ' checked' : '');
tr('H&R', $hrRadio, 1);
}
print("<tr><td class=\"toolbox\" colspan=\"2\" align=\"center\"><input id=\"qr\" type=\"submit\" value=\"".$lang_edit['submit_edit_it']."\" /> <input type=\"reset\" value=\"".$lang_edit['submit_revert_changes']."\" /></td></tr>\n"); print("<tr><td class=\"toolbox\" colspan=\"2\" align=\"center\"><input id=\"qr\" type=\"submit\" value=\"".$lang_edit['submit_edit_it']."\" /> <input type=\"reset\" value=\"".$lang_edit['submit_revert_changes']."\" /></td></tr>\n");
print("</table>\n"); print("</table>\n");

View File

@@ -3,9 +3,9 @@ require "../include/bittorrent.php";
dbconn(); dbconn();
require_once(get_langfile_path()); require_once(get_langfile_path());
//Send some headers to keep the user's browser from caching the response. //Send some headers to keep the user's browser from caching the response.
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" ); header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" );
header("Cache-Control: no-cache, must-revalidate" ); header("Cache-Control: no-cache, must-revalidate" );
header("Pragma: no-cache" ); header("Pragma: no-cache" );
header("Content-Type: text/xml; charset=utf-8"); header("Content-Type: text/xml; charset=utf-8");
function maketable($res, $mode = 'seeding') function maketable($res, $mode = 'seeding')
@@ -94,6 +94,7 @@ function maketable($res, $mode = 'seeding')
$sphighlight = get_torrent_bg_color($arr['sp_state']); $sphighlight = get_torrent_bg_color($arr['sp_state']);
$sp_torrent = get_torrent_promotion_append($arr['sp_state']); $sp_torrent = get_torrent_promotion_append($arr['sp_state']);
$hrImg = get_hr_img($arr);
//torrent name //torrent name
$dispname = $nametitle = htmlspecialchars($arr["torrentname"]); $dispname = $nametitle = htmlspecialchars($arr["torrentname"]);
@@ -113,7 +114,7 @@ function maketable($res, $mode = 'seeding')
} }
else $dissmall_descr == ""; else $dissmall_descr == "";
$ret .= "<tr" . $sphighlight . "><td class=\"rowfollow nowrap\" valign=\"middle\" style='padding: 0px'>".return_category_image($arr['category'], "torrents.php?allsec=1&amp;")."</td>\n" . $ret .= "<tr" . $sphighlight . "><td class=\"rowfollow nowrap\" valign=\"middle\" style='padding: 0px'>".return_category_image($arr['category'], "torrents.php?allsec=1&amp;")."</td>\n" .
"<td class=\"rowfollow\" width=\"100%\" align=\"left\"><a href=\"".htmlspecialchars("details.php?id=".$arr['torrent']."&hit=1")."\" title=\"".$nametitle."\"><b>" . $dispname . "</b></a>". $sp_torrent .($dissmall_descr == "" ? "" : "<br />" . $dissmall_descr) . "</td>"; "<td class=\"rowfollow\" width=\"100%\" align=\"left\"><a href=\"".htmlspecialchars("details.php?id=".$arr['torrent']."&hit=1")."\" title=\"".$nametitle."\"><b>" . $dispname . "</b></a>". $sp_torrent . $hrImg .($dissmall_descr == "" ? "" : "<br />" . $dissmall_descr) . "</td>";
//size //size
if ($showsize) if ($showsize)
$ret .= "<td class=\"rowfollow\" align=\"center\">". mksize_compact($arr['size'])."</td>"; $ret .= "<td class=\"rowfollow\" align=\"center\">". mksize_compact($arr['size'])."</td>";
@@ -155,7 +156,7 @@ function maketable($res, $mode = 'seeding')
if ($showanonymous) if ($showanonymous)
$ret .= "<td class=\"rowfollow\" align=\"center\">".$arr['anonymous']."</td>"; $ret .= "<td class=\"rowfollow\" align=\"center\">".$arr['anonymous']."</td>";
$ret .="</tr>\n"; $ret .="</tr>\n";
} }
$ret .= "</table>\n"; $ret .= "</table>\n";
return $ret; return $ret;
@@ -172,7 +173,7 @@ switch ($type)
{ {
case 'uploaded': case 'uploaded':
{ {
$res = sql_query("SELECT torrents.id AS torrent, torrents.name as torrentname, small_descr, seeders, leechers, anonymous, categories.name AS catname, categories.image, category, sp_state, size, snatched.seedtime, snatched.uploaded FROM torrents LEFT JOIN snatched ON torrents.id = snatched.torrentid LEFT JOIN categories ON torrents.category = categories.id WHERE torrents.owner=$id AND snatched.userid=$id " . (($CURUSER["id"] != $id)?((get_user_class() < $viewanonymous_class) ? " AND anonymous = 'no'":""):"") ." ORDER BY torrents.added DESC") or sqlerr(__FILE__, __LINE__); $res = sql_query("SELECT torrents.id AS torrent, torrents.name as torrentname, small_descr, seeders, leechers, anonymous, categories.name AS catname, categories.image, category, sp_state, size, hr, snatched.seedtime, snatched.uploaded FROM torrents LEFT JOIN snatched ON torrents.id = snatched.torrentid LEFT JOIN categories ON torrents.category = categories.id WHERE torrents.owner=$id AND snatched.userid=$id " . (($CURUSER["id"] != $id)?((get_user_class() < $viewanonymous_class) ? " AND anonymous = 'no'":""):"") ." ORDER BY torrents.added DESC") or sqlerr(__FILE__, __LINE__);
$count = mysql_num_rows($res); $count = mysql_num_rows($res);
if ($count > 0) if ($count > 0)
{ {
@@ -184,7 +185,7 @@ switch ($type)
// Current Seeding // Current Seeding
case 'seeding': case 'seeding':
{ {
$res = sql_query("SELECT torrent,added,snatched.uploaded,snatched.downloaded,torrents.name as torrentname, torrents.small_descr, torrents.sp_state, categories.name as catname,size,image,category,seeders,leechers FROM peers LEFT JOIN torrents ON peers.torrent = torrents.id LEFT JOIN categories ON torrents.category = categories.id LEFT JOIN snatched ON torrents.id = snatched.torrentid WHERE peers.userid=$id AND snatched.userid = $id AND peers.seeder='yes' ORDER BY torrents.added DESC") or sqlerr(); $res = sql_query("SELECT torrent,added,snatched.uploaded,snatched.downloaded,torrents.name as torrentname, torrents.small_descr, torrents.sp_state, categories.name as catname,size,hr,image,category,seeders,leechers FROM peers LEFT JOIN torrents ON peers.torrent = torrents.id LEFT JOIN categories ON torrents.category = categories.id LEFT JOIN snatched ON torrents.id = snatched.torrentid WHERE peers.userid=$id AND snatched.userid = $id AND peers.seeder='yes' ORDER BY torrents.added DESC") or sqlerr();
$count = mysql_num_rows($res); $count = mysql_num_rows($res);
if ($count > 0){ if ($count > 0){
$torrentlist = maketable($res, 'seeding'); $torrentlist = maketable($res, 'seeding');
@@ -195,7 +196,7 @@ switch ($type)
// Current Leeching // Current Leeching
case 'leeching': case 'leeching':
{ {
$res = sql_query("SELECT torrent,snatched.uploaded,snatched.downloaded,torrents.name as torrentname, torrents.small_descr, torrents.sp_state, categories.name as catname,size,image,category,seeders,leechers FROM peers LEFT JOIN torrents ON peers.torrent = torrents.id LEFT JOIN categories ON torrents.category = categories.id LEFT JOIN snatched ON torrents.id = snatched.torrentid WHERE peers.userid=$id AND snatched.userid = $id AND peers.seeder='no' ORDER BY torrents.added DESC") or sqlerr(); $res = sql_query("SELECT torrent,snatched.uploaded,snatched.downloaded,torrents.name as torrentname, torrents.small_descr, torrents.sp_state, categories.name as catname,size,hr,image,category,seeders,leechers FROM peers LEFT JOIN torrents ON peers.torrent = torrents.id LEFT JOIN categories ON torrents.category = categories.id LEFT JOIN snatched ON torrents.id = snatched.torrentid WHERE peers.userid=$id AND snatched.userid = $id AND peers.seeder='no' ORDER BY torrents.added DESC") or sqlerr();
$count = mysql_num_rows($res); $count = mysql_num_rows($res);
if ($count > 0){ if ($count > 0){
$torrentlist = maketable($res, 'leeching'); $torrentlist = maketable($res, 'leeching');
@@ -206,7 +207,7 @@ switch ($type)
// Completed torrents // Completed torrents
case 'completed': case 'completed':
{ {
$res = sql_query("SELECT torrents.id AS torrent, torrents.name AS torrentname, small_descr, categories.name AS catname, categories.image, category, sp_state, size, snatched.uploaded, snatched.seedtime, snatched.leechtime, snatched.completedat FROM torrents LEFT JOIN snatched ON torrents.id = snatched.torrentid LEFT JOIN categories on torrents.category = categories.id WHERE snatched.finished='yes' AND torrents.owner != $id AND userid=$id ORDER BY snatched.completedat DESC") or sqlerr(); $res = sql_query("SELECT torrents.id AS torrent, torrents.name AS torrentname, small_descr, categories.name AS catname, categories.image, category, sp_state, size, hr,snatched.uploaded, snatched.seedtime, snatched.leechtime, snatched.completedat FROM torrents LEFT JOIN snatched ON torrents.id = snatched.torrentid LEFT JOIN categories on torrents.category = categories.id WHERE snatched.finished='yes' AND torrents.owner != $id AND userid=$id ORDER BY snatched.completedat DESC") or sqlerr();
$count = mysql_num_rows($res); $count = mysql_num_rows($res);
if ($count > 0) if ($count > 0)
{ {
@@ -218,7 +219,7 @@ switch ($type)
// Incomplete torrents // Incomplete torrents
case 'incomplete': case 'incomplete':
{ {
$res = sql_query("SELECT torrents.id AS torrent, torrents.name AS torrentname, small_descr, categories.name AS catname, categories.image, category, sp_state, size, snatched.uploaded, snatched.downloaded, snatched.leechtime FROM torrents LEFT JOIN snatched ON torrents.id = snatched.torrentid LEFT JOIN categories on torrents.category = categories.id WHERE snatched.finished='no' AND userid=$id AND torrents.owner != $id ORDER BY snatched.startdat DESC") or sqlerr(); $res = sql_query("SELECT torrents.id AS torrent, torrents.name AS torrentname, small_descr, categories.name AS catname, categories.image, category, sp_state, size, hr,snatched.uploaded, snatched.downloaded, snatched.leechtime FROM torrents LEFT JOIN snatched ON torrents.id = snatched.torrentid LEFT JOIN categories on torrents.category = categories.id WHERE snatched.finished='no' AND userid=$id AND torrents.owner != $id ORDER BY snatched.startdat DESC") or sqlerr();
$count = mysql_num_rows($res); $count = mysql_num_rows($res);
if ($count > 0) if ($count > 0)
{ {
@@ -226,7 +227,7 @@ switch ($type)
} }
break; break;
} }
default: default:
{ {
$count = 0; $count = 0;
$torrentlist = ""; $torrentlist = "";

View File

@@ -88,6 +88,17 @@ function bonusarray($option){
$bonus['description'] = $lang_mybonus['text_charity_giving_note']; $bonus['description'] = $lang_mybonus['text_charity_giving_note'];
break; break;
} }
case 10: {
$bonus['points'] = \App\Models\BonusLogs::getBonusForCancelHitAndRun();
$bonus['art'] = 'cancel_hr';
$bonus['menge'] = 0;
$bonus['name'] = $lang_mybonus['text_cancel_hr_title'];
$bonus['description'] = '<p>
<span style="">' . $lang_mybonus['text_cancel_hr_label'] . '</span>
<input type="number" name="hr_id" />
</p>';
break;
}
default: break; default: break;
} }
return $bonus; return $bonus;
@@ -116,6 +127,8 @@ if (isset($do)) {
$msg = $lang_mybonus['text_success_no_ad']; $msg = $lang_mybonus['text_success_no_ad'];
elseif ($do == "charity") elseif ($do == "charity")
$msg = $lang_mybonus['text_success_charity']; $msg = $lang_mybonus['text_success_charity'];
elseif ($do == "cancel_hr")
$msg = $lang_mybonus['text_success_cancel_hr'];
else else
$msg = ''; $msg = '';
} }
@@ -137,11 +150,17 @@ print("<tr><td class=\"colhead\" align=\"center\">".$lang_mybonus['col_option'].
"<td class=\"colhead\" align=\"center\">".$lang_mybonus['col_points']."</td>". "<td class=\"colhead\" align=\"center\">".$lang_mybonus['col_points']."</td>".
"<td class=\"colhead\" align=\"center\">".$lang_mybonus['col_trade']."</td>". "<td class=\"colhead\" align=\"center\">".$lang_mybonus['col_trade']."</td>".
"</tr>"); "</tr>");
for ($i=1; $i <=9; $i++) for ($i=1; $i <=10; $i++)
{ {
$bonusarray = bonusarray($i); $bonusarray = bonusarray($i);
if (($i == 7 && $bonusgift_bonus == 'no') || ($i == 8 && ($enablead_advertisement == 'no' || $bonusnoad_advertisement == 'no'))) if (
continue; ($i == 7 && $bonusgift_bonus == 'no')
|| ($i == 8 && ($enablead_advertisement == 'no' || $bonusnoad_advertisement == 'no'))
|| ($i == 10 && !\App\Models\HitAndRun::getIsEnabled())
) {
continue;
}
print("<tr>"); print("<tr>");
print("<form action=\"?action=exchange\" method=\"post\">"); print("<form action=\"?action=exchange\" method=\"post\">");
print("<td class=\"rowhead_center\"><input type=\"hidden\" name=\"option\" value=\"".$i."\" /><b>".$i."</b></td>"); print("<td class=\"rowhead_center\"><input type=\"hidden\" name=\"option\" value=\"".$i."\" /><b>".$i."</b></td>");
@@ -217,6 +236,7 @@ for ($i=1; $i <=9; $i++)
print("</tr>"); print("</tr>");
} }
print("</table><br />"); print("</table><br />");
?> ?>
@@ -306,13 +326,12 @@ print($lang_mybonus['text_howto_get_karma_five'].$uploadtorrent_bonus.$lang_mybo
// Bonus exchange // Bonus exchange
if ($action == "exchange") { if ($action == "exchange") {
if ($_POST["userid"] || $_POST["points"] || $_POST["bonus"] || $_POST["art"]){ if (isset($_POST["userid"]) || isset($_POST["points"]) || isset($_POST["bonus"]) || isset($_POST["art"])){
write_log("User " . $CURUSER["username"] . "," . $CURUSER["ip"] . " is trying to cheat at bonus system",'mod'); write_log("User " . $CURUSER["username"] . "," . $CURUSER["ip"] . " is trying to cheat at bonus system",'mod');
die($lang_mybonus['text_cheat_alert']); die($lang_mybonus['text_cheat_alert']);
} }
$option = (int)$_POST["option"]; $option = intval($_POST["option"] ?? 0);
$bonusarray = bonusarray($option); $bonusarray = bonusarray($option);
$points = $bonusarray['points']; $points = $bonusarray['points'];
$userid = $CURUSER['id']; $userid = $CURUSER['id'];
$art = $bonusarray['art']; $art = $bonusarray['art'];
@@ -472,7 +491,19 @@ if ($action == "exchange") {
print("<table width=\"97%\"><tr><td class=\"colhead\" align=\"left\" colspan=\"2\"><h1>".$lang_mybonus['text_oups']."</h1></td></tr>"); print("<table width=\"97%\"><tr><td class=\"colhead\" align=\"left\" colspan=\"2\"><h1>".$lang_mybonus['text_oups']."</h1></td></tr>");
print("<tr><td align=\"left\"></td><td align=\"left\">".$lang_mybonus['text_not_enough_karma']."<br /><br /></td></tr></table>"); print("<tr><td align=\"left\"></td><td align=\"left\">".$lang_mybonus['text_not_enough_karma']."<br /><br /></td></tr></table>");
} }
} } elseif ($art == 'cancel_hr') {
if (empty($_POST['hr_id'])) {
stderr("Error","Invalid H&R ID: " . ($_POST['hr_id'] ?? ''), false, false);
}
try {
$bonusRep = new \App\Repositories\BonusRepository();
$bonusRep->consumeToCancelHitAndRun($userid, $_POST['hr_id']);
nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=cancel_hr");
} catch (\Exception $exception) {
do_log($exception->getMessage(), 'error');
stderr('Error', "Something wrong...", false, false);
}
}
} }
} }
stdfoot(); stdfoot();

95
public/myhr.php Normal file
View File

@@ -0,0 +1,95 @@
<?php
require "../include/bittorrent.php";
dbconn();
loggedinorreturn();
require_once(get_langfile_path());
$userid = $CURUSER['id'];
if (get_user_class() >= UC_ADMINISTRATOR && !empty($_GET['userid'])) {
$userid = $_GET['userid'];
}
$userInfo = \App\Models\User::query()->find($userid);
if (empty($userInfo)) {
stderr('Error', "User not exists.");
}
$pageTitle = $userInfo->username . ' - H&R';
stdhead($pageTitle);
print("<h1>$pageTitle</h1>");
$status = $_GET['status'] ?? \App\Models\HitAndRun::STATUS_INSPECTING;
$allStatus = \App\Models\HitAndRun::listStatus();
$headerFilters = [];
foreach ($allStatus as $key => $value) {
$headerFilters[] = sprintf('<a href="?status=%s" class="%s"><b>%s</b></a>', $key, $key == $status ? 'faqlink' : '', $value['text']);
}
print("<p>" . implode(' | ', $headerFilters) . "</p>");
$q = $_GET['q'] ?? '';
$filterForm = <<<FORM
<form id="filterForm" action="{$_SERVER['REQUEST_URI']}" method="get">
<input id="q" type="text" name="q" value="{$q}" placeholder="{$lang_myhr['th_hr_id']}">
<input type="submit">
<input type="reset" onclick="document.getElementById('q').value='';document.getElementById('filterForm').submit();">
</form>
FORM;
begin_main_frame("", true);
print $filterForm;
$rescount = \App\Models\HitAndRun::query()->where('status', $status)->count();
list($pagertop, $pagerbottom, $limit, $offset, $pageSize) = pager(50, $rescount, "?status=$status");
print("<table width='100%'>");
print("<tr>
<td class='colhead' align='center'>{$lang_myhr['th_hr_id']}</td>
<td class='colhead' align='center'>{$lang_myhr['th_torrent_name']}</td>
<td class='colhead' align='center'>{$lang_myhr['th_uploaded']}</td>
<td class='colhead' align='center'>{$lang_myhr['th_downloaded']}</td>
<td class='colhead' align='center'>{$lang_myhr['th_share_ratio']}</td>
<td class='colhead' align='center'>{$lang_myhr['th_seed_time_required']}</td>
<td class='colhead' align='center'>{$lang_myhr['th_completed_at']}</td>
<td class='colhead' align='center'>{$lang_myhr['th_ttl']}</td>
<td class='colhead' align='center'>{$lang_myhr['th_comment']}</td>
</tr>");
if ($rescount) {
$query = \App\Models\HitAndRun::query()
->where('uid', $userid)
->where('status', $status)
->with([
'torrent' => function ($query) {$query->select(['id', 'size', 'name']);},
'snatch',
'user' => function ($query) {$query->select(['id', 'lang']);},
'user.language',
])
->offset($offset)
->limit($pageSize)
->orderBy('id', 'desc');
if (!empty($q)) {
$query->where('id', $q);
}
$list = $query->get();
foreach($list as $row) {
print("<tr>
<td class='rowfollow nowrap' align='center'>" . $row->id . "</td>
<td class='rowfollow' align='left'><a href='details.php?id=" . $row->torrent_id . "'>" . $row->torrent->name . "</a></td>
<td class='rowfollow nowrap' align='center'>" . mksize($row->snatch->uploaded) . "</td>
<td class='rowfollow nowrap' align='center'>" . mksize($row->snatch->downloaded) . "</td>
<td class='rowfollow nowrap' align='center'>" . get_hr_ratio($row->snatch->uploaded, $row->snatch->downloaded) . "</td>
<td class='rowfollow nowrap' align='center'>" . ($row->status == \App\Models\HitAndRun::STATUS_INSPECTING ? mkprettytime(3600 * get_setting('hr.seed_time_minimum') - $row->snatch->seedtime) : '---') . "</td>
<td class='rowfollow nowrap' align='center'>" . $row->snatch->completedat->toDateTimeString() . "</td>
<td class='rowfollow nowrap' align='center' >" . ($row->status == \App\Models\HitAndRun::STATUS_INSPECTING ? mkprettytime(\Carbon\Carbon::now()->diffInSeconds($row->snatch->completedat->addHours(get_setting('hr.inspect_time')))) : '---') . "</td>
<td class='rowfollow nowrap' align='left' style='padding-left: 10px'>" . nl2br($row->comment) . "</td>
</tr>");
}
}
print("</table>");
print($pagerbottom);
end_main_frame();
stdfoot();

View File

@@ -91,7 +91,7 @@ elseif ($action == 'savesettings_code') // save database
elseif ($action == 'savesettings_bonus') // save bonus elseif ($action == 'savesettings_bonus') // save bonus
{ {
stdhead($lang_settings['head_save_bonus_settings']); stdhead($lang_settings['head_save_bonus_settings']);
$validConfig = array('donortimes','perseeding','maxseeding','tzero','nzero','bzero','l', 'uploadtorrent','uploadsubtitle','starttopic','makepost','addcomment','pollvote','offervote', 'funboxvote','saythanks','receivethanks','funboxreward','onegbupload','fivegbupload','tengbupload', 'ratiolimit','dlamountlimit','oneinvite','customtitle','vipstatus','bonusgift', 'basictax', 'taxpercentage', 'prolinkpoint', 'prolinktime', 'attendance_initial', 'attendance_step', 'attendance_max'); $validConfig = array('donortimes','perseeding','maxseeding','tzero','nzero','bzero','l', 'uploadtorrent','uploadsubtitle','starttopic','makepost','addcomment','pollvote','offervote', 'funboxvote','saythanks','receivethanks','funboxreward','onegbupload','fivegbupload','tengbupload', 'ratiolimit','dlamountlimit','oneinvite','customtitle','vipstatus','bonusgift', 'basictax', 'taxpercentage', 'prolinkpoint', 'prolinktime', 'attendance_initial', 'attendance_step', 'attendance_max', 'cancel_hr');
GetVar($validConfig); GetVar($validConfig);
$BONUS = []; $BONUS = [];
foreach($validConfig as $config) { foreach($validConfig as $config) {
@@ -193,7 +193,7 @@ elseif ($action == 'savesettings_security') // save security
elseif ($action == 'savesettings_authority') // save user authority elseif ($action == 'savesettings_authority') // save user authority
{ {
stdhead($lang_settings['head_save_authority_settings']); stdhead($lang_settings['head_save_authority_settings']);
$validConfig = array('defaultclass','staffmem','newsmanage','newfunitem','funmanage','sbmanage','pollmanage','applylink', 'linkmanage', 'postmanage','commanage','forummanage','viewuserlist','torrentmanage','torrentsticky', 'torrentonpromotion', 'askreseed', 'viewnfo', 'torrentstructure','sendinvite','viewhistory','topten','log','confilog','userprofile', 'torrenthistory','prfmanage', 'cruprfmanage','uploadsub','delownsub','submanage','updateextinfo', 'viewanonymous','beanonymous','addoffer','offermanage', 'upload','uploadspecial','view_special_torrent','movetorrent','chrmanage','viewinvite', 'buyinvite','seebanned','againstoffer','userbar'); $validConfig = array('defaultclass','staffmem','newsmanage','newfunitem','funmanage','sbmanage','pollmanage','applylink', 'linkmanage', 'postmanage','commanage','forummanage','viewuserlist','torrentmanage','torrentsticky', 'torrentonpromotion', 'torrent_hr', 'askreseed', 'viewnfo', 'torrentstructure','sendinvite','viewhistory','topten','log','confilog','userprofile', 'torrenthistory','prfmanage', 'cruprfmanage','uploadsub','delownsub','submanage','updateextinfo', 'viewanonymous','beanonymous','addoffer','offermanage', 'upload','uploadspecial','view_special_torrent','movetorrent','chrmanage','viewinvite', 'buyinvite','seebanned','againstoffer','userbar');
GetVar($validConfig); GetVar($validConfig);
$AUTHORITY = []; $AUTHORITY = [];
foreach($validConfig as $config) { foreach($validConfig as $config) {
@@ -389,6 +389,7 @@ elseif ($action == 'authoritysettings') //Authority settings
tr($lang_settings['row_torrent_management'], $lang_settings['text_minimum_class'].classlist('torrentmanage',$maxclass,$AUTHORITY['torrentmanage']).$lang_settings['text_default'].get_user_class_name(UC_MODERATOR,false,true,true).$lang_settings['text_torrent_management_note'], 1); tr($lang_settings['row_torrent_management'], $lang_settings['text_minimum_class'].classlist('torrentmanage',$maxclass,$AUTHORITY['torrentmanage']).$lang_settings['text_default'].get_user_class_name(UC_MODERATOR,false,true,true).$lang_settings['text_torrent_management_note'], 1);
tr($lang_settings['row_torrent_sticky'], $lang_settings['text_minimum_class'].classlist('torrentsticky',$maxclass,$AUTHORITY['torrentsticky']).$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).$lang_settings['text_torrent_sticky_note'],1); tr($lang_settings['row_torrent_sticky'], $lang_settings['text_minimum_class'].classlist('torrentsticky',$maxclass,$AUTHORITY['torrentsticky']).$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).$lang_settings['text_torrent_sticky_note'],1);
tr($lang_settings['row_torrent_on_promotion'], $lang_settings['text_minimum_class'].classlist('torrentonpromotion',$maxclass,$AUTHORITY['torrentonpromotion'] ?? '').$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).$lang_settings['text_torrent_promotion_note'],1); tr($lang_settings['row_torrent_on_promotion'], $lang_settings['text_minimum_class'].classlist('torrentonpromotion',$maxclass,$AUTHORITY['torrentonpromotion'] ?? '').$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).$lang_settings['text_torrent_promotion_note'],1);
tr($lang_settings['row_torrent_hr'], $lang_settings['text_minimum_class'].classlist('torrent_hr',$maxclass,$AUTHORITY['torrent_hr'] ?? '').$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).$lang_settings['text_torrent_hr_note'],1);
tr($lang_settings['row_ask_for_reseed'], $lang_settings['text_minimum_class'].classlist('askreseed',$maxclass,$AUTHORITY['askreseed']).$lang_settings['text_default'].get_user_class_name(UC_POWER_USER,false,true,true).$lang_settings['text_ask_for_reseed_note'],1); tr($lang_settings['row_ask_for_reseed'], $lang_settings['text_minimum_class'].classlist('askreseed',$maxclass,$AUTHORITY['askreseed']).$lang_settings['text_default'].get_user_class_name(UC_POWER_USER,false,true,true).$lang_settings['text_ask_for_reseed_note'],1);
tr($lang_settings['row_view_nfo'], $lang_settings['text_minimum_class'].classlist('viewnfo',$maxclass,$AUTHORITY['viewnfo']).$lang_settings['text_default'].get_user_class_name(UC_POWER_USER,false,true,true).$lang_settings['text_view_nfo_note'],1); tr($lang_settings['row_view_nfo'], $lang_settings['text_minimum_class'].classlist('viewnfo',$maxclass,$AUTHORITY['viewnfo']).$lang_settings['text_default'].get_user_class_name(UC_POWER_USER,false,true,true).$lang_settings['text_view_nfo_note'],1);
tr($lang_settings['row_view_torrent_structure'], $lang_settings['text_minimum_class'].classlist('torrentstructure',$maxclass,$AUTHORITY['torrentstructure']).$lang_settings['text_default'].get_user_class_name(UC_ULTIMATE_USER,false,true,true).$lang_settings['text_view_torrent_structure_note'],1); tr($lang_settings['row_view_torrent_structure'], $lang_settings['text_minimum_class'].classlist('torrentstructure',$maxclass,$AUTHORITY['torrentstructure']).$lang_settings['text_default'].get_user_class_name(UC_ULTIMATE_USER,false,true,true).$lang_settings['text_view_torrent_structure_note'],1);
@@ -523,6 +524,7 @@ elseif ($action == 'bonussettings'){
tr($lang_settings['row_vip_status'],$lang_settings['text_it_costs_user']."<input type='text' style=\"width: 50px\" name=vipstatus value='".(isset($BONUS["vipstatus"]) ? $BONUS["vipstatus"] : 8000 )."'>".$lang_settings['text_vip_status_note'], 1); tr($lang_settings['row_vip_status'],$lang_settings['text_it_costs_user']."<input type='text' style=\"width: 50px\" name=vipstatus value='".(isset($BONUS["vipstatus"]) ? $BONUS["vipstatus"] : 8000 )."'>".$lang_settings['text_vip_status_note'], 1);
yesorno($lang_settings['row_allow_giving_bonus_gift'], 'bonusgift', $BONUS["bonusgift"], $lang_settings['text_giving_bonus_gift_note']); yesorno($lang_settings['row_allow_giving_bonus_gift'], 'bonusgift', $BONUS["bonusgift"], $lang_settings['text_giving_bonus_gift_note']);
tr($lang_settings['row_bonus_gift_tax'], $lang_settings['text_system_charges']."<input type='text' style=\"width: 50px\" name='basictax' value='".(isset($BONUS["basictax"]) ? $BONUS["basictax"] : 5 )."'>".$lang_settings['text_bonus_points_plus']."<input type='text' style=\"width: 50px\" name='taxpercentage' value='".(isset($BONUS["taxpercentage"]) ? $BONUS["taxpercentage"] : 10 )."'>".$lang_settings['text_bonus_gift_tax_note'], 1); tr($lang_settings['row_bonus_gift_tax'], $lang_settings['text_system_charges']."<input type='text' style=\"width: 50px\" name='basictax' value='".(isset($BONUS["basictax"]) ? $BONUS["basictax"] : 5 )."'>".$lang_settings['text_bonus_points_plus']."<input type='text' style=\"width: 50px\" name='taxpercentage' value='".(isset($BONUS["taxpercentage"]) ? $BONUS["taxpercentage"] : 10 )."'>".$lang_settings['text_bonus_gift_tax_note'], 1);
tr($lang_settings['row_cancel_hr'],$lang_settings['text_it_costs_user']."<input type='text' style=\"width: 50px\" name=cancel_hr value='".(isset($BONUS["cancel_hr"]) ? $BONUS["cancel_hr"] : \App\Models\BonusLogs::DEFAULT_BONUS_CANCEL_ONE_HIT_AND_RUN )."'>".$lang_settings['text_cancel_hr_note'], 1);
echo '<tr><td colspan="2" align="center"><b>签到奖励</b></td></tr>'; echo '<tr><td colspan="2" align="center"><b>签到奖励</b></td></tr>';
tr('初始奖励',sprintf('首次签到获得 <input type="number" style="width: 30px" name="attendance_initial" value="%u" min="0" /> 个魔力值。', $attendance_initial_bonus),true); tr('初始奖励',sprintf('首次签到获得 <input type="number" style="width: 30px" name="attendance_initial" value="%u" min="0" /> 个魔力值。', $attendance_initial_bonus),true);
tr('奖励增量',sprintf('每次签到增加 <input type="number" style="width: 30px" name="attendance_step" value="%u" min="0" /> 个魔力值。', $attendance_step_bonus),true); tr('奖励增量',sprintf('每次签到增加 <input type="number" style="width: 30px" name="attendance_step" value="%u" min="0" /> 个魔力值。', $attendance_step_bonus),true);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -474,3 +474,9 @@ img.sltbar
height:10px; height:10px;
background:url(bar.gif) repeat-x 0 -116px; background:url(bar.gif) repeat-x 0 -116px;
} }
img.hitandrun {
width: 35px;
height: 12px;
background: url(icons.gif) no-repeat -100px -171px;
margin-left: 0.5em;
}

View File

@@ -58,6 +58,14 @@ if (!empty($_POST['pt_gen'])) {
$updateset[] = "tags = " . array_sum($_POST['tags'] ?? []); $updateset[] = "tags = " . array_sum($_POST['tags'] ?? []);
$updateset[] = "technical_info = " . sqlesc($_POST['technical_info'] ?? ''); $updateset[] = "technical_info = " . sqlesc($_POST['technical_info'] ?? '');
/**
* hr
* @since 1.6.0-beta12
*/
if (isset($_POST['hr']) && isset(\App\Models\Torrent::$hrStatus[$_POST['hr']])) {
$updateset[] = "hr = " . sqlesc($_POST['hr']);
}
if ($enablenfo_main=='yes'){ if ($enablenfo_main=='yes'){
$nfoaction = $_POST['nfoaction']; $nfoaction = $_POST['nfoaction'];

View File

@@ -872,10 +872,10 @@ if ($count)
list($pagertop, $pagerbottom, $limit) = pager($torrentsperpage, $count, "?" . $addparam); list($pagertop, $pagerbottom, $limit) = pager($torrentsperpage, $count, "?" . $addparam);
if ($allsec == 1 || $enablespecial != 'yes'){ if ($allsec == 1 || $enablespecial != 'yes'){
$query = "SELECT torrents.id, torrents.sp_state, torrents.promotion_time_type, torrents.promotion_until, torrents.banned, torrents.picktype, torrents.pos_state, torrents.category, torrents.source, torrents.medium, torrents.codec, torrents.standard, torrents.processing, torrents.team, torrents.audiocodec, torrents.leechers, torrents.seeders, torrents.name, torrents.small_descr, torrents.times_completed, torrents.size, torrents.added, torrents.comments,torrents.anonymous,torrents.owner,torrents.url,torrents.cache_stamp,torrents.pt_gen,tags FROM torrents ".($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "")." $where $orderby $limit"; $query = "SELECT torrents.id, torrents.sp_state, torrents.promotion_time_type, torrents.promotion_until, torrents.banned, torrents.picktype, torrents.pos_state, torrents.category, torrents.source, torrents.medium, torrents.codec, torrents.standard, torrents.processing, torrents.team, torrents.audiocodec, torrents.leechers, torrents.seeders, torrents.name, torrents.small_descr, torrents.times_completed, torrents.size, torrents.added, torrents.comments,torrents.anonymous,torrents.owner,torrents.url,torrents.cache_stamp,torrents.pt_gen,torrents.tags,torrents.hr FROM torrents ".($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "")." $where $orderby $limit";
} }
else{ else{
$query = "SELECT torrents.id, torrents.sp_state, torrents.promotion_time_type, torrents.promotion_until, torrents.banned, torrents.picktype, torrents.pos_state, torrents.category, torrents.source, torrents.medium, torrents.codec, torrents.standard, torrents.processing, torrents.team, torrents.audiocodec, torrents.leechers, torrents.seeders, torrents.name, torrents.small_descr, torrents.times_completed, torrents.size, torrents.added, torrents.comments,torrents.anonymous,torrents.owner,torrents.url,torrents.cache_stamp,torrents.pt_gen,tags FROM torrents ".($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "")." LEFT JOIN categories ON torrents.category=categories.id $where $orderby $limit"; $query = "SELECT torrents.id, torrents.sp_state, torrents.promotion_time_type, torrents.promotion_until, torrents.banned, torrents.picktype, torrents.pos_state, torrents.category, torrents.source, torrents.medium, torrents.codec, torrents.standard, torrents.processing, torrents.team, torrents.audiocodec, torrents.leechers, torrents.seeders, torrents.name, torrents.small_descr, torrents.times_completed, torrents.size, torrents.added, torrents.comments,torrents.anonymous,torrents.owner,torrents.url,torrents.cache_stamp,torrents.pt_gen,torrents.tags,torrents.hr FROM torrents ".($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "")." LEFT JOIN categories ON torrents.category=categories.id $where $orderby $limit";
} }
$res = sql_query($query); $res = sql_query($query);

26
resources/lang/en/hr.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
return [
'status_' . \App\Models\HitAndRun::STATUS_INSPECTING => 'Inspecting',
'status_' . \App\Models\HitAndRun::STATUS_REACHED => 'Reached',
'status_' . \App\Models\HitAndRun::STATUS_UNREACHED => 'Unreached',
'status_' . \App\Models\HitAndRun::STATUS_PARDONED => 'Pardoned',
'mode_' . \App\Models\HitAndRun::MODE_DISABLED => 'Disabled',
'mode_' . \App\Models\HitAndRun::MODE_MANUAL => 'Manual',
'mode_' . \App\Models\HitAndRun::MODE_GLOBAL => 'Global',
'reached_by_seed_time_comment' => 'Up to:nowseed time: :seed_time Hour(s) reached :seed_time_minimum Hour(s)',
'reached_by_share_ratio_comment' => "Up to:now \nseed time: :seed_time Hour(s) Unreached :seed_time_minimum Hour(s) \nShare ratio: :share_ratio reached standard:ignore_when_ratio_reach",
'reached_message_subject' => 'H&R(ID: :hit_and_run_id) reached!',
'reached_message_content' => 'Congratulation! The torrent: :torrent_name(ID: :torrent_id) you download at: :completed_at has reach the requirement.',
'unreached_comment' => "Up to:now \nseed time :seed_time Hour(s) Unreached the requirement:seed_time_minimum Hour(s) \nshare ratio:share_ratio unreached the requirement:ignore_when_ratio_reach too",
'unreached_message_subject' => 'H&R(ID: :hit_and_run_id) unreached!',
'unreached_message_content' => 'The torrent :torrent_name(ID: :torrent_id) you downloaded on :completed_at: did not reached! Please note that accumulating a certain number of H&R your account will be disabled.',
'unreached_disable_comment' => 'H&R quantity reached the upper limit and account was disabled by the system',
'unreached_disable_message_content' => 'Your account has been disabled because the cumulative H&R count has been reached the system limit: :ban_user_when_counts_reach',
'bonus_cancel_comment' => ':now, spend :bonus canceled',
];

View File

@@ -0,0 +1,26 @@
<?php
return [
'status_' . \App\Models\HitAndRun::STATUS_INSPECTING => '考察中',
'status_' . \App\Models\HitAndRun::STATUS_REACHED => '已达标',
'status_' . \App\Models\HitAndRun::STATUS_UNREACHED => '未达标',
'status_' . \App\Models\HitAndRun::STATUS_PARDONED => '已免罪',
'mode_' . \App\Models\HitAndRun::MODE_DISABLED => '停用',
'mode_' . \App\Models\HitAndRun::MODE_MANUAL => '手动',
'mode_' . \App\Models\HitAndRun::MODE_GLOBAL => '全局',
'reached_by_seed_time_comment' => '截止::now做种时间: :seed_time Hour(s) 已达标 :seed_time_minimum Hour(s)',
'reached_by_share_ratio_comment' => "截止::now \n做种时间: :seed_time Hour(s) 未达标 :seed_time_minimum Hour(s) \n分享率: :share_ratio 达忽略标准::ignore_when_ratio_reach",
'reached_message_subject' => 'H&R(ID: :hit_and_run_id) 已达标!',
'reached_message_content' => '你于 :completed_at 下载完成的种子::torrent_name(ID: :torrent_id) H&R 已达标,恭喜!',
'unreached_comment' => "截止::now \n做种时间: :seed_time Hour(s) 未达要求::seed_time_minimum Hour(s) \n分享率::share_ratio 亦未达忽略标准::ignore_when_ratio_reach",
'unreached_message_subject' => 'H&R(ID: :hit_and_run_id) 未达标!',
'unreached_message_content' => '你于 :completed_at 下载完成的种子::torrent_name(ID: :torrent_id) H&R 未达标!累计一定数量账号将会被禁用,请注意。',
'unreached_disable_comment' => 'H&R 数量达上限被系统禁用。',
'unreached_disable_message_content' => '由于累计 H&R 数量已达系统上限::ban_user_when_counts_reach你的账号已被禁用。',
'bonus_cancel_comment' => ':now 花费 :bonus 魔力进行了消除',
];

View File

@@ -0,0 +1,26 @@
<?php
return [
'status_' . \App\Models\HitAndRun::STATUS_INSPECTING => '考察中',
'status_' . \App\Models\HitAndRun::STATUS_REACHED => '已達標',
'status_' . \App\Models\HitAndRun::STATUS_UNREACHED => '未達標',
'status_' . \App\Models\HitAndRun::STATUS_PARDONED => '已免罪',
'mode_' . \App\Models\HitAndRun::MODE_DISABLED => '停用',
'mode_' . \App\Models\HitAndRun::MODE_MANUAL => '手動',
'mode_' . \App\Models\HitAndRun::MODE_GLOBAL => '全局',
'reached_by_seed_time_comment' => '截止::now做種時間: :seed_time Hour(s) 已達標 :seed_time_minimum Hour(s)',
'reached_by_share_ratio_comment' => "截止::now \n做種時間: :seed_time Hour(s) 未達標 :seed_time_minimum Hour(s) \n分享率: :share_ratio 達忽略標準::ignore_when_ratio_reach",
'reached_message_subject' => 'H&R(ID: :hit_and_run_id) 已達標!',
'reached_message_content' => '你於 :completed_at 下載完成的種子::torrent_name(ID: :torrent_id) H&R 已達標,恭喜!',
'unreached_comment' => "截止::now \n做種時間: :seed_time Hour(s) 未達要求::seed_time_minimum Hour(s) \n分享率::share_ratio 亦未達忽略標準::ignore_when_ratio_reach",
'unreached_message_subject' => 'H&R(ID: :hit_and_run_id) 未達標!',
'unreached_message_content' => '你於 :completed_at 下載完成的種子::torrent_name(ID: :torrent_id) H&R 未達標!累計一定數量賬號將會被禁用,請註意。',
'unreached_disable_comment' => 'H&R 數量達上限被系統禁用。',
'unreached_disable_message_content' => '由於累計 H&R 數量已達系統上限::ban_user_when_counts_reach你的賬號已被禁用。',
'bonus_cancel_comment' => ':now 花費 :bonus 魔力進行了消除',
];