format code base using laravel/pint

This commit is contained in:
Christian Winther 2024-02-11 18:14:41 +00:00
parent f92aba7e7d
commit cd5325df56
1004 changed files with 39682 additions and 39542 deletions

View File

@ -138,11 +138,8 @@ jobs:
path: vendor/
key: composer-8.3-${{ hashFiles('composer.lock') }}
- name: Install laravel/pint
run: php composer.phar require laravel/pint --dev
- name: Install composer dependencies
run: php composer.phar install --no-interaction --prefer-dist
- name: Run laravel/pint
run: ./vendor/bin/pint --test
run: ./vendor/bin/pint --test --verbose

View File

@ -6,28 +6,29 @@ use Illuminate\Database\Eloquent\Model;
class AccountInterstitial extends Model
{
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $casts = [
'read_at' => 'datetime',
'appeal_requested_at' => 'datetime'
];
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $casts = [
'read_at' => 'datetime',
'appeal_requested_at' => 'datetime',
];
public const JSON_MESSAGE = 'Please use web browser to proceed.';
public const JSON_MESSAGE = 'Please use web browser to proceed.';
public function user()
{
return $this->belongsTo(User::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function status()
{
if($this->item_type != 'App\Status') {
return;
}
return $this->hasOne(Status::class, 'id', 'item_id');
}
public function status()
{
if ($this->item_type != 'App\Status') {
return;
}
return $this->hasOne(Status::class, 'id', 'item_id');
}
}

View File

@ -6,11 +6,10 @@ use Illuminate\Database\Eloquent\Model;
class AccountLog extends Model
{
protected $fillable = ['*'];
protected $fillable = ['*'];
public function user()
{
return $this->belongsTo(User::class);
return $this->belongsTo(User::class);
}
}

View File

@ -7,18 +7,18 @@ use Illuminate\Database\Eloquent\Model;
class Activity extends Model
{
protected $casts = [
'processed_at' => 'datetime'
'processed_at' => 'datetime',
];
protected $fillable = ['data', 'to_id', 'from_id', 'object_type'];
public function toProfile()
{
return $this->belongsTo(Profile::class, 'to_id');
}
public function toProfile()
{
return $this->belongsTo(Profile::class, 'to_id');
}
public function fromProfile()
{
return $this->belongsTo(Profile::class, 'from_id');
}
public function fromProfile()
{
return $this->belongsTo(Profile::class, 'from_id');
}
}

View File

@ -11,7 +11,6 @@ class BearerTokenResponse extends \League\OAuth2\Server\ResponseTypes\BearerToke
* AuthorizationServer::getResponseType() to pull in your version of
* this class rather than the default.
*
* @param AccessTokenEntityInterface $accessToken
*
* @return array
*/

View File

@ -17,9 +17,9 @@ class Avatar extends Model
protected $casts = [
'deleted_at' => 'datetime',
'last_fetched_at' => 'datetime',
'last_processed_at' => 'datetime'
'last_processed_at' => 'datetime',
];
protected $guarded = [];
protected $visible = [
@ -31,6 +31,6 @@ class Avatar extends Model
public function profile()
{
return $this->belongsTo(Profile::class);
return $this->belongsTo(Profile::class);
}
}

View File

@ -6,16 +6,15 @@ use Illuminate\Database\Eloquent\Model;
class Bookmark extends Model
{
protected $fillable = ['profile_id', 'status_id'];
protected $fillable = ['profile_id', 'status_id'];
public function status()
{
return $this->belongsTo(Status::class);
}
public function status()
{
return $this->belongsTo(Status::class);
}
public function profile()
{
return $this->belongsTo(Profile::class);
}
public function profile()
{
return $this->belongsTo(Profile::class);
}
}

View File

@ -8,28 +8,28 @@ class Circle extends Model
{
protected $fillable = [
'profile_id',
'name',
'description',
'bcc',
'scope',
'active'
'name',
'description',
'bcc',
'scope',
'active',
];
public function members()
{
return $this->hasManyThrough(
Profile::class,
CircleProfile::class,
'circle_id',
'id',
'id',
'profile_id'
);
return $this->hasManyThrough(
Profile::class,
CircleProfile::class,
'circle_id',
'id',
'id',
'profile_id'
);
}
public function owner()
{
return $this->belongsTo(Profile::class, 'profile_id');
return $this->belongsTo(Profile::class, 'profile_id');
}
public function url()

View File

@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Model;
class CircleProfile extends Model
{
protected $fillable = [
'circle_id',
'profile_id'
'circle_id',
'profile_id',
];
}

View File

@ -2,13 +2,11 @@
namespace App;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\Model;
use App\HasSnowflakePrimary;
class Collection extends Model
{
use HasSnowflakePrimary;
use HasSnowflakePrimary;
/**
* Indicates if the IDs are auto-incrementing.
@ -21,10 +19,10 @@ class Collection extends Model
public $dates = ['published_at'];
public function profile()
{
return $this->belongsTo(Profile::class);
}
public function profile()
{
return $this->belongsTo(Profile::class);
}
public function items()
{

View File

@ -3,28 +3,27 @@
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\HasSnowflakePrimary;
class CollectionItem extends Model
{
use HasSnowflakePrimary;
use HasSnowflakePrimary;
public $fillable = [
'collection_id',
'object_type',
'object_id',
'order'
'order',
];
/**
* Indicates if the IDs are auto-incrementing.
*
* @var bool
*/
public $incrementing = false;
public function collection()
{
return $this->belongsTo(Collection::class);
}
public function collection()
{
return $this->belongsTo(Collection::class);
}
}

View File

@ -2,11 +2,11 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\AccountService;
use App\Services\Account\AccountStatService;
use App\Status;
use App\Profile;
use App\Services\Account\AccountStatService;
use App\Services\AccountService;
use App\Status;
use Illuminate\Console\Command;
class AccountPostCountStatUpdate extends Command
{
@ -30,20 +30,22 @@ class AccountPostCountStatUpdate extends Command
public function handle()
{
$ids = AccountStatService::getAllPostCountIncr();
if(!$ids || !count($ids)) {
if (! $ids || ! count($ids)) {
return;
}
foreach($ids as $id) {
foreach ($ids as $id) {
$acct = AccountService::get($id, true);
if(!$acct) {
if (! $acct) {
AccountStatService::removeFromPostCount($id);
continue;
}
$statusCount = Status::whereProfileId($id)->count();
if($statusCount != $acct['statuses_count']) {
if ($statusCount != $acct['statuses_count']) {
$profile = Profile::find($id);
if(!$profile) {
if (! $profile) {
AccountStatService::removeFromPostCount($id);
continue;
}
$profile->status_count = $statusCount;
@ -52,6 +54,6 @@ class AccountPostCountStatUpdate extends Command
}
AccountStatService::removeFromPostCount($id);
}
return;
}
}

View File

@ -2,13 +2,14 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use App\Models\DefaultDomainBlock;
use App\Models\UserDomainBlock;
use function Laravel\Prompts\text;
use App\User;
use Illuminate\Console\Command;
use function Laravel\Prompts\confirm;
use function Laravel\Prompts\progress;
use function Laravel\Prompts\text;
class AddUserDomainBlock extends Command
{
@ -34,42 +35,44 @@ class AddUserDomainBlock extends Command
$domain = text('Enter domain you want to block');
$domain = strtolower($domain);
$domain = $this->validateDomain($domain);
if(!$domain || empty($domain)) {
if (! $domain || empty($domain)) {
$this->error('Invalid domain');
return;
}
$this->processBlocks($domain);
return;
}
protected function validateDomain($domain)
{
if(!strpos($domain, '.')) {
if (! strpos($domain, '.')) {
return;
}
if(str_starts_with($domain, 'https://')) {
if (str_starts_with($domain, 'https://')) {
$domain = str_replace('https://', '', $domain);
}
if(str_starts_with($domain, 'http://')) {
if (str_starts_with($domain, 'http://')) {
$domain = str_replace('http://', '', $domain);
}
$domain = strtolower(parse_url('https://' . $domain, PHP_URL_HOST));
$domain = strtolower(parse_url('https://'.$domain, PHP_URL_HOST));
$valid = filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME|FILTER_NULL_ON_FAILURE);
if(!$valid) {
$valid = filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME | FILTER_NULL_ON_FAILURE);
if (! $valid) {
return;
}
if($domain === config('pixelfed.domain.app')) {
if ($domain === config('pixelfed.domain.app')) {
$this->error('Invalid domain');
return;
}
$confirmed = confirm('Are you sure you want to block ' . $domain . '?');
if(!$confirmed) {
$confirmed = confirm('Are you sure you want to block '.$domain.'?');
if (! $confirmed) {
return;
}
@ -79,7 +82,7 @@ class AddUserDomainBlock extends Command
protected function processBlocks($domain)
{
DefaultDomainBlock::updateOrCreate([
'domain' => $domain
'domain' => $domain,
]);
progress(
label: 'Updating user domain blocks...',
@ -90,17 +93,17 @@ class AddUserDomainBlock extends Command
protected function performTask($user, $domain)
{
if(!$user->profile_id || $user->delete_after) {
if (! $user->profile_id || $user->delete_after) {
return;
}
if($user->status != null && $user->status != 'disabled') {
if ($user->status != null && $user->status != 'disabled') {
return;
}
UserDomainBlock::updateOrCreate([
'profile_id' => $user->profile_id,
'domain' => $domain
'domain' => $domain,
]);
}
}

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\AdminInvite;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
class AdminInviteCommand extends Command
@ -46,27 +46,27 @@ class AdminInviteCommand extends Command
'Create invite',
'View invites',
'Expire invite',
'Cancel'
'Cancel',
],
3
);
switch($action) {
switch ($action) {
case 'Create invite':
return $this->create();
break;
break;
case 'View invites':
return $this->view();
break;
break;
case 'Expire invite':
return $this->expire();
break;
break;
case 'Cancel':
return;
break;
break;
}
}
@ -91,24 +91,24 @@ class AdminInviteCommand extends Command
[
'No - invite never expires',
'Yes - expire after 24 hours',
'Custom - let me pick an expiry date'
'Custom - let me pick an expiry date',
],
0
);
switch($shouldExpire) {
switch ($shouldExpire) {
case 'No - invite never expires':
$expires = null;
break;
break;
case 'Yes - expire after 24 hours':
$expires = now()->addHours(24);
break;
break;
case 'Custom - let me pick an expiry date':
$this->info('Set custom expiry date in days');
$customExpiry = $this->ask('Custom Expiry', 14);
$expires = now()->addDays($customExpiry);
break;
break;
}
$this->info('Skip email verification for invitees?');
@ -121,7 +121,7 @@ class AdminInviteCommand extends Command
$invite->max_uses = $max_uses;
$invite->skip_email_verification = $skipEmailVerification === 'Yes';
$invite->expires_at = $expires;
$invite->invite_code = Str::uuid() . Str::random(random_int(1,6));
$invite->invite_code = Str::uuid().Str::random(random_int(1, 6));
$invite->save();
$this->info('####################');
@ -129,6 +129,7 @@ class AdminInviteCommand extends Command
$this->line(' ');
$this->info($invite->url());
$this->line(' ');
return Command::SUCCESS;
}
@ -136,18 +137,19 @@ class AdminInviteCommand extends Command
{
$this->info('View Invites');
$this->line('=============');
if(AdminInvite::count() == 0) {
if (AdminInvite::count() == 0) {
$this->line(' ');
$this->error('No invites found!');
return;
}
$this->table(
['Invite Code', 'Uses Left', 'Expires'],
AdminInvite::all(['invite_code', 'max_uses', 'uses', 'expires_at'])->map(function($invite) {
AdminInvite::all(['invite_code', 'max_uses', 'uses', 'expires_at'])->map(function ($invite) {
return [
'invite_code' => $invite->invite_code,
'uses_left' => $invite->max_uses ? ($invite->max_uses - $invite->uses) : '∞',
'expires_at' => $invite->expires_at ? $invite->expires_at->diffForHumans() : 'never'
'expires_at' => $invite->expires_at ? $invite->expires_at->diffForHumans() : 'never',
];
})->toArray()
);
@ -155,25 +157,28 @@ class AdminInviteCommand extends Command
protected function expire()
{
$token = $this->anticipate('Enter invite code to expire', function($val) {
if(!$val || empty($val)) {
$token = $this->anticipate('Enter invite code to expire', function ($val) {
if (! $val || empty($val)) {
return [];
}
return AdminInvite::where('invite_code', 'like', '%' . $val . '%')->pluck('invite_code')->toArray();
return AdminInvite::where('invite_code', 'like', '%'.$val.'%')->pluck('invite_code')->toArray();
});
if(!$token || empty($token)) {
if (! $token || empty($token)) {
$this->error('Invalid invite code');
return;
}
$invite = AdminInvite::whereInviteCode($token)->first();
if(!$invite) {
if (! $invite) {
$this->error('Invalid invite code');
return;
}
$invite->max_uses = 1;
$invite->expires_at = now()->subHours(2);
$invite->save();
$this->info('Expired the following invite: ' . $invite->url());
$this->info('Expired the following invite: '.$invite->url());
}
}

View File

@ -2,9 +2,10 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Avatar;
use Cache, DB;
use Cache;
use DB;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
class AvatarDefaultMigration extends Command
@ -43,7 +44,7 @@ class AvatarDefaultMigration extends Command
$this->info('Running avatar migration...');
$count = Avatar::whereChangeCount(0)->count();
if($count == 0) {
if ($count == 0) {
$this->info('Found no avatars needing to be migrated!');
exit;
}
@ -51,29 +52,29 @@ class AvatarDefaultMigration extends Command
$bar = $this->output->createProgressBar($count);
$this->info("Found {$count} avatars that may need to be migrated");
Avatar::whereChangeCount(0)->chunk(50, function($avatars) use ($bar) {
foreach($avatars as $avatar) {
if( $avatar->media_path == 'public/avatars/default.png' ||
Avatar::whereChangeCount(0)->chunk(50, function ($avatars) use ($bar) {
foreach ($avatars as $avatar) {
if ($avatar->media_path == 'public/avatars/default.png' ||
$avatar->thumb_path == 'public/avatars/default.png' ||
$avatar->media_path == 'public/avatars/default.jpg' ||
$avatar->media_path == 'public/avatars/default.jpg' ||
$avatar->thumb_path == 'public/avatars/default.jpg'
) {
continue;
}
if(Str::endsWith($avatar->media_path, '/avatar.svg') == false) {
if (Str::endsWith($avatar->media_path, '/avatar.svg') == false) {
// do not modify non-default avatars
continue;
}
DB::transaction(function() use ($avatar, $bar) {
if(is_file(storage_path('app/' . $avatar->media_path))) {
@unlink(storage_path('app/' . $avatar->media_path));
DB::transaction(function () use ($avatar, $bar) {
if (is_file(storage_path('app/'.$avatar->media_path))) {
@unlink(storage_path('app/'.$avatar->media_path));
}
if(is_file(storage_path('app/' . $avatar->thumb_path))) {
@unlink(storage_path('app/' . $avatar->thumb_path));
if (is_file(storage_path('app/'.$avatar->thumb_path))) {
@unlink(storage_path('app/'.$avatar->thumb_path));
}
$avatar->media_path = 'public/avatars/default.jpg';
@ -81,7 +82,7 @@ class AvatarDefaultMigration extends Command
$avatar->change_count = $avatar->change_count + 1;
$avatar->save();
Cache::forget('avatar:' . $avatar->profile_id);
Cache::forget('avatar:'.$avatar->profile_id);
$bar->advance();
});
}

View File

@ -2,16 +2,15 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Avatar;
use App\Jobs\AvatarPipeline\RemoteAvatarFetch;
use App\Profile;
use App\User;
use Cache;
use Storage;
use App\Services\AccountService;
use App\Util\Lexer\PrettyNumber;
use Cache;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
use App\Jobs\AvatarPipeline\RemoteAvatarFetch;
use Storage;
class AvatarStorage extends Command
{
@ -30,8 +29,11 @@ class AvatarStorage extends Command
protected $description = 'Manage avatar storage';
public $found = 0;
public $notFetched = 0;
public $fixed = 0;
public $missing = 0;
/**
@ -47,32 +49,32 @@ class AvatarStorage extends Command
[
'Local',
Avatar::whereNull('is_remote')->count(),
PrettyNumber::size(Avatar::whereNull('is_remote')->sum('size'))
PrettyNumber::size(Avatar::whereNull('is_remote')->sum('size')),
],
[
'Remote',
Avatar::whereIsRemote(true)->count(),
PrettyNumber::size(Avatar::whereIsRemote(true)->sum('size'))
PrettyNumber::size(Avatar::whereIsRemote(true)->sum('size')),
],
[
'Cached (CDN)',
Avatar::whereNotNull('cdn_url')->count(),
PrettyNumber::size(Avatar::whereNotNull('cdn_url')->sum('size'))
PrettyNumber::size(Avatar::whereNotNull('cdn_url')->sum('size')),
],
[
'Uncached',
Avatar::whereNull('cdn_url')->count(),
PrettyNumber::size(Avatar::whereNull('cdn_url')->sum('size'))
PrettyNumber::size(Avatar::whereNull('cdn_url')->sum('size')),
],
[
'------------',
'----------',
'-----'
'-----',
],
[
'Total',
Avatar::count(),
PrettyNumber::size(Avatar::sum('size'))
PrettyNumber::size(Avatar::sum('size')),
],
];
$this->table(
@ -82,21 +84,21 @@ class AvatarStorage extends Command
$this->line(' ');
if(config_cache('pixelfed.cloud_storage')) {
if (config_cache('pixelfed.cloud_storage')) {
$this->info('✅ - Cloud storage configured');
$this->line(' ');
}
if(config('instance.avatar.local_to_cloud')) {
if (config('instance.avatar.local_to_cloud')) {
$this->info('✅ - Store avatars on cloud filesystem');
$this->line(' ');
}
if(config_cache('pixelfed.cloud_storage') && config('instance.avatar.local_to_cloud')) {
if (config_cache('pixelfed.cloud_storage') && config('instance.avatar.local_to_cloud')) {
$disk = Storage::disk(config_cache('filesystems.cloud'));
$exists = $disk->exists('cache/avatars/default.jpg');
$state = $exists ? '✅' : '❌';
$msg = $state . ' - Cloud default avatar exists';
$msg = $state.' - Cloud default avatar exists';
$this->info($msg);
}
@ -105,14 +107,14 @@ class AvatarStorage extends Command
'Cancel',
'Upload default avatar to cloud',
'Move local avatars to cloud',
'Re-fetch remote avatars'
'Re-fetch remote avatars',
] : [
'Cancel',
'Re-fetch remote avatars'
];
'Re-fetch remote avatars',
];
$this->missing = Profile::where('created_at', '<', now()->subDays(1))->doesntHave('avatar')->count();
if($this->missing != 0) {
if ($this->missing != 0) {
$options[] = 'Fix missing avatars';
}
@ -130,7 +132,7 @@ class AvatarStorage extends Command
switch ($id) {
case 'Cancel':
return;
break;
break;
case 'Upload default avatar to cloud':
return $this->uploadDefaultAvatar();
@ -152,7 +154,7 @@ class AvatarStorage extends Command
protected function uploadDefaultAvatar()
{
if(!$this->confirm('Are you sure you want to upload the default avatar to the cloud storage disk?')) {
if (! $this->confirm('Are you sure you want to upload the default avatar to the cloud storage disk?')) {
return;
}
$disk = Storage::disk(config_cache('filesystems.cloud'));
@ -164,35 +166,37 @@ class AvatarStorage extends Command
protected function uploadAvatarsToCloud()
{
if(!config_cache('pixelfed.cloud_storage') || !config('instance.avatar.local_to_cloud')) {
if (! config_cache('pixelfed.cloud_storage') || ! config('instance.avatar.local_to_cloud')) {
$this->error('Enable cloud storage and avatar cloud storage to perform this action');
return;
}
$confirm = $this->confirm('Are you sure you want to move local avatars to cloud storage?');
if(!$confirm) {
if (! $confirm) {
$this->error('Aborted action');
return;
}
$disk = Storage::disk(config_cache('filesystems.cloud'));
if($disk->missing('cache/avatars/default.jpg')) {
if ($disk->missing('cache/avatars/default.jpg')) {
$disk->put('cache/avatars/default.jpg', Storage::get('public/avatars/default.jpg'));
}
Avatar::whereNull('is_remote')->chunk(5, function($avatars) use($disk) {
foreach($avatars as $avatar) {
if($avatar->media_path === 'public/avatars/default.jpg') {
Avatar::whereNull('is_remote')->chunk(5, function ($avatars) use ($disk) {
foreach ($avatars as $avatar) {
if ($avatar->media_path === 'public/avatars/default.jpg') {
$avatar->cdn_url = $disk->url('cache/avatars/default.jpg');
$avatar->save();
} else {
if(!$avatar->media_path || !Str::of($avatar->media_path)->startsWith('public/avatars/')) {
if (! $avatar->media_path || ! Str::of($avatar->media_path)->startsWith('public/avatars/')) {
continue;
}
$ext = pathinfo($avatar->media_path, PATHINFO_EXTENSION);
$newPath = 'cache/avatars/' . $avatar->profile_id . '/avatar_' . strtolower(Str::random(6)) . '.' . $ext;
$newPath = 'cache/avatars/'.$avatar->profile_id.'/avatar_'.strtolower(Str::random(6)).'.'.$ext;
$existing = Storage::disk('local')->get($avatar->media_path);
if(!$existing) {
if (! $existing) {
continue;
}
$newMediaPath = $disk->put($newPath, $existing);
@ -201,20 +205,21 @@ class AvatarStorage extends Command
$avatar->save();
}
Cache::forget('avatar:' . $avatar->profile_id);
Cache::forget(AccountService::CACHE_KEY . $avatar->profile_id);
Cache::forget('avatar:'.$avatar->profile_id);
Cache::forget(AccountService::CACHE_KEY.$avatar->profile_id);
}
});
}
protected function refetchRemoteAvatars()
{
if(!$this->confirm('Are you sure you want to refetch all remote avatars? This could take a while.')) {
if (! $this->confirm('Are you sure you want to refetch all remote avatars? This could take a while.')) {
return;
}
if(config_cache('pixelfed.cloud_storage') == false && config_cache('federation.avatars.store_local') == false) {
if (config_cache('pixelfed.cloud_storage') == false && config_cache('federation.avatars.store_local') == false) {
$this->error('You have cloud storage disabled and local avatar storage disabled, we cannot refetch avatars.');
return;
}
@ -223,22 +228,22 @@ class AvatarStorage extends Command
->whereNull('user_id')
->count();
$this->info('Found ' . $count . ' remote avatars to re-fetch');
$this->info('Found '.$count.' remote avatars to re-fetch');
$this->line(' ');
$bar = $this->output->createProgressBar($count);
Profile::has('avatar')
->with('avatar')
->whereNull('user_id')
->chunk(50, function($profiles) use($bar) {
foreach($profiles as $profile) {
$avatar = $profile->avatar;
$avatar->last_fetched_at = null;
$avatar->save();
RemoteAvatarFetch::dispatch($profile)->onQueue('low');
$bar->advance();
}
});
->chunk(50, function ($profiles) use ($bar) {
foreach ($profiles as $profile) {
$avatar = $profile->avatar;
$avatar->last_fetched_at = null;
$avatar->save();
RemoteAvatarFetch::dispatch($profile)->onQueue('low');
$bar->advance();
}
});
$this->line(' ');
$this->line(' ');
$this->info('Finished dispatching avatar refetch jobs!');
@ -249,45 +254,45 @@ class AvatarStorage extends Command
protected function incr($name)
{
switch($name) {
switch ($name) {
case 'found':
$this->found = $this->found + 1;
break;
break;
case 'notFetched':
$this->notFetched = $this->notFetched + 1;
break;
break;
case 'fixed':
$this->fixed++;
break;
break;
}
}
protected function fixMissingAvatars()
{
if(!$this->confirm('Are you sure you want to fix missing avatars?')) {
if (! $this->confirm('Are you sure you want to fix missing avatars?')) {
return;
}
$this->info('Found ' . $this->missing . ' accounts with missing profiles');
$this->info('Found '.$this->missing.' accounts with missing profiles');
Profile::where('created_at', '<', now()->subDays(1))
->doesntHave('avatar')
->chunk(50, function($profiles) {
foreach($profiles as $profile) {
->chunk(50, function ($profiles) {
foreach ($profiles as $profile) {
Avatar::updateOrCreate([
'profile_id' => $profile->id
'profile_id' => $profile->id,
], [
'media_path' => 'public/avatars/default.jpg',
'is_remote' => $profile->domain == null && $profile->private_key == null
'is_remote' => $profile->domain == null && $profile->private_key == null,
]);
$this->incr('fixed');
}
});
});
$this->line(' ');
$this->line(' ');
$this->info('Fixed ' . $this->fixed . ' accounts with a blank avatar');
$this->info('Fixed '.$this->fixed.' accounts with a blank avatar');
}
}

View File

@ -2,11 +2,11 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Cache;
use Storage;
use App\Avatar;
use App\Jobs\AvatarPipeline\AvatarStorageCleanup;
use Cache;
use Illuminate\Console\Command;
use Storage;
class AvatarStorageDeepClean extends Command
{
@ -25,6 +25,7 @@ class AvatarStorageDeepClean extends Command
protected $description = 'Cleanup avatar storage';
protected $shouldKeepRunning = true;
protected $counter = 0;
/**
@ -45,30 +46,30 @@ class AvatarStorageDeepClean extends Command
$storage = [
'cloud' => boolval(config_cache('pixelfed.cloud_storage')),
'local' => boolval(config_cache('federation.avatars.store_local'))
'local' => boolval(config_cache('federation.avatars.store_local')),
];
if(!$storage['cloud'] && !$storage['local']) {
if (! $storage['cloud'] && ! $storage['local']) {
$this->error('Remote avatars are not cached locally, there is nothing to purge. Aborting...');
exit;
}
$start = 0;
if(!$this->confirm('Are you sure you want to proceed?')) {
if (! $this->confirm('Are you sure you want to proceed?')) {
$this->error('Aborting...');
exit;
}
if(!$this->activeCheck()) {
if (! $this->activeCheck()) {
$this->info('Found existing deep cleaning job');
if(!$this->confirm('Do you want to continue where you left off?')) {
if (! $this->confirm('Do you want to continue where you left off?')) {
$this->error('Aborting...');
exit;
} else {
$start = Cache::has('cmd:asdp') ? (int) Cache::get('cmd:asdp') : (int) Storage::get('avatar-deep-clean.json');
if($start && $start < 1 || $start > PHP_INT_MAX) {
if ($start && $start < 1 || $start > PHP_INT_MAX) {
$this->error('Error fetching cached value');
$this->error('Aborting...');
exit;
@ -79,7 +80,7 @@ class AvatarStorageDeepClean extends Command
$count = Avatar::whereNotNull('cdn_url')->where('is_remote', true)->where('id', '>', $start)->count();
$bar = $this->output->createProgressBar($count);
foreach(Avatar::whereNotNull('cdn_url')->where('is_remote', true)->where('id', '>', $start)->lazyById(10, 'id') as $avatar) {
foreach (Avatar::whereNotNull('cdn_url')->where('is_remote', true)->where('id', '>', $start)->lazyById(10, 'id') as $avatar) {
usleep(random_int(50, 1000));
$this->counter++;
$this->handleAvatar($avatar);
@ -91,14 +92,14 @@ class AvatarStorageDeepClean extends Command
protected function updateCache($id)
{
Cache::put('cmd:asdp', $id);
if($this->counter % 5 === 0) {
if ($this->counter % 5 === 0) {
Storage::put('avatar-deep-clean.json', $id);
}
}
protected function activeCheck()
{
if(Storage::exists('avatar-deep-clean.json') || Cache::has('cmd:asdp')) {
if (Storage::exists('avatar-deep-clean.json') || Cache::has('cmd:asdp')) {
return false;
}

View File

@ -2,198 +2,198 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Avatar;
use App\Profile;
use App\Jobs\AvatarPipeline\RemoteAvatarFetch;
use App\Util\ActivityPub\Helpers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Console\Command;
class AvatarSync extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'avatars:sync';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'avatars:sync';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Perform actions on avatars';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Perform actions on avatars';
public $found = 0;
public $notFetched = 0;
public $fixed = 0;
public $found = 0;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
public $notFetched = 0;
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$this->info('Welcome to the avatar sync manager');
$this->line(' ');
$this->line(' ');
$this->error('This command is deprecated and will be removed in a future version');
$this->error('You should use the following command instead: ');
$this->line(' ');
$this->info('php artisan avatar:storage');
$this->line(' ');
public $fixed = 0;
$confirm = $this->confirm('Are you sure you want to use this deprecated command even though it is no longer supported?');
if(!$confirm) {
return;
}
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
$actions = [
'Analyze',
'Full Analyze',
'Fetch - Fetch missing remote avatars',
'Fix - Fix remote accounts without avatar record',
'Sync - Store latest remote avatars',
];
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$this->info('Welcome to the avatar sync manager');
$this->line(' ');
$this->line(' ');
$this->error('This command is deprecated and will be removed in a future version');
$this->error('You should use the following command instead: ');
$this->line(' ');
$this->info('php artisan avatar:storage');
$this->line(' ');
$name = $this->choice(
'Select an action',
$actions,
0,
1,
false
);
$confirm = $this->confirm('Are you sure you want to use this deprecated command even though it is no longer supported?');
if (! $confirm) {
return;
}
$this->info('Selected: ' . $name);
$actions = [
'Analyze',
'Full Analyze',
'Fetch - Fetch missing remote avatars',
'Fix - Fix remote accounts without avatar record',
'Sync - Store latest remote avatars',
];
switch($name) {
case $actions[0]:
$this->analyze();
break;
$name = $this->choice(
'Select an action',
$actions,
0,
1,
false
);
case $actions[1]:
$this->fullAnalyze();
break;
$this->info('Selected: '.$name);
case $actions[2]:
$this->fetch();
break;
switch ($name) {
case $actions[0]:
$this->analyze();
break;
case $actions[3]:
$this->fix();
break;
case $actions[1]:
$this->fullAnalyze();
break;
case $actions[4]:
$this->sync();
break;
}
return Command::SUCCESS;
}
case $actions[2]:
$this->fetch();
break;
protected function incr($name)
{
switch($name) {
case 'found':
$this->found = $this->found + 1;
break;
case $actions[3]:
$this->fix();
break;
case 'notFetched':
$this->notFetched = $this->notFetched + 1;
break;
case $actions[4]:
$this->sync();
break;
}
case 'fixed':
$this->fixed++;
break;
}
}
return Command::SUCCESS;
}
protected function analyze()
{
$count = Avatar::whereIsRemote(true)->whereNull('cdn_url')->count();
$this->info('Found ' . $count . ' profiles with blank avatars.');
$this->line(' ');
$this->comment('We suggest running php artisan avatars:sync again and selecting the sync option');
$this->line(' ');
}
protected function incr($name)
{
switch ($name) {
case 'found':
$this->found = $this->found + 1;
break;
protected function fullAnalyze()
{
$count = Profile::count();
$bar = $this->output->createProgressBar($count);
$bar->start();
case 'notFetched':
$this->notFetched = $this->notFetched + 1;
break;
Profile::chunk(50, function($profiles) use ($bar) {
foreach($profiles as $profile) {
if($profile->domain == null) {
$bar->advance();
continue;
}
$avatar = Avatar::whereProfileId($profile->id)->first();
if(!$avatar || $avatar->cdn_url == null) {
$this->incr('notFetched');
}
$this->incr('found');
$bar->advance();
}
});
case 'fixed':
$this->fixed++;
break;
}
}
$this->line(' ');
$this->line(' ');
$this->info('Found ' . $this->found . ' remote accounts');
$this->info('Found ' . $this->notFetched . ' remote avatars to fetch');
}
protected function analyze()
{
$count = Avatar::whereIsRemote(true)->whereNull('cdn_url')->count();
$this->info('Found '.$count.' profiles with blank avatars.');
$this->line(' ');
$this->comment('We suggest running php artisan avatars:sync again and selecting the sync option');
$this->line(' ');
}
protected function fetch()
{
$this->error('This action has been deprecated, please run the following command instead:');
$this->line(' ');
$this->info('php artisan avatar:storage');
$this->line(' ');
return;
}
protected function fullAnalyze()
{
$count = Profile::count();
$bar = $this->output->createProgressBar($count);
$bar->start();
protected function fix()
{
Profile::chunk(5000, function($profiles) {
foreach($profiles as $profile) {
if($profile->domain == null || $profile->private_key) {
continue;
}
$avatar = Avatar::whereProfileId($profile->id)->first();
if($avatar) {
continue;
}
$avatar = new Avatar;
$avatar->is_remote = true;
$avatar->profile_id = $profile->id;
$avatar->save();
$this->incr('fixed');
}
});
$this->line(' ');
$this->line(' ');
$this->info('Fixed ' . $this->fixed . ' accounts with a blank avatar');
}
Profile::chunk(50, function ($profiles) use ($bar) {
foreach ($profiles as $profile) {
if ($profile->domain == null) {
$bar->advance();
protected function sync()
{
$this->error('This action has been deprecated, please run the following command instead:');
$this->line(' ');
$this->info('php artisan avatar:storage');
$this->line(' ');
return;
}
continue;
}
$avatar = Avatar::whereProfileId($profile->id)->first();
if (! $avatar || $avatar->cdn_url == null) {
$this->incr('notFetched');
}
$this->incr('found');
$bar->advance();
}
});
$this->line(' ');
$this->line(' ');
$this->info('Found '.$this->found.' remote accounts');
$this->info('Found '.$this->notFetched.' remote avatars to fetch');
}
protected function fetch()
{
$this->error('This action has been deprecated, please run the following command instead:');
$this->line(' ');
$this->info('php artisan avatar:storage');
$this->line(' ');
}
protected function fix()
{
Profile::chunk(5000, function ($profiles) {
foreach ($profiles as $profile) {
if ($profile->domain == null || $profile->private_key) {
continue;
}
$avatar = Avatar::whereProfileId($profile->id)->first();
if ($avatar) {
continue;
}
$avatar = new Avatar;
$avatar->is_remote = true;
$avatar->profile_id = $profile->id;
$avatar->save();
$this->incr('fixed');
}
});
$this->line(' ');
$this->line(' ');
$this->info('Fixed '.$this->fixed.' accounts with a blank avatar');
}
protected function sync()
{
$this->error('This action has been deprecated, please run the following command instead:');
$this->line(' ');
$this->info('php artisan avatar:storage');
$this->line(' ');
}
}

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Http\File;
use Illuminate\Console\Command;
use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;
use Spatie\Backup\BackupDestination\BackupDestination;
@ -40,37 +40,39 @@ class BackupToCloud extends Command
*/
public function handle()
{
$localDisk = Storage::disk('local');
$cloudDisk = Storage::disk('backup');
$backupDestination = new BackupDestination($localDisk, '', 'local');
$localDisk = Storage::disk('local');
$cloudDisk = Storage::disk('backup');
$backupDestination = new BackupDestination($localDisk, '', 'local');
if(
empty(config('filesystems.disks.backup.key')) ||
empty(config('filesystems.disks.backup.secret')) ||
empty(config('filesystems.disks.backup.endpoint')) ||
empty(config('filesystems.disks.backup.region')) ||
empty(config('filesystems.disks.backup.bucket'))
) {
$this->error('Backup disk not configured.');
$this->error('See https://docs.pixelfed.org/technical-documentation/env.html#filesystem for more information.');
return Command::FAILURE;
}
if (
empty(config('filesystems.disks.backup.key')) ||
empty(config('filesystems.disks.backup.secret')) ||
empty(config('filesystems.disks.backup.endpoint')) ||
empty(config('filesystems.disks.backup.region')) ||
empty(config('filesystems.disks.backup.bucket'))
) {
$this->error('Backup disk not configured.');
$this->error('See https://docs.pixelfed.org/technical-documentation/env.html#filesystem for more information.');
$newest = $backupDestination->newestBackup();
$name = $newest->path();
$parts = explode('/', $name);
$fileName = array_pop($parts);
$storagePath = 'backups';
$path = storage_path('app/'. $name);
$file = $cloudDisk->putFileAs($storagePath, new File($path), $fileName, 'private');
$this->info("Backup file successfully saved!");
$url = $cloudDisk->url($file);
$this->table(
['Name', 'URL'],
[
[$fileName, $url]
],
);
return Command::SUCCESS;
return Command::FAILURE;
}
$newest = $backupDestination->newestBackup();
$name = $newest->path();
$parts = explode('/', $name);
$fileName = array_pop($parts);
$storagePath = 'backups';
$path = storage_path('app/'.$name);
$file = $cloudDisk->putFileAs($storagePath, new File($path), $fileName, 'private');
$this->info('Backup file successfully saved!');
$url = $cloudDisk->url($file);
$this->table(
['Name', 'URL'],
[
[$fileName, $url],
],
);
return Command::SUCCESS;
}
}

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use App\Services\EmailService;
use App\User;
use Illuminate\Console\Command;
class BannedEmailCheck extends Command
{
@ -39,12 +39,12 @@ class BannedEmailCheck extends Command
*/
public function handle()
{
$users = User::whereNull('status')->get()->filter(function($u) {
$users = User::whereNull('status')->get()->filter(function ($u) {
return EmailService::isBanned($u->email) == true;
});
foreach($users as $user) {
$this->info('Found banned domain: ' . $user->email . PHP_EOL);
foreach ($users as $user) {
$this->info('Found banned domain: '.$user->email.PHP_EOL);
}
}
}

View File

@ -2,7 +2,6 @@
namespace App\Console\Commands;
use DB;
use App\Jobs\ImageOptimizePipeline\ImageOptimize;
use App\Media;
use Illuminate\Console\Command;
@ -50,7 +49,7 @@ class CatchUnoptimizedMedia extends Command
'image/jpeg',
'image/png',
])
->chunk(50, function($medias) {
->chunk(50, function ($medias) {
foreach ($medias as $media) {
ImageOptimize::dispatch($media);
}

View File

@ -2,10 +2,10 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Media;
use App\Services\MediaStorageService;
use App\Util\Lexer\PrettyNumber;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@ -36,16 +36,18 @@ class CloudMediaMigrate extends Command
public function handle()
{
$enabled = config('pixelfed.cloud_storage');
if(!$enabled) {
if (! $enabled) {
$this->error('Cloud storage not enabled. Exiting...');
return;
}
$limit = $this->option('limit');
$hugeMode = $this->option('huge');
if($limit > 500 && !$hugeMode) {
if ($limit > 500 && ! $hugeMode) {
$this->error('Max limit exceeded, use a limit lower than 500 or run again with the --huge flag');
return;
}
@ -60,19 +62,22 @@ class CloudMediaMigrate extends Command
->orderByDesc('size')
->take($limit)
->get()
->each(function($media) use($bar) {
if(Storage::disk('local')->exists($media->media_path)) {
->each(function ($media) use ($bar) {
if (Storage::disk('local')->exists($media->media_path)) {
$this->totalSize = $this->totalSize + $media->size;
try {
MediaStorageService::store($media);
} catch (FileNotFoundException $e) {
$this->error('Error migrating media ' . $media->id . ' to cloud storage: ' . $e->getMessage());
$this->error('Error migrating media '.$media->id.' to cloud storage: '.$e->getMessage());
return;
} catch (NotFoundHttpException $e) {
$this->error('Error migrating media ' . $media->id . ' to cloud storage: ' . $e->getMessage());
$this->error('Error migrating media '.$media->id.' to cloud storage: '.$e->getMessage());
return;
} catch (\Exception $e) {
$this->error('Error migrating media ' . $media->id . ' to cloud storage: ' . $e->getMessage());
$this->error('Error migrating media '.$media->id.' to cloud storage: '.$e->getMessage());
return;
}
}
@ -82,11 +87,12 @@ class CloudMediaMigrate extends Command
$bar->finish();
$this->line(' ');
$this->info('Finished!');
if($this->totalSize) {
$this->info('Uploaded ' . PrettyNumber::size($this->totalSize) . ' of media to cloud storage!');
if ($this->totalSize) {
$this->info('Uploaded '.PrettyNumber::size($this->totalSize).' of media to cloud storage!');
$this->line(' ');
$this->info('These files are still stored locally, and will be automatically removed.');
}
return Command::SUCCESS;
}
}

View File

@ -38,18 +38,18 @@ class DatabaseSessionGarbageCollector extends Command
*/
public function handle()
{
if(config('session.driver') !== 'database') {
return Command::SUCCESS;
}
if (config('session.driver') !== 'database') {
return Command::SUCCESS;
}
DB::transaction(function() {
DB::table('sessions')->whereNull('user_id')->delete();
});
DB::transaction(function () {
DB::table('sessions')->whereNull('user_id')->delete();
});
DB::transaction(function() {
$ts = now()->subMonths(3)->timestamp;
DB::table('sessions')->where('last_activity', '<', $ts)->delete();
});
DB::transaction(function () {
$ts = now()->subMonths(3)->timestamp;
DB::table('sessions')->where('last_activity', '<', $ts)->delete();
});
return Command::SUCCESS;
}

View File

@ -2,13 +2,13 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use App\Models\DefaultDomainBlock;
use App\Models\UserDomainBlock;
use function Laravel\Prompts\text;
use Illuminate\Console\Command;
use function Laravel\Prompts\confirm;
use function Laravel\Prompts\progress;
use function Laravel\Prompts\text;
class DeleteUserDomainBlock extends Command
{
@ -34,41 +34,42 @@ class DeleteUserDomainBlock extends Command
$domain = text('Enter domain you want to unblock');
$domain = strtolower($domain);
$domain = $this->validateDomain($domain);
if(!$domain || empty($domain)) {
if (! $domain || empty($domain)) {
$this->error('Invalid domain');
return;
}
$this->processUnblocks($domain);
return;
}
protected function validateDomain($domain)
{
if(!strpos($domain, '.')) {
if (! strpos($domain, '.')) {
return;
}
if(str_starts_with($domain, 'https://')) {
if (str_starts_with($domain, 'https://')) {
$domain = str_replace('https://', '', $domain);
}
if(str_starts_with($domain, 'http://')) {
if (str_starts_with($domain, 'http://')) {
$domain = str_replace('http://', '', $domain);
}
$domain = strtolower(parse_url('https://' . $domain, PHP_URL_HOST));
$domain = strtolower(parse_url('https://'.$domain, PHP_URL_HOST));
$valid = filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME|FILTER_NULL_ON_FAILURE);
if(!$valid) {
$valid = filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME | FILTER_NULL_ON_FAILURE);
if (! $valid) {
return;
}
if($domain === config('pixelfed.domain.app')) {
if ($domain === config('pixelfed.domain.app')) {
return;
}
$confirmed = confirm('Are you sure you want to unblock ' . $domain . '?');
if(!$confirmed) {
$confirmed = confirm('Are you sure you want to unblock '.$domain.'?');
if (! $confirmed) {
return;
}
@ -78,8 +79,9 @@ class DeleteUserDomainBlock extends Command
protected function processUnblocks($domain)
{
DefaultDomainBlock::whereDomain($domain)->delete();
if(!UserDomainBlock::whereDomain($domain)->count()) {
if (! UserDomainBlock::whereDomain($domain)->count()) {
$this->info('No results found!');
return;
}
progress(

View File

@ -27,7 +27,7 @@ class ExportLanguages extends Command
*/
public function __construct()
{
parent::__construct();
parent::__construct();
}
/**
@ -37,38 +37,39 @@ class ExportLanguages extends Command
*/
public function handle()
{
if(config('app.env') !== 'local') {
$this->error('This command is meant for development purposes and should only be run in a local environment');
return Command::FAILURE;
}
if (config('app.env') !== 'local') {
$this->error('This command is meant for development purposes and should only be run in a local environment');
$path = base_path('resources/lang');
$langs = [];
return Command::FAILURE;
}
foreach (new \DirectoryIterator($path) as $io) {
$name = $io->getFilename();
$skip = ['vendor'];
if($io->isDot() || in_array($name, $skip)) {
continue;
}
$path = base_path('resources/lang');
$langs = [];
if($io->isDir()) {
array_push($langs, $name);
}
}
foreach (new \DirectoryIterator($path) as $io) {
$name = $io->getFilename();
$skip = ['vendor'];
if ($io->isDot() || in_array($name, $skip)) {
continue;
}
$exportDir = resource_path('assets/js/i18n/');
$exportDirAlt = public_path('_lang/');
if ($io->isDir()) {
array_push($langs, $name);
}
}
foreach($langs as $lang) {
$strings = \Lang::get('web', [], $lang);
$json = json_encode($strings, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
$path = "{$exportDir}{$lang}.json";
file_put_contents($path, $json);
$pathAlt = "{$exportDirAlt}{$lang}.json";
file_put_contents($pathAlt, $json);
}
$exportDir = resource_path('assets/js/i18n/');
$exportDirAlt = public_path('_lang/');
return Command::SUCCESS;
foreach ($langs as $lang) {
$strings = \Lang::get('web', [], $lang);
$json = json_encode($strings, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
$path = "{$exportDir}{$lang}.json";
file_put_contents($path, $json);
$pathAlt = "{$exportDirAlt}{$lang}.json";
file_put_contents($pathAlt, $json);
}
return Command::SUCCESS;
}
}

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\FailedJob;
use Illuminate\Console\Command;
class FailedJobGC extends Command
{
@ -38,9 +38,9 @@ class FailedJobGC extends Command
*/
public function handle()
{
FailedJob::chunk(50, function($jobs) {
foreach($jobs as $job) {
if($job->failed_at->lt(now()->subHours(48))) {
FailedJob::chunk(50, function ($jobs) {
foreach ($jobs as $job) {
if ($job->failed_at->lt(now()->subHours(48))) {
$job->delete();
}
}

View File

@ -2,11 +2,11 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Media;
use Illuminate\Support\Facades\Http;
use App\Services\MediaService;
use App\Services\StatusService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class FetchMissingMediaMimeType extends Command
{
@ -29,20 +29,20 @@ class FetchMissingMediaMimeType extends Command
*/
public function handle()
{
foreach(Media::whereNotNull(['remote_url', 'status_id'])->whereNull('mime')->lazyByIdDesc(50, 'id') as $media) {
foreach (Media::whereNotNull(['remote_url', 'status_id'])->whereNull('mime')->lazyByIdDesc(50, 'id') as $media) {
$res = Http::retry(2, 100, throw: false)->head($media->remote_url);
if(!$res->successful()) {
if (! $res->successful()) {
continue;
}
if(!in_array($res->header('content-type'), explode(',',config('pixelfed.media_types')))) {
if (! in_array($res->header('content-type'), explode(',', config('pixelfed.media_types')))) {
continue;
}
$media->mime = $res->header('content-type');
if($res->hasHeader('content-length')) {
if ($res->hasHeader('content-length')) {
$media->size = $res->header('content-length');
}
@ -50,7 +50,7 @@ class FetchMissingMediaMimeType extends Command
MediaService::del($media->status_id);
StatusService::del($media->status_id);
$this->info('mid:'.$media->id . ' (' . $res->header('content-type') . ':' . $res->header('content-length') . ' bytes)');
$this->info('mid:'.$media->id.' ('.$res->header('content-type').':'.$res->header('content-length').' bytes)');
}
}
}

View File

@ -2,40 +2,36 @@
namespace App\Console\Commands;
use App\Avatar;
use App\Bookmark;
use App\Collection;
use App\DirectMessage;
use App\Follower;
use App\FollowRequest;
use App\HashtagFollow;
use App\Like;
use App\Media;
use App\MediaTag;
use App\Mention;
use App\Models\Conversation;
use App\Models\Portfolio;
use App\Models\UserPronoun;
use App\Profile;
use App\Report;
use App\ReportComment;
use App\ReportLog;
use App\Status;
use App\StatusArchived;
use App\StatusHashtag;
use App\StatusView;
use App\Story;
use App\StoryView;
use App\User;
use App\UserFilter;
use Cache;
use DB;
use Illuminate\Console\Command;
use App\{
Avatar,
Bookmark,
Collection,
DirectMessage,
FollowRequest,
Follower,
HashtagFollow,
Like,
Media,
MediaTag,
Mention,
Profile,
Report,
ReportComment,
ReportLog,
StatusArchived,
StatusHashtag,
StatusView,
Status,
Story,
StoryView,
User,
UserFilter
};
use App\Models\{
Conversation,
Portfolio,
UserPronoun
};
use DB, Cache;
class FixDuplicateProfiles extends Command
{
/**
@ -76,16 +72,16 @@ class FixDuplicateProfiles extends Command
->havingRaw('COUNT(*) > 1')
->pluck('username');
foreach($duplicates as $dupe) {
foreach ($duplicates as $dupe) {
$ids = Profile::whereNull('domain')->whereUsername($dupe)->pluck('id');
if(!$ids || $ids->count() != 2) {
if (! $ids || $ids->count() != 2) {
continue;
}
$id = $ids->first();
$oid = $ids->last();
$user = User::whereUsername($dupe)->first();
if($user) {
if ($user) {
$user->profile_id = $id;
$user->save();
} else {
@ -156,17 +152,17 @@ class FixDuplicateProfiles extends Command
protected function checkFollowers($id, $oid)
{
$f = Follower::whereProfileId($oid)->pluck('following_id');
foreach($f as $fo) {
foreach ($f as $fo) {
Follower::updateOrCreate([
'profile_id' => $id,
'following_id' => $fo
'following_id' => $fo,
]);
}
$f = Follower::whereFollowingId($oid)->pluck('profile_id');
foreach($f as $fo) {
foreach ($f as $fo) {
Follower::updateOrCreate([
'profile_id' => $fo,
'following_id' => $id
'following_id' => $id,
]);
}
}
@ -250,5 +246,4 @@ class FixDuplicateProfiles extends Command
{
UserPronoun::whereProfileId($oid)->update(['profile_id' => $id]);
}
}

View File

@ -2,13 +2,8 @@
namespace App\Console\Commands;
use App\StatusHashtag;
use Illuminate\Console\Command;
use DB;
use App\{
Hashtag,
Status,
StatusHashtag
};
class FixHashtags extends Command
{
@ -51,18 +46,18 @@ class FixHashtags extends Command
$this->info(' /_/ /_/_/|_|\___/_/_/ \___/\__,_/ ');
$this->info(' ');
$this->info(' ');
$this->info('Pixelfed version: ' . config('pixelfed.version'));
$this->info('Pixelfed version: '.config('pixelfed.version'));
$this->info(' ');
$this->info('Running Fix Hashtags command');
$this->info(' ');
$missingCount = StatusHashtag::doesntHave('profile')->doesntHave('status')->count();
if($missingCount > 0) {
if ($missingCount > 0) {
$this->info("Found {$missingCount} orphaned StatusHashtag records to delete ...");
$this->info(' ');
$bar = $this->output->createProgressBar($missingCount);
$bar->start();
foreach(StatusHashtag::doesntHave('profile')->doesntHave('status')->get() as $tag) {
foreach (StatusHashtag::doesntHave('profile')->doesntHave('status')->get() as $tag) {
$tag->delete();
$bar->advance();
}
@ -72,17 +67,17 @@ class FixHashtags extends Command
$this->info(' ');
$this->info('Found no orphaned hashtags to delete!');
}
$this->info(' ');
$count = StatusHashtag::whereNull('status_visibility')->count();
if($count > 0) {
if ($count > 0) {
$this->info("Found {$count} hashtags to fix ...");
$this->info(' ');
} else {
$this->info('Found no hashtags to fix!');
$this->info(' ');
return;
}
@ -90,17 +85,17 @@ class FixHashtags extends Command
$bar->start();
StatusHashtag::with('status')
->whereNull('status_visibility')
->chunk(50, function($tags) use($bar) {
foreach($tags as $tag) {
if(!$tag->status || !$tag->status->scope) {
continue;
->whereNull('status_visibility')
->chunk(50, function ($tags) use ($bar) {
foreach ($tags as $tag) {
if (! $tag->status || ! $tag->status->scope) {
continue;
}
$tag->status_visibility = $tag->status->scope;
$tag->save();
$bar->advance();
}
$tag->status_visibility = $tag->status->scope;
$tag->save();
$bar->advance();
}
});
});
$bar->finish();
$this->info(' ');

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use App\Like;
use App\Status;
use Illuminate\Console\Command;
use App\{Like, Status};
use DB;
class FixLikes extends Command
{
@ -41,10 +41,11 @@ class FixLikes extends Command
{
$chunk = 100;
$limit = Like::select('status_id')->groupBy('status_id')->get()->count();
if($limit > 1000) {
if($this->confirm('We have found more than 1000 records to update, this may take a few moments. Are you sure you want to continue?') == false) {
if ($limit > 1000) {
if ($this->confirm('We have found more than 1000 records to update, this may take a few moments. Are you sure you want to continue?') == false) {
$this->error('Cancelling command...');
return;
}
}
@ -56,11 +57,11 @@ class FixLikes extends Command
$bar->start();
Like::selectRaw('count(id) as count, status_id')
->groupBy(['status_id','id'])
->chunk($chunk, function($likes) use($bar) {
foreach($likes as $like) {
->groupBy(['status_id', 'id'])
->chunk($chunk, function ($likes) use ($bar) {
foreach ($likes as $like) {
$s = Status::find($like['status_id']);
if($s && $s->likes_count == 0) {
if ($s && $s->likes_count == 0) {
$s->likes_count = $like['count'];
$s->save();
}

View File

@ -2,132 +2,136 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use App\Media;
use League\Flysystem\MountManager;
use App\Jobs\ImageOptimizePipeline\ImageOptimize;
use App\Jobs\MediaPipeline\MediaFixLocalFilesystemCleanupPipeline;
use App\Media;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\MountManager;
class FixMediaDriver extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'media:fix-nonlocal-driver';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'media:fix-nonlocal-driver';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Fix filesystem when FILESYSTEM_DRIVER not set to local';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Fix filesystem when FILESYSTEM_DRIVER not set to local';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
if(config('filesystems.default') !== 'local') {
$this->error('Invalid default filesystem, set FILESYSTEM_DRIVER=local to proceed');
return Command::SUCCESS;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
if (config('filesystems.default') !== 'local') {
$this->error('Invalid default filesystem, set FILESYSTEM_DRIVER=local to proceed');
if(config_cache('pixelfed.cloud_storage') == false) {
$this->error('Cloud storage not enabled, exiting...');
return Command::SUCCESS;
}
return Command::SUCCESS;
}
$this->info(' ____ _ ______ __ ');
$this->info(' / __ \(_) _____ / / __/__ ____/ / ');
$this->info(' / /_/ / / |/_/ _ \/ / /_/ _ \/ __ / ');
$this->info(' / ____/ /> </ __/ / __/ __/ /_/ / ');
$this->info(' /_/ /_/_/|_|\___/_/_/ \___/\__,_/ ');
$this->info(' ');
$this->info(' Media Filesystem Fix');
$this->info(' =====================');
$this->info(' Fix media that was created when FILESYSTEM_DRIVER=local');
$this->info(' was not properly set. This command will fix media urls');
$this->info(' and optionally optimize/generate thumbnails when applicable,');
$this->info(' clean up temporary local media files and clear the app cache');
$this->info(' to fix media paths/urls.');
$this->info(' ');
$this->error(' Remember, FILESYSTEM_DRIVER=local must remain set or you will break things!');
if (config_cache('pixelfed.cloud_storage') == false) {
$this->error('Cloud storage not enabled, exiting...');
if(!$this->confirm('Are you sure you want to perform this command?')) {
$this->info('Exiting...');
return Command::SUCCESS;
}
return Command::SUCCESS;
}
$optimize = $this->choice(
'Do you want to optimize media and generate thumbnails? This will store s3 locally and re-upload optimized versions.',
['no', 'yes'],
1
);
$this->info(' ____ _ ______ __ ');
$this->info(' / __ \(_) _____ / / __/__ ____/ / ');
$this->info(' / /_/ / / |/_/ _ \/ / /_/ _ \/ __ / ');
$this->info(' / ____/ /> </ __/ / __/ __/ /_/ / ');
$this->info(' /_/ /_/_/|_|\___/_/_/ \___/\__,_/ ');
$this->info(' ');
$this->info(' Media Filesystem Fix');
$this->info(' =====================');
$this->info(' Fix media that was created when FILESYSTEM_DRIVER=local');
$this->info(' was not properly set. This command will fix media urls');
$this->info(' and optionally optimize/generate thumbnails when applicable,');
$this->info(' clean up temporary local media files and clear the app cache');
$this->info(' to fix media paths/urls.');
$this->info(' ');
$this->error(' Remember, FILESYSTEM_DRIVER=local must remain set or you will break things!');
$cloud = Storage::disk(config('filesystems.cloud'));
$mountManager = new MountManager([
's3' => $cloud->getDriver(),
'local' => Storage::disk('local')->getDriver(),
]);
if (! $this->confirm('Are you sure you want to perform this command?')) {
$this->info('Exiting...');
$this->info('Fixing media, this may take a while...');
$this->line(' ');
$bar = $this->output->createProgressBar(Media::whereNotNull('status_id')->whereNull('cdn_url')->count());
$bar->start();
return Command::SUCCESS;
}
foreach(Media::whereNotNull('status_id')->whereNull('cdn_url')->lazyById(20) as $media) {
if($cloud->exists($media->media_path)) {
if($optimize === 'yes') {
$mountManager->copy(
's3://' . $media->media_path,
'local://' . $media->media_path
);
sleep(1);
if(empty($media->original_sha256)) {
$hash = \hash_file('sha256', Storage::disk('local')->path($media->media_path));
$media->original_sha256 = $hash;
$media->save();
sleep(1);
}
if(
$media->mime &&
in_array($media->mime, [
'image/jpeg',
'image/png',
'image/webp'
])
) {
ImageOptimize::dispatch($media);
sleep(3);
}
} else {
$media->cdn_url = $cloud->url($media->media_path);
$media->save();
}
}
$bar->advance();
}
$optimize = $this->choice(
'Do you want to optimize media and generate thumbnails? This will store s3 locally and re-upload optimized versions.',
['no', 'yes'],
1
);
$bar->finish();
$this->line(' ');
$this->line(' ');
$cloud = Storage::disk(config('filesystems.cloud'));
$mountManager = new MountManager([
's3' => $cloud->getDriver(),
'local' => Storage::disk('local')->getDriver(),
]);
$this->callSilently('cache:clear');
$this->info('Fixing media, this may take a while...');
$this->line(' ');
$bar = $this->output->createProgressBar(Media::whereNotNull('status_id')->whereNull('cdn_url')->count());
$bar->start();
$this->info('Successfully fixed media paths and cleared cached!');
foreach (Media::whereNotNull('status_id')->whereNull('cdn_url')->lazyById(20) as $media) {
if ($cloud->exists($media->media_path)) {
if ($optimize === 'yes') {
$mountManager->copy(
's3://'.$media->media_path,
'local://'.$media->media_path
);
sleep(1);
if (empty($media->original_sha256)) {
$hash = \hash_file('sha256', Storage::disk('local')->path($media->media_path));
$media->original_sha256 = $hash;
$media->save();
sleep(1);
}
if (
$media->mime &&
in_array($media->mime, [
'image/jpeg',
'image/png',
'image/webp',
])
) {
ImageOptimize::dispatch($media);
sleep(3);
}
} else {
$media->cdn_url = $cloud->url($media->media_path);
$media->save();
}
}
$bar->advance();
}
if($optimize === 'yes') {
MediaFixLocalFilesystemCleanupPipeline::dispatch()->delay(now()->addMinutes(15))->onQueue('default');
$this->line(' ');
$this->info('A cleanup job has been dispatched to delete media stored locally, it may take a few minutes to process!');
}
$bar->finish();
$this->line(' ');
$this->line(' ');
$this->line(' ');
return Command::SUCCESS;
}
$this->callSilently('cache:clear');
$this->info('Successfully fixed media paths and cleared cached!');
if ($optimize === 'yes') {
MediaFixLocalFilesystemCleanupPipeline::dispatch()->delay(now()->addMinutes(15))->onQueue('default');
$this->line(' ');
$this->info('A cleanup job has been dispatched to delete media stored locally, it may take a few minutes to process!');
}
$this->line(' ');
return Command::SUCCESS;
}
}

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Profile;
use App\Status;
use Illuminate\Console\Command;
class FixRemotePostCount extends Command
{
@ -39,8 +39,8 @@ class FixRemotePostCount extends Command
*/
public function handle()
{
Profile::whereNotNull('domain')->chunk(50, function($profiles) {
foreach($profiles as $profile) {
Profile::whereNotNull('domain')->chunk(50, function ($profiles) {
foreach ($profiles as $profile) {
$count = Status::whereNull(['in_reply_to_id', 'reblog_of_id'])->whereProfileId($profile->id)->count();
$this->info("Checking {$profile->id} {$profile->username} - found {$count} statuses");
$profile->status_count = $count;

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Profile;
use App\Services\AccountService;
use Illuminate\Console\Command;
class FixStatusCount extends Command
{
@ -39,7 +39,7 @@ class FixStatusCount extends Command
*/
public function handle()
{
if(!$this->confirm('Are you sure you want to run the fix status command?')) {
if (! $this->confirm('Are you sure you want to run the fix status command?')) {
return;
}
$this->line(' ');
@ -51,7 +51,7 @@ class FixStatusCount extends Command
$resync = $this->option('resync');
$resync24hours = false;
if($resync) {
if ($resync) {
$resyncChoices = ['Only resync accounts that havent been synced in 24 hours', 'Resync all accounts'];
$rsc = $this->choice(
'Do you want to resync all accounts, or just accounts that havent been resynced for 24 hours?',
@ -59,7 +59,7 @@ class FixStatusCount extends Command
0
);
$rsci = array_search($rsc, $resyncChoices);
if($rsci === 0) {
if ($rsci === 0) {
$resync24hours = true;
$nulls = ['status', 'domain', 'last_fetched_at'];
} else {
@ -70,7 +70,7 @@ class FixStatusCount extends Command
$remote = $this->option('remote');
if($remote) {
if ($remote) {
$ni = array_search('domain', $nulls);
unset($nulls[$ni]);
$ni = array_search('last_fetched_at', $nulls);
@ -79,7 +79,7 @@ class FixStatusCount extends Command
$remoteOnly = $this->option('remote-only');
if($remoteOnly) {
if ($remoteOnly) {
$ni = array_search('domain', $nulls);
unset($nulls[$ni]);
$ni = array_search('last_fetched_at', $nulls);
@ -91,9 +91,9 @@ class FixStatusCount extends Command
$nulls = array_values($nulls);
foreach(
Profile::when($resync24hours, function($query, $resync24hours) use($nulls) {
if(in_array('domain', $nulls)) {
foreach (
Profile::when($resync24hours, function ($query, $resync24hours) use ($nulls) {
if (in_array('domain', $nulls)) {
return $query->whereNull('domain')
->whereNull('last_fetched_at')
->orWhere('last_fetched_at', '<', now()->subHours(24));
@ -102,31 +102,31 @@ class FixStatusCount extends Command
->orWhere('last_fetched_at', '<', now()->subHours(24));
}
})
->when($remoteOnly, function($query, $remoteOnly) {
return $query->whereNull('last_fetched_at')
->orWhere('last_fetched_at', '<', now()->subHours(24));
})
->whereNull($nulls)
->lazyById(50, 'id') as $profile
->when($remoteOnly, function ($query, $remoteOnly) {
return $query->whereNull('last_fetched_at')
->orWhere('last_fetched_at', '<', now()->subHours(24));
})
->whereNull($nulls)
->lazyById(50, 'id') as $profile
) {
$ogc = $profile->status_count;
$upc = $profile->statuses()
->getQuery()
->whereIn('scope', ['public', 'private', 'unlisted'])
->count();
if($ogc != $upc) {
->getQuery()
->whereIn('scope', ['public', 'private', 'unlisted'])
->count();
if ($ogc != $upc) {
$profile->status_count = $upc;
$profile->last_fetched_at = $now;
$profile->save();
AccountService::del($profile->id);
if($dlog) {
$this->info($profile->id . ':' . $profile->username . ' : ' . $upc);
if ($dlog) {
$this->info($profile->id.':'.$profile->username.' : '.$upc);
}
} else {
$profile->last_fetched_at = $now;
$profile->save();
if($dlog) {
$this->info($profile->id . ':' . $profile->username . ' : ' . $upc);
if ($dlog) {
$this->info($profile->id.':'.$profile->username.' : '.$upc);
}
}
}

View File

@ -2,10 +2,11 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\{Profile, User};
use DB;
use App\Profile;
use App\User;
use App\Util\Lexer\RestrictedNames;
use DB;
use Illuminate\Console\Command;
class FixUsernames extends Command
{
@ -52,67 +53,67 @@ class FixUsernames extends Command
$restricted = RestrictedNames::get();
$users = User::chunk(100, function($users) use($affected, $restricted) {
foreach($users as $user) {
if($user->is_admin || $user->status == 'deleted') {
$users = User::chunk(100, function ($users) use ($affected, $restricted) {
foreach ($users as $user) {
if ($user->is_admin || $user->status == 'deleted') {
continue;
}
if(in_array(strtolower($user->username), array_map('strtolower', $restricted))) {
if (in_array(strtolower($user->username), array_map('strtolower', $restricted))) {
$affected->push($user);
}
$val = str_replace(['-', '_', '.'], '', $user->username);
if(!ctype_alnum($val)) {
$this->info('Found invalid username: ' . $user->username);
if (! ctype_alnum($val)) {
$this->info('Found invalid username: '.$user->username);
$affected->push($user);
}
}
});
if($affected->count() > 0) {
$this->info('Found: ' . $affected->count() . ' affected usernames');
if ($affected->count() > 0) {
$this->info('Found: '.$affected->count().' affected usernames');
$opts = [
'Random replace (assigns random username)',
'Best try replace (assigns alpha numeric username)',
'Manual replace (manually set username)',
'Skip (do not replace. Use at your own risk)'
'Skip (do not replace. Use at your own risk)',
];
foreach($affected as $u) {
foreach ($affected as $u) {
$old = $u->username;
$this->info("Found user: {$old}");
$opt = $this->choice('Select fix method:', $opts, 3);
switch ($opt) {
case $opts[0]:
$new = "user_" . str_random(6);
$this->info('New username: ' . $new);
$new = 'user_'.str_random(6);
$this->info('New username: '.$new);
break;
case $opts[1]:
$new = filter_var($old, FILTER_SANITIZE_STRING|FILTER_FLAG_STRIP_LOW);
if(strlen($new) < 6) {
$new = $new . '_' . str_random(4);
$new = filter_var($old, FILTER_SANITIZE_STRING | FILTER_FLAG_STRIP_LOW);
if (strlen($new) < 6) {
$new = $new.'_'.str_random(4);
}
$this->info('New username: ' . $new);
$this->info('New username: '.$new);
break;
case $opts[2]:
$new = $this->ask('Enter new username:');
$this->info('New username: ' . $new);
$this->info('New username: '.$new);
break;
case $opts[3]:
$new = false;
break;
default:
$new = "user_" . str_random(6);
$new = 'user_'.str_random(6);
break;
}
if($new) {
DB::transaction(function() use($u, $new) {
if ($new) {
DB::transaction(function () use ($u, $new) {
$profile = $u->profile;
$profile->username = $new;
$u->username = $new;
@ -120,10 +121,10 @@ class FixUsernames extends Command
$profile->save();
});
}
$this->info('Selected: ' . $opt);
$this->info('Selected: '.$opt);
}
$this->info('Fixed ' . $affected->count() . ' usernames!');
$this->info('Fixed '.$affected->count().' usernames!');
} else {
$this->info('No restricted usernames found!');
}
@ -140,23 +141,24 @@ class FixUsernames extends Command
$count = $profiles->count();
if($count > 0) {
if ($count > 0) {
$this->info("Found {$count} remote usernames to fix ...");
$this->line(' ');
} else {
$this->info('No remote fixes found!');
$this->line(' ');
return;
}
foreach($profiles as $p) {
foreach ($profiles as $p) {
$this->info("Fixed $p->username => $p->webfinger");
$p->username = $p->webfinger ?? "@{$p->username}@{$p->domain}";
if(Profile::whereUsername($p->username)->exists()) {
if (Profile::whereUsername($p->username)->exists()) {
return;
}
$p->save();
}
if($count > 0) {
if ($count > 0) {
$this->line(' ');
}

View File

@ -2,72 +2,73 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use App\Models\InstanceActor;
use Cache;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Schema;
class GenerateInstanceActor extends Command
{
protected $signature = 'instance:actor';
protected $description = 'Generate instance actor';
protected $signature = 'instance:actor';
public function __construct()
{
parent::__construct();
}
protected $description = 'Generate instance actor';
public function handle()
{
if(Schema::hasTable('instance_actors') == false) {
$this->line(' ');
$this->error('Missing instance_actors table.');
$this->info('Run "php artisan migrate" and try again.');
$this->line(' ');
exit;
}
public function __construct()
{
parent::__construct();
}
if(InstanceActor::exists()) {
$actor = InstanceActor::whereNotNull('public_key')
->whereNotNull('private_key')
->firstOrFail();
Cache::rememberForever(InstanceActor::PKI_PUBLIC, function() use($actor) {
return $actor->public_key;
});
public function handle()
{
if (Schema::hasTable('instance_actors') == false) {
$this->line(' ');
$this->error('Missing instance_actors table.');
$this->info('Run "php artisan migrate" and try again.');
$this->line(' ');
exit;
}
Cache::rememberForever(InstanceActor::PKI_PRIVATE, function() use($actor) {
return $actor->private_key;
});
$this->info('Instance actor succesfully generated. You do not need to run this command again.');
return;
}
if (InstanceActor::exists()) {
$actor = InstanceActor::whereNotNull('public_key')
->whereNotNull('private_key')
->firstOrFail();
Cache::rememberForever(InstanceActor::PKI_PUBLIC, function () use ($actor) {
return $actor->public_key;
});
$pkiConfig = [
'digest_alg' => 'sha512',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$pki = openssl_pkey_new($pkiConfig);
openssl_pkey_export($pki, $pki_private);
$pki_public = openssl_pkey_get_details($pki);
$pki_public = $pki_public['key'];
Cache::rememberForever(InstanceActor::PKI_PRIVATE, function () use ($actor) {
return $actor->private_key;
});
$this->info('Instance actor succesfully generated. You do not need to run this command again.');
$actor = new InstanceActor();
$actor->public_key = $pki_public;
$actor->private_key = $pki_private;
$actor->save();
return;
}
Cache::rememberForever(InstanceActor::PKI_PUBLIC, function() use($actor) {
return $actor->public_key;
});
$pkiConfig = [
'digest_alg' => 'sha512',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$pki = openssl_pkey_new($pkiConfig);
openssl_pkey_export($pki, $pki_private);
$pki_public = openssl_pkey_get_details($pki);
$pki_public = $pki_public['key'];
Cache::rememberForever(InstanceActor::PKI_PRIVATE, function() use($actor) {
return $actor->private_key;
});
$actor = new InstanceActor();
$actor->public_key = $pki_public;
$actor->private_key = $pki_private;
$actor->save();
$this->info('Instance actor succesfully generated. You do not need to run this command again.');
Cache::rememberForever(InstanceActor::PKI_PUBLIC, function () use ($actor) {
return $actor->public_key;
});
return 0;
}
Cache::rememberForever(InstanceActor::PKI_PRIVATE, function () use ($actor) {
return $actor->private_key;
});
$this->info('Instance actor succesfully generated. You do not need to run this command again.');
return 0;
}
}

View File

@ -2,10 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Hashtag;
use App\StatusHashtag;
use DB;
use Illuminate\Console\Command;
class HashtagCachedCountUpdate extends Command
{
@ -31,19 +30,20 @@ class HashtagCachedCountUpdate extends Command
$limit = $this->option('limit');
$tags = Hashtag::whereNull('cached_count')->limit($limit)->get();
$count = count($tags);
if(!$count) {
if (! $count) {
return;
}
$bar = $this->output->createProgressBar($count);
$bar->start();
foreach($tags as $tag) {
foreach ($tags as $tag) {
$count = DB::table('status_hashtags')->whereHashtagId($tag->id)->count();
if(!$count) {
if (! $count) {
$tag->cached_count = 0;
$tag->saveQuietly();
$bar->advance();
continue;
}
$tag->cached_count = $count;
@ -52,6 +52,6 @@ class HashtagCachedCountUpdate extends Command
}
$bar->finish();
$this->line(' ');
return;
}
}

View File

@ -2,14 +2,15 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Hashtag;
use App\StatusHashtag;
use App\Models\HashtagRelated;
use App\Services\HashtagRelatedService;
use App\StatusHashtag;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\PromptsForMissingInput;
use function Laravel\Prompts\multiselect;
use function Laravel\Prompts\confirm;
use function Laravel\Prompts\multiselect;
class HashtagRelatedGenerate extends Command implements PromptsForMissingInput
{
@ -46,30 +47,30 @@ class HashtagRelatedGenerate extends Command implements PromptsForMissingInput
{
$tag = $this->argument('tag');
$hashtag = Hashtag::whereName($tag)->orWhere('slug', $tag)->first();
if(!$hashtag) {
if (! $hashtag) {
$this->error('Hashtag not found, aborting...');
exit;
}
$exists = HashtagRelated::whereHashtagId($hashtag->id)->exists();
if($exists) {
if ($exists) {
$confirmed = confirm('Found existing related tags, do you want to regenerate them?');
if(!$confirmed) {
if (! $confirmed) {
$this->error('Aborting...');
exit;
}
}
$this->info('Looking up #' . $tag . '...');
$this->info('Looking up #'.$tag.'...');
$tags = StatusHashtag::whereHashtagId($hashtag->id)->count();
if(!$tags || $tags < 100) {
if (! $tags || $tags < 100) {
$this->error('Not enough posts found to generate related hashtags!');
exit;
}
$this->info('Found ' . $tags . ' posts that use that hashtag');
$this->info('Found '.$tags.' posts that use that hashtag');
$related = collect(HashtagRelatedService::fetchRelatedTags($tag));
$selected = multiselect(
@ -78,15 +79,15 @@ class HashtagRelatedGenerate extends Command implements PromptsForMissingInput
required: true,
);
$filtered = $related->filter(fn($i) => in_array($i['name'], $selected))->all();
$agg_score = $related->filter(fn($i) => in_array($i['name'], $selected))->sum('related_count');
$filtered = $related->filter(fn ($i) => in_array($i['name'], $selected))->all();
$agg_score = $related->filter(fn ($i) => in_array($i['name'], $selected))->sum('related_count');
HashtagRelated::updateOrCreate([
'hashtag_id' => $hashtag->id,
], [
'related_tags' => array_values($filtered),
'agg_score' => $agg_score,
'last_calculated_at' => now()
'last_calculated_at' => now(),
]);
$this->info('Finished!');

View File

@ -1,9 +1,10 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Place;
use DB;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
class ImportCities extends Command
@ -24,7 +25,6 @@ class ImportCities extends Command
/**
* Checksum of city dataset.
*
*/
const CHECKSUM = 'e203c0247538788b2a91166c7cf4b95f58291d998f514e9306d315aa72b09e48bfd3ddf310bf737afc4eefadca9083b8ff796c67796c6bd8e882a3d268bd16af';
@ -54,7 +54,7 @@ class ImportCities extends Command
'TZ' => 'Tanzania',
'US' => 'USA',
'VE' => 'Venezuela',
'XK' => 'Kosovo'
'XK' => 'Kosovo',
];
/**
@ -78,16 +78,18 @@ class ImportCities extends Command
ini_set('memory_limit', '256M');
$path = storage_path('app/cities.json');
if(hash_file('sha512', $path) !== self::CHECKSUM) {
if (hash_file('sha512', $path) !== self::CHECKSUM) {
$this->error('Invalid or corrupt storage/app/cities.json data.');
$this->line('');
$this->info('Run the following command to fix:');
$this->info('git checkout storage/app/cities.json');
return;
}
if (!is_file($path)) {
if (! is_file($path)) {
$this->error('Missing storage/app/cities.json file!');
return;
}
@ -103,20 +105,20 @@ class ImportCities extends Command
$this->line('');
$this->info("Found {$cityCount} cities to insert ...");
$this->line('');
$bar = $this->output->createProgressBar($cityCount);
$bar->start();
$buffer = [];
$count = 0;
foreach ($cities as $city) {
$buffer[] = [
"name" => $city->name,
"slug" => Str::slug($city->name),
"country" => $this->codeToCountry($city->country),
"lat" => $city->lat,
"long" => $city->lng
'name' => $city->name,
'slug' => Str::slug($city->name),
'country' => $this->codeToCountry($city->country),
'lat' => $city->lat,
'long' => $city->lng,
];
$count++;
@ -135,10 +137,10 @@ class ImportCities extends Command
$this->line('');
$this->line('');
$this->info('Successfully imported ' . $cityCount . ' entries!');
$this->info('Successfully imported '.$cityCount.' entries!');
$this->line('');
ini_set('memory_limit', $old_memory_limit);
return;
}
private function insertBuffer($buffer)
@ -149,12 +151,13 @@ class ImportCities extends Command
private function codeToCountry($code)
{
$countries = $this->countries;
if(isset($countries[$code])) {
if (isset($countries[$code])) {
return $countries[$code];
}
$country = (new \League\ISO3166\ISO3166)->alpha2($code);
$this->countries[$code] = $country['name'];
return $this->countries[$code];
}
}

View File

@ -21,7 +21,6 @@ class ImportEmojis extends Command
{--overwrite : Overwrite existing emojis}
{--disabled : Import all emojis as disabled}';
/**
* The console command description.
*
@ -38,8 +37,9 @@ class ImportEmojis extends Command
{
$path = $this->argument('path');
if (!file_exists($path) || !mime_content_type($path) == 'application/x-tar') {
if (! file_exists($path) || ! mime_content_type($path) == 'application/x-tar') {
$this->error('Path does not exist or is not a tarfile');
return Command::FAILURE;
}
@ -52,8 +52,9 @@ class ImportEmojis extends Command
foreach (new \RecursiveIteratorIterator($tar) as $entry) {
$this->line("Processing {$entry->getFilename()}");
if (!$entry->isFile() || !$this->isImage($entry) || !$this->isEmoji($entry->getPathname())) {
if (! $entry->isFile() || ! $this->isImage($entry) || ! $this->isEmoji($entry->getPathname())) {
$failed++;
continue;
}
@ -73,8 +74,9 @@ class ImportEmojis extends Command
$customEmoji = CustomEmoji::whereShortcode($shortcode)->first();
if ($customEmoji && !$this->option('overwrite')) {
if ($customEmoji && ! $this->option('overwrite')) {
$skipped++;
continue;
}
@ -84,9 +86,9 @@ class ImportEmojis extends Command
$emoji->disabled = $this->option('disabled');
$emoji->save();
$fileName = $emoji->id . '.' . $extension;
$fileName = $emoji->id.'.'.$extension;
Storage::putFileAs('public/emoji', $entry->getPathname(), $fileName);
$emoji->media_path = 'emoji/' . $fileName;
$emoji->media_path = 'emoji/'.$fileName;
$emoji->save();
$imported++;
Cache::forget('pf:custom_emoji');
@ -105,6 +107,7 @@ class ImportEmojis extends Command
private function isImage($file)
{
$image = getimagesize($file->getPathname());
return $image !== false;
}

View File

@ -2,12 +2,11 @@
namespace App\Console\Commands;
use App\Models\ImportPost;
use App\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use App\User;
use App\Models\ImportPost;
use App\Services\ImportService;
class ImportRemoveDeletedAccounts extends Command
{
@ -32,7 +31,7 @@ class ImportRemoveDeletedAccounts extends Command
*/
public function handle()
{
$skipMinId = Cache::remember(self::CACHE_KEY, 864000, function() {
$skipMinId = Cache::remember(self::CACHE_KEY, 864000, function () {
return 1;
});
@ -43,13 +42,13 @@ class ImportRemoveDeletedAccounts extends Command
->limit(500)
->pluck('id');
if(!$deletedIds || !$deletedIds->count()) {
if (! $deletedIds || ! $deletedIds->count()) {
return;
}
foreach($deletedIds as $did) {
if(Storage::exists('imports/' . $did)) {
Storage::deleteDirectory('imports/' . $did);
foreach ($deletedIds as $did) {
if (Storage::exists('imports/'.$did)) {
Storage::deleteDirectory('imports/'.$did);
}
ImportPost::where('user_id', $did)->delete();

View File

@ -2,11 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\ImportPost;
use Storage;
use App\Services\ImportService;
use App\User;
use Illuminate\Console\Command;
use Storage;
class ImportUploadCleanStorage extends Command
{
@ -31,10 +29,10 @@ class ImportUploadCleanStorage extends Command
{
$dirs = Storage::allDirectories('imports');
foreach($dirs as $dir) {
foreach ($dirs as $dir) {
$uid = last(explode('/', $dir));
$skip = User::whereNull('status')->find($uid);
if(!$skip) {
if (! $skip) {
Storage::deleteDirectory($dir);
}
}

View File

@ -2,10 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\ImportPost;
use Storage;
use App\Services\ImportService;
use Illuminate\Console\Command;
class ImportUploadGarbageCollection extends Command
{
@ -28,17 +27,17 @@ class ImportUploadGarbageCollection extends Command
*/
public function handle()
{
if(!config('import.instagram.enabled')) {
if (! config('import.instagram.enabled')) {
return;
}
$ips = ImportPost::whereNull('status_id')->where('skip_missing_media', true)->take(100)->get();
if(!$ips->count()) {
if (! $ips->count()) {
return;
}
foreach($ips as $ip) {
foreach ($ips as $ip) {
$pid = $ip->profile_id;
$ip->delete();
ImportService::getPostCount($pid, true);

View File

@ -2,9 +2,10 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\ImportPost;
use App\Jobs\ImportPipeline\ImportMediaToCloudPipeline;
use App\Models\ImportPost;
use Illuminate\Console\Command;
use function Laravel\Prompts\progress;
class ImportUploadMediaToCloudStorage extends Command
@ -28,11 +29,12 @@ class ImportUploadMediaToCloudStorage extends Command
*/
public function handle()
{
if(
if (
(bool) config('import.instagram.storage.cloud.enabled') === false ||
(bool) config_cache('pixelfed.cloud_storage') === false
) {
$this->error('Aborted. Cloud storage is not enabled for IG imports.');
return;
}
@ -44,7 +46,7 @@ class ImportUploadMediaToCloudStorage extends Command
$posts = ImportPost::whereUploadedToS3(false)->take($limit)->get();
foreach($posts as $post) {
foreach ($posts as $post) {
ImportMediaToCloudPipeline::dispatch($post)->onQueue('low');
$progress->advance();
}

View File

@ -4,7 +4,7 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;
use \PDO;
use PDO;
class Installer extends Command
{
@ -55,7 +55,7 @@ class Installer extends Command
$this->info(' Welcome to the Pixelfed Installer!');
$this->info(' ');
$this->info(' ');
$this->info('Pixelfed version: ' . config('pixelfed.version'));
$this->info('Pixelfed version: '.config('pixelfed.version'));
$this->line(' ');
$this->installerSteps();
}
@ -102,7 +102,7 @@ class Installer extends Command
{
if (file_exists(base_path('.env')) &&
filesize(base_path('.env')) !== 0 &&
!$this->option('dangerously-overwrite-env')
! $this->option('dangerously-overwrite-env')
) {
$this->line('');
$this->error('Existing .env File Found - Installation Aborted');
@ -116,7 +116,7 @@ class Installer extends Command
{
$this->line('');
$this->info('Creating .env if required');
if (!file_exists(app()->environmentFilePath())) {
if (! file_exists(app()->environmentFilePath())) {
exec('cp .env.example .env');
}
}
@ -211,9 +211,9 @@ class Installer extends Command
];
foreach ($paths as $path) {
if (is_writeable($path) == false) {
$this->error("- Invalid permission found! Aborting installation.");
$this->error(" Please make the following path writeable by the web server:");
if (is_writable($path) == false) {
$this->error('- Invalid permission found! Aborting installation.');
$this->error(' Please make the following path writeable by the web server:');
$this->error(" $path");
exit;
} else {
@ -310,7 +310,7 @@ class Installer extends Command
}
$this->updateEnvFile('APP_NAME', $name);
$this->updateEnvFile('APP_URL', 'https://' . $domain);
$this->updateEnvFile('APP_URL', 'https://'.$domain);
$this->updateEnvFile('APP_DOMAIN', $domain);
$this->updateEnvFile('ADMIN_DOMAIN', $domain);
$this->updateEnvFile('SESSION_DOMAIN', $domain);
@ -320,11 +320,11 @@ class Installer extends Command
{
$this->line('');
$this->info('Laravel Settings (Defaults are recommended):');
$session = $this->choice('Select session driver', ["database", "file", "cookie", "redis", "memcached", "array"], 0);
$cache = $this->choice('Select cache driver', ["redis", "apc", "array", "database", "file", "memcached"], 0);
$queue = $this->choice('Select queue driver', ["redis", "database", "sync", "beanstalkd", "sqs", "null"], 0);
$broadcast = $this->choice('Select broadcast driver', ["log", "redis", "pusher", "null"], 0);
$log = $this->choice('Select Log Channel', ["stack", "single", "daily", "stderr", "syslog", "null"], 0);
$session = $this->choice('Select session driver', ['database', 'file', 'cookie', 'redis', 'memcached', 'array'], 0);
$cache = $this->choice('Select cache driver', ['redis', 'apc', 'array', 'database', 'file', 'memcached'], 0);
$queue = $this->choice('Select queue driver', ['redis', 'database', 'sync', 'beanstalkd', 'sqs', 'null'], 0);
$broadcast = $this->choice('Select broadcast driver', ['log', 'redis', 'pusher', 'null'], 0);
$log = $this->choice('Select Log Channel', ['stack', 'single', 'daily', 'stderr', 'syslog', 'null'], 0);
$horizon = $this->ask('Set Horizon Prefix [ex: horizon-]', 'horizon-');
$this->updateEnvFile('SESSION_DRIVER', $session);
@ -442,14 +442,14 @@ class Installer extends Command
protected function validateEnv()
{
$this->checkEnvKeys('APP_KEY', "key:generate failed?");
$this->checkEnvKeys('APP_ENV', "APP_ENV value should be production");
$this->checkEnvKeys('APP_DEBUG', "APP_DEBUG value should be false");
$this->checkEnvKeys('APP_KEY', 'key:generate failed?');
$this->checkEnvKeys('APP_ENV', 'APP_ENV value should be production');
$this->checkEnvKeys('APP_DEBUG', 'APP_DEBUG value should be false');
}
#####
# Installer Functions
#####
//####
// Installer Functions
//####
protected function checkEnvKeys($key, $error)
{
@ -471,7 +471,7 @@ class Installer extends Command
$payload = str_replace("{$key}={$existing}", "{$key}=\"{$value}\"", $payload);
$this->storeEnv($payload);
} else {
$payload = $payload . "\n{$key}=\"{$value}\"\n";
$payload = $payload."\n{$key}=\"{$value}\"\n";
$this->storeEnv($payload);
}
}
@ -482,6 +482,7 @@ class Installer extends Command
if ($matches && count($matches)) {
return substr($matches[0], strlen($needle) + 1);
}
return false;
}

View File

@ -2,15 +2,15 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Instance;
use App\Profile;
use App\Services\InstanceService;
use App\Jobs\InstancePipeline\FetchNodeinfoPipeline;
use function Laravel\Prompts\select;
use App\Services\InstanceService;
use Illuminate\Console\Command;
use function Laravel\Prompts\confirm;
use function Laravel\Prompts\progress;
use function Laravel\Prompts\search;
use function Laravel\Prompts\select;
use function Laravel\Prompts\table;
class InstanceManager extends Command
@ -47,42 +47,42 @@ class InstanceManager extends Command
],
);
switch($action) {
switch ($action) {
case 'Recalculate Stats':
return $this->recalculateStats();
break;
break;
case 'Unlisted Instances':
return $this->viewUnlistedInstances();
break;
break;
case 'Banned Instances':
return $this->viewBannedInstances();
break;
break;
case 'Unlist Instance':
return $this->unlistInstance();
break;
break;
case 'Ban Instance':
return $this->banInstance();
break;
break;
case 'Unban Instance':
return $this->unbanInstance();
break;
break;
case 'Relist Instance':
return $this->relistInstance();
break;
break;
}
}
protected function recalculateStats()
{
$instanceCount = Instance::count();
$confirmed = confirm('Do you want to recalculate stats for all ' . $instanceCount . ' instances?');
if(!$confirmed) {
$confirmed = confirm('Do you want to recalculate stats for all '.$instanceCount.' instances?');
if (! $confirmed) {
$this->error('Aborting...');
exit;
}
@ -109,7 +109,7 @@ class InstanceManager extends Command
);
$instance = Instance::find($id);
if(!$instance) {
if (! $instance) {
$this->error('Oops, an error occured');
exit;
}
@ -119,7 +119,7 @@ class InstanceManager extends Command
$instance->domain,
number_format($instance->status_count),
number_format($instance->user_count),
]
],
];
table(
['Domain', 'Status Count', 'User Count'],
@ -127,7 +127,7 @@ class InstanceManager extends Command
);
$confirmed = confirm('Are you sure you want to unlist this instance?');
if(!$confirmed) {
if (! $confirmed) {
$this->error('Aborting instance unlisting');
exit;
}
@ -135,7 +135,7 @@ class InstanceManager extends Command
$instance->unlisted = true;
$instance->save();
InstanceService::refresh();
$this->info('Successfully unlisted ' . $instance->domain . '!');
$this->info('Successfully unlisted '.$instance->domain.'!');
exit;
}
@ -149,7 +149,7 @@ class InstanceManager extends Command
);
$instance = Instance::find($id);
if(!$instance) {
if (! $instance) {
$this->error('Oops, an error occured');
exit;
}
@ -159,7 +159,7 @@ class InstanceManager extends Command
$instance->domain,
number_format($instance->status_count),
number_format($instance->user_count),
]
],
];
table(
['Domain', 'Status Count', 'User Count'],
@ -167,7 +167,7 @@ class InstanceManager extends Command
);
$confirmed = confirm('Are you sure you want to re-list this instance?');
if(!$confirmed) {
if (! $confirmed) {
$this->error('Aborting instance re-listing');
exit;
}
@ -175,7 +175,7 @@ class InstanceManager extends Command
$instance->unlisted = false;
$instance->save();
InstanceService::refresh();
$this->info('Successfully re-listed ' . $instance->domain . '!');
$this->info('Successfully re-listed '.$instance->domain.'!');
exit;
}
@ -189,7 +189,7 @@ class InstanceManager extends Command
);
$instance = Instance::find($id);
if(!$instance) {
if (! $instance) {
$this->error('Oops, an error occured');
exit;
}
@ -199,7 +199,7 @@ class InstanceManager extends Command
$instance->domain,
number_format($instance->status_count),
number_format($instance->user_count),
]
],
];
table(
['Domain', 'Status Count', 'User Count'],
@ -207,7 +207,7 @@ class InstanceManager extends Command
);
$confirmed = confirm('Are you sure you want to ban this instance?');
if(!$confirmed) {
if (! $confirmed) {
$this->error('Aborting instance ban');
exit;
}
@ -215,7 +215,7 @@ class InstanceManager extends Command
$instance->banned = true;
$instance->save();
InstanceService::refresh();
$this->info('Successfully banned ' . $instance->domain . '!');
$this->info('Successfully banned '.$instance->domain.'!');
exit;
}
@ -229,7 +229,7 @@ class InstanceManager extends Command
);
$instance = Instance::find($id);
if(!$instance) {
if (! $instance) {
$this->error('Oops, an error occured');
exit;
}
@ -239,7 +239,7 @@ class InstanceManager extends Command
$instance->domain,
number_format($instance->status_count),
number_format($instance->user_count),
]
],
];
table(
['Domain', 'Status Count', 'User Count'],
@ -247,7 +247,7 @@ class InstanceManager extends Command
);
$confirmed = confirm('Are you sure you want to unban this instance?');
if(!$confirmed) {
if (! $confirmed) {
$this->error('Aborting instance unban');
exit;
}
@ -255,7 +255,7 @@ class InstanceManager extends Command
$instance->banned = false;
$instance->save();
InstanceService::refresh();
$this->info('Successfully un-banned ' . $instance->domain . '!');
$this->info('Successfully un-banned '.$instance->domain.'!');
exit;
}
@ -263,7 +263,7 @@ class InstanceManager extends Command
{
$data = Instance::whereBanned(true)
->get(['domain', 'user_count', 'status_count'])
->map(function($d) {
->map(function ($d) {
return [
'domain' => $d->domain,
'user_count' => number_format($d->user_count),
@ -281,12 +281,12 @@ class InstanceManager extends Command
{
$data = Instance::whereUnlisted(true)
->get(['domain', 'user_count', 'status_count', 'banned'])
->map(function($d) {
->map(function ($d) {
return [
'domain' => $d->domain,
'user_count' => number_format($d->user_count),
'status_count' => number_format($d->status_count),
'banned' => $d->banned ? '✅' : null
'banned' => $d->banned ? '✅' : null,
];
})
->toArray();

View File

@ -2,42 +2,43 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Media;
use Cache, Storage;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\PromptsForMissingInput;
use Storage;
class MediaCloudUrlRewrite extends Command implements PromptsForMissingInput
{
/**
* The name and signature of the console command.
*
* @var string
*/
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'media:cloud-url-rewrite {oldDomain} {newDomain}';
/**
* Prompt for missing input arguments using the returned questions.
*
* @return array
*/
* Prompt for missing input arguments using the returned questions.
*
* @return array
*/
protected function promptForMissingArgumentsUsing()
{
return [
'oldDomain' => 'The old S3 domain',
'newDomain' => 'The new S3 domain'
'newDomain' => 'The new S3 domain',
];
}
/**
* The console command description.
*
* @var string
*/
* The console command description.
*
* @var string
*/
protected $description = 'Rewrite S3 media urls from local users';
/**
* Execute the console command.
*/
* Execute the console command.
*/
public function handle()
{
$this->preflightCheck();
@ -47,7 +48,7 @@ class MediaCloudUrlRewrite extends Command implements PromptsForMissingInput
protected function preflightCheck()
{
if(config_cache('pixelfed.cloud_storage') != true) {
if (config_cache('pixelfed.cloud_storage') != true) {
$this->info('Error: Cloud storage is not enabled!');
$this->error('Aborting...');
exit;
@ -64,8 +65,8 @@ class MediaCloudUrlRewrite extends Command implements PromptsForMissingInput
$this->info(' ');
$this->info(' Media Cloud Url Rewrite Tool');
$this->info(' ===');
$this->info(' Old S3: ' . trim($this->argument('oldDomain')));
$this->info(' New S3: ' . trim($this->argument('newDomain')));
$this->info(' Old S3: '.trim($this->argument('oldDomain')));
$this->info(' New S3: '.trim($this->argument('newDomain')));
$this->info(' ');
}
@ -73,12 +74,12 @@ class MediaCloudUrlRewrite extends Command implements PromptsForMissingInput
{
$disk = Storage::disk(config('filesystems.cloud'))->url('test');
$domain = parse_url($disk, PHP_URL_HOST);
if(trim($this->argument('newDomain')) !== $domain) {
if (trim($this->argument('newDomain')) !== $domain) {
$this->error('Error: The new S3 domain you entered is not currently configured');
exit;
}
if(!$this->confirm('Confirm this is correct')) {
if (! $this->confirm('Confirm this is correct')) {
$this->error('Aborting...');
exit;
}
@ -96,30 +97,32 @@ class MediaCloudUrlRewrite extends Command implements PromptsForMissingInput
$bar = $this->output->createProgressBar($count);
$counter = 0;
$bar->start();
foreach(Media::whereNotNull('cdn_url')->lazyById(1000, 'id') as $media) {
if(strncmp($media->media_path, 'http', 4) === 0) {
foreach (Media::whereNotNull('cdn_url')->lazyById(1000, 'id') as $media) {
if (strncmp($media->media_path, 'http', 4) === 0) {
$bar->advance();
continue;
}
$cdnHost = parse_url($media->cdn_url, PHP_URL_HOST);
if($oldDomain != $cdnHost || $newDomain == $cdnHost) {
if ($oldDomain != $cdnHost || $newDomain == $cdnHost) {
$bar->advance();
continue;
}
$media->cdn_url = str_replace($oldDomain, $newDomain, $media->cdn_url);
if($media->thumbnail_url != null) {
if ($media->thumbnail_url != null) {
$thumbHost = parse_url($media->thumbnail_url, PHP_URL_HOST);
if($thumbHost == $oldDomain) {
if ($thumbHost == $oldDomain) {
$thumbUrl = $disk->url($media->thumbnail_path);
$media->thumbnail_url = $thumbUrl;
}
}
if($media->optimized_url != null) {
if ($media->optimized_url != null) {
$optiHost = parse_url($media->optimized_url, PHP_URL_HOST);
if($optiHost == $oldDomain) {
if ($optiHost == $oldDomain) {
$optiUrl = str_replace($oldDomain, $newDomain, $media->optimized_url);
$media->optimized_url = $optiUrl;
}
@ -133,7 +136,7 @@ class MediaCloudUrlRewrite extends Command implements PromptsForMissingInput
$bar->finish();
$this->line(' ');
$this->info('Finished! Updated ' . $counter . ' total records!');
$this->info('Finished! Updated '.$counter.' total records!');
$this->line(' ');
$this->info('Tip: Run `php artisan cache:clear` to purge cached urls');
}

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Util\Media\Filter;
use App\Media;
use App\Util\Media\Filter;
use Illuminate\Console\Command;
class MediaFix extends Command
{
@ -39,7 +39,7 @@ class MediaFix extends Command
*/
public function handle()
{
if(!version_compare(config('pixelfed.version'),'0.10.8','ge')) {
if (! version_compare(config('pixelfed.version'), '0.10.8', 'ge')) {
$this->error('Please update to version 0.10.8 or newer.');
exit;
}
@ -47,15 +47,15 @@ class MediaFix extends Command
$classes = Filter::classes();
Media::whereNotNull('filter_class')
->chunk(50, function($filters) use($classes) {
foreach($filters as $filter) {
->chunk(50, function ($filters) use ($classes) {
foreach ($filters as $filter) {
$match = $filter->filter_class ? in_array($filter->filter_class, $classes) : true;
if(!$match) {
if (! $match) {
$filter->filter_class = null;
$filter->filter_name = null;
$filter->save();
}
}
});
});
}
}

View File

@ -2,57 +2,57 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\{Media, Status};
use App\Media;
use App\Services\MediaStorageService;
use Illuminate\Console\Command;
class MediaGarbageCollector extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'media:gc';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'media:gc';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Delete media uploads not attached to any active statuses';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Delete media uploads not attached to any active statuses';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$limit = 500;
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$limit = 500;
$gc = Media::whereNull('status_id')
->where('created_at', '<', now()->subHours(2)->toDateTimeString())
->take($limit)
->get();
$gc = Media::whereNull('status_id')
->where('created_at', '<', now()->subHours(2)->toDateTimeString())
->take($limit)
->get();
$bar = $this->output->createProgressBar($gc->count());
$bar->start();
foreach($gc as $media) {
MediaStorageService::delete($media, true);
$bar->advance();
}
$bar->finish();
$this->line('');
}
$bar = $this->output->createProgressBar($gc->count());
$bar->start();
foreach ($gc as $media) {
MediaStorageService::delete($media, true);
$bar->advance();
}
$bar->finish();
$this->line('');
}
}

View File

@ -2,58 +2,59 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Media;
use App\Status;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use App\Services\MediaService;
use App\Services\StatusService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class MediaS3GarbageCollector extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'media:s3gc {--limit=200} {--huge} {--log-errors}';
/**
* The console command description.
*
* @var string
*/
* The console command description.
*
* @var string
*/
protected $description = 'Delete (local) media uploads that exist on S3';
/**
* Create a new command instance.
*
* @return void
*/
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
* Execute the console command.
*
* @return int
*/
public function handle()
{
$enabled = in_array(config_cache('pixelfed.cloud_storage'), ['1', true, 'true']);
if(!$enabled) {
if (! $enabled) {
$this->error('Cloud storage not enabled. Exiting...');
return;
}
$deleteEnabled = config('media.delete_local_after_cloud');
if(!$deleteEnabled) {
if (! $deleteEnabled) {
$this->error('Delete local storage after cloud upload is not enabled');
return;
}
@ -61,17 +62,18 @@ class MediaS3GarbageCollector extends Command
$hugeMode = $this->option('huge');
$log = $this->option('log-errors');
if($limit > 2000 && !$hugeMode) {
if ($limit > 2000 && ! $hugeMode) {
$this->error('Limit exceeded, please use a limit under 2000 or run again with the --huge flag');
return;
}
$minId = Media::orderByDesc('id')->where('created_at', '<', now()->subHours(12))->first();
if(!$minId) {
return;
if (! $minId) {
return;
} else {
$minId = $minId->id;
$minId = $minId->id;
}
return $hugeMode ?
@ -95,19 +97,19 @@ class MediaS3GarbageCollector extends Command
$cloudDisk = Storage::disk(config('filesystems.cloud'));
$localDisk = Storage::disk('local');
foreach($gc as $media) {
foreach ($gc as $media) {
try {
if(
if (
$cloudDisk->exists($media->media_path)
) {
if( $localDisk->exists($media->media_path)) {
if ($localDisk->exists($media->media_path)) {
$localDisk->delete($media->media_path);
$media->version = 4;
$media->save();
$totalSize = $totalSize + $media->size;
MediaService::del($media->status_id);
StatusService::del($media->status_id, false);
if($localDisk->exists($media->thumbnail_path)) {
if ($localDisk->exists($media->thumbnail_path)) {
$localDisk->delete($media->thumbnail_path);
}
} else {
@ -115,28 +117,32 @@ class MediaS3GarbageCollector extends Command
$media->save();
}
} else {
if($log) {
if ($log) {
Log::channel('media')->info('[GC] Local media not properly persisted to cloud storage', ['media_id' => $media->id]);
}
}
$bar->advance();
} catch (FileNotFoundException $e) {
$bar->advance();
continue;
} catch (NotFoundHttpException $e) {
$bar->advance();
continue;
} catch (\Exception $e) {
$bar->advance();
continue;
}
}
$bar->finish();
$this->line(' ');
$this->info('Finished!');
if($totalSize) {
$this->info('Cleared ' . $totalSize . ' bytes of media from local disk!');
if ($totalSize) {
$this->info('Cleared '.$totalSize.' bytes of media from local disk!');
}
return 0;
}
@ -152,17 +158,17 @@ class MediaS3GarbageCollector extends Command
->whereNotNull(['status_id', 'cdn_url', 'replicated_at'])
->whereNot('version', '4')
->where('id', '<', $minId)
->chunk(50, function($medias) use($cloudDisk, $localDisk, $bar, $log) {
foreach($medias as $media) {
->chunk(50, function ($medias) use ($cloudDisk, $localDisk, $bar, $log) {
foreach ($medias as $media) {
try {
if($cloudDisk->exists($media->media_path)) {
if( $localDisk->exists($media->media_path)) {
if ($cloudDisk->exists($media->media_path)) {
if ($localDisk->exists($media->media_path)) {
$localDisk->delete($media->media_path);
$media->version = 4;
$media->save();
MediaService::del($media->status_id);
StatusService::del($media->status_id, false);
if($localDisk->exists($media->thumbnail_path)) {
if ($localDisk->exists($media->thumbnail_path)) {
$localDisk->delete($media->thumbnail_path);
}
} else {
@ -170,23 +176,26 @@ class MediaS3GarbageCollector extends Command
$media->save();
}
} else {
if($log) {
if ($log) {
Log::channel('media')->info('[GC] Local media not properly persisted to cloud storage', ['media_id' => $media->id]);
}
}
$bar->advance();
} catch (FileNotFoundException $e) {
$bar->advance();
continue;
} catch (NotFoundHttpException $e) {
$bar->advance();
continue;
} catch (\Exception $e) {
$bar->advance();
continue;
}
}
});
});
$bar->finish();
$this->line(' ');

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Jobs\InternalPipeline\NotificationEpochUpdatePipeline;
use Illuminate\Console\Command;
class NotificationEpochUpdate extends Command
{

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\EmailVerification;
use Illuminate\Console\Command;
class PasswordResetGC extends Command
{
@ -39,8 +39,8 @@ class PasswordResetGC extends Command
public function handle()
{
EmailVerification::where('created_at', '<', now()->subMinutes(1441))
->chunk(50, function($emails) {
foreach($emails as $em) {
->chunk(50, function ($emails) {
foreach ($emails as $em) {
$em->delete();
}
});

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Media;
use DB;
use Illuminate\Console\Command;
class RegenerateThumbnails extends Command
{
@ -39,10 +39,10 @@ class RegenerateThumbnails extends Command
*/
public function handle()
{
DB::transaction(function() {
DB::transaction(function () {
Media::whereIn('mime', ['image/jpeg', 'image/png'])
->chunk(50, function($medias) {
foreach($medias as $media) {
->chunk(50, function ($medias) {
foreach ($medias as $media) {
\App\Jobs\ImageOptimizePipeline\ImageThumbnail::dispatch($media);
}
});

View File

@ -47,15 +47,15 @@ class SeedFollows extends Command
$actor = Profile::whereDomain(false)->inRandomOrder()->firstOrFail();
$target = Profile::whereDomain(false)->inRandomOrder()->firstOrFail();
if($actor->id == $target->id) {
if ($actor->id == $target->id) {
continue;
}
$follow = Follower::firstOrCreate([
'profile_id' => $actor->id,
'following_id' => $target->id
'profile_id' => $actor->id,
'following_id' => $target->id,
]);
if($follow->wasRecentlyCreated == true) {
if ($follow->wasRecentlyCreated == true) {
FollowPipeline::dispatch($follow);
}
} catch (Exception $e) {

View File

@ -2,12 +2,12 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Storage;
use App\Instance;
use App\Profile;
use App\User;
use App\Instance;
use App\Util\ActivityPub\Helpers;
use Illuminate\Console\Command;
use Storage;
use Symfony\Component\HttpKernel\Exception\HttpException;
class SendUpdateActor extends Command
@ -35,33 +35,35 @@ class SendUpdateActor extends Command
{
$totalUserCount = Profile::whereNotNull('user_id')->count();
$totalInstanceCount = Instance::count();
$this->info('Found ' . $totalUserCount . ' local accounts and ' . $totalInstanceCount . ' remote instances');
$this->info('Found '.$totalUserCount.' local accounts and '.$totalInstanceCount.' remote instances');
$task = $this->choice(
'What do you want to do?',
[
'View top instances',
'Send updates to an instance'
'Send updates to an instance',
],
0
);
if($task === 'View top instances') {
if ($task === 'View top instances') {
$this->table(
['domain', 'user_count', 'last_synced'],
Instance::orderByDesc('user_count')->take(20)->get(['domain', 'user_count', 'actors_last_synced_at'])->toArray()
);
return Command::SUCCESS;
} else {
$domain = $this->anticipate('Enter the instance domain', function ($input) {
return Instance::where('domain', 'like', '%' . $input . '%')->pluck('domain')->toArray();
return Instance::where('domain', 'like', '%'.$input.'%')->pluck('domain')->toArray();
});
if(!$this->confirm('Are you sure you want to send actor updates to ' . $domain . '?')) {
if (! $this->confirm('Are you sure you want to send actor updates to '.$domain.'?')) {
return;
}
if($cur = Instance::whereDomain($domain)->whereNotNull('actors_last_synced_at')->first()) {
if(!$this->option('force')) {
$this->error('ERROR: Cannot re-sync this instance, it was already synced on ' . $cur->actors_last_synced_at);
if ($cur = Instance::whereDomain($domain)->whereNotNull('actors_last_synced_at')->first()) {
if (! $this->option('force')) {
$this->error('ERROR: Cannot re-sync this instance, it was already synced on '.$cur->actors_last_synced_at);
return;
}
}
@ -69,25 +71,27 @@ class SendUpdateActor extends Command
$this->line(' ');
$this->error('Keep this window open during this process or it will not complete!');
$sharedInbox = Profile::whereDomain($domain)->whereNotNull('sharedInbox')->first();
if(!$sharedInbox) {
$this->error('ERROR: Cannot find the sharedInbox of ' . $domain);
if (! $sharedInbox) {
$this->error('ERROR: Cannot find the sharedInbox of '.$domain);
return;
}
$url = $sharedInbox->sharedInbox;
$this->line(' ');
$this->info('Found sharedInbox: ' . $url);
$this->info('Found sharedInbox: '.$url);
$bar = $this->output->createProgressBar($totalUserCount);
$bar->start();
$startCache = $this->getStorageCache($domain);
User::whereNull('status')->when($startCache, function($query, $startCache) use($bar) {
User::whereNull('status')->when($startCache, function ($query, $startCache) use ($bar) {
$bar->advance($startCache);
return $query->where('id', '>', $startCache);
})->chunk(50, function($users) use($bar, $url, $domain) {
foreach($users as $user) {
})->chunk(50, function ($users) use ($bar, $url, $domain) {
foreach ($users as $user) {
$this->updateStorageCache($domain, $user->id);
$profile = Profile::find($user->profile_id);
if(!$profile) {
if (! $profile) {
continue;
}
$body = $this->updateObject($profile);
@ -105,6 +109,7 @@ class SendUpdateActor extends Command
$instance->actors_last_synced_at = now();
$instance->save();
$this->info('Finished!');
return Command::SUCCESS;
}
@ -121,61 +126,63 @@ class SendUpdateActor extends Command
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
],
],
'id' => $profile->permalink('#updates/' . time()),
'id' => $profile->permalink('#updates/'.time()),
'actor' => $profile->permalink(),
'type' => 'Update',
'object' => $this->actorObject($profile)
'object' => $this->actorObject($profile),
];
}
protected function touchStorageCache($domain)
{
$path = 'actor-update-cache/' . $domain;
if(!Storage::exists($path)) {
Storage::put($path, "");
$path = 'actor-update-cache/'.$domain;
if (! Storage::exists($path)) {
Storage::put($path, '');
}
}
protected function getStorageCache($domain)
{
$path = 'actor-update-cache/' . $domain;
$path = 'actor-update-cache/'.$domain;
return Storage::get($path);
}
protected function updateStorageCache($domain, $value)
{
$path = 'actor-update-cache/' . $domain;
$path = 'actor-update-cache/'.$domain;
Storage::put($path, $value);
}
protected function actorObject($profile)
{
$permalink = $profile->permalink();
return [
'id' => $permalink,
'type' => 'Person',
'following' => $permalink . '/following',
'followers' => $permalink . '/followers',
'inbox' => $permalink . '/inbox',
'outbox' => $permalink . '/outbox',
'preferredUsername' => $profile->username,
'name' => $profile->name,
'summary' => $profile->bio,
'url' => $profile->url(),
'id' => $permalink,
'type' => 'Person',
'following' => $permalink.'/following',
'followers' => $permalink.'/followers',
'inbox' => $permalink.'/inbox',
'outbox' => $permalink.'/outbox',
'preferredUsername' => $profile->username,
'name' => $profile->name,
'summary' => $profile->bio,
'url' => $profile->url(),
'manuallyApprovesFollowers' => (bool) $profile->is_private,
'publicKey' => [
'id' => $permalink . '#main-key',
'owner' => $permalink,
'id' => $permalink.'#main-key',
'owner' => $permalink,
'publicKeyPem' => $profile->public_key,
],
'icon' => [
'type' => 'Image',
'type' => 'Image',
'mediaType' => 'image/jpeg',
'url' => $profile->avatarUrl(),
'url' => $profile->avatarUrl(),
],
'endpoints' => [
'sharedInbox' => config('app.url') . '/f/inbox'
]
'sharedInbox' => config('app.url').'/f/inbox',
],
];
}
}

View File

@ -2,10 +2,10 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Jobs\StatusPipeline\StatusDelete;
use App\Status;
use DB;
use App\Jobs\StatusPipeline\StatusDelete;
use Illuminate\Console\Command;
class StatusDedupe extends Command
{
@ -41,8 +41,9 @@ class StatusDedupe extends Command
public function handle()
{
if(config('database.default') == 'pgsql') {
if (config('database.default') == 'pgsql') {
$this->info('This command is not compatible with Postgres, we are working on a fix.');
return;
}
DB::table('statuses')
@ -52,13 +53,13 @@ class StatusDedupe extends Command
->groupBy('uri')
->orderBy('created_at')
->having('occurences', '>', 1)
->chunk(50, function($statuses) {
foreach($statuses as $status) {
->chunk(50, function ($statuses) {
foreach ($statuses as $status) {
$this->info("Found duplicate: $status->uri");
Status::whereUri($status->uri)
->where('id', '!=', $status->id)
->get()
->map(function($status) {
->map(function ($status) {
$this->info("Deleting Duplicate ID: $status->id");
StatusDelete::dispatch($status);
});

View File

@ -2,83 +2,82 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use App\Story;
use App\StoryView;
use App\Jobs\StoryPipeline\StoryExpire;
use App\Jobs\StoryPipeline\StoryRotateMedia;
use App\Services\StoryService;
use App\Story;
use Illuminate\Console\Command;
class StoryGC extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'story:gc';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'story:gc';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Clear expired Stories';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Clear expired Stories';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->archiveExpiredStories();
$this->rotateMedia();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->archiveExpiredStories();
$this->rotateMedia();
}
protected function archiveExpiredStories()
{
$stories = Story::whereActive(true)
->where('expires_at', '<', now())
->get();
protected function archiveExpiredStories()
{
$stories = Story::whereActive(true)
->where('expires_at', '<', now())
->get();
foreach($stories as $story) {
StoryExpire::dispatch($story)->onQueue('story');
}
}
foreach ($stories as $story) {
StoryExpire::dispatch($story)->onQueue('story');
}
}
protected function rotateMedia()
{
$queue = StoryService::rotateQueue();
protected function rotateMedia()
{
$queue = StoryService::rotateQueue();
if(!$queue || count($queue) == 0) {
return;
}
if (! $queue || count($queue) == 0) {
return;
}
collect($queue)
->each(function($id) {
$story = StoryService::getById($id);
if(!$story) {
StoryService::removeRotateQueue($id);
return;
}
if($story->created_at->gt(now()->subMinutes(20))) {
return;
}
StoryRotateMedia::dispatch($story)->onQueue('story');
StoryService::removeRotateQueue($id);
return;
});
}
collect($queue)
->each(function ($id) {
$story = StoryService::getById($id);
if (! $story) {
StoryService::removeRotateQueue($id);
return;
}
if ($story->created_at->gt(now()->subMinutes(20))) {
return;
}
StoryRotateMedia::dispatch($story)->onQueue('story');
StoryService::removeRotateQueue($id);
});
}
}

View File

@ -2,17 +2,17 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\ImportPost;
use App\Services\ImportService;
use App\Media;
use App\Models\ImportPost;
use App\Profile;
use App\Status;
use Storage;
use App\Services\AccountService;
use App\Services\ImportService;
use App\Services\MediaPathService;
use Illuminate\Support\Str;
use App\Status;
use App\Util\Lexer\Autolink;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
use Storage;
class TransformImports extends Command
{
@ -35,23 +35,24 @@ class TransformImports extends Command
*/
public function handle()
{
if(!config('import.instagram.enabled')) {
if (! config('import.instagram.enabled')) {
return;
}
$ips = ImportPost::whereNull('status_id')->where('skip_missing_media', '!=', true)->take(500)->get();
if(!$ips->count()) {
if (! $ips->count()) {
return;
}
foreach($ips as $ip) {
foreach ($ips as $ip) {
$id = $ip->user_id;
$pid = $ip->profile_id;
$profile = Profile::find($pid);
if(!$profile) {
if (! $profile) {
$ip->skip_missing_media = true;
$ip->save();
continue;
}
@ -63,39 +64,43 @@ class TransformImports extends Command
->where('creation_day', $ip->creation_day)
->exists();
if($exists == true) {
if ($exists == true) {
$ip->skip_missing_media = true;
$ip->save();
continue;
}
$idk = ImportService::getId($ip->user_id, $ip->creation_year, $ip->creation_month, $ip->creation_day);
if(!$idk) {
if (! $idk) {
$ip->skip_missing_media = true;
$ip->save();
continue;
}
if(Storage::exists('imports/' . $id . '/' . $ip->filename) === false) {
if (Storage::exists('imports/'.$id.'/'.$ip->filename) === false) {
ImportService::clearAttempts($profile->id);
ImportService::getPostCount($profile->id, true);
$ip->skip_missing_media = true;
$ip->save();
continue;
}
$missingMedia = false;
foreach($ip->media as $ipm) {
foreach ($ip->media as $ipm) {
$fileName = last(explode('/', $ipm['uri']));
$og = 'imports/' . $id . '/' . $fileName;
if(!Storage::exists($og)) {
$og = 'imports/'.$id.'/'.$fileName;
if (! Storage::exists($og)) {
$missingMedia = true;
}
}
if($missingMedia === true) {
if ($missingMedia === true) {
$ip->skip_missing_media = true;
$ip->save();
continue;
}
@ -112,20 +117,21 @@ class TransformImports extends Command
$status->created_at = now()->parse($ip->creation_date);
$status->save();
foreach($ip->media as $ipm) {
foreach ($ip->media as $ipm) {
$fileName = last(explode('/', $ipm['uri']));
$ext = last(explode('.', $fileName));
$basePath = MediaPathService::get($profile);
$og = 'imports/' . $id . '/' . $fileName;
if(!Storage::exists($og)) {
$og = 'imports/'.$id.'/'.$fileName;
if (! Storage::exists($og)) {
$ip->skip_missing_media = true;
$ip->save();
continue;
}
$size = Storage::size($og);
$mime = Storage::mimeType($og);
$newFile = Str::random(40) . '.' . $ext;
$np = $basePath . '/' . $newFile;
$newFile = Str::random(40).'.'.$ext;
$np = $basePath.'/'.$newFile;
Storage::move($og, $np);
$media = new Media;
$media->profile_id = $pid;

View File

@ -2,9 +2,7 @@
namespace App\Console\Commands;
use Schema;
use Illuminate\Console\Command;
use App\Jobs\ImageOptimizePipeline\ImageThumbnail;
class UpdateCommand extends Command
{
@ -45,14 +43,15 @@ class UpdateCommand extends Command
public function update()
{
$v = $this->getVersionFile();
if($v && isset($v['commit_hash']) && $v['commit_hash'] == exec('git rev-parse HEAD') && \App\StatusHashtag::whereNull('profile_id')->count() == 0) {
if ($v && isset($v['commit_hash']) && $v['commit_hash'] == exec('git rev-parse HEAD') && \App\StatusHashtag::whereNull('profile_id')->count() == 0) {
$this->info('No updates found.');
return;
}
$bar = $this->output->createProgressBar(\App\StatusHashtag::whereNull('profile_id')->count());
\App\StatusHashtag::whereNull('profile_id')->with('status')->chunk(50, function($sh) use ($bar) {
foreach($sh as $status_hashtag) {
if(!$status_hashtag->status) {
\App\StatusHashtag::whereNull('profile_id')->with('status')->chunk(50, function ($sh) use ($bar) {
foreach ($sh as $status_hashtag) {
if (! $status_hashtag->status) {
$status_hashtag->delete();
} else {
$status_hashtag->profile_id = $status_hashtag->status->profile_id;
@ -68,17 +67,19 @@ class UpdateCommand extends Command
protected function getVersionFile()
{
$path = storage_path('app/version.json');
return is_file($path) ?
return is_file($path) ?
json_decode(file_get_contents($path), true) :
false;
}
protected function updateVersionFile() {
protected function updateVersionFile()
{
$path = storage_path('app/version.json');
$contents = [
'commit_hash' => exec('git rev-parse HEAD'),
'version' => config('pixelfed.version'),
'timestamp' => date('c')
'timestamp' => date('c'),
];
$json = json_encode($contents, JSON_PRETTY_PRINT);
file_put_contents($path, $json);

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use App\User;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\PromptsForMissingInput;
use App\User;
class UserAdmin extends Command implements PromptsForMissingInput
{
@ -45,19 +45,19 @@ class UserAdmin extends Command implements PromptsForMissingInput
$user = User::whereUsername($id)->first();
if(!$user) {
if (! $user) {
$this->error('Could not find any user with that username or id.');
exit;
}
$this->info('Found username: ' . $user->username);
$this->info('Found username: '.$user->username);
$state = $user->is_admin ? 'Remove admin privileges from this user?' : 'Add admin privileges to this user?';
$confirmed = $this->confirm($state);
if(!$confirmed) {
if (! $confirmed) {
exit;
}
$user->is_admin = !$user->is_admin;
$user->is_admin = ! $user->is_admin;
$user->save();
$this->info('Successfully changed permissions!');
}

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use Illuminate\Console\Command;
class UserCreate extends Command
{
@ -42,7 +42,7 @@ class UserCreate extends Command
$o = $this->options();
if( $o['name'] &&
if ($o['name'] &&
$o['username'] &&
$o['email'] &&
$o['password']
@ -57,6 +57,7 @@ class UserCreate extends Command
$user->save();
$this->info('Successfully created user!');
return;
}
@ -64,14 +65,14 @@ class UserCreate extends Command
$username = $this->ask('Username');
if(User::whereUsername($username)->exists()) {
if (User::whereUsername($username)->exists()) {
$this->error('Username already in use, please try again...');
exit;
}
$email = $this->ask('Email');
if(User::whereEmail($email)->exists()) {
if (User::whereEmail($email)->exists()) {
$this->error('Email already in use, please try again...');
exit;
}
@ -79,23 +80,23 @@ class UserCreate extends Command
$password = $this->secret('Password');
$confirm = $this->secret('Confirm Password');
if($password !== $confirm) {
if ($password !== $confirm) {
$this->error('Password mismatch, please try again...');
exit;
}
if (strlen($password) < 6) {
$this->error('Must be 6 or more characters, please try again...');
exit;
}
$is_admin = $this->confirm('Make this user an admin?');
$confirm_email = $this->confirm('Manually verify email address?');
if($this->confirm('Are you sure you want to create this user?') &&
if ($this->confirm('Are you sure you want to create this user?') &&
$username &&
$name &&
$email &&
$name &&
$email &&
$password
) {
$user = new User;

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use App\Jobs\DeletePipeline\DeleteAccountPipeline;
use App\User;
use Illuminate\Console\Command;
class UserDelete extends Command
{
@ -42,39 +42,40 @@ class UserDelete extends Command
$id = $this->argument('id');
$force = $this->option('force');
if(ctype_digit($id) == true) {
if (ctype_digit($id) == true) {
$user = User::find($id);
} else {
$user = User::whereUsername($id)->first();
}
if(!$user) {
if (! $user) {
$this->error('Could not find any user with that username or id.');
exit;
}
if($user->status == 'deleted' && $force == false) {
if ($user->status == 'deleted' && $force == false) {
$this->error('Account has already been deleted.');
return;
}
if($user->is_admin == true) {
if ($user->is_admin == true) {
$this->error('Cannot delete an admin account from CLI.');
exit;
}
if(!$this->confirm('Are you sure you want to delete this account?')) {
if (! $this->confirm('Are you sure you want to delete this account?')) {
exit;
}
$confirmation = $this->ask('Enter the username to confirm deletion');
if($confirmation !== $user->username) {
if ($confirmation !== $user->username) {
$this->error('Username does not match, exiting...');
exit;
}
if($user->status !== 'deleted') {
if ($user->status !== 'deleted') {
$profile = $user->profile;
$profile->status = $user->status = 'deleted';
$profile->save();

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\EmailVerification;
use App\User;
use Illuminate\Console\Command;
class UserRegistrationMagicLink extends Command
{
@ -31,45 +31,50 @@ class UserRegistrationMagicLink extends Command
{
$username = $this->option('username');
$email = $this->option('email');
if(!$username && !$email) {
if (! $username && ! $email) {
$this->error('Please provide the username or email as arguments');
$this->line(' ');
$this->info('Example: ');
$this->info('php artisan user:app-magic-link --username=dansup');
$this->info('php artisan user:app-magic-link --email=dansup@pixelfed.com');
return;
}
$user = User::when($username, function($q, $username) {
$user = User::when($username, function ($q, $username) {
return $q->whereUsername($username);
})
->when($email, function($q, $email) {
return $q->whereEmail($email);
})
->first();
->when($email, function ($q, $email) {
return $q->whereEmail($email);
})
->first();
if(!$user) {
if (! $user) {
$this->error('We cannot find any matching accounts');
return;
}
if($user->email_verified_at) {
if ($user->email_verified_at) {
$this->error('User already verified email address');
return;
}
if(!$user->register_source || $user->register_source !== 'app' || !$user->app_register_token) {
if (! $user->register_source || $user->register_source !== 'app' || ! $user->app_register_token) {
$this->error('User did not register via app');
return;
}
$verify = EmailVerification::whereUserId($user->id)->first();
if(!$verify) {
if (! $verify) {
$this->error('Cannot find user verification codes');
return;
}
$appUrl = 'pixelfed://confirm-account/'. $user->app_register_token . '?rt=' . $verify->random_token;
$appUrl = 'pixelfed://confirm-account/'.$user->app_register_token.'?rt='.$verify->random_token;
$this->line(' ');
$this->info('Magic link found! Copy the following link and send to user');
$this->line(' ');
@ -77,6 +82,7 @@ class UserRegistrationMagicLink extends Command
$this->info($appUrl);
$this->line(' ');
$this->line(' ');
return Command::SUCCESS;
}
}

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use Illuminate\Console\Command;
class UserShow extends Command
{
@ -39,20 +39,20 @@ class UserShow extends Command
public function handle()
{
$id = $this->argument('id');
if(ctype_digit($id) == true) {
if (ctype_digit($id) == true) {
$user = User::find($id);
} else {
$user = User::whereUsername($id)->first();
}
if(!$user) {
if (! $user) {
$this->error('Could not find any user with that username or id.');
exit;
}
$this->info('User ID: ' . $user->id);
$this->info('Username: ' . $user->username);
$this->info('Email: ' . $user->email);
$this->info('Joined: ' . $user->created_at->diffForHumans());
$this->info('Status Count: ' . $user->statuses()->count());
$this->info('User ID: '.$user->id);
$this->info('Username: '.$user->username);
$this->info('Email: '.$user->email);
$this->info('Joined: '.$user->created_at->diffForHumans());
$this->info('Status Count: '.$user->statuses()->count());
}
}

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use Illuminate\Console\Command;
class UserSuspend extends Command
{
@ -39,17 +39,17 @@ class UserSuspend extends Command
public function handle()
{
$id = $this->argument('id');
if(ctype_digit($id) == true) {
if (ctype_digit($id) == true) {
$user = User::find($id);
} else {
$user = User::whereUsername($id)->first();
}
if(!$user) {
if (! $user) {
$this->error('Could not find any user with that username or id.');
exit;
}
$this->info('Found user, username: ' . $user->username);
if($this->confirm('Are you sure you want to suspend this user?')) {
$this->info('Found user, username: '.$user->username);
if ($this->confirm('Are you sure you want to suspend this user?')) {
$profile = $user->profile;
$user->status = $profile->status = 'suspended';
$user->save();

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use Illuminate\Console\Command;
class UserTable extends Command
{

View File

@ -2,9 +2,9 @@
namespace App\Console\Commands;
use App\User;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\PromptsForMissingInput;
use App\User;
class UserToggle2FA extends Command implements PromptsForMissingInput
{
@ -41,13 +41,14 @@ class UserToggle2FA extends Command implements PromptsForMissingInput
{
$user = User::whereUsername($this->argument('username'))->first();
if(!$user) {
if (! $user) {
$this->error('Could not find any user with that username');
exit;
}
if(!$user->{'2fa_enabled'}) {
if (! $user->{'2fa_enabled'}) {
$this->info('User did not have 2FA enabled!');
return;
}

View File

@ -2,8 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\User;
use Illuminate\Console\Command;
class UserUnsuspend extends Command
{
@ -39,17 +39,17 @@ class UserUnsuspend extends Command
public function handle()
{
$id = $this->argument('id');
if(ctype_digit($id) == true) {
if (ctype_digit($id) == true) {
$user = User::find($id);
} else {
$user = User::whereUsername($id)->first();
}
if(!$user) {
if (! $user) {
$this->error('Could not find any user with that username or id.');
exit;
}
$this->info('Found user, username: ' . $user->username);
if($this->confirm('Are you sure you want to unsuspend this user?')) {
$this->info('Found user, username: '.$user->username);
if ($this->confirm('Are you sure you want to unsuspend this user?')) {
$profile = $user->profile;
$user->status = $profile->status = null;
$user->save();

View File

@ -2,9 +2,8 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
use App\User;
use Illuminate\Console\Command;
class UserVerifyEmail extends Command
{
@ -41,13 +40,14 @@ class UserVerifyEmail extends Command
{
$user = User::whereUsername($this->argument('username'))->first();
if(!$user) {
if (! $user) {
$this->error('Username not found');
return;
}
$user->email_verified_at = now();
$user->save();
$this->info('Successfully verified email address for ' . $user->username);
$this->info('Successfully verified email address for '.$user->username);
}
}

View File

@ -2,10 +2,9 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Jobs\VideoPipeline\VideoThumbnail as Pipeline;
use App\Media;
use App\Jobs\VideoPipeline\VideoThumbnail as Pipeline;
use Illuminate\Console\Command;
class VideoThumbnail extends Command
{
@ -42,10 +41,10 @@ class VideoThumbnail extends Command
{
$limit = 10;
$videos = Media::whereMime('video/mp4')
->whereNull('thumbnail_path')
->take($limit)
->get();
foreach($videos as $video) {
->whereNull('thumbnail_path')
->take($limit)
->get();
foreach ($videos as $video) {
Pipeline::dispatch($video);
}
}

View File

@ -19,7 +19,6 @@ class Kernel extends ConsoleKernel
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
*
* @return void
*/
@ -33,17 +32,17 @@ class Kernel extends ConsoleKernel
$schedule->command('gc:passwordreset')->dailyAt('09:41');
$schedule->command('gc:sessions')->twiceDaily(13, 23);
if(in_array(config_cache('pixelfed.cloud_storage'), ['1', true, 'true']) && config('media.delete_local_after_cloud')) {
if (in_array(config_cache('pixelfed.cloud_storage'), ['1', true, 'true']) && config('media.delete_local_after_cloud')) {
$schedule->command('media:s3gc')->hourlyAt(15);
}
if(config('import.instagram.enabled')) {
if (config('import.instagram.enabled')) {
$schedule->command('app:transform-imports')->everyTenMinutes();
$schedule->command('app:import-upload-garbage-collection')->hourlyAt(51);
$schedule->command('app:import-remove-deleted-accounts')->hourlyAt(37);
$schedule->command('app:import-upload-clean-storage')->twiceDailyAt(1, 13, 32);
if(config('import.instagram.storage.cloud.enabled') && (bool) config_cache('pixelfed.cloud_storage')) {
if (config('import.instagram.storage.cloud.enabled') && (bool) config_cache('pixelfed.cloud_storage')) {
$schedule->command('app:import-upload-media-to-cloud-storage')->hourlyAt(39);
}
}

View File

@ -8,11 +8,11 @@ class Contact extends Model
{
public function user()
{
return $this->belongsTo(User::class);
return $this->belongsTo(User::class);
}
public function adminUrl()
{
return url('/i/admin/messages/show/' . $this->id);
return url('/i/admin/messages/show/'.$this->id);
}
}

View File

@ -9,17 +9,17 @@ class DirectMessage extends Model
{
public function status()
{
return $this->belongsTo(Status::class, 'status_id', 'id');
return $this->belongsTo(Status::class, 'status_id', 'id');
}
public function url()
{
return config('app.url') . '/account/direct/m/' . $this->status_id;
return config('app.url').'/account/direct/m/'.$this->status_id;
}
public function author()
{
return $this->belongsTo(Profile::class, 'from_id', 'id');
return $this->belongsTo(Profile::class, 'from_id', 'id');
}
public function recipient()
@ -29,6 +29,6 @@ class DirectMessage extends Model
public function me()
{
return Auth::user()->profile->id === $this->from_id;
return Auth::user()->profile->id === $this->from_id;
}
}

View File

@ -3,7 +3,6 @@
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\{Status, StatusHashtag};
class DiscoverCategory extends Model
{
@ -11,22 +10,22 @@ class DiscoverCategory extends Model
public function media()
{
return $this->belongsTo(Media::class);
return $this->belongsTo(Media::class);
}
public function url()
{
return url('/discover/c/'.$this->slug);
return url('/discover/c/'.$this->slug);
}
public function editUrl()
{
return url('/i/admin/discover/category/edit/' . $this->id);
return url('/i/admin/discover/category/edit/'.$this->id);
}
public function thumb()
{
return $this->media->thumb();
return $this->media->thumb();
}
public function mediaUrl()
@ -34,31 +33,30 @@ class DiscoverCategory extends Model
return $this->media->url();
}
public function items()
{
return $this->hasMany(DiscoverCategoryHashtag::class, 'discover_category_id');
return $this->hasMany(DiscoverCategoryHashtag::class, 'discover_category_id');
}
public function hashtags()
{
return $this->hasManyThrough(
Hashtag::class,
DiscoverCategoryHashtag::class,
'discover_category_id',
'id',
'id',
'hashtag_id'
);
return $this->hasManyThrough(
Hashtag::class,
DiscoverCategoryHashtag::class,
'discover_category_id',
'id',
'id',
'hashtag_id'
);
}
public function posts()
{
return Status::select('*')
->join('status_hashtags', 'statuses.id', '=', 'status_hashtags.status_id')
->join('hashtags', 'status_hashtags.hashtag_id', '=', 'hashtags.id')
->join('discover_category_hashtags', 'hashtags.id', '=', 'discover_category_hashtags.hashtag_id')
->join('discover_categories', 'discover_category_hashtags.discover_category_id', '=', 'discover_categories.id')
->where('discover_categories.id', $this->id);
return Status::select('*')
->join('status_hashtags', 'statuses.id', '=', 'status_hashtags.status_id')
->join('hashtags', 'status_hashtags.hashtag_id', '=', 'hashtags.id')
->join('discover_category_hashtags', 'hashtags.id', '=', 'discover_category_hashtags.hashtag_id')
->join('discover_categories', 'discover_category_hashtags.discover_category_id', '=', 'discover_categories.id')
->where('discover_categories.id', $this->id);
}
}

View File

@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Model;
class DiscoverCategoryHashtag extends Model
{
protected $fillable = [
'discover_category_id',
'hashtag_id'
'discover_category_id',
'hashtag_id',
];
}

View File

@ -14,8 +14,8 @@ class EmailVerification extends Model
return "{$base}{$path}";
}
public function user()
{
return $this->belongsTo(User::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}

View File

@ -2,20 +2,19 @@
namespace App\Events\LiveStream;
use App\Models\LiveStream;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\LiveStream;
class BanUser implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $livestream;
public $profileId;
/**
@ -36,7 +35,7 @@ class BanUser implements ShouldBroadcast
*/
public function broadcastOn()
{
return new Channel('live.chat.' . $this->livestream->profile_id);
return new Channel('live.chat.'.$this->livestream->profile_id);
}
public function broadcastAs()

View File

@ -2,20 +2,19 @@
namespace App\Events\LiveStream;
use App\Models\LiveStream;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\LiveStream;
class DeleteChatComment implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $livestream;
public $chatmsg;
/**
@ -36,7 +35,7 @@ class DeleteChatComment implements ShouldBroadcast
*/
public function broadcastOn()
{
return new Channel('live.chat.' . $this->livestream->profile_id);
return new Channel('live.chat.'.$this->livestream->profile_id);
}
public function broadcastAs()

View File

@ -2,20 +2,19 @@
namespace App\Events\LiveStream;
use App\Models\LiveStream;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\LiveStream;
class NewChatComment implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $livestream;
public $chatmsg;
/**
@ -36,7 +35,7 @@ class NewChatComment implements ShouldBroadcast
*/
public function broadcastOn()
{
return new Channel('live.chat.' . $this->livestream->profile_id);
return new Channel('live.chat.'.$this->livestream->profile_id);
}
public function broadcastAs()

View File

@ -2,20 +2,19 @@
namespace App\Events\LiveStream;
use App\Models\LiveStream;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\LiveStream;
class PinChatMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $livestream;
public $chatmsg;
/**
@ -36,7 +35,7 @@ class PinChatMessage implements ShouldBroadcast
*/
public function broadcastOn()
{
return new Channel('live.chat.' . $this->livestream->profile_id);
return new Channel('live.chat.'.$this->livestream->profile_id);
}
public function broadcastAs()

View File

@ -4,8 +4,6 @@ namespace App\Events\LiveStream;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
@ -33,7 +31,7 @@ class StreamEnd implements ShouldBroadcast
*/
public function broadcastOn()
{
return new Channel('live.chat.' . $this->id);
return new Channel('live.chat.'.$this->id);
}
public function broadcastAs()
@ -43,6 +41,6 @@ class StreamEnd implements ShouldBroadcast
public function broadcastWith()
{
return ['ts' => time() ];
return ['ts' => time()];
}
}

View File

@ -4,8 +4,6 @@ namespace App\Events\LiveStream;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
@ -33,7 +31,7 @@ class StreamStart implements ShouldBroadcast
*/
public function broadcastOn()
{
return new Channel('live.chat.' . $this->id);
return new Channel('live.chat.'.$this->id);
}
public function broadcastAs()
@ -43,6 +41,6 @@ class StreamStart implements ShouldBroadcast
public function broadcastWith()
{
return ['ts' => time() ];
return ['ts' => time()];
}
}

View File

@ -2,20 +2,19 @@
namespace App\Events\LiveStream;
use App\Models\LiveStream;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Models\LiveStream;
class UnpinChatMessage implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $livestream;
public $chatmsg;
/**
@ -36,7 +35,7 @@ class UnpinChatMessage implements ShouldBroadcast
*/
public function broadcastOn()
{
return new Channel('live.chat.' . $this->livestream->profile_id);
return new Channel('live.chat.'.$this->livestream->profile_id);
}
public function broadcastAs()

View File

@ -2,20 +2,19 @@
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use App\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NewMention implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
protected $user;
protected $data;
/**
@ -36,7 +35,7 @@ class NewMention implements ShouldBroadcastNow
public function broadcastOn()
{
return new PrivateChannel('App.User.' . $this->user->id);
return new PrivateChannel('App.User.'.$this->user->id);
}
public function broadcastWith()

View File

@ -2,18 +2,14 @@
namespace App\Events\Notification;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use App\Status;
use App\Transformer\Api\StatusTransformer;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use League\Fractal;
use League\Fractal\Serializer\ArraySerializer;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
class NewPublicPost implements ShouldBroadcastNow
{
@ -45,8 +41,9 @@ class NewPublicPost implements ShouldBroadcastNow
{
$resource = new Fractal\Resource\Item($this->status, new StatusTransformer());
$res = $this->fractal->createData($resource)->toArray();
return [
'entity' => $res
'entity' => $res,
];
}

View File

@ -3,85 +3,84 @@
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
use League\OAuth2\Server\Exception\OAuthServerException;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport = [
OAuthServerException::class,
\Zttp\ConnectionException::class,
\GuzzleHttp\Exception\ConnectException::class,
\Illuminate\Http\Client\ConnectionException::class
];
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport = [
OAuthServerException::class,
\Zttp\ConnectionException::class,
\GuzzleHttp\Exception\ConnectException::class,
\Illuminate\Http\Client\ConnectionException::class,
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
/**
* Report or log an exception.
*
* @param \Exception $exception
*
* @return void
*/
public function report(Throwable $exception)
{
parent::report($exception);
}
/**
* Report or log an exception.
*
* @param \Exception $exception
* @return void
*/
public function report(Throwable $exception)
{
parent::report($exception);
}
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (\BadMethodCallException $e) {
return app()->environment() !== 'production';
});
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (\BadMethodCallException $e) {
return app()->environment() !== 'production';
});
$this->reportable(function (\Illuminate\Http\Client\ConnectionException $e) {
return app()->environment() !== 'production';
});
}
$this->reportable(function (\Illuminate\Http\Client\ConnectionException $e) {
return app()->environment() !== 'production';
});
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
*
* @return \Illuminate\Http\Response
*/
public function render($request, Throwable $exception)
{
if ($exception instanceof \Illuminate\Validation\ValidationException && $request->wantsJson()) {
return response()->json(
[
'message' => $exception->getMessage(),
'errors' => $exception->validator->getMessageBag()
],
method_exists($exception, 'getStatusCode') ? $exception->getStatusCode() : 500
);
} else if ($request->wantsJson()) {
return response()->json(
['error' => $exception->getMessage()],
method_exists($exception, 'getStatusCode') ? $exception->getStatusCode() : 500
);
}
return parent::render($request, $exception);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Throwable $exception)
{
if ($exception instanceof \Illuminate\Validation\ValidationException && $request->wantsJson()) {
return response()->json(
[
'message' => $exception->getMessage(),
'errors' => $exception->validator->getMessageBag(),
],
method_exists($exception, 'getStatusCode') ? $exception->getStatusCode() : 500
);
} elseif ($request->wantsJson()) {
return response()->json(
['error' => $exception->getMessage()],
method_exists($exception, 'getStatusCode') ? $exception->getStatusCode() : 500
);
}
return parent::render($request, $exception);
}
}

View File

@ -2,18 +2,19 @@
namespace App;
use Illuminate\Database\Eloquent\Model;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
class FailedJob extends Model
{
const CREATED_AT = 'failed_at';
const UPDATED_AT = 'failed_at';
public $timestamps = 'failed_at';
public function getFailedAtAttribute($val)
{
return Carbon::parse($val);
return Carbon::parse($val);
}
}
}

View File

@ -6,17 +6,17 @@ use Illuminate\Database\Eloquent\Model;
class FollowRequest extends Model
{
protected $fillable = ['follower_id', 'following_id', 'activity', 'handled_at'];
protected $fillable = ['follower_id', 'following_id', 'activity', 'handled_at'];
protected $casts = [
'activity' => 'array',
];
protected $casts = [
'activity' => 'array',
];
public function actor()
{
return $this->belongsTo(Profile::class, 'follower_id', 'id');
}
public function follower()
{
return $this->belongsTo(Profile::class, 'follower_id', 'id');
@ -35,6 +35,7 @@ class FollowRequest extends Model
public function permalink($append = null, $namespace = '#accepts')
{
$path = $this->target->permalink("{$namespace}/follows/{$this->id}{$append}");
return url($path);
}
}

View File

@ -6,10 +6,10 @@ use Illuminate\Database\Eloquent\Model;
class Follower extends Model
{
protected $fillable = ['profile_id', 'following_id', 'local_profile'];
const MAX_FOLLOWING = 7500;
const FOLLOW_PER_HOUR = 150;
public function actor()
@ -30,6 +30,7 @@ class Follower extends Model
public function permalink($append = null)
{
$path = $this->actor->permalink("#accepts/follows/{$this->id}{$append}");
return url($path);
}
}

View File

@ -6,14 +6,14 @@ use App\Services\SnowflakeService;
trait HasSnowflakePrimary
{
public static function bootHasSnowflakePrimary()
{
static::saving(function ($model) {
if (is_null($model->getKey())) {
$keyName = $model->getKeyName();
$id = SnowflakeService::next();
$model->setAttribute($keyName, $id);
}
});
}
public static function bootHasSnowflakePrimary()
{
static::saving(function ($model) {
if (is_null($model->getKey())) {
$keyName = $model->getKeyName();
$id = SnowflakeService::next();
$model->setAttribute($keyName, $id);
}
});
}
}

View File

@ -11,13 +11,13 @@ class Hashtag extends Model
public function posts()
{
return $this->hasManyThrough(
Status::class,
StatusHashtag::class,
'hashtag_id',
'id',
'id',
'status_id'
);
Status::class,
StatusHashtag::class,
'hashtag_id',
'id',
'id',
'status_id'
);
}
public function url($suffix = '')

View File

@ -7,15 +7,15 @@ use Illuminate\Database\Eloquent\Model;
class HashtagFollow extends Model
{
protected $fillable = [
'user_id',
'profile_id',
'hashtag_id'
'user_id',
'profile_id',
'hashtag_id',
];
const MAX_LIMIT = 250;
public function hashtag()
{
return $this->belongsTo(Hashtag::class);
return $this->belongsTo(Hashtag::class);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -2,35 +2,36 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Status;
use App\AccountInterstitial;
use App\Status;
use Illuminate\Http\Request;
class AccountInterstitialController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function __construct()
{
$this->middleware('auth');
}
public function get(Request $request)
{
$interstitial = $request->user()
$interstitial = $request->user()
->interstitials()
->whereNull('read_at')
->first();
if(!$interstitial) {
if (! $interstitial) {
$user = $request->user();
$user->has_interstitial = false;
$user->save();
return redirect('/');
}
$meta = json_decode($interstitial->meta);
$view = $interstitial->view;
return view($view, compact('interstitial', 'meta'));
return view($view, compact('interstitial', 'meta'));
}
public function read(Request $request)
@ -39,7 +40,7 @@ class AccountInterstitialController extends Controller
'id' => 'required',
'type' => 'required|in:post.cw,post.removed,post.unlist,post.autospam',
'action' => 'required|in:appeal,confirm',
'appeal_message' => 'nullable|max:500'
'appeal_message' => 'nullable|max:500',
]);
$redirect = '/';
@ -52,7 +53,7 @@ class AccountInterstitialController extends Controller
->whereType($request->input('type'))
->findOrFail($id);
if($action == 'appeal') {
if ($action == 'appeal') {
$ai->appeal_requested_at = now();
$ai->appeal_message = $request->input('appeal_message');
}
@ -64,12 +65,12 @@ class AccountInterstitialController extends Controller
->whereNull('read_at')
->exists();
if(!$more) {
if (! $more) {
$user->has_interstitial = false;
$user->save();
}
if(in_array($ai->type, ['post.cw', 'post.unlist'])) {
if (in_array($ai->type, ['post.cw', 'post.unlist'])) {
$redirect = Status::findOrFail($ai->item_id)->url();
}

View File

@ -2,140 +2,121 @@
namespace App\Http\Controllers\Admin;
use DB, Cache;
use App\{
AccountInterstitial,
DiscoverCategory,
DiscoverCategoryHashtag,
Hashtag,
Media,
Profile,
Status,
StatusHashtag,
User
};
use App\Models\ConfigCache;
use App\Models\AutospamCustomTokens;
use App\Services\AccountService;
use App\Services\ConfigCacheService;
use App\Services\StatusService;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use League\ISO3166\ISO3166;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Http;
use App\Http\Controllers\PixelfedDirectoryController;
use \DateInterval;
use \DatePeriod;
use App\AccountInterstitial;
use App\Http\Resources\AdminSpamReport;
use App\Util\Lexer\Classifier;
use App\Jobs\AutospamPipeline\AutospamPretrainPipeline;
use App\Jobs\AutospamPipeline\AutospamPretrainNonSpamPipeline;
use App\Jobs\AutospamPipeline\AutospamPretrainPipeline;
use App\Jobs\AutospamPipeline\AutospamUpdateCachedDataPipeline;
use Illuminate\Support\Facades\URL;
use App\Models\AutospamCustomTokens;
use App\Profile;
use App\Services\AccountService;
use App\Services\AutospamService;
use App\Services\ConfigCacheService;
use Cache;
use DB;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
trait AdminAutospamController
{
public function autospamHome(Request $request)
{
return view('admin.autospam.home');
}
public function autospamHome(Request $request)
{
return view('admin.autospam.home');
}
public function getAutospamConfigApi(Request $request)
{
$open = Cache::remember('admin-dash:reports:spam-count', 3600, function() {
return AccountInterstitial::whereType('post.autospam')->whereNull('appeal_handled_at')->count();
});
public function getAutospamConfigApi(Request $request)
{
$open = Cache::remember('admin-dash:reports:spam-count', 3600, function () {
return AccountInterstitial::whereType('post.autospam')->whereNull('appeal_handled_at')->count();
});
$closed = Cache::remember('admin-dash:reports:spam-count-closed', 3600, function() {
return AccountInterstitial::whereType('post.autospam')->whereNotNull('appeal_handled_at')->count();
});
$closed = Cache::remember('admin-dash:reports:spam-count-closed', 3600, function () {
return AccountInterstitial::whereType('post.autospam')->whereNotNull('appeal_handled_at')->count();
});
$thisWeek = Cache::remember('admin-dash:reports:spam-count-stats-this-week ', 86400, function() {
$sr = config('database.default') == 'pgsql' ? "to_char(created_at, 'MM-YYYY')" : "DATE_FORMAT(created_at, '%m-%Y')";
$gb = config('database.default') == 'pgsql' ? [DB::raw($sr)] : DB::raw($sr);
$s = AccountInterstitial::select(
DB::raw('count(id) as count'),
DB::raw($sr . " as month_year")
)
->where('created_at', '>=', now()->subWeeks(52))
->groupBy($gb)
->get()
->map(function($s) {
$dt = now()->parse('01-' . $s->month_year);
return [
'id' => $dt->format('Ym'),
'x' => $dt->format('M Y'),
'y' => $s->count
];
})
->sortBy('id')
->values()
->toArray();
return $s;
});
$thisWeek = Cache::remember('admin-dash:reports:spam-count-stats-this-week ', 86400, function () {
$sr = config('database.default') == 'pgsql' ? "to_char(created_at, 'MM-YYYY')" : "DATE_FORMAT(created_at, '%m-%Y')";
$gb = config('database.default') == 'pgsql' ? [DB::raw($sr)] : DB::raw($sr);
$s = AccountInterstitial::select(
DB::raw('count(id) as count'),
DB::raw($sr.' as month_year')
)
->where('created_at', '>=', now()->subWeeks(52))
->groupBy($gb)
->get()
->map(function ($s) {
$dt = now()->parse('01-'.$s->month_year);
$files = [
'spam' => [
'exists' => Storage::exists(AutospamService::MODEL_SPAM_PATH),
'size' => 0
],
'ham' => [
'exists' => Storage::exists(AutospamService::MODEL_HAM_PATH),
'size' => 0
],
'combined' => [
'exists' => Storage::exists(AutospamService::MODEL_FILE_PATH),
'size' => 0
]
];
return [
'id' => $dt->format('Ym'),
'x' => $dt->format('M Y'),
'y' => $s->count,
];
})
->sortBy('id')
->values()
->toArray();
if($files['spam']['exists']) {
$files['spam']['size'] = Storage::size(AutospamService::MODEL_SPAM_PATH);
}
return $s;
});
if($files['ham']['exists']) {
$files['ham']['size'] = Storage::size(AutospamService::MODEL_HAM_PATH);
}
$files = [
'spam' => [
'exists' => Storage::exists(AutospamService::MODEL_SPAM_PATH),
'size' => 0,
],
'ham' => [
'exists' => Storage::exists(AutospamService::MODEL_HAM_PATH),
'size' => 0,
],
'combined' => [
'exists' => Storage::exists(AutospamService::MODEL_FILE_PATH),
'size' => 0,
],
];
if($files['combined']['exists']) {
$files['combined']['size'] = Storage::size(AutospamService::MODEL_FILE_PATH);
}
if ($files['spam']['exists']) {
$files['spam']['size'] = Storage::size(AutospamService::MODEL_SPAM_PATH);
}
return [
'autospam_enabled' => (bool) config_cache('pixelfed.bouncer.enabled') ?? false,
'nlp_enabled' => (bool) AutospamService::active(),
'files' => $files,
'open' => $open,
'closed' => $closed,
'graph' => collect($thisWeek)->map(fn($s) => $s['y'])->values(),
'graphLabels' => collect($thisWeek)->map(fn($s) => $s['x'])->values()
];
}
if ($files['ham']['exists']) {
$files['ham']['size'] = Storage::size(AutospamService::MODEL_HAM_PATH);
}
if ($files['combined']['exists']) {
$files['combined']['size'] = Storage::size(AutospamService::MODEL_FILE_PATH);
}
return [
'autospam_enabled' => (bool) config_cache('pixelfed.bouncer.enabled') ?? false,
'nlp_enabled' => (bool) AutospamService::active(),
'files' => $files,
'open' => $open,
'closed' => $closed,
'graph' => collect($thisWeek)->map(fn ($s) => $s['y'])->values(),
'graphLabels' => collect($thisWeek)->map(fn ($s) => $s['x'])->values(),
];
}
public function getAutospamReportsClosedApi(Request $request)
{
$appeals = AdminSpamReport::collection(
AccountInterstitial::orderBy('id', 'desc')
->whereType('post.autospam')
->whereIsSpam(true)
->whereNotNull('appeal_handled_at')
->cursorPaginate(6)
->withQueryString()
);
$appeals = AdminSpamReport::collection(
AccountInterstitial::orderBy('id', 'desc')
->whereType('post.autospam')
->whereIsSpam(true)
->whereNotNull('appeal_handled_at')
->cursorPaginate(6)
->withQueryString()
);
return $appeals;
return $appeals;
}
public function postAutospamTrainSpamApi(Request $request)
{
$aiCount = AccountInterstitial::whereItemType('App\Status')
->whereIsSpam(true)
->count();
$aiCount = AccountInterstitial::whereItemType('App\Status')
->whereIsSpam(true)
->count();
abort_if($aiCount < 100, 422, 'You don\'t have enough data to pre-train against.');
$existing = Cache::get('pf:admin:autospam:pretrain:recent');
@ -144,112 +125,121 @@ trait AdminAutospamController
Cache::put('pf:admin:autospam:pretrain:recent', 1, 1440);
return [
'msg' => 'Success!'
'msg' => 'Success!',
];
}
public function postAutospamTrainNonSpamSearchApi(Request $request)
{
$this->validate($request, [
'q' => 'required|string|min:1'
]);
$this->validate($request, [
'q' => 'required|string|min:1',
]);
$q = $request->input('q');
$q = $request->input('q');
$res = Profile::whereNull(['status', 'domain'])
->where('username', 'like', '%' . $q . '%')
->orderByDesc('followers_count')
->take(10)
->get()
->map(function($p) {
$acct = AccountService::get($p->id, true);
return [
'id' => (string) $p->id,
'avatar' => $acct['avatar'],
'username' => $p->username
];
})
->values();
return $res;
$res = Profile::whereNull(['status', 'domain'])
->where('username', 'like', '%'.$q.'%')
->orderByDesc('followers_count')
->take(10)
->get()
->map(function ($p) {
$acct = AccountService::get($p->id, true);
return [
'id' => (string) $p->id,
'avatar' => $acct['avatar'],
'username' => $p->username,
];
})
->values();
return $res;
}
public function postAutospamTrainNonSpamSubmitApi(Request $request)
{
$this->validate($request, [
'accounts' => 'required|array|min:1|max:10'
]);
$this->validate($request, [
'accounts' => 'required|array|min:1|max:10',
]);
$accts = $request->input('accounts');
$accts = $request->input('accounts');
$accounts = Profile::whereNull(['domain', 'status'])->find(collect($accts)->map(function($a) { return $a['id'];}));
$accounts = Profile::whereNull(['domain', 'status'])->find(collect($accts)->map(function ($a) {
return $a['id'];
}));
abort_if(!$accounts || !$accounts->count(), 422, 'One or more of the selected accounts are not valid');
abort_if(! $accounts || ! $accounts->count(), 422, 'One or more of the selected accounts are not valid');
AutospamPretrainNonSpamPipeline::dispatch($accounts);
return $accounts;
AutospamPretrainNonSpamPipeline::dispatch($accounts);
return $accounts;
}
public function getAutospamCustomTokensApi(Request $request)
{
return AutospamCustomTokens::latest()->cursorPaginate(6);
return AutospamCustomTokens::latest()->cursorPaginate(6);
}
public function saveNewAutospamCustomTokensApi(Request $request)
{
$this->validate($request, [
'token' => 'required|unique:autospam_custom_tokens,token',
]);
$this->validate($request, [
'token' => 'required|unique:autospam_custom_tokens,token',
]);
$ct = new AutospamCustomTokens;
$ct->token = $request->input('token');
$ct->weight = $request->input('weight');
$ct->category = $request->input('category') === 'spam' ? 'spam' : 'ham';
$ct->note = $request->input('note');
$ct->active = $request->input('active');
$ct->save();
$ct = new AutospamCustomTokens;
$ct->token = $request->input('token');
$ct->weight = $request->input('weight');
$ct->category = $request->input('category') === 'spam' ? 'spam' : 'ham';
$ct->note = $request->input('note');
$ct->active = $request->input('active');
$ct->save();
AutospamUpdateCachedDataPipeline::dispatch();
return $ct;
AutospamUpdateCachedDataPipeline::dispatch();
return $ct;
}
public function updateAutospamCustomTokensApi(Request $request)
{
$this->validate($request, [
'id' => 'required',
'token' => 'required',
'category' => 'required|in:spam,ham',
'active' => 'required|boolean'
]);
$this->validate($request, [
'id' => 'required',
'token' => 'required',
'category' => 'required|in:spam,ham',
'active' => 'required|boolean',
]);
$ct = AutospamCustomTokens::findOrFail($request->input('id'));
$ct->weight = $request->input('weight');
$ct->category = $request->input('category');
$ct->note = $request->input('note');
$ct->active = $request->input('active');
$ct->save();
$ct = AutospamCustomTokens::findOrFail($request->input('id'));
$ct->weight = $request->input('weight');
$ct->category = $request->input('category');
$ct->note = $request->input('note');
$ct->active = $request->input('active');
$ct->save();
AutospamUpdateCachedDataPipeline::dispatch();
AutospamUpdateCachedDataPipeline::dispatch();
return $ct;
return $ct;
}
public function exportAutospamCustomTokensApi(Request $request)
{
abort_if(!Storage::exists(AutospamService::MODEL_SPAM_PATH), 422, 'Autospam Dataset does not exist, please train spam before attempting to export');
return Storage::download(AutospamService::MODEL_SPAM_PATH);
abort_if(! Storage::exists(AutospamService::MODEL_SPAM_PATH), 422, 'Autospam Dataset does not exist, please train spam before attempting to export');
return Storage::download(AutospamService::MODEL_SPAM_PATH);
}
public function enableAutospamApi(Request $request)
{
ConfigCacheService::put('autospam.nlp.enabled', true);
Cache::forget(AutospamService::CHCKD_CACHE_KEY);
return ['msg' => 'Success'];
ConfigCacheService::put('autospam.nlp.enabled', true);
Cache::forget(AutospamService::CHCKD_CACHE_KEY);
return ['msg' => 'Success'];
}
public function disableAutospamApi(Request $request)
{
ConfigCacheService::put('autospam.nlp.enabled', false);
Cache::forget(AutospamService::CHCKD_CACHE_KEY);
return ['msg' => 'Success'];
ConfigCacheService::put('autospam.nlp.enabled', false);
Cache::forget(AutospamService::CHCKD_CACHE_KEY);
return ['msg' => 'Success'];
}
}

View File

@ -2,30 +2,20 @@
namespace App\Http\Controllers\Admin;
use DB, Cache;
use App\{
DiscoverCategory,
DiscoverCategoryHashtag,
Hashtag,
Media,
Profile,
Status,
StatusHashtag,
User
};
use App\Http\Controllers\PixelfedDirectoryController;
use App\Models\ConfigCache;
use App\Services\AccountService;
use App\Services\ConfigCacheService;
use App\Services\StatusService;
use Carbon\Carbon;
use App\Status;
use App\User;
use Cache;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use League\ISO3166\ISO3166;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Http;
use App\Http\Controllers\PixelfedDirectoryController;
use Illuminate\Support\Str;
use League\ISO3166\ISO3166;
trait AdminDirectoryController
{
@ -41,37 +31,37 @@ trait AdminDirectoryController
$res['countries'] = collect((new ISO3166)->all())->pluck('name');
$res['admins'] = User::whereIsAdmin(true)
->where('2fa_enabled', true)
->get()->map(function($user) {
return [
'uid' => (string) $user->id,
'pid' => (string) $user->profile_id,
'username' => $user->username,
'created_at' => $user->created_at
];
});
->get()->map(function ($user) {
return [
'uid' => (string) $user->id,
'pid' => (string) $user->profile_id,
'username' => $user->username,
'created_at' => $user->created_at,
];
});
$config = ConfigCache::whereK('pixelfed.directory')->first();
if($config) {
if ($config) {
$data = $config->v ? json_decode($config->v, true) : [];
$res = array_merge($res, $data);
}
if(empty($res['summary'])) {
if (empty($res['summary'])) {
$summary = ConfigCache::whereK('app.short_description')->pluck('v');
$res['summary'] = $summary ? $summary[0] : null;
}
if(isset($res['banner_image']) && !empty($res['banner_image'])) {
if (isset($res['banner_image']) && ! empty($res['banner_image'])) {
$res['banner_image'] = url(Storage::url($res['banner_image']));
}
if(isset($res['favourite_posts'])) {
$res['favourite_posts'] = collect($res['favourite_posts'])->map(function($id) {
if (isset($res['favourite_posts'])) {
$res['favourite_posts'] = collect($res['favourite_posts'])->map(function ($id) {
return StatusService::get($id);
})
->filter(function($post) {
return $post && isset($post['account']);
})
->values();
->filter(function ($post) {
return $post && isset($post['account']);
})
->values();
}
$res['community_guidelines'] = config_cache('app.rules') ? json_decode(config_cache('app.rules'), true) : [];
@ -93,12 +83,12 @@ trait AdminDirectoryController
'account_deletion' => config_cache('pixelfed.account_deletion'),
];
if(config_cache('pixelfed.directory.testimonials')) {
$testimonials = collect(json_decode(config_cache('pixelfed.directory.testimonials'),true))
->map(function($t) {
if (config_cache('pixelfed.directory.testimonials')) {
$testimonials = collect(json_decode(config_cache('pixelfed.directory.testimonials'), true))
->map(function ($t) {
return [
'profile' => AccountService::get($t['profile_id']),
'body' => $t['body']
'body' => $t['body'],
];
});
$res['testimonials'] = $testimonials;
@ -107,8 +97,8 @@ trait AdminDirectoryController
$validator = Validator::make($res['feature_config'], [
'media_types' => [
'required',
function ($attribute, $value, $fail) {
if (!in_array('image/jpeg', $value->toArray()) || !in_array('image/png', $value->toArray())) {
function ($attribute, $value, $fail) {
if (! in_array('image/jpeg', $value->toArray()) || ! in_array('image/png', $value->toArray())) {
$fail('You must enable image/jpeg and image/png support.');
}
},
@ -119,7 +109,7 @@ trait AdminDirectoryController
'max_account_size' => 'required_if:enforce_account_limit,true|integer|min:1000000',
'max_album_length' => 'required|integer|min:4|max:20',
'account_deletion' => 'required|accepted',
'max_caption_length' => 'required|integer|min:500|max:10000'
'max_caption_length' => 'required|integer|min:500|max:10000',
]);
$res['requirements_validator'] = $validator->errors();
@ -145,11 +135,11 @@ trait AdminDirectoryController
foreach (new \DirectoryIterator($path) as $io) {
$name = $io->getFilename();
$skip = ['vendor'];
if($io->isDot() || in_array($name, $skip)) {
if ($io->isDot() || in_array($name, $skip)) {
continue;
}
if($io->isDir()) {
if ($io->isDir()) {
$langs->push(['code' => $name, 'name' => locale_get_display_name($name)]);
}
}
@ -158,25 +148,26 @@ trait AdminDirectoryController
$res['primary_locale'] = config('app.locale');
$submissionState = Http::withoutVerifying()
->post('https://pixelfed.org/api/v1/directory/check-submission', [
'domain' => config('pixelfed.domain.app')
]);
->post('https://pixelfed.org/api/v1/directory/check-submission', [
'domain' => config('pixelfed.domain.app'),
]);
$res['submission_state'] = $submissionState->json();
return $res;
}
protected function validVal($res, $val, $count = false, $minLen = false)
{
if(!isset($res[$val])) {
if (! isset($res[$val])) {
return false;
}
if($count) {
if ($count) {
return count($res[$val]) >= $count;
}
if($minLen) {
if ($minLen) {
return strlen($res[$val]) >= $minLen;
}
@ -193,11 +184,11 @@ trait AdminDirectoryController
'favourite_posts' => 'array|max:12',
'favourite_posts.*' => 'distinct',
'privacy_pledge' => 'sometimes',
'banner_image' => 'sometimes|mimes:jpg,png|dimensions:width=1920,height:1080|max:5000'
'banner_image' => 'sometimes|mimes:jpg,png|dimensions:width=1920,height:1080|max:5000',
]);
$config = ConfigCache::firstOrNew([
'k' => 'pixelfed.directory'
'k' => 'pixelfed.directory',
]);
$res = $config->v ? json_decode($config->v, true) : [];
@ -207,26 +198,27 @@ trait AdminDirectoryController
$res['contact_email'] = $request->input('contact_email');
$res['privacy_pledge'] = (bool) $request->input('privacy_pledge');
if($request->filled('location')) {
if ($request->filled('location')) {
$exists = (new ISO3166)->name($request->location);
if($exists) {
if ($exists) {
$res['location'] = $request->input('location');
}
}
if($request->hasFile('banner_image')) {
if ($request->hasFile('banner_image')) {
collect(Storage::files('public/headers'))
->filter(function($name) {
$protected = [
'public/headers/.gitignore',
'public/headers/default.jpg',
'public/headers/missing.png'
];
return !in_array($name, $protected);
})
->each(function($name) {
Storage::delete($name);
});
->filter(function ($name) {
$protected = [
'public/headers/.gitignore',
'public/headers/default.jpg',
'public/headers/missing.png',
];
return ! in_array($name, $protected);
})
->each(function ($name) {
Storage::delete($name);
});
$path = $request->file('banner_image')->store('public/headers');
$res['banner_image'] = $path;
ConfigCacheService::put('app.banner_image', url(Storage::url($path)));
@ -239,9 +231,10 @@ trait AdminDirectoryController
ConfigCacheService::put('pixelfed.directory', $config->v);
$updated = json_decode($config->v, true);
if(isset($updated['banner_image'])) {
if (isset($updated['banner_image'])) {
$updated['banner_image'] = url(Storage::url($updated['banner_image']));
}
return $updated;
}
@ -270,8 +263,8 @@ trait AdminDirectoryController
'oauth_enabled' => 'required|accepted',
'media_types' => [
'required',
function ($attribute, $value, $fail) {
if (!in_array('image/jpeg', $value->toArray()) || !in_array('image/png', $value->toArray())) {
function ($attribute, $value, $fail) {
if (! in_array('image/jpeg', $value->toArray()) || ! in_array('image/png', $value->toArray())) {
$fail('You must enable image/jpeg and image/png support.');
}
},
@ -282,10 +275,10 @@ trait AdminDirectoryController
'max_account_size' => 'required_if:enforce_account_limit,true|integer|min:1000000',
'max_album_length' => 'required|integer|min:4|max:20',
'account_deletion' => 'required|accepted',
'max_caption_length' => 'required|integer|min:500|max:10000'
'max_caption_length' => 'required|integer|min:500|max:10000',
]);
if(!$validator->validate()) {
if (! $validator->validate()) {
return response()->json($validator->errors(), 422);
}
@ -294,6 +287,7 @@ trait AdminDirectoryController
$data = (new PixelfedDirectoryController())->buildListing();
$res = Http::withoutVerifying()->post('https://pixelfed.org/api/v1/directory/submission', $data);
return 200;
}
@ -301,7 +295,7 @@ trait AdminDirectoryController
{
$bannerImage = ConfigCache::whereK('app.banner_image')->first();
$directory = ConfigCache::whereK('pixelfed.directory')->first();
if(!$bannerImage && !$directory || empty($directory->v)) {
if (! $bannerImage && ! $directory || empty($directory->v)) {
return;
}
$directoryArr = json_decode($directory->v, true);
@ -309,12 +303,12 @@ trait AdminDirectoryController
$protected = [
'public/headers/.gitignore',
'public/headers/default.jpg',
'public/headers/missing.png'
'public/headers/missing.png',
];
if(!$path || in_array($path, $protected)) {
if (! $path || in_array($path, $protected)) {
return;
}
if(Storage::exists($directoryArr['banner_image'])) {
if (Storage::exists($directoryArr['banner_image'])) {
Storage::delete($directoryArr['banner_image']);
}
@ -325,12 +319,13 @@ trait AdminDirectoryController
$bannerImage->save();
Cache::forget('api:v1:instance-data-response-v1');
ConfigCacheService::put('pixelfed.directory', $directory);
return $bannerImage->v;
}
public function directoryGetPopularPosts(Request $request)
{
$ids = Cache::remember('admin:api:popular_posts', 86400, function() {
$ids = Cache::remember('admin:api:popular_posts', 86400, function () {
return Status::whereLocal(true)
->whereScope('public')
->whereType('photo')
@ -340,21 +335,21 @@ trait AdminDirectoryController
->pluck('id');
});
$res = $ids->map(function($id) {
$res = $ids->map(function ($id) {
return StatusService::get($id);
})
->filter(function($post) {
return $post && isset($post['account']);
})
->values();
->filter(function ($post) {
return $post && isset($post['account']);
})
->values();
return response()->json($res, 200, [], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
return response()->json($res, 200, [], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
public function directoryGetAddPostByIdSearch(Request $request)
{
$this->validate($request, [
'q' => 'required|integer'
'q' => 'required|integer',
]);
$id = $request->input('q');
@ -377,11 +372,12 @@ trait AdminDirectoryController
$profile_id = $request->input('profile_id');
$testimonials = ConfigCache::whereK('pixelfed.directory.testimonials')->firstOrFail();
$existing = collect(json_decode($testimonials->v, true))
->filter(function($t) use($profile_id) {
->filter(function ($t) use ($profile_id) {
return $t['profile_id'] !== $profile_id;
})
->values();
ConfigCacheService::put('pixelfed.directory.testimonials', $existing);
return $existing;
}
@ -389,13 +385,13 @@ trait AdminDirectoryController
{
$this->validate($request, [
'username' => 'required',
'body' => 'required|string|min:5|max:500'
'body' => 'required|string|min:5|max:500',
]);
$user = User::whereUsername($request->input('username'))->whereNull('status')->firstOrFail();
$configCache = ConfigCache::firstOrCreate([
'k' => 'pixelfed.directory.testimonials'
'k' => 'pixelfed.directory.testimonials',
]);
$testimonials = $configCache->v ? collect(json_decode($configCache->v, true)) : collect([]);
@ -406,7 +402,7 @@ trait AdminDirectoryController
$testimonials->push([
'profile_id' => (string) $user->profile_id,
'username' => $request->input('username'),
'body' => $request->input('body')
'body' => $request->input('body'),
]);
$configCache->v = json_encode($testimonials->toArray());
@ -414,8 +410,9 @@ trait AdminDirectoryController
ConfigCacheService::put('pixelfed.directory.testimonials', $configCache->v);
$res = [
'profile' => AccountService::get($user->profile_id),
'body' => $request->input('body')
'body' => $request->input('body'),
];
return $res;
}
@ -423,7 +420,7 @@ trait AdminDirectoryController
{
$this->validate($request, [
'profile_id' => 'required',
'body' => 'required|string|min:5|max:500'
'body' => 'required|string|min:5|max:500',
]);
$profile_id = $request->input('profile_id');
@ -431,18 +428,19 @@ trait AdminDirectoryController
$user = User::whereProfileId($profile_id)->firstOrFail();
$configCache = ConfigCache::firstOrCreate([
'k' => 'pixelfed.directory.testimonials'
'k' => 'pixelfed.directory.testimonials',
]);
$testimonials = $configCache->v ? collect(json_decode($configCache->v, true)) : collect([]);
$updated = $testimonials->map(function($t) use($profile_id, $body) {
if($t['profile_id'] == $profile_id) {
$updated = $testimonials->map(function ($t) use ($profile_id, $body) {
if ($t['profile_id'] == $profile_id) {
$t['body'] = $body;
}
return $t;
})
->values();
->values();
$configCache->v = json_encode($updated);
$configCache->save();

View File

@ -2,104 +2,102 @@
namespace App\Http\Controllers\Admin;
use DB, Cache;
use App\{
DiscoverCategory,
DiscoverCategoryHashtag,
Hashtag,
Media,
Profile,
StatusHashtag
};
use Carbon\Carbon;
use App\DiscoverCategory;
use App\DiscoverCategoryHashtag;
use App\Hashtag;
use App\Media;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
trait AdminDiscoverController
{
public function discoverHome()
{
$categories = DiscoverCategory::orderByDesc('id')->paginate(10);
return view('admin.discover.home', compact('categories'));
}
public function discoverHome()
{
$categories = DiscoverCategory::orderByDesc('id')->paginate(10);
public function discoverCreateCategory()
{
return view('admin.discover.create-category');
}
return view('admin.discover.home', compact('categories'));
}
public function discoverCreateCategoryStore(Request $request)
{
$this->validate($request, [
'name' => 'required|string|min:1',
'active' => 'required|boolean',
'media' => 'nullable|integer|min:1'
]);
public function discoverCreateCategory()
{
return view('admin.discover.create-category');
}
$name = $request->input('name');
$slug = str_slug($name);
$active = $request->input('active');
$media = (int) $request->input('media');
public function discoverCreateCategoryStore(Request $request)
{
$this->validate($request, [
'name' => 'required|string|min:1',
'active' => 'required|boolean',
'media' => 'nullable|integer|min:1',
]);
$media = Media::findOrFail($media);
$name = $request->input('name');
$slug = str_slug($name);
$active = $request->input('active');
$media = (int) $request->input('media');
$category = DiscoverCategory::firstOrNew(['slug' => $slug]);
$category->name = $name;
$category->active = $active;
$category->media_id = $media->id;
$category->save();
return $category;
}
$media = Media::findOrFail($media);
public function discoverCategoryEdit(Request $request, $id)
{
$category = DiscoverCategory::findOrFail($id);
return view('admin.discover.show', compact('category'));
}
$category = DiscoverCategory::firstOrNew(['slug' => $slug]);
$category->name = $name;
$category->active = $active;
$category->media_id = $media->id;
$category->save();
public function discoverCategoryUpdate(Request $request, $id)
{
$this->validate($request, [
'name' => 'required|string|min:1',
'active' => 'required|boolean',
'media' => 'nullable|integer|min:1',
'hashtags' => 'nullable|string'
]);
$name = $request->input('name');
$slug = str_slug($name);
$active = $request->input('active');
$media = (int) $request->input('media');
$media = Media::findOrFail($media);
return $category;
}
$category = DiscoverCategory::findOrFail($id);
$category->name = $name;
$category->active = $active;
$category->media_id = $media->id;
$category->save();
public function discoverCategoryEdit(Request $request, $id)
{
$category = DiscoverCategory::findOrFail($id);
return $category;
}
return view('admin.discover.show', compact('category'));
}
public function discoveryCategoryTagStore(Request $request)
{
$this->validate($request, [
'category_id' => 'required|integer|min:1',
'hashtag' => 'required|string',
'action' => 'required|string|min:1|max:6'
]);
$category_id = $request->input('category_id');
$category = DiscoverCategory::findOrFail($category_id);
$hashtag = Hashtag::whereName($request->input('hashtag'))->firstOrFail();
public function discoverCategoryUpdate(Request $request, $id)
{
$this->validate($request, [
'name' => 'required|string|min:1',
'active' => 'required|boolean',
'media' => 'nullable|integer|min:1',
'hashtags' => 'nullable|string',
]);
$name = $request->input('name');
$slug = str_slug($name);
$active = $request->input('active');
$media = (int) $request->input('media');
$media = Media::findOrFail($media);
$tag = DiscoverCategoryHashtag::firstOrCreate([
'hashtag_id' => $hashtag->id,
'discover_category_id' => $category->id
]);
$category = DiscoverCategory::findOrFail($id);
$category->name = $name;
$category->active = $active;
$category->media_id = $media->id;
$category->save();
if($request->input('action') == 'delete') {
$tag->delete();
return [];
}
return $tag;
}
}
return $category;
}
public function discoveryCategoryTagStore(Request $request)
{
$this->validate($request, [
'category_id' => 'required|integer|min:1',
'hashtag' => 'required|string',
'action' => 'required|string|min:1|max:6',
]);
$category_id = $request->input('category_id');
$category = DiscoverCategory::findOrFail($category_id);
$hashtag = Hashtag::whereName($request->input('hashtag'))->firstOrFail();
$tag = DiscoverCategoryHashtag::firstOrCreate([
'hashtag_id' => $hashtag->id,
'discover_category_id' => $category->id,
]);
if ($request->input('action') == 'delete') {
$tag->delete();
return [];
}
return $tag;
}
}

View File

@ -2,13 +2,11 @@
namespace App\Http\Controllers\Admin;
use Cache;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Hashtag;
use App\StatusHashtag;
use App\Http\Resources\AdminHashtag;
use App\Services\TrendingHashtagService;
use App\StatusHashtag;
use Illuminate\Http\Request;
trait AdminHashtagsController
{
@ -22,25 +20,25 @@ trait AdminHashtagsController
$this->validate($request, [
'action' => 'sometimes|in:banned,nsfw',
'sort' => 'sometimes|in:id,name,cached_count,can_search,can_trend,is_banned,is_nsfw',
'dir' => 'sometimes|in:asc,desc'
'dir' => 'sometimes|in:asc,desc',
]);
$action = $request->input('action');
$query = $request->input('q');
$sort = $request->input('sort');
$order = $request->input('dir');
$hashtags = Hashtag::when($query, function($q, $query) {
return $q->where('name', 'like', $query . '%');
})
->when($sort, function($q, $sort) use($order) {
$hashtags = Hashtag::when($query, function ($q, $query) {
return $q->where('name', 'like', $query.'%');
})
->when($sort, function ($q, $sort) use ($order) {
return $q->orderBy($sort, $order);
}, function($q) {
}, function ($q) {
return $q->orderByDesc('id');
})
->when($action, function($q, $action) {
if($action === 'banned') {
->when($action, function ($q, $action) {
if ($action === 'banned') {
return $q->whereIsBanned(true);
} else if ($action === 'nsfw') {
} elseif ($action === 'nsfw') {
return $q->whereIsNsfw(true);
}
})
@ -57,7 +55,7 @@ trait AdminHashtagsController
'total_posts' => StatusHashtag::count(),
'added_14_days' => Hashtag::where('created_at', '>', now()->subDays(14))->count(),
'total_banned' => Hashtag::whereIsBanned(true)->count(),
'total_nsfw' => Hashtag::whereIsNsfw(true)->count()
'total_nsfw' => Hashtag::whereIsNsfw(true)->count(),
];
return response()->json($stats);
@ -77,7 +75,7 @@ trait AdminHashtagsController
'can_search' => 'required:boolean',
'can_trend' => 'required:boolean',
'is_nsfw' => 'required:boolean',
'is_banned' => 'required:boolean'
'is_banned' => 'required:boolean',
]);
$hashtag = Hashtag::whereSlug($request->input('slug'))->findOrFail($request->input('id'));
@ -96,7 +94,7 @@ trait AdminHashtagsController
public function hashtagsClearTrendingCache(Request $request)
{
TrendingHashtagService::refresh();
return [];
}
}

View File

@ -2,301 +2,316 @@
namespace App\Http\Controllers\Admin;
use DB, Cache;
use App\{Instance, Profile};
use Carbon\Carbon;
use App\Http\Resources\AdminInstance;
use App\Instance;
use App\Profile;
use App\Services\InstanceService;
use Cache;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use App\Services\InstanceService;
use App\Http\Resources\AdminInstance;
trait AdminInstanceController
{
public function instances(Request $request)
{
return view('admin.instances.home');
}
public function instances(Request $request)
{
return view('admin.instances.home');
}
public function instanceScan(Request $request)
{
Profile::whereNotNull('domain')
->latest()
->groupBy(['domain', 'id'])
->where('created_at', '>', now()->subMonths(2))
->chunk(100, function($domains) {
foreach($domains as $domain) {
Instance::firstOrCreate([
'domain' => $domain->domain
]);
}
});
public function instanceScan(Request $request)
{
Profile::whereNotNull('domain')
->latest()
->groupBy(['domain', 'id'])
->where('created_at', '>', now()->subMonths(2))
->chunk(100, function ($domains) {
foreach ($domains as $domain) {
Instance::firstOrCreate([
'domain' => $domain->domain,
]);
}
});
return redirect()->back();
}
return redirect()->back();
}
public function instanceShow(Request $request, $id)
{
$instance = Instance::findOrFail($id);
return view('admin.instances.show', compact('instance'));
}
public function instanceShow(Request $request, $id)
{
$instance = Instance::findOrFail($id);
public function instanceEdit(Request $request, $id)
{
$this->validate($request, [
'action' => [
'required',
'string',
'min:1',
'max:20',
Rule::in(['autocw', 'unlist', 'ban'])
],
]);
return view('admin.instances.show', compact('instance'));
}
$instance = Instance::findOrFail($id);
$unlisted = $instance->unlisted;
$autocw = $instance->auto_cw;
$banned = $instance->banned;
public function instanceEdit(Request $request, $id)
{
$this->validate($request, [
'action' => [
'required',
'string',
'min:1',
'max:20',
Rule::in(['autocw', 'unlist', 'ban']),
],
]);
switch ($request->action) {
case 'autocw':
$instance->auto_cw = $autocw == true ? false : true;
$instance->save();
break;
$instance = Instance::findOrFail($id);
$unlisted = $instance->unlisted;
$autocw = $instance->auto_cw;
$banned = $instance->banned;
case 'unlist':
$instance->unlisted = $unlisted == true ? false : true;
$instance->save();
break;
switch ($request->action) {
case 'autocw':
$instance->auto_cw = $autocw == true ? false : true;
$instance->save();
break;
case 'ban':
$instance->banned = $banned == true ? false : true;
$instance->save();
break;
}
case 'unlist':
$instance->unlisted = $unlisted == true ? false : true;
$instance->save();
break;
Cache::forget(InstanceService::CACHE_KEY_BANNED_DOMAINS);
Cache::forget(InstanceService::CACHE_KEY_UNLISTED_DOMAINS);
Cache::forget(InstanceService::CACHE_KEY_NSFW_DOMAINS);
case 'ban':
$instance->banned = $banned == true ? false : true;
$instance->save();
break;
}
return response()->json([]);
}
Cache::forget(InstanceService::CACHE_KEY_BANNED_DOMAINS);
Cache::forget(InstanceService::CACHE_KEY_UNLISTED_DOMAINS);
Cache::forget(InstanceService::CACHE_KEY_NSFW_DOMAINS);
public function getInstancesStatsApi(Request $request)
{
return InstanceService::stats();
}
return response()->json([]);
}
public function getInstancesQueryApi(Request $request)
{
$this->validate($request, [
'q' => 'required'
]);
public function getInstancesStatsApi(Request $request)
{
return InstanceService::stats();
}
$q = $request->input('q');
public function getInstancesQueryApi(Request $request)
{
$this->validate($request, [
'q' => 'required',
]);
return AdminInstance::collection(
Instance::where('domain', 'like', '%' . $q . '%')
->orderByDesc('user_count')
->cursorPaginate(10)
->withQueryString()
);
}
$q = $request->input('q');
public function getInstancesApi(Request $request)
{
$this->validate($request, [
'filter' => [
'nullable',
'string',
'min:1',
'max:20',
Rule::in([
'cw',
'unlisted',
'banned',
'popular_users',
'popular_statuses',
'new',
'all'
])
],
'sort' => [
'sometimes',
'string',
Rule::in([
'id',
'domain',
'software',
'user_count',
'status_count',
'banned',
'auto_cw',
'unlisted'
])
],
'dir' => 'sometimes|in:desc,asc'
]);
$filter = $request->input('filter');
$query = $request->input('q');
$sortCol = $request->input('sort');
$sortDir = $request->input('dir');
return AdminInstance::collection(
Instance::where('domain', 'like', '%'.$q.'%')
->orderByDesc('user_count')
->cursorPaginate(10)
->withQueryString()
);
}
return AdminInstance::collection(Instance::when($query, function($q, $qq) use($query) {
return $q->where('domain', 'like', '%' . $query . '%');
})
->when($filter, function($q, $f) use($filter) {
if($filter == 'cw') { return $q->whereAutoCw(true); }
if($filter == 'unlisted') { return $q->whereUnlisted(true); }
if($filter == 'banned') { return $q->whereBanned(true); }
if($filter == 'new') { return $q->orderByDesc('id'); }
if($filter == 'popular_users') { return $q->orderByDesc('user_count'); }
if($filter == 'popular_statuses') { return $q->orderByDesc('status_count'); }
return $q->orderByDesc('id');
})
->when($sortCol, function($q, $s) use($sortCol, $sortDir, $filter) {
if(!in_array($filter, ['popular_users', 'popular_statuses'])) {
return $q->whereNotNull($sortCol)->orderBy($sortCol, $sortDir);
}
}, function($q) use($filter) {
if(!$filter || !in_array($filter, ['popular_users', 'popular_statuses'])) {
return $q->orderByDesc('id');
}
})
->cursorPaginate(10)
->withQueryString());
}
public function getInstancesApi(Request $request)
{
$this->validate($request, [
'filter' => [
'nullable',
'string',
'min:1',
'max:20',
Rule::in([
'cw',
'unlisted',
'banned',
'popular_users',
'popular_statuses',
'new',
'all',
]),
],
'sort' => [
'sometimes',
'string',
Rule::in([
'id',
'domain',
'software',
'user_count',
'status_count',
'banned',
'auto_cw',
'unlisted',
]),
],
'dir' => 'sometimes|in:desc,asc',
]);
$filter = $request->input('filter');
$query = $request->input('q');
$sortCol = $request->input('sort');
$sortDir = $request->input('dir');
public function postInstanceUpdateApi(Request $request)
{
$this->validate($request, [
'id' => 'required',
'banned' => 'boolean',
'auto_cw' => 'boolean',
'unlisted' => 'boolean',
'notes' => 'nullable|string|max:500',
]);
return AdminInstance::collection(Instance::when($query, function ($q, $qq) use ($query) {
return $q->where('domain', 'like', '%'.$query.'%');
})
->when($filter, function ($q, $f) use ($filter) {
if ($filter == 'cw') {
return $q->whereAutoCw(true);
}
if ($filter == 'unlisted') {
return $q->whereUnlisted(true);
}
if ($filter == 'banned') {
return $q->whereBanned(true);
}
if ($filter == 'new') {
return $q->orderByDesc('id');
}
if ($filter == 'popular_users') {
return $q->orderByDesc('user_count');
}
if ($filter == 'popular_statuses') {
return $q->orderByDesc('status_count');
}
$id = $request->input('id');
$instance = Instance::findOrFail($id);
$instance->update($request->only([
'banned',
'auto_cw',
'unlisted',
'notes'
]));
return $q->orderByDesc('id');
})
->when($sortCol, function ($q, $s) use ($sortCol, $sortDir, $filter) {
if (! in_array($filter, ['popular_users', 'popular_statuses'])) {
return $q->whereNotNull($sortCol)->orderBy($sortCol, $sortDir);
}
}, function ($q) use ($filter) {
if (! $filter || ! in_array($filter, ['popular_users', 'popular_statuses'])) {
return $q->orderByDesc('id');
}
})
->cursorPaginate(10)
->withQueryString());
}
InstanceService::refresh();
public function postInstanceUpdateApi(Request $request)
{
$this->validate($request, [
'id' => 'required',
'banned' => 'boolean',
'auto_cw' => 'boolean',
'unlisted' => 'boolean',
'notes' => 'nullable|string|max:500',
]);
return new AdminInstance($instance);
}
$id = $request->input('id');
$instance = Instance::findOrFail($id);
$instance->update($request->only([
'banned',
'auto_cw',
'unlisted',
'notes',
]));
public function postInstanceCreateNewApi(Request $request)
{
$this->validate($request, [
'domain' => 'required|string',
'banned' => 'boolean',
'auto_cw' => 'boolean',
'unlisted' => 'boolean',
'notes' => 'nullable|string|max:500'
]);
InstanceService::refresh();
$domain = $request->input('domain');
return new AdminInstance($instance);
}
abort_if(!strpos($domain, '.'), 400, 'Invalid domain');
abort_if(!filter_var($domain, FILTER_VALIDATE_DOMAIN), 400, 'Invalid domain');
public function postInstanceCreateNewApi(Request $request)
{
$this->validate($request, [
'domain' => 'required|string',
'banned' => 'boolean',
'auto_cw' => 'boolean',
'unlisted' => 'boolean',
'notes' => 'nullable|string|max:500',
]);
$instance = new Instance;
$instance->domain = $request->input('domain');
$instance->banned = $request->input('banned');
$instance->auto_cw = $request->input('auto_cw');
$instance->unlisted = $request->input('unlisted');
$instance->manually_added = true;
$instance->notes = $request->input('notes');
$instance->save();
$domain = $request->input('domain');
InstanceService::refresh();
abort_if(! strpos($domain, '.'), 400, 'Invalid domain');
abort_if(! filter_var($domain, FILTER_VALIDATE_DOMAIN), 400, 'Invalid domain');
return new AdminInstance($instance);
}
$instance = new Instance;
$instance->domain = $request->input('domain');
$instance->banned = $request->input('banned');
$instance->auto_cw = $request->input('auto_cw');
$instance->unlisted = $request->input('unlisted');
$instance->manually_added = true;
$instance->notes = $request->input('notes');
$instance->save();
public function postInstanceRefreshStatsApi(Request $request)
{
$this->validate($request, [
'id' => 'required'
]);
InstanceService::refresh();
$instance = Instance::findOrFail($request->input('id'));
$instance->user_count = Profile::whereDomain($instance->domain)->count();
return new AdminInstance($instance);
}
public function postInstanceRefreshStatsApi(Request $request)
{
$this->validate($request, [
'id' => 'required',
]);
$instance = Instance::findOrFail($request->input('id'));
$instance->user_count = Profile::whereDomain($instance->domain)->count();
$instance->status_count = Profile::whereDomain($instance->domain)->leftJoin('statuses', 'profiles.id', '=', 'statuses.profile_id')->count();
$instance->save();
return new AdminInstance($instance);
}
}
public function postInstanceDeleteApi(Request $request)
{
$this->validate($request, [
'id' => 'required'
]);
public function postInstanceDeleteApi(Request $request)
{
$this->validate($request, [
'id' => 'required',
]);
$instance = Instance::findOrFail($request->input('id'));
$instance->delete();
$instance = Instance::findOrFail($request->input('id'));
$instance->delete();
InstanceService::refresh();
InstanceService::refresh();
return 200;
}
return 200;
}
public function downloadBackup(Request $request)
{
return response()->streamDownload(function () {
$json = [
'version' => 1,
'auto_cw' => Instance::whereAutoCw(true)->pluck('domain')->toArray(),
'unlisted' => Instance::whereUnlisted(true)->pluck('domain')->toArray(),
'banned' => Instance::whereBanned(true)->pluck('domain')->toArray(),
'created_at' => now()->format('c'),
];
$chk = hash('sha256', json_encode($json, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES));
$json['_sha256'] = $chk;
echo json_encode($json, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}, 'pixelfed-instances-mod.json');
}
public function downloadBackup(Request $request)
{
return response()->streamDownload(function () {
$json = [
'version' => 1,
'auto_cw' => Instance::whereAutoCw(true)->pluck('domain')->toArray(),
'unlisted' => Instance::whereUnlisted(true)->pluck('domain')->toArray(),
'banned' => Instance::whereBanned(true)->pluck('domain')->toArray(),
'created_at' => now()->format('c'),
];
$chk = hash('sha256', json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
$json['_sha256'] = $chk;
echo json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}, 'pixelfed-instances-mod.json');
}
public function importBackup(Request $request)
{
$this->validate($request, [
'banned' => 'sometimes|array',
'auto_cw' => 'sometimes|array',
'unlisted' => 'sometimes|array',
]);
public function importBackup(Request $request)
{
$this->validate($request, [
'banned' => 'sometimes|array',
'auto_cw' => 'sometimes|array',
'unlisted' => 'sometimes|array',
]);
$banned = $request->input('banned');
$auto_cw = $request->input('auto_cw');
$unlisted = $request->input('unlisted');
$banned = $request->input('banned');
$auto_cw = $request->input('auto_cw');
$unlisted = $request->input('unlisted');
foreach($banned as $i) {
Instance::updateOrCreate(
['domain' => $i],
['banned' => true]
);
}
foreach ($banned as $i) {
Instance::updateOrCreate(
['domain' => $i],
['banned' => true]
);
}
foreach($auto_cw as $i) {
Instance::updateOrCreate(
['domain' => $i],
['auto_cw' => true]
);
}
foreach ($auto_cw as $i) {
Instance::updateOrCreate(
['domain' => $i],
['auto_cw' => true]
);
}
foreach($unlisted as $i) {
Instance::updateOrCreate(
['domain' => $i],
['unlisted' => true]
);
}
foreach ($unlisted as $i) {
Instance::updateOrCreate(
['domain' => $i],
['unlisted' => true]
);
}
InstanceService::refresh();
return [200];
}
InstanceService::refresh();
return [200];
}
}

View File

@ -2,55 +2,54 @@
namespace App\Http\Controllers\Admin;
use DB, Cache;
use App\{
Media,
MediaBlocklist,
Profile,
Status
};
use Carbon\Carbon;
use App\Media;
use App\MediaBlocklist;
use App\Profile;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
trait AdminMediaController
{
public function media(Request $request)
{
$this->validate($request, [
'layout' => [
'nullable',
'string',
'min:1',
'max:13',
Rule::in(['grid','list', 'banned', 'addbanned'])
],
'search' => 'nullable|string|min:1|max:20'
]);
public function media(Request $request)
{
$this->validate($request, [
'layout' => [
'nullable',
'string',
'min:1',
'max:13',
Rule::in(['grid', 'list', 'banned', 'addbanned']),
],
'search' => 'nullable|string|min:1|max:20',
]);
if($request->filled('search')) {
$profiles = Profile::where('username', 'like', '%'.$request->input('search').'%')->pluck('id')->toArray();
$media = Media::whereHas('status')
->with('status')
->orderby('id', 'desc')
->whereIn('profile_id', $profiles)
->orWhere('mime', $request->input('search'))
->paginate(12);
return view('admin.media.home', compact('media'));
}
if ($request->filled('search')) {
$profiles = Profile::where('username', 'like', '%'.$request->input('search').'%')->pluck('id')->toArray();
$media = Media::whereHas('status')
->with('status')
->orderby('id', 'desc')
->whereIn('profile_id', $profiles)
->orWhere('mime', $request->input('search'))
->paginate(12);
if($request->input('layout') == 'banned') {
$media = MediaBlocklist::latest()->paginate(12);
return view('admin.media.home', compact('media'));
}
return view('admin.media.home', compact('media'));
}
$media = Media::whereNull('remote_url')->orderby('id', 'desc')->simplePaginate(12);
return view('admin.media.home', compact('media'));
}
if ($request->input('layout') == 'banned') {
$media = MediaBlocklist::latest()->paginate(12);
public function mediaShow(Request $request, $id)
{
$media = Media::findOrFail($id);
return view('admin.media.show', compact('media'));
}
return view('admin.media.home', compact('media'));
}
$media = Media::whereNull('remote_url')->orderby('id', 'desc')->simplePaginate(12);
return view('admin.media.home', compact('media'));
}
public function mediaShow(Request $request, $id)
{
$media = Media::findOrFail($id);
return view('admin.media.show', compact('media'));
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More