Cat 1 年之前
父节点
当前提交
f802a93777
共有 45 个文件被更改,包括 283 次插入404 次删除
  1. 0 2
      .github/FUNDING.yml
  2. 二进制
      .github/PATREON.png
  3. 0 6
      .github/dependabot.yml
  4. 二进制
      .github/do.png
  5. 二进制
      .github/vultr.png
  6. 1 1
      .github/workflows/lint.yml
  7. 19 4
      .github/workflows/lockdown.yml
  8. 10 10
      .github/workflows/minify.yml
  9. 3 5
      .github/workflows/sonarcloud.yml
  10. 7 7
      .github/workflows/stale.yml
  11. 5 7
      .github/workflows/unit.yaml
  12. 1 36
      README.md
  13. 0 1
      SECURITY.md
  14. 3 4
      composer.json
  15. 113 149
      composer.lock
  16. 4 23
      resources/views/tabler/admin/announcement/create.tpl
  17. 4 23
      resources/views/tabler/admin/announcement/edit.tpl
  18. 5 24
      resources/views/tabler/admin/docs/create.tpl
  19. 4 23
      resources/views/tabler/admin/docs/edit.tpl
  20. 2 2
      resources/views/tabler/datatable.tpl
  21. 23 0
      resources/views/tabler/tinymce.tpl
  22. 2 2
      src/Controllers/Admin/AnnController.php
  23. 3 3
      src/Controllers/Admin/NodeController.php
  24. 1 1
      src/Controllers/Admin/UserController.php
  25. 1 1
      src/Controllers/AuthController.php
  26. 1 1
      src/Controllers/PasswordController.php
  27. 1 1
      src/Models/Node.php
  28. 1 1
      src/Models/SubscribeLog.php
  29. 1 1
      src/Models/User.php
  30. 1 1
      src/Services/Bot/Telegram/Callback.php
  31. 2 2
      src/Services/Bot/Telegram/Commands/CheckinCommand.php
  32. 2 2
      src/Services/Bot/Telegram/Commands/HelpCommand.php
  33. 1 1
      src/Services/Bot/Telegram/Commands/MenuCommand.php
  34. 1 1
      src/Services/Bot/Telegram/Commands/MyCommand.php
  35. 4 4
      src/Services/Bot/Telegram/Commands/PingCommand.php
  36. 2 2
      src/Services/Bot/Telegram/Commands/StartCommand.php
  37. 3 3
      src/Services/Bot/Telegram/Commands/UnbindCommand.php
  38. 6 14
      src/Services/Bot/Telegram/Message.php
  39. 29 19
      src/Services/Gateway/PayPal.php
  40. 10 7
      src/Services/Gateway/Stripe.php
  41. 1 1
      src/Services/LLM/VertexAI.php
  42. 1 1
      src/Services/RateLimit.php
  43. 1 1
      src/Services/Reward.php
  44. 4 4
      src/Utils/Tools.php
  45. 0 3
      update.sh

+ 0 - 2
.github/FUNDING.yml

@@ -1,2 +0,0 @@
-# These are supported funding model platforms
-patreon: catdev

二进制
.github/PATREON.png


+ 0 - 6
.github/dependabot.yml

@@ -1,6 +0,0 @@
-version: 2
-updates:
-  - package-ecosystem: "composer"
-    directory: "/"
-    schedule:
-      interval: "monthly"

二进制
.github/do.png


二进制
.github/vultr.png


+ 1 - 1
.github/workflows/lint.yml

@@ -31,6 +31,6 @@ jobs:
         with:
           php-version: 8.3
       - run: |
-          composer install --no-interaction --no-progress --no-suggest
+          composer install --no-interaction --no-progress --no-suggest --quiet
           php vendor/bin/phpinsights analyse --no-interaction --format=github-action \
           --min-style=100 --min-architecture=100 --min-quality=100

+ 19 - 4
.github/workflows/lockdown.yml

@@ -1,17 +1,19 @@
-name: Lockdown
+name: Lockdown Issue & PR
+
 on:
   issues:
     types: [opened]
   issue_comment:
     types: [created]
+  pull_request:
+    types: [opened, synchronize, reopened]
 
 jobs:
-  closeAndlock:
+  issueLockdown:
+    if: ${{ github.event_name == 'issues' }}
     runs-on: ubuntu-latest
     permissions:
       issues: write
-      pull-requests: write
-
     steps:
     - name: Close & Lock Issue
       run: |
@@ -20,3 +22,16 @@ jobs:
       env:
         GH_REPO: ${{ github.repository }}
         GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+  prLockdown:
+    if: ${{ github.event_name == 'pull_request' }}
+    runs-on: ubuntu-latest
+    permissions:
+      pull-requests: write
+    steps:
+    - name: Close & Lock PR
+      run: |
+        gh pr close ${{ github.event.pull_request.number }}
+        gh pr lock ${{ github.event.pull_request.number }}
+      env:
+        GH_REPO: ${{ github.repository }}
+        GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

+ 10 - 10
.github/workflows/minify.yml

@@ -13,25 +13,25 @@ jobs:
     steps:
       - uses: actions/checkout@v4
         with:
-          token: ${{ secrets.PAT }}
-      - name: Auto Minify Tabler Theme CSS file
-        uses: nizarmah/auto-minify@master
+          token: ${{ secrets.GITHUB_TOKEN }}
+      - name: Auto minify tabler theme CSS file
+        uses: nizarmah/auto-minify@v3
         with:
           directory: 'public/theme/tabler/css'
-      - name: Auto Minify Tabler Theme JS file
-        uses: nizarmah/auto-minify@master
+      - name: Auto minify tabler theme JS file
+        uses: nizarmah/auto-minify@v3
         with:
           directory: 'public/theme/tabler/js'
-      - name: Auto Minify CSS file
-        uses: nizarmah/auto-minify@master
+      - name: Auto minify asset CSS file
+        uses: nizarmah/auto-minify@v3
         with:
           directory: 'public/assets/css'
-      - name: Auto Minify JS file
-        uses: nizarmah/auto-minify@master
+      - name: Auto minify asset JS file
+        uses: nizarmah/auto-minify@v3
         with:
           directory: 'public/assets/js'
       - name: Auto committing minified files
         uses: stefanzweifel/git-auto-commit-action@v5
         with:
           repository: 'public'
-          commit_message: "Github Action: Auto Minified Theme CSS/JS Files"
+          commit_message: "chore: auto minified theme CSS/JS files"

+ 3 - 5
.github/workflows/sonarcloud.yml

@@ -2,10 +2,8 @@ name: SonarCloud
 
 on:
   push:
-    branches: [ "dev" ]
   pull_request:
-    branches: [ "dev" ]
-  workflow_dispatch:
+    types: [ opened, reopened, synchronize ]
 
 permissions:
   pull-requests: read
@@ -24,7 +22,7 @@ jobs:
           php-version: '8.3'
           coverage: xdebug
       - name: Install dependencies with composer
-        run: composer update --no-ansi --no-interaction --no-progress
+        run: composer update --no-interaction --no-progress --no-suggest --quiet
       - name: Run tests with phpunit/phpunit
         run: vendor/bin/phpunit --coverage-clover=coverage.xml
       - name: Fix code coverage paths
@@ -32,7 +30,7 @@ jobs:
       - name: Analyze with SonarCloud
         uses: SonarSource/sonarcloud-github-action@master
         env:
-          GITHUB_TOKEN: ${{ secrets.PAT }}
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
         with:
           args:

+ 7 - 7
.github/workflows/stale.yml

@@ -2,21 +2,21 @@ name: Mark stale issues and pull requests
 
 on:
   schedule:
-  - cron: '40 2 * * *'
+  - cron: '0 0 * * *'
 
 jobs:
   stale:
-
     runs-on: ubuntu-latest
     permissions:
       issues: write
       pull-requests: write
-
     steps:
     - uses: actions/stale@v9
       with:
         repo-token: ${{ secrets.GITHUB_TOKEN }}
-        stale-issue-message: 'This issue has had no activity for over 60 days, hence marked as "staled-issue". This issue will be closed in 7 days.'
-        stale-pr-message: 'This PR has had no activity for over 60 days, hence marked as "staled-pr". This PR will be closed in 7 days.'
-        stale-issue-label: 'staled-issue'
-        stale-pr-label: 'staled-pr'
+        days-before-stale: 180
+        days-before-close: 14
+        stale-issue-message: 'This issue has had no activity for over 180 days and will be closed in 14 days.'
+        stale-pr-message: 'This PR has had no activity for over 180 days and will be closed in 14 days.'
+        stale-issue-label: 'staled'
+        stale-pr-label: 'staled'

+ 5 - 7
.github/workflows/unit.yaml

@@ -2,10 +2,8 @@ name: PHP Unit Tests
 
 on:
   push:
-    branches: [ "dev" ]
   pull_request:
-    branches: [ "dev" ]
-  workflow_dispatch:
+    types: [ opened, reopened, synchronize ]
 
 jobs:
   php-file-changed:
@@ -23,7 +21,7 @@ jobs:
             php:
               - '**/*.php'
 
-  unit-test-php82:
+  php8.2:
     needs: php-file-changed
     if: ${{ needs.php-file-changed.outputs.php == 'true' }}
     runs-on: ubuntu-latest
@@ -33,10 +31,10 @@ jobs:
       with:
         php-version: 8.2
     - run: |
-        composer install --no-interaction --no-progress --no-suggest
+        composer install --no-interaction --no-progress --no-suggest --quiet
         php vendor/bin/phpunit
 
-  unit-test-php83:
+  php8.3:
     needs: php-file-changed
     if: ${{ needs.php-file-changed.outputs.php == 'true' }}
     runs-on: ubuntu-latest
@@ -46,5 +44,5 @@ jobs:
         with:
           php-version: 8.3
       - run: |
-          composer install --no-interaction --no-progress --no-suggest
+          composer install --no-interaction --no-progress --no-suggest --quiet
           php vendor/bin/phpunit

+ 1 - 36
README.md

@@ -7,21 +7,9 @@
 <br>
 <br>
 
-[![License](https://img.shields.io/github/license/SSPanel-UIM/SSPanel-UIM-Dev?style=flat-square)](https://github.com/SSPanel-UIM/SSPanel-UIM-Dev/blob/dev/LICENSE)
-![GitHub repo size](https://img.shields.io/github/repo-size/SSPanel-UIM/SSPanel-UIM-Dev?style=flat-square)
-![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/Anankke/SSPanel-Uim?style=flat-square)
-![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/SSPanel-UIM/SSPanel-UIM-Dev/lint.yml?branch=dev&label=lint&style=flat-square)
-![Sonar Quality Gate](https://img.shields.io/sonar/quality_gate/sspanel-uim_SSPanel-Uim-Dev/dev?server=https%3A%2F%2Fsonarcloud.io&style=flat-square)
-![Sonar Coverage](https://img.shields.io/sonar/coverage/sspanel-uim_SSPanel-Uim-Dev/dev?server=https%3A%2F%2Fsonarcloud.io&style=flat-square)
-
-[![Release](https://img.shields.io/badge/Telegram-Release-blue?style=flat-square)](https://t.me/sspanel_uim)
-[![Dev](https://img.shields.io/badge/Telegram-Dev-blue?style=flat-square)](https://t.me/sspanel_uim_dev)
-[![Discord](https://img.shields.io/discord/1049692075085549600?color=5865F2&label=Discord&style=flat-square)](https://discord.gg/A7uFKCvf8V)
-[![Dev Blog](https://img.shields.io/badge/Dev-Blog-blue?style=flat-square)](https://blog.sspanel.org)
-
 ## TL;DR
 
-SSPanel UIM is a multi-purpose proxy service management system designed for Shadowsocks / V2Ray / Trojan / TUIC protocol.
+SSPanel UIM is a multi-purpose proxy service management system designed for Shadowsocks(2022) / V2Ray / Trojan / TUIC protocol.
 
 ## Features
 
@@ -46,29 +34,6 @@ SSPanel UIM requires the following programs to be installed and run normally:
 - MariaDB 10.11+(Disable strict mode)
 - Redis 7.0+
 
-## Documentation
-
-> We install, we update, we develop
-
-[SSPanel UIM Wiki (zh)](https://wiki.sspanel.org), here you can find answers to most questions.
-
-## Related Projects
-
-SSPanel-UIM is not just a panel, it also includes a series of peripheral projects to help you use it better.
-
-You can view other projects maintained by our developers on the [SSPanel-UIM Dev Team](https://github.com/sspanel-uim) page.
-
-## Support Developers
-
-### M1Screw
-
-<a href="https://www.patreon.com/catdev"><img src=".github/PATREON.png" width="300"></a>
-
-<a href="https://www.vultr.com/?ref=8941355-8H"><img src=".github/vultr.png" width="300"></a>
-
-<a href="https://www.digitalocean.com/?refcode=50f1a3b6244c"><img src=".github/do.png" width="300"></a>
-
-
 ## Sponsors
 
 [![](.github/jetbrains.png)](https://www.jetbrains.com/?from=SSPanel-UIM)

+ 0 - 1
SECURITY.md

@@ -1 +0,0 @@
-All reports gose to here: [email protected] & [email protected]

+ 3 - 4
composer.json

@@ -14,7 +14,7 @@
         "ext-xml": "*",
         "ext-yaml": "*",
         "ext-zip": "*",
-        "alibabacloud/dm-20170622": "^1.2",
+        "alibabacloud/dm-20170622": "^1",
         "alipaysdk/openapi": "*@dev",
         "aws/aws-sdk-php": "^3",
         "geoip2/geoip2": "^3",
@@ -28,7 +28,6 @@
         "mailgun/mailgun-php": "^4",
         "nikolaposa/rate-limit": "^3",
         "openai-php/client": "^0",
-        "ozdemir/datatables": "^2",
         "phpmailer/phpmailer": "^6",
         "postal/postal": "^2",
         "ramsey/uuid": "^4",
@@ -38,7 +37,7 @@
         "slim/slim": "^4",
         "smarty/smarty": "^5",
         "srmklive/paypal": "^3",
-        "stripe/stripe-php": "^13",
+        "stripe/stripe-php": "^14",
         "symfony/http-client": "^7",
         "symfony/translation": "^7",
         "tronovav/geoip2-update": "^2",
@@ -60,7 +59,7 @@
         }
     },
     "require-dev": {
-        "dg/bypass-finals": "^1.6",
+        "dg/bypass-finals": "^1",
         "nunomaduro/phpinsights": "*",
         "phpunit/phpunit": "^10"
     },

+ 113 - 149
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": "39ab430ad43a297c4e1b232afd979153",
+    "content-hash": "bb79de1b57be0eca9cd7fa5c4c2e1e6c",
     "packages": [
         {
             "name": "adbario/php-dot-notation",
@@ -186,16 +186,16 @@
         },
         {
             "name": "alibabacloud/dm-20170622",
-            "version": "1.2.1",
+            "version": "1.2.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/alibabacloud-sdk-php/dm-20170622.git",
-                "reference": "a5efe273e9651b53ed648a806d3f653217d733a2"
+                "reference": "400f9de65896f7fd2b854bb6a6c51bfe5d56e324"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/alibabacloud-sdk-php/dm-20170622/zipball/a5efe273e9651b53ed648a806d3f653217d733a2",
-                "reference": "a5efe273e9651b53ed648a806d3f653217d733a2",
+                "url": "https://api.github.com/repos/alibabacloud-sdk-php/dm-20170622/zipball/400f9de65896f7fd2b854bb6a6c51bfe5d56e324",
+                "reference": "400f9de65896f7fd2b854bb6a6c51bfe5d56e324",
                 "shasum": ""
             },
             "require": {
@@ -223,9 +223,9 @@
             ],
             "description": "Alibaba Cloud Dm (20170622) SDK Library for PHP",
             "support": {
-                "source": "https://github.com/alibabacloud-sdk-php/dm-20170622/tree/1.2.1"
+                "source": "https://github.com/alibabacloud-sdk-php/dm-20170622/tree/1.2.2"
             },
-            "time": "2024-02-20T17:15:43+00:00"
+            "time": "2024-04-10T17:15:45+00:00"
         },
         {
             "name": "alibabacloud/endpoint-util",
@@ -510,12 +510,12 @@
             "source": {
                 "type": "git",
                 "url": "https://github.com/alipay/alipay-sdk-php-all.git",
-                "reference": "3b86882423995c15992c277ffeb1c8e8b2a4a6c3"
+                "reference": "0f286297fe8bdd05594b11714ff4521e49a1e738"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/alipay/alipay-sdk-php-all/zipball/3b86882423995c15992c277ffeb1c8e8b2a4a6c3",
-                "reference": "3b86882423995c15992c277ffeb1c8e8b2a4a6c3",
+                "url": "https://api.github.com/repos/alipay/alipay-sdk-php-all/zipball/0f286297fe8bdd05594b11714ff4521e49a1e738",
+                "reference": "0f286297fe8bdd05594b11714ff4521e49a1e738",
                 "shasum": ""
             },
             "require": {
@@ -564,7 +564,7 @@
             "support": {
                 "source": "https://github.com/alipay/alipay-sdk-php-all/tree/master"
             },
-            "time": "2024-03-27T06:32:49+00:00"
+            "time": "2024-04-16T07:11:33+00:00"
         },
         {
             "name": "aws/aws-crt-php",
@@ -622,16 +622,16 @@
         },
         {
             "name": "aws/aws-sdk-php",
-            "version": "3.304.1",
+            "version": "3.304.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/aws/aws-sdk-php.git",
-                "reference": "6dac9b3257873a807ac73f6dc4418bdc49a5d9db"
+                "reference": "02abf9b8e2afbdf281e28757c582049d3db16df7"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6dac9b3257873a807ac73f6dc4418bdc49a5d9db",
-                "reference": "6dac9b3257873a807ac73f6dc4418bdc49a5d9db",
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/02abf9b8e2afbdf281e28757c582049d3db16df7",
+                "reference": "02abf9b8e2afbdf281e28757c582049d3db16df7",
                 "shasum": ""
             },
             "require": {
@@ -711,9 +711,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.304.1"
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.304.6"
             },
-            "time": "2024-04-09T19:25:27+00:00"
+            "time": "2024-04-17T18:27:31+00:00"
         },
         {
             "name": "bacon/bacon-qr-code",
@@ -1703,16 +1703,16 @@
         },
         {
             "name": "illuminate/collections",
-            "version": "v11.3.0",
+            "version": "v11.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/collections.git",
-                "reference": "aee944e8220588756e21aa4c30eebd5f6481e453"
+                "reference": "19c6554c7eba0efabc3f8aa4c434815b7f6b4b7d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/collections/zipball/aee944e8220588756e21aa4c30eebd5f6481e453",
-                "reference": "aee944e8220588756e21aa4c30eebd5f6481e453",
+                "url": "https://api.github.com/repos/illuminate/collections/zipball/19c6554c7eba0efabc3f8aa4c434815b7f6b4b7d",
+                "reference": "19c6554c7eba0efabc3f8aa4c434815b7f6b4b7d",
                 "shasum": ""
             },
             "require": {
@@ -1754,11 +1754,11 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-04-04T17:36:49+00:00"
+            "time": "2024-04-15T15:26:05+00:00"
         },
         {
             "name": "illuminate/conditionable",
-            "version": "v11.3.0",
+            "version": "v11.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/conditionable.git",
@@ -1804,7 +1804,7 @@
         },
         {
             "name": "illuminate/container",
-            "version": "v11.3.0",
+            "version": "v11.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/container.git",
@@ -1855,7 +1855,7 @@
         },
         {
             "name": "illuminate/contracts",
-            "version": "v11.3.0",
+            "version": "v11.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/contracts.git",
@@ -1903,16 +1903,16 @@
         },
         {
             "name": "illuminate/database",
-            "version": "v11.3.0",
+            "version": "v11.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/database.git",
-                "reference": "d9eabd0bb1d05b05f6d045b0e1d1d8e008e40eb1"
+                "reference": "aa4171c74d3bac4500128aedc6084377e2e4b950"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/database/zipball/d9eabd0bb1d05b05f6d045b0e1d1d8e008e40eb1",
-                "reference": "d9eabd0bb1d05b05f6d045b0e1d1d8e008e40eb1",
+                "url": "https://api.github.com/repos/illuminate/database/zipball/aa4171c74d3bac4500128aedc6084377e2e4b950",
+                "reference": "aa4171c74d3bac4500128aedc6084377e2e4b950",
                 "shasum": ""
             },
             "require": {
@@ -1967,11 +1967,11 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-04-09T14:34:24+00:00"
+            "time": "2024-04-16T14:29:11+00:00"
         },
         {
             "name": "illuminate/macroable",
-            "version": "v11.3.0",
+            "version": "v11.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/macroable.git",
@@ -2017,16 +2017,16 @@
         },
         {
             "name": "illuminate/pagination",
-            "version": "v11.3.0",
+            "version": "v11.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/pagination.git",
-                "reference": "ab541626a692597278bae9dabaf7ae3c3657e035"
+                "reference": "0752b63f17105b7de8fa3dea12acd3c4099db21e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/pagination/zipball/ab541626a692597278bae9dabaf7ae3c3657e035",
-                "reference": "ab541626a692597278bae9dabaf7ae3c3657e035",
+                "url": "https://api.github.com/repos/illuminate/pagination/zipball/0752b63f17105b7de8fa3dea12acd3c4099db21e",
+                "reference": "0752b63f17105b7de8fa3dea12acd3c4099db21e",
                 "shasum": ""
             },
             "require": {
@@ -2063,20 +2063,20 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-04-02T13:11:56+00:00"
+            "time": "2024-04-16T14:29:11+00:00"
         },
         {
             "name": "illuminate/support",
-            "version": "v11.3.0",
+            "version": "v11.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/support.git",
-                "reference": "0794cd2077e57cabe9dead2b081e7e20f71e4ffe"
+                "reference": "e7de8b8aa7658c827c48c99212927695848540b8"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/support/zipball/0794cd2077e57cabe9dead2b081e7e20f71e4ffe",
-                "reference": "0794cd2077e57cabe9dead2b081e7e20f71e4ffe",
+                "url": "https://api.github.com/repos/illuminate/support/zipball/e7de8b8aa7658c827c48c99212927695848540b8",
+                "reference": "e7de8b8aa7658c827c48c99212927695848540b8",
                 "shasum": ""
             },
             "require": {
@@ -2137,7 +2137,7 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2024-04-09T14:13:50+00:00"
+            "time": "2024-04-15T12:21:59+00:00"
         },
         {
             "name": "irazasyed/telegram-bot-sdk",
@@ -2283,16 +2283,16 @@
         },
         {
             "name": "lcobucci/jwt",
-            "version": "5.2.0",
+            "version": "5.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/lcobucci/jwt.git",
-                "reference": "0ba88aed12c04bd2ed9924f500673f32b67a6211"
+                "reference": "08071d8d2c7f4b00222cc4b1fb6aa46990a80f83"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/lcobucci/jwt/zipball/0ba88aed12c04bd2ed9924f500673f32b67a6211",
-                "reference": "0ba88aed12c04bd2ed9924f500673f32b67a6211",
+                "url": "https://api.github.com/repos/lcobucci/jwt/zipball/08071d8d2c7f4b00222cc4b1fb6aa46990a80f83",
+                "reference": "08071d8d2c7f4b00222cc4b1fb6aa46990a80f83",
                 "shasum": ""
             },
             "require": {
@@ -2340,7 +2340,7 @@
             ],
             "support": {
                 "issues": "https://github.com/lcobucci/jwt/issues",
-                "source": "https://github.com/lcobucci/jwt/tree/5.2.0"
+                "source": "https://github.com/lcobucci/jwt/tree/5.3.0"
             },
             "funding": [
                 {
@@ -2352,7 +2352,7 @@
                     "type": "patreon"
                 }
             ],
-            "time": "2023-11-20T21:17:42+00:00"
+            "time": "2024-04-11T23:07:54+00:00"
         },
         {
             "name": "league/event",
@@ -2989,21 +2989,21 @@
         },
         {
             "name": "openai-php/client",
-            "version": "v0.8.4",
+            "version": "v0.8.5",
             "source": {
                 "type": "git",
                 "url": "https://github.com/openai-php/client.git",
-                "reference": "00470f5fedd7b08ee4860959d6952f0be0ec48a0"
+                "reference": "0f755fafa4d3f8d5c8ed964d3166d078fac0605a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/openai-php/client/zipball/00470f5fedd7b08ee4860959d6952f0be0ec48a0",
-                "reference": "00470f5fedd7b08ee4860959d6952f0be0ec48a0",
+                "url": "https://api.github.com/repos/openai-php/client/zipball/0f755fafa4d3f8d5c8ed964d3166d078fac0605a",
+                "reference": "0f755fafa4d3f8d5c8ed964d3166d078fac0605a",
                 "shasum": ""
             },
             "require": {
                 "php": "^8.1.0",
-                "php-http/discovery": "^1.19.2",
+                "php-http/discovery": "^1.19.4",
                 "php-http/multipart-stream-builder": "^1.3.0",
                 "psr/http-client": "^1.0.3",
                 "psr/http-client-implementation": "^1.0.1",
@@ -3013,15 +3013,15 @@
             "require-dev": {
                 "guzzlehttp/guzzle": "^7.8.1",
                 "guzzlehttp/psr7": "^2.6.2",
-                "laravel/pint": "^1.13.7",
-                "mockery/mockery": "^1.6.7",
+                "laravel/pint": "^1.15.0",
+                "mockery/mockery": "^1.6.11",
                 "nunomaduro/collision": "^7.10.0",
-                "pestphp/pest": "^2.30.0",
-                "pestphp/pest-plugin-arch": "^2.6",
-                "pestphp/pest-plugin-type-coverage": "^2.7.0",
-                "phpstan/phpstan": "^1.10.55",
-                "rector/rector": "^0.16.0",
-                "symfony/var-dumper": "^6.4.2"
+                "pestphp/pest": "^2.34.6",
+                "pestphp/pest-plugin-arch": "^2.7",
+                "pestphp/pest-plugin-type-coverage": "^2.8.1",
+                "phpstan/phpstan": "^1.10.66",
+                "rector/rector": "^1.0.4",
+                "symfony/var-dumper": "^6.4.4"
             },
             "type": "library",
             "autoload": {
@@ -3061,7 +3061,7 @@
             ],
             "support": {
                 "issues": "https://github.com/openai-php/client/issues",
-                "source": "https://github.com/openai-php/client/tree/v0.8.4"
+                "source": "https://github.com/openai-php/client/tree/v0.8.5"
             },
             "funding": [
                 {
@@ -3077,50 +3077,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2024-02-07T07:57:38+00:00"
-        },
-        {
-            "name": "ozdemir/datatables",
-            "version": "2.3.7",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/n1crack/datatables.git",
-                "reference": "7d8d51dccc1647fc68d3b6f90453e3f8b8b8bf9d"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/n1crack/datatables/zipball/7d8d51dccc1647fc68d3b6f90453e3f8b8b8bf9d",
-                "reference": "7d8d51dccc1647fc68d3b6f90453e3f8b8b8bf9d",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=7.1.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^7.0|^8.0|^9.0"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "Ozdemir\\Datatables\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Yusuf Özdemir",
-                    "email": "[email protected]"
-                }
-            ],
-            "description": "PHP Library to handle server-side processing for Datatables, in a fast and simple way.",
-            "support": {
-                "issues": "https://github.com/n1crack/datatables/issues",
-                "source": "https://github.com/n1crack/datatables/tree/2.3.7"
-            },
-            "time": "2023-05-29T10:42:49+00:00"
+            "time": "2024-04-15T19:11:23+00:00"
         },
         {
             "name": "php-http/client-common",
@@ -4396,16 +4353,16 @@
         },
         {
             "name": "sendgrid/php-http-client",
-            "version": "4.1.0",
+            "version": "4.1.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sendgrid/php-http-client.git",
-                "reference": "84fe926f3d2ac3454f088c9a06ebdc398cc3727e"
+                "reference": "ec09bcfccabeb21d69e245a1e1c0e51f2813fc35"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sendgrid/php-http-client/zipball/84fe926f3d2ac3454f088c9a06ebdc398cc3727e",
-                "reference": "84fe926f3d2ac3454f088c9a06ebdc398cc3727e",
+                "url": "https://api.github.com/repos/sendgrid/php-http-client/zipball/ec09bcfccabeb21d69e245a1e1c0e51f2813fc35",
+                "reference": "ec09bcfccabeb21d69e245a1e1c0e51f2813fc35",
                 "shasum": ""
             },
             "require": {
@@ -4452,22 +4409,22 @@
                 "sendgrid"
             ],
             "support": {
-                "source": "https://github.com/sendgrid/php-http-client/tree/4.1.0"
+                "source": "https://github.com/sendgrid/php-http-client/tree/4.1.1"
             },
-            "time": "2023-12-01T05:16:21+00:00"
+            "time": "2023-12-14T08:50:59+00:00"
         },
         {
             "name": "sendgrid/sendgrid",
-            "version": "8.1.1",
+            "version": "8.1.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sendgrid/sendgrid-php.git",
-                "reference": "08514e75789f192c034fdcf18efe6d8b1a7c91da"
+                "reference": "6700d2cf50df38915fa2d9a03affbca58c48599f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sendgrid/sendgrid-php/zipball/08514e75789f192c034fdcf18efe6d8b1a7c91da",
-                "reference": "08514e75789f192c034fdcf18efe6d8b1a7c91da",
+                "url": "https://api.github.com/repos/sendgrid/sendgrid-php/zipball/6700d2cf50df38915fa2d9a03affbca58c48599f",
+                "reference": "6700d2cf50df38915fa2d9a03affbca58c48599f",
                 "shasum": ""
             },
             "require": {
@@ -4476,7 +4433,7 @@
                 "ext-mbstring": "*",
                 "ext-openssl": "*",
                 "php": ">=7.3",
-                "sendgrid/php-http-client": "4.1.0",
+                "sendgrid/php-http-client": "~4.1",
                 "starkbank/ecdsa": "0.*"
             },
             "replace": {
@@ -4517,9 +4474,9 @@
                 "twilio sendgrid"
             ],
             "support": {
-                "source": "https://github.com/sendgrid/sendgrid-php/tree/8.1.1"
+                "source": "https://github.com/sendgrid/sendgrid-php/tree/8.1.2"
             },
-            "time": "2023-12-06T07:11:08+00:00"
+            "time": "2024-04-18T11:09:09+00:00"
         },
         {
             "name": "sentry/sdk",
@@ -4578,16 +4535,16 @@
         },
         {
             "name": "sentry/sentry",
-            "version": "4.6.1",
+            "version": "4.7.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/getsentry/sentry-php.git",
-                "reference": "5a94184175e5830b589bf923da8c9c3af2c0f409"
+                "reference": "d6769b2a5e6bf19ed3bbfbf52328ceaf8e6fcb1f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/5a94184175e5830b589bf923da8c9c3af2c0f409",
-                "reference": "5a94184175e5830b589bf923da8c9c3af2c0f409",
+                "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/d6769b2a5e6bf19ed3bbfbf52328ceaf8e6fcb1f",
+                "reference": "d6769b2a5e6bf19ed3bbfbf52328ceaf8e6fcb1f",
                 "shasum": ""
             },
             "require": {
@@ -4651,7 +4608,7 @@
             ],
             "support": {
                 "issues": "https://github.com/getsentry/sentry-php/issues",
-                "source": "https://github.com/getsentry/sentry-php/tree/4.6.1"
+                "source": "https://github.com/getsentry/sentry-php/tree/4.7.0"
             },
             "funding": [
                 {
@@ -4663,7 +4620,7 @@
                     "type": "custom"
                 }
             ],
-            "time": "2024-03-08T08:18:09+00:00"
+            "time": "2024-04-10T13:22:13+00:00"
         },
         {
             "name": "slim/http",
@@ -5038,16 +4995,16 @@
         },
         {
             "name": "stripe/stripe-php",
-            "version": "v13.18.0",
+            "version": "v14.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/stripe/stripe-php.git",
-                "reference": "02abb043b103766f4ed920642ae56ffdc58c7467"
+                "reference": "6b77ba6b2f8791dabc5404befd6c0ead59203892"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/stripe/stripe-php/zipball/02abb043b103766f4ed920642ae56ffdc58c7467",
-                "reference": "02abb043b103766f4ed920642ae56ffdc58c7467",
+                "url": "https://api.github.com/repos/stripe/stripe-php/zipball/6b77ba6b2f8791dabc5404befd6c0ead59203892",
+                "reference": "6b77ba6b2f8791dabc5404befd6c0ead59203892",
                 "shasum": ""
             },
             "require": {
@@ -5091,9 +5048,9 @@
             ],
             "support": {
                 "issues": "https://github.com/stripe/stripe-php/issues",
-                "source": "https://github.com/stripe/stripe-php/tree/v13.18.0"
+                "source": "https://github.com/stripe/stripe-php/tree/v14.2.0"
             },
-            "time": "2024-04-09T21:08:04+00:00"
+            "time": "2024-04-16T15:58:21+00:00"
         },
         {
             "name": "symfony/clock",
@@ -6410,30 +6367,37 @@
         },
         {
             "name": "twig/twig",
-            "version": "v3.8.0",
+            "version": "v3.9.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/twigphp/Twig.git",
-                "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d"
+                "reference": "a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
-                "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
+                "url": "https://api.github.com/repos/twigphp/Twig/zipball/a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58",
+                "reference": "a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.2.5",
+                "symfony/deprecation-contracts": "^2.5|^3",
                 "symfony/polyfill-ctype": "^1.8",
                 "symfony/polyfill-mbstring": "^1.3",
                 "symfony/polyfill-php80": "^1.22"
             },
             "require-dev": {
                 "psr/container": "^1.0|^2.0",
-                "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0"
+                "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
             },
             "type": "library",
             "autoload": {
+                "files": [
+                    "src/Resources/core.php",
+                    "src/Resources/debug.php",
+                    "src/Resources/escaper.php",
+                    "src/Resources/string_loader.php"
+                ],
                 "psr-4": {
                     "Twig\\": "src/"
                 }
@@ -6466,7 +6430,7 @@
             ],
             "support": {
                 "issues": "https://github.com/twigphp/Twig/issues",
-                "source": "https://github.com/twigphp/Twig/tree/v3.8.0"
+                "source": "https://github.com/twigphp/Twig/tree/v3.9.3"
             },
             "funding": [
                 {
@@ -6478,7 +6442,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2023-11-21T18:54:41+00:00"
+            "time": "2024-04-18T11:59:33+00:00"
         },
         {
             "name": "vectorface/googleauthenticator",
@@ -7273,16 +7237,16 @@
         },
         {
             "name": "friendsofphp/php-cs-fixer",
-            "version": "v3.53.0",
+            "version": "v3.54.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
-                "reference": "69a19093a9ded8d1baac62ed6c009b8bc148d008"
+                "reference": "2aecbc8640d7906c38777b3dcab6f4ca79004d08"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/69a19093a9ded8d1baac62ed6c009b8bc148d008",
-                "reference": "69a19093a9ded8d1baac62ed6c009b8bc148d008",
+                "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/2aecbc8640d7906c38777b3dcab6f4ca79004d08",
+                "reference": "2aecbc8640d7906c38777b3dcab6f4ca79004d08",
                 "shasum": ""
             },
             "require": {
@@ -7354,7 +7318,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.53.0"
+                "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.54.0"
             },
             "funding": [
                 {
@@ -7362,7 +7326,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2024-04-08T15:03:00+00:00"
+            "time": "2024-04-17T08:12:13+00:00"
         },
         {
             "name": "justinrainbow/json-schema",
@@ -8288,16 +8252,16 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "10.5.17",
+            "version": "10.5.19",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "c1f736a473d21957ead7e94fcc029f571895abf5"
+                "reference": "c726f0de022368f6ed103e452a765d3304a996a4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c1f736a473d21957ead7e94fcc029f571895abf5",
-                "reference": "c1f736a473d21957ead7e94fcc029f571895abf5",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c726f0de022368f6ed103e452a765d3304a996a4",
+                "reference": "c726f0de022368f6ed103e452a765d3304a996a4",
                 "shasum": ""
             },
             "require": {
@@ -8369,7 +8333,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.5.17"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.19"
             },
             "funding": [
                 {
@@ -8385,7 +8349,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-04-05T04:39:01+00:00"
+            "time": "2024-04-17T14:06:18+00:00"
         },
         {
             "name": "psr/cache",

+ 4 - 23
resources/views/tabler/admin/announcement/create.tpl

@@ -1,7 +1,5 @@
 {include file='admin/header.tpl'}
 
-<script src="//cdnjs.cloudflare.com/ajax/libs/tinymce/7.0.0/tinymce.min.js"></script>
-
 <div class="page-wrapper">
     <div class="container-xl">
         <div class="page-header d-print-none text-white">
@@ -16,7 +14,7 @@
                 </div>
                 <div class="col-auto ms-auto d-print-none">
                     <div class="btn-list">
-                        <button id="create-ann" href="#" class="btn btn-primary">
+                        <button id="create" href="#" class="btn btn-primary">
                             <i class="icon ti ti-device-floppy"></i>
                             保存
                         </button>
@@ -61,27 +59,10 @@
     </div>
 </div>
 
-<script>
-    document.addEventListener("DOMContentLoaded", function () {
-        let options = {
-            selector: '#tinymce',
-            menubar: false,
-            statusbar: false,
-            plugins:
-                'advlist autolink lists link image charmap preview anchor searchreplace visualblocks ' +
-                'code insertdatetime media table',
-            toolbar: 'undo redo | bold italic backcolor link | styles | fontsize | lineheight | alignleft aligncenter ' +
-                'alignright alignjustify | bullist numlist outdent indent | removeformat',
-            content_style: 'body { font-size: 14px; }',
-            {if $user->is_dark_mode}
-            skin: 'oxide-dark',
-            content_css: 'dark',
-            {/if}
-        }
-        tinyMCE.init(options);
-    })
+{include file='tinymce.tpl'}
 
-    $("#create-ann").click(function () {
+<script>
+    $("#create").click(function () {
         $.ajax({
             url: '/admin/announcement',
             type: 'POST',

+ 4 - 23
resources/views/tabler/admin/announcement/edit.tpl

@@ -1,7 +1,5 @@
 {include file='admin/header.tpl'}
 
-<script src="//cdnjs.cloudflare.com/ajax/libs/tinymce/7.0.0/tinymce.min.js"></script>
-
 <div class="page-wrapper">
     <div class="container-xl">
         <div class="page-header d-print-none text-white">
@@ -16,7 +14,7 @@
                 </div>
                 <div class="col-auto ms-auto d-print-none">
                     <div class="btn-list">
-                        <button id="save-ann" href="#" class="btn btn-primary">
+                        <button id="save" href="#" class="btn btn-primary">
                             <i class="icon ti ti-device-floppy"></i>
                             保存
                         </button>
@@ -40,27 +38,10 @@
     </div>
 </div>
 
-<script>
-    document.addEventListener("DOMContentLoaded", function () {
-        let options = {
-            selector: '#tinymce',
-            menubar: false,
-            statusbar: false,
-            plugins:
-                'advlist autolink lists link image charmap preview anchor searchreplace visualblocks ' +
-                'code insertdatetime media table',
-            toolbar: 'undo redo | bold italic backcolor link | styles | fontsize | lineheight | alignleft aligncenter ' +
-                'alignright alignjustify | bullist numlist outdent indent | removeformat',
-            content_style: 'body { font-size: 14px; }',
-            {if $user->is_dark_mode}
-            skin: 'oxide-dark',
-            content_css: 'dark',
-            {/if}
-        }
-        tinyMCE.init(options);
-    })
+{include file='tinymce.tpl'}
 
-    $("#save-ann").click(function () {
+<script>
+    $("#save").click(function () {
         $.ajax({
             url: '/admin/announcement/' + {$ann->id},
             type: 'PUT',

+ 5 - 24
resources/views/tabler/admin/docs/create.tpl

@@ -1,7 +1,5 @@
 {include file='admin/header.tpl'}
 
-<script src="//cdnjs.cloudflare.com/ajax/libs/tinymce/7.0.0/tinymce.min.js"></script>
-
 <div class="page-wrapper">
     <div class="container-xl">
         <div class="page-header d-print-none text-white">
@@ -21,7 +19,7 @@
                             <i class="icon ti ti-robot"></i>
                             AI 文档生成
                         </button>
-                        <button id="create-doc" href="#" class="btn btn-primary">
+                        <button id="create" href="#" class="btn btn-primary">
                             <i class="icon ti ti-device-floppy"></i>
                             保存
                         </button>
@@ -71,26 +69,9 @@
     </div>
 </div>
 
-<script>
-    document.addEventListener("DOMContentLoaded", function () {
-        let options = {
-            selector: '#tinymce',
-            menubar: false,
-            statusbar: false,
-            plugins:
-                'advlist autolink lists link image charmap preview anchor searchreplace visualblocks ' +
-                'code insertdatetime media table',
-            toolbar: 'undo redo | bold italic backcolor link | styles | fontsize | lineheight | alignleft aligncenter ' +
-                'alignright alignjustify | bullist numlist outdent indent | removeformat',
-            content_style: 'body { font-size: 14px; }',
-            {if $user->is_dark_mode}
-            skin: 'oxide-dark',
-            content_css: 'dark',
-            {/if}
-        }
-        tinyMCE.init(options);
-    })
+{include file='tinymce.tpl'}
 
+<script>
     $("#generate").click(function () {
         $.ajax({
             url: "/admin/docs/generate",
@@ -112,14 +93,14 @@
         })
     });
 
-    $("#create-doc").click(function () {
+    $("#create").click(function () {
         $.ajax({
             url: '/admin/docs',
             type: 'POST',
             dataType: "json",
             data: {
                 title: $("#title").val(),
-                content: tinyMCE.get('tinymce').getContent(),
+                content: tinyMCE.activeEditor.getContent(),
             },
             success: function (data) {
                 if (data.ret === 1) {

+ 4 - 23
resources/views/tabler/admin/docs/edit.tpl

@@ -1,7 +1,5 @@
 {include file='admin/header.tpl'}
 
-<script src="//cdnjs.cloudflare.com/ajax/libs/tinymce/7.0.0/tinymce.min.js"></script>
-
 <div class="page-wrapper">
     <div class="container-xl">
         <div class="page-header d-print-none text-white">
@@ -16,7 +14,7 @@
                 </div>
                 <div class="col-auto ms-auto d-print-none">
                     <div class="btn-list">
-                        <button id="save-doc" href="#" class="btn btn-primary">
+                        <button id="save" href="#" class="btn btn-primary">
                             <i class="icon ti ti-device-floppy"></i>
                             保存
                         </button>
@@ -46,27 +44,10 @@
     </div>
 </div>
 
-<script>
-    document.addEventListener("DOMContentLoaded", function () {
-        let options = {
-            selector: '#tinymce',
-            menubar: false,
-            statusbar: false,
-            plugins:
-                'advlist autolink lists link image charmap preview anchor searchreplace visualblocks ' +
-                'code insertdatetime media table',
-            toolbar: 'undo redo | bold italic backcolor link | styles | fontsize | lineheight | alignleft aligncenter ' +
-                'alignright alignjustify | bullist numlist outdent indent | removeformat',
-            content_style: 'body { font-size: 14px; }',
-            {if $user->is_dark_mode}
-            skin: 'oxide-dark',
-            content_css: 'dark',
-            {/if}
-        }
-        tinyMCE.init(options);
-    })
+{include file='tinymce.tpl'}
 
-    $("#save-doc").click(function () {
+<script>
+    $("#save").click(function () {
         $.ajax({
             url: '/admin/docs/' + {$doc->id},
             type: 'PUT',

+ 2 - 2
resources/views/tabler/datatable.tpl

@@ -1,5 +1,5 @@
-<link href="//cdn.datatables.net/v/bs5/dt-2.0.3/datatables.min.css" rel="stylesheet"/>
-<script src="//cdn.datatables.net/v/bs5/dt-2.0.3/datatables.min.js"></script>
+<link href="//cdn.datatables.net/v/bs5/dt-2.0.4/datatables.min.css" rel="stylesheet"/>
+<script src="//cdn.datatables.net/v/bs5/dt-2.0.4/datatables.min.js"></script>
 
 <script>
     let tableConfig = {

+ 23 - 0
resources/views/tabler/tinymce.tpl

@@ -0,0 +1,23 @@
+<script src="//cdnjs.cloudflare.com/ajax/libs/tinymce/7.0.1/tinymce.min.js"></script>
+
+<script>
+    document.addEventListener("DOMContentLoaded", function () {
+        tinyMCE.baseURL = '//cdnjs.cloudflare.com/ajax/libs/tinymce/7.0.1/';
+        tinyMCE.suffix = '.min';
+        tinyMCE.init({
+            selector: '#tinymce',
+            menubar: false,
+            statusbar: false,
+            plugins:
+                'advlist autolink lists link image charmap preview anchor searchreplace visualblocks ' +
+                'code insertdatetime media table',
+            toolbar: 'undo redo | bold italic backcolor link | styles | fontsize | lineheight | alignleft aligncenter ' +
+                'alignright alignjustify | bullist numlist outdent indent | removeformat',
+            content_style: 'body { font-size: 14px; }',
+            {if $user->is_dark_mode}
+            skin: 'oxide-dark',
+            content_css: 'dark',
+            {/if}
+        });
+    })
+</script>

+ 2 - 2
src/Controllers/Admin/AnnController.php

@@ -116,7 +116,7 @@ final class AnnController extends BaseController
         if (Config::obtain('enable_telegram')) {
             try {
                 (new Telegram())->sendHtml(0, '新公告:' . PHP_EOL . $content);
-            } catch (TelegramSDKException $e) {
+            } catch (TelegramSDKException) {
                 return $response->withJson([
                     'ret' => 0,
                     'msg' => $email_notify === 1 ? '公告添加成功,邮件发送成功,Telegram发送失败' : '公告添加成功,Telegram发送失败',
@@ -164,7 +164,7 @@ final class AnnController extends BaseController
         if (Config::obtain('enable_telegram')) {
             try {
                 (new Telegram())->sendHtml(0, '公告更新:' . PHP_EOL . $request->getParam('content'));
-            } catch (TelegramSDKException $e) {
+            } catch (TelegramSDKException) {
                 return $response->withJson([
                     'ret' => 0,
                     'msg' => '公告更新成功,Telegram发送失败',

+ 3 - 3
src/Controllers/Admin/NodeController.php

@@ -140,7 +140,7 @@ final class NodeController extends BaseController
                         Config::obtain('telegram_add_node_text')
                     )
                 );
-            } catch (TelegramSDKException $e) {
+            } catch (TelegramSDKException) {
                 return $response->withJson([
                     'ret' => 1,
                     'msg' => '添加成功,但 Telegram 通知失败',
@@ -234,7 +234,7 @@ final class NodeController extends BaseController
                         Config::obtain('telegram_update_node_text')
                     )
                 );
-            } catch (TelegramSDKException $e) {
+            } catch (TelegramSDKException) {
                 return $response->withJson([
                     'ret' => 1,
                     'msg' => '修改成功,但 Telegram 通知失败',
@@ -296,7 +296,7 @@ final class NodeController extends BaseController
                         Config::obtain('telegram_delete_node_text')
                     )
                 );
-            } catch (TelegramSDKException $e) {
+            } catch (TelegramSDKException) {
                 return $response->withJson([
                     'ret' => 1,
                     'msg' => '删除成功,但Telegram通知失败',

+ 1 - 1
src/Controllers/Admin/UserController.php

@@ -140,7 +140,7 @@ final class UserController extends BaseController
 
         return $response->withJson([
             'ret' => 1,
-            'msg' => '添加成功,用户邮箱:'.$email.' 密码:'.$password,
+            'msg' => '添加成功,用户邮箱:' . $email . ' 密码:'.$password,
         ]);
     }
 

+ 1 - 1
src/Controllers/AuthController.php

@@ -183,7 +183,7 @@ final class AuthController extends BaseController
                         'expire' => date('Y-m-d H:i:s', time() + Config::obtain('email_verify_code_ttl')),
                     ]
                 );
-            } catch (Exception|ClientExceptionInterface $e) {
+            } catch (Exception|ClientExceptionInterface) {
                 return ResponseHelper::error($response, '邮件发送失败,请联系网站管理员。');
             }
 

+ 1 - 1
src/Controllers/PasswordController.php

@@ -68,7 +68,7 @@ final class PasswordController extends BaseController
         if ($user !== null) {
             try {
                 Password::sendResetEmail($email);
-            } catch (ClientExceptionInterface|RedisException $e) {
+            } catch (ClientExceptionInterface|RedisException) {
                 $msg = '邮件发送失败';
             }
         }

+ 1 - 1
src/Models/Node.php

@@ -131,7 +131,7 @@ final class Node extends Model
                 $result = dns_get_record($this->server, DNS_A + DNS_AAAA);
                 $this->ipv4 = $result[0]['ip'] ?? '127.0.0.1';
                 $this->ipv6 = $result[1]['ipv6'] ?? '::1';
-            } catch (Exception $e) {
+            } catch (Exception) {
                 $this->ipv4 = '127.0.0.1';
                 $this->ipv6 = '::1';
             }

+ 1 - 1
src/Models/SubscribeLog.php

@@ -43,7 +43,7 @@ final class SubscribeLog extends Model
     {
         try {
             return Tools::getIpLocation($this->request_ip);
-        } catch (Exception $e) {
+        } catch (Exception) {
             return '未知';
         }
     }

+ 1 - 1
src/Models/User.php

@@ -95,7 +95,7 @@ final class User extends Model
      */
     public function getDiceBearAttribute(): string
     {
-        return 'https://api.dicebear.com/7.x/identicon/svg?seed=' . hash('sha3-256', $this->email);
+        return 'https://api.dicebear.com/8.x/identicon/svg?seed=' . hash('sha3-256', $this->email);
     }
 
     /**

+ 1 - 1
src/Services/Bot/Telegram/Callback.php

@@ -987,7 +987,7 @@ final class Callback
             if (! $traffic) {
                 $msg = '签到失败';
             } else {
-                $msg = '获得了 ' . $traffic . 'MB 流量.';
+                $msg = '获得了 ' . $traffic . 'MB 流量';
             }
         } else {
             $msg = '你今天已经签到过了';

+ 2 - 2
src/Services/Bot/Telegram/Commands/CheckinCommand.php

@@ -23,7 +23,7 @@ final class CheckinCommand extends Command
     /**
      * @var string Command Description
      */
-    protected string $description = '[群组/私聊] 每日签到.';
+    protected string $description = '[群组/私聊] 每日签到';
 
     /**
      * {@inheritdoc}
@@ -71,7 +71,7 @@ final class CheckinCommand extends Command
                 if (! $traffic) {
                     $msg = '签到失败';
                 } else {
-                    $msg = '获得了 ' . $traffic . 'MB 流量.';
+                    $msg = '获得了 ' . $traffic . 'MB 流量';
                 }
             } else {
                 $msg = '你今天已经签到过了';

+ 2 - 2
src/Services/Bot/Telegram/Commands/HelpCommand.php

@@ -23,7 +23,7 @@ final class HelpCommand extends Command
     /**
      * @var string Command Description
      */
-    protected string $description = '[群组/私聊] 系统中可用的所有命令.';
+    protected string $description = '[群组/私聊] 系统中可用的所有指令';
 
     public function handle(): void
     {
@@ -41,7 +41,7 @@ final class HelpCommand extends Command
 
         $this->replyWithChatAction(['action' => Actions::TYPING]);
         $commands = $this->telegram->getCommands();
-        $text = '系统中可用的所有命令.';
+        $text = '系统中可用的所有指令:';
         $text .= PHP_EOL . PHP_EOL;
 
         foreach ($commands as $name => $handler) {

+ 1 - 1
src/Services/Bot/Telegram/Commands/MenuCommand.php

@@ -23,7 +23,7 @@ final class MenuCommand extends Command
     /**
      * @var string Command Description
      */
-    protected string $description = '[私聊]     用户主菜单、个人中心.';
+    protected string $description = '[私聊] 个人中心';
 
     /**
      * {@inheritdoc}

+ 1 - 1
src/Services/Bot/Telegram/Commands/MyCommand.php

@@ -25,7 +25,7 @@ final class MyCommand extends Command
     /**
      * @var string Command Description
      */
-    protected string $description = '[群组/私聊] 我的个人信息.';
+    protected string $description = '[群组/私聊] 我的个人信息';
 
     /**
      * {@inheritdoc}

+ 4 - 4
src/Services/Bot/Telegram/Commands/PingCommand.php

@@ -23,7 +23,7 @@ final class PingCommand extends Command
     /**
      * @var string Command Description
      */
-    protected string $description = '[群组/私聊] 获取我或者群组的唯一 ID.';
+    protected string $description = '[群组/私聊] 获取我或者群组的唯一 ID';
 
     public function handle(): void
     {
@@ -38,7 +38,7 @@ final class PingCommand extends Command
 
             $text = [
                 'Pong!',
-                '你的 ID 是 ' . $chat_id . '.',
+                'User ID is ' . $chat_id,
             ];
 
             // 回送信息
@@ -59,8 +59,8 @@ final class PingCommand extends Command
 
             $text = [
                 'Pong!',
-                '你的 ID 是 ' . $message->getFrom()->getId() . '.',
-                '这个群组的 ID 是 ' . $chat_id . '.',
+                'User ID is ' . $message->getFrom()->getId(),
+                'Group ID is ' . $chat_id,
             ];
 
             // 回送信息

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

@@ -21,7 +21,7 @@ final class StartCommand extends Command
     /**
      * @var string Command Description
      */
-    protected string $description = '[群组/私聊] Bot 初始命令.';
+    protected string $description = '[群组/私聊] Bot 初始命令';
 
     public function handle(): void
     {
@@ -47,7 +47,7 @@ final class StartCommand extends Command
                 // 回送信息
                 $this->replyWithMessage(
                     [
-                        'text' => '喵喵喵.',
+                        'text' => '?',
                         'parse_mode' => 'Markdown',
                         'reply_to_message_id' => $message->getMessageId(),
                     ]

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

@@ -27,7 +27,7 @@ final class UnbindCommand extends Command
     /**
      * @var string Command Description
      */
-    protected string $description = '[私聊]     解除账户绑定.';
+    protected string $description = '[私聊] 解除账户绑定';
 
     /**
      * @throws TelegramSDKException
@@ -109,10 +109,10 @@ final class UnbindCommand extends Command
 
     public function sendText(): string
     {
-        $text = '以 `/unbind example@qq.com` 的形式发送进行解绑.';
+        $text = '以 `/unbind example@gmail.com` 的形式发送进行解绑。';
 
         if (Config::obtain('telegram_unbind_kick_member')) {
-            $text .= PHP_EOL . PHP_EOL . '根据管理员的设定,你解绑账户将会被自动移出用户群.';
+            $text .= PHP_EOL . PHP_EOL . '根据管理员的设定,你解绑账户将会被自动移出用户群';
         }
 
         return $text;

+ 6 - 14
src/Services/Bot/Telegram/Message.php

@@ -87,7 +87,7 @@ final class Message
 
         $member = [
             'id' => $new_chat_member->getId(),
-            'name' => $new_chat_member->getFirstName() . ' Message.php' . $new_chat_member->getLastName(),
+            'name' => $new_chat_member->getFirstName() . ' ' . $new_chat_member->getLastName(),
         ];
 
         if ($new_chat_member->getUsername() === Config::obtain('telegram_bot')) {
@@ -96,13 +96,6 @@ final class Message
                 &&
                 ! in_array($this->chat_id, json_decode(Config::obtain('group_id_allowed_to_join')))) {
                 // 退群
-
-                $this->replyWithMessage(
-                    [
-                        'text' => '不约,叔叔我们不约.',
-                    ]
-                );
-
                 self::sendPost(
                     'kickChatMember',
                     [
@@ -131,7 +124,7 @@ final class Message
             ) {
                 $this->replyWithMessage(
                     [
-                        'text' => '由于 ' . $member['name'] . ' 未绑定账户,将被移除。',
+                        'text' => $member['name'] . ' 未绑定 Telegram 账户,将被移除。',
                     ]
                 );
 
@@ -196,9 +189,9 @@ final class Message
     public static function getUserTitle(User $user): string
     {
         if ($user->class > 0) {
-            $text = '尊敬的 VIP ' . $user->class . ' 你好:';
+            $text = '付费用户你好:';
         } else {
-            $text = '尊敬的用户你好:';
+            $text = '免费用户你好:';
         }
 
         return $text;
@@ -236,10 +229,9 @@ final class Message
      * 搜索用户
      *
      * @param int $value  搜索值
-     * @param string $method 查找列
      */
-    public static function getUser(int $value, string $method = 'im_value'): null|Model|User
+    public static function getUser(int $value): null|Model|User
     {
-        return (new User())->where('im_type', 4)->where($method, $value)->first();
+        return (new User())->where('im_type', 4)->where('im_value', $value)->first();
     }
 }

+ 29 - 19
src/Services/Gateway/PayPal.php

@@ -63,11 +63,6 @@ final class PayPal extends Base
         return 'PayPal';
     }
 
-    /**
-     * @throws GuzzleException
-     * @throws RedisException
-     * @throws Throwable
-     */
     public function purchase(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
         $price = $this->antiXss->xss_clean($request->getParam('price'));
@@ -81,7 +76,14 @@ final class PayPal extends Base
             ]);
         }
 
-        $exchange_amount = (new Exchange())->exchange($price, 'CNY', Config::obtain('paypal_currency'));
+        try {
+            $exchange_amount = (new Exchange())->exchange($price, 'CNY', Config::obtain('paypal_currency'));
+        } catch (GuzzleException|RedisException) {
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => '汇率获取失败',
+            ]);
+        }
 
         $order_data = [
             'intent' => 'CAPTURE',
@@ -96,36 +98,44 @@ final class PayPal extends Base
             ],
         ];
 
-        $pp = new PayPalClient($this->gateway_config);
-        $pp->getAccessToken();
-
-        $order = $pp->createOrder($order_data);
+        try {
+            $pp = new PayPalClient($this->gateway_config);
+            $pp->getAccessToken();
+            $order = $pp->createOrder($order_data);
+        } catch (Throwable) {
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => 'PayPal API Error',
+            ]);
+        }
 
         $user = Auth::getUser();
-        $pl = new Paylist();
 
+        $pl = new Paylist();
         $pl->userid = $user->id;
         $pl->total = $price;
         $pl->invoice_id = $invoice_id;
         $pl->tradeno = $trade_no;
         $pl->gateway = self::_readableName();
-
         $pl->save();
 
         return $response->withJson($order);
     }
 
-    /**
-     * @throws Throwable
-     */
     public function notify($request, $response, $args): ResponseInterface
     {
         $order_id = $this->antiXss->xss_clean($request->getParam('order_id'));
 
-        $pp = new PayPalClient($this->gateway_config);
-        $pp->getAccessToken();
-
-        $result = $pp->capturePaymentOrder($order_id);
+        try {
+            $pp = new PayPalClient($this->gateway_config);
+            $pp->getAccessToken();
+            $result = $pp->capturePaymentOrder($order_id);
+        } catch (Throwable) {
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => 'PayPal API Error',
+            ]);
+        }
 
         if (isset($result['status']) && $result['status'] === 'COMPLETED') {
             $this->postPayment($result['purchase_units'][0]['reference_id']);

+ 10 - 7
src/Services/Gateway/Stripe.php

@@ -45,10 +45,6 @@ final class Stripe extends Base
         return 'Stripe';
     }
 
-    /**
-     * @throws GuzzleException
-     * @throws RedisException
-     */
     public function purchase(ServerRequest $request, Response $response, array $args): ResponseInterface
     {
         $price = $this->antiXss->xss_clean($request->getParam('price'));
@@ -65,8 +61,8 @@ final class Stripe extends Base
         }
 
         $user = Auth::getUser();
-        $pl = new Paylist();
 
+        $pl = new Paylist();
         $pl->userid = $user->id;
         $pl->total = $price;
         $pl->invoice_id = $invoice_id;
@@ -74,7 +70,14 @@ final class Stripe extends Base
         $pl->gateway = self::_readableName();
         $pl->save();
 
-        $exchange_amount = (new Exchange())->exchange((float) $price, 'CNY', Config::obtain('stripe_currency'));
+        try {
+            $exchange_amount = (new Exchange())->exchange((float) $price, 'CNY', Config::obtain('stripe_currency'));
+        } catch (GuzzleException|RedisException) {
+            return $response->withJson([
+                'ret' => 0,
+                'msg' => '汇率获取失败',
+            ]);
+        }
 
         StripeSDK::setApiKey(Config::obtain('stripe_sk'));
         $session = null;
@@ -103,7 +106,7 @@ final class Stripe extends Base
                 'success_url' => $_ENV['baseUrl'] . '/user/invoice/' . $invoice_id,
                 'cancel_url' => $_ENV['baseUrl'] . '/user/invoice/' . $invoice_id,
             ]);
-        } catch (ApiErrorException $e) {
+        } catch (ApiErrorException) {
             return $response->withJson([
                 'ret' => 0,
                 'msg' => 'Stripe API error',

+ 1 - 1
src/Services/LLM/VertexAI.php

@@ -21,7 +21,7 @@ final class VertexAI extends Base
 
         $client = new Client();
 
-        $api_url = 'https://' . $_ENV['vertex_ai_location'] .'-aiplatform.googleapis.com/v1/projects/' .
+        $api_url = 'https://' . $_ENV['vertex_ai_location'] . '-aiplatform.googleapis.com/v1/projects/' .
             $_ENV['vertex_ai_project_id'] . '/locations/' . $_ENV['vertex_ai_location'] . '/publishers/google/models/' .
             $_ENV['vertex_ai_model_id'] . ':streamGenerateContent';
 

+ 1 - 1
src/Services/RateLimit.php

@@ -36,7 +36,7 @@ final class RateLimit
 
         try {
             $limiter->limit($value);
-        } catch (LimitExceeded $e) {
+        } catch (LimitExceeded) {
             return false;
         }
 

+ 1 - 1
src/Services/Reward.php

@@ -134,7 +134,7 @@ final class Reward
         } else {
             try {
                 $traffic = random_int($checkin_min, $checkin_max);
-            } catch (Exception $e) {
+            } catch (Exception) {
                 $traffic = 0;
             }
         }

+ 4 - 4
src/Utils/Tools.php

@@ -57,19 +57,19 @@ final class Tools
         if ($_ENV['maxmind_license_key'] !== '') {
             try {
                 $geoip = new GeoIP2();
-            } catch (InvalidDatabaseException $e) {
+            } catch (InvalidDatabaseException) {
                 return $data;
             }
 
             try {
                 $city = $geoip->getCity($ip);
-            } catch (AddressNotFoundException|InvalidDatabaseException $e) {
+            } catch (AddressNotFoundException|InvalidDatabaseException) {
                 $city = '未知城市';
             }
 
             try {
                 $country = $geoip->getCountry($ip);
-            } catch (AddressNotFoundException|InvalidDatabaseException $e) {
+            } catch (AddressNotFoundException|InvalidDatabaseException) {
                 $country = '未知国家';
             }
         }
@@ -182,7 +182,7 @@ final class Tools
 
         try {
             $randomString = bin2hex(random_bytes((int) ceil($length / 2)));
-        } catch (RandomException $e) {
+        } catch (RandomException) {
             return false;
         }
 

+ 0 - 3
update.sh

@@ -1,9 +1,6 @@
 #!/usr/bin/bash
 
 cat << "EOF"
-SSPanel-UIM update script
-Author: M1Screw
-Github: https://github.com/sspanel-uim/SSPanel-Uim-Dev
 Usage:
 ./update.sh dev --> Upgrade to the latest development version
 ./update.sh release $release_version $db_version --> Upgrade to the release version with the specified database version