Skip to content

Commit b65b777

Browse files
FlexKleksrmartinoscarBoy132
authored
Add PasteFox Share plugin (#63)
* Add PasteFox Share plugin * Add update URL and update.json for pastefox-share * Remove auto-update, set update_url to null * Add admin settings page in sidebar * Add optional API key, effects, password, theme settings * Fix lint: remove unused imports and whitespace * Sync plugin settings modal with admin page settings * Fix indentation * Add Server Folders plugin * Update Server Folders & PasteFox Share * Add role-based folder sharing to Server Folders * Fix lint errors in Server Folders * PasteFox Share: Use HasPluginSettings instead of separate page * Remove server-folders (will be separate PR) * Update pastefox-share/src/PasteFoxSharePlugin.php Co-authored-by: MartinOscar <40749467+rmartinoscar@users.noreply.github.com> * Update pastefox-share/src/Filament/Components/Actions/UploadLogsAction.php Co-authored-by: MartinOscar <40749467+rmartinoscar@users.noreply.github.com> * Fix indentation in UploadLogsAction.php * Fix indentation and update .env reference in messages * Add translations for settings page, update README and plugin URL * cleanup readme --------- Co-authored-by: MartinOscar <40749467+rmartinoscar@users.noreply.github.com> Co-authored-by: Boy132 <mail@boy132.de>
1 parent a3f26b9 commit b65b777

8 files changed

Lines changed: 344 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ A curated list of plugins for the [Pelican Panel](https://pelican.dev). Feel fre
1414
- [Legal Pages](/legal-pages) - Adds legal pages (Imprint, Privacy Policy, ToS) to the panel
1515
- [MCLogs Uploader](/mclogs-uploader) - Upload console logs to mclo.gs
1616
- [Minecraft Modrinth](/minecraft-modrinth) - Download Minecraft mods & plugins from Modrinth
17+
- [PasteFox Share](/pastefox-share) - Share console logs via pastefox.com
1718
- [Player Counter](/player-counter) - Show connected players count for game servers
1819
- [Register](/register) - Enable user self-registration on all panels
1920
- [Robo Avatars](/robo-avatars) - Adds RoboHash as avatar provider

pastefox-share/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# PasteFox Share (by FlexKleks)
2+
3+
Share console logs via [pastefox.com](https://pastefox.com) with one click.
4+
5+
## Features
6+
7+
- One-click log sharing from server console
8+
- Optional API key for extended features (without API key, pastes expire after 7 days)
9+
- Configurable visibility (PUBLIC/PRIVATE - requires API key)
10+
- Visual effects (Matrix, Confetti, Glitch, etc.)
11+
- Theme selection (Light/Dark)
12+
- Password protection support
13+
- Fetches up to 5000 log lines
14+
15+
## Configuration
16+
17+
1. Go to **Admin → Plugins**
18+
2. Find **PasteFox Share** and click the **Settings** (gear icon) button
19+
3. Configure the following settings:
20+
21+
| Setting | Description |
22+
|------------|----------------------------------------------------|
23+
| API Key | Optional - Get from https://pastefox.com/dashboard |
24+
| Visibility | PUBLIC or PRIVATE (requires API key) |
25+
| Effect | Visual effect for the paste |
26+
| Theme | Light or Dark theme |
27+
| Password | Optional password protection |
28+
29+
### Without API Key
30+
- Pastes expire after 7 days
31+
- Always public visibility
32+
33+
### With API Key
34+
- No expiration limit
35+
- Private pastes available
36+
- Password protection
37+
38+
## Usage
39+
40+
1. Open a server console
41+
2. Click the **"Share Logs"** button in the header
42+
3. Copy the generated link from the notification
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
return [
4+
'api_key' => env('PASTEFOX_API_KEY'),
5+
'visibility' => env('PASTEFOX_VISIBILITY', 'PUBLIC'),
6+
'effect' => env('PASTEFOX_EFFECT', 'NONE'),
7+
'theme' => env('PASTEFOX_THEME', 'dark'),
8+
'password' => env('PASTEFOX_PASSWORD'),
9+
];
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
return [
4+
'share_logs' => 'Share Logs',
5+
'share_file' => 'Share',
6+
'uploaded' => 'Logs uploaded to PasteFox',
7+
'file_uploaded' => 'File uploaded to PasteFox',
8+
'upload_failed' => 'Upload failed',
9+
'api_key_missing' => 'PasteFox API key not configured. Add it in the plugin settings.',
10+
'expires_7_days' => '⚠️ Without API key, paste expires in 7 days',
11+
12+
// Settings
13+
'settings_saved' => 'Settings saved',
14+
'section_api' => 'API Configuration',
15+
'section_api_description' => 'Without API key, pastes expire after 7 days and are always public.',
16+
'section_paste' => 'Paste Settings',
17+
'api_key' => 'API Key',
18+
'api_key_helper' => 'Optional - Get your API key from https://pastefox.com/dashboard',
19+
'visibility' => 'Visibility',
20+
'visibility_public' => 'Public',
21+
'visibility_private' => 'Private (requires API key)',
22+
'visibility_helper' => 'Private pastes require an API key',
23+
'effect' => 'Visual Effect',
24+
'effect_none' => 'None',
25+
'effect_matrix' => 'Matrix Rain',
26+
'effect_glitch' => 'Glitch',
27+
'effect_confetti' => 'Confetti',
28+
'effect_scratch' => 'Scratch Card',
29+
'effect_puzzle' => 'Puzzle Reveal',
30+
'effect_slots' => 'Slot Machine',
31+
'effect_shake' => 'Shake',
32+
'effect_fireworks' => 'Fireworks',
33+
'effect_typewriter' => 'Typewriter',
34+
'effect_blur' => 'Blur Reveal',
35+
'theme' => 'Theme',
36+
'theme_dark' => 'Dark',
37+
'theme_light' => 'Light',
38+
'password' => 'Password Protection',
39+
'password_helper' => 'Optional - 4-100 characters',
40+
];

pastefox-share/plugin.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"id": "pastefox-share",
3+
"name": "PasteFox Share",
4+
"author": "FlexKleks",
5+
"version": "1.0.0",
6+
"description": "Share console logs via pastefox.com",
7+
"category": "plugin",
8+
"url": "https://github.com/pelican-dev/plugins/tree/main/pastefox-share",
9+
"update_url": null,
10+
"namespace": "FlexKleks\\PasteFoxShare",
11+
"class": "PasteFoxSharePlugin",
12+
"panels": ["admin", "server"],
13+
"panel_version": null,
14+
"composer_packages": null
15+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
namespace FlexKleks\PasteFoxShare\Filament\Components\Actions;
4+
5+
use App\Models\Server;
6+
use Exception;
7+
use Filament\Actions\Action;
8+
use Filament\Facades\Filament;
9+
use Filament\Notifications\Notification;
10+
use Filament\Support\Enums\Size;
11+
use Illuminate\Support\Facades\Http;
12+
13+
class UploadLogsAction extends Action
14+
{
15+
public static function getDefaultName(): ?string
16+
{
17+
return 'upload_logs_pastefox';
18+
}
19+
20+
protected function setUp(): void
21+
{
22+
parent::setUp();
23+
24+
$this->hidden(function () {
25+
/** @var Server $server */
26+
$server = Filament::getTenant();
27+
28+
return $server->retrieveStatus()->isOffline();
29+
});
30+
31+
$this->label(fn () => trans('pastefox-share::messages.share_logs'));
32+
33+
$this->icon('tabler-share');
34+
35+
$this->color('primary');
36+
37+
$this->size(Size::ExtraLarge);
38+
39+
$this->action(function () {
40+
/** @var Server $server */
41+
$server = Filament::getTenant();
42+
43+
try {
44+
$logs = Http::daemon($server->node)
45+
->get("/api/servers/{$server->uuid}/logs", [
46+
'size' => 5000,
47+
])
48+
->throw()
49+
->json('data');
50+
51+
$logs = is_array($logs) ? implode(PHP_EOL, $logs) : $logs;
52+
53+
$apiKey = config('pastefox-share.api_key');
54+
$hasApiKey = filled($apiKey);
55+
56+
$headers = ['Content-Type' => 'application/json'];
57+
58+
$payload = [
59+
'content' => $logs,
60+
'title' => 'Console Logs: ' . $server->name . ' - ' . now()->format('Y-m-d H:i:s'),
61+
'language' => 'log',
62+
'effect' => config('pastefox-share.effect'),
63+
'theme' => config('pastefox-share.theme'),
64+
];
65+
66+
if ($hasApiKey) {
67+
$headers['X-API-Key'] = $apiKey;
68+
$payload['visibility'] = config('pastefox-share.visibility');
69+
70+
$password = config('pastefox-share.password');
71+
if (filled($password)) {
72+
$payload['password'] = $password;
73+
}
74+
}
75+
76+
$response = Http::withHeaders($headers)
77+
->post('https://pastefox.com/api/pastes', $payload)
78+
->timeout(30)
79+
->connectTimeout(5)
80+
->throw()
81+
->json();
82+
83+
if ($response['success']) {
84+
$url = 'https://pastefox.com/'.$response['data']['slug'];
85+
86+
$body = $url;
87+
if (!$hasApiKey) {
88+
$body .= "\n".trans('pastefox-share::messages.expires_7_days');
89+
}
90+
91+
Notification::make()
92+
->title(trans('pastefox-share::messages.uploaded'))
93+
->body($body)
94+
->persistent()
95+
->success()
96+
->send();
97+
} else {
98+
Notification::make()
99+
->title(trans('pastefox-share::messages.upload_failed'))
100+
->body($response['error'] ?? 'Unknown error')
101+
->danger()
102+
->send();
103+
}
104+
} catch (Exception $exception) {
105+
report($exception);
106+
107+
Notification::make()
108+
->title(trans('pastefox-share::messages.upload_failed'))
109+
->body($exception->getMessage())
110+
->danger()
111+
->send();
112+
}
113+
});
114+
}
115+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
namespace FlexKleks\PasteFoxShare;
4+
5+
use App\Contracts\Plugins\HasPluginSettings;
6+
use App\Traits\EnvironmentWriterTrait;
7+
use Filament\Contracts\Plugin;
8+
use Filament\Forms\Components\Select;
9+
use Filament\Forms\Components\TextInput;
10+
use Filament\Notifications\Notification;
11+
use Filament\Panel;
12+
use Filament\Schemas\Components\Section;
13+
14+
class PasteFoxSharePlugin implements HasPluginSettings, Plugin
15+
{
16+
use EnvironmentWriterTrait;
17+
18+
public function getId(): string
19+
{
20+
return 'pastefox-share';
21+
}
22+
23+
public function register(Panel $panel): void {}
24+
25+
public function boot(Panel $panel): void {}
26+
27+
public function getSettingsForm(): array
28+
{
29+
return [
30+
Section::make(trans('pastefox-share::messages.section_api'))
31+
->description(trans('pastefox-share::messages.section_api_description'))
32+
->schema([
33+
TextInput::make('api_key')
34+
->label(trans('pastefox-share::messages.api_key'))
35+
->password()
36+
->revealable()
37+
->helperText(trans('pastefox-share::messages.api_key_helper'))
38+
->default(fn () => config('pastefox-share.api_key')),
39+
]),
40+
41+
Section::make(trans('pastefox-share::messages.section_paste'))
42+
->schema([
43+
Select::make('visibility')
44+
->label(trans('pastefox-share::messages.visibility'))
45+
->options([
46+
'PUBLIC' => trans('pastefox-share::messages.visibility_public'),
47+
'PRIVATE' => trans('pastefox-share::messages.visibility_private'),
48+
])
49+
->default(fn () => config('pastefox-share.visibility', 'PUBLIC'))
50+
->helperText(trans('pastefox-share::messages.visibility_helper')),
51+
52+
Select::make('effect')
53+
->label(trans('pastefox-share::messages.effect'))
54+
->options([
55+
'NONE' => trans('pastefox-share::messages.effect_none'),
56+
'MATRIX' => trans('pastefox-share::messages.effect_matrix'),
57+
'GLITCH' => trans('pastefox-share::messages.effect_glitch'),
58+
'CONFETTI' => trans('pastefox-share::messages.effect_confetti'),
59+
'SCRATCH' => trans('pastefox-share::messages.effect_scratch'),
60+
'PUZZLE' => trans('pastefox-share::messages.effect_puzzle'),
61+
'SLOTS' => trans('pastefox-share::messages.effect_slots'),
62+
'SHAKE' => trans('pastefox-share::messages.effect_shake'),
63+
'FIREWORKS' => trans('pastefox-share::messages.effect_fireworks'),
64+
'TYPEWRITER' => trans('pastefox-share::messages.effect_typewriter'),
65+
'BLUR' => trans('pastefox-share::messages.effect_blur'),
66+
])
67+
->default(fn () => config('pastefox-share.effect', 'NONE')),
68+
69+
Select::make('theme')
70+
->label(trans('pastefox-share::messages.theme'))
71+
->options([
72+
'dark' => trans('pastefox-share::messages.theme_dark'),
73+
'light' => trans('pastefox-share::messages.theme_light'),
74+
])
75+
->default(fn () => config('pastefox-share.theme', 'dark')),
76+
77+
TextInput::make('password')
78+
->label(trans('pastefox-share::messages.password'))
79+
->password()
80+
->revealable()
81+
->minLength(4)
82+
->maxLength(100)
83+
->helperText(trans('pastefox-share::messages.password_helper'))
84+
->default(fn () => config('pastefox-share.password')),
85+
]),
86+
];
87+
}
88+
89+
public function saveSettings(array $data): void
90+
{
91+
$this->writeToEnvironment([
92+
'PASTEFOX_API_KEY' => $data['api_key'] ?? '',
93+
'PASTEFOX_VISIBILITY' => $data['visibility'] ?? 'PUBLIC',
94+
'PASTEFOX_EFFECT' => $data['effect'] ?? 'NONE',
95+
'PASTEFOX_THEME' => $data['theme'] ?? 'dark',
96+
'PASTEFOX_PASSWORD' => $data['password'] ?? '',
97+
]);
98+
99+
Notification::make()
100+
->title(trans('pastefox-share::messages.settings_saved'))
101+
->success()
102+
->send();
103+
}
104+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace FlexKleks\PasteFoxShare\Providers;
4+
5+
use App\Enums\HeaderActionPosition;
6+
use App\Filament\Server\Pages\Console;
7+
use FlexKleks\PasteFoxShare\Filament\Components\Actions\UploadLogsAction;
8+
use Illuminate\Support\ServiceProvider;
9+
10+
class PasteFoxSharePluginProvider extends ServiceProvider
11+
{
12+
public function register(): void
13+
{
14+
Console::registerCustomHeaderActions(HeaderActionPosition::Before, UploadLogsAction::make());
15+
}
16+
17+
public function boot(): void {}
18+
}

0 commit comments

Comments
 (0)