Browse Source

Merge pull request #2121 from sspanel-uim/dev

Dev 20230816
M1Screw 2 years ago
parent
commit
169d5e49e8

+ 1 - 0
composer.json

@@ -22,6 +22,7 @@
         "illuminate/pagination": "^10.0",
         "irazasyed/telegram-bot-sdk": "^3",
         "khanamiryan/qrcode-detector-decoder": "*",
+        "lcobucci/jwt": "^5.0",
         "league/omnipay": "^3.2.1",
         "mailgun/mailgun-php": "^3",
         "nikolaposa/rate-limit": "^3.0",

+ 183 - 58
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "bad3138158c7a10aaed33f12515774b0",
+    "content-hash": "2fcedaff11e3ab25db456faff60ebd95",
     "packages": [
         {
             "name": "anankke/omnipay-alipay",
@@ -123,16 +123,16 @@
         },
         {
             "name": "aws/aws-sdk-php",
-            "version": "3.278.0",
+            "version": "3.278.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/aws/aws-sdk-php.git",
-                "reference": "494c3bcd0e1f99aed7ef8b90e3a413d82f6c7e4d"
+                "reference": "596534c0627d8b38597061341e99b460437d1a16"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/494c3bcd0e1f99aed7ef8b90e3a413d82f6c7e4d",
-                "reference": "494c3bcd0e1f99aed7ef8b90e3a413d82f6c7e4d",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/596534c0627d8b38597061341e99b460437d1a16",
+                "reference": "596534c0627d8b38597061341e99b460437d1a16",
                 "shasum": ""
             },
             "require": {
@@ -212,9 +212,9 @@
             "support": {
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.278.0"
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.278.3"
             },
-            "time": "2023-08-10T18:15:03+00:00"
+            "time": "2023-08-15T18:07:55+00:00"
         },
         {
             "name": "bacon/bacon-qr-code",
@@ -1233,16 +1233,16 @@
         },
         {
             "name": "illuminate/collections",
-            "version": "v10.18.0",
+            "version": "v10.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/collections.git",
-                "reference": "66ff5aab0dd10659aff0efe3ff101819db192dfe"
+                "reference": "f494398dbaaead9e5ff16a18002d11634e8358e6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/collections/zipball/66ff5aab0dd10659aff0efe3ff101819db192dfe",
-                "reference": "66ff5aab0dd10659aff0efe3ff101819db192dfe",
+                "url": "https://api.github.com/repos/illuminate/collections/zipball/f494398dbaaead9e5ff16a18002d11634e8358e6",
+                "reference": "f494398dbaaead9e5ff16a18002d11634e8358e6",
                 "shasum": ""
             },
             "require": {
@@ -1284,11 +1284,11 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2023-08-02T14:57:32+00:00"
+            "time": "2023-08-11T14:48:51+00:00"
         },
         {
             "name": "illuminate/conditionable",
-            "version": "v10.18.0",
+            "version": "v10.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/conditionable.git",
@@ -1334,7 +1334,7 @@
         },
         {
             "name": "illuminate/container",
-            "version": "v10.18.0",
+            "version": "v10.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/container.git",
@@ -1385,7 +1385,7 @@
         },
         {
             "name": "illuminate/contracts",
-            "version": "v10.18.0",
+            "version": "v10.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/contracts.git",
@@ -1433,16 +1433,16 @@
         },
         {
             "name": "illuminate/database",
-            "version": "v10.18.0",
+            "version": "v10.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/database.git",
-                "reference": "a52129be2133f83298204770b6110631a1ee13a9"
+                "reference": "cb735802ee3c303494ebfa4112f3f6b78ba80ec5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/database/zipball/a52129be2133f83298204770b6110631a1ee13a9",
-                "reference": "a52129be2133f83298204770b6110631a1ee13a9",
+                "url": "https://api.github.com/repos/illuminate/database/zipball/cb735802ee3c303494ebfa4112f3f6b78ba80ec5",
+                "reference": "cb735802ee3c303494ebfa4112f3f6b78ba80ec5",
                 "shasum": ""
             },
             "require": {
@@ -1498,11 +1498,11 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2023-08-08T14:15:49+00:00"
+            "time": "2023-08-14T14:50:08+00:00"
         },
         {
             "name": "illuminate/macroable",
-            "version": "v10.18.0",
+            "version": "v10.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/macroable.git",
@@ -1548,7 +1548,7 @@
         },
         {
             "name": "illuminate/pagination",
-            "version": "v10.18.0",
+            "version": "v10.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/pagination.git",
@@ -1598,16 +1598,16 @@
         },
         {
             "name": "illuminate/support",
-            "version": "v10.18.0",
+            "version": "v10.19.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/support.git",
-                "reference": "9ce4a26975a919ec33ed21307633ac02208537a8"
+                "reference": "0a8526d55756955fcec6be7c2c6cd14d915c8c0f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/support/zipball/9ce4a26975a919ec33ed21307633ac02208537a8",
-                "reference": "9ce4a26975a919ec33ed21307633ac02208537a8",
+                "url": "https://api.github.com/repos/illuminate/support/zipball/0a8526d55756955fcec6be7c2c6cd14d915c8c0f",
+                "reference": "0a8526d55756955fcec6be7c2c6cd14d915c8c0f",
                 "shasum": ""
             },
             "require": {
@@ -1665,7 +1665,7 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2023-08-08T14:14:45+00:00"
+            "time": "2023-08-14T21:56:59+00:00"
         },
         {
             "name": "irazasyed/telegram-bot-sdk",
@@ -1867,6 +1867,81 @@
             },
             "time": "2022-11-17T10:54:53+00:00"
         },
+        {
+            "name": "lcobucci/jwt",
+            "version": "5.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/lcobucci/jwt.git",
+                "reference": "47bdb0e0b5d00c2f89ebe33e7e384c77e84e7c34"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/lcobucci/jwt/zipball/47bdb0e0b5d00c2f89ebe33e7e384c77e84e7c34",
+                "reference": "47bdb0e0b5d00c2f89ebe33e7e384c77e84e7c34",
+                "shasum": ""
+            },
+            "require": {
+                "ext-hash": "*",
+                "ext-json": "*",
+                "ext-openssl": "*",
+                "ext-sodium": "*",
+                "php": "~8.1.0 || ~8.2.0",
+                "psr/clock": "^1.0"
+            },
+            "require-dev": {
+                "infection/infection": "^0.26.19",
+                "lcobucci/clock": "^3.0",
+                "lcobucci/coding-standard": "^9.0",
+                "phpbench/phpbench": "^1.2.8",
+                "phpstan/extension-installer": "^1.2",
+                "phpstan/phpstan": "^1.10.3",
+                "phpstan/phpstan-deprecation-rules": "^1.1.2",
+                "phpstan/phpstan-phpunit": "^1.3.8",
+                "phpstan/phpstan-strict-rules": "^1.5.0",
+                "phpunit/phpunit": "^10.0.12"
+            },
+            "suggest": {
+                "lcobucci/clock": ">= 3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Lcobucci\\JWT\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Luís Cobucci",
+                    "email": "[email protected]",
+                    "role": "Developer"
+                }
+            ],
+            "description": "A simple library to work with JSON Web Token and JSON Web Signature",
+            "keywords": [
+                "JWS",
+                "jwt"
+            ],
+            "support": {
+                "issues": "https://github.com/lcobucci/jwt/issues",
+                "source": "https://github.com/lcobucci/jwt/tree/5.0.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/lcobucci",
+                    "type": "github"
+                },
+                {
+                    "url": "https://www.patreon.com/lcobucci",
+                    "type": "patreon"
+                }
+            ],
+            "time": "2023-02-25T21:35:16+00:00"
+        },
         {
             "name": "league/event",
             "version": "3.0.2",
@@ -1991,16 +2066,16 @@
         },
         {
             "name": "mailgun/mailgun-php",
-            "version": "v3.5.9",
+            "version": "v3.6.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/mailgun/mailgun-php.git",
-                "reference": "181749e4daea67cb33cdb27ac422261d3601aeb9"
+                "reference": "02d8b5c7e082a64fb8e9bf9aea557501bf69fa41"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/mailgun/mailgun-php/zipball/181749e4daea67cb33cdb27ac422261d3601aeb9",
-                "reference": "181749e4daea67cb33cdb27ac422261d3601aeb9",
+                "url": "https://api.github.com/repos/mailgun/mailgun-php/zipball/02d8b5c7e082a64fb8e9bf9aea557501bf69fa41",
+                "reference": "02d8b5c7e082a64fb8e9bf9aea557501bf69fa41",
                 "shasum": ""
             },
             "require": {
@@ -2015,6 +2090,7 @@
                 "nyholm/nsa": "^1.2.1",
                 "nyholm/psr7": "^1.3.1",
                 "phpunit/phpunit": "^9.3",
+                "squizlabs/php_codesniffer": "^3.7",
                 "symfony/http-client": "^5.3"
             },
             "suggest": {
@@ -2045,9 +2121,9 @@
             "description": "The Mailgun SDK provides methods for all API functions.",
             "support": {
                 "issues": "https://github.com/mailgun/mailgun-php/issues",
-                "source": "https://github.com/mailgun/mailgun-php/tree/v3.5.9"
+                "source": "https://github.com/mailgun/mailgun-php/tree/v3.6.0"
             },
-            "time": "2023-07-19T11:28:29+00:00"
+            "time": "2023-08-13T13:48:52+00:00"
         },
         {
             "name": "maxmind-db/reader",
@@ -3404,6 +3480,54 @@
             },
             "time": "2023-07-24T11:37:11+00:00"
         },
+        {
+            "name": "psr/clock",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/clock.git",
+                "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+                "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0 || ^8.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Clock\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "https://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for reading the clock.",
+            "homepage": "https://github.com/php-fig/clock",
+            "keywords": [
+                "clock",
+                "now",
+                "psr",
+                "psr-20",
+                "time"
+            ],
+            "support": {
+                "issues": "https://github.com/php-fig/clock/issues",
+                "source": "https://github.com/php-fig/clock/tree/1.0.0"
+            },
+            "time": "2022-11-25T14:36:26+00:00"
+        },
         {
             "name": "psr/container",
             "version": "2.0.2",
@@ -7131,16 +7255,16 @@
         },
         {
             "name": "friendsofphp/php-cs-fixer",
-            "version": "v3.22.0",
+            "version": "v3.23.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
-                "reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3"
+                "reference": "35af3cbbacfa91e164b252a28ec0b644f1ed4e78"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/92b019f6c8d79aa26349d0db7671d37440dc0ff3",
-                "reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3",
+                "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/35af3cbbacfa91e164b252a28ec0b644f1ed4e78",
+                "reference": "35af3cbbacfa91e164b252a28ec0b644f1ed4e78",
                 "shasum": ""
             },
             "require": {
@@ -7216,7 +7340,7 @@
             ],
             "support": {
                 "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
-                "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.22.0"
+                "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.23.0"
             },
             "funding": [
                 {
@@ -7224,7 +7348,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2023-07-16T23:08:06+00:00"
+            "time": "2023-08-14T12:27:35+00:00"
         },
         {
             "name": "justinrainbow/json-schema",
@@ -7439,16 +7563,16 @@
         },
         {
             "name": "nikic/php-parser",
-            "version": "v4.16.0",
+            "version": "v4.17.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "19526a33fb561ef417e822e85f08a00db4059c17"
+                "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17",
-                "reference": "19526a33fb561ef417e822e85f08a00db4059c17",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
+                "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
                 "shasum": ""
             },
             "require": {
@@ -7489,9 +7613,9 @@
             ],
             "support": {
                 "issues": "https://github.com/nikic/PHP-Parser/issues",
-                "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0"
+                "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
             },
-            "time": "2023-06-25T14:52:30+00:00"
+            "time": "2023-08-13T19:53:39+00:00"
         },
         {
             "name": "nunomaduro/phpinsights",
@@ -8136,16 +8260,16 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "10.3.1",
+            "version": "10.3.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "d442ce7c4104d5683c12e67e4dcb5058159e9804"
+                "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d442ce7c4104d5683c12e67e4dcb5058159e9804",
-                "reference": "d442ce7c4104d5683c12e67e4dcb5058159e9804",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0dafb1175c366dd274eaa9a625e914451506bcd1",
+                "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1",
                 "shasum": ""
             },
             "require": {
@@ -8217,7 +8341,7 @@
             "support": {
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.1"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.2"
             },
             "funding": [
                 {
@@ -8233,7 +8357,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2023-08-04T06:48:08+00:00"
+            "time": "2023-08-15T05:34:23+00:00"
         },
         {
             "name": "psr/cache",
@@ -8453,16 +8577,16 @@
         },
         {
             "name": "sebastian/comparator",
-            "version": "5.0.0",
+            "version": "5.0.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/comparator.git",
-                "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c"
+                "reference": "2db5010a484d53ebf536087a70b4a5423c102372"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/72f01e6586e0caf6af81297897bd112eb7e9627c",
-                "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c",
+                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372",
+                "reference": "2db5010a484d53ebf536087a70b4a5423c102372",
                 "shasum": ""
             },
             "require": {
@@ -8473,7 +8597,7 @@
                 "sebastian/exporter": "^5.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "^10.0"
+                "phpunit/phpunit": "^10.3"
             },
             "type": "library",
             "extra": {
@@ -8517,7 +8641,8 @@
             ],
             "support": {
                 "issues": "https://github.com/sebastianbergmann/comparator/issues",
-                "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.0"
+                "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+                "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1"
             },
             "funding": [
                 {
@@ -8525,7 +8650,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2023-02-03T07:07:16+00:00"
+            "time": "2023-08-14T13:18:12+00:00"
         },
         {
             "name": "sebastian/complexity",

+ 30 - 0
config/settings.json

@@ -999,6 +999,36 @@
         "default": "",
         "mark": "Slack App Token"
     },
+    {
+        "id": null,
+        "item": "slack_client_id",
+        "value": "",
+        "class": "slack",
+        "is_public": 0,
+        "type": "",
+        "default": "string",
+        "mark": "Slack Client ID"
+    },
+    {
+        "id": null,
+        "item": "slack_client_secret",
+        "value": "",
+        "class": "slack",
+        "is_public": 0,
+        "type": "string",
+        "default": "",
+        "mark": "Slack Client Secret"
+    },
+    {
+        "id": null,
+        "item": "slack_team_id",
+        "value": "",
+        "class": "slack",
+        "is_public": 0,
+        "type": "string",
+        "default": "",
+        "mark": "Slack Team ID"
+    },
     {
         "id": null,
         "item": "tawk_id",

+ 18 - 0
resources/views/tabler/admin/setting/im.tpl

@@ -342,6 +342,24 @@
                                         <input id="slack_token" type="text" class="form-control" value="{$settings['slack_token']}">
                                     </div>
                                 </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Client ID</label>
+                                    <div class="col">
+                                        <input id="slack_client_id" type="text" class="form-control" value="{$settings['slack_client_id']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Client Secret</label>
+                                    <div class="col">
+                                        <input id="slack_client_secret" type="text" class="form-control" value="{$settings['slack_client_secret']}">
+                                    </div>
+                                </div>
+                                <div class="form-group mb-3 row">
+                                    <label class="form-label col-3 col-form-label">Team ID</label>
+                                    <div class="col">
+                                        <input id="slack_team_id" type="text" class="form-control" value="{$settings['slack_team_id']}">
+                                    </div>
+                                </div>
                                 <div class="form-group mb-3 row">
                                     <label class="form-label col-3 col-form-label">Slack 用户 ID</label>
                                     <input type="text" class="form-control" id="slack_user_id" value="">

+ 4 - 5
resources/views/tabler/user/edit.tpl

@@ -770,12 +770,12 @@
             } else if ($(this).val() === '1') {
                 $('#oauth-provider').empty();
                 $('#oauth-provider').append(
-                    '<a id=\"bind-slack\" class=\"btn btn-azure ms-auto\">绑定 Slack<\/a>'
+                    "<a id='bind-slack' class='btn btn-azure ms-auto'>绑定 Slack</a>"
                 );
             } else if ($(this).val() === '2') {
                 $('#oauth-provider').empty();
                 $('#oauth-provider').append(
-                    '<a id=\"bind-discord\" class=\"btn btn-indigo ms-auto\">绑定 Discord<\/a>'
+                    "<a id='bind-discord' class='btn btn-indigo ms-auto'>绑定 Discord</a>"
                 );
             } else if ($(this).val() === '4'){
                 $('#oauth-provider').empty();
@@ -795,8 +795,7 @@
                 dataType: "json",
                 success: function(data) {
                     if (data.ret === 1) {
-                        $('#success-message').text(data.msg);
-                        $('#success-dialog').modal('show');
+                        window.location.replace(data.redir);
                     } else {
                         $('#fail-message').text(data.msg);
                         $('#fail-dialog').modal('show');
@@ -812,7 +811,7 @@
                 dataType: "json",
                 success: function(data) {
                     if (data.ret === 1) {
-                        window.setTimeout(location.href=data.redir, 0);
+                        window.location.replace(data.redir);
                     } else {
                         $('#fail-message').text(data.msg);
                         $('#fail-dialog').modal('show');

+ 3 - 0
src/Controllers/Admin/Setting/ImController.php

@@ -53,6 +53,9 @@ final class ImController extends BaseController
         'discord_client_secret',
         'discord_guild_id',
         'slack_token',
+        'slack_client_id',
+        'slack_client_secret',
+        'slack_team_id',
     ];
 
     /**

+ 1 - 1
src/Controllers/CallbackController.php

@@ -5,7 +5,7 @@ declare(strict_types=1);
 namespace App\Controllers;
 
 use App\Models\Setting;
-use App\Utils\Telegram\Process;
+use App\Services\Bot\Telegram\Process;
 use MaxMind\Db\Reader\InvalidDatabaseException;
 use Psr\Http\Message\ResponseInterface;
 use RedisException;

+ 66 - 2
src/Controllers/OAuthController.php

@@ -9,8 +9,11 @@ use App\Models\User;
 use App\Services\Cache;
 use App\Utils\ResponseHelper;
 use App\Utils\Tools;
+use Exception;
 use GuzzleHttp\Client;
 use GuzzleHttp\Exception\GuzzleException;
+use Lcobucci\JWT\Encoding\JoseEncoder;
+use Lcobucci\JWT\Token\Parser;
 use Psr\Http\Message\ResponseInterface;
 use RedisException;
 use Slim\Http\Response;
@@ -44,9 +47,70 @@ final class OAuthController extends BaseController
         };
     }
 
+    /**
+     * @throws GuzzleException
+     * @throws RedisException
+     * @throws Exception
+     */
     public function slack(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
-        return ResponseHelper::error($response, '暂不支持');
+        $user = $this->user;
+        $redis = Cache::initRedis();
+
+        if ($request->getParam('code') === null) {
+            $state = Tools::genRandomChar(16);
+            $redis->setex('slack_state:' . $user->id, 300, $state);
+            $client_id = Setting::obtain('slack_client_id');
+            $team_id = Setting::obtain('slack_team_id');
+            $redirect_uri = $_ENV['baseUrl'] . '/oauth/slack';
+
+            return $response->withJson([
+                'ret' => 1,
+                'redir' => 'https://slack.com/openid/connect/authorize?response_type=code&scope=openid profile&client_id='
+                    . $client_id . '&state=' . $state . '&team=' . $team_id .
+                    '&nonce=' . $state . '&redirect_uri=' . $redirect_uri,
+            ]);
+        }
+
+        $code = $request->getParam('code');
+        $state = $request->getParam('state');
+
+        if ($state !== $redis->get('slack_state:' . $user->id)) {
+            return ResponseHelper::error($response, '参数错误');
+        }
+
+        $client = new Client();
+        $slack_api_url = 'https://slack.com/api/openid.connect.token';
+
+        $code_headers = [
+            'Content-Type' => 'application/x-www-form-urlencoded',
+        ];
+
+        $code_body = [
+            'client_id' => Setting::obtain('slack_client_id'),
+            'client_secret' => Setting::obtain('slack_client_secret'),
+            'grant_type' => 'authorization_code',
+            'code' => $code,
+            'redirect_uri' => $_ENV['baseUrl'] . '/oauth/slack',
+        ];
+
+        $code_response = $client->post($slack_api_url, [
+            'headers' => $code_headers,
+            'form_params' => $code_body,
+        ]);
+
+        if (! json_decode($code_response->getBody()->__toString())->ok) {
+            return ResponseHelper::error($response, 'OAuth 请求失败');
+        }
+
+        $parser = new Parser(new JoseEncoder());
+        $id_token = $parser->parse(json_decode($code_response->getBody()->__toString())->id_token);
+
+        $user->im_type = 1;
+        $user->im_value = $id_token->claims()->get('https://slack.com/user_id');
+        $user->save();
+
+        return $response->withRedirect($_ENV['baseUrl'] . '/user/edit');
     }
 
     /**
@@ -120,7 +184,7 @@ final class OAuthController extends BaseController
         }
 
         $user->im_type = 2;
-        $user->im_value = json_decode($user_response->getBody()->getContents())->id;
+        $user->im_value = json_decode($user_response->getBody()->getContents(), true)['id'];
         $user->save();
 
         if (Setting::obtain('discord_guild_id') !== 0) {

+ 6 - 3
src/Controllers/WebAPI/NodeController.php

@@ -19,18 +19,21 @@ final class NodeController extends BaseController
     {
         $node_id = $args['id'];
         $node = Node::find($node_id);
+
         if ($node === null) {
-            $res = [
+            return $response->withJson([
                 'ret' => 0,
-            ];
-            return $response->withJson($res);
+                'data' => 'Node not found.',
+            ]);
         }
+
         if ($node->sort === 0) {
             $node_explode = explode(';', $node->server);
             $node_server = $node_explode[0];
         } else {
             $node_server = $node->server;
         }
+
         $data = [
             'node_group' => $node->node_group,
             'node_class' => $node->node_class,

+ 14 - 7
src/Controllers/WebAPI/UserController.php

@@ -9,17 +9,14 @@ use App\Models\DetectLog;
 use App\Models\Node;
 use App\Services\DB;
 use App\Utils\ResponseHelper;
+use App\Utils\Tools;
 use Psr\Http\Message\ResponseInterface;
 use Slim\Http\Response;
 use Slim\Http\ServerRequest;
 use function count;
-use function filter_var;
 use function is_array;
 use function json_decode;
 use function time;
-use const FILTER_FLAG_IPV4;
-use const FILTER_FLAG_IPV6;
-use const FILTER_VALIDATE_IP;
 
 final class UserController extends BaseController
 {
@@ -40,6 +37,7 @@ final class UserController extends BaseController
         if ($node === null) {
             return $response->withJson([
                 'ret' => 0,
+                'data' => 'Node not found.',
             ]);
         }
 
@@ -136,6 +134,7 @@ final class UserController extends BaseController
         if (! $data || ! is_array($data->data)) {
             return $response->withJson([
                 'ret' => 0,
+                'data' => 'Invalid data.',
             ]);
         }
 
@@ -146,6 +145,7 @@ final class UserController extends BaseController
         if ($node === null) {
             return $response->withJson([
                 'ret' => 0,
+                'data' => 'Node not found.',
             ]);
         }
 
@@ -164,9 +164,11 @@ final class UserController extends BaseController
             $u = $log?->u;
             $d = $log?->d;
             $user_id = $log?->user_id;
+
             if ($user_id) {
                 $stat->execute([(int) ($u * $rate), (int) ($d * $rate), (int) ($u + $d), (int) ($u + $d), $user_id]);
             }
+
             $sum += $u + $d;
         }
 
@@ -196,6 +198,7 @@ final class UserController extends BaseController
         if (! $data || ! is_array($data->data)) {
             return $response->withJson([
                 'ret' => 0,
+                'data' => 'Invalid data.',
             ]);
         }
 
@@ -205,6 +208,7 @@ final class UserController extends BaseController
         if ($node_id === null || ! Node::where('id', $node_id)->exists()) {
             return $response->withJson([
                 'ret' => 0,
+                'data' => 'Node not found.',
             ]);
         }
 
@@ -218,10 +222,10 @@ final class UserController extends BaseController
             $ip = (string) $log?->ip;
             $user_id = (int) $log?->user_id;
 
-            if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
+            if (Tools::isIPv4($ip)) {
                 // convert IPv4 Address to IPv4-mapped IPv6 Address
                 $ip = "::ffff:{$ip}";
-            } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
+            } elseif (! Tools::isIPv6($ip)) {
                 // either IPv4 or IPv6 Address
                 continue;
             }
@@ -247,18 +251,21 @@ final class UserController extends BaseController
     public function addDetectLog(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
         $data = json_decode($request->getBody()->__toString());
+
         if (! $data || ! is_array($data->data)) {
             return $response->withJson([
                 'ret' => 0,
+                'data' => 'Invalid data.',
             ]);
         }
-        $data = $data->data;
 
+        $data = $data->data;
         $node_id = $request->getQueryParam('node_id');
 
         if ($node_id === null || ! Node::where('id', $node_id)->exists()) {
             return $response->withJson([
                 'ret' => 0,
+                'data' => 'Node not found.',
             ]);
         }
 

+ 13 - 13
src/Utils/Telegram/Callback.php → src/Services/Bot/Telegram/Callback.php

@@ -2,7 +2,7 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram;
+namespace App\Services\Bot\Telegram;
 
 use App\Controllers\LinkController;
 use App\Controllers\SubController;
@@ -77,10 +77,10 @@ final class Callback
         $this->bot = $bot;
         $this->triggerUser = [
             'id' => $Callback->getFrom()->getId(),
-            'name' => $Callback->getFrom()->getFirstName() . ' ' . $Callback->getFrom()->getLastName(),
+            'name' => $Callback->getFrom()->getFirstName() . ' Callback.php' . $Callback->getFrom()->getLastName(),
             'username' => $Callback->getFrom()->getUsername(),
         ];
-        $this->User = TelegramTools::getUser($this->triggerUser['id']);
+        $this->User = Tool::getUser($this->triggerUser['id']);
         $this->ChatID = $Callback->getMessage()->getChat()->getId();
         $this->Callback = $Callback;
         $this->MessageID = $Callback->getMessage()->getMessageId();
@@ -115,7 +115,7 @@ final class Callback
             $sendMessage
         );
         if ($this->AllowEditMessage) {
-            TelegramTools::sendPost('editMessageText', $sendMessage);
+            Tool::sendPost('editMessageText', $sendMessage);
         } else {
             $this->bot->sendMessage($sendMessage);
         }
@@ -142,7 +142,7 @@ final class Callback
             ],
             $sendMessage
         );
-        TelegramTools::sendPost('answerCallbackQuery', $sendMessage);
+        Tool::sendPost('answerCallbackQuery', $sendMessage);
     }
 
     public static function getUserIndexKeyboard($user): array
@@ -176,9 +176,9 @@ final class Callback
                 ],
             ],
         ];
-        $text = Reply::getUserTitle($user);
+        $text = Message::getUserTitle($user);
         $text .= PHP_EOL . PHP_EOL;
-        $text .= Reply::getUserInfo($user);
+        $text .= Message::getUserInfo($user);
 
         return [
             'text' => $text,
@@ -253,9 +253,9 @@ final class Callback
 
     public function getUserCenterKeyboard(): array
     {
-        $text = Reply::getUserTitle($this->User);
+        $text = Message::getUserTitle($this->User);
         $text .= PHP_EOL . PHP_EOL;
-        $text .= Reply::getUserTrafficInfo($this->User);
+        $text .= Message::getUserTrafficInfo($this->User);
         $keyboard = [
             [
                 [
@@ -439,7 +439,7 @@ final class Callback
 
     public function getUserEditKeyboard(): array
     {
-        $text = Reply::getUserTitle($this->User);
+        $text = Message::getUserTitle($this->User);
         $keyboard = [
             [
                 [
@@ -682,7 +682,7 @@ final class Callback
                 break;
             case 'unban_update':
                 // 提交群组解封
-                TelegramTools::sendPost(
+                Tool::sendPost(
                     'unbanChatMember',
                     [
                         'chat_id' => Setting::obtain('telegram_chatid'),
@@ -957,9 +957,9 @@ final class Callback
         if ($this->ChatID > 0) {
             $temp = self::getUserIndexKeyboard($this->User);
         } else {
-            $temp['text'] = Reply::getUserTitle($this->User);
+            $temp['text'] = Message::getUserTitle($this->User);
             $temp['text'] .= PHP_EOL . PHP_EOL;
-            $temp['text'] .= Reply::getUserTrafficInfo($this->User);
+            $temp['text'] .= Message::getUserTrafficInfo($this->User);
             $temp['keyboard'] = [
                 [
                     [

+ 3 - 3
src/Utils/Telegram/Commands/CheckinCommand.php → src/Services/Bot/Telegram/Commands/CheckinCommand.php

@@ -2,10 +2,10 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram\Commands;
+namespace App\Services\Bot\Telegram\Commands;
 
 use App\Models\Setting;
-use App\Utils\Telegram\TelegramTools;
+use App\Services\Bot\Telegram\Tool;
 use Telegram\Bot\Actions;
 use Telegram\Bot\Commands\Command;
 
@@ -53,7 +53,7 @@ final class CheckinCommand extends Command
         $SendUser = [
             'id' => $Message->getFrom()->getId(),
         ];
-        $User = TelegramTools::getUser($SendUser['id']);
+        $User = Tool::getUser($SendUser['id']);
         if ($User === null) {
             // 回送信息
             $response = $this->replyWithMessage(

+ 1 - 1
src/Utils/Telegram/Commands/HelpCommand.php → src/Services/Bot/Telegram/Commands/HelpCommand.php

@@ -2,7 +2,7 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram\Commands;
+namespace App\Services\Bot\Telegram\Commands;
 
 use App\Models\Setting;
 use Telegram\Bot\Actions;

+ 4 - 4
src/Utils/Telegram/Commands/MenuCommand.php → src/Services/Bot/Telegram/Commands/MenuCommand.php

@@ -2,10 +2,10 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram\Commands;
+namespace App\Services\Bot\Telegram\Commands;
 
-use App\Utils\Telegram\Callback;
-use App\Utils\Telegram\TelegramTools;
+use App\Services\Bot\Telegram\Callback;
+use App\Services\Bot\Telegram\Tool;
 use Telegram\Bot\Actions;
 use Telegram\Bot\Commands\Command;
 use function json_encode;
@@ -47,7 +47,7 @@ final class MenuCommand extends Command
                 'id' => $Message->getFrom()->getId(),
             ];
 
-            $user = TelegramTools::getUser($SendUser['id']);
+            $user = Tool::getUser($SendUser['id']);
             if ($user === null) {
                 $reply = null;
             } else {

+ 5 - 5
src/Utils/Telegram/Commands/MyCommand.php → src/Services/Bot/Telegram/Commands/MyCommand.php

@@ -2,11 +2,11 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram\Commands;
+namespace App\Services\Bot\Telegram\Commands;
 
 use App\Models\Setting;
 use App\Models\User;
-use App\Utils\Telegram\Reply;
+use App\Services\Bot\Telegram\Message;
 use Telegram\Bot\Actions;
 use Telegram\Bot\Commands\Command;
 use function json_encode;
@@ -57,7 +57,7 @@ final class MyCommand extends Command
         // 触发用户
         $SendUser = [
             'id' => $Message->getFrom()->getId(),
-            'name' => $Message->getFrom()->getFirstName() . ' ' . $Message->getFrom()->getLastName(),
+            'name' => $Message->getFrom()->getFirstName() . ' MyCommand.php' . $Message->getFrom()->getLastName(),
             'username' => $Message->getFrom()->getUsername(),
         ];
 
@@ -86,9 +86,9 @@ final class MyCommand extends Command
 
     public function group($User, $SendUser, $ChatID, $Message, $MessageID)
     {
-        $text = Reply::getUserTitle($User);
+        $text = Message::getUserTitle($User);
         $text .= PHP_EOL . PHP_EOL;
-        $text .= Reply::getUserTrafficInfo($User);
+        $text .= Message::getUserTrafficInfo($User);
         // 回送信息
         return $this->replyWithMessage(
             [

+ 1 - 1
src/Utils/Telegram/Commands/PingCommand.php → src/Services/Bot/Telegram/Commands/PingCommand.php

@@ -2,7 +2,7 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram\Commands;
+namespace App\Services\Bot\Telegram\Commands;
 
 use App\Models\Setting;
 use Telegram\Bot\Actions;

+ 2 - 2
src/Utils/Telegram/Commands/StartCommand.php → src/Services/Bot/Telegram/Commands/StartCommand.php

@@ -2,7 +2,7 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram\Commands;
+namespace App\Services\Bot\Telegram\Commands;
 
 use App\Models\Setting;
 use RedisException;
@@ -41,7 +41,7 @@ final class StartCommand extends Command
             // 触发用户
             $SendUser = [
                 'id' => $Message->getFrom()->getId(),
-                'name' => $Message->getFrom()->getFirstName() . ' ' . $Message->getFrom()->getLastName(),
+                'name' => $Message->getFrom()->getFirstName() . ' StartCommand.php' . $Message->getFrom()->getLastName(),
                 'username' => $Message->getFrom()->getUsername(),
             ];
             // 消息内容

+ 3 - 3
src/Utils/Telegram/Commands/UnbindCommand.php → src/Services/Bot/Telegram/Commands/UnbindCommand.php

@@ -2,10 +2,10 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram\Commands;
+namespace App\Services\Bot\Telegram\Commands;
 
 use App\Models\Setting;
-use App\Utils\Telegram\TelegramTools;
+use App\Services\Bot\Telegram\Tool;
 use Telegram\Bot\Actions;
 use Telegram\Bot\Commands\Command;
 
@@ -36,7 +36,7 @@ final class UnbindCommand extends Command
             'id' => $Message->getFrom()->getId(),
         ];
 
-        $User = TelegramTools::getUser($SendUser['id']);
+        $User = Tool::getUser($SendUser['id']);
 
         if ($ChatID > 0) {
             // 私人

+ 56 - 7
src/Utils/Telegram/Message.php → src/Services/Bot/Telegram/Message.php

@@ -2,9 +2,10 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram;
+namespace App\Services\Bot\Telegram;
 
 use App\Models\Setting;
+use App\Models\User;
 use RedisException;
 use Telegram\Bot\Api;
 use Telegram\Bot\Exceptions\TelegramSDKException;
@@ -48,10 +49,10 @@ final class Message
         $this->bot = $bot;
         $this->triggerUser = [
             'id' => $Message->getFrom()->getId(),
-            'name' => $Message->getFrom()->getFirstName() . ' ' . $Message->getFrom()->getLastName(),
+            'name' => $Message->getFrom()->getFirstName() . ' Message.php' . $Message->getFrom()->getLastName(),
             'username' => $Message->getFrom()->getUsername(),
         ];
-        $this->User = TelegramTools::getUser($this->triggerUser['id']);
+        $this->User = Tool::getUser($this->triggerUser['id']);
         $this->ChatID = $Message->getChat()->getId();
         $this->Message = $Message;
         $this->MessageID = $Message->getMessageId();
@@ -77,6 +78,7 @@ final class Message
             ],
             $sendMessage
         );
+
         $this->bot->sendMessage($sendMessage);
     }
 
@@ -91,7 +93,7 @@ final class Message
 
         $Member = [
             'id' => $NewChatMember->getId(),
-            'name' => $NewChatMember->getFirstName() . ' ' . $NewChatMember->getLastName(),
+            'name' => $NewChatMember->getFirstName() . ' Message.php' . $NewChatMember->getLastName(),
         ];
 
         if ($NewChatMember->getUsername() === Setting::obtain('telegram_bot')) {
@@ -107,7 +109,7 @@ final class Message
                     ]
                 );
 
-                TelegramTools::sendPost(
+                Tool::sendPost(
                     'kickChatMember',
                     [
                         'chat_id' => $this->ChatID,
@@ -123,7 +125,7 @@ final class Message
             }
         } else {
             // 新成员加入群组
-            $NewUser = TelegramTools::getUser($Member['id']);
+            $NewUser = Tool::getUser($Member['id']);
 
             if (Setting::obtain('telegram_group_bound_user')
                 &&
@@ -139,7 +141,7 @@ final class Message
                     ]
                 );
 
-                TelegramTools::sendPost(
+                Tool::sendPost(
                     'kickChatMember',
                     [
                         'chat_id' => $this->ChatID,
@@ -161,4 +163,51 @@ final class Message
             }
         }
     }
+
+    /**
+     * 用户的流量使用讯息
+     */
+    public static function getUserTrafficInfo(User $user): string
+    {
+        $text = [
+            '你当前的流量状况:',
+            '',
+            '今日已使用 ' . $user->todayUsedTrafficPercent() . '% :' . $user->todayUsedTraffic(),
+            '之前已使用 ' . $user->lastUsedTrafficPercent() . '% :' . $user->lastUsedTraffic(),
+            '流量约剩余 ' . $user->unusedTrafficPercent() . '% :' . $user->unusedTraffic(),
+        ];
+
+        return implode(PHP_EOL, $text);
+    }
+
+    /**
+     * 用户基本讯息
+     */
+    public static function getUserInfo(User $user): string
+    {
+        $text = [
+            '当前余额:' . $user->money,
+            '在线 IP 数:' . ($user->node_iplimit !== 0 ? $user->onlineIpCount() .
+                ' / ' . $user->node_iplimit : $user->onlineIpCount() . ' / 不限制'),
+            '端口速率:' . ($user->node_speedlimit > 0 ? $user->node_speedlimit . 'Mbps' : '不限制'),
+            '上次使用:' . $user->lastUseTime(),
+            '过期时间:' . $user->class_expire,
+        ];
+
+        return implode(PHP_EOL, $text);
+    }
+
+    /**
+     * 获取用户或管理的尊称
+     */
+    public static function getUserTitle(User $user): string
+    {
+        if ($user->class > 0) {
+            $text = '尊敬的 VIP ' . $user->class . ' 你好:';
+        } else {
+            $text = '尊敬的用户你好:';
+        }
+
+        return $text;
+    }
 }

+ 1 - 1
src/Utils/Telegram/Process.php → src/Services/Bot/Telegram/Process.php

@@ -2,7 +2,7 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram;
+namespace App\Services\Bot\Telegram;
 
 use App\Models\Setting;
 use MaxMind\Db\Reader\InvalidDatabaseException;

+ 2 - 2
src/Utils/Telegram/TelegramTools.php → src/Services/Bot/Telegram/Tool.php

@@ -2,7 +2,7 @@
 
 declare(strict_types=1);
 
-namespace App\Utils\Telegram;
+namespace App\Services\Bot\Telegram;
 
 use App\Models\Setting;
 use App\Models\User;
@@ -17,7 +17,7 @@ use const CURLOPT_POSTFIELDS;
 use const CURLOPT_TIMEOUT;
 use const CURLOPT_URL;
 
-final class TelegramTools
+final class Tool
 {
     /**
      * 搜索用户

+ 0 - 54
src/Utils/Telegram/Reply.php

@@ -1,54 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Utils\Telegram;
-
-use App\Models\User;
-
-final class Reply
-{
-    /**
-     * 用户的流量使用讯息
-     */
-    public static function getUserTrafficInfo(User $user): string
-    {
-        $text = [
-            '你当前的流量状况:',
-            '',
-            '今日已使用 ' . $user->todayUsedTrafficPercent() . '% :' . $user->todayUsedTraffic(),
-            '之前已使用 ' . $user->lastUsedTrafficPercent() . '% :' . $user->lastUsedTraffic(),
-            '流量约剩余 ' . $user->unusedTrafficPercent() . '% :' . $user->unusedTraffic(),
-        ];
-        return implode(PHP_EOL, $text);
-    }
-
-    /**
-     * 用户基本讯息
-     */
-    public static function getUserInfo(User $user): string
-    {
-        $text = [
-            '当前余额:' . $user->money,
-            '在线 IP 数:' . ($user->node_iplimit !== 0 ? $user->onlineIpCount() .
-                ' / ' . $user->node_iplimit : $user->onlineIpCount() . ' / 不限制'),
-            '端口速率:' . ($user->node_speedlimit > 0 ? $user->node_speedlimit . 'Mbps' : '不限制'),
-            '上次使用:' . $user->lastUseTime(),
-            '过期时间:' . $user->class_expire,
-        ];
-        return implode(PHP_EOL, $text);
-    }
-
-    /**
-     * 获取用户或管理的尊称
-     */
-    public static function getUserTitle(User $user): string
-    {
-        if ($user->class > 0) {
-            $text = '尊敬的 VIP ' . $user->class . ' 你好:';
-        } else {
-            $text = '尊敬的用户你好:';
-        }
-        return $text;
-    }
-}

+ 7 - 9
src/Utils/Tools.php

@@ -270,7 +270,7 @@ final class Tools
 
     public static function isIPv4($input): bool
     {
-        if (filter_var($input, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false) {
+        if (! filter_var($input, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
             return false;
         }
 
@@ -279,7 +279,7 @@ final class Tools
 
     public static function isIPv6($input): bool
     {
-        if (filter_var($input, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false) {
+        if (! filter_var($input, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
             return false;
         }
 
@@ -288,7 +288,7 @@ final class Tools
 
     public static function isInt($input): bool
     {
-        if (filter_var($input, FILTER_VALIDATE_INT) === false) {
+        if (! filter_var($input, FILTER_VALIDATE_INT)) {
             return false;
         }
 
@@ -297,13 +297,11 @@ final class Tools
 
     public static function genSubToken(): string
     {
-        for ($i = 0; $i < 10; $i++) {
-            $token = self::genRandomChar($_ENV['sub_token_len']);
-            $is_token_used = Link::where('token', $token)->first();
+        $token = self::genRandomChar($_ENV['sub_token_len']);
+        $is_token_used = Link::where('token', $token)->first();
 
-            if ($is_token_used === null) {
-                return $token;
-            }
+        if ($is_token_used === null) {
+            return $token;
         }
 
         return "couldn't alloc token";