Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions pastefox-share/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# PasteFox Share

Share console logs via [pastefox.com](https://pastefox.com) with one click.

## Features

- One-click log sharing from server console
- Configurable visibility (PUBLIC/PRIVATE)
- Fetches up to 5000 log lines
- Admin settings page in sidebar

## Installation

1. Download and extract to `/var/www/pelican/plugins/pastefox-share`
2. Run `php artisan p:plugin:install`
3. Configure in Admin → Advanced → PasteFox

Get your API key from https://pastefox.com/dashboard

## Usage

1. Open a server console
2. Click the "Share Logs" button
3. Copy the generated link from the notification

## Coming Soon

- File sharing
- Custom domains
- Folders
- Syntax highlighting themes

## License

MIT
6 changes: 6 additions & 0 deletions pastefox-share/config/pastefox-share.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

return [
'api_key' => env('PASTEFOX_API_KEY'),
'visibility' => env('PASTEFOX_VISIBILITY', 'PUBLIC'),
];
10 changes: 10 additions & 0 deletions pastefox-share/lang/en/messages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

return [
'share_logs' => 'Share Logs',
'share_file' => 'Share',
'uploaded' => 'Logs uploaded to PasteFox',
'file_uploaded' => 'File uploaded to PasteFox',
'upload_failed' => 'Upload failed',
'api_key_missing' => 'PasteFox API key not configured. Add PASTEFOX_API_KEY to your .env file.',
];
15 changes: 15 additions & 0 deletions pastefox-share/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"id": "pastefox-share",
"name": "PasteFox Share",
"author": "FlexKleks",
"version": "1.0.0",
"description": "Share console logs via pastefox.com",
"category": "plugin",
"url": "https://github.com/FlexKleks/PelicanPasteFox",
"update_url": null,
"namespace": "FlexKleks\\PasteFoxShare",
"class": "PasteFoxSharePlugin",
"panels": ["admin", "server"],
"panel_version": null,
"composer_packages": null
}
106 changes: 106 additions & 0 deletions pastefox-share/src/Filament/Admin/Pages/PasteFoxSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

namespace FlexKleks\PasteFoxShare\Filament\Admin\Pages;

use App\Traits\EnvironmentWriterTrait;
use Filament\Actions\Action;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Notifications\Notification;
use Filament\Pages\Concerns\InteractsWithFormActions;
use Filament\Pages\Page;
use Filament\Schemas\Components\Component;
use Filament\Schemas\Schema;

/**
* @property Schema $form
*/
class PasteFoxSettings extends Page
{
use EnvironmentWriterTrait;
use InteractsWithFormActions;
use InteractsWithForms;

protected static string|\BackedEnum|null $navigationIcon = 'tabler-share';

protected string $view = 'filament.server.pages.server-form-page';

/** @var array<mixed>|null */
public ?array $data = [];

public function getTitle(): string
{
return 'PasteFox Settings';
}

public static function getNavigationLabel(): string
{
return 'PasteFox';
}

public static function getNavigationGroup(): ?string
{
return trans('admin/dashboard.advanced');
}

public function mount(): void
{
$this->form->fill([
'api_key' => config('pastefox-share.api_key'),
'visibility' => config('pastefox-share.visibility', 'PUBLIC'),
]);
}

/**
* @return Component[]
*/
public function getFormSchema(): array
{
return [
TextInput::make('api_key')
->label('API Key')
->password()
->revealable()
->required()
->helperText('Get your API key from https://pastefox.com/dashboard'),
Select::make('visibility')
->label('Default Visibility')
->options([
'PUBLIC' => 'Public',
'PRIVATE' => 'Private',
])
->default('PUBLIC'),
];
}

protected function getFormStatePath(): ?string
{
return 'data';
}

protected function getHeaderActions(): array
{
return [
Action::make('save')
->label(trans('filament-panels::resources/pages/edit-record.form.actions.save.label'))
->action('save')
->keyBindings(['mod+s']),
];
}

public function save(): void
{
$data = $this->form->getState();

$this->writeToEnvironment([
'PASTEFOX_API_KEY' => $data['api_key'],
'PASTEFOX_VISIBILITY' => $data['visibility'],
]);

Notification::make()
->title('Settings saved')
->success()
->send();
}
}
106 changes: 106 additions & 0 deletions pastefox-share/src/Filament/Components/Actions/UploadLogsAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

namespace FlexKleks\PasteFoxShare\Filament\Components\Actions;

use App\Models\Server;
use Exception;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Notifications\Notification;
use Filament\Support\Enums\Size;
use Illuminate\Support\Facades\Http;

class UploadLogsAction extends Action
{
public static function getDefaultName(): ?string
{
return 'upload_logs_pastefox';
}

protected function setUp(): void
{
parent::setUp();

$this->hidden(function () {
/** @var Server $server */
$server = Filament::getTenant();

return $server->retrieveStatus()->isOffline();
});

$this->label(fn () => trans('pastefox-share::messages.share_logs'));

$this->icon('tabler-share');

$this->color('primary');

$this->size(Size::ExtraLarge);

$this->action(function () {
/** @var Server $server */
$server = Filament::getTenant();

try {
$logs = Http::daemon($server->node)
->get("/api/servers/{$server->uuid}/logs", [
'size' => 5000,
])
->throw()
->json('data');

$logs = is_array($logs) ? implode(PHP_EOL, $logs) : $logs;

$apiKey = config('pastefox-share.api_key');

if (empty($apiKey)) {
Notification::make()
->title(trans('pastefox-share::messages.api_key_missing'))
->danger()
->send();

return;
}

$response = Http::withHeaders([
'X-API-Key' => $apiKey,
'Content-Type' => 'application/json',
])
->timeout(30)
->connectTimeout(5)
->throw()
->post('https://pastefox.com/api/pastes', [
'content' => $logs,
'title' => 'Console Logs: '.$server->name.' - '.now()->format('Y-m-d H:i:s'),
'language' => 'log',
'visibility' => config('pastefox-share.visibility', 'PUBLIC'),
])
->json();

if ($response['success']) {
$url = 'https://pastefox.com/'.$response['data']['slug'];

Notification::make()
->title(trans('pastefox-share::messages.uploaded'))
->body($url)
->persistent()
->success()
->send();
} else {
Notification::make()
->title(trans('pastefox-share::messages.upload_failed'))
->body($response['error'] ?? 'Unknown error')
->danger()
->send();
}
} catch (Exception $exception) {
report($exception);

Notification::make()
->title(trans('pastefox-share::messages.upload_failed'))
->body($exception->getMessage())
->danger()
->send();
}
});
}
}
66 changes: 66 additions & 0 deletions pastefox-share/src/PasteFoxSharePlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace FlexKleks\PasteFoxShare;

use App\Contracts\Plugins\HasPluginSettings;
use App\Traits\EnvironmentWriterTrait;
use Filament\Contracts\Plugin;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Panel;

class PasteFoxSharePlugin implements HasPluginSettings, Plugin
{
use EnvironmentWriterTrait;

public function getId(): string
{
return 'pastefox-share';
}

public function register(Panel $panel): void
{
$id = str($panel->getId())->title();

$panel->discoverPages(
plugin_path($this->getId(), "src/Filament/$id/Pages"),
"FlexKleks\\PasteFoxShare\\Filament\\$id\\Pages"
);
}

public function boot(Panel $panel): void {}

public function getSettingsForm(): array
{
return [
TextInput::make('api_key')
->label('API Key')
->password()
->revealable()
->required()
->helperText('Get your API key from https://pastefox.com/dashboard')
->default(fn () => config('pastefox-share.api_key')),
Select::make('visibility')
->label('Default Visibility')
->options([
'PUBLIC' => 'Public',
'PRIVATE' => 'Private',
])
->default(fn () => config('pastefox-share.visibility', 'PUBLIC')),
];
}

public function saveSettings(array $data): void
{
$this->writeToEnvironment([
'PASTEFOX_API_KEY' => $data['api_key'],
'PASTEFOX_VISIBILITY' => $data['visibility'],
]);

Notification::make()
->title('Settings saved')
->success()
->send();
}
}
18 changes: 18 additions & 0 deletions pastefox-share/src/Providers/PasteFoxSharePluginProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace FlexKleks\PasteFoxShare\Providers;

use App\Enums\HeaderActionPosition;
use App\Filament\Server\Pages\Console;
use FlexKleks\PasteFoxShare\Filament\Components\Actions\UploadLogsAction;
use Illuminate\Support\ServiceProvider;

class PasteFoxSharePluginProvider extends ServiceProvider
{
public function register(): void
{
Console::registerCustomHeaderActions(HeaderActionPosition::Before, UploadLogsAction::make());
}

public function boot(): void {}
}