Compare commits
8 commits
js-rewrite
...
trunk
Author | SHA1 | Date | |
---|---|---|---|
7805bbae68 |
|||
a482719a32 |
|||
5bac7dac34 |
|||
5a468051ce |
|||
31a4b84dd5 |
|||
6e177caaf8 |
|||
a8359af2e3 | |||
55918d5cab |
13 changed files with 271 additions and 260 deletions
30
LICENCE
Normal file
30
LICENCE
Normal file
|
@ -0,0 +1,30 @@
|
|||
Copyright (c) 2021-2025, 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 @@
|
|||
# Uiharu
|
||||
|
||||
Uiharu is a service that looks up metadata for a given URL.
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"require": {
|
||||
"flashwave/index": "^0.2410",
|
||||
"flashwave/index": "^0.2503",
|
||||
"sentry/sdk": "^4.0"
|
||||
},
|
||||
"autoload": {
|
||||
|
|
289
composer.lock
generated
289
composer.lock
generated
|
@ -4,25 +4,27 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "023574a93f076ef7a987151cdbfdb33e",
|
||||
"content-hash": "ca6ae2c3d6229791acf93914e055bf41",
|
||||
"packages": [
|
||||
{
|
||||
"name": "flashwave/index",
|
||||
"version": "v0.2410.191603",
|
||||
"version": "v0.2503.211818",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://patchii.net/flash/index.git",
|
||||
"reference": "17cdb4d1c239241200d7e30968122a8cd8b26509"
|
||||
"reference": "8df1d32304eebab3f8d005634353c496679d5a87"
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": ">=8.3",
|
||||
"twig/html-extra": "^3.13",
|
||||
"twig/twig": "^3.14"
|
||||
"php": ">=8.4",
|
||||
"psr/http-message": "^2.0",
|
||||
"psr/http-server-handler": "^1.0",
|
||||
"twig/html-extra": "^3.20",
|
||||
"twig/twig": "^3.20"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.11",
|
||||
"phpunit/phpunit": "^11.2"
|
||||
"phpstan/phpstan": "^2.1",
|
||||
"phpunit/phpunit": "^12.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-memcache": "Support for the Index\\Cache\\Memcached namespace (only if you can't use ext-memcached for some reason).",
|
||||
|
@ -59,7 +61,7 @@
|
|||
],
|
||||
"description": "Composer package for the common library for my projects.",
|
||||
"homepage": "https://railgun.sh/index",
|
||||
"time": "2024-10-19T16:04:17+00:00"
|
||||
"time": "2025-03-21T18:19:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
|
@ -179,28 +181,29 @@
|
|||
},
|
||||
{
|
||||
"name": "jean85/pretty-package-versions",
|
||||
"version": "2.0.6",
|
||||
"version": "2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Jean85/pretty-package-versions.git",
|
||||
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4"
|
||||
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4",
|
||||
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4",
|
||||
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/4d7aa5dab42e2a76d99559706022885de0e18e1a",
|
||||
"reference": "4d7aa5dab42e2a76d99559706022885de0e18e1a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-runtime-api": "^2.0.0",
|
||||
"php": "^7.1|^8.0"
|
||||
"composer-runtime-api": "^2.1.0",
|
||||
"php": "^7.4|^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"
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpunit/phpunit": "^7.5|^8.5|^9.6",
|
||||
"rector/rector": "^2.0",
|
||||
"vimeo/psalm": "^4.3 || ^5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
@ -232,9 +235,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
|
||||
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6"
|
||||
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.1"
|
||||
},
|
||||
"time": "2024-03-08T09:58:59+00:00"
|
||||
"time": "2025-03-19T14:43:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-factory",
|
||||
|
@ -344,6 +347,62 @@
|
|||
},
|
||||
"time": "2023-04-04T09:54:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-server-handler",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-server-handler.git",
|
||||
"reference": "84c4fb66179be4caaf8e97bd239203245302e7d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-server-handler/zipball/84c4fb66179be4caaf8e97bd239203245302e7d4",
|
||||
"reference": "84c4fb66179be4caaf8e97bd239203245302e7d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0",
|
||||
"psr/http-message": "^1.0 || ^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Server\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP server-side request handler",
|
||||
"keywords": [
|
||||
"handler",
|
||||
"http",
|
||||
"http-interop",
|
||||
"psr",
|
||||
"psr-15",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response",
|
||||
"server"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-server-handler/tree/1.0.2"
|
||||
},
|
||||
"time": "2023-04-10T20:06:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "3.0.2",
|
||||
|
@ -495,16 +554,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sentry/sentry",
|
||||
"version": "4.9.0",
|
||||
"version": "4.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/getsentry/sentry-php.git",
|
||||
"reference": "788ec170f51ebb22f2809a1e3f78b19ccd39b70d"
|
||||
"reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/788ec170f51ebb22f2809a1e3f78b19ccd39b70d",
|
||||
"reference": "788ec170f51ebb22f2809a1e3f78b19ccd39b70d",
|
||||
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/2af937d47d8aadb8dab0b1d7b9557e495dd12856",
|
||||
"reference": "2af937d47d8aadb8dab0b1d7b9557e495dd12856",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -522,12 +581,12 @@
|
|||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.4",
|
||||
"guzzlehttp/promises": "^1.0|^2.0",
|
||||
"guzzlehttp/promises": "^2.0.3",
|
||||
"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",
|
||||
"phpunit/phpunit": "^8.5|^9.6",
|
||||
"symfony/phpunit-bridge": "^5.2|^6.0|^7.0",
|
||||
"vimeo/psalm": "^4.17"
|
||||
},
|
||||
|
@ -568,7 +627,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/getsentry/sentry-php/issues",
|
||||
"source": "https://github.com/getsentry/sentry-php/tree/4.9.0"
|
||||
"source": "https://github.com/getsentry/sentry-php/tree/4.10.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -580,20 +639,20 @@
|
|||
"type": "custom"
|
||||
}
|
||||
],
|
||||
"time": "2024-08-08T14:40:50+00:00"
|
||||
"time": "2024-11-06T07:44:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.5.0",
|
||||
"version": "v3.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
|
||||
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
|
||||
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
|
||||
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -601,12 +660,12 @@
|
|||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.5-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -631,7 +690,7 @@
|
|||
"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"
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -647,20 +706,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-04-18T09:32:20+00:00"
|
||||
"time": "2024-09-25T14:20:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/mime",
|
||||
"version": "v7.1.5",
|
||||
"version": "v7.2.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/mime.git",
|
||||
"reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff"
|
||||
"reference": "87ca22046b78c3feaff04b337f33b38510fd686b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/711d2e167e8ce65b05aea6b258c449671cdd38ff",
|
||||
"reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff",
|
||||
"url": "https://api.github.com/repos/symfony/mime/zipball/87ca22046b78c3feaff04b337f33b38510fd686b",
|
||||
"reference": "87ca22046b78c3feaff04b337f33b38510fd686b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -715,7 +774,7 @@
|
|||
"mime-type"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/mime/tree/v7.1.5"
|
||||
"source": "https://github.com/symfony/mime/tree/v7.2.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -731,20 +790,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-20T08:28:38+00:00"
|
||||
"time": "2025-02-19T08:51:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/options-resolver",
|
||||
"version": "v7.1.1",
|
||||
"version": "v7.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/options-resolver.git",
|
||||
"reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55"
|
||||
"reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/47aa818121ed3950acd2b58d1d37d08a94f9bf55",
|
||||
"reference": "47aa818121ed3950acd2b58d1d37d08a94f9bf55",
|
||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
|
||||
"reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -782,7 +841,7 @@
|
|||
"options"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.1.1"
|
||||
"source": "https://github.com/symfony/options-resolver/tree/v7.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -798,7 +857,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-05-31T14:57:53+00:00"
|
||||
"time": "2024-11-20T11:17:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
|
@ -826,8 +885,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -903,8 +962,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -985,8 +1044,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1069,8 +1128,8 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -1123,98 +1182,22 @@
|
|||
],
|
||||
"time": "2024-09-09T11:45:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php81",
|
||||
"version": "v1.31.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
|
||||
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php81\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"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": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php81/tree/v1.31.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-09-09T11:45:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/html-extra",
|
||||
"version": "v3.13.0",
|
||||
"version": "v3.20.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/html-extra.git",
|
||||
"reference": "8229e750091171c1f11801a525927811c7ac5a7e"
|
||||
"reference": "f7d54d4de1b64182af745cfb66777f699b599734"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/html-extra/zipball/8229e750091171c1f11801a525927811c7ac5a7e",
|
||||
"reference": "8229e750091171c1f11801a525927811c7ac5a7e",
|
||||
"url": "https://api.github.com/repos/twigphp/html-extra/zipball/f7d54d4de1b64182af745cfb66777f699b599734",
|
||||
"reference": "f7d54d4de1b64182af745cfb66777f699b599734",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.2",
|
||||
"php": ">=8.1.0",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/mime": "^5.4|^6.4|^7.0",
|
||||
"twig/twig": "^3.13|^4.0"
|
||||
|
@ -1253,7 +1236,7 @@
|
|||
"twig"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/twigphp/html-extra/tree/v3.13.0"
|
||||
"source": "https://github.com/twigphp/html-extra/tree/v3.20.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1265,30 +1248,30 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-03T13:08:40+00:00"
|
||||
"time": "2025-01-31T20:45:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.14.0",
|
||||
"version": "v3.20.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72"
|
||||
"reference": "3468920399451a384bef53cf7996965f7cd40183"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
|
||||
"reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/3468920399451a384bef53cf7996965f7cd40183",
|
||||
"reference": "3468920399451a384bef53cf7996965f7cd40183",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.2",
|
||||
"php": ">=8.1.0",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/polyfill-ctype": "^1.8",
|
||||
"symfony/polyfill-mbstring": "^1.3",
|
||||
"symfony/polyfill-php81": "^1.29"
|
||||
"symfony/polyfill-mbstring": "^1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"psr/container": "^1.0|^2.0",
|
||||
"symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
|
||||
},
|
||||
|
@ -1332,7 +1315,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.14.0"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.20.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1344,16 +1327,16 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-09-09T17:55:12+00:00"
|
||||
"time": "2025-02-13T08:34:43+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"platform": {},
|
||||
"platform-dev": {},
|
||||
"plugin-api-version": "2.6.0"
|
||||
}
|
||||
|
|
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -126,9 +126,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
||||
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
|
||||
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^2.0.0",
|
||||
|
@ -208,9 +208,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz",
|
||||
"integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==",
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
|
||||
"integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"entities": "^4.5.0"
|
||||
|
@ -251,9 +251,9 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.20.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.20.1.tgz",
|
||||
"integrity": "sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==",
|
||||
"version": "6.21.2",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.2.tgz",
|
||||
"integrity": "sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="uiharu-footer">
|
||||
<a href="https://flash.moe" target="_blank" rel="noopener">flashwave</a> 2021-2024
|
||||
<a href="https://flash.moe" target="_blank" rel="noopener">flashwave</a> 2021-2025
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,9 +3,9 @@ namespace Uiharu;
|
|||
|
||||
require_once __DIR__ . '/../uiharu.php';
|
||||
|
||||
$ctx->registerLookup(new \Uiharu\Lookup\EEPROMLookup('eeprom', 'eeprom.flashii.net', ['i.fii.moe', 'i.flashii.net']));
|
||||
$ctx->registerLookup(new \Uiharu\Lookup\EEPROMLookup('eeprom', 'flashii.net', ['i.fii.moe', 'i.flashii.net']));
|
||||
if(UIH_DEBUG)
|
||||
$ctx->registerLookup(new \Uiharu\Lookup\EEPROMLookup('devrom', 'eeprom.edgii.net', ['i.edgii.net']));
|
||||
$ctx->registerLookup(new \Uiharu\Lookup\EEPROMLookup('devrom', 'edgii.net', ['i.edgii.net']));
|
||||
|
||||
$ctx->registerLookup(new \Uiharu\Lookup\YouTubeLookup($cfg->scopeTo('google')));
|
||||
$ctx->registerLookup(new \Uiharu\Lookup\NicoNicoLookup);
|
||||
|
|
|
@ -17,11 +17,15 @@ use Uiharu\Lookup\NicoNicoLookupResult;
|
|||
use Index\MediaType;
|
||||
use Index\Cache\CacheProvider;
|
||||
use Index\Colour\{Colour,ColourRgb};
|
||||
use Index\Http\Routing\{HttpGet,HttpPost,RouteHandlerTrait};
|
||||
use Index\Http\{HttpRequest,HttpResponseBuilder};
|
||||
use Index\Http\Routing\RouteHandlerCommon;
|
||||
use Index\Http\Routing\AccessControl\AccessControl;
|
||||
use Index\Http\Routing\Routes\ExactRoute;
|
||||
use Index\Http\Streams\Stream;
|
||||
use Index\Performance\Stopwatch;
|
||||
|
||||
final class v1_0 implements \Uiharu\IApi {
|
||||
use RouteHandlerTrait;
|
||||
use RouteHandlerCommon;
|
||||
|
||||
private UihContext $ctx;
|
||||
private CacheProvider $cache;
|
||||
|
@ -35,8 +39,9 @@ final class v1_0 implements \Uiharu\IApi {
|
|||
return !str_starts_with($url, '/v');
|
||||
}
|
||||
|
||||
#[HttpGet('/metadata/thumb/audio')]
|
||||
public function getThumbAudio($response, $request) {
|
||||
#[AccessControl]
|
||||
#[ExactRoute('GET', '/metadata/thumb/audio')]
|
||||
public function getThumbAudio(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$targetUrl = (string)$request->getParam('url');
|
||||
|
||||
if(empty($targetUrl))
|
||||
|
@ -53,11 +58,12 @@ final class v1_0 implements \Uiharu\IApi {
|
|||
|
||||
$response->setContentType('image/png');
|
||||
$response->setCacheControl('public', 'max-age=31536000', 'immutable');
|
||||
$response->setContent(FFMPEG::grabFirstAudioCover($parsedUrl));
|
||||
$response->body = Stream::createStream(FFMPEG::grabFirstAudioCover($parsedUrl));
|
||||
}
|
||||
|
||||
#[HttpGet('/metadata/thumb/video')]
|
||||
public function getThumbVideo($response, $request) {
|
||||
#[AccessControl]
|
||||
#[ExactRoute('GET', '/metadata/thumb/video')]
|
||||
public function getThumbVideo(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
$targetUrl = (string)$request->getParam('url');
|
||||
|
||||
if(empty($targetUrl))
|
||||
|
@ -74,55 +80,37 @@ final class v1_0 implements \Uiharu\IApi {
|
|||
|
||||
$response->setContentType('image/png');
|
||||
$response->setCacheControl('public', 'max-age=31536000', 'immutable');
|
||||
$response->setContent(FFMPEG::grabFirstVideoFrame($parsedUrl));
|
||||
$response->body = Stream::createStream(FFMPEG::grabFirstVideoFrame($parsedUrl));
|
||||
}
|
||||
|
||||
#[HttpGet('/metadata')]
|
||||
public function getMetadata($response, $request) {
|
||||
if($request->getMethod() === 'HEAD') {
|
||||
$response->setTypeJson();
|
||||
return;
|
||||
}
|
||||
|
||||
#[AccessControl]
|
||||
#[ExactRoute('GET', '/metadata')]
|
||||
public function getMetadata(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
return $this->handleMetadata(
|
||||
$response, $request,
|
||||
(string)$request->getParam('url')
|
||||
);
|
||||
}
|
||||
|
||||
#[HttpPost('/metadata')]
|
||||
public function postMetadata($response, $request) {
|
||||
if(!$request->isStringContent())
|
||||
return 400;
|
||||
|
||||
#[AccessControl]
|
||||
#[ExactRoute('POST', '/metadata')]
|
||||
public function postMetadata(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
return $this->handleMetadata(
|
||||
$response, $request,
|
||||
(string)$request->getContent()
|
||||
(string)$request->getBody()
|
||||
);
|
||||
}
|
||||
|
||||
#[HttpGet('/metadata/batch')]
|
||||
public function getMetadataBatch($response, $request) {
|
||||
if($request->getMethod() === 'HEAD') {
|
||||
$response->setTypeJson();
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->handleMetadataBatch(
|
||||
$response, $request,
|
||||
$request->getParam('url', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY)
|
||||
);
|
||||
#[AccessControl]
|
||||
#[ExactRoute('GET', '/metadata/batch')]
|
||||
public function getMetadataBatch(): int {
|
||||
return 410;
|
||||
}
|
||||
|
||||
#[HttpPost('/metadata/batch')]
|
||||
public function postMetadataBatch($response, $request) {
|
||||
if(!$request->isFormContent())
|
||||
return 400;
|
||||
|
||||
return $this->handleMetadataBatch(
|
||||
$response, $request,
|
||||
$request->getContent()->getParam('url', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY)
|
||||
);
|
||||
#[AccessControl]
|
||||
#[ExactRoute('POST', '/metadata/batch')]
|
||||
public function postMetadataBatch(): int {
|
||||
return 410;
|
||||
}
|
||||
|
||||
private function metadataLookup(string $targetUrl) {
|
||||
|
@ -172,11 +160,11 @@ final class v1_0 implements \Uiharu\IApi {
|
|||
$resp->content_type = MediaTypeExts::toV1($result->getMediaType());
|
||||
if($result->hasColour()) {
|
||||
$colour = $result->getColour();
|
||||
if($colour->getAlpha() < 1.0)
|
||||
if($colour->alpha < 1.0)
|
||||
$colour = new ColourRgb(
|
||||
$colour->getRed(),
|
||||
$colour->getGreen(),
|
||||
$colour->getBlue()
|
||||
$colour->red,
|
||||
$colour->green,
|
||||
$colour->blue,
|
||||
);
|
||||
|
||||
$resp->color = (string)$colour;
|
||||
|
@ -278,7 +266,7 @@ final class v1_0 implements \Uiharu\IApi {
|
|||
}
|
||||
|
||||
$sw->stop();
|
||||
$resp->took = $sw->getElapsedTime() / 1000;
|
||||
$resp->took = $sw->elapsedTime / 1000;
|
||||
$respJson = json_encode($resp);
|
||||
|
||||
$this->cache->set($cacheKey, $respJson, 10 * 60);
|
||||
|
@ -290,14 +278,14 @@ final class v1_0 implements \Uiharu\IApi {
|
|||
return $resp;
|
||||
}
|
||||
|
||||
private function handleMetadata($response, $request, string $targetUrl) {
|
||||
private function handleMetadata(HttpResponseBuilder $response, HttpRequest $request, string $targetUrl) {
|
||||
$result = $this->metadataLookup($targetUrl);
|
||||
if(is_int($result))
|
||||
return $result;
|
||||
|
||||
if(is_object($result)) {
|
||||
if(!empty($result->status))
|
||||
$response->setStatusCode($result->status);
|
||||
$response->statusCode = $result->status;
|
||||
} elseif(is_string($result)) {
|
||||
$response->setTypeJson();
|
||||
}
|
||||
|
@ -305,7 +293,7 @@ final class v1_0 implements \Uiharu\IApi {
|
|||
return $result;
|
||||
}
|
||||
|
||||
private function handleMetadataBatch($response, $request, array $urls) {
|
||||
private function handleMetadataBatch(HttpResponseBuilder $response, HttpRequest $request, array $urls) {
|
||||
$sw = Stopwatch::startNew();
|
||||
|
||||
if(count($urls) > 20)
|
||||
|
|
|
@ -61,7 +61,9 @@ final class EEPROMLookup implements \Uiharu\ILookup {
|
|||
|
||||
if(!isset($fileId))
|
||||
throw new RuntimeException('Was unable to find EEPROM file id.');
|
||||
if(!preg_match('#^([A-Za-z0-9-_]+)$#', $fileId))
|
||||
|
||||
$fileId = pathinfo($fileId, PATHINFO_FILENAME);
|
||||
if(!is_string($fileId) || !preg_match('#^([A-Za-z0-9-_]+)$#', $fileId))
|
||||
throw new RuntimeException('Invalid EEPROM file id format.');
|
||||
|
||||
$fileInfo = $this->rawLookup($fileId);
|
||||
|
|
|
@ -141,7 +141,7 @@ final class WebLookup implements \Uiharu\ILookup {
|
|||
// and i'm not about to rewrite this whole fucking thing in nodejs
|
||||
// also at this point Index should probably provide a wrapper for proc_open lol
|
||||
$extract = proc_open(
|
||||
sprintf('node %s/extract.mjs', UIH_ROOT),
|
||||
sprintf('/opt/nodejs/bin/node %s/extract.mjs', UIH_ROOT),
|
||||
[0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
|
||||
$pipes
|
||||
);
|
||||
|
|
|
@ -7,14 +7,14 @@ final class MediaTypeExts {
|
|||
public static function toV1(MediaType $mediaType): array {
|
||||
$parts = [
|
||||
'string' => (string)$mediaType,
|
||||
'type' => $mediaType->getCategory(),
|
||||
'subtype' => $mediaType->getKind(),
|
||||
'type' => $mediaType->category,
|
||||
'subtype' => $mediaType->kind,
|
||||
];
|
||||
|
||||
if(!empty($suffix = $mediaType->getSuffix()))
|
||||
if(!empty($suffix = $mediaType->suffix))
|
||||
$parts['suffix'] = $suffix;
|
||||
|
||||
if(!empty($params = $mediaType->getParams()))
|
||||
if(!empty($params = $mediaType->params))
|
||||
$parts['params'] = $params;
|
||||
|
||||
return $parts;
|
||||
|
|
|
@ -3,12 +3,15 @@ namespace Uiharu;
|
|||
|
||||
use Index\Cache\CacheProvider;
|
||||
use Index\Config\Config;
|
||||
use Index\Http\Routing\HttpRouter;
|
||||
use Index\Http\HttpResponseBuilder;
|
||||
use Index\Http\Routing\{Router,RouteHandler,RouteHandlerCommon};
|
||||
use Index\Http\Routing\Filters\PrefixFilter;
|
||||
use Index\Http\Routing\Routes\ExactRoute;
|
||||
|
||||
final class UihContext {
|
||||
private CacheProvider $cache;
|
||||
private Config $config;
|
||||
private HttpRouter $router;
|
||||
private Router $router;
|
||||
private array $apis = [];
|
||||
private array $lookups = [];
|
||||
|
||||
|
@ -21,52 +24,28 @@ final class UihContext {
|
|||
return $this->cache;
|
||||
}
|
||||
|
||||
public function getRouter(): HttpRouter {
|
||||
public function getRouter(): Router {
|
||||
return $this->router;
|
||||
}
|
||||
|
||||
public function isOriginAllowed(string $origin): bool {
|
||||
$origin = mb_strtolower(parse_url($origin, PHP_URL_HOST));
|
||||
|
||||
if($origin === $_SERVER['HTTP_HOST'])
|
||||
return true;
|
||||
|
||||
$allowed = $this->config->getArray('cors:origins');
|
||||
if(empty($allowed))
|
||||
return true;
|
||||
|
||||
return in_array($origin, $allowed);
|
||||
}
|
||||
|
||||
public function setupHttp(): void {
|
||||
$this->router = new HttpRouter;
|
||||
$this->router->use('/', function($response) {
|
||||
$response->setPoweredBy('Uiharu');
|
||||
});
|
||||
$this->router = new Router(
|
||||
accessControlHandler: new UiharuAccessControlHandler($this->config->getArray('cors:origins')),
|
||||
);
|
||||
$this->router->register(new class implements RouteHandler {
|
||||
use RouteHandlerCommon;
|
||||
|
||||
$this->router->use('/', function($response, $request) {
|
||||
$origin = $request->getHeaderLine('Origin');
|
||||
|
||||
if(!empty($origin)) {
|
||||
if(!$this->isOriginAllowed($origin))
|
||||
return 403;
|
||||
|
||||
$response->setHeader('Access-Control-Allow-Origin', $origin);
|
||||
$response->setHeader('Vary', 'Origin');
|
||||
#[PrefixFilter('/')]
|
||||
public function filterPoweredBy(HttpResponseBuilder $response): void {
|
||||
$response->setPoweredBy('Uiharu');
|
||||
}
|
||||
});
|
||||
|
||||
$this->router->use('/', function($response, $request) {
|
||||
if($request->getMethod() === 'OPTIONS') {
|
||||
$response->setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST');
|
||||
return 204;
|
||||
#[ExactRoute('GET', '/')]
|
||||
public function getIndex(HttpResponseBuilder $response): void {
|
||||
$response->accelRedirect('/index.html');
|
||||
$response->setContentType('text/html; charset=utf-8');
|
||||
}
|
||||
});
|
||||
|
||||
$this->router->get('/', function($response) {
|
||||
$response->accelRedirect('/index.html');
|
||||
$response->setContentType('text/html; charset=utf-8');
|
||||
});
|
||||
}
|
||||
|
||||
public function dispatchHttp(): void {
|
||||
|
|
26
src/UiharuAccessControlHandler.php
Normal file
26
src/UiharuAccessControlHandler.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
namespace Uiharu;
|
||||
|
||||
use Index\Http\HttpUri;
|
||||
use Index\Http\Routing\HandlerContext;
|
||||
use Index\Http\Routing\Routes\RouteInfo;
|
||||
use Index\Http\Routing\AccessControl\{AccessControl,SimpleAccessControlHandler};
|
||||
|
||||
class UiharuAccessControlHandler extends SimpleAccessControlHandler {
|
||||
public function __construct(
|
||||
private array $origins,
|
||||
) {}
|
||||
|
||||
#[\Override]
|
||||
public function checkAccess(
|
||||
HandlerContext $context,
|
||||
AccessControl $accessControl,
|
||||
HttpUri $origin,
|
||||
?RouteInfo $routeInfo = null,
|
||||
): string|bool {
|
||||
if(!in_array($origin->host, $this->origins))
|
||||
return false;
|
||||
|
||||
return $accessControl->credentials ? (string)$origin : true;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue