-
-
Notifications
You must be signed in to change notification settings - Fork 42
Add version update reminders #212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5b979da
19a45cf
6af0049
027273b
3b3b14a
3982e9f
1389567
fe5e3c8
4634387
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| <?php | ||
|
|
||
| // This command fetches extension metadata on a schedule, to then provide administrators | ||
| // with stuff like latest version info, and maybe more in the future. | ||
| // | ||
| // 1. make a request to blueprint.zip/api/extensions/latest | ||
| // 2. figure out which extensions it should write metadata for | ||
| // 3. build a json object for those extensions' metadata | ||
| // 4. flush metadata table | ||
| // 5. write metadata table | ||
|
|
||
| namespace Pterodactyl\Console\Commands\BlueprintFramework; | ||
|
|
||
| use Illuminate\Console\Command; | ||
| use Illuminate\Support\Facades\DB; | ||
| use Pterodactyl\Models\ExtensionCachedMetadata; | ||
| use Pterodactyl\BlueprintFramework\Services\PlaceholderService\BlueprintPlaceholderService; | ||
| use Pterodactyl\BlueprintFramework\Libraries\ExtensionLibrary\Console\BlueprintConsoleLibrary as BlueprintExtensionLibrary; | ||
|
|
||
| class MetadataCacheCommand extends Command | ||
| { | ||
| protected $description = 'Refreshes extension metadata'; | ||
| protected $signature = 'bp:meta'; | ||
|
|
||
| public function __construct( | ||
| private BlueprintPlaceholderService $PlaceholderService, | ||
| private BlueprintExtensionLibrary $blueprint, | ||
| ) { | ||
| parent::__construct(); | ||
| } | ||
|
|
||
| public function handle() | ||
| { | ||
| if(! $this->blueprint->dbGet("blueprint", "flags:remote_metadata")) { | ||
| $this->error('remote_metadata flag set to false'); | ||
| return false; | ||
| } | ||
|
|
||
| $now = now(); | ||
| $rows = []; | ||
| $installedExtensions = $this->blueprint->extensions(); | ||
|
|
||
| // get version info | ||
| $context = stream_context_create(['http' => ['method' => 'GET', 'header' => 'User-Agent: BlueprintFramework']]); | ||
| $remoteVersions = @file_get_contents( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe use a proper http client instead
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I took the file_get_contents shenanigans directly from a few other Artisan commands of ours, but I'll migrate it over to use |
||
| $this->PlaceholderService->api_url() . '/api/extensions/latest', | ||
| false, | ||
| $context | ||
| ); | ||
|
|
||
| if($remoteVersions) { | ||
| $remoteVersionsData = json_decode($remoteVersions, true); | ||
| } | ||
|
|
||
| if(! isset($remoteVersionsData)) { | ||
| $this->error('failed to fetch extension versions'); | ||
| return false; | ||
| } | ||
|
|
||
| foreach ($installedExtensions as $identifier) { | ||
| if(! isset($remoteVersionsData[$identifier]) || ! is_scalar($remoteVersionsData[$identifier])) continue; | ||
|
|
||
| $local_extension = $this->blueprint->extensionConfig($identifier); | ||
|
|
||
| $rows[] = [ | ||
| 'identifier' => $identifier, | ||
| 'metadata' => json_encode([ | ||
| 'latest_version' => (string) $remoteVersionsData[$identifier], | ||
| 'local_version' => (string) $local_extension['info']['version'] ?? '', | ||
| ]), | ||
| 'fetched_at' => $now, | ||
| ]; | ||
| } | ||
|
|
||
| if (empty($rows)) { | ||
| $this->info('no relevant data available, do you have any extensions installed?'); | ||
| return false; | ||
| } | ||
|
|
||
| $table = (new ExtensionCachedMetadata())->getTable(); | ||
|
|
||
| DB::transaction(function () use ($rows, $table) { | ||
| DB::table($table)->delete(); | ||
| DB::table($table)->insert($rows); | ||
| }); | ||
|
|
||
| $this->info('updated extension cached metadata'); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| <?php | ||
|
|
||
| namespace Pterodactyl\Models; | ||
|
|
||
| class ExtensionCachedMetadata extends Model | ||
| { | ||
| protected $table = 'extension_cached_metadata'; | ||
| protected $casts = [ | ||
| 'metadata' => 'array', | ||
| 'fetched_at' => 'datetime', | ||
| ]; | ||
| protected $fillable = ['identifier', 'metadata', 'fetched_at']; | ||
| public $timestamps = true; | ||
|
|
||
| // return the latest_version for a given extension identifier, or null if not found | ||
| public static function latestVersionFor(string $identifier): ?string | ||
| { | ||
| $row = static::where('identifier', $identifier)->first(['metadata']); | ||
|
|
||
| if (! $row) { | ||
| return null; | ||
| } | ||
|
|
||
| return $row->metadata['latest_version'] ?? null; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
version in the user agent could be useful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I somewhat agree, but would that kind of conflict with users disabling telemetry?