Initial import.
This commit is contained in:
commit
adb24dae9f
21 changed files with 1587 additions and 0 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
* text=auto
|
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[Tt]humbs.db
|
||||||
|
[Dd]esktop.ini
|
||||||
|
.DS_Store
|
||||||
|
/.debug
|
||||||
|
/vendor
|
||||||
|
/aleister.cfg
|
30
LICENCE
Normal file
30
LICENCE
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
Copyright (c) 2024, flashwave <me@flash.moe>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted (subject to the limitations in the disclaimer
|
||||||
|
below) provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from this
|
||||||
|
software without specific prior written permission.
|
||||||
|
|
||||||
|
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
|
||||||
|
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||||
|
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Aleister
|
||||||
|
|
||||||
|
Aleister is the API gateway server for Flashii.
|
32
aleister.php
Normal file
32
aleister.php
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister;
|
||||||
|
|
||||||
|
use Syokuhou\FileConfig;
|
||||||
|
|
||||||
|
define('CRW_STARTUP', microtime(true));
|
||||||
|
define('CRW_ROOT', __DIR__);
|
||||||
|
define('CRW_CLI', PHP_SAPI === 'cli');
|
||||||
|
define('CRW_DEBUG', is_file(CRW_ROOT . '/.debug'));
|
||||||
|
|
||||||
|
require_once CRW_ROOT . '/vendor/autoload.php';
|
||||||
|
|
||||||
|
error_reporting(CRW_DEBUG ? -1 : 0);
|
||||||
|
mb_internal_encoding('UTF-8');
|
||||||
|
date_default_timezone_set('GMT');
|
||||||
|
|
||||||
|
$cfg = FileConfig::fromFile(CRW_ROOT . '/aleister.cfg');
|
||||||
|
|
||||||
|
if($cfg->hasValues('sentry:dsn'))
|
||||||
|
(function($cfg) {
|
||||||
|
\Sentry\init([
|
||||||
|
'dsn' => $cfg->getString('dsn'),
|
||||||
|
'traces_sample_rate' => $cfg->getFloat('tracesRate', 0.2),
|
||||||
|
'profiles_sample_rate' => $cfg->getFloat('profilesRate', 0.2),
|
||||||
|
]);
|
||||||
|
|
||||||
|
set_exception_handler(function(\Throwable $ex) {
|
||||||
|
\Sentry\captureException($ex);
|
||||||
|
});
|
||||||
|
})($cfg->scopeTo('sentry'));
|
||||||
|
|
||||||
|
$ctx = new AleisterContext($cfg);
|
16
composer.json
Normal file
16
composer.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Aleister\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"flashwave/index": "^0.2408.40014",
|
||||||
|
"flashwave/syokuhou": "^1.2",
|
||||||
|
"flashwave/aiwass": "^1.0",
|
||||||
|
"sentry/sdk": "^4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "^1.11"
|
||||||
|
}
|
||||||
|
}
|
852
composer.lock
generated
Normal file
852
composer.lock
generated
Normal file
|
@ -0,0 +1,852 @@
|
||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "f16579c0b9bf3a7b6091a2eec61e2354",
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "flashwave/aiwass",
|
||||||
|
"version": "v1.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://patchii.net/flashii/aiwass.git",
|
||||||
|
"reference": "de27da54b603f0fdc06dab89341908e73ea7a880"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-msgpack": ">=2.2",
|
||||||
|
"flashwave/index": "^0.2408.40014",
|
||||||
|
"php": ">=8.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "^1.11",
|
||||||
|
"phpunit/phpunit": "^11.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Aiwass\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"bsd-3-clause-clear"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "flashwave",
|
||||||
|
"email": "packagist@flash.moe",
|
||||||
|
"homepage": "https://flash.moe",
|
||||||
|
"role": "mom"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Shared HTTP RPC client/server library.",
|
||||||
|
"homepage": "https://railgun.sh/aiwass",
|
||||||
|
"time": "2024-08-16T15:59:19+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flashwave/index",
|
||||||
|
"version": "v0.2408.182001",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://patchii.net/flash/index.git",
|
||||||
|
"reference": "5a1fdcccedf818897a3468d5457875fabfb2ce28"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": ">=8.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "^1.11",
|
||||||
|
"phpunit/phpunit": "^11.2"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-mysqli": "Support for the Index\\Data\\MariaDB namespace (both mysqlnd and libmysql are supported).",
|
||||||
|
"ext-sqlite3": "Support for the Index\\Data\\SQLite namespace."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Index\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"bsd-3-clause-clear"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "flashwave",
|
||||||
|
"email": "packagist@flash.moe",
|
||||||
|
"homepage": "https://flash.moe",
|
||||||
|
"role": "mom"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Composer package for the common library for my projects.",
|
||||||
|
"homepage": "https://railgun.sh/index",
|
||||||
|
"time": "2024-08-18T20:01:21+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flashwave/syokuhou",
|
||||||
|
"version": "v1.2.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://patchii.net/flash/syokuhou.git",
|
||||||
|
"reference": "129a46c0d917382f9bc195cce278be51984eb87d"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"flashwave/index": "^0.2408.40014",
|
||||||
|
"php": ">=8.3"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpstan/phpstan": "^1.11",
|
||||||
|
"phpunit/phpunit": "^11.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Syokuhou\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"bsd-3-clause-clear"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "flashwave",
|
||||||
|
"email": "packagist@flash.moe",
|
||||||
|
"homepage": "https://flash.moe",
|
||||||
|
"role": "mom"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Configuration library for PHP.",
|
||||||
|
"homepage": "https://railgun.sh/syokuhou",
|
||||||
|
"time": "2024-08-04T01:07:23+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "guzzlehttp/psr7",
|
||||||
|
"version": "2.7.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/guzzle/psr7.git",
|
||||||
|
"reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
|
||||||
|
"reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2.5 || ^8.0",
|
||||||
|
"psr/http-factory": "^1.0",
|
||||||
|
"psr/http-message": "^1.1 || ^2.0",
|
||||||
|
"ralouphie/getallheaders": "^3.0"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/http-factory-implementation": "1.0",
|
||||||
|
"psr/http-message-implementation": "1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||||
|
"http-interop/http-factory-tests": "0.9.0",
|
||||||
|
"phpunit/phpunit": "^8.5.39 || ^9.6.20"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"bamarni-bin": {
|
||||||
|
"bin-links": true,
|
||||||
|
"forward-command": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"GuzzleHttp\\Psr7\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Graham Campbell",
|
||||||
|
"email": "hello@gjcampbell.co.uk",
|
||||||
|
"homepage": "https://github.com/GrahamCampbell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Michael Dowling",
|
||||||
|
"email": "mtdowling@gmail.com",
|
||||||
|
"homepage": "https://github.com/mtdowling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "George Mponos",
|
||||||
|
"email": "gmponos@gmail.com",
|
||||||
|
"homepage": "https://github.com/gmponos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tobias Nyholm",
|
||||||
|
"email": "tobias.nyholm@gmail.com",
|
||||||
|
"homepage": "https://github.com/Nyholm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Márk Sági-Kazár",
|
||||||
|
"email": "mark.sagikazar@gmail.com",
|
||||||
|
"homepage": "https://github.com/sagikazarmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tobias Schultze",
|
||||||
|
"email": "webmaster@tubo-world.de",
|
||||||
|
"homepage": "https://github.com/Tobion"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Márk Sági-Kazár",
|
||||||
|
"email": "mark.sagikazar@gmail.com",
|
||||||
|
"homepage": "https://sagikazarmark.hu"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PSR-7 message implementation that also provides common utility methods",
|
||||||
|
"keywords": [
|
||||||
|
"http",
|
||||||
|
"message",
|
||||||
|
"psr-7",
|
||||||
|
"request",
|
||||||
|
"response",
|
||||||
|
"stream",
|
||||||
|
"uri",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/guzzle/psr7/issues",
|
||||||
|
"source": "https://github.com/guzzle/psr7/tree/2.7.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/GrahamCampbell",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/Nyholm",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-07-18T11:15:46+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "jean85/pretty-package-versions",
|
||||||
|
"version": "2.0.6",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Jean85/pretty-package-versions.git",
|
||||||
|
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4",
|
||||||
|
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"composer-runtime-api": "^2.0.0",
|
||||||
|
"php": "^7.1|^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.2",
|
||||||
|
"jean85/composer-provided-replaced-stub-package": "^1.0",
|
||||||
|
"phpstan/phpstan": "^1.4",
|
||||||
|
"phpunit/phpunit": "^7.5|^8.5|^9.4",
|
||||||
|
"vimeo/psalm": "^4.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Jean85\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Alessandro Lai",
|
||||||
|
"email": "alessandro.lai85@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A library to get pretty versions strings of installed dependencies",
|
||||||
|
"keywords": [
|
||||||
|
"composer",
|
||||||
|
"package",
|
||||||
|
"release",
|
||||||
|
"versions"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
|
||||||
|
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6"
|
||||||
|
},
|
||||||
|
"time": "2024-03-08T09:58:59+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/http-factory",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/http-factory.git",
|
||||||
|
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
|
||||||
|
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1",
|
||||||
|
"psr/http-message": "^1.0 || ^2.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Http\\Message\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "https://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
|
||||||
|
"keywords": [
|
||||||
|
"factory",
|
||||||
|
"http",
|
||||||
|
"message",
|
||||||
|
"psr",
|
||||||
|
"psr-17",
|
||||||
|
"psr-7",
|
||||||
|
"request",
|
||||||
|
"response"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/php-fig/http-factory"
|
||||||
|
},
|
||||||
|
"time": "2024-04-15T12:06:14+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/http-message",
|
||||||
|
"version": "2.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/http-message.git",
|
||||||
|
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
|
||||||
|
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2 || ^8.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "2.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Http\\Message\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "https://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Common interface for HTTP messages",
|
||||||
|
"homepage": "https://github.com/php-fig/http-message",
|
||||||
|
"keywords": [
|
||||||
|
"http",
|
||||||
|
"http-message",
|
||||||
|
"psr",
|
||||||
|
"psr-7",
|
||||||
|
"request",
|
||||||
|
"response"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/php-fig/http-message/tree/2.0"
|
||||||
|
},
|
||||||
|
"time": "2023-04-04T09:54:51+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "psr/log",
|
||||||
|
"version": "3.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/php-fig/log.git",
|
||||||
|
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||||
|
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.0.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Psr\\Log\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "PHP-FIG",
|
||||||
|
"homepage": "https://www.php-fig.org/"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Common interface for logging libraries",
|
||||||
|
"homepage": "https://github.com/php-fig/log",
|
||||||
|
"keywords": [
|
||||||
|
"log",
|
||||||
|
"psr",
|
||||||
|
"psr-3"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/php-fig/log/tree/3.0.0"
|
||||||
|
},
|
||||||
|
"time": "2021-07-14T16:46:02+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ralouphie/getallheaders",
|
||||||
|
"version": "3.0.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/ralouphie/getallheaders.git",
|
||||||
|
"reference": "120b605dfeb996808c31b6477290a714d356e822"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
|
||||||
|
"reference": "120b605dfeb996808c31b6477290a714d356e822",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.6"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"php-coveralls/php-coveralls": "^2.1",
|
||||||
|
"phpunit/phpunit": "^5 || ^6.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/getallheaders.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ralph Khattar",
|
||||||
|
"email": "ralph.khattar@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A polyfill for getallheaders.",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/ralouphie/getallheaders/issues",
|
||||||
|
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
|
||||||
|
},
|
||||||
|
"time": "2019-03-08T08:55:37+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sentry/sdk",
|
||||||
|
"version": "4.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/getsentry/sentry-php-sdk.git",
|
||||||
|
"reference": "fcbca864e8d1dc712f3ecfaa95ea89d024fb2e53"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/fcbca864e8d1dc712f3ecfaa95ea89d024fb2e53",
|
||||||
|
"reference": "fcbca864e8d1dc712f3ecfaa95ea89d024fb2e53",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"sentry/sentry": "^4.0"
|
||||||
|
},
|
||||||
|
"type": "metapackage",
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Sentry",
|
||||||
|
"email": "accounts@sentry.io"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "This is a meta package of sentry/sentry. We recommend using sentry/sentry directly.",
|
||||||
|
"homepage": "http://sentry.io",
|
||||||
|
"keywords": [
|
||||||
|
"crash-reporting",
|
||||||
|
"crash-reports",
|
||||||
|
"error-handler",
|
||||||
|
"error-monitoring",
|
||||||
|
"log",
|
||||||
|
"logging",
|
||||||
|
"sentry"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/getsentry/sentry-php-sdk/issues",
|
||||||
|
"source": "https://github.com/getsentry/sentry-php-sdk/tree/4.0.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://sentry.io/",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://sentry.io/pricing/",
|
||||||
|
"type": "custom"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-11-06T10:23:19+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sentry/sentry",
|
||||||
|
"version": "4.9.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/getsentry/sentry-php.git",
|
||||||
|
"reference": "788ec170f51ebb22f2809a1e3f78b19ccd39b70d"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/788ec170f51ebb22f2809a1e3f78b19ccd39b70d",
|
||||||
|
"reference": "788ec170f51ebb22f2809a1e3f78b19ccd39b70d",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-curl": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
|
||||||
|
"jean85/pretty-package-versions": "^1.5|^2.0.4",
|
||||||
|
"php": "^7.2|^8.0",
|
||||||
|
"psr/log": "^1.0|^2.0|^3.0",
|
||||||
|
"symfony/options-resolver": "^4.4.30|^5.0.11|^6.0|^7.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"raven/raven": "*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.4",
|
||||||
|
"guzzlehttp/promises": "^1.0|^2.0",
|
||||||
|
"guzzlehttp/psr7": "^1.8.4|^2.1.1",
|
||||||
|
"monolog/monolog": "^1.6|^2.0|^3.0",
|
||||||
|
"phpbench/phpbench": "^1.0",
|
||||||
|
"phpstan/phpstan": "^1.3",
|
||||||
|
"phpunit/phpunit": "^8.5.14|^9.4",
|
||||||
|
"symfony/phpunit-bridge": "^5.2|^6.0|^7.0",
|
||||||
|
"vimeo/psalm": "^4.17"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"monolog/monolog": "Allow sending log messages to Sentry by using the included Monolog handler."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"src/functions.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Sentry\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Sentry",
|
||||||
|
"email": "accounts@sentry.io"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP SDK for Sentry (http://sentry.io)",
|
||||||
|
"homepage": "http://sentry.io",
|
||||||
|
"keywords": [
|
||||||
|
"crash-reporting",
|
||||||
|
"crash-reports",
|
||||||
|
"error-handler",
|
||||||
|
"error-monitoring",
|
||||||
|
"log",
|
||||||
|
"logging",
|
||||||
|
"profiling",
|
||||||
|
"sentry",
|
||||||
|
"tracing"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/getsentry/sentry-php/issues",
|
||||||
|
"source": "https://github.com/getsentry/sentry-php/tree/4.9.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://sentry.io/",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://sentry.io/pricing/",
|
||||||
|
"type": "custom"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-08-08T14:40:50+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/deprecation-contracts",
|
||||||
|
"version": "v3.5.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||||
|
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
|
||||||
|
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "3.5-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/contracts",
|
||||||
|
"url": "https://github.com/symfony/contracts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"function.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A generic function and convention to trigger deprecation notices",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-04-18T09:32:20+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/options-resolver",
|
||||||
|
"version": "v7.1.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/options-resolver.git",
|
||||||
|
"reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55",
|
||||||
|
"reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.2",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\OptionsResolver\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides an improved replacement for the array_replace PHP function",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"config",
|
||||||
|
"configuration",
|
||||||
|
"options"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/options-resolver/tree/v7.1.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-05-31T14:57:53+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "phpstan/phpstan",
|
||||||
|
"version": "1.11.10",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/phpstan/phpstan.git",
|
||||||
|
"reference": "640410b32995914bde3eed26fa89552f9c2c082f"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/640410b32995914bde3eed26fa89552f9c2c082f",
|
||||||
|
"reference": "640410b32995914bde3eed26fa89552f9c2c082f",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2|^8.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"phpstan/phpstan-shim": "*"
|
||||||
|
},
|
||||||
|
"bin": [
|
||||||
|
"phpstan",
|
||||||
|
"phpstan.phar"
|
||||||
|
],
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "PHPStan - PHP Static Analysis Tool",
|
||||||
|
"keywords": [
|
||||||
|
"dev",
|
||||||
|
"static analysis"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"docs": "https://phpstan.org/user-guide/getting-started",
|
||||||
|
"forum": "https://github.com/phpstan/phpstan/discussions",
|
||||||
|
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||||
|
"security": "https://github.com/phpstan/phpstan/security/policy",
|
||||||
|
"source": "https://github.com/phpstan/phpstan-src"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/ondrejmirtes",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/phpstan",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-08-08T09:02:50+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": [],
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": [],
|
||||||
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "2.6.0"
|
||||||
|
}
|
9
phpstan.neon
Normal file
9
phpstan.neon
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
parameters:
|
||||||
|
level: 5
|
||||||
|
paths:
|
||||||
|
- src
|
||||||
|
bootstrapFiles:
|
||||||
|
- aleister.php
|
||||||
|
dynamicConstantNames:
|
||||||
|
- CRW_CLI
|
||||||
|
- CRW_DEBUG
|
21
public/index.php
Normal file
21
public/index.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../aleister.php';
|
||||||
|
|
||||||
|
set_exception_handler(function(\Throwable $ex) {
|
||||||
|
\Sentry\captureException($ex);
|
||||||
|
|
||||||
|
ob_clean();
|
||||||
|
|
||||||
|
http_response_code(500);
|
||||||
|
header('Content-Type: text/plain; charset=utf-8');
|
||||||
|
|
||||||
|
if(CRW_DEBUG)
|
||||||
|
echo (string)$ex;
|
||||||
|
else
|
||||||
|
echo 'Internal Server Error';
|
||||||
|
exit;
|
||||||
|
});
|
||||||
|
|
||||||
|
$ctx->getRouter()->dispatch();
|
2
public/robots.txt
Normal file
2
public/robots.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
User-agent: *
|
||||||
|
Disallow: /
|
58
src/AleisterContentHandler.php
Normal file
58
src/AleisterContentHandler.php
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister;
|
||||||
|
|
||||||
|
use JsonSerializable;
|
||||||
|
use Index\Bencode\IBencodeSerialisable;
|
||||||
|
use Index\Http\HttpResponseBuilder;
|
||||||
|
use Index\Http\ContentHandling\IContentHandler;
|
||||||
|
|
||||||
|
class AleisterContentHandler implements IContentHandler {
|
||||||
|
public function __construct(
|
||||||
|
private HttpAcceptHeader $accept
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function hasAcceptableType(): bool {
|
||||||
|
return $this->accept->getMostPreferred([
|
||||||
|
'application/json',
|
||||||
|
'text/html', // pretty printed JSON
|
||||||
|
]) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function match(mixed $content): bool {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(HttpResponseBuilder $response, mixed $content): void {
|
||||||
|
// mostly for debug and info pages, so we'll ignore the accept header for strings
|
||||||
|
if(is_string($content)) {
|
||||||
|
if(stripos($content, '<!doctype ') === 0)
|
||||||
|
$response->setTypeHTML('utf-8');
|
||||||
|
else
|
||||||
|
$response->setTypePlain('utf-8');
|
||||||
|
|
||||||
|
$response->setContent($content);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($content instanceof JsonSerializable)
|
||||||
|
$content = $content->jsonSerialize();
|
||||||
|
elseif($content instanceof IBencodeSerialisable)
|
||||||
|
$content = $content->bencodeSerialise();
|
||||||
|
|
||||||
|
// default to JSON
|
||||||
|
if(!$response->hasContentType())
|
||||||
|
$response->setTypeJson();
|
||||||
|
|
||||||
|
$flags = JSON_UNESCAPED_UNICODE
|
||||||
|
| JSON_UNESCAPED_SLASHES
|
||||||
|
| JSON_THROW_ON_ERROR
|
||||||
|
| JSON_PRESERVE_ZERO_FRACTION
|
||||||
|
| JSON_INVALID_UTF8_SUBSTITUTE;
|
||||||
|
|
||||||
|
// pretty print if text/html is acceptable, someone is likely poking using a browser
|
||||||
|
if($this->accept->isAcceptable('text/html'))
|
||||||
|
$flags |= JSON_PRETTY_PRINT;
|
||||||
|
|
||||||
|
$response->setContent(json_encode($content, $flags));
|
||||||
|
}
|
||||||
|
}
|
92
src/AleisterContext.php
Normal file
92
src/AleisterContext.php
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
use Aleister\RpcModels\Hanyuu\OAuth2AuthInfo;
|
||||||
|
use Index\Http\Routing\{HttpRouter,IRouter,IRouteHandler};
|
||||||
|
use Syokuhou\IConfig;
|
||||||
|
|
||||||
|
class AleisterContext {
|
||||||
|
private RpcClientWrapper $rpcWrapper;
|
||||||
|
private HttpRouter $router;
|
||||||
|
|
||||||
|
private OAuth2AuthInfo $authInfo;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private IConfig $config
|
||||||
|
) {
|
||||||
|
$this->authInfo = new OAuth2AuthInfo(['error' => 'none']);
|
||||||
|
|
||||||
|
$this->rpcWrapper = new RpcClientWrapper;
|
||||||
|
$this->rpcWrapper->createHmacConfig($config, 'hanyuu');
|
||||||
|
|
||||||
|
$this->router = new HttpRouter(
|
||||||
|
errorHandler: 'plain',
|
||||||
|
registerDefaultContentHandlers: false
|
||||||
|
);
|
||||||
|
$this->router->use('/', fn($resp) => $resp->setPoweredBy('Flashii'));
|
||||||
|
$this->router->use('/', $this->handleAcceptHeader(...));
|
||||||
|
$this->router->use('/', $this->handleAuthzHeader(...));
|
||||||
|
$this->router->get('/', fn() => '<!doctype html>Hello! Someday this page will probably redirect to documentation, but none exists yet.');
|
||||||
|
|
||||||
|
$this->router->scopeTo('/oauth2')->register(new OAuth2\OAuth2Routes($this));
|
||||||
|
$this->router->scopeTo('/v1')->register(new V1\V1Routes(new V1\V1Context($this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRpcClient(): RpcClientWrapper {
|
||||||
|
return $this->rpcWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRouter(): IRouter {
|
||||||
|
return $this->router;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthInfo(): OAuth2AuthInfo {
|
||||||
|
return $this->authInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleAcceptHeader($response, $request) {
|
||||||
|
$accept = HttpAcceptHeader::parse($request->getHeaderLine('Accept'));
|
||||||
|
$contentHandler = new AleisterContentHandler($accept);
|
||||||
|
|
||||||
|
if(!$contentHandler->hasAcceptableType())
|
||||||
|
return 406;
|
||||||
|
|
||||||
|
$this->router->setErrorHandler(new AleisterErrorHandler($contentHandler));
|
||||||
|
$this->router->registerContentHandler($contentHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleAuthzHeader($response, $request): void {
|
||||||
|
$authInfo = null;
|
||||||
|
|
||||||
|
$authzHeader = explode(' ', (string)$request->getHeaderLine('Authorization'), 2);
|
||||||
|
if(count($authzHeader) > 1) {
|
||||||
|
$authzMethod = array_shift($authzHeader);
|
||||||
|
$authzInfo = array_shift($authzHeader);
|
||||||
|
|
||||||
|
if(strcasecmp($authzMethod, 'basic') === 0) {
|
||||||
|
$authzInfo = base64_decode($authzInfo);
|
||||||
|
if($authzInfo !== false) {
|
||||||
|
$authzInfo = explode(':', $authzInfo, 2);
|
||||||
|
if(count($authzInfo) > 0)
|
||||||
|
try {
|
||||||
|
$authInfo = $this->rpcWrapper->procedure(
|
||||||
|
'hanyuu:oauth2:attemptAppAuth',
|
||||||
|
['clientId' => array_shift($authzInfo), 'clientSecret' => array_shift($authzInfo) ?? '']
|
||||||
|
);
|
||||||
|
} catch(RuntimeException $ex) {}
|
||||||
|
}
|
||||||
|
} elseif(strcasecmp($authzMethod, 'bearer') === 0) {
|
||||||
|
try {
|
||||||
|
$authInfo = $this->rpcWrapper->procedure(
|
||||||
|
'hanyuu:oauth2:getTokenInfo',
|
||||||
|
['type' => 'Bearer', 'token' => $authzInfo]
|
||||||
|
);
|
||||||
|
} catch(RuntimeException $ex) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($authInfo !== null)
|
||||||
|
$this->authInfo = new OAuth2AuthInfo($authInfo);
|
||||||
|
}
|
||||||
|
}
|
18
src/AleisterErrorHandler.php
Normal file
18
src/AleisterErrorHandler.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister;
|
||||||
|
|
||||||
|
use Index\Http\{HttpResponseBuilder,HttpRequest};
|
||||||
|
use Index\Http\ErrorHandling\IErrorHandler;
|
||||||
|
|
||||||
|
class AleisterErrorHandler implements IErrorHandler {
|
||||||
|
public function __construct(
|
||||||
|
private AleisterContentHandler $contentHandler,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function handle(HttpResponseBuilder $response, HttpRequest $request, int $code, string $message): void {
|
||||||
|
$this->contentHandler->handle($response, [
|
||||||
|
'code' => sprintf('http:%s', $code),
|
||||||
|
'message' => $message,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
59
src/HttpAcceptHeader.php
Normal file
59
src/HttpAcceptHeader.php
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister;
|
||||||
|
|
||||||
|
use Index\{MediaType,XString};
|
||||||
|
|
||||||
|
class HttpAcceptHeader {
|
||||||
|
public function __construct(
|
||||||
|
private array $accept,
|
||||||
|
) {
|
||||||
|
usort($this->accept, fn($a, $b) => $b->getQuality() <=> $a->getQuality());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAcceptable(string $option, bool $strict = false): bool {
|
||||||
|
if(empty($this->accept))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
foreach($this->accept as $type)
|
||||||
|
if($type->equals($option) && $type->getQuality() > 0
|
||||||
|
&& (!$strict || ($type->getCategory() !== '*' && $type->getKind() !== '*')))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMostPreferred(array $options = []): ?string {
|
||||||
|
if(empty($options))
|
||||||
|
return null;
|
||||||
|
if(empty($this->accept))
|
||||||
|
return $options[array_key_first($options)];
|
||||||
|
|
||||||
|
$prefer = null;
|
||||||
|
$weight = 0;
|
||||||
|
|
||||||
|
foreach($options as $option)
|
||||||
|
foreach($this->accept as $type) {
|
||||||
|
$quality = $type->getQuality();
|
||||||
|
if($quality <= 0 || $quality <= $weight || !$type->equals($option))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$prefer = $option;
|
||||||
|
$weight = $quality;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $prefer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function parse(string $header): HttpAcceptHeader {
|
||||||
|
$accept = [];
|
||||||
|
$types = explode(',', $header);
|
||||||
|
|
||||||
|
foreach($types as $type) {
|
||||||
|
$type = trim($type);
|
||||||
|
if($type !== '')
|
||||||
|
$accept[] = MediaType::parse($type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HttpAcceptHeader($accept);
|
||||||
|
}
|
||||||
|
}
|
190
src/OAuth2/OAuth2Routes.php
Normal file
190
src/OAuth2/OAuth2Routes.php
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister\OAuth2;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
use Aleister\AleisterContext;
|
||||||
|
use Aleister\RpcModels\Hanyuu\{OAuth2AuthInfo,OAuth2RfcModel};
|
||||||
|
use Index\Http\Routing\{HttpGet,HttpOptions,HttpPost,RouteHandler};
|
||||||
|
|
||||||
|
class OAuth2Routes extends RouteHandler {
|
||||||
|
public const REQ_AUTH_ERRORS = [
|
||||||
|
'invalid_request', 'invalid_client', 'invalid_grant', 'unauthorized_client',
|
||||||
|
'unsupported_grant_type', 'invalid_scope', 'server_error', 'temporarily_unavailable',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private AleisterContext $ctx
|
||||||
|
) {}
|
||||||
|
|
||||||
|
private static function filter($response, array $result, bool $authzHeader = false): array {
|
||||||
|
if(array_key_exists('error', $result)) {
|
||||||
|
if($authzHeader) {
|
||||||
|
$wwwAuth = sprintf('Basic realm="%s"', $_SERVER['HTTP_HOST']);
|
||||||
|
foreach($result as $name => $value)
|
||||||
|
$wwwAuth .= sprintf(', %s="%s"', $name, rawurlencode($value));
|
||||||
|
|
||||||
|
$response->setStatusCode(401);
|
||||||
|
$response->setHeader('WWW-Authenticate', $wwwAuth);
|
||||||
|
} else
|
||||||
|
$response->setStatusCode(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[HttpPost('/request-authorise')]
|
||||||
|
public function postRequestAuthorise($response, $request) {
|
||||||
|
$response->setHeader('Cache-Control', 'no-store');
|
||||||
|
|
||||||
|
$authInfo = $this->ctx->getAuthInfo();
|
||||||
|
if($authInfo->getError() === 'secret')
|
||||||
|
return self::filter($response, [
|
||||||
|
'error' => 'invalid_client',
|
||||||
|
'error_description' => 'Provided client secret is not correct for this application.',
|
||||||
|
], authzHeader: true);
|
||||||
|
|
||||||
|
if(!$request->isFormContent())
|
||||||
|
return self::filter($response, [
|
||||||
|
'error' => 'invalid_request',
|
||||||
|
'error_description' => 'Your request must use content type application/x-www-form-urlencoded.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$rpc = $this->ctx->getRpcClient();
|
||||||
|
$content = $request->getContent();
|
||||||
|
|
||||||
|
if($authInfo->getMethod() === '')
|
||||||
|
try {
|
||||||
|
$authInfo = new OAuth2AuthInfo($rpc->procedure('hanyuu:oauth2:attemptAppAuth', [
|
||||||
|
'clientId' => (string)$content->getParam('client_id'),
|
||||||
|
]));
|
||||||
|
} catch(RuntimeException $ex) {}
|
||||||
|
|
||||||
|
if(!$authInfo->isAppUser())
|
||||||
|
return self::filter($response, [
|
||||||
|
'error' => 'invalid_client',
|
||||||
|
'error_description' => 'App authentication failed.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$reqInfo = new OAuth2RfcModel($rpc->procedure('hanyuu:oauth2:createAuthoriseRequest', [
|
||||||
|
'appId' => $authInfo->getAppId(),
|
||||||
|
'scope' => (string)$content->getParam('scope'),
|
||||||
|
]));
|
||||||
|
} catch(RuntimeException $ex) {}
|
||||||
|
|
||||||
|
if($reqInfo === null || ($reqInfo->hasError() && !in_array($reqInfo->getError(), self::REQ_AUTH_ERRORS)))
|
||||||
|
return self::filter($response, [
|
||||||
|
'error' => 'server_error',
|
||||||
|
'error_description' => 'Authorisation server gave unexpected response.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return self::filter($response, $reqInfo->getRaw());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[HttpOptions('/token')]
|
||||||
|
#[HttpPost('/token')]
|
||||||
|
public function postToken($response, $request) {
|
||||||
|
$response->setHeader('Cache-Control', 'no-store');
|
||||||
|
|
||||||
|
$originHeaders = ['Origin', 'X-Origin', 'Referer'];
|
||||||
|
$origins = [];
|
||||||
|
foreach($originHeaders as $originHeader) {
|
||||||
|
$originHeader = $request->getHeaderFirstLine($originHeader);
|
||||||
|
if($originHeader !== '' && !in_array($originHeader, $origins))
|
||||||
|
$origins[] = $originHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!empty($origins)) {
|
||||||
|
// TODO: check if none of the provided origins is on a blocklist or something
|
||||||
|
// different origins being specified for each header should probably also be considered suspect...
|
||||||
|
|
||||||
|
$response->setHeader('Access-Control-Allow-Origin', $origins[0]);
|
||||||
|
$response->setHeader('Access-Control-Allow-Methods', 'OPTIONS, POST');
|
||||||
|
$response->setHeader('Access-Control-Allow-Headers', 'Authorization');
|
||||||
|
$response->setHeader('Access-Control-Expose-Headers', 'Vary');
|
||||||
|
foreach($originHeaders as $originHeader)
|
||||||
|
$response->setHeader('Vary', $originHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($request->getMethod() === 'OPTIONS')
|
||||||
|
return 204;
|
||||||
|
|
||||||
|
if(!$request->isFormContent())
|
||||||
|
return self::filter($response, [
|
||||||
|
'error' => 'invalid_request',
|
||||||
|
'error_description' => 'Your request must use content type application/x-www-form-urlencoded.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$rpc = $this->ctx->getRpcClient();
|
||||||
|
$content = $request->getContent();
|
||||||
|
|
||||||
|
$authInfo = $this->ctx->getAuthInfo();
|
||||||
|
if($authInfo->getMethod() === '')
|
||||||
|
try {
|
||||||
|
$authInfo = new OAuth2AuthInfo($rpc->procedure('hanyuu:oauth2:attemptAppAuth', [
|
||||||
|
'clientId' => (string)$content->getParam('client_id'),
|
||||||
|
'clientSecret' => (string)$content->getParam('client_secret')
|
||||||
|
]));
|
||||||
|
} catch(RuntimeException $ex) {
|
||||||
|
$authInfo = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($authInfo === null || !$authInfo->isAppUser())
|
||||||
|
return self::filter($response, [
|
||||||
|
'error' => 'invalid_client',
|
||||||
|
'error_description' => 'App authentication failed.',
|
||||||
|
]);
|
||||||
|
if($authInfo->getError() === 'secret')
|
||||||
|
return self::filter($response, [
|
||||||
|
'error' => 'invalid_client',
|
||||||
|
'error_description' => 'Provided client secret is not correct for this application.'
|
||||||
|
], authzHeader: true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$name = '';
|
||||||
|
$args = ['appId' => $authInfo->getAppId(), 'isAuthed' => $authInfo->isAuthed()];
|
||||||
|
|
||||||
|
switch($content->getParam('grant_type')) {
|
||||||
|
case 'authorization_code':
|
||||||
|
$name = 'authorisationCode';
|
||||||
|
$args['code'] = (string)$content->getParam('code');
|
||||||
|
$args['codeVerifier'] = (string)$content->getParam('code_verifier');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'refresh_token':
|
||||||
|
$name = 'refreshToken';
|
||||||
|
$args['refreshToken'] = (string)$content->getParam('refresh_token');
|
||||||
|
|
||||||
|
if($content->hasParam('scope'))
|
||||||
|
$args['scope'] = (string)$content->getParam('scope');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'client_credentials':
|
||||||
|
$name = 'clientCredentials';
|
||||||
|
|
||||||
|
if($content->hasParam('scope'))
|
||||||
|
$args['scope'] = (string)$content->getParam('scope');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'urn:ietf:params:oauth:grant-type:device_code':
|
||||||
|
case 'device_code':
|
||||||
|
$name = 'deviceCode';
|
||||||
|
$args['deviceCode'] = (string)$content->getParam('device_code');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($name === '')
|
||||||
|
return self::filter($response, [
|
||||||
|
'error' => 'unsupported_grant_type',
|
||||||
|
'error_description' => 'Requested grant type is not supported by this server.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return self::filter($response, $rpc->procedure('hanyuu:oauth2:createBearerToken:' . $name, $args));
|
||||||
|
} catch(RuntimeException $ex) {
|
||||||
|
return self::filter($response, [
|
||||||
|
'error' => 'server_error',
|
||||||
|
'error_description' => 'Authorisation server gave unexpected response.',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
src/RpcClientWrapper.php
Normal file
47
src/RpcClientWrapper.php
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
use Aiwass\Client\{IRpcClient,RpcClient,RpcClientScoped};
|
||||||
|
use Syokuhou\IConfig;
|
||||||
|
|
||||||
|
class RpcClientWrapper implements IRpcClient {
|
||||||
|
private array $clients = [];
|
||||||
|
|
||||||
|
public function createHmacConfig(IConfig $config, string $prefix): void {
|
||||||
|
$config = $config->scopeTo($prefix);
|
||||||
|
$this->createHmac(
|
||||||
|
$prefix . ':',
|
||||||
|
$config->getString('endpoint'),
|
||||||
|
fn() => $config->getString('secret')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createHmac(string $prefix, string $url, $getSecretKey): void {
|
||||||
|
$this->register($prefix, RpcClient::createHmac($url, $getSecretKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register(string $prefix, IRpcClient $client): void {
|
||||||
|
$this->clients[$prefix] = $client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function scopeTo(string $prefix): IRpcClient {
|
||||||
|
return new RpcClientScoped($this, $prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function query(string $action, array $params): mixed {
|
||||||
|
foreach($this->clients as $prefix => $client)
|
||||||
|
if(str_starts_with($action, $prefix))
|
||||||
|
return $client->query($action, $params);
|
||||||
|
|
||||||
|
throw new RuntimeException(sprintf('Unable to handle this query: %s', $action));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function procedure(string $action, array $params): mixed {
|
||||||
|
foreach($this->clients as $prefix => $client)
|
||||||
|
if(str_starts_with($action, $prefix))
|
||||||
|
return $client->procedure($action, $params);
|
||||||
|
|
||||||
|
throw new RuntimeException(sprintf('Unable to handle this procedure: %s', $action));
|
||||||
|
}
|
||||||
|
}
|
38
src/RpcModels/Hanyuu/OAuth2AuthInfo.php
Normal file
38
src/RpcModels/Hanyuu/OAuth2AuthInfo.php
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister\RpcModels\Hanyuu;
|
||||||
|
|
||||||
|
use Aleister\RpcModels\RpcModel;
|
||||||
|
|
||||||
|
class OAuth2AuthInfo extends RpcModel {
|
||||||
|
public function getMethod(): string {
|
||||||
|
return $this->getString('method');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAuthed(): bool {
|
||||||
|
return $this->getBoolean('authed');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAppId(): string {
|
||||||
|
return $this->getString('app_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasUserId(): bool {
|
||||||
|
return $this->hasValue('user_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAppUser(): bool {
|
||||||
|
return $this->getMethod() === 'basic' || $this->getUserId() === '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserId(): string {
|
||||||
|
return $this->getString('user_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getScope(): string {
|
||||||
|
return $this->getString('scope');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExpiresIn(): int {
|
||||||
|
return $this->getInteger('expires_in');
|
||||||
|
}
|
||||||
|
}
|
22
src/RpcModels/Hanyuu/OAuth2RfcModel.php
Normal file
22
src/RpcModels/Hanyuu/OAuth2RfcModel.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister\RpcModels\Hanyuu;
|
||||||
|
|
||||||
|
use Aleister\RpcModels\RpcModel;
|
||||||
|
|
||||||
|
class OAuth2RfcModel extends RpcModel {
|
||||||
|
public function hasErrorDescription(): bool {
|
||||||
|
return $this->hasValue('error_description');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getErrorDescription(): string {
|
||||||
|
return $this->getString('error_description');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasErrorUri(): bool {
|
||||||
|
return $this->hasValue('error_uri');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getErrorUri(): string {
|
||||||
|
return $this->getString('error_uri');
|
||||||
|
}
|
||||||
|
}
|
55
src/RpcModels/RpcModel.php
Normal file
55
src/RpcModels/RpcModel.php
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister\RpcModels;
|
||||||
|
|
||||||
|
abstract class RpcModel {
|
||||||
|
protected array $info;
|
||||||
|
|
||||||
|
public function __construct(array $info) {
|
||||||
|
$this->info = $info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasError(): bool {
|
||||||
|
return $this->hasValue('error');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getError(): string {
|
||||||
|
return $this->getString('error');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRaw(): array {
|
||||||
|
return $this->info;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function hasValue(string $name): bool {
|
||||||
|
return array_key_exists($name, $this->info);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getValue(string $name, mixed $fallback = null): mixed {
|
||||||
|
return array_key_exists($name, $this->info) ? $this->info[$name] : $fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getArray(string $name): array {
|
||||||
|
return array_key_exists($name, $this->info) && is_array($this->info[$name])
|
||||||
|
? $this->info[$name] : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getBoolean(string $name): bool {
|
||||||
|
return array_key_exists($name, $this->info) && is_bool($this->info[$name])
|
||||||
|
&& $this->info[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getInteger(string $name): int {
|
||||||
|
return array_key_exists($name, $this->info) && is_int($this->info[$name])
|
||||||
|
? $this->info[$name] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getFloat(string $name): float {
|
||||||
|
return array_key_exists($name, $this->info) && is_float($this->info[$name])
|
||||||
|
? $this->info[$name] : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getString(string $name): string {
|
||||||
|
return array_key_exists($name, $this->info) && is_string($this->info[$name])
|
||||||
|
? $this->info[$name] : '';
|
||||||
|
}
|
||||||
|
}
|
20
src/V1/V1Context.php
Normal file
20
src/V1/V1Context.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister\V1;
|
||||||
|
|
||||||
|
use Aleister\AleisterContext;
|
||||||
|
use Aleister\RpcModels\Hanyuu\OAuth2AuthInfo;
|
||||||
|
use Aiwass\Client\IRpcClient;
|
||||||
|
|
||||||
|
class V1Context {
|
||||||
|
public function __construct(
|
||||||
|
private AleisterContext $ctx
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function getRpcClient(): IRpcClient {
|
||||||
|
return $this->ctx->getRpcClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthInfo(): OAuth2AuthInfo {
|
||||||
|
return $this->ctx->getAuthInfo();
|
||||||
|
}
|
||||||
|
}
|
16
src/V1/V1Routes.php
Normal file
16
src/V1/V1Routes.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
namespace Aleister\V1;
|
||||||
|
|
||||||
|
use Aleister\RpcModels\Hanyuu\OAuth2AuthInfo;
|
||||||
|
use Aiwass\Client\IRpcClient;
|
||||||
|
use Index\Http\Routing\{IRouter,IRouteHandler};
|
||||||
|
|
||||||
|
class V1Routes implements IRouteHandler {
|
||||||
|
public function __construct(
|
||||||
|
private V1Context $ctx
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function registerRoutes(IRouter $router): void {
|
||||||
|
$router->get('/', fn() => ['status' => 'operational']);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue