Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e54060e527 | ||
|
|
ca14674c36 | ||
|
|
1e27fb9413 | ||
|
|
460483fdef | ||
|
|
3a733c85ad |
-131
@@ -1,131 +0,0 @@
|
|||||||
import os
|
|
||||||
import time
|
|
||||||
import requests
|
|
||||||
import hashlib
|
|
||||||
from github import Github
|
|
||||||
|
|
||||||
|
|
||||||
def get_github_latest_release():
|
|
||||||
g = Github()
|
|
||||||
repo = g.get_repo("naiba/nezha")
|
|
||||||
release = repo.get_latest_release()
|
|
||||||
if release:
|
|
||||||
print(f"Latest release tag is: {release.tag_name}")
|
|
||||||
print(f"Latest release info is: {release.body}")
|
|
||||||
files = []
|
|
||||||
for asset in release.get_assets():
|
|
||||||
url = asset.browser_download_url
|
|
||||||
name = asset.name
|
|
||||||
|
|
||||||
response = requests.get(url)
|
|
||||||
if response.status_code == 200:
|
|
||||||
with open(name, 'wb') as f:
|
|
||||||
f.write(response.content)
|
|
||||||
print(f"Downloaded {name}")
|
|
||||||
else:
|
|
||||||
print(f"Failed to download {name}")
|
|
||||||
file_abs_path = get_abs_path(asset.name)
|
|
||||||
files.append(file_abs_path)
|
|
||||||
sync_to_gitee(release.tag_name, release.body, files)
|
|
||||||
else:
|
|
||||||
print("No releases found.")
|
|
||||||
|
|
||||||
|
|
||||||
def delete_gitee_releases(latest_id, client, uri, token):
|
|
||||||
get_data = {
|
|
||||||
'access_token': token
|
|
||||||
}
|
|
||||||
|
|
||||||
release_info = []
|
|
||||||
release_response = client.get(uri, json=get_data)
|
|
||||||
if release_response.status_code == 200:
|
|
||||||
release_info = release_response.json()
|
|
||||||
else:
|
|
||||||
print(
|
|
||||||
f"Request failed with status code {release_response.status_code}")
|
|
||||||
|
|
||||||
release_ids = []
|
|
||||||
for block in release_info:
|
|
||||||
if 'id' in block:
|
|
||||||
release_ids.append(block['id'])
|
|
||||||
|
|
||||||
print(f'Current release ids: {release_ids}')
|
|
||||||
release_ids.remove(latest_id)
|
|
||||||
|
|
||||||
for id in release_ids:
|
|
||||||
release_uri = f"{uri}/{id}"
|
|
||||||
delete_data = {
|
|
||||||
'access_token': token
|
|
||||||
}
|
|
||||||
delete_response = client.delete(release_uri, json=delete_data)
|
|
||||||
if delete_response.status_code == 204:
|
|
||||||
print(f'Successfully deleted release #{id}.')
|
|
||||||
else:
|
|
||||||
raise ValueError(
|
|
||||||
f"Request failed with status code {delete_response.status_code}")
|
|
||||||
|
|
||||||
|
|
||||||
def sync_to_gitee(tag: str, body: str, files: slice):
|
|
||||||
release_id = ""
|
|
||||||
owner = "naibahq"
|
|
||||||
repo = "nezha"
|
|
||||||
release_api_uri = f"https://gitee.com/api/v5/repos/{owner}/{repo}/releases"
|
|
||||||
api_client = requests.Session()
|
|
||||||
api_client.headers.update({
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
})
|
|
||||||
|
|
||||||
access_token = os.environ['GITEE_TOKEN']
|
|
||||||
release_data = {
|
|
||||||
'access_token': access_token,
|
|
||||||
'tag_name': tag,
|
|
||||||
'name': tag,
|
|
||||||
'body': body,
|
|
||||||
'prerelease': False,
|
|
||||||
'target_commitish': 'master'
|
|
||||||
}
|
|
||||||
release_api_response = api_client.post(release_api_uri, json=release_data)
|
|
||||||
if release_api_response.status_code == 201:
|
|
||||||
release_info = release_api_response.json()
|
|
||||||
release_id = release_info.get('id')
|
|
||||||
else:
|
|
||||||
print(
|
|
||||||
f"Request failed with status code {release_api_response.status_code}")
|
|
||||||
|
|
||||||
print(f"Gitee release id: {release_id}")
|
|
||||||
asset_api_uri = f"{release_api_uri}/{release_id}/attach_files"
|
|
||||||
|
|
||||||
for file_path in files:
|
|
||||||
files = {
|
|
||||||
'file': open(file_path, 'rb')
|
|
||||||
}
|
|
||||||
|
|
||||||
asset_api_response = requests.post(
|
|
||||||
asset_api_uri, params={'access_token': access_token}, files=files)
|
|
||||||
|
|
||||||
if asset_api_response.status_code == 201:
|
|
||||||
asset_info = asset_api_response.json()
|
|
||||||
asset_name = asset_info.get('name')
|
|
||||||
print(f"Successfully uploaded {asset_name}!")
|
|
||||||
else:
|
|
||||||
print(
|
|
||||||
f"Request failed with status code {asset_api_response.status_code}")
|
|
||||||
|
|
||||||
# 仅保留最新 Release 以防超出 Gitee 仓库配额
|
|
||||||
try:
|
|
||||||
delete_gitee_releases(release_id, api_client,
|
|
||||||
release_api_uri, access_token)
|
|
||||||
except ValueError as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
api_client.close()
|
|
||||||
print("Sync is completed!")
|
|
||||||
|
|
||||||
|
|
||||||
def get_abs_path(path: str):
|
|
||||||
wd = os.getcwd()
|
|
||||||
return os.path.join(wd, path)
|
|
||||||
|
|
||||||
|
|
||||||
get_github_latest_release()
|
|
||||||
@@ -12,13 +12,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Fetch IPInfo GeoIP Database
|
|
||||||
env:
|
|
||||||
IPINFO_TOKEN: ${{ secrets.IPINFO_TOKEN }}
|
|
||||||
run: |
|
|
||||||
rm pkg/geoip/geoip.db
|
|
||||||
wget -O pkg/geoip/geoip.db https://ipinfo.io/data/free/country.mmdb?token=${IPINFO_TOKEN}
|
|
||||||
|
|
||||||
- name: Extract branch name
|
- name: Extract branch name
|
||||||
run: |
|
run: |
|
||||||
export TAG_NAME=$(echo ${GITHUB_REF#refs/tags/})
|
export TAG_NAME=$(echo ${GITHUB_REF#refs/tags/})
|
||||||
@@ -29,21 +22,19 @@ jobs:
|
|||||||
uses: crazy-max/ghaction-xgo@v2
|
uses: crazy-max/ghaction-xgo@v2
|
||||||
with:
|
with:
|
||||||
xgo_version: latest
|
xgo_version: latest
|
||||||
go_version: 1.21.x
|
go_version: 1.21
|
||||||
dest: dist
|
dest: dist
|
||||||
pkg: cmd/dashboard
|
pkg: cmd/dashboard
|
||||||
prefix: dashboard
|
prefix: dashboard
|
||||||
targets: linux/amd64,linux/arm64,linux/arm-7,linux/s390x,linux/riscv64,windows/amd64,windows/386,windows/arm64 # linux/386,
|
targets: linux/amd64,linux/arm64,linux/arm-7,linux/s390x,linux/riscv64 # linux/386,
|
||||||
v: true
|
v: true
|
||||||
x: false
|
x: false
|
||||||
race: false
|
race: false
|
||||||
tags: timetzdata
|
|
||||||
ldflags: -s -w --extldflags '-static -fpic' -X github.com/naiba/nezha/service/singleton.Version=${{ steps.extract_branch.outputs.tag }}
|
ldflags: -s -w --extldflags '-static -fpic' -X github.com/naiba/nezha/service/singleton.Version=${{ steps.extract_branch.outputs.tag }}
|
||||||
buildmode: default
|
buildmode: default
|
||||||
|
|
||||||
- name: fix dist
|
- name: fix dist
|
||||||
run: |
|
run: |
|
||||||
ls -al dist/
|
|
||||||
mv dist/dashboard-linux-arm-7 dist/dashboard-linux-arm
|
mv dist/dashboard-linux-arm-7 dist/dashboard-linux-arm
|
||||||
|
|
||||||
- name: Log in to the GHCR
|
- name: Log in to the GHCR
|
||||||
@@ -115,16 +106,3 @@ jobs:
|
|||||||
curl -s https://purge.jsdelivr.net/gh/$LOWER_USERNAME/nezha@master/script/nezha-agent.service
|
curl -s https://purge.jsdelivr.net/gh/$LOWER_USERNAME/nezha@master/script/nezha-agent.service
|
||||||
curl -s https://purge.jsdelivr.net/gh/$LOWER_USERNAME/nezha@master/script/docker-compose.yaml
|
curl -s https://purge.jsdelivr.net/gh/$LOWER_USERNAME/nezha@master/script/docker-compose.yaml
|
||||||
curl -s https://purge.jsdelivr.net/gh/$LOWER_USERNAME/nezha@master/script/config.yaml
|
curl -s https://purge.jsdelivr.net/gh/$LOWER_USERNAME/nezha@master/script/config.yaml
|
||||||
|
|
||||||
- name: Trigger sync
|
|
||||||
if: ${{ env.SYNCED == 0 }}
|
|
||||||
uses: actions/github-script@v6
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
script: |
|
|
||||||
await github.rest.actions.createWorkflowDispatch({
|
|
||||||
owner: 'naiba',
|
|
||||||
repo: 'nezha',
|
|
||||||
workflow_id: 'sync-release.yml',
|
|
||||||
ref: 'master'
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
name: Sync Release to Gitee
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
sync-release-to-gitee:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
GITEE_TOKEN: ${{ secrets.GITEE_TOKEN }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Sync to Gitee
|
|
||||||
run: |
|
|
||||||
pip3 install PyGitHub
|
|
||||||
python3 .github/sync.py
|
|
||||||
@@ -25,19 +25,14 @@ jobs:
|
|||||||
uses: crazy-max/ghaction-xgo@v2
|
uses: crazy-max/ghaction-xgo@v2
|
||||||
with:
|
with:
|
||||||
xgo_version: latest
|
xgo_version: latest
|
||||||
go_version: 1.21.x
|
go_version: 1.21
|
||||||
dest: dist
|
dest: dist
|
||||||
pkg: cmd/dashboard
|
pkg: cmd/dashboard
|
||||||
prefix: dashboard
|
prefix: dashboard
|
||||||
targets: linux/amd64,linux/arm64,linux/arm-7,linux/s390x,linux/riscv64,windows/amd64,windows/386,windows/arm64 # linux/386,
|
targets: linux/amd64,linux/arm64,linux/arm-7,linux/s390x,linux/riscv64 # linux/386,
|
||||||
v: true
|
v: true
|
||||||
x: false
|
x: false
|
||||||
race: false
|
race: false
|
||||||
tags: timetzdata
|
|
||||||
ldflags: -s -w --extldflags '-static -fpic' -X github.com/naiba/nezha/service/singleton.Version=test
|
ldflags: -s -w --extldflags '-static -fpic' -X github.com/naiba/nezha/service/singleton.Version=test
|
||||||
buildmode: default
|
buildmode: default
|
||||||
- name: fix dist
|
|
||||||
run: |
|
|
||||||
ls -al dist/
|
|
||||||
mv dist/dashboard-linux-arm-7 dist/dashboard-linux-arm
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,18 +32,13 @@ jobs:
|
|||||||
uses: crazy-max/ghaction-xgo@v2
|
uses: crazy-max/ghaction-xgo@v2
|
||||||
with:
|
with:
|
||||||
xgo_version: latest
|
xgo_version: latest
|
||||||
go_version: 1.21.x
|
go_version: 1.21
|
||||||
dest: dist
|
dest: dist
|
||||||
pkg: cmd/dashboard
|
pkg: cmd/dashboard
|
||||||
prefix: dashboard
|
prefix: dashboard
|
||||||
targets: linux/amd64,linux/arm64,linux/arm-7,linux/s390x,linux/riscv64,windows/amd64,windows/386,windows/arm64 # linux/386,
|
targets: linux/amd64,linux/arm64,linux/arm-7,linux/s390x,linux/riscv64 # linux/386,
|
||||||
v: true
|
v: true
|
||||||
x: false
|
x: false
|
||||||
race: false
|
race: false
|
||||||
tags: timetzdata
|
|
||||||
ldflags: -s -w --extldflags '-static -fpic' -X github.com/naiba/nezha/service/singleton.Version=test
|
ldflags: -s -w --extldflags '-static -fpic' -X github.com/naiba/nezha/service/singleton.Version=test
|
||||||
buildmode: default
|
buildmode: default
|
||||||
- name: fix dist
|
|
||||||
run: |
|
|
||||||
ls -al dist/
|
|
||||||
mv dist/dashboard-linux-arm-7 dist/dashboard-linux-arm
|
|
||||||
|
|||||||
@@ -4,15 +4,13 @@
|
|||||||
<br>
|
<br>
|
||||||
<small><i>LOGO designed by <a href="https://xio.ng" target="_blank">熊大</a> .</i></small>
|
<small><i>LOGO designed by <a href="https://xio.ng" target="_blank">熊大</a> .</i></small>
|
||||||
<br><br>
|
<br><br>
|
||||||
<img alt="GitHub release (with filter)" src="https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&style=for-the-badge&logo=github&label=Dashboard"> <img src="https://img.shields.io/github/v/release/nezhahq/agent?color=brightgreen&label=Agent&style=for-the-badge&logo=github"> <img src="https://img.shields.io/github/actions/workflow/status/nezhahq/agent/agent.yml?label=Agent%20CI&logo=github&style=for-the-badge"> <img src="https://img.shields.io/badge/Installer-v0.18.3-brightgreen?style=for-the-badge&logo=linux">
|
<img alt="GitHub release (with filter)" src="https://img.shields.io/github/v/release/naiba/nezha?color=brightgreen&style=for-the-badge&logo=github&label=Dashboard"> <img src="https://img.shields.io/github/v/release/nezhahq/agent?color=brightgreen&label=Agent&style=for-the-badge&logo=github"> <img src="https://img.shields.io/github/actions/workflow/status/nezhahq/agent/agent.yml?label=Agent%20CI&logo=github&style=for-the-badge"> <img src="https://img.shields.io/badge/Installer-v0.15.9-brightgreen?style=for-the-badge&logo=linux">
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<p>:trollface: <b>Nezha Monitoring: Self-hostable, lightweight, servers and websites monitoring and O&M tool.</b></p>
|
<p>:trollface: <b>Nezha Monitoring: Self-hostable, lightweight, servers and websites monitoring and O&M tool.</b></p>
|
||||||
<p>Supports <b>monitoring</b> system status, HTTP (SSL certificate change, upcoming expiration, expired), TCP, Ping and supports <b>push alerts</b>, run scheduled tasks and <b>web terminal</b>.</p>
|
<p>Supports <b>monitoring</b> system status, HTTP (SSL certificate change, upcoming expiration, expired), TCP, Ping and supports <b>push alerts</b>, run scheduled tasks and <b>web terminal</b>.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
\>> Telegram Channel: [哪吒监控(中文通知频道)](https://t.me/nezhanews)
|
|
||||||
|
|
||||||
\>> Telegram Group: [Nezha Monitoring Global (English Only)](https://t.me/nezhamonitoring_global), [哪吒监控(中文群组)](https://t.me/nezhamonitoring)
|
\>> Telegram Group: [Nezha Monitoring Global (English Only)](https://t.me/nezhamonitoring_global), [哪吒监控(中文群组)](https://t.me/nezhamonitoring)
|
||||||
|
|
||||||
\>> [Use Cases | 我们的用户](https://www.google.com/search?q=%22powered+by+Nezha+Monitoring%22+OR+%22powered+by+%E5%93%AA%E5%90%92%E7%9B%91%E6%8E%A7%22) (Google)
|
\>> [Use Cases | 我们的用户](https://www.google.com/search?q=%22powered+by+Nezha+Monitoring%22+OR+%22powered+by+%E5%93%AA%E5%90%92%E7%9B%91%E6%8E%A7%22) (Google)
|
||||||
@@ -43,22 +41,22 @@ You can change the dashboard language in the settings page (`/setting`) after th
|
|||||||
<!--GAMFC_DELIMITER--><a href="https://github.com/naiba" title="naiba"><img src="https://avatars.githubusercontent.com/u/29243953?v=4" width="50;" alt="naiba"/></a>
|
<!--GAMFC_DELIMITER--><a href="https://github.com/naiba" title="naiba"><img src="https://avatars.githubusercontent.com/u/29243953?v=4" width="50;" alt="naiba"/></a>
|
||||||
<a href="https://github.com/AkkiaS7" title="Akkia"><img src="https://avatars.githubusercontent.com/u/68485070?v=4" width="50;" alt="Akkia"/></a>
|
<a href="https://github.com/AkkiaS7" title="Akkia"><img src="https://avatars.githubusercontent.com/u/68485070?v=4" width="50;" alt="Akkia"/></a>
|
||||||
<a href="https://github.com/Erope" title="卖女孩的小火柴"><img src="https://avatars.githubusercontent.com/u/44471469?v=4" width="50;" alt="卖女孩的小火柴"/></a>
|
<a href="https://github.com/Erope" title="卖女孩的小火柴"><img src="https://avatars.githubusercontent.com/u/44471469?v=4" width="50;" alt="卖女孩的小火柴"/></a>
|
||||||
<a href="https://github.com/uubulb" title="UUBulb"><img src="https://avatars.githubusercontent.com/u/35923940?v=4" width="50;" alt="UUBulb"/></a>
|
|
||||||
<a href="https://github.com/dysf888" title="黑歌"><img src="https://avatars.githubusercontent.com/u/47450409?v=4" width="50;" alt="黑歌"/></a>
|
<a href="https://github.com/dysf888" title="黑歌"><img src="https://avatars.githubusercontent.com/u/47450409?v=4" width="50;" alt="黑歌"/></a>
|
||||||
<a href="https://github.com/nap0o" title="nap0o"><img src="https://avatars.githubusercontent.com/u/144927971?v=4" width="50;" alt="nap0o"/></a>
|
|
||||||
<a href="https://github.com/xykt" title="xykt"><img src="https://avatars.githubusercontent.com/u/152045469?v=4" width="50;" alt="xykt"/></a>
|
|
||||||
<a href="https://github.com/MikoyChinese" title="MikoyChinese"><img src="https://avatars.githubusercontent.com/u/22676744?v=4" width="50;" alt="MikoyChinese"/></a>
|
<a href="https://github.com/MikoyChinese" title="MikoyChinese"><img src="https://avatars.githubusercontent.com/u/22676744?v=4" width="50;" alt="MikoyChinese"/></a>
|
||||||
<a href="https://github.com/JackieSung4ev" title="JackieSung4ev"><img src="https://avatars.githubusercontent.com/u/24974735?v=4" width="50;" alt="JackieSung4ev"/></a>
|
<a href="https://github.com/JackieSung4ev" title="JackieSung4ev"><img src="https://avatars.githubusercontent.com/u/24974735?v=4" width="50;" alt="JackieSung4ev"/></a>
|
||||||
<a href="https://github.com/cantoblanco" title="Kris"><img src="https://avatars.githubusercontent.com/u/116849421?v=4" width="50;" alt="Kris"/></a>
|
|
||||||
<a href="https://github.com/lemoeo" title="Lemoe"><img src="https://avatars.githubusercontent.com/u/18618627?v=4" width="50;" alt="Lemoe"/></a>
|
<a href="https://github.com/lemoeo" title="Lemoe"><img src="https://avatars.githubusercontent.com/u/18618627?v=4" width="50;" alt="Lemoe"/></a>
|
||||||
<a href="https://github.com/spiritLHLS" title="spiritlhl"><img src="https://avatars.githubusercontent.com/u/103393591?v=4" width="50;" alt="spiritlhl"/></a>
|
<a href="https://github.com/cantoblanco" title="Kris"><img src="https://avatars.githubusercontent.com/u/116849421?v=4" width="50;" alt="Kris"/></a>
|
||||||
<a href="https://github.com/liuyanxi975" title="刘颜溪"><img src="https://avatars.githubusercontent.com/u/24417037?v=4" width="50;" alt="刘颜溪"/></a>
|
<a href="https://github.com/nap0o" title="nap0o"><img src="https://avatars.githubusercontent.com/u/144927971?v=4" width="50;" alt="nap0o"/></a>
|
||||||
<a href="https://github.com/CosmosZ-code" title="CosmosZ-code"><img src="https://avatars.githubusercontent.com/u/81398224?v=4" width="50;" alt="CosmosZ-code"/></a>
|
<a href="https://github.com/CosmosZ-code" title="CosmosZ-code"><img src="https://avatars.githubusercontent.com/u/81398224?v=4" width="50;" alt="CosmosZ-code"/></a>
|
||||||
<a href="https://github.com/lvgj-stack" title="Ko no dio"><img src="https://avatars.githubusercontent.com/u/38449861?v=4" width="50;" alt="Ko no dio"/></a>
|
<a href="https://github.com/liuyanxi975" title="刘颜溪"><img src="https://avatars.githubusercontent.com/u/24417037?v=4" width="50;" alt="刘颜溪"/></a>
|
||||||
<a href="https://github.com/hhhkkk520" title="Kris"><img src="https://avatars.githubusercontent.com/u/52115472?v=4" width="50;" alt="Kris"/></a>
|
<a href="https://github.com/spiritLHLS" title="spiritlhl"><img src="https://avatars.githubusercontent.com/u/103393591?v=4" width="50;" alt="spiritlhl"/></a>
|
||||||
<a href="https://github.com/1ridic" title="1ridic"><img src="https://avatars.githubusercontent.com/u/88495501?v=4" width="50;" alt="1ridic"/></a>
|
<a href="https://github.com/1ridic" title="1ridic"><img src="https://avatars.githubusercontent.com/u/88495501?v=4" width="50;" alt="1ridic"/></a>
|
||||||
|
<a href="https://github.com/hhhkkk520" title="Kris"><img src="https://avatars.githubusercontent.com/u/52115472?v=4" width="50;" alt="Kris"/></a>
|
||||||
|
<a href="https://github.com/lvgj-stack" title="Ko no dio"><img src="https://avatars.githubusercontent.com/u/38449861?v=4" width="50;" alt="Ko no dio"/></a>
|
||||||
|
<a href="https://github.com/uubulb" title="UUBulb"><img src="https://avatars.githubusercontent.com/u/35923940?v=4" width="50;" alt="UUBulb"/></a>
|
||||||
<a href="https://github.com/Mmx233" title="Mmx"><img src="https://avatars.githubusercontent.com/u/36563672?v=4" width="50;" alt="Mmx"/></a>
|
<a href="https://github.com/Mmx233" title="Mmx"><img src="https://avatars.githubusercontent.com/u/36563672?v=4" width="50;" alt="Mmx"/></a>
|
||||||
<a href="https://github.com/rootmelo92118" title="rootmelo92118"><img src="https://avatars.githubusercontent.com/u/32770959?v=4" width="50;" alt="rootmelo92118"/></a>
|
<a href="https://github.com/rootmelo92118" title="rootmelo92118"><img src="https://avatars.githubusercontent.com/u/32770959?v=4" width="50;" alt="rootmelo92118"/></a>
|
||||||
|
<a href="https://github.com/xykt" title="xykt"><img src="https://avatars.githubusercontent.com/u/152045469?v=4" width="50;" alt="xykt"/></a>
|
||||||
<a href="https://github.com/iilemon" title="Sean"><img src="https://avatars.githubusercontent.com/u/33201711?v=4" width="50;" alt="Sean"/></a>
|
<a href="https://github.com/iilemon" title="Sean"><img src="https://avatars.githubusercontent.com/u/33201711?v=4" width="50;" alt="Sean"/></a>
|
||||||
<a href="https://github.com/fscarmen" title="fscarmen"><img src="https://avatars.githubusercontent.com/u/62703343?v=4" width="50;" alt="fscarmen"/></a>
|
<a href="https://github.com/fscarmen" title="fscarmen"><img src="https://avatars.githubusercontent.com/u/62703343?v=4" width="50;" alt="fscarmen"/></a>
|
||||||
<a href="https://github.com/ch8o" title="no-name-now"><img src="https://avatars.githubusercontent.com/u/9103372?v=4" width="50;" alt="no-name-now"/></a>
|
<a href="https://github.com/ch8o" title="no-name-now"><img src="https://avatars.githubusercontent.com/u/9103372?v=4" width="50;" alt="no-name-now"/></a>
|
||||||
@@ -66,36 +64,23 @@ You can change the dashboard language in the settings page (`/setting`) after th
|
|||||||
<a href="https://github.com/DarcJC" title="Darc Z."><img src="https://avatars.githubusercontent.com/u/53445798?v=4" width="50;" alt="Darc Z."/></a>
|
<a href="https://github.com/DarcJC" title="Darc Z."><img src="https://avatars.githubusercontent.com/u/53445798?v=4" width="50;" alt="Darc Z."/></a>
|
||||||
<a href="https://github.com/Creling" title="Creling"><img src="https://avatars.githubusercontent.com/u/43109504?v=4" width="50;" alt="Creling"/></a>
|
<a href="https://github.com/Creling" title="Creling"><img src="https://avatars.githubusercontent.com/u/43109504?v=4" width="50;" alt="Creling"/></a>
|
||||||
<a href="https://github.com/coreff" title="Core F"><img src="https://avatars.githubusercontent.com/u/38347122?v=4" width="50;" alt="Core F"/></a>
|
<a href="https://github.com/coreff" title="Core F"><img src="https://avatars.githubusercontent.com/u/38347122?v=4" width="50;" alt="Core F"/></a>
|
||||||
<a href="https://github.com/nickfox-taterli" title="Tater Li"><img src="https://avatars.githubusercontent.com/u/19658596?v=4" width="50;" alt="Tater Li"/></a>
|
|
||||||
<a href="https://github.com/hmsjy2017" title="Tony"><img src="https://avatars.githubusercontent.com/u/42692274?v=4" width="50;" alt="Tony"/></a>
|
|
||||||
<a href="https://github.com/adminsama" title="adminsama"><img src="https://avatars.githubusercontent.com/u/60880076?v=4" width="50;" alt="adminsama"/></a>
|
|
||||||
<a href="https://github.com/acgpiano" title="Acgpiano"><img src="https://avatars.githubusercontent.com/u/15900800?v=4" width="50;" alt="Acgpiano"/></a>
|
|
||||||
<a href="https://github.com/eya46" title="eya46"><img src="https://avatars.githubusercontent.com/u/61458340?v=4" width="50;" alt="eya46"/></a>
|
|
||||||
<a href="https://github.com/guoyongchang" title="guoyongchang"><img src="https://avatars.githubusercontent.com/u/10484506?v=4" width="50;" alt="guoyongchang"/></a>
|
|
||||||
<a href="https://github.com/hiDandelion" title="hiDandelion"><img src="https://avatars.githubusercontent.com/u/77157418?v=4" width="50;" alt="hiDandelion"/></a>
|
|
||||||
<a href="https://github.com/yuanweize" title="I"><img src="https://avatars.githubusercontent.com/u/30067203?v=4" width="50;" alt="I"/></a>
|
|
||||||
<a href="https://github.com/lvyaoting" title="lvyaoting"><img src="https://avatars.githubusercontent.com/u/166296299?v=4" width="50;" alt="lvyaoting"/></a>
|
|
||||||
<a href="https://github.com/unclezs" title="unclezs"><img src="https://avatars.githubusercontent.com/u/42318775?v=4" width="50;" alt="unclezs"/></a>
|
|
||||||
<a href="https://github.com/ysicing" title="缘生"><img src="https://avatars.githubusercontent.com/u/8605565?v=4" width="50;" alt="缘生"/></a>
|
|
||||||
<a href="https://github.com/zhucaidan" title="zhucaidan"><img src="https://avatars.githubusercontent.com/u/47970938?v=4" width="50;" alt="zhucaidan"/></a>
|
|
||||||
<a href="https://github.com/arkylin" title="凌"><img src="https://avatars.githubusercontent.com/u/35104502?v=4" width="50;" alt="凌"/></a>
|
|
||||||
<a href="https://github.com/colour93" title="玖叁"><img src="https://avatars.githubusercontent.com/u/64313711?v=4" width="50;" alt="玖叁"/></a>
|
<a href="https://github.com/colour93" title="玖叁"><img src="https://avatars.githubusercontent.com/u/64313711?v=4" width="50;" alt="玖叁"/></a>
|
||||||
<a href="https://github.com/IamTaoChen" title="Tao Chen"><img src="https://avatars.githubusercontent.com/u/42793494?v=4" width="50;" alt="Tao Chen"/></a>
|
<a href="https://github.com/arkylin" title="凌"><img src="https://avatars.githubusercontent.com/u/35104502?v=4" width="50;" alt="凌"/></a>
|
||||||
<a href="https://github.com/Septrum101" title="Spetrum"><img src="https://avatars.githubusercontent.com/u/11692994?v=4" width="50;" alt="Spetrum"/></a>
|
<a href="https://github.com/ysicing" title="缘生"><img src="https://avatars.githubusercontent.com/u/8605565?v=4" width="50;" alt="缘生"/></a>
|
||||||
<a href="https://github.com/dreamingsleeping" title="Nanjing Hopefun Network Technology Co. Ltd."><img src="https://avatars.githubusercontent.com/u/13828658?v=4" width="50;" alt="Nanjing Hopefun Network Technology Co. Ltd."/></a>
|
<a href="https://github.com/sunnywangzi" title="wang"><img src="https://avatars.githubusercontent.com/u/88769439?v=4" width="50;" alt="wang"/></a>
|
||||||
<a href="https://github.com/silver-ymz" title="Mingzhuo Yin"><img src="https://avatars.githubusercontent.com/u/78400701?v=4" width="50;" alt="Mingzhuo Yin"/></a>
|
<a href="https://github.com/unclezs" title="unclezs"><img src="https://avatars.githubusercontent.com/u/42318775?v=4" width="50;" alt="unclezs"/></a>
|
||||||
|
<a href="https://github.com/yuanweize" title="I"><img src="https://avatars.githubusercontent.com/u/30067203?v=4" width="50;" alt="I"/></a>
|
||||||
|
<a href="https://github.com/guoyongchang" title="guoyongchang"><img src="https://avatars.githubusercontent.com/u/10484506?v=4" width="50;" alt="guoyongchang"/></a>
|
||||||
|
<a href="https://github.com/acgpiano" title="Acgpiano"><img src="https://avatars.githubusercontent.com/u/15900800?v=4" width="50;" alt="Acgpiano"/></a>
|
||||||
|
<a href="https://github.com/adminsama" title="adminsama"><img src="https://avatars.githubusercontent.com/u/60880076?v=4" width="50;" alt="adminsama"/></a>
|
||||||
|
<a href="https://github.com/hmsjy2017" title="Tony"><img src="https://avatars.githubusercontent.com/u/42692274?v=4" width="50;" alt="Tony"/></a>
|
||||||
|
<a href="https://github.com/nickfox-taterli" title="Tater Li"><img src="https://avatars.githubusercontent.com/u/19658596?v=4" width="50;" alt="Tater Li"/></a>
|
||||||
<a href="https://github.com/MartijnLindeman" title="Martijn Lindeman"><img src="https://avatars.githubusercontent.com/u/78365708?v=4" width="50;" alt="Martijn Lindeman"/></a>
|
<a href="https://github.com/MartijnLindeman" title="Martijn Lindeman"><img src="https://avatars.githubusercontent.com/u/78365708?v=4" width="50;" alt="Martijn Lindeman"/></a>
|
||||||
<a href="https://github.com/xrgzs" title="MadDogOwner"><img src="https://avatars.githubusercontent.com/u/26499123?v=4" width="50;" alt="MadDogOwner"/></a>
|
|
||||||
<a href="https://github.com/funnyzak" title="Leon"><img src="https://avatars.githubusercontent.com/u/2562087?v=4" width="50;" alt="Leon"/></a>
|
|
||||||
<a href="https://github.com/KorenKrita" title="KorenKrita"><img src="https://avatars.githubusercontent.com/u/22239339?v=4" width="50;" alt="KorenKrita"/></a>
|
<a href="https://github.com/KorenKrita" title="KorenKrita"><img src="https://avatars.githubusercontent.com/u/22239339?v=4" width="50;" alt="KorenKrita"/></a>
|
||||||
<a href="https://github.com/techotaku" title="Ian Li"><img src="https://avatars.githubusercontent.com/u/1948179?v=4" width="50;" alt="Ian Li"/></a>
|
<a href="https://github.com/techotaku" title="Ian Li"><img src="https://avatars.githubusercontent.com/u/1948179?v=4" width="50;" alt="Ian Li"/></a>
|
||||||
<a href="https://github.com/GreenTeodoro839" title="GreenTeodoro839"><img src="https://avatars.githubusercontent.com/u/77104800?v=4" width="50;" alt="GreenTeodoro839"/></a>
|
<a href="https://github.com/GreenTeodoro839" title="GreenTeodoro839"><img src="https://avatars.githubusercontent.com/u/77104800?v=4" width="50;" alt="GreenTeodoro839"/></a>
|
||||||
<a href="https://github.com/Es-dese" title="Esdese"><img src="https://avatars.githubusercontent.com/u/71542548?v=4" width="50;" alt="Esdese"/></a>
|
<a href="https://github.com/Es-dese" title="Esdese"><img src="https://avatars.githubusercontent.com/u/71542548?v=4" width="50;" alt="Esdese"/></a>
|
||||||
<a href="https://github.com/wwng2333" title="Crazy"><img src="https://avatars.githubusercontent.com/u/17147265?v=4" width="50;" alt="Crazy"/></a>
|
<a href="https://github.com/wwng2333" title="Crazy"><img src="https://avatars.githubusercontent.com/u/17147265?v=4" width="50;" alt="Crazy"/></a><!--GAMFC_DELIMITER_END-->
|
||||||
<a href="https://github.com/wellcoming" title="Coming"><img src="https://avatars.githubusercontent.com/u/74850890?v=4" width="50;" alt="Coming"/></a><!--GAMFC_DELIMITER_END-->
|
|
||||||
|
|
||||||
## Special Thanks
|
|
||||||
- [IPInfo](https://ipinfo.io/) for providing an accurate GeoIP Database.
|
|
||||||
|
|
||||||
## Star History
|
## Star History
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -20,13 +23,22 @@ import (
|
|||||||
"github.com/naiba/nezha/pkg/utils"
|
"github.com/naiba/nezha/pkg/utils"
|
||||||
"github.com/naiba/nezha/pkg/websocketx"
|
"github.com/naiba/nezha/pkg/websocketx"
|
||||||
"github.com/naiba/nezha/proto"
|
"github.com/naiba/nezha/proto"
|
||||||
"github.com/naiba/nezha/service/rpc"
|
|
||||||
"github.com/naiba/nezha/service/singleton"
|
"github.com/naiba/nezha/service/singleton"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type terminalContext struct {
|
||||||
|
agentConn *websocketx.Conn
|
||||||
|
userConn *websocketx.Conn
|
||||||
|
serverID uint64
|
||||||
|
host string
|
||||||
|
useSSL bool
|
||||||
|
}
|
||||||
|
|
||||||
type commonPage struct {
|
type commonPage struct {
|
||||||
r *gin.Engine
|
r *gin.Engine
|
||||||
requestGroup singleflight.Group
|
terminals map[string]*terminalContext
|
||||||
|
terminalsLock *sync.Mutex
|
||||||
|
requestGroup singleflight.Group
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *commonPage) serve() {
|
func (cp *commonPage) serve() {
|
||||||
@@ -55,6 +67,7 @@ type viewPasswordForm struct {
|
|||||||
func (p *commonPage) issueViewPassword(c *gin.Context) {
|
func (p *commonPage) issueViewPassword(c *gin.Context) {
|
||||||
var vpf viewPasswordForm
|
var vpf viewPasswordForm
|
||||||
err := c.ShouldBind(&vpf)
|
err := c.ShouldBind(&vpf)
|
||||||
|
log.Println("bingo", vpf)
|
||||||
var hash []byte
|
var hash []byte
|
||||||
if err == nil && vpf.Password != singleton.Conf.Site.ViewPassword {
|
if err == nil && vpf.Password != singleton.Conf.Site.ViewPassword {
|
||||||
err = errors.New(singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "WrongAccessPassword"}))
|
err = errors.New(singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "WrongAccessPassword"}))
|
||||||
@@ -99,6 +112,7 @@ func (p *commonPage) service(c *gin.Context) {
|
|||||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ServicesStatus"}),
|
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "ServicesStatus"}),
|
||||||
"Services": res.([]interface{})[0],
|
"Services": res.([]interface{})[0],
|
||||||
"CycleTransferStats": res.([]interface{})[1],
|
"CycleTransferStats": res.([]interface{})[1],
|
||||||
|
"CustomCode": singleton.Conf.Site.CustomCode,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,30 +217,25 @@ func (cp *commonPage) network(c *gin.Context) {
|
|||||||
c.HTML(http.StatusOK, mygin.GetPreferredTheme(c, "/network"), mygin.CommonEnvironment(c, gin.H{
|
c.HTML(http.StatusOK, mygin.GetPreferredTheme(c, "/network"), mygin.CommonEnvironment(c, gin.H{
|
||||||
"Servers": string(serversBytes),
|
"Servers": string(serversBytes),
|
||||||
"MonitorInfos": string(monitorInfos),
|
"MonitorInfos": string(monitorInfos),
|
||||||
|
"CustomCode": singleton.Conf.Site.CustomCode,
|
||||||
"MaxTCPPingValue": singleton.Conf.MaxTCPPingValue,
|
"MaxTCPPingValue": singleton.Conf.MaxTCPPingValue,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *commonPage) getServerStat(c *gin.Context) ([]byte, error) {
|
func (cp *commonPage) getServerStat(c *gin.Context) ([]byte, error) {
|
||||||
_, isMember := c.Get(model.CtxKeyAuthorizedUser)
|
v, err, _ := cp.requestGroup.Do("serverStats", func() (any, error) {
|
||||||
_, isViewPasswordVerfied := c.Get(model.CtxKeyViewPasswordVerified)
|
|
||||||
authorized := isMember || isViewPasswordVerfied
|
|
||||||
v, err, _ := cp.requestGroup.Do(fmt.Sprintf("serverStats::%t", authorized), func() (interface{}, error) {
|
|
||||||
singleton.SortedServerLock.RLock()
|
singleton.SortedServerLock.RLock()
|
||||||
defer singleton.SortedServerLock.RUnlock()
|
defer singleton.SortedServerLock.RUnlock()
|
||||||
|
|
||||||
|
_, isMember := c.Get(model.CtxKeyAuthorizedUser)
|
||||||
|
_, isViewPasswordVerfied := c.Get(model.CtxKeyViewPasswordVerified)
|
||||||
|
|
||||||
var servers []*model.Server
|
var servers []*model.Server
|
||||||
|
|
||||||
if authorized {
|
if isMember || isViewPasswordVerfied {
|
||||||
servers = singleton.SortedServerList
|
servers = singleton.SortedServerList
|
||||||
} else {
|
} else {
|
||||||
filteredServers := make([]*model.Server, len(singleton.SortedServerListForGuest))
|
servers = singleton.SortedServerListForGuest
|
||||||
for i, server := range singleton.SortedServerListForGuest {
|
|
||||||
filteredServer := *server
|
|
||||||
filteredServer.DDNSDomain = "redacted"
|
|
||||||
filteredServers[i] = &filteredServer
|
|
||||||
}
|
|
||||||
servers = filteredServers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.Json.Marshal(Data{
|
return utils.Json.Marshal(Data{
|
||||||
@@ -252,13 +261,14 @@ func (cp *commonPage) home(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.HTML(http.StatusOK, mygin.GetPreferredTheme(c, "/home"), mygin.CommonEnvironment(c, gin.H{
|
c.HTML(http.StatusOK, mygin.GetPreferredTheme(c, "/home"), mygin.CommonEnvironment(c, gin.H{
|
||||||
"Servers": string(stat),
|
"Servers": string(stat),
|
||||||
|
"CustomCode": singleton.Conf.Site.CustomCode,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
var upgrader = websocket.Upgrader{
|
||||||
ReadBufferSize: 10240,
|
ReadBufferSize: 1024,
|
||||||
WriteBufferSize: 10240,
|
WriteBufferSize: 1024,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Data struct {
|
type Data struct {
|
||||||
@@ -266,6 +276,8 @@ type Data struct {
|
|||||||
Servers []*model.Server `json:"servers,omitempty"`
|
Servers []*model.Server `json:"servers,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cloudflareCookiesValidator = regexp.MustCompile("^[A-Za-z0-9-_]+$")
|
||||||
|
|
||||||
func (cp *commonPage) ws(c *gin.Context) {
|
func (cp *commonPage) ws(c *gin.Context) {
|
||||||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -302,8 +314,10 @@ func (cp *commonPage) ws(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cp *commonPage) terminal(c *gin.Context) {
|
func (cp *commonPage) terminal(c *gin.Context) {
|
||||||
streamId := c.Param("id")
|
terminalID := c.Param("id")
|
||||||
if _, err := rpc.NezhaHandlerSingleton.GetStream(streamId); err != nil {
|
cp.terminalsLock.Lock()
|
||||||
|
if terminalID == "" || cp.terminals[terminalID] == nil {
|
||||||
|
cp.terminalsLock.Unlock()
|
||||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||||
Code: http.StatusForbidden,
|
Code: http.StatusForbidden,
|
||||||
Title: "无权访问",
|
Title: "无权访问",
|
||||||
@@ -313,7 +327,104 @@ func (cp *commonPage) terminal(c *gin.Context) {
|
|||||||
}, true)
|
}, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rpc.NezhaHandlerSingleton.CloseStream(streamId)
|
|
||||||
|
terminal := cp.terminals[terminalID]
|
||||||
|
cp.terminalsLock.Unlock()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
// 清理 context
|
||||||
|
cp.terminalsLock.Lock()
|
||||||
|
defer cp.terminalsLock.Unlock()
|
||||||
|
delete(cp.terminals, terminalID)
|
||||||
|
}()
|
||||||
|
|
||||||
|
var isAgent bool
|
||||||
|
|
||||||
|
if _, authorized := c.Get(model.CtxKeyAuthorizedUser); !authorized {
|
||||||
|
singleton.ServerLock.RLock()
|
||||||
|
_, hasID := singleton.SecretToID[c.Request.Header.Get("Secret")]
|
||||||
|
singleton.ServerLock.RUnlock()
|
||||||
|
if !hasID {
|
||||||
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||||
|
Code: http.StatusForbidden,
|
||||||
|
Title: "无权访问",
|
||||||
|
Msg: "用户未登录或非法终端",
|
||||||
|
Link: "/",
|
||||||
|
Btn: "返回首页",
|
||||||
|
}, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if terminal.userConn == nil {
|
||||||
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||||
|
Code: http.StatusForbidden,
|
||||||
|
Title: "无权访问",
|
||||||
|
Msg: "用户不在线",
|
||||||
|
Link: "/",
|
||||||
|
Btn: "返回首页",
|
||||||
|
}, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if terminal.agentConn != nil {
|
||||||
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||||
|
Code: http.StatusInternalServerError,
|
||||||
|
Title: "连接已存在",
|
||||||
|
Msg: "Websocket协议切换失败",
|
||||||
|
Link: "/",
|
||||||
|
Btn: "返回首页",
|
||||||
|
}, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isAgent = true
|
||||||
|
} else {
|
||||||
|
singleton.ServerLock.RLock()
|
||||||
|
server := singleton.ServerList[terminal.serverID]
|
||||||
|
singleton.ServerLock.RUnlock()
|
||||||
|
if server == nil || server.TaskStream == nil {
|
||||||
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||||
|
Code: http.StatusForbidden,
|
||||||
|
Title: "请求失败",
|
||||||
|
Msg: "服务器不存在或处于离线状态",
|
||||||
|
Link: "/server",
|
||||||
|
Btn: "返回重试",
|
||||||
|
}, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cloudflareCookies, _ := c.Cookie("CF_Authorization")
|
||||||
|
// Cloudflare Cookies 合法性验证
|
||||||
|
// 其应该包含.分隔的三组BASE64-URL编码
|
||||||
|
if cloudflareCookies != "" {
|
||||||
|
encodedCookies := strings.Split(cloudflareCookies, ".")
|
||||||
|
if len(encodedCookies) == 3 {
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
if !cloudflareCookiesValidator.MatchString(encodedCookies[i]) {
|
||||||
|
cloudflareCookies = ""
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cloudflareCookies = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terminalData, _ := utils.Json.Marshal(&model.TerminalTask{
|
||||||
|
Host: terminal.host,
|
||||||
|
UseSSL: terminal.useSSL,
|
||||||
|
Session: terminalID,
|
||||||
|
Cookie: cloudflareCookies,
|
||||||
|
})
|
||||||
|
if err := server.TaskStream.Send(&proto.Task{
|
||||||
|
Type: model.TaskTypeTerminal,
|
||||||
|
Data: string(terminalData),
|
||||||
|
}); err != nil {
|
||||||
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||||
|
Code: http.StatusForbidden,
|
||||||
|
Title: "请求失败",
|
||||||
|
Msg: "Agent信令下发失败",
|
||||||
|
Link: "/server",
|
||||||
|
Btn: "返回重试",
|
||||||
|
}, true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wsConn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
wsConn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -329,7 +440,36 @@ func (cp *commonPage) terminal(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer wsConn.Close()
|
defer wsConn.Close()
|
||||||
conn := websocketx.NewConn(wsConn)
|
conn := &websocketx.Conn{Conn: wsConn}
|
||||||
|
|
||||||
|
log.Printf("NEZHA>> terminal connected %t %q", isAgent, c.Request.URL)
|
||||||
|
defer log.Printf("NEZHA>> terminal disconnected %t %q", isAgent, c.Request.URL)
|
||||||
|
|
||||||
|
if isAgent {
|
||||||
|
terminal.agentConn = conn
|
||||||
|
defer func() {
|
||||||
|
// Agent断开链接时断开用户连接
|
||||||
|
if terminal.userConn != nil {
|
||||||
|
terminal.userConn.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
terminal.userConn = conn
|
||||||
|
defer func() {
|
||||||
|
// 用户断开链接时断开 Agent 连接
|
||||||
|
if terminal.agentConn != nil {
|
||||||
|
terminal.agentConn.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
deadlineCh := make(chan interface{})
|
||||||
|
go func() {
|
||||||
|
// 对方连接超时
|
||||||
|
connectDeadline := time.NewTimer(time.Second * 15)
|
||||||
|
<-connectDeadline.C
|
||||||
|
deadlineCh <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// PING 保活
|
// PING 保活
|
||||||
@@ -341,11 +481,58 @@ func (cp *commonPage) terminal(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err = rpc.NezhaHandlerSingleton.UserConnected(streamId, conn); err != nil {
|
dataCh := make(chan []byte)
|
||||||
return
|
errorCh := make(chan error)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
msgType, data, err := conn.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
errorCh <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 将文本消息转换为命令输入
|
||||||
|
if msgType == websocket.TextMessage {
|
||||||
|
data = append([]byte{0}, data...)
|
||||||
|
}
|
||||||
|
dataCh <- data
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var dataBuffer [][]byte
|
||||||
|
var distConn *websocketx.Conn
|
||||||
|
checkDistConn := func() {
|
||||||
|
if distConn == nil {
|
||||||
|
if isAgent {
|
||||||
|
distConn = terminal.userConn
|
||||||
|
} else {
|
||||||
|
distConn = terminal.agentConn
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc.NezhaHandlerSingleton.StartStream(streamId, time.Second*10)
|
for {
|
||||||
|
select {
|
||||||
|
case <-deadlineCh:
|
||||||
|
checkDistConn()
|
||||||
|
if distConn == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case <-errorCh:
|
||||||
|
return
|
||||||
|
case data := <-dataCh:
|
||||||
|
dataBuffer = append(dataBuffer, data)
|
||||||
|
checkDistConn()
|
||||||
|
if distConn != nil {
|
||||||
|
for i := 0; i < len(dataBuffer); i++ {
|
||||||
|
err = distConn.WriteMessage(websocket.BinaryMessage, dataBuffer[i])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataBuffer = dataBuffer[:0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type createTerminalRequest struct {
|
type createTerminalRequest struct {
|
||||||
@@ -377,7 +564,7 @@ func (cp *commonPage) createTerminal(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
streamId, err := uuid.GenerateUUID()
|
id, err := uuid.GenerateUUID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||||
Code: http.StatusInternalServerError,
|
Code: http.StatusInternalServerError,
|
||||||
@@ -391,8 +578,6 @@ func (cp *commonPage) createTerminal(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc.NezhaHandlerSingleton.CreateStream(streamId)
|
|
||||||
|
|
||||||
singleton.ServerLock.RLock()
|
singleton.ServerLock.RLock()
|
||||||
server := singleton.ServerList[createTerminalReq.ID]
|
server := singleton.ServerList[createTerminalReq.ID]
|
||||||
singleton.ServerLock.RUnlock()
|
singleton.ServerLock.RUnlock()
|
||||||
@@ -407,25 +592,17 @@ func (cp *commonPage) createTerminal(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
terminalData, _ := utils.Json.Marshal(&model.TerminalTask{
|
cp.terminalsLock.Lock()
|
||||||
StreamID: streamId,
|
defer cp.terminalsLock.Unlock()
|
||||||
})
|
|
||||||
if err := server.TaskStream.Send(&proto.Task{
|
cp.terminals[id] = &terminalContext{
|
||||||
Type: model.TaskTypeTerminalGRPC,
|
serverID: createTerminalReq.ID,
|
||||||
Data: string(terminalData),
|
host: createTerminalReq.Host,
|
||||||
}); err != nil {
|
useSSL: createTerminalReq.Protocol == "https:",
|
||||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
|
||||||
Code: http.StatusForbidden,
|
|
||||||
Title: "请求失败",
|
|
||||||
Msg: "Agent信令下发失败",
|
|
||||||
Link: "/server",
|
|
||||||
Btn: "返回重试",
|
|
||||||
}, true)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/terminal", mygin.CommonEnvironment(c, gin.H{
|
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/terminal", mygin.CommonEnvironment(c, gin.H{
|
||||||
"SessionID": streamId,
|
"SessionID": id,
|
||||||
"ServerName": server.Name,
|
"ServerName": server.Name,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
@@ -10,54 +9,43 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.cloudfoundry.org/bytefmt"
|
"code.cloudfoundry.org/bytefmt"
|
||||||
"github.com/gin-contrib/pprof"
|
"github.com/gin-contrib/pprof"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/hashicorp/go-uuid"
|
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||||
|
|
||||||
"github.com/naiba/nezha/model"
|
|
||||||
"github.com/naiba/nezha/pkg/mygin"
|
"github.com/naiba/nezha/pkg/mygin"
|
||||||
"github.com/naiba/nezha/pkg/utils"
|
|
||||||
"github.com/naiba/nezha/proto"
|
|
||||||
"github.com/naiba/nezha/resource"
|
"github.com/naiba/nezha/resource"
|
||||||
"github.com/naiba/nezha/service/rpc"
|
|
||||||
"github.com/naiba/nezha/service/singleton"
|
"github.com/naiba/nezha/service/singleton"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ServeWeb(port uint) *http.Server {
|
func ServeWeb(port uint) *http.Server {
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
|
tmpl := template.New("").Funcs(funcMap)
|
||||||
|
var err error
|
||||||
|
tmpl, err = tmpl.ParseFS(resource.TemplateFS, "template/**/*.html")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
tmpl = loadThirdPartyTemplates(tmpl)
|
||||||
|
r.SetHTMLTemplate(tmpl)
|
||||||
if singleton.Conf.Debug {
|
if singleton.Conf.Debug {
|
||||||
gin.SetMode(gin.DebugMode)
|
gin.SetMode(gin.DebugMode)
|
||||||
pprof.Register(r)
|
pprof.Register(r)
|
||||||
}
|
}
|
||||||
r.Use(natGateway)
|
r.Use(mygin.RecordPath)
|
||||||
if os.Getenv("NZ_LOCAL_TEMPLATE") == "true" {
|
staticFs, err := fs.Sub(resource.StaticFS, "static")
|
||||||
r.SetFuncMap(funcMap)
|
if err != nil {
|
||||||
r.Use(mygin.RecordPath)
|
panic(err)
|
||||||
r.Static("/static", "resource/static")
|
|
||||||
r.LoadHTMLGlob("resource/template/**/*.html")
|
|
||||||
} else {
|
|
||||||
tmpl := template.New("").Funcs(funcMap)
|
|
||||||
var err error
|
|
||||||
tmpl, err = tmpl.ParseFS(resource.TemplateFS, "template/**/*.html")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
tmpl = loadThirdPartyTemplates(tmpl)
|
|
||||||
r.SetHTMLTemplate(tmpl)
|
|
||||||
r.Use(mygin.RecordPath)
|
|
||||||
staticFs, err := fs.Sub(resource.StaticFS, "static")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
r.StaticFS("/static", http.FS(staticFs))
|
|
||||||
}
|
}
|
||||||
|
r.StaticFS("/static", http.FS(staticFs))
|
||||||
r.Static("/static-custom", "resource/static/custom")
|
r.Static("/static-custom", "resource/static/custom")
|
||||||
routers(r)
|
routers(r)
|
||||||
|
|
||||||
page404 := func(c *gin.Context) {
|
page404 := func(c *gin.Context) {
|
||||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
||||||
Code: http.StatusNotFound,
|
Code: http.StatusNotFound,
|
||||||
@@ -80,7 +68,7 @@ func ServeWeb(port uint) *http.Server {
|
|||||||
|
|
||||||
func routers(r *gin.Engine) {
|
func routers(r *gin.Engine) {
|
||||||
// 通用页面
|
// 通用页面
|
||||||
cp := commonPage{r: r}
|
cp := commonPage{r: r, terminals: make(map[string]*terminalContext), terminalsLock: new(sync.Mutex)}
|
||||||
cp.serve()
|
cp.serve()
|
||||||
// 游客页面
|
// 游客页面
|
||||||
gp := guestPage{r}
|
gp := guestPage{r}
|
||||||
@@ -251,64 +239,3 @@ var funcMap = template.FuncMap{
|
|||||||
return singleton.StatusCodeToString(singleton.GetStatusCode(val))
|
return singleton.StatusCodeToString(singleton.GetStatusCode(val))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func natGateway(c *gin.Context) {
|
|
||||||
natConfig := singleton.GetNATConfigByDomain(c.Request.Host)
|
|
||||||
if natConfig == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
singleton.ServerLock.RLock()
|
|
||||||
server := singleton.ServerList[natConfig.ServerID]
|
|
||||||
singleton.ServerLock.RUnlock()
|
|
||||||
if server == nil || server.TaskStream == nil {
|
|
||||||
c.Writer.WriteString("server not found or not connected")
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
streamId, err := uuid.GenerateUUID()
|
|
||||||
if err != nil {
|
|
||||||
c.Writer.WriteString(fmt.Sprintf("stream id error: %v", err))
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rpc.NezhaHandlerSingleton.CreateStream(streamId)
|
|
||||||
defer rpc.NezhaHandlerSingleton.CloseStream(streamId)
|
|
||||||
|
|
||||||
taskData, err := json.Marshal(model.TaskNAT{
|
|
||||||
StreamID: streamId,
|
|
||||||
Host: natConfig.Host,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
c.Writer.WriteString(fmt.Sprintf("task data error: %v", err))
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := server.TaskStream.Send(&proto.Task{
|
|
||||||
Type: model.TaskTypeNAT,
|
|
||||||
Data: string(taskData),
|
|
||||||
}); err != nil {
|
|
||||||
c.Writer.WriteString(fmt.Sprintf("send task error: %v", err))
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w, err := utils.NewRequestWrapper(c.Request, c.Writer)
|
|
||||||
if err != nil {
|
|
||||||
c.Writer.WriteString(fmt.Sprintf("request wrapper error: %v", err))
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := rpc.NezhaHandlerSingleton.UserConnected(streamId, w); err != nil {
|
|
||||||
c.Writer.WriteString(fmt.Sprintf("user connected error: %v", err))
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rpc.NezhaHandlerSingleton.StartStream(streamId, time.Second*10)
|
|
||||||
c.Abort()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ func (gp *guestPage) serve() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gp *guestPage) login(c *gin.Context) {
|
func (gp *guestPage) login(c *gin.Context) {
|
||||||
if singleton.Conf.Oauth2.OidcAutoLogin {
|
|
||||||
c.Redirect(http.StatusFound, "/oauth2/login")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
LoginType := "GitHub"
|
LoginType := "GitHub"
|
||||||
RegistrationLink := "https://github.com/join"
|
RegistrationLink := "https://github.com/join"
|
||||||
if singleton.Conf.Oauth2.Type == model.ConfigTypeGitee {
|
if singleton.Conf.Oauth2.Type == model.ConfigTypeGitee {
|
||||||
@@ -53,12 +49,6 @@ func (gp *guestPage) login(c *gin.Context) {
|
|||||||
} else if singleton.Conf.Oauth2.Type == model.ConfigTypeGitea {
|
} else if singleton.Conf.Oauth2.Type == model.ConfigTypeGitea {
|
||||||
LoginType = "Gitea"
|
LoginType = "Gitea"
|
||||||
RegistrationLink = fmt.Sprintf("%s/user/sign_up", singleton.Conf.Oauth2.Endpoint)
|
RegistrationLink = fmt.Sprintf("%s/user/sign_up", singleton.Conf.Oauth2.Endpoint)
|
||||||
} else if singleton.Conf.Oauth2.Type == model.ConfigTypeCloudflare {
|
|
||||||
LoginType = "Cloudflare"
|
|
||||||
RegistrationLink = "https://dash.cloudflare.com/sign-up/teams"
|
|
||||||
} else if singleton.Conf.Oauth2.Type == model.ConfigTypeOidc {
|
|
||||||
LoginType = singleton.Conf.Oauth2.OidcDisplayName
|
|
||||||
RegistrationLink = singleton.Conf.Oauth2.OidcRegisterURL
|
|
||||||
}
|
}
|
||||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/login", mygin.CommonEnvironment(c, gin.H{
|
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/login", mygin.CommonEnvironment(c, gin.H{
|
||||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Login"}),
|
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Login"}),
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -46,7 +45,6 @@ func (ma *memberAPI) serve() {
|
|||||||
mr.POST("/batch-update-server-group", ma.batchUpdateServerGroup)
|
mr.POST("/batch-update-server-group", ma.batchUpdateServerGroup)
|
||||||
mr.POST("/batch-delete-server", ma.batchDeleteServer)
|
mr.POST("/batch-delete-server", ma.batchDeleteServer)
|
||||||
mr.POST("/notification", ma.addOrEditNotification)
|
mr.POST("/notification", ma.addOrEditNotification)
|
||||||
mr.POST("/nat", ma.addOrEditNAT)
|
|
||||||
mr.POST("/alert-rule", ma.addOrEditAlertRule)
|
mr.POST("/alert-rule", ma.addOrEditAlertRule)
|
||||||
mr.POST("/setting", ma.updateSetting)
|
mr.POST("/setting", ma.updateSetting)
|
||||||
mr.DELETE("/:model/:id", ma.delete)
|
mr.DELETE("/:model/:id", ma.delete)
|
||||||
@@ -211,11 +209,6 @@ func (ma *memberAPI) delete(c *gin.Context) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
singleton.OnDeleteNotification(id)
|
singleton.OnDeleteNotification(id)
|
||||||
}
|
}
|
||||||
case "nat":
|
|
||||||
err = singleton.DB.Unscoped().Delete(&model.NAT{}, "id = ?", id).Error
|
|
||||||
if err == nil {
|
|
||||||
singleton.OnNATUpdate()
|
|
||||||
}
|
|
||||||
case "monitor":
|
case "monitor":
|
||||||
err = singleton.DB.Unscoped().Delete(&model.Monitor{}, "id = ?", id).Error
|
err = singleton.DB.Unscoped().Delete(&model.Monitor{}, "id = ?", id).Error
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -308,10 +301,7 @@ type serverForm struct {
|
|||||||
Note string
|
Note string
|
||||||
HideForGuest string
|
HideForGuest string
|
||||||
EnableDDNS string
|
EnableDDNS string
|
||||||
EnableIPv4 string
|
|
||||||
EnableIpv6 string
|
|
||||||
DDNSDomain string
|
DDNSDomain string
|
||||||
DDNSProfile string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ma *memberAPI) addOrEditServer(c *gin.Context) {
|
func (ma *memberAPI) addOrEditServer(c *gin.Context) {
|
||||||
@@ -328,10 +318,7 @@ func (ma *memberAPI) addOrEditServer(c *gin.Context) {
|
|||||||
s.Note = sf.Note
|
s.Note = sf.Note
|
||||||
s.HideForGuest = sf.HideForGuest == "on"
|
s.HideForGuest = sf.HideForGuest == "on"
|
||||||
s.EnableDDNS = sf.EnableDDNS == "on"
|
s.EnableDDNS = sf.EnableDDNS == "on"
|
||||||
s.EnableIPv4 = sf.EnableIPv4 == "on"
|
|
||||||
s.EnableIpv6 = sf.EnableIpv6 == "on"
|
|
||||||
s.DDNSDomain = sf.DDNSDomain
|
s.DDNSDomain = sf.DDNSDomain
|
||||||
s.DDNSProfile = sf.DDNSProfile
|
|
||||||
if s.ID == 0 {
|
if s.ID == 0 {
|
||||||
s.Secret, err = utils.GenerateRandomString(18)
|
s.Secret, err = utils.GenerateRandomString(18)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -385,7 +372,6 @@ func (ma *memberAPI) addOrEditServer(c *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
s.Host = &model.Host{}
|
s.Host = &model.Host{}
|
||||||
s.State = &model.HostState{}
|
s.State = &model.HostState{}
|
||||||
s.TaskCloseLock = new(sync.Mutex)
|
|
||||||
singleton.ServerLock.Lock()
|
singleton.ServerLock.Lock()
|
||||||
singleton.SecretToID[s.Secret] = s.ID
|
singleton.SecretToID[s.Secret] = s.ID
|
||||||
singleton.ServerList[s.ID] = &s
|
singleton.ServerList[s.ID] = &s
|
||||||
@@ -445,23 +431,25 @@ func (ma *memberAPI) addOrEditMonitor(c *gin.Context) {
|
|||||||
if m.NotificationTag == "" {
|
if m.NotificationTag == "" {
|
||||||
m.NotificationTag = "default"
|
m.NotificationTag = "default"
|
||||||
}
|
}
|
||||||
err = utils.Json.Unmarshal([]byte(mf.FailTriggerTasksRaw), &m.FailTriggerTasks)
|
if err == nil {
|
||||||
}
|
err = utils.Json.Unmarshal([]byte(mf.FailTriggerTasksRaw), &m.FailTriggerTasks)
|
||||||
if err == nil {
|
|
||||||
err = utils.Json.Unmarshal([]byte(mf.RecoverTriggerTasksRaw), &m.RecoverTriggerTasks)
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
if m.ID == 0 {
|
|
||||||
err = singleton.DB.Create(&m).Error
|
|
||||||
} else {
|
|
||||||
err = singleton.DB.Save(&m).Error
|
|
||||||
}
|
}
|
||||||
}
|
if err == nil {
|
||||||
if err == nil {
|
err = utils.Json.Unmarshal([]byte(mf.RecoverTriggerTasksRaw), &m.RecoverTriggerTasks)
|
||||||
if m.Cover == 0 {
|
}
|
||||||
err = singleton.DB.Unscoped().Delete(&model.MonitorHistory{}, "monitor_id = ? and server_id in (?)", m.ID, strings.Split(m.SkipServersRaw[1:len(m.SkipServersRaw)-1], ",")).Error
|
if err == nil {
|
||||||
} else {
|
if m.ID == 0 {
|
||||||
err = singleton.DB.Unscoped().Delete(&model.MonitorHistory{}, "monitor_id = ? and server_id not in (?)", m.ID, strings.Split(m.SkipServersRaw[1:len(m.SkipServersRaw)-1], ",")).Error
|
err = singleton.DB.Create(&m).Error
|
||||||
|
} else {
|
||||||
|
err = singleton.DB.Save(&m).Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
if m.Cover == 0 {
|
||||||
|
err = singleton.DB.Unscoped().Delete(&model.MonitorHistory{}, "monitor_id = ? and server_id in (?)", m.ID, strings.Split(m.SkipServersRaw[1:len(m.SkipServersRaw)-1], ",")).Error
|
||||||
|
} else {
|
||||||
|
err = singleton.DB.Unscoped().Delete(&model.MonitorHistory{}, "monitor_id = ? and server_id not in (?)", m.ID, strings.Split(m.SkipServersRaw[1:len(m.SkipServersRaw)-1], ",")).Error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -741,45 +729,6 @@ func (ma *memberAPI) addOrEditNotification(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type natForm struct {
|
|
||||||
ID uint64
|
|
||||||
Name string
|
|
||||||
ServerID uint64
|
|
||||||
Host string
|
|
||||||
Domain string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ma *memberAPI) addOrEditNAT(c *gin.Context) {
|
|
||||||
var nf natForm
|
|
||||||
var n model.NAT
|
|
||||||
err := c.ShouldBindJSON(&nf)
|
|
||||||
if err == nil {
|
|
||||||
n.Name = nf.Name
|
|
||||||
n.ID = nf.ID
|
|
||||||
n.Domain = nf.Domain
|
|
||||||
n.Host = nf.Host
|
|
||||||
n.ServerID = nf.ServerID
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
if n.ID == 0 {
|
|
||||||
err = singleton.DB.Create(&n).Error
|
|
||||||
} else {
|
|
||||||
err = singleton.DB.Save(&n).Error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Response{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
Message: fmt.Sprintf("请求错误:%s", err),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
singleton.OnNATUpdate()
|
|
||||||
c.JSON(http.StatusOK, model.Response{
|
|
||||||
Code: http.StatusOK,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type alertRuleForm struct {
|
type alertRuleForm struct {
|
||||||
ID uint64
|
ID uint64
|
||||||
Name string
|
Name string
|
||||||
@@ -894,11 +843,6 @@ func (ma *memberAPI) logout(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Response{
|
c.JSON(http.StatusOK, model.Response{
|
||||||
Code: http.StatusOK,
|
Code: http.StatusOK,
|
||||||
})
|
})
|
||||||
|
|
||||||
if oidcLogoutUrl := singleton.Conf.Oauth2.OidcLogoutURL; oidcLogoutUrl != "" {
|
|
||||||
// 重定向到 OIDC 退出登录地址。不知道为什么,这里的重定向不生效
|
|
||||||
c.Redirect(http.StatusOK, oidcLogoutUrl)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type settingForm struct {
|
type settingForm struct {
|
||||||
@@ -908,7 +852,6 @@ type settingForm struct {
|
|||||||
Theme string
|
Theme string
|
||||||
DashboardTheme string
|
DashboardTheme string
|
||||||
CustomCode string
|
CustomCode string
|
||||||
CustomCodeDashboard string
|
|
||||||
ViewPassword string
|
ViewPassword string
|
||||||
IgnoredIPNotification string
|
IgnoredIPNotification string
|
||||||
IPChangeNotificationTag string // IP变更提醒的通知组
|
IPChangeNotificationTag string // IP变更提醒的通知组
|
||||||
@@ -974,7 +917,6 @@ func (ma *memberAPI) updateSetting(c *gin.Context) {
|
|||||||
singleton.Conf.Site.Theme = sf.Theme
|
singleton.Conf.Site.Theme = sf.Theme
|
||||||
singleton.Conf.Site.DashboardTheme = sf.DashboardTheme
|
singleton.Conf.Site.DashboardTheme = sf.DashboardTheme
|
||||||
singleton.Conf.Site.CustomCode = sf.CustomCode
|
singleton.Conf.Site.CustomCode = sf.CustomCode
|
||||||
singleton.Conf.Site.CustomCodeDashboard = sf.CustomCodeDashboard
|
|
||||||
singleton.Conf.Site.ViewPassword = sf.ViewPassword
|
singleton.Conf.Site.ViewPassword = sf.ViewPassword
|
||||||
singleton.Conf.Oauth2.Admin = sf.Admin
|
singleton.Conf.Oauth2.Admin = sf.Admin
|
||||||
// 保证NotificationTag不为空
|
// 保证NotificationTag不为空
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ func (mp *memberPage) serve() {
|
|||||||
mr.GET("/monitor", mp.monitor)
|
mr.GET("/monitor", mp.monitor)
|
||||||
mr.GET("/cron", mp.cron)
|
mr.GET("/cron", mp.cron)
|
||||||
mr.GET("/notification", mp.notification)
|
mr.GET("/notification", mp.notification)
|
||||||
mr.GET("/nat", mp.nat)
|
|
||||||
mr.GET("/setting", mp.setting)
|
mr.GET("/setting", mp.setting)
|
||||||
mr.GET("/api", mp.api)
|
mr.GET("/api", mp.api)
|
||||||
}
|
}
|
||||||
@@ -78,15 +77,6 @@ func (mp *memberPage) notification(c *gin.Context) {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mp *memberPage) nat(c *gin.Context) {
|
|
||||||
var data []model.NAT
|
|
||||||
singleton.DB.Find(&data)
|
|
||||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/nat", mygin.CommonEnvironment(c, gin.H{
|
|
||||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "NAT"}),
|
|
||||||
"NAT": data,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mp *memberPage) setting(c *gin.Context) {
|
func (mp *memberPage) setting(c *gin.Context) {
|
||||||
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/setting", mygin.CommonEnvironment(c, gin.H{
|
c.HTML(http.StatusOK, "dashboard-"+singleton.Conf.Site.DashboardTheme+"/setting", mygin.CommonEnvironment(c, gin.H{
|
||||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Settings"}),
|
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "Settings"}),
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -10,27 +9,23 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/coreos/go-oidc/v3/oidc"
|
|
||||||
"github.com/naiba/nezha/pkg/oidc/cloudflare"
|
|
||||||
myOidc "github.com/naiba/nezha/pkg/oidc/general"
|
|
||||||
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
GitHubAPI "github.com/google/go-github/v47/github"
|
GitHubAPI "github.com/google/go-github/v47/github"
|
||||||
"github.com/naiba/nezha/model"
|
|
||||||
"github.com/naiba/nezha/pkg/mygin"
|
|
||||||
"github.com/naiba/nezha/pkg/utils"
|
|
||||||
"github.com/naiba/nezha/service/singleton"
|
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
GitHubOauth2 "golang.org/x/oauth2/github"
|
GitHubOauth2 "golang.org/x/oauth2/github"
|
||||||
GitlabOauth2 "golang.org/x/oauth2/gitlab"
|
GitlabOauth2 "golang.org/x/oauth2/gitlab"
|
||||||
|
|
||||||
|
"github.com/naiba/nezha/model"
|
||||||
|
"github.com/naiba/nezha/pkg/mygin"
|
||||||
|
"github.com/naiba/nezha/pkg/utils"
|
||||||
|
"github.com/naiba/nezha/service/singleton"
|
||||||
)
|
)
|
||||||
|
|
||||||
type oauth2controller struct {
|
type oauth2controller struct {
|
||||||
r gin.IRoutes
|
r gin.IRoutes
|
||||||
oidcProvider *oidc.Provider
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (oa *oauth2controller) serve() {
|
func (oa *oauth2controller) serve() {
|
||||||
@@ -79,38 +74,6 @@ func (oa *oauth2controller) getCommonOauth2Config(c *gin.Context) *oauth2.Config
|
|||||||
},
|
},
|
||||||
RedirectURL: oa.getRedirectURL(c),
|
RedirectURL: oa.getRedirectURL(c),
|
||||||
}
|
}
|
||||||
} else if singleton.Conf.Oauth2.Type == model.ConfigTypeCloudflare {
|
|
||||||
return &oauth2.Config{
|
|
||||||
ClientID: singleton.Conf.Oauth2.ClientID,
|
|
||||||
ClientSecret: singleton.Conf.Oauth2.ClientSecret,
|
|
||||||
Scopes: []string{"openid", "email", "profile", "groups"},
|
|
||||||
Endpoint: oauth2.Endpoint{
|
|
||||||
AuthURL: fmt.Sprintf("%s/cdn-cgi/access/sso/oidc/%s/authorization", singleton.Conf.Oauth2.Endpoint, singleton.Conf.Oauth2.ClientID),
|
|
||||||
TokenURL: fmt.Sprintf("%s/cdn-cgi/access/sso/oidc/%s/token", singleton.Conf.Oauth2.Endpoint, singleton.Conf.Oauth2.ClientID),
|
|
||||||
},
|
|
||||||
RedirectURL: oa.getRedirectURL(c),
|
|
||||||
}
|
|
||||||
} else if singleton.Conf.Oauth2.Type == model.ConfigTypeOidc {
|
|
||||||
var err error
|
|
||||||
oa.oidcProvider, err = oidc.NewProvider(c.Request.Context(), singleton.Conf.Oauth2.OidcIssuer)
|
|
||||||
if err != nil {
|
|
||||||
mygin.ShowErrorPage(c, mygin.ErrInfo{
|
|
||||||
Code: http.StatusBadRequest,
|
|
||||||
Title: fmt.Sprintf("Cannot get OIDC infomaion from issuer from %s", singleton.Conf.Oauth2.OidcIssuer),
|
|
||||||
Msg: err.Error(),
|
|
||||||
}, true)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
scopes := strings.Split(singleton.Conf.Oauth2.OidcScopes, ",")
|
|
||||||
scopes = append(scopes, oidc.ScopeOpenID)
|
|
||||||
uniqueScopes := removeDuplicates(scopes)
|
|
||||||
return &oauth2.Config{
|
|
||||||
ClientID: singleton.Conf.Oauth2.ClientID,
|
|
||||||
ClientSecret: singleton.Conf.Oauth2.ClientSecret,
|
|
||||||
Scopes: uniqueScopes,
|
|
||||||
Endpoint: oa.oidcProvider.Endpoint(),
|
|
||||||
RedirectURL: oa.getRedirectURL(c),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return &oauth2.Config{
|
return &oauth2.Config{
|
||||||
ClientID: singleton.Conf.Oauth2.ClientID,
|
ClientID: singleton.Conf.Oauth2.ClientID,
|
||||||
@@ -123,8 +86,7 @@ func (oa *oauth2controller) getCommonOauth2Config(c *gin.Context) *oauth2.Config
|
|||||||
|
|
||||||
func (oa *oauth2controller) getRedirectURL(c *gin.Context) string {
|
func (oa *oauth2controller) getRedirectURL(c *gin.Context) string {
|
||||||
scheme := "http://"
|
scheme := "http://"
|
||||||
referer := c.Request.Referer()
|
if strings.HasPrefix(c.Request.Referer(), "https://") {
|
||||||
if forwardedProto := c.Request.Header.Get("X-Forwarded-Proto"); forwardedProto == "https" || strings.HasPrefix(referer, "https://") {
|
|
||||||
scheme = "https://"
|
scheme = "https://"
|
||||||
}
|
}
|
||||||
return scheme + c.Request.Host + "/oauth2/callback"
|
return scheme + c.Request.Host + "/oauth2/callback"
|
||||||
@@ -193,28 +155,6 @@ func (oa *oauth2controller) callback(c *gin.Context) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
user = model.NewUserFromGitea(u)
|
user = model.NewUserFromGitea(u)
|
||||||
}
|
}
|
||||||
} else if singleton.Conf.Oauth2.Type == model.ConfigTypeCloudflare {
|
|
||||||
client := oauth2Config.Client(context.Background(), otk)
|
|
||||||
resp, err := client.Get(fmt.Sprintf("%s/cdn-cgi/access/sso/oidc/%s/userinfo", singleton.Conf.Oauth2.Endpoint, singleton.Conf.Oauth2.ClientID))
|
|
||||||
if err == nil {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
var cloudflareUserInfo *cloudflare.UserInfo
|
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&cloudflareUserInfo); err == nil {
|
|
||||||
user = cloudflareUserInfo.MapToNezhaUser()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if singleton.Conf.Oauth2.Type == model.ConfigTypeOidc {
|
|
||||||
userInfo, err := oa.oidcProvider.UserInfo(c.Request.Context(), oauth2.StaticTokenSource(otk))
|
|
||||||
if err == nil {
|
|
||||||
loginClaim := singleton.Conf.Oauth2.OidcLoginClaim
|
|
||||||
groupClain := singleton.Conf.Oauth2.OidcGroupClaim
|
|
||||||
adminGroups := strings.Split(singleton.Conf.Oauth2.AdminGroups, ",")
|
|
||||||
autoCreate := singleton.Conf.Oauth2.OidcAutoCreate
|
|
||||||
var oidceUserInfo *myOidc.UserInfo
|
|
||||||
if err := userInfo.Claims(&oidceUserInfo); err == nil {
|
|
||||||
user = oidceUserInfo.MapToNezhaUser(loginClaim, groupClain, adminGroups, autoCreate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
var client *GitHubAPI.Client
|
var client *GitHubAPI.Client
|
||||||
oc := oauth2Config.Client(ctx, otk)
|
oc := oauth2Config.Client(ctx, otk)
|
||||||
@@ -228,12 +168,15 @@ func (oa *oauth2controller) callback(c *gin.Context) {
|
|||||||
client = GitHubAPI.NewClient(oc)
|
client = GitHubAPI.NewClient(oc)
|
||||||
}
|
}
|
||||||
var gu *GitHubAPI.User
|
var gu *GitHubAPI.User
|
||||||
gu, _, err = client.Users.Get(ctx, "")
|
if err == nil {
|
||||||
|
gu, _, err = client.Users.Get(ctx, "")
|
||||||
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
user = model.NewUserFromGitHub(gu)
|
user = model.NewUserFromGitHub(gu)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil && user.Login == "" {
|
if err == nil && user.Login == "" {
|
||||||
err = errors.New("获取用户信息失败")
|
err = errors.New("获取用户信息失败")
|
||||||
}
|
}
|
||||||
@@ -247,15 +190,10 @@ func (oa *oauth2controller) callback(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var isAdmin bool
|
var isAdmin bool
|
||||||
|
for _, admin := range strings.Split(singleton.Conf.Oauth2.Admin, ",") {
|
||||||
if user.SuperAdmin {
|
if admin != "" && strings.EqualFold(user.Login, admin) {
|
||||||
isAdmin = true
|
isAdmin = true
|
||||||
} else {
|
break
|
||||||
for _, admin := range strings.Split(singleton.Conf.Oauth2.Admin, ",") {
|
|
||||||
if admin != "" && strings.EqualFold(user.Login, admin) {
|
|
||||||
isAdmin = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !isAdmin {
|
if !isAdmin {
|
||||||
@@ -282,16 +220,3 @@ func (oa *oauth2controller) callback(c *gin.Context) {
|
|||||||
"URL": "/",
|
"URL": "/",
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeDuplicates(elements []string) []string {
|
|
||||||
encountered := map[string]bool{}
|
|
||||||
result := []string{}
|
|
||||||
|
|
||||||
for _, v := range elements {
|
|
||||||
if !encountered[v] {
|
|
||||||
encountered[v] = true
|
|
||||||
result = append(result, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,12 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/naiba/nezha/cmd/dashboard/controller"
|
"github.com/naiba/nezha/cmd/dashboard/controller"
|
||||||
"github.com/naiba/nezha/cmd/dashboard/rpc"
|
"github.com/naiba/nezha/cmd/dashboard/rpc"
|
||||||
"github.com/naiba/nezha/model"
|
"github.com/naiba/nezha/model"
|
||||||
"github.com/naiba/nezha/proto"
|
|
||||||
"github.com/naiba/nezha/service/singleton"
|
"github.com/naiba/nezha/service/singleton"
|
||||||
"github.com/ory/graceful"
|
"github.com/ory/graceful"
|
||||||
flag "github.com/spf13/pflag"
|
flag "github.com/spf13/pflag"
|
||||||
@@ -61,7 +59,6 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 使用 cmux 在同一端口服务 HTTP 和 gRPC
|
|
||||||
singleton.CleanMonitorHistory()
|
singleton.CleanMonitorHistory()
|
||||||
go rpc.ServeRPC(singleton.Conf.GRPCPort)
|
go rpc.ServeRPC(singleton.Conf.GRPCPort)
|
||||||
serviceSentinelDispatchBus := make(chan model.Monitor) // 用于传递服务监控任务信息的channel
|
serviceSentinelDispatchBus := make(chan model.Monitor) // 用于传递服务监控任务信息的channel
|
||||||
@@ -70,7 +67,6 @@ func main() {
|
|||||||
go singleton.AlertSentinelStart()
|
go singleton.AlertSentinelStart()
|
||||||
singleton.NewServiceSentinel(serviceSentinelDispatchBus)
|
singleton.NewServiceSentinel(serviceSentinelDispatchBus)
|
||||||
srv := controller.ServeWeb(singleton.Conf.HTTPPort)
|
srv := controller.ServeWeb(singleton.Conf.HTTPPort)
|
||||||
go dispatchReportInfoTask()
|
|
||||||
if err := graceful.Graceful(func() error {
|
if err := graceful.Graceful(func() error {
|
||||||
return srv.ListenAndServe()
|
return srv.ListenAndServe()
|
||||||
}, func(c context.Context) error {
|
}, func(c context.Context) error {
|
||||||
@@ -83,18 +79,3 @@ func main() {
|
|||||||
log.Printf("NEZHA>> ERROR: %v", err)
|
log.Printf("NEZHA>> ERROR: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func dispatchReportInfoTask() {
|
|
||||||
time.Sleep(time.Second * 15)
|
|
||||||
singleton.ServerLock.RLock()
|
|
||||||
defer singleton.ServerLock.RUnlock()
|
|
||||||
for _, server := range singleton.ServerList {
|
|
||||||
if server == nil || server.TaskStream == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
server.TaskStream.Send(&proto.Task{
|
|
||||||
Type: model.TaskTypeReportHostInfo,
|
|
||||||
Data: "",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ import (
|
|||||||
|
|
||||||
func ServeRPC(port uint) {
|
func ServeRPC(port uint) {
|
||||||
server := grpc.NewServer()
|
server := grpc.NewServer()
|
||||||
rpcService.NezhaHandlerSingleton = rpcService.NewNezhaHandler()
|
pb.RegisterNezhaServiceServer(server, &rpcService.NezhaHandler{
|
||||||
pb.RegisterNezhaServiceServer(server, rpcService.NezhaHandlerSingleton)
|
Auth: &rpcService.AuthHandler{},
|
||||||
|
})
|
||||||
listen, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
listen, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ module github.com/naiba/nezha
|
|||||||
|
|
||||||
go 1.21
|
go 1.21
|
||||||
|
|
||||||
|
toolchain go1.21.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.cloudfoundry.org/bytefmt v0.0.0-20240425163905-bcdc1ad063ea
|
code.cloudfoundry.org/bytefmt v0.0.0-20240322144145-4816192cb114
|
||||||
code.gitea.io/sdk/gitea v0.18.0
|
code.gitea.io/sdk/gitea v0.17.1
|
||||||
github.com/BurntSushi/toml v1.3.2
|
github.com/BurntSushi/toml v1.3.2
|
||||||
github.com/coreos/go-oidc/v3 v3.11.0
|
|
||||||
github.com/gin-contrib/pprof v1.4.0
|
github.com/gin-contrib/pprof v1.4.0
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/google/go-github/v47 v47.1.0
|
github.com/google/go-github/v47 v47.1.0
|
||||||
@@ -16,21 +17,20 @@ require (
|
|||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.4.0
|
github.com/nicksnyder/go-i18n/v2 v2.4.0
|
||||||
github.com/ory/graceful v0.1.3
|
github.com/ory/graceful v0.1.3
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
|
github.com/samber/lo v1.39.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/viper v1.18.2
|
github.com/spf13/viper v1.18.2
|
||||||
github.com/xanzy/go-gitlab v0.103.0
|
github.com/xanzy/go-gitlab v0.100.0
|
||||||
golang.org/x/crypto v0.25.0
|
golang.org/x/crypto v0.21.0
|
||||||
golang.org/x/net v0.27.0
|
golang.org/x/oauth2 v0.18.0
|
||||||
golang.org/x/oauth2 v0.21.0
|
golang.org/x/sync v0.6.0
|
||||||
golang.org/x/sync v0.7.0
|
golang.org/x/text v0.14.0
|
||||||
golang.org/x/text v0.16.0
|
google.golang.org/grpc v1.62.1
|
||||||
google.golang.org/grpc v1.63.0
|
google.golang.org/protobuf v1.33.0
|
||||||
google.golang.org/protobuf v1.34.2
|
|
||||||
gorm.io/driver/sqlite v1.5.5
|
gorm.io/driver/sqlite v1.5.5
|
||||||
gorm.io/gorm v1.25.10
|
gorm.io/gorm v1.25.8
|
||||||
sigs.k8s.io/yaml v1.4.0
|
sigs.k8s.io/yaml v1.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -42,14 +42,14 @@ require (
|
|||||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-fed/httpsig v1.1.0 // indirect
|
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
|
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.2 // indirect
|
||||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
@@ -57,7 +57,7 @@ require (
|
|||||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
@@ -76,9 +76,11 @@ require (
|
|||||||
go.uber.org/multierr v1.9.0 // indirect
|
go.uber.org/multierr v1.9.0 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
golang.org/x/sys v0.22.0 // indirect
|
golang.org/x/net v0.22.0 // indirect
|
||||||
|
golang.org/x/sys v0.18.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
google.golang.org/appengine v1.6.8 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
code.cloudfoundry.org/bytefmt v0.0.0-20240425163905-bcdc1ad063ea h1:1tgMNDgo8PjpsHhlaxdibj28C0WyLeOW2SPJ7GGdc9A=
|
code.cloudfoundry.org/bytefmt v0.0.0-20240322144145-4816192cb114 h1:7KJsK0gPah7XfO46ARJA2TUXHZaJEnPI80mzxQLre68=
|
||||||
code.cloudfoundry.org/bytefmt v0.0.0-20240425163905-bcdc1ad063ea/go.mod h1:3+xXJBOD8PsGHDqHedtCLalbaVJ+yi1OW+mXx9IcNxI=
|
code.cloudfoundry.org/bytefmt v0.0.0-20240322144145-4816192cb114/go.mod h1:TNAH6xe5WOszc47+zM7NnpaJWBR8oYt12BUf4WLIZ98=
|
||||||
code.gitea.io/sdk/gitea v0.18.0 h1:+zZrwVmujIrgobt6wVBWCqITz6bn1aBjnCUHmpZrerI=
|
code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8=
|
||||||
code.gitea.io/sdk/gitea v0.18.0/go.mod h1:IG9xZJoltDNeDSW0qiF2Vqx5orMWa7OhVWrjvrd5NpI=
|
code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM=
|
||||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
@@ -10,8 +10,6 @@ github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZX
|
|||||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||||
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
|
|
||||||
github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
|
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -19,8 +17,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
|||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
@@ -36,8 +34,6 @@ github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
|||||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||||
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||||
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
|
|
||||||
github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
|
||||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
@@ -58,6 +54,9 @@ github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGF
|
|||||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
@@ -68,16 +67,17 @@ github.com/google/go-github/v47 v47.1.0/go.mod h1:VPZBXNbFSJGjyjFRUKo9vZGawTajnW
|
|||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
|
github.com/google/pprof v0.0.0-20240320155624-b11c3daa6f07 h1:57oOH2Mu5Nw16KnZAVLdlUjmPH/TSYCKTJgG0OVfX0Y=
|
||||||
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
github.com/google/pprof v0.0.0-20240320155624-b11c3daa6f07/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||||
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
|
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||||
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
|
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
|
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
|
||||||
|
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||||
@@ -112,8 +112,8 @@ github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3v
|
|||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
|
||||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
@@ -125,14 +125,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
|||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
|
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
|
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
|
||||||
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
|
github.com/onsi/ginkgo/v2 v2.17.0 h1:kdnunFXpBjbzN56hcJHrXZ8M+LOkenKA7NnBzTNigTI=
|
||||||
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
github.com/onsi/ginkgo/v2 v2.17.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||||
github.com/onsi/gomega v1.33.0 h1:snPCflnZrpMsy94p4lXVEkHo12lmPnc3vY5XBbreexE=
|
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
|
||||||
github.com/onsi/gomega v1.33.0/go.mod h1:+925n5YtiFsLzzafLUHzVMBpvvRAzrydIBiSIxjX3wY=
|
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
|
||||||
github.com/ory/graceful v0.1.3 h1:FaeXcHZh168WzS+bqruqWEw/HgXWLdNv2nJ+fbhxbhc=
|
github.com/ory/graceful v0.1.3 h1:FaeXcHZh168WzS+bqruqWEw/HgXWLdNv2nJ+fbhxbhc=
|
||||||
github.com/ory/graceful v0.1.3/go.mod h1:4zFz687IAF7oNHHiB586U4iL+/4aV09o/PYLE34t2bA=
|
github.com/ory/graceful v0.1.3/go.mod h1:4zFz687IAF7oNHHiB586U4iL+/4aV09o/PYLE34t2bA=
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE=
|
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8=
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||||
@@ -154,6 +152,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
|
|||||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||||
|
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
|
||||||
|
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||||
@@ -167,6 +167,7 @@ github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMV
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
@@ -175,9 +176,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
@@ -186,8 +186,9 @@ github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6
|
|||||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/xanzy/go-gitlab v0.103.0 h1:J9pTQoq0GsEFqzd6srCM1QfdfKAxSNz6mT6ntrpNF2w=
|
github.com/xanzy/go-gitlab v0.100.0 h1:jaOtYj5nWI19+9oVVmgy233pax2oYqucwetogYU46ks=
|
||||||
github.com/xanzy/go-gitlab v0.103.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
|
github.com/xanzy/go-gitlab v0.100.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||||
@@ -199,50 +200,81 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
|
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||||
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
|
||||||
|
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
|
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
|
||||||
|
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||||
|
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
|
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
|
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||||
google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
|
||||||
google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||||
|
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||||
|
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
@@ -259,8 +291,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E=
|
gorm.io/driver/sqlite v1.5.5 h1:7MDMtUZhV065SilG62E0MquljeArQZNfJnjd9i9gx3E=
|
||||||
gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE=
|
gorm.io/driver/sqlite v1.5.5/go.mod h1:6NgQ7sQWAIFsPrJJl1lSNSu2TABh0ZZ/zm5fosATavE=
|
||||||
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
|
gorm.io/gorm v1.25.8 h1:WAGEZ/aEcznN4D03laj8DKnehe1e9gYQAjW8xyPRdeo=
|
||||||
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
gorm.io/gorm v1.25.8/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||||
|
|||||||
+25
-55
@@ -22,7 +22,7 @@ var Themes = map[string]string{
|
|||||||
"mdui": "Neko Mdui",
|
"mdui": "Neko Mdui",
|
||||||
"hotaru": "Hotaru",
|
"hotaru": "Hotaru",
|
||||||
"angel-kanade": "AngelKanade",
|
"angel-kanade": "AngelKanade",
|
||||||
"server-status": "ServerStatus",
|
"server-status": "SeverStatus",
|
||||||
"custom": "Custom(local)",
|
"custom": "Custom(local)",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,13 +32,11 @@ var DashboardThemes = map[string]string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ConfigTypeGitHub = "github"
|
ConfigTypeGitHub = "github"
|
||||||
ConfigTypeGitee = "gitee"
|
ConfigTypeGitee = "gitee"
|
||||||
ConfigTypeGitlab = "gitlab"
|
ConfigTypeGitlab = "gitlab"
|
||||||
ConfigTypeJihulab = "jihulab"
|
ConfigTypeJihulab = "jihulab"
|
||||||
ConfigTypeGitea = "gitea"
|
ConfigTypeGitea = "gitea"
|
||||||
ConfigTypeCloudflare = "cloudflare"
|
|
||||||
ConfigTypeOidc = "oidc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -72,7 +70,7 @@ func (c *AgentConfig) Save() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return os.WriteFile(c.v.ConfigFileUsed(), data, 0600)
|
return os.WriteFile(c.v.ConfigFileUsed(), data, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config 站点配置
|
// Config 站点配置
|
||||||
@@ -80,30 +78,19 @@ type Config struct {
|
|||||||
Debug bool // debug模式开关
|
Debug bool // debug模式开关
|
||||||
Language string // 系统语言,默认 zh-CN
|
Language string // 系统语言,默认 zh-CN
|
||||||
Site struct {
|
Site struct {
|
||||||
Brand string // 站点名称
|
Brand string // 站点名称
|
||||||
CookieName string // 浏览器 Cookie 名称
|
CookieName string // 浏览器 Cookie 名称
|
||||||
Theme string
|
Theme string
|
||||||
DashboardTheme string
|
DashboardTheme string
|
||||||
CustomCode string
|
CustomCode string
|
||||||
CustomCodeDashboard string
|
ViewPassword string // 前台查看密码
|
||||||
ViewPassword string // 前台查看密码
|
|
||||||
}
|
}
|
||||||
Oauth2 struct {
|
Oauth2 struct {
|
||||||
Type string
|
Type string
|
||||||
Admin string // 管理员用户名列表
|
Admin string // 管理员用户名列表
|
||||||
AdminGroups string // 管理员用户组列表
|
ClientID string
|
||||||
ClientID string
|
ClientSecret string
|
||||||
ClientSecret string
|
Endpoint string
|
||||||
Endpoint string
|
|
||||||
OidcDisplayName string // for OIDC Display Name
|
|
||||||
OidcIssuer string // for OIDC Issuer
|
|
||||||
OidcLogoutURL string // for OIDC Logout URL
|
|
||||||
OidcRegisterURL string // for OIDC Register URL
|
|
||||||
OidcLoginClaim string // for OIDC Claim
|
|
||||||
OidcGroupClaim string // for OIDC Group Claim
|
|
||||||
OidcScopes string // for OIDC Scopes
|
|
||||||
OidcAutoCreate bool // for OIDC Auto Create
|
|
||||||
OidcAutoLogin bool // for OIDC Auto Login
|
|
||||||
}
|
}
|
||||||
HTTPPort uint
|
HTTPPort uint
|
||||||
GRPCPort uint
|
GRPCPort uint
|
||||||
@@ -138,20 +125,9 @@ type Config struct {
|
|||||||
WebhookRequestBody string
|
WebhookRequestBody string
|
||||||
WebhookHeaders string
|
WebhookHeaders string
|
||||||
MaxRetries uint32
|
MaxRetries uint32
|
||||||
Profiles map[string]DDNSProfile
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DDNSProfile struct {
|
|
||||||
Provider string
|
|
||||||
AccessID string
|
|
||||||
AccessSecret string
|
|
||||||
WebhookURL string
|
|
||||||
WebhookMethod string
|
|
||||||
WebhookRequestBody string
|
|
||||||
WebhookHeaders string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read 读取配置文件并应用
|
// Read 读取配置文件并应用
|
||||||
func (c *Config) Read(path string) error {
|
func (c *Config) Read(path string) error {
|
||||||
c.v = viper.New()
|
c.v = viper.New()
|
||||||
@@ -190,21 +166,15 @@ func (c *Config) Read(path string) error {
|
|||||||
if c.AvgPingCount == 0 {
|
if c.AvgPingCount == 0 {
|
||||||
c.AvgPingCount = 2
|
c.AvgPingCount = 2
|
||||||
}
|
}
|
||||||
|
if c.DDNS.Provider == "" {
|
||||||
|
c.DDNS.Provider = "webhook"
|
||||||
|
}
|
||||||
|
if c.DDNS.WebhookMethod == "" {
|
||||||
|
c.DDNS.WebhookMethod = "POST"
|
||||||
|
}
|
||||||
if c.DDNS.MaxRetries == 0 {
|
if c.DDNS.MaxRetries == 0 {
|
||||||
c.DDNS.MaxRetries = 3
|
c.DDNS.MaxRetries = 3
|
||||||
}
|
}
|
||||||
if c.Oauth2.OidcScopes == "" {
|
|
||||||
c.Oauth2.OidcScopes = "openid,profile,email"
|
|
||||||
}
|
|
||||||
if c.Oauth2.OidcLoginClaim == "" {
|
|
||||||
c.Oauth2.OidcLoginClaim = "sub"
|
|
||||||
}
|
|
||||||
if c.Oauth2.OidcDisplayName == "" {
|
|
||||||
c.Oauth2.OidcDisplayName = "OIDC"
|
|
||||||
}
|
|
||||||
if c.Oauth2.OidcGroupClaim == "" {
|
|
||||||
c.Oauth2.OidcGroupClaim = "groups"
|
|
||||||
}
|
|
||||||
|
|
||||||
c.updateIgnoredIPNotificationID()
|
c.updateIgnoredIPNotificationID()
|
||||||
return nil
|
return nil
|
||||||
@@ -229,5 +199,5 @@ func (c *Config) Save() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return os.WriteFile(c.v.ConfigFileUsed(), data, 0600)
|
return os.WriteFile(c.v.ConfigFileUsed(), data, os.ModePerm)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,6 @@ const (
|
|||||||
MTReportHostState
|
MTReportHostState
|
||||||
)
|
)
|
||||||
|
|
||||||
type SensorTemperature struct {
|
|
||||||
Name string
|
|
||||||
Temperature float64
|
|
||||||
}
|
|
||||||
|
|
||||||
type HostState struct {
|
type HostState struct {
|
||||||
CPU float64
|
CPU float64
|
||||||
MemUsed uint64
|
MemUsed uint64
|
||||||
@@ -31,19 +26,9 @@ type HostState struct {
|
|||||||
TcpConnCount uint64
|
TcpConnCount uint64
|
||||||
UdpConnCount uint64
|
UdpConnCount uint64
|
||||||
ProcessCount uint64
|
ProcessCount uint64
|
||||||
Temperatures []SensorTemperature
|
|
||||||
GPU float64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HostState) PB() *pb.State {
|
func (s *HostState) PB() *pb.State {
|
||||||
var ts []*pb.State_SensorTemperature
|
|
||||||
for _, t := range s.Temperatures {
|
|
||||||
ts = append(ts, &pb.State_SensorTemperature{
|
|
||||||
Name: t.Name,
|
|
||||||
Temperature: t.Temperature,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return &pb.State{
|
return &pb.State{
|
||||||
Cpu: s.CPU,
|
Cpu: s.CPU,
|
||||||
MemUsed: s.MemUsed,
|
MemUsed: s.MemUsed,
|
||||||
@@ -60,20 +45,10 @@ func (s *HostState) PB() *pb.State {
|
|||||||
TcpConnCount: s.TcpConnCount,
|
TcpConnCount: s.TcpConnCount,
|
||||||
UdpConnCount: s.UdpConnCount,
|
UdpConnCount: s.UdpConnCount,
|
||||||
ProcessCount: s.ProcessCount,
|
ProcessCount: s.ProcessCount,
|
||||||
Temperatures: ts,
|
|
||||||
Gpu: s.GPU,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func PB2State(s *pb.State) HostState {
|
func PB2State(s *pb.State) HostState {
|
||||||
var ts []SensorTemperature
|
|
||||||
for _, t := range s.GetTemperatures() {
|
|
||||||
ts = append(ts, SensorTemperature{
|
|
||||||
Name: t.GetName(),
|
|
||||||
Temperature: t.GetTemperature(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return HostState{
|
return HostState{
|
||||||
CPU: s.GetCpu(),
|
CPU: s.GetCpu(),
|
||||||
MemUsed: s.GetMemUsed(),
|
MemUsed: s.GetMemUsed(),
|
||||||
@@ -90,8 +65,6 @@ func PB2State(s *pb.State) HostState {
|
|||||||
TcpConnCount: s.GetTcpConnCount(),
|
TcpConnCount: s.GetTcpConnCount(),
|
||||||
UdpConnCount: s.GetUdpConnCount(),
|
UdpConnCount: s.GetUdpConnCount(),
|
||||||
ProcessCount: s.GetProcessCount(),
|
ProcessCount: s.GetProcessCount(),
|
||||||
Temperatures: ts,
|
|
||||||
GPU: s.GetGpu(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +81,6 @@ type Host struct {
|
|||||||
IP string `json:"-"`
|
IP string `json:"-"`
|
||||||
CountryCode string
|
CountryCode string
|
||||||
Version string
|
Version string
|
||||||
GPU []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Host) PB() *pb.Host {
|
func (h *Host) PB() *pb.Host {
|
||||||
@@ -125,7 +97,6 @@ func (h *Host) PB() *pb.Host {
|
|||||||
Ip: h.IP,
|
Ip: h.IP,
|
||||||
CountryCode: h.CountryCode,
|
CountryCode: h.CountryCode,
|
||||||
Version: h.Version,
|
Version: h.Version,
|
||||||
Gpu: h.GPU,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +114,5 @@ func PB2Host(h *pb.Host) Host {
|
|||||||
IP: h.GetIp(),
|
IP: h.GetIp(),
|
||||||
CountryCode: h.GetCountryCode(),
|
CountryCode: h.GetCountryCode(),
|
||||||
Version: h.GetVersion(),
|
Version: h.GetVersion(),
|
||||||
GPU: h.GetGpu(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-11
@@ -13,25 +13,24 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
_ = iota
|
_ = iota
|
||||||
TaskTypeHTTPGet
|
TaskTypeHTTPGET
|
||||||
TaskTypeICMPPing
|
TaskTypeICMPPing
|
||||||
TaskTypeTCPPing
|
TaskTypeTCPPing
|
||||||
TaskTypeCommand
|
TaskTypeCommand
|
||||||
TaskTypeTerminal
|
TaskTypeTerminal
|
||||||
TaskTypeUpgrade
|
TaskTypeUpgrade
|
||||||
TaskTypeKeepalive
|
TaskTypeKeepalive
|
||||||
TaskTypeTerminalGRPC
|
|
||||||
TaskTypeNAT
|
|
||||||
TaskTypeReportHostInfo
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TerminalTask struct {
|
type TerminalTask struct {
|
||||||
StreamID string
|
// websocket 主机名
|
||||||
}
|
Host string `json:"host,omitempty"`
|
||||||
|
// 是否启用 SSL
|
||||||
type TaskNAT struct {
|
UseSSL bool `json:"use_ssl,omitempty"`
|
||||||
StreamID string
|
// 会话标识
|
||||||
Host string
|
Session string `json:"session,omitempty"`
|
||||||
|
// Agent在连接Server时需要的额外Cookie信息
|
||||||
|
Cookie string `json:"cookie,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -121,7 +120,7 @@ func (m *Monitor) AfterFind(tx *gorm.DB) error {
|
|||||||
|
|
||||||
// IsServiceSentinelNeeded 判断该任务类型是否需要进行服务监控 需要则返回true
|
// IsServiceSentinelNeeded 判断该任务类型是否需要进行服务监控 需要则返回true
|
||||||
func IsServiceSentinelNeeded(t uint64) bool {
|
func IsServiceSentinelNeeded(t uint64) bool {
|
||||||
return t != TaskTypeCommand && t != TaskTypeTerminalGRPC && t != TaskTypeUpgrade
|
return t != TaskTypeCommand && t != TaskTypeTerminal && t != TaskTypeUpgrade
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Monitor) InitSkipServers() error {
|
func (m *Monitor) InitSkipServers() error {
|
||||||
|
|||||||
@@ -19,3 +19,4 @@ type MonitorHistory struct {
|
|||||||
Down uint64 // 检查状态异常计数
|
Down uint64 // 检查状态异常计数
|
||||||
Data string
|
Data string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type NAT struct {
|
|
||||||
Common
|
|
||||||
Name string
|
|
||||||
ServerID uint64
|
|
||||||
Host string
|
|
||||||
Domain string `gorm:"unique"`
|
|
||||||
}
|
|
||||||
@@ -170,23 +170,14 @@ func (ns *NotificationServerBundle) replaceParamsInString(str string, message st
|
|||||||
|
|
||||||
if ns.Server != nil {
|
if ns.Server != nil {
|
||||||
str = strings.ReplaceAll(str, "#SERVER.NAME#", mod(ns.Server.Name))
|
str = strings.ReplaceAll(str, "#SERVER.NAME#", mod(ns.Server.Name))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.ID#", mod(fmt.Sprintf("%d", ns.Server.ID)))
|
|
||||||
str = strings.ReplaceAll(str, "#SERVER.CPU#", mod(fmt.Sprintf("%f", ns.Server.State.CPU)))
|
str = strings.ReplaceAll(str, "#SERVER.CPU#", mod(fmt.Sprintf("%f", ns.Server.State.CPU)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.MEM#", mod(fmt.Sprintf("%d", ns.Server.State.MemUsed)))
|
str = strings.ReplaceAll(str, "#SERVER.MEM#", mod(fmt.Sprintf("%d", ns.Server.State.MemUsed)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.SWAP#", mod(fmt.Sprintf("%d", ns.Server.State.SwapUsed)))
|
str = strings.ReplaceAll(str, "#SERVER.SWAP#", mod(fmt.Sprintf("%d", ns.Server.State.SwapUsed)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.DISK#", mod(fmt.Sprintf("%d", ns.Server.State.DiskUsed)))
|
str = strings.ReplaceAll(str, "#SERVER.DISK#", mod(fmt.Sprintf("%d", ns.Server.State.DiskUsed)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.MEMUSED#", mod(fmt.Sprintf("%d", ns.Server.State.MemUsed)))
|
|
||||||
str = strings.ReplaceAll(str, "#SERVER.SWAPUSED#", mod(fmt.Sprintf("%d", ns.Server.State.SwapUsed)))
|
|
||||||
str = strings.ReplaceAll(str, "#SERVER.DISKUSED#", mod(fmt.Sprintf("%d", ns.Server.State.DiskUsed)))
|
|
||||||
str = strings.ReplaceAll(str, "#SERVER.MEMTOTAL#", mod(fmt.Sprintf("%d", ns.Server.Host.MemTotal)))
|
|
||||||
str = strings.ReplaceAll(str, "#SERVER.SWAPTOTAL#", mod(fmt.Sprintf("%d", ns.Server.Host.SwapTotal)))
|
|
||||||
str = strings.ReplaceAll(str, "#SERVER.DISKTOTAL#", mod(fmt.Sprintf("%d", ns.Server.Host.DiskTotal)))
|
|
||||||
str = strings.ReplaceAll(str, "#SERVER.NETINSPEED#", mod(fmt.Sprintf("%d", ns.Server.State.NetInSpeed)))
|
str = strings.ReplaceAll(str, "#SERVER.NETINSPEED#", mod(fmt.Sprintf("%d", ns.Server.State.NetInSpeed)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.NETOUTSPEED#", mod(fmt.Sprintf("%d", ns.Server.State.NetOutSpeed)))
|
str = strings.ReplaceAll(str, "#SERVER.NETOUTSPEED#", mod(fmt.Sprintf("%d", ns.Server.State.NetOutSpeed)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.TRANSFERIN#", mod(fmt.Sprintf("%d", ns.Server.State.NetInTransfer)))
|
str = strings.ReplaceAll(str, "#SERVER.TRANSFERIN#", mod(fmt.Sprintf("%d", ns.Server.State.NetInTransfer)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.TRANSFEROUT#", mod(fmt.Sprintf("%d", ns.Server.State.NetOutTransfer)))
|
str = strings.ReplaceAll(str, "#SERVER.TRANSFEROUT#", mod(fmt.Sprintf("%d", ns.Server.State.NetOutTransfer)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.NETINTRANSFER#", mod(fmt.Sprintf("%d", ns.Server.State.NetInTransfer)))
|
|
||||||
str = strings.ReplaceAll(str, "#SERVER.NETOUTTRANSFER#", mod(fmt.Sprintf("%d", ns.Server.State.NetOutTransfer)))
|
|
||||||
str = strings.ReplaceAll(str, "#SERVER.LOAD1#", mod(fmt.Sprintf("%f", ns.Server.State.Load1)))
|
str = strings.ReplaceAll(str, "#SERVER.LOAD1#", mod(fmt.Sprintf("%f", ns.Server.State.Load1)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.LOAD5#", mod(fmt.Sprintf("%f", ns.Server.State.Load5)))
|
str = strings.ReplaceAll(str, "#SERVER.LOAD5#", mod(fmt.Sprintf("%f", ns.Server.State.Load5)))
|
||||||
str = strings.ReplaceAll(str, "#SERVER.LOAD15#", mod(fmt.Sprintf("%f", ns.Server.State.Load15)))
|
str = strings.ReplaceAll(str, "#SERVER.LOAD15#", mod(fmt.Sprintf("%f", ns.Server.State.Load15)))
|
||||||
|
|||||||
@@ -72,11 +72,11 @@ func execCase(t *testing.T, item testSt) {
|
|||||||
UdpConnCount: 0,
|
UdpConnCount: 0,
|
||||||
ProcessCount: 0,
|
ProcessCount: 0,
|
||||||
},
|
},
|
||||||
LastActive: time.Time{},
|
LastActive: time.Time{},
|
||||||
TaskClose: nil,
|
TaskClose: nil,
|
||||||
TaskStream: nil,
|
TaskStream: nil,
|
||||||
PrevTransferInSnapshot: 0,
|
PrevHourlyTransferIn: 0,
|
||||||
PrevTransferOutSnapshot: 0,
|
PrevHourlyTransferOut: 0,
|
||||||
}
|
}
|
||||||
ns := NotificationServerBundle{
|
ns := NotificationServerBundle{
|
||||||
Notification: &n,
|
Notification: &n,
|
||||||
|
|||||||
+6
-33
@@ -5,8 +5,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"github.com/naiba/nezha/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -44,19 +42,6 @@ func percentage(used, total uint64) float64 {
|
|||||||
return float64(used) * 100 / float64(total)
|
return float64(used) * 100 / float64(total)
|
||||||
}
|
}
|
||||||
|
|
||||||
func maxSliceValue(slice []float64) float64 {
|
|
||||||
if len(slice) != 0 {
|
|
||||||
max := slice[0]
|
|
||||||
for _, val := range slice {
|
|
||||||
if max < val {
|
|
||||||
max = val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return max
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Snapshot 未通过规则返回 struct{}{}, 通过返回 nil
|
// Snapshot 未通过规则返回 struct{}{}, 通过返回 nil
|
||||||
func (u *Rule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server, db *gorm.DB) interface{} {
|
func (u *Rule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server, db *gorm.DB) interface{} {
|
||||||
// 监控全部但是排除了此服务器
|
// 监控全部但是排除了此服务器
|
||||||
@@ -78,8 +63,6 @@ func (u *Rule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server,
|
|||||||
switch u.Type {
|
switch u.Type {
|
||||||
case "cpu":
|
case "cpu":
|
||||||
src = float64(server.State.CPU)
|
src = float64(server.State.CPU)
|
||||||
case "gpu":
|
|
||||||
src = float64(server.State.GPU)
|
|
||||||
case "memory":
|
case "memory":
|
||||||
src = percentage(server.State.MemUsed, server.Host.MemTotal)
|
src = percentage(server.State.MemUsed, server.Host.MemTotal)
|
||||||
case "swap":
|
case "swap":
|
||||||
@@ -105,24 +88,24 @@ func (u *Rule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server,
|
|||||||
src = float64(server.LastActive.Unix())
|
src = float64(server.LastActive.Unix())
|
||||||
}
|
}
|
||||||
case "transfer_in_cycle":
|
case "transfer_in_cycle":
|
||||||
src = float64(utils.Uint64SubInt64(server.State.NetInTransfer, server.PrevTransferInSnapshot))
|
src = float64(server.State.NetInTransfer - uint64(server.PrevHourlyTransferIn))
|
||||||
if u.CycleInterval != 0 {
|
if u.CycleInterval != 0 {
|
||||||
var res NResult
|
var res NResult
|
||||||
db.Model(&Transfer{}).Select("SUM(`in`) AS n").Where("datetime(`created_at`) >= datetime(?) AND server_id = ?", u.GetTransferDurationStart().UTC(), server.ID).Scan(&res)
|
db.Model(&Transfer{}).Select("SUM(`in`) AS n").Where("created_at > ? AND server_id = ?", u.GetTransferDurationStart(), server.ID).Scan(&res)
|
||||||
src += float64(res.N)
|
src += float64(res.N)
|
||||||
}
|
}
|
||||||
case "transfer_out_cycle":
|
case "transfer_out_cycle":
|
||||||
src = float64(utils.Uint64SubInt64(server.State.NetOutTransfer, server.PrevTransferOutSnapshot))
|
src = float64(server.State.NetOutTransfer - uint64(server.PrevHourlyTransferOut))
|
||||||
if u.CycleInterval != 0 {
|
if u.CycleInterval != 0 {
|
||||||
var res NResult
|
var res NResult
|
||||||
db.Model(&Transfer{}).Select("SUM(`out`) AS n").Where("datetime(`created_at`) >= datetime(?) AND server_id = ?", u.GetTransferDurationStart().UTC(), server.ID).Scan(&res)
|
db.Model(&Transfer{}).Select("SUM(`out`) AS n").Where("created_at > ? AND server_id = ?", u.GetTransferDurationStart(), server.ID).Scan(&res)
|
||||||
src += float64(res.N)
|
src += float64(res.N)
|
||||||
}
|
}
|
||||||
case "transfer_all_cycle":
|
case "transfer_all_cycle":
|
||||||
src = float64(utils.Uint64SubInt64(server.State.NetOutTransfer, server.PrevTransferOutSnapshot) + utils.Uint64SubInt64(server.State.NetInTransfer, server.PrevTransferInSnapshot))
|
src = float64(server.State.NetOutTransfer - uint64(server.PrevHourlyTransferOut) + server.State.NetInTransfer - uint64(server.PrevHourlyTransferIn))
|
||||||
if u.CycleInterval != 0 {
|
if u.CycleInterval != 0 {
|
||||||
var res NResult
|
var res NResult
|
||||||
db.Model(&Transfer{}).Select("SUM(`in`+`out`) AS n").Where("datetime(`created_at`) >= datetime(?) AND server_id = ?", u.GetTransferDurationStart().UTC(), server.ID).Scan(&res)
|
db.Model(&Transfer{}).Select("SUM(`in`+`out`) AS n").Where("created_at > ? AND server_id = ?", u.GetTransferDurationStart(), server.ID).Scan(&res)
|
||||||
src += float64(res.N)
|
src += float64(res.N)
|
||||||
}
|
}
|
||||||
case "load1":
|
case "load1":
|
||||||
@@ -137,16 +120,6 @@ func (u *Rule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server,
|
|||||||
src = float64(server.State.UdpConnCount)
|
src = float64(server.State.UdpConnCount)
|
||||||
case "process_count":
|
case "process_count":
|
||||||
src = float64(server.State.ProcessCount)
|
src = float64(server.State.ProcessCount)
|
||||||
case "temperature_max":
|
|
||||||
var temp []float64
|
|
||||||
if server.State.Temperatures != nil {
|
|
||||||
for _, tempStat := range server.State.Temperatures {
|
|
||||||
if tempStat.Temperature != 0 {
|
|
||||||
temp = append(temp, tempStat.Temperature)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
src = maxSliceValue(temp)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 循环区间流量检测 · 更新下次需要检测时间
|
// 循环区间流量检测 · 更新下次需要检测时间
|
||||||
|
|||||||
+9
-16
@@ -3,7 +3,6 @@ package model
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/naiba/nezha/pkg/utils"
|
"github.com/naiba/nezha/pkg/utils"
|
||||||
@@ -18,22 +17,18 @@ type Server struct {
|
|||||||
Note string `json:"-"` // 管理员可见备注
|
Note string `json:"-"` // 管理员可见备注
|
||||||
DisplayIndex int // 展示排序,越大越靠前
|
DisplayIndex int // 展示排序,越大越靠前
|
||||||
HideForGuest bool // 对游客隐藏
|
HideForGuest bool // 对游客隐藏
|
||||||
EnableDDNS bool `json:"-"` // 是否启用DDNS 未在配置文件中启用DDNS 或 DDNS检查时间为0时此项无效
|
EnableDDNS bool // 是否启用DDNS 未在配置文件中启用DDNS 或 DDNS检查时间为0时此项无效
|
||||||
EnableIPv4 bool `json:"-"` // 是否启用DDNS IPv4
|
DDNSDomain string // DDNS中的前缀 如基础域名为abc.oracle DDNSName为mjj 就会把mjj.abc.oracle解析服务器IP 为空则停用
|
||||||
EnableIpv6 bool `json:"-"` // 是否启用DDNS IPv6
|
|
||||||
DDNSDomain string `json:"-"` // DDNS中的前缀 如基础域名为abc.oracle DDNSName为mjj 就会把mjj.abc.oracle解析服务器IP 为空则停用
|
|
||||||
DDNSProfile string `json:"-"` // DDNS配置
|
|
||||||
|
|
||||||
Host *Host `gorm:"-"`
|
Host *Host `gorm:"-"`
|
||||||
State *HostState `gorm:"-"`
|
State *HostState `gorm:"-"`
|
||||||
LastActive time.Time `gorm:"-"`
|
LastActive time.Time `gorm:"-"`
|
||||||
|
|
||||||
TaskClose chan error `gorm:"-" json:"-"`
|
TaskClose chan error `gorm:"-" json:"-"`
|
||||||
TaskCloseLock *sync.Mutex `gorm:"-" json:"-"`
|
TaskStream pb.NezhaService_RequestTaskServer `gorm:"-" json:"-"`
|
||||||
TaskStream pb.NezhaService_RequestTaskServer `gorm:"-" json:"-"`
|
|
||||||
|
|
||||||
PrevTransferInSnapshot int64 `gorm:"-" json:"-"` // 上次数据点时的入站使用量
|
PrevHourlyTransferIn int64 `gorm:"-" json:"-"` // 上次数据点时的入站使用量
|
||||||
PrevTransferOutSnapshot int64 `gorm:"-" json:"-"` // 上次数据点时的出站使用量
|
PrevHourlyTransferOut int64 `gorm:"-" json:"-"` // 上次数据点时的出站使用量
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) CopyFromRunningServer(old *Server) {
|
func (s *Server) CopyFromRunningServer(old *Server) {
|
||||||
@@ -41,10 +36,9 @@ func (s *Server) CopyFromRunningServer(old *Server) {
|
|||||||
s.State = old.State
|
s.State = old.State
|
||||||
s.LastActive = old.LastActive
|
s.LastActive = old.LastActive
|
||||||
s.TaskClose = old.TaskClose
|
s.TaskClose = old.TaskClose
|
||||||
s.TaskCloseLock = old.TaskCloseLock
|
|
||||||
s.TaskStream = old.TaskStream
|
s.TaskStream = old.TaskStream
|
||||||
s.PrevTransferInSnapshot = old.PrevTransferInSnapshot
|
s.PrevHourlyTransferIn = old.PrevHourlyTransferIn
|
||||||
s.PrevTransferOutSnapshot = old.PrevTransferOutSnapshot
|
s.PrevHourlyTransferOut = old.PrevHourlyTransferOut
|
||||||
}
|
}
|
||||||
|
|
||||||
func boolToString(b bool) string {
|
func boolToString(b bool) string {
|
||||||
@@ -60,6 +54,5 @@ func (s Server) Marshal() template.JS {
|
|||||||
note, _ := utils.Json.Marshal(s.Note)
|
note, _ := utils.Json.Marshal(s.Note)
|
||||||
secret, _ := utils.Json.Marshal(s.Secret)
|
secret, _ := utils.Json.Marshal(s.Secret)
|
||||||
ddnsDomain, _ := utils.Json.Marshal(s.DDNSDomain)
|
ddnsDomain, _ := utils.Json.Marshal(s.DDNSDomain)
|
||||||
ddnsProfile, _ := utils.Json.Marshal(s.DDNSProfile)
|
return template.JS(fmt.Sprintf(`{"ID":%d,"Name":%s,"Secret":%s,"DisplayIndex":%d,"Tag":%s,"Note":%s,"HideForGuest": %s,"EnableDDNS": %s,"DDNSDomain": %s}`, s.ID, name, secret, s.DisplayIndex, tag, note, boolToString(s.HideForGuest), boolToString(s.EnableDDNS), ddnsDomain)) // #nosec
|
||||||
return template.JS(fmt.Sprintf(`{"ID":%d,"Name":%s,"Secret":%s,"DisplayIndex":%d,"Tag":%s,"Note":%s,"HideForGuest": %s,"EnableDDNS": %s,"EnableIPv4": %s,"EnableIpv6": %s,"DDNSDomain": %s,"DDNSProfile": %s}`, s.ID, name, secret, s.DisplayIndex, tag, note, boolToString(s.HideForGuest), boolToString(s.EnableDDNS), boolToString(s.EnableIPv4), boolToString(s.EnableIpv6), ddnsDomain, ddnsProfile)) // #nosec
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type ProviderCloudflare struct {
|
|||||||
Secret string
|
Secret string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *ProviderCloudflare) UpdateDomain(domainConfig *DomainConfig) bool {
|
func (provider ProviderCloudflare) UpdateDomain(domainConfig *DomainConfig) bool {
|
||||||
if domainConfig == nil {
|
if domainConfig == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ func (provider *ProviderCloudflare) UpdateDomain(domainConfig *DomainConfig) boo
|
|||||||
return resultV4 && resultV6
|
return resultV4 && resultV6
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *ProviderCloudflare) addDomainRecord(zoneID string, domainConfig *DomainConfig, isIpv4 bool) bool {
|
func (provider ProviderCloudflare) addDomainRecord(zoneID string, domainConfig *DomainConfig, isIpv4 bool) bool {
|
||||||
record, err := provider.findDNSRecord(zoneID, domainConfig.FullDomain, isIpv4)
|
record, err := provider.findDNSRecord(zoneID, domainConfig.FullDomain, isIpv4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("查找 DNS 记录时出错: %s\n", err)
|
log.Printf("查找 DNS 记录时出错: %s\n", err)
|
||||||
@@ -58,7 +58,7 @@ func (provider *ProviderCloudflare) addDomainRecord(zoneID string, domainConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *ProviderCloudflare) getZoneID(domain string) (string, error) {
|
func (provider ProviderCloudflare) getZoneID(domain string) (string, error) {
|
||||||
_, realDomain := SplitDomain(domain)
|
_, realDomain := SplitDomain(domain)
|
||||||
url := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones?name=%s", realDomain)
|
url := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones?name=%s", realDomain)
|
||||||
body, err := provider.sendRequest("GET", url, nil)
|
body, err := provider.sendRequest("GET", url, nil)
|
||||||
@@ -81,7 +81,7 @@ func (provider *ProviderCloudflare) getZoneID(domain string) (string, error) {
|
|||||||
return "", fmt.Errorf("找不到 Zone ID")
|
return "", fmt.Errorf("找不到 Zone ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *ProviderCloudflare) findDNSRecord(zoneID string, domain string, isIPv4 bool) (map[string]interface{}, error) {
|
func (provider ProviderCloudflare) findDNSRecord(zoneID string, domain string, isIPv4 bool) (map[string]interface{}, error) {
|
||||||
var ipType = "A"
|
var ipType = "A"
|
||||||
if !isIPv4 {
|
if !isIPv4 {
|
||||||
ipType = "AAAA"
|
ipType = "AAAA"
|
||||||
@@ -106,7 +106,7 @@ func (provider *ProviderCloudflare) findDNSRecord(zoneID string, domain string,
|
|||||||
return nil, nil // 没有找到 DNS 记录
|
return nil, nil // 没有找到 DNS 记录
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *ProviderCloudflare) createDNSRecord(zoneID string, domainConfig *DomainConfig, isIPv4 bool) bool {
|
func (provider ProviderCloudflare) createDNSRecord(zoneID string, domainConfig *DomainConfig, isIPv4 bool) bool {
|
||||||
var ipType = "A"
|
var ipType = "A"
|
||||||
var ipAddr = domainConfig.Ipv4Addr
|
var ipAddr = domainConfig.Ipv4Addr
|
||||||
if !isIPv4 {
|
if !isIPv4 {
|
||||||
@@ -126,7 +126,7 @@ func (provider *ProviderCloudflare) createDNSRecord(zoneID string, domainConfig
|
|||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *ProviderCloudflare) updateDNSRecord(zoneID string, recordID string, domainConfig *DomainConfig, isIPv4 bool) bool {
|
func (provider ProviderCloudflare) updateDNSRecord(zoneID string, recordID string, domainConfig *DomainConfig, isIPv4 bool) bool {
|
||||||
var ipType = "A"
|
var ipType = "A"
|
||||||
var ipAddr = domainConfig.Ipv4Addr
|
var ipAddr = domainConfig.Ipv4Addr
|
||||||
if !isIPv4 {
|
if !isIPv4 {
|
||||||
@@ -147,7 +147,7 @@ func (provider *ProviderCloudflare) updateDNSRecord(zoneID string, recordID stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 以下为辅助方法,如发送 HTTP 请求等
|
// 以下为辅助方法,如发送 HTTP 请求等
|
||||||
func (provider *ProviderCloudflare) sendRequest(method string, url string, data []byte) ([]byte, error) {
|
func (provider ProviderCloudflare) sendRequest(method string, url string, data []byte) ([]byte, error) {
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
req, err := http.NewRequest(method, url, bytes.NewBuffer(data))
|
req, err := http.NewRequest(method, url, bytes.NewBuffer(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+1
-1
@@ -2,6 +2,6 @@ package ddns
|
|||||||
|
|
||||||
type ProviderDummy struct{}
|
type ProviderDummy struct{}
|
||||||
|
|
||||||
func (provider *ProviderDummy) UpdateDomain(domainConfig *DomainConfig) bool {
|
func (provider ProviderDummy) UpdateDomain(domainConfig *DomainConfig) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-5
@@ -1,7 +1,7 @@
|
|||||||
package ddns
|
package ddns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.org/x/net/publicsuffix"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -33,8 +33,29 @@ func SetStringHeadersToRequest(req *http.Request, headers []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SplitDomain 分割域名为前缀和一级域名
|
// SplitDomain 分割域名为前缀和一级域名
|
||||||
func SplitDomain(domain string) (prefix string, realDomain string) {
|
func SplitDomain(domain string) (prefix string, topLevelDomain string) {
|
||||||
realDomain, _ = publicsuffix.EffectiveTLDPlusOne(domain)
|
// 带有二级TLD的一些常见例子,需要特别处理
|
||||||
prefix = domain[:len(domain)-len(realDomain)-1]
|
secondLevelTLDs := map[string]bool{
|
||||||
return prefix, realDomain
|
".co.uk": true, ".com.cn": true, ".gov.cn": true, ".net.cn": true, ".org.cn": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分割域名为"."的各部分
|
||||||
|
parts := strings.Split(domain, ".")
|
||||||
|
|
||||||
|
// 处理特殊情况,例如 ".co.uk"
|
||||||
|
for i := len(parts) - 2; i > 0; i-- {
|
||||||
|
potentialTLD := fmt.Sprintf(".%s.%s", parts[i], parts[i+1])
|
||||||
|
if secondLevelTLDs[potentialTLD] {
|
||||||
|
if i > 1 {
|
||||||
|
return strings.Join(parts[:i-1], "."), strings.Join(parts[i-1:], ".")
|
||||||
|
}
|
||||||
|
return "", domain // 当域名仅为二级TLD时,无前缀
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 常规处理,查找最后一个"."前的所有内容作为前缀
|
||||||
|
if len(parts) > 2 {
|
||||||
|
return strings.Join(parts[:len(parts)-2], "."), strings.Join(parts[len(parts)-2:], ".")
|
||||||
|
}
|
||||||
|
return "", domain // 当域名不包含子域名时,无前缀
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,228 +0,0 @@
|
|||||||
package ddns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
url = "https://dnspod.tencentcloudapi.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ProviderTencentCloud struct {
|
|
||||||
SecretID string
|
|
||||||
SecretKey string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provider *ProviderTencentCloud) UpdateDomain(domainConfig *DomainConfig) bool {
|
|
||||||
if domainConfig == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当IPv4和IPv6同时成功才算作成功
|
|
||||||
var resultV4 = true
|
|
||||||
var resultV6 = true
|
|
||||||
if domainConfig.EnableIPv4 {
|
|
||||||
if !provider.addDomainRecord(domainConfig, true) {
|
|
||||||
resultV4 = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if domainConfig.EnableIpv6 {
|
|
||||||
if !provider.addDomainRecord(domainConfig, false) {
|
|
||||||
resultV6 = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultV4 && resultV6
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provider *ProviderTencentCloud) addDomainRecord(domainConfig *DomainConfig, isIpv4 bool) bool {
|
|
||||||
record, err := provider.findDNSRecord(domainConfig.FullDomain, isIpv4)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("查找 DNS 记录时出错: %s\n", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if errResponse, ok := record["Error"].(map[string]interface{}); ok {
|
|
||||||
if errCode, ok := errResponse["Code"].(string); ok && errCode == "ResourceNotFound.NoDataOfRecord" { // 没有找到 DNS 记录
|
|
||||||
// 添加 DNS 记录
|
|
||||||
return provider.createDNSRecord(domainConfig.FullDomain, domainConfig, isIpv4)
|
|
||||||
} else {
|
|
||||||
log.Printf("查询 DNS 记录时出错,错误代码为: %s\n", errCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 默认情况下更新 DNS 记录
|
|
||||||
return provider.updateDNSRecord(domainConfig.FullDomain, record["RecordList"].([]interface{})[0].(map[string]interface{})["RecordId"].(float64), domainConfig, isIpv4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provider *ProviderTencentCloud) findDNSRecord(domain string, isIPv4 bool) (map[string]interface{}, error) {
|
|
||||||
var ipType = "A"
|
|
||||||
if !isIPv4 {
|
|
||||||
ipType = "AAAA"
|
|
||||||
}
|
|
||||||
_, realDomain := SplitDomain(domain)
|
|
||||||
prefix, _ := SplitDomain(domain)
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"RecordType": ipType,
|
|
||||||
"Domain": realDomain,
|
|
||||||
"RecordLine": "默认",
|
|
||||||
"Subdomain": prefix,
|
|
||||||
}
|
|
||||||
jsonData, _ := json.Marshal(data)
|
|
||||||
body, err := provider.sendRequest("DescribeRecordList", jsonData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var res map[string]interface{}
|
|
||||||
err = json.Unmarshal(body, &res)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := res["Response"].(map[string]interface{})
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provider *ProviderTencentCloud) createDNSRecord(domain string, domainConfig *DomainConfig, isIPv4 bool) bool {
|
|
||||||
var ipType = "A"
|
|
||||||
var ipAddr = domainConfig.Ipv4Addr
|
|
||||||
if !isIPv4 {
|
|
||||||
ipType = "AAAA"
|
|
||||||
ipAddr = domainConfig.Ipv6Addr
|
|
||||||
}
|
|
||||||
_, realDomain := SplitDomain(domain)
|
|
||||||
prefix, _ := SplitDomain(domain)
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"RecordType": ipType,
|
|
||||||
"RecordLine": "默认",
|
|
||||||
"Domain": realDomain,
|
|
||||||
"SubDomain": prefix,
|
|
||||||
"Value": ipAddr,
|
|
||||||
"TTL": 600,
|
|
||||||
}
|
|
||||||
jsonData, _ := json.Marshal(data)
|
|
||||||
_, err := provider.sendRequest("CreateRecord", jsonData)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provider *ProviderTencentCloud) updateDNSRecord(domain string, recordID float64, domainConfig *DomainConfig, isIPv4 bool) bool {
|
|
||||||
var ipType = "A"
|
|
||||||
var ipAddr = domainConfig.Ipv4Addr
|
|
||||||
if !isIPv4 {
|
|
||||||
ipType = "AAAA"
|
|
||||||
ipAddr = domainConfig.Ipv6Addr
|
|
||||||
}
|
|
||||||
_, realDomain := SplitDomain(domain)
|
|
||||||
prefix, _ := SplitDomain(domain)
|
|
||||||
data := map[string]interface{}{
|
|
||||||
"RecordType": ipType,
|
|
||||||
"RecordLine": "默认",
|
|
||||||
"Domain": realDomain,
|
|
||||||
"SubDomain": prefix,
|
|
||||||
"Value": ipAddr,
|
|
||||||
"TTL": 600,
|
|
||||||
"RecordId": recordID,
|
|
||||||
}
|
|
||||||
jsonData, _ := json.Marshal(data)
|
|
||||||
_, err := provider.sendRequest("ModifyRecord", jsonData)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 以下为辅助方法,如发送 HTTP 请求等
|
|
||||||
func (provider *ProviderTencentCloud) sendRequest(action string, data []byte) ([]byte, error) {
|
|
||||||
client := &http.Client{}
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
req.Header.Set("X-TC-Version", "2021-03-23")
|
|
||||||
|
|
||||||
provider.signRequest(provider.SecretID, provider.SecretKey, req, action, string(data))
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func(Body io.ReadCloser) {
|
|
||||||
err := Body.Close()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("NEZHA>> 无法关闭HTTP响应体流: %s\n", err.Error())
|
|
||||||
}
|
|
||||||
}(resp.Body)
|
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return body, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/jeessy2/ddns-go/blob/master/util/tencent_cloud_signer.go
|
|
||||||
|
|
||||||
func (provider *ProviderTencentCloud) sha256hex(s string) string {
|
|
||||||
b := sha256.Sum256([]byte(s))
|
|
||||||
return hex.EncodeToString(b[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provider *ProviderTencentCloud) hmacsha256(s, key string) string {
|
|
||||||
hashed := hmac.New(sha256.New, []byte(key))
|
|
||||||
hashed.Write([]byte(s))
|
|
||||||
return string(hashed.Sum(nil))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provider *ProviderTencentCloud) WriteString(strs ...string) string {
|
|
||||||
var b strings.Builder
|
|
||||||
for _, str := range strs {
|
|
||||||
b.WriteString(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (provider *ProviderTencentCloud) signRequest(secretId string, secretKey string, r *http.Request, action string, payload string) {
|
|
||||||
algorithm := "TC3-HMAC-SHA256"
|
|
||||||
service := "dnspod"
|
|
||||||
host := provider.WriteString(service, ".tencentcloudapi.com")
|
|
||||||
timestamp := time.Now().Unix()
|
|
||||||
timestampStr := strconv.FormatInt(timestamp, 10)
|
|
||||||
|
|
||||||
// 步骤 1:拼接规范请求串
|
|
||||||
canonicalHeaders := provider.WriteString("content-type:application/json\nhost:", host, "\nx-tc-action:", strings.ToLower(action), "\n")
|
|
||||||
signedHeaders := "content-type;host;x-tc-action"
|
|
||||||
hashedRequestPayload := provider.sha256hex(payload)
|
|
||||||
canonicalRequest := provider.WriteString("POST\n/\n\n", canonicalHeaders, "\n", signedHeaders, "\n", hashedRequestPayload)
|
|
||||||
|
|
||||||
// 步骤 2:拼接待签名字符串
|
|
||||||
date := time.Unix(timestamp, 0).UTC().Format("2006-01-02")
|
|
||||||
credentialScope := provider.WriteString(date, "/", service, "/tc3_request")
|
|
||||||
hashedCanonicalRequest := provider.sha256hex(canonicalRequest)
|
|
||||||
string2sign := provider.WriteString(algorithm, "\n", timestampStr, "\n", credentialScope, "\n", hashedCanonicalRequest)
|
|
||||||
|
|
||||||
// 步骤 3:计算签名
|
|
||||||
secretDate := provider.hmacsha256(date, provider.WriteString("TC3", secretKey))
|
|
||||||
secretService := provider.hmacsha256(service, secretDate)
|
|
||||||
secretSigning := provider.hmacsha256("tc3_request", secretService)
|
|
||||||
signature := hex.EncodeToString([]byte(provider.hmacsha256(string2sign, secretSigning)))
|
|
||||||
|
|
||||||
// 步骤 4:拼接 Authorization
|
|
||||||
authorization := provider.WriteString(algorithm, " Credential=", secretId, "/", credentialScope, ", SignedHeaders=", signedHeaders, ", Signature=", signature)
|
|
||||||
|
|
||||||
r.Header.Add("Authorization", authorization)
|
|
||||||
r.Header.Set("Host", host)
|
|
||||||
r.Header.Set("X-TC-Action", action)
|
|
||||||
r.Header.Add("X-TC-Timestamp", timestampStr)
|
|
||||||
}
|
|
||||||
+1
-1
@@ -14,7 +14,7 @@ type ProviderWebHook struct {
|
|||||||
RequestHeader string
|
RequestHeader string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *ProviderWebHook) UpdateDomain(domainConfig *DomainConfig) bool {
|
func (provider ProviderWebHook) UpdateDomain(domainConfig *DomainConfig) bool {
|
||||||
if domainConfig == nil {
|
if domainConfig == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
stub
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package geoip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"embed"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
maxminddb "github.com/oschwald/maxminddb-golang"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed geoip.db
|
|
||||||
var geoDBFS embed.FS
|
|
||||||
|
|
||||||
var (
|
|
||||||
dbData []byte
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
type IPInfo struct {
|
|
||||||
Country string `maxminddb:"country"`
|
|
||||||
CountryName string `maxminddb:"country_name"`
|
|
||||||
Continent string `maxminddb:"continent"`
|
|
||||||
ContinentName string `maxminddb:"continent_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
dbData, err = geoDBFS.ReadFile("geoip.db")
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("NEZHA>> Failed to open geoip database: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Lookup(ip net.IP, record *IPInfo) (string, error) {
|
|
||||||
db, err := maxminddb.FromBytes(dbData)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
err = db.Lookup(ip, record)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if record.Country != "" {
|
|
||||||
return strings.ToLower(record.Country), nil
|
|
||||||
} else if record.Continent != "" {
|
|
||||||
return strings.ToLower(record.Continent), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", fmt.Errorf("IP not found")
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
package grpcx
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"github.com/naiba/nezha/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ io.ReadWriteCloser = &IOStreamWrapper{}
|
|
||||||
|
|
||||||
type IOStream interface {
|
|
||||||
Recv() (*proto.IOStreamData, error)
|
|
||||||
Send(*proto.IOStreamData) error
|
|
||||||
Context() context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
type IOStreamWrapper struct {
|
|
||||||
IOStream
|
|
||||||
dataBuf []byte
|
|
||||||
closed *atomic.Bool
|
|
||||||
closeCh chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewIOStreamWrapper(stream IOStream) *IOStreamWrapper {
|
|
||||||
return &IOStreamWrapper{
|
|
||||||
IOStream: stream,
|
|
||||||
closeCh: make(chan struct{}),
|
|
||||||
closed: new(atomic.Bool),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IOStreamWrapper) Read(p []byte) (n int, err error) {
|
|
||||||
if len(iw.dataBuf) > 0 {
|
|
||||||
n := copy(p, iw.dataBuf)
|
|
||||||
iw.dataBuf = iw.dataBuf[n:]
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
var data *proto.IOStreamData
|
|
||||||
if data, err = iw.Recv(); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
n = copy(p, data.Data)
|
|
||||||
if n < len(data.Data) {
|
|
||||||
iw.dataBuf = data.Data[n:]
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IOStreamWrapper) Write(p []byte) (n int, err error) {
|
|
||||||
err = iw.Send(&proto.IOStreamData{Data: p})
|
|
||||||
return len(p), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IOStreamWrapper) Close() error {
|
|
||||||
if iw.closed.CompareAndSwap(false, true) {
|
|
||||||
close(iw.closeCh)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (iw *IOStreamWrapper) Wait() {
|
|
||||||
<-iw.closeCh
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,6 @@ var adminPage = map[string]bool{
|
|||||||
"/monitor": true,
|
"/monitor": true,
|
||||||
"/setting": true,
|
"/setting": true,
|
||||||
"/notification": true,
|
"/notification": true,
|
||||||
"/nat": true,
|
|
||||||
"/cron": true,
|
"/cron": true,
|
||||||
"/api": true,
|
"/api": true,
|
||||||
}
|
}
|
||||||
@@ -26,8 +25,6 @@ func CommonEnvironment(c *gin.Context, data map[string]interface{}) gin.H {
|
|||||||
data["Version"] = singleton.Version
|
data["Version"] = singleton.Version
|
||||||
data["Conf"] = singleton.Conf
|
data["Conf"] = singleton.Conf
|
||||||
data["Themes"] = model.Themes
|
data["Themes"] = model.Themes
|
||||||
data["CustomCode"] = singleton.Conf.Site.CustomCode
|
|
||||||
data["CustomCodeDashboard"] = singleton.Conf.Site.CustomCodeDashboard
|
|
||||||
// 是否是管理页面
|
// 是否是管理页面
|
||||||
data["IsAdminPage"] = adminPage[data["MatchedPath"].(string)]
|
data["IsAdminPage"] = adminPage[data["MatchedPath"].(string)]
|
||||||
// 站点标题
|
// 站点标题
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ func ValidateViewPassword(opt ValidateViewPasswordOption) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
if opt.IsPage {
|
if opt.IsPage {
|
||||||
c.HTML(http.StatusOK, GetPreferredTheme(c, "/viewpassword"), CommonEnvironment(c, gin.H{
|
c.HTML(http.StatusOK, GetPreferredTheme(c, "/viewpassword"), CommonEnvironment(c, gin.H{
|
||||||
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "VerifyPassword"}),
|
"Title": singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "VerifyPassword"}),
|
||||||
|
"CustomCode": singleton.Conf.Site.CustomCode,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
package cloudflare
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/naiba/nezha/model"
|
|
||||||
"github.com/naiba/nezha/service/singleton"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UserInfo struct {
|
|
||||||
Sub string `json:"sub"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Groups []string `json:"groups"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u UserInfo) MapToNezhaUser() model.User {
|
|
||||||
var user model.User
|
|
||||||
singleton.DB.Where("login = ?", u.Sub).First(&user)
|
|
||||||
user.Login = u.Sub
|
|
||||||
user.Email = u.Email
|
|
||||||
user.Name = u.Name
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
package general
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/naiba/nezha/model"
|
|
||||||
"github.com/naiba/nezha/service/singleton"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UserInfo struct {
|
|
||||||
Sub string `json:"sub"`
|
|
||||||
Username string `json:"preferred_username"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Groups []string `json:"groups,omitempty"`
|
|
||||||
Roles []string `json:"roles,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u UserInfo) MapToNezhaUser(loginClaim string, groupClaim string, adminGroups []string, autoCreate bool) model.User {
|
|
||||||
var user model.User
|
|
||||||
var login string
|
|
||||||
var groups []string
|
|
||||||
var isAdmin bool
|
|
||||||
if loginClaim == "email" {
|
|
||||||
login = u.Email
|
|
||||||
} else if loginClaim == "preferred_username" {
|
|
||||||
login = u.Username
|
|
||||||
} else {
|
|
||||||
login = u.Sub
|
|
||||||
}
|
|
||||||
if groupClaim == "roles" {
|
|
||||||
groups = u.Roles
|
|
||||||
} else {
|
|
||||||
groups = u.Groups
|
|
||||||
}
|
|
||||||
// Check if user is admin
|
|
||||||
adminGroupSet := make(map[string]struct{}, len(adminGroups))
|
|
||||||
for _, adminGroup := range adminGroups {
|
|
||||||
adminGroupSet[adminGroup] = struct{}{}
|
|
||||||
}
|
|
||||||
for _, group := range groups {
|
|
||||||
if _, found := adminGroupSet[group]; found {
|
|
||||||
isAdmin = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result := singleton.DB.Where("login = ?", login).First(&user)
|
|
||||||
user.Login = login
|
|
||||||
user.Email = u.Email
|
|
||||||
user.Name = u.Name
|
|
||||||
user.SuperAdmin = isAdmin
|
|
||||||
if result.Error != nil && autoCreate {
|
|
||||||
singleton.DB.Create(&user)
|
|
||||||
} else if result.Error != nil {
|
|
||||||
return model.User{}
|
|
||||||
}
|
|
||||||
return user
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ io.ReadWriteCloser = &RequestWrapper{}
|
|
||||||
|
|
||||||
type RequestWrapper struct {
|
|
||||||
req *http.Request
|
|
||||||
reader *bytes.Buffer
|
|
||||||
writer net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRequestWrapper(req *http.Request, writer gin.ResponseWriter) (*RequestWrapper, error) {
|
|
||||||
conn, _, err := writer.Hijack()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
buf := bytes.NewBuffer(nil)
|
|
||||||
if err = req.Write(buf); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &RequestWrapper{
|
|
||||||
req: req,
|
|
||||||
reader: buf,
|
|
||||||
writer: conn,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rw *RequestWrapper) Read(p []byte) (int, error) {
|
|
||||||
count, err := rw.reader.Read(p)
|
|
||||||
if err == nil {
|
|
||||||
return count, nil
|
|
||||||
}
|
|
||||||
if err != io.EOF {
|
|
||||||
return count, err
|
|
||||||
}
|
|
||||||
// request 数据读完之后等待客户端断开连接或 grpc 超时
|
|
||||||
return rw.writer.Read(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rw *RequestWrapper) Write(p []byte) (int, error) {
|
|
||||||
return rw.writer.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rw *RequestWrapper) Close() error {
|
|
||||||
rw.req.Body.Close()
|
|
||||||
rw.writer.Close()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -76,13 +76,3 @@ func GenerateRandomString(n int) (string, error) {
|
|||||||
}
|
}
|
||||||
return string(ret), nil
|
return string(ret), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Uint64SubInt64(a uint64, b int64) uint64 {
|
|
||||||
if b < 0 {
|
|
||||||
return a + uint64(-b)
|
|
||||||
}
|
|
||||||
if a < uint64(b) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return a - uint64(b)
|
|
||||||
}
|
|
||||||
|
|||||||
+10
-41
@@ -1,56 +1,25 @@
|
|||||||
package websocketx
|
package websocketx
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ io.ReadWriteCloser = &Conn{}
|
|
||||||
|
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
*websocket.Conn
|
*websocket.Conn
|
||||||
writeLock *sync.Mutex
|
writeLock sync.Mutex
|
||||||
dataBuf []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConn(conn *websocket.Conn) *Conn {
|
func (conn *Conn) WriteMessage(msgType int, data []byte) error {
|
||||||
return &Conn{Conn: conn, writeLock: new(sync.Mutex)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (conn *Conn) Write(data []byte) (int, error) {
|
|
||||||
conn.writeLock.Lock()
|
conn.writeLock.Lock()
|
||||||
defer conn.writeLock.Unlock()
|
defer conn.writeLock.Unlock()
|
||||||
if err := conn.Conn.WriteMessage(websocket.BinaryMessage, data); err != nil {
|
var err error
|
||||||
return 0, err
|
lo.TryCatchWithErrorValue(func() error {
|
||||||
}
|
return conn.Conn.WriteMessage(msgType, data)
|
||||||
return len(data), nil
|
}, func(res any) {
|
||||||
}
|
err = res.(error)
|
||||||
|
})
|
||||||
func (conn *Conn) WriteMessage(messageType int, data []byte) error {
|
return err
|
||||||
conn.writeLock.Lock()
|
|
||||||
defer conn.writeLock.Unlock()
|
|
||||||
return conn.Conn.WriteMessage(messageType, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (conn *Conn) Read(data []byte) (int, error) {
|
|
||||||
if len(conn.dataBuf) > 0 {
|
|
||||||
n := copy(data, conn.dataBuf)
|
|
||||||
conn.dataBuf = conn.dataBuf[n:]
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
mType, innerData, err := conn.Conn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
// 将文本消息转换为命令输入
|
|
||||||
if mType == websocket.TextMessage {
|
|
||||||
innerData = append([]byte{0}, innerData...)
|
|
||||||
}
|
|
||||||
n := copy(data, innerData)
|
|
||||||
if n < len(innerData) {
|
|
||||||
conn.dataBuf = innerData[n:]
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
+109
-358
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.34.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v5.26.1
|
// protoc v3.21.12
|
||||||
// source: proto/nezha.proto
|
// source: proto/nezha.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
@@ -35,9 +35,8 @@ type Host struct {
|
|||||||
Virtualization string `protobuf:"bytes,8,opt,name=virtualization,proto3" json:"virtualization,omitempty"`
|
Virtualization string `protobuf:"bytes,8,opt,name=virtualization,proto3" json:"virtualization,omitempty"`
|
||||||
BootTime uint64 `protobuf:"varint,9,opt,name=boot_time,json=bootTime,proto3" json:"boot_time,omitempty"`
|
BootTime uint64 `protobuf:"varint,9,opt,name=boot_time,json=bootTime,proto3" json:"boot_time,omitempty"`
|
||||||
Ip string `protobuf:"bytes,10,opt,name=ip,proto3" json:"ip,omitempty"`
|
Ip string `protobuf:"bytes,10,opt,name=ip,proto3" json:"ip,omitempty"`
|
||||||
CountryCode string `protobuf:"bytes,11,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"` // deprecated
|
CountryCode string `protobuf:"bytes,11,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
|
||||||
Version string `protobuf:"bytes,12,opt,name=version,proto3" json:"version,omitempty"`
|
Version string `protobuf:"bytes,12,opt,name=version,proto3" json:"version,omitempty"`
|
||||||
Gpu []string `protobuf:"bytes,13,rep,name=gpu,proto3" json:"gpu,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Host) Reset() {
|
func (x *Host) Reset() {
|
||||||
@@ -156,35 +155,26 @@ func (x *Host) GetVersion() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Host) GetGpu() []string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Gpu
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type State struct {
|
type State struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Cpu float64 `protobuf:"fixed64,1,opt,name=cpu,proto3" json:"cpu,omitempty"`
|
Cpu float64 `protobuf:"fixed64,1,opt,name=cpu,proto3" json:"cpu,omitempty"`
|
||||||
MemUsed uint64 `protobuf:"varint,3,opt,name=mem_used,json=memUsed,proto3" json:"mem_used,omitempty"`
|
MemUsed uint64 `protobuf:"varint,3,opt,name=mem_used,json=memUsed,proto3" json:"mem_used,omitempty"`
|
||||||
SwapUsed uint64 `protobuf:"varint,4,opt,name=swap_used,json=swapUsed,proto3" json:"swap_used,omitempty"`
|
SwapUsed uint64 `protobuf:"varint,4,opt,name=swap_used,json=swapUsed,proto3" json:"swap_used,omitempty"`
|
||||||
DiskUsed uint64 `protobuf:"varint,5,opt,name=disk_used,json=diskUsed,proto3" json:"disk_used,omitempty"`
|
DiskUsed uint64 `protobuf:"varint,5,opt,name=disk_used,json=diskUsed,proto3" json:"disk_used,omitempty"`
|
||||||
NetInTransfer uint64 `protobuf:"varint,6,opt,name=net_in_transfer,json=netInTransfer,proto3" json:"net_in_transfer,omitempty"`
|
NetInTransfer uint64 `protobuf:"varint,6,opt,name=net_in_transfer,json=netInTransfer,proto3" json:"net_in_transfer,omitempty"`
|
||||||
NetOutTransfer uint64 `protobuf:"varint,7,opt,name=net_out_transfer,json=netOutTransfer,proto3" json:"net_out_transfer,omitempty"`
|
NetOutTransfer uint64 `protobuf:"varint,7,opt,name=net_out_transfer,json=netOutTransfer,proto3" json:"net_out_transfer,omitempty"`
|
||||||
NetInSpeed uint64 `protobuf:"varint,8,opt,name=net_in_speed,json=netInSpeed,proto3" json:"net_in_speed,omitempty"`
|
NetInSpeed uint64 `protobuf:"varint,8,opt,name=net_in_speed,json=netInSpeed,proto3" json:"net_in_speed,omitempty"`
|
||||||
NetOutSpeed uint64 `protobuf:"varint,9,opt,name=net_out_speed,json=netOutSpeed,proto3" json:"net_out_speed,omitempty"`
|
NetOutSpeed uint64 `protobuf:"varint,9,opt,name=net_out_speed,json=netOutSpeed,proto3" json:"net_out_speed,omitempty"`
|
||||||
Uptime uint64 `protobuf:"varint,10,opt,name=uptime,proto3" json:"uptime,omitempty"`
|
Uptime uint64 `protobuf:"varint,10,opt,name=uptime,proto3" json:"uptime,omitempty"`
|
||||||
Load1 float64 `protobuf:"fixed64,11,opt,name=load1,proto3" json:"load1,omitempty"`
|
Load1 float64 `protobuf:"fixed64,11,opt,name=load1,proto3" json:"load1,omitempty"`
|
||||||
Load5 float64 `protobuf:"fixed64,12,opt,name=load5,proto3" json:"load5,omitempty"`
|
Load5 float64 `protobuf:"fixed64,12,opt,name=load5,proto3" json:"load5,omitempty"`
|
||||||
Load15 float64 `protobuf:"fixed64,13,opt,name=load15,proto3" json:"load15,omitempty"`
|
Load15 float64 `protobuf:"fixed64,13,opt,name=load15,proto3" json:"load15,omitempty"`
|
||||||
TcpConnCount uint64 `protobuf:"varint,14,opt,name=tcp_conn_count,json=tcpConnCount,proto3" json:"tcp_conn_count,omitempty"`
|
TcpConnCount uint64 `protobuf:"varint,14,opt,name=tcp_conn_count,json=tcpConnCount,proto3" json:"tcp_conn_count,omitempty"`
|
||||||
UdpConnCount uint64 `protobuf:"varint,15,opt,name=udp_conn_count,json=udpConnCount,proto3" json:"udp_conn_count,omitempty"`
|
UdpConnCount uint64 `protobuf:"varint,15,opt,name=udp_conn_count,json=udpConnCount,proto3" json:"udp_conn_count,omitempty"`
|
||||||
ProcessCount uint64 `protobuf:"varint,16,opt,name=process_count,json=processCount,proto3" json:"process_count,omitempty"`
|
ProcessCount uint64 `protobuf:"varint,16,opt,name=process_count,json=processCount,proto3" json:"process_count,omitempty"`
|
||||||
Temperatures []*State_SensorTemperature `protobuf:"bytes,17,rep,name=temperatures,proto3" json:"temperatures,omitempty"`
|
|
||||||
Gpu float64 `protobuf:"fixed64,18,opt,name=gpu,proto3" json:"gpu,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *State) Reset() {
|
func (x *State) Reset() {
|
||||||
@@ -324,75 +314,6 @@ func (x *State) GetProcessCount() uint64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *State) GetTemperatures() []*State_SensorTemperature {
|
|
||||||
if x != nil {
|
|
||||||
return x.Temperatures
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *State) GetGpu() float64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Gpu
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type State_SensorTemperature struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
|
||||||
Temperature float64 `protobuf:"fixed64,2,opt,name=temperature,proto3" json:"temperature,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *State_SensorTemperature) Reset() {
|
|
||||||
*x = State_SensorTemperature{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_proto_nezha_proto_msgTypes[2]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *State_SensorTemperature) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*State_SensorTemperature) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *State_SensorTemperature) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_proto_nezha_proto_msgTypes[2]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use State_SensorTemperature.ProtoReflect.Descriptor instead.
|
|
||||||
func (*State_SensorTemperature) Descriptor() ([]byte, []int) {
|
|
||||||
return file_proto_nezha_proto_rawDescGZIP(), []int{2}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *State_SensorTemperature) GetName() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Name
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *State_SensorTemperature) GetTemperature() float64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Temperature
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type Task struct {
|
type Task struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -406,7 +327,7 @@ type Task struct {
|
|||||||
func (x *Task) Reset() {
|
func (x *Task) Reset() {
|
||||||
*x = Task{}
|
*x = Task{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_proto_nezha_proto_msgTypes[3]
|
mi := &file_proto_nezha_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -419,7 +340,7 @@ func (x *Task) String() string {
|
|||||||
func (*Task) ProtoMessage() {}
|
func (*Task) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Task) ProtoReflect() protoreflect.Message {
|
func (x *Task) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_proto_nezha_proto_msgTypes[3]
|
mi := &file_proto_nezha_proto_msgTypes[2]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -432,7 +353,7 @@ func (x *Task) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Task.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Task.ProtoReflect.Descriptor instead.
|
||||||
func (*Task) Descriptor() ([]byte, []int) {
|
func (*Task) Descriptor() ([]byte, []int) {
|
||||||
return file_proto_nezha_proto_rawDescGZIP(), []int{3}
|
return file_proto_nezha_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Task) GetId() uint64 {
|
func (x *Task) GetId() uint64 {
|
||||||
@@ -471,7 +392,7 @@ type TaskResult struct {
|
|||||||
func (x *TaskResult) Reset() {
|
func (x *TaskResult) Reset() {
|
||||||
*x = TaskResult{}
|
*x = TaskResult{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_proto_nezha_proto_msgTypes[4]
|
mi := &file_proto_nezha_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -484,7 +405,7 @@ func (x *TaskResult) String() string {
|
|||||||
func (*TaskResult) ProtoMessage() {}
|
func (*TaskResult) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *TaskResult) ProtoReflect() protoreflect.Message {
|
func (x *TaskResult) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_proto_nezha_proto_msgTypes[4]
|
mi := &file_proto_nezha_proto_msgTypes[3]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -497,7 +418,7 @@ func (x *TaskResult) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use TaskResult.ProtoReflect.Descriptor instead.
|
// Deprecated: Use TaskResult.ProtoReflect.Descriptor instead.
|
||||||
func (*TaskResult) Descriptor() ([]byte, []int) {
|
func (*TaskResult) Descriptor() ([]byte, []int) {
|
||||||
return file_proto_nezha_proto_rawDescGZIP(), []int{4}
|
return file_proto_nezha_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TaskResult) GetId() uint64 {
|
func (x *TaskResult) GetId() uint64 {
|
||||||
@@ -546,7 +467,7 @@ type Receipt struct {
|
|||||||
func (x *Receipt) Reset() {
|
func (x *Receipt) Reset() {
|
||||||
*x = Receipt{}
|
*x = Receipt{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_proto_nezha_proto_msgTypes[5]
|
mi := &file_proto_nezha_proto_msgTypes[4]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -559,7 +480,7 @@ func (x *Receipt) String() string {
|
|||||||
func (*Receipt) ProtoMessage() {}
|
func (*Receipt) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Receipt) ProtoReflect() protoreflect.Message {
|
func (x *Receipt) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_proto_nezha_proto_msgTypes[5]
|
mi := &file_proto_nezha_proto_msgTypes[4]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -572,7 +493,7 @@ func (x *Receipt) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Receipt.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Receipt.ProtoReflect.Descriptor instead.
|
||||||
func (*Receipt) Descriptor() ([]byte, []int) {
|
func (*Receipt) Descriptor() ([]byte, []int) {
|
||||||
return file_proto_nezha_proto_rawDescGZIP(), []int{5}
|
return file_proto_nezha_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Receipt) GetProced() bool {
|
func (x *Receipt) GetProced() bool {
|
||||||
@@ -582,113 +503,11 @@ func (x *Receipt) GetProced() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
type IOStreamData struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *IOStreamData) Reset() {
|
|
||||||
*x = IOStreamData{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_proto_nezha_proto_msgTypes[6]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *IOStreamData) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*IOStreamData) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *IOStreamData) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_proto_nezha_proto_msgTypes[6]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use IOStreamData.ProtoReflect.Descriptor instead.
|
|
||||||
func (*IOStreamData) Descriptor() ([]byte, []int) {
|
|
||||||
return file_proto_nezha_proto_rawDescGZIP(), []int{6}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *IOStreamData) GetData() []byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.Data
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GeoIP struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
|
|
||||||
CountryCode string `protobuf:"bytes,2,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIP) Reset() {
|
|
||||||
*x = GeoIP{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_proto_nezha_proto_msgTypes[7]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIP) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GeoIP) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *GeoIP) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_proto_nezha_proto_msgTypes[7]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use GeoIP.ProtoReflect.Descriptor instead.
|
|
||||||
func (*GeoIP) Descriptor() ([]byte, []int) {
|
|
||||||
return file_proto_nezha_proto_rawDescGZIP(), []int{7}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIP) GetIp() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Ip
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIP) GetCountryCode() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.CountryCode
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_proto_nezha_proto protoreflect.FileDescriptor
|
var File_proto_nezha_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_proto_nezha_proto_rawDesc = []byte{
|
var file_proto_nezha_proto_rawDesc = []byte{
|
||||||
0x0a, 0x11, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6e, 0x65, 0x7a, 0x68, 0x61, 0x2e, 0x70, 0x72,
|
0x0a, 0x11, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6e, 0x65, 0x7a, 0x68, 0x61, 0x2e, 0x70, 0x72,
|
||||||
0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf2, 0x02, 0x0a, 0x04, 0x48,
|
0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe0, 0x02, 0x0a, 0x04, 0x48,
|
||||||
0x6f, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18,
|
0x6f, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12,
|
||||||
0x29, 0x0a, 0x10, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73,
|
0x29, 0x0a, 0x10, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73,
|
||||||
@@ -710,89 +529,65 @@ var file_proto_nezha_proto_rawDesc = []byte{
|
|||||||
0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65,
|
0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65,
|
||||||
0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43,
|
0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43,
|
||||||
0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c,
|
0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xd3, 0x03,
|
||||||
0x03, 0x67, 0x70, 0x75, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x67, 0x70, 0x75, 0x22,
|
0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x01,
|
||||||
0xa9, 0x04, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x70, 0x75,
|
0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x63, 0x70, 0x75, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x65, 0x6d,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x63, 0x70, 0x75, 0x12, 0x19, 0x0a, 0x08, 0x6d,
|
0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x65, 0x6d,
|
||||||
0x65, 0x6d, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d,
|
0x55, 0x73, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x75, 0x73, 0x65,
|
||||||
0x65, 0x6d, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x77, 0x61, 0x70, 0x5f, 0x75,
|
0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x77, 0x61, 0x70, 0x55, 0x73, 0x65,
|
||||||
0x73, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x77, 0x61, 0x70, 0x55,
|
0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x05,
|
||||||
0x73, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x69, 0x73, 0x6b, 0x5f, 0x75, 0x73, 0x65, 0x64,
|
0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x55, 0x73, 0x65, 0x64, 0x12, 0x26,
|
||||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x69, 0x73, 0x6b, 0x55, 0x73, 0x65, 0x64,
|
0x0a, 0x0f, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65,
|
||||||
0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6e, 0x65, 0x74, 0x49, 0x6e, 0x54, 0x72,
|
||||||
0x66, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6e, 0x65, 0x74, 0x49, 0x6e,
|
0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x65, 0x74, 0x5f, 0x6f, 0x75,
|
||||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x6e, 0x65, 0x74, 0x5f,
|
0x74, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04,
|
||||||
0x6f, 0x75, 0x74, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01,
|
0x52, 0x0e, 0x6e, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72,
|
||||||
0x28, 0x04, 0x52, 0x0e, 0x6e, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66,
|
0x12, 0x20, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x65, 0x64,
|
||||||
0x65, 0x72, 0x12, 0x20, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65,
|
0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x6e, 0x65, 0x74, 0x49, 0x6e, 0x53, 0x70, 0x65,
|
||||||
0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x6e, 0x65, 0x74, 0x49, 0x6e, 0x53,
|
0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x65, 0x74, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x70,
|
||||||
0x70, 0x65, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x65, 0x74, 0x5f, 0x6f, 0x75, 0x74, 0x5f,
|
0x65, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6e, 0x65, 0x74, 0x4f, 0x75,
|
||||||
0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6e, 0x65, 0x74,
|
0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65,
|
||||||
0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, 0x74, 0x69,
|
0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x14,
|
||||||
0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65,
|
0x0a, 0x05, 0x6c, 0x6f, 0x61, 0x64, 0x31, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x6c,
|
||||||
0x12, 0x14, 0x0a, 0x05, 0x6c, 0x6f, 0x61, 0x64, 0x31, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52,
|
0x6f, 0x61, 0x64, 0x31, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x6f, 0x61, 0x64, 0x35, 0x18, 0x0c, 0x20,
|
||||||
0x05, 0x6c, 0x6f, 0x61, 0x64, 0x31, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x6f, 0x61, 0x64, 0x35, 0x18,
|
0x01, 0x28, 0x01, 0x52, 0x05, 0x6c, 0x6f, 0x61, 0x64, 0x35, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f,
|
||||||
0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x6c, 0x6f, 0x61, 0x64, 0x35, 0x12, 0x16, 0x0a, 0x06,
|
0x61, 0x64, 0x31, 0x35, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x6c, 0x6f, 0x61, 0x64,
|
||||||
0x6c, 0x6f, 0x61, 0x64, 0x31, 0x35, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x6c, 0x6f,
|
0x31, 0x35, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x5f, 0x63,
|
||||||
0x61, 0x64, 0x31, 0x35, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x6e,
|
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x74, 0x63, 0x70, 0x43,
|
||||||
0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x74, 0x63,
|
0x6f, 0x6e, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x75, 0x64, 0x70, 0x5f,
|
||||||
0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x75, 0x64,
|
0x63, 0x6f, 0x6e, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04,
|
||||||
0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01,
|
0x52, 0x0c, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23,
|
||||||
0x28, 0x04, 0x52, 0x0c, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
|
0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
|
||||||
0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
|
0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f,
|
||||||
0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
|
0x75, 0x6e, 0x74, 0x22, 0x3e, 0x0a, 0x04, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||||
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x42, 0x0a, 0x0c, 0x74, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61,
|
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74,
|
||||||
0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72,
|
0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
|
||||||
0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72,
|
0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64,
|
||||||
0x54, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0c, 0x74, 0x65, 0x6d,
|
0x61, 0x74, 0x61, 0x22, 0x7a, 0x0a, 0x0a, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c,
|
||||||
0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x70, 0x75,
|
0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69,
|
||||||
0x18, 0x12, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x67, 0x70, 0x75, 0x22, 0x4f, 0x0a, 0x17, 0x53,
|
0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52,
|
||||||
0x74, 0x61, 0x74, 0x65, 0x5f, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x54, 0x65, 0x6d, 0x70, 0x65,
|
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x03,
|
||||||
0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
|
0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x64,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x65,
|
0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12,
|
||||||
0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52,
|
0x1e, 0x0a, 0x0a, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x18, 0x05, 0x20,
|
||||||
0x0b, 0x74, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3e, 0x0a, 0x04,
|
0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x22,
|
||||||
0x54, 0x61, 0x73, 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
|
0x21, 0x0a, 0x07, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72,
|
||||||
0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
|
0x6f, 0x63, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x63,
|
||||||
0x28, 0x04, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61,
|
0x65, 0x64, 0x32, 0xd6, 0x01, 0x0a, 0x0c, 0x4e, 0x65, 0x7a, 0x68, 0x61, 0x53, 0x65, 0x72, 0x76,
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x7a, 0x0a, 0x0a,
|
0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x79, 0x73,
|
||||||
0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
|
0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79,
|
0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52,
|
||||||
0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14,
|
0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x10, 0x52, 0x65, 0x70, 0x6f,
|
||||||
0x0a, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x64,
|
0x72, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0b, 0x2e, 0x70,
|
||||||
0x65, 0x6c, 0x61, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01,
|
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x75, 0x63, 0x63,
|
0x6f, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x0a, 0x52,
|
||||||
0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x75,
|
0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x22, 0x21, 0x0a, 0x07, 0x52, 0x65, 0x63, 0x65,
|
0x6f, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x0e, 0x2e, 0x70,
|
||||||
0x69, 0x70, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x64, 0x18, 0x01, 0x20,
|
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x22, 0x00, 0x12, 0x2b,
|
||||||
0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x64, 0x22, 0x22, 0x0a, 0x0c, 0x49,
|
0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0b, 0x2e,
|
||||||
0x4f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22,
|
0x74, 0x6f, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x22, 0x00, 0x30, 0x01, 0x42, 0x09, 0x5a, 0x07, 0x2e,
|
||||||
0x3a, 0x0a, 0x05, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01,
|
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e,
|
|
||||||
0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
|
|
||||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x32, 0xbf, 0x02, 0x0a, 0x0c,
|
|
||||||
0x4e, 0x65, 0x7a, 0x68, 0x61, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x11,
|
|
||||||
0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74,
|
|
||||||
0x65, 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a,
|
|
||||||
0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x22,
|
|
||||||
0x00, 0x12, 0x31, 0x0a, 0x10, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65,
|
|
||||||
0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x6f,
|
|
||||||
0x73, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x65, 0x69,
|
|
||||||
0x70, 0x74, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x0a, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x61,
|
|
||||||
0x73, 0x6b, 0x12, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52,
|
|
||||||
0x65, 0x73, 0x75, 0x6c, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
|
|
||||||
0x63, 0x65, 0x69, 0x70, 0x74, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65,
|
|
||||||
0x73, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48,
|
|
||||||
0x6f, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x61, 0x73, 0x6b,
|
|
||||||
0x22, 0x00, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x08, 0x49, 0x4f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
|
|
||||||
0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x4f, 0x53, 0x74, 0x72, 0x65, 0x61,
|
|
||||||
0x6d, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x4f,
|
|
||||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01,
|
|
||||||
0x12, 0x2b, 0x0a, 0x0b, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x12,
|
|
||||||
0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x1a, 0x0c, 0x2e,
|
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x22, 0x00, 0x42, 0x09, 0x5a,
|
|
||||||
0x07, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -807,36 +602,28 @@ func file_proto_nezha_proto_rawDescGZIP() []byte {
|
|||||||
return file_proto_nezha_proto_rawDescData
|
return file_proto_nezha_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_proto_nezha_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
var file_proto_nezha_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
var file_proto_nezha_proto_goTypes = []interface{}{
|
var file_proto_nezha_proto_goTypes = []interface{}{
|
||||||
(*Host)(nil), // 0: proto.Host
|
(*Host)(nil), // 0: proto.Host
|
||||||
(*State)(nil), // 1: proto.State
|
(*State)(nil), // 1: proto.State
|
||||||
(*State_SensorTemperature)(nil), // 2: proto.State_SensorTemperature
|
(*Task)(nil), // 2: proto.Task
|
||||||
(*Task)(nil), // 3: proto.Task
|
(*TaskResult)(nil), // 3: proto.TaskResult
|
||||||
(*TaskResult)(nil), // 4: proto.TaskResult
|
(*Receipt)(nil), // 4: proto.Receipt
|
||||||
(*Receipt)(nil), // 5: proto.Receipt
|
|
||||||
(*IOStreamData)(nil), // 6: proto.IOStreamData
|
|
||||||
(*GeoIP)(nil), // 7: proto.GeoIP
|
|
||||||
}
|
}
|
||||||
var file_proto_nezha_proto_depIdxs = []int32{
|
var file_proto_nezha_proto_depIdxs = []int32{
|
||||||
2, // 0: proto.State.temperatures:type_name -> proto.State_SensorTemperature
|
1, // 0: proto.NezhaService.ReportSystemState:input_type -> proto.State
|
||||||
1, // 1: proto.NezhaService.ReportSystemState:input_type -> proto.State
|
0, // 1: proto.NezhaService.ReportSystemInfo:input_type -> proto.Host
|
||||||
0, // 2: proto.NezhaService.ReportSystemInfo:input_type -> proto.Host
|
3, // 2: proto.NezhaService.ReportTask:input_type -> proto.TaskResult
|
||||||
4, // 3: proto.NezhaService.ReportTask:input_type -> proto.TaskResult
|
0, // 3: proto.NezhaService.RequestTask:input_type -> proto.Host
|
||||||
0, // 4: proto.NezhaService.RequestTask:input_type -> proto.Host
|
4, // 4: proto.NezhaService.ReportSystemState:output_type -> proto.Receipt
|
||||||
6, // 5: proto.NezhaService.IOStream:input_type -> proto.IOStreamData
|
4, // 5: proto.NezhaService.ReportSystemInfo:output_type -> proto.Receipt
|
||||||
7, // 6: proto.NezhaService.LookupGeoIP:input_type -> proto.GeoIP
|
4, // 6: proto.NezhaService.ReportTask:output_type -> proto.Receipt
|
||||||
5, // 7: proto.NezhaService.ReportSystemState:output_type -> proto.Receipt
|
2, // 7: proto.NezhaService.RequestTask:output_type -> proto.Task
|
||||||
5, // 8: proto.NezhaService.ReportSystemInfo:output_type -> proto.Receipt
|
4, // [4:8] is the sub-list for method output_type
|
||||||
5, // 9: proto.NezhaService.ReportTask:output_type -> proto.Receipt
|
0, // [0:4] is the sub-list for method input_type
|
||||||
3, // 10: proto.NezhaService.RequestTask:output_type -> proto.Task
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
6, // 11: proto.NezhaService.IOStream:output_type -> proto.IOStreamData
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
7, // 12: proto.NezhaService.LookupGeoIP:output_type -> proto.GeoIP
|
0, // [0:0] is the sub-list for field type_name
|
||||||
7, // [7:13] is the sub-list for method output_type
|
|
||||||
1, // [1:7] is the sub-list for method input_type
|
|
||||||
1, // [1:1] is the sub-list for extension type_name
|
|
||||||
1, // [1:1] is the sub-list for extension extendee
|
|
||||||
0, // [0:1] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_proto_nezha_proto_init() }
|
func init() { file_proto_nezha_proto_init() }
|
||||||
@@ -870,18 +657,6 @@ func file_proto_nezha_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_proto_nezha_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
file_proto_nezha_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*State_SensorTemperature); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_proto_nezha_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Task); i {
|
switch v := v.(*Task); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -893,7 +668,7 @@ func file_proto_nezha_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_proto_nezha_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
file_proto_nezha_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*TaskResult); i {
|
switch v := v.(*TaskResult); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -905,7 +680,7 @@ func file_proto_nezha_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_proto_nezha_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
file_proto_nezha_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*Receipt); i {
|
switch v := v.(*Receipt); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -917,30 +692,6 @@ func file_proto_nezha_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_proto_nezha_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*IOStreamData); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_proto_nezha_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*GeoIP); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
@@ -948,7 +699,7 @@ func file_proto_nezha_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_proto_nezha_proto_rawDesc,
|
RawDescriptor: file_proto_nezha_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 8,
|
NumMessages: 5,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-20
@@ -8,8 +8,6 @@ service NezhaService {
|
|||||||
rpc ReportSystemInfo(Host)returns(Receipt){}
|
rpc ReportSystemInfo(Host)returns(Receipt){}
|
||||||
rpc ReportTask(TaskResult)returns(Receipt){}
|
rpc ReportTask(TaskResult)returns(Receipt){}
|
||||||
rpc RequestTask(Host)returns(stream Task){}
|
rpc RequestTask(Host)returns(stream Task){}
|
||||||
rpc IOStream(stream IOStreamData)returns(stream IOStreamData){}
|
|
||||||
rpc LookupGeoIP(GeoIP)returns(GeoIP){}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Host {
|
message Host {
|
||||||
@@ -23,9 +21,8 @@ message Host {
|
|||||||
string virtualization = 8;
|
string virtualization = 8;
|
||||||
uint64 boot_time = 9;
|
uint64 boot_time = 9;
|
||||||
string ip = 10;
|
string ip = 10;
|
||||||
string country_code = 11; // deprecated
|
string country_code = 11;
|
||||||
string version = 12;
|
string version = 12;
|
||||||
repeated string gpu = 13;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message State {
|
message State {
|
||||||
@@ -44,13 +41,6 @@ message State {
|
|||||||
uint64 tcp_conn_count = 14;
|
uint64 tcp_conn_count = 14;
|
||||||
uint64 udp_conn_count = 15;
|
uint64 udp_conn_count = 15;
|
||||||
uint64 process_count = 16;
|
uint64 process_count = 16;
|
||||||
repeated State_SensorTemperature temperatures = 17;
|
|
||||||
double gpu = 18;
|
|
||||||
}
|
|
||||||
|
|
||||||
message State_SensorTemperature {
|
|
||||||
string name = 1;
|
|
||||||
double temperature = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Task {
|
message Task {
|
||||||
@@ -70,12 +60,3 @@ message TaskResult {
|
|||||||
message Receipt{
|
message Receipt{
|
||||||
bool proced = 1;
|
bool proced = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message IOStreamData {
|
|
||||||
bytes data = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GeoIP {
|
|
||||||
string ip = 1;
|
|
||||||
string country_code = 2;
|
|
||||||
}
|
|
||||||
+1
-107
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.3.0
|
// - protoc-gen-go-grpc v1.3.0
|
||||||
// - protoc v5.26.1
|
// - protoc v3.21.12
|
||||||
// source: proto/nezha.proto
|
// source: proto/nezha.proto
|
||||||
|
|
||||||
package proto
|
package proto
|
||||||
@@ -23,8 +23,6 @@ const (
|
|||||||
NezhaService_ReportSystemInfo_FullMethodName = "/proto.NezhaService/ReportSystemInfo"
|
NezhaService_ReportSystemInfo_FullMethodName = "/proto.NezhaService/ReportSystemInfo"
|
||||||
NezhaService_ReportTask_FullMethodName = "/proto.NezhaService/ReportTask"
|
NezhaService_ReportTask_FullMethodName = "/proto.NezhaService/ReportTask"
|
||||||
NezhaService_RequestTask_FullMethodName = "/proto.NezhaService/RequestTask"
|
NezhaService_RequestTask_FullMethodName = "/proto.NezhaService/RequestTask"
|
||||||
NezhaService_IOStream_FullMethodName = "/proto.NezhaService/IOStream"
|
|
||||||
NezhaService_LookupGeoIP_FullMethodName = "/proto.NezhaService/LookupGeoIP"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NezhaServiceClient is the client API for NezhaService service.
|
// NezhaServiceClient is the client API for NezhaService service.
|
||||||
@@ -35,8 +33,6 @@ type NezhaServiceClient interface {
|
|||||||
ReportSystemInfo(ctx context.Context, in *Host, opts ...grpc.CallOption) (*Receipt, error)
|
ReportSystemInfo(ctx context.Context, in *Host, opts ...grpc.CallOption) (*Receipt, error)
|
||||||
ReportTask(ctx context.Context, in *TaskResult, opts ...grpc.CallOption) (*Receipt, error)
|
ReportTask(ctx context.Context, in *TaskResult, opts ...grpc.CallOption) (*Receipt, error)
|
||||||
RequestTask(ctx context.Context, in *Host, opts ...grpc.CallOption) (NezhaService_RequestTaskClient, error)
|
RequestTask(ctx context.Context, in *Host, opts ...grpc.CallOption) (NezhaService_RequestTaskClient, error)
|
||||||
IOStream(ctx context.Context, opts ...grpc.CallOption) (NezhaService_IOStreamClient, error)
|
|
||||||
LookupGeoIP(ctx context.Context, in *GeoIP, opts ...grpc.CallOption) (*GeoIP, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type nezhaServiceClient struct {
|
type nezhaServiceClient struct {
|
||||||
@@ -106,46 +102,6 @@ func (x *nezhaServiceRequestTaskClient) Recv() (*Task, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *nezhaServiceClient) IOStream(ctx context.Context, opts ...grpc.CallOption) (NezhaService_IOStreamClient, error) {
|
|
||||||
stream, err := c.cc.NewStream(ctx, &NezhaService_ServiceDesc.Streams[1], NezhaService_IOStream_FullMethodName, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
x := &nezhaServiceIOStreamClient{stream}
|
|
||||||
return x, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type NezhaService_IOStreamClient interface {
|
|
||||||
Send(*IOStreamData) error
|
|
||||||
Recv() (*IOStreamData, error)
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type nezhaServiceIOStreamClient struct {
|
|
||||||
grpc.ClientStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *nezhaServiceIOStreamClient) Send(m *IOStreamData) error {
|
|
||||||
return x.ClientStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *nezhaServiceIOStreamClient) Recv() (*IOStreamData, error) {
|
|
||||||
m := new(IOStreamData)
|
|
||||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nezhaServiceClient) LookupGeoIP(ctx context.Context, in *GeoIP, opts ...grpc.CallOption) (*GeoIP, error) {
|
|
||||||
out := new(GeoIP)
|
|
||||||
err := c.cc.Invoke(ctx, NezhaService_LookupGeoIP_FullMethodName, in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NezhaServiceServer is the server API for NezhaService service.
|
// NezhaServiceServer is the server API for NezhaService service.
|
||||||
// All implementations should embed UnimplementedNezhaServiceServer
|
// All implementations should embed UnimplementedNezhaServiceServer
|
||||||
// for forward compatibility
|
// for forward compatibility
|
||||||
@@ -154,8 +110,6 @@ type NezhaServiceServer interface {
|
|||||||
ReportSystemInfo(context.Context, *Host) (*Receipt, error)
|
ReportSystemInfo(context.Context, *Host) (*Receipt, error)
|
||||||
ReportTask(context.Context, *TaskResult) (*Receipt, error)
|
ReportTask(context.Context, *TaskResult) (*Receipt, error)
|
||||||
RequestTask(*Host, NezhaService_RequestTaskServer) error
|
RequestTask(*Host, NezhaService_RequestTaskServer) error
|
||||||
IOStream(NezhaService_IOStreamServer) error
|
|
||||||
LookupGeoIP(context.Context, *GeoIP) (*GeoIP, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnimplementedNezhaServiceServer should be embedded to have forward compatible implementations.
|
// UnimplementedNezhaServiceServer should be embedded to have forward compatible implementations.
|
||||||
@@ -174,12 +128,6 @@ func (UnimplementedNezhaServiceServer) ReportTask(context.Context, *TaskResult)
|
|||||||
func (UnimplementedNezhaServiceServer) RequestTask(*Host, NezhaService_RequestTaskServer) error {
|
func (UnimplementedNezhaServiceServer) RequestTask(*Host, NezhaService_RequestTaskServer) error {
|
||||||
return status.Errorf(codes.Unimplemented, "method RequestTask not implemented")
|
return status.Errorf(codes.Unimplemented, "method RequestTask not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedNezhaServiceServer) IOStream(NezhaService_IOStreamServer) error {
|
|
||||||
return status.Errorf(codes.Unimplemented, "method IOStream not implemented")
|
|
||||||
}
|
|
||||||
func (UnimplementedNezhaServiceServer) LookupGeoIP(context.Context, *GeoIP) (*GeoIP, error) {
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method LookupGeoIP not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnsafeNezhaServiceServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeNezhaServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
// Use of this interface is not recommended, as added methods to NezhaServiceServer will
|
// Use of this interface is not recommended, as added methods to NezhaServiceServer will
|
||||||
@@ -267,50 +215,6 @@ func (x *nezhaServiceRequestTaskServer) Send(m *Task) error {
|
|||||||
return x.ServerStream.SendMsg(m)
|
return x.ServerStream.SendMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _NezhaService_IOStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
|
||||||
return srv.(NezhaServiceServer).IOStream(&nezhaServiceIOStreamServer{stream})
|
|
||||||
}
|
|
||||||
|
|
||||||
type NezhaService_IOStreamServer interface {
|
|
||||||
Send(*IOStreamData) error
|
|
||||||
Recv() (*IOStreamData, error)
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
type nezhaServiceIOStreamServer struct {
|
|
||||||
grpc.ServerStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *nezhaServiceIOStreamServer) Send(m *IOStreamData) error {
|
|
||||||
return x.ServerStream.SendMsg(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *nezhaServiceIOStreamServer) Recv() (*IOStreamData, error) {
|
|
||||||
m := new(IOStreamData)
|
|
||||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func _NezhaService_LookupGeoIP_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(GeoIP)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(NezhaServiceServer).LookupGeoIP(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: NezhaService_LookupGeoIP_FullMethodName,
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(NezhaServiceServer).LookupGeoIP(ctx, req.(*GeoIP))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NezhaService_ServiceDesc is the grpc.ServiceDesc for NezhaService service.
|
// NezhaService_ServiceDesc is the grpc.ServiceDesc for NezhaService service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@@ -330,10 +234,6 @@ var NezhaService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "ReportTask",
|
MethodName: "ReportTask",
|
||||||
Handler: _NezhaService_ReportTask_Handler,
|
Handler: _NezhaService_ReportTask_Handler,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MethodName: "LookupGeoIP",
|
|
||||||
Handler: _NezhaService_LookupGeoIP_Handler,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{
|
Streams: []grpc.StreamDesc{
|
||||||
{
|
{
|
||||||
@@ -341,12 +241,6 @@ var NezhaService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
Handler: _NezhaService_RequestTask_Handler,
|
Handler: _NezhaService_RequestTask_Handler,
|
||||||
ServerStreams: true,
|
ServerStreams: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
StreamName: "IOStream",
|
|
||||||
Handler: _NezhaService_IOStream_Handler,
|
|
||||||
ServerStreams: true,
|
|
||||||
ClientStreams: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Metadata: "proto/nezha.proto",
|
Metadata: "proto/nezha.proto",
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+12
-36
@@ -32,10 +32,10 @@ other = "Logout"
|
|||||||
other = "Login"
|
other = "Login"
|
||||||
|
|
||||||
[ConfirmLogout]
|
[ConfirmLogout]
|
||||||
other = "Do you want to Logout?"
|
other = "Confirm Logout?"
|
||||||
|
|
||||||
[AfterLoggingOutYouHaveToLoginAgain]
|
[AfterLoggingOutYouHaveToLoginAgain]
|
||||||
other = "You need to Login again to continue"
|
other = "You need to login again after logout to continue"
|
||||||
|
|
||||||
[Cancel]
|
[Cancel]
|
||||||
other = "Cancel"
|
other = "Cancel"
|
||||||
@@ -227,7 +227,7 @@ other = "Secret"
|
|||||||
other = "Note"
|
other = "Note"
|
||||||
|
|
||||||
[LinuxOneKeyInstall]
|
[LinuxOneKeyInstall]
|
||||||
other = "Linux One-Command Install"
|
other = "Linux One-Key Install"
|
||||||
|
|
||||||
[NoDomainAlert]
|
[NoDomainAlert]
|
||||||
other = "Set CDN bypassed Domain/IP in setting before using this function"
|
other = "Set CDN bypassed Domain/IP in setting before using this function"
|
||||||
@@ -257,7 +257,7 @@ other = "Execute by Trigger"
|
|||||||
other = "Delete Scheduled Task"
|
other = "Delete Scheduled Task"
|
||||||
|
|
||||||
[ConfirmToDeleteThisScheduledTask]
|
[ConfirmToDeleteThisScheduledTask]
|
||||||
other = "Are you sure you want to Delete?"
|
other = "Confirm Delete?"
|
||||||
|
|
||||||
[AccessDenied]
|
[AccessDenied]
|
||||||
other = "Access Denied"
|
other = "Access Denied"
|
||||||
@@ -293,7 +293,7 @@ other = "Delete Notification Method"
|
|||||||
other = "Confirm to Delete This Notification Method?"
|
other = "Confirm to Delete This Notification Method?"
|
||||||
|
|
||||||
[ForceUpdate]
|
[ForceUpdate]
|
||||||
other = "Force to Update"
|
other = "Force Update"
|
||||||
|
|
||||||
[SelectAll]
|
[SelectAll]
|
||||||
other = "Select All"
|
other = "Select All"
|
||||||
@@ -302,7 +302,7 @@ other = "Select All"
|
|||||||
other = "Version"
|
other = "Version"
|
||||||
|
|
||||||
[OneKeyInstall]
|
[OneKeyInstall]
|
||||||
other = "One-Command Install"
|
other = "One-Key Install"
|
||||||
|
|
||||||
[ClickToCopy]
|
[ClickToCopy]
|
||||||
other = "Click To Copy"
|
other = "Click To Copy"
|
||||||
@@ -331,9 +331,6 @@ other = "Frontend Theme"
|
|||||||
[CustomCodes]
|
[CustomCodes]
|
||||||
other = "Custom Codes (Style and Script)"
|
other = "Custom Codes (Style and Script)"
|
||||||
|
|
||||||
[CustomCodesDashboard]
|
|
||||||
other = "Custom Codes for Dashboard"
|
|
||||||
|
|
||||||
[AccessPassword]
|
[AccessPassword]
|
||||||
other = "Frontend Access Password"
|
other = "Frontend Access Password"
|
||||||
|
|
||||||
@@ -401,7 +398,7 @@ other = "Virtualization"
|
|||||||
other = "Swap"
|
other = "Swap"
|
||||||
|
|
||||||
[NetTransfer]
|
[NetTransfer]
|
||||||
other = "Usage"
|
other = "Transfer"
|
||||||
|
|
||||||
[Load]
|
[Load]
|
||||||
other = "Load"
|
other = "Load"
|
||||||
@@ -422,7 +419,7 @@ other = "Last Active"
|
|||||||
other = "Version"
|
other = "Version"
|
||||||
|
|
||||||
[NetSpeed]
|
[NetSpeed]
|
||||||
other = "NIC"
|
other = "Speed"
|
||||||
|
|
||||||
[Uptime]
|
[Uptime]
|
||||||
other = "Uptime"
|
other = "Uptime"
|
||||||
@@ -476,7 +473,7 @@ other = "Next check"
|
|||||||
other = "Current Usage"
|
other = "Current Usage"
|
||||||
|
|
||||||
[VerifyPassword]
|
[VerifyPassword]
|
||||||
other = "Please enter your password"
|
other = "Verify Password"
|
||||||
|
|
||||||
[LightMode]
|
[LightMode]
|
||||||
other = "Light Mode"
|
other = "Light Mode"
|
||||||
@@ -485,7 +482,7 @@ other = "Light Mode"
|
|||||||
other = "Dark Mode"
|
other = "Dark Mode"
|
||||||
|
|
||||||
[FollowSystem]
|
[FollowSystem]
|
||||||
other = "System Auto"
|
other = "Follow System"
|
||||||
|
|
||||||
[GridLayout]
|
[GridLayout]
|
||||||
other = "Grid Layout"
|
other = "Grid Layout"
|
||||||
@@ -622,18 +619,9 @@ other = "Enable Show in Service"
|
|||||||
[EnableDDNS]
|
[EnableDDNS]
|
||||||
other = "Enable DDNS"
|
other = "Enable DDNS"
|
||||||
|
|
||||||
[EnableIPv4]
|
|
||||||
other = "Enable DDNS IPv4"
|
|
||||||
|
|
||||||
[EnableIpv6]
|
|
||||||
other = "Enable DDNS IPv6"
|
|
||||||
|
|
||||||
[DDNSDomain]
|
[DDNSDomain]
|
||||||
other = "DDNS Domain"
|
other = "DDNS Domain"
|
||||||
|
|
||||||
[DDNSProfile]
|
|
||||||
other = "DDNS Profile Name"
|
|
||||||
|
|
||||||
[Feature]
|
[Feature]
|
||||||
other = "Feature"
|
other = "Feature"
|
||||||
|
|
||||||
@@ -641,19 +629,7 @@ other = "Feature"
|
|||||||
other = "Template"
|
other = "Template"
|
||||||
|
|
||||||
[Stat]
|
[Stat]
|
||||||
other = "Asset"
|
other = "Stat"
|
||||||
|
|
||||||
[Temperature]
|
|
||||||
other = "Temperature"
|
|
||||||
|
|
||||||
[DisableSwitchTemplateInFrontend]
|
[DisableSwitchTemplateInFrontend]
|
||||||
other = "Disable Switch Template in Frontend"
|
other = "Disable Switch Template in Frontend"
|
||||||
|
|
||||||
[ServersOnWorldMap]
|
|
||||||
other = "Servers On World Map"
|
|
||||||
|
|
||||||
[NAT]
|
|
||||||
other = "NAT"
|
|
||||||
|
|
||||||
[NetworkSpiterList]
|
|
||||||
other = "Network Monitor"
|
|
||||||
Vendored
+1
-25
@@ -331,9 +331,6 @@ other = "Tema de Frontend"
|
|||||||
[CustomCodes]
|
[CustomCodes]
|
||||||
other = "Códigos Personalizados (Incluye style y script)"
|
other = "Códigos Personalizados (Incluye style y script)"
|
||||||
|
|
||||||
[CustomCodesDashboard]
|
|
||||||
other = "Custom Codes for Dashboard"
|
|
||||||
|
|
||||||
[AccessPassword]
|
[AccessPassword]
|
||||||
other = "Contraseña de Acceso al Frontend"
|
other = "Contraseña de Acceso al Frontend"
|
||||||
|
|
||||||
@@ -622,18 +619,9 @@ other = "Mostrar en servicio"
|
|||||||
[EnableDDNS]
|
[EnableDDNS]
|
||||||
other = "Habilitar DDNS"
|
other = "Habilitar DDNS"
|
||||||
|
|
||||||
[EnableIPv4]
|
|
||||||
other = "Habilitar DDNS IPv4"
|
|
||||||
|
|
||||||
[EnableIpv6]
|
|
||||||
other = "Habilitar DDNS IPv6"
|
|
||||||
|
|
||||||
[DDNSDomain]
|
[DDNSDomain]
|
||||||
other = "Dominio DDNS"
|
other = "Dominio DDNS"
|
||||||
|
|
||||||
[DDNSProfile]
|
|
||||||
other = "Nombre del perfil de DDNS"
|
|
||||||
|
|
||||||
[Feature]
|
[Feature]
|
||||||
other = "Característica"
|
other = "Característica"
|
||||||
|
|
||||||
@@ -643,17 +631,5 @@ other = "Plantilla"
|
|||||||
[Stat]
|
[Stat]
|
||||||
other = "Stat"
|
other = "Stat"
|
||||||
|
|
||||||
[Temperature]
|
|
||||||
other = "Temperatura"
|
|
||||||
|
|
||||||
[DisableSwitchTemplateInFrontend]
|
[DisableSwitchTemplateInFrontend]
|
||||||
other = "Deshabilitar Cambio de Plantilla en Frontend"
|
other = "Deshabilitar Cambio de Plantilla en Frontend"
|
||||||
|
|
||||||
[ServersOnWorldMap]
|
|
||||||
other = "Servidores en el mapa mundial"
|
|
||||||
|
|
||||||
[NAT]
|
|
||||||
other = "NAT"
|
|
||||||
|
|
||||||
[NetworkSpiterList]
|
|
||||||
other = "Red Monitor"
|
|
||||||
Vendored
-24
@@ -331,9 +331,6 @@ other = "前台界面主题"
|
|||||||
[CustomCodes]
|
[CustomCodes]
|
||||||
other = "自定义代码(包括 style 和 script)"
|
other = "自定义代码(包括 style 和 script)"
|
||||||
|
|
||||||
[CustomCodesDashboard]
|
|
||||||
other = "Custom Codes for Dashboard"
|
|
||||||
|
|
||||||
[AccessPassword]
|
[AccessPassword]
|
||||||
other = "前台访问密码"
|
other = "前台访问密码"
|
||||||
|
|
||||||
@@ -622,18 +619,9 @@ other = "在服务中显示"
|
|||||||
[EnableDDNS]
|
[EnableDDNS]
|
||||||
other = "启用DDNS"
|
other = "启用DDNS"
|
||||||
|
|
||||||
[EnableIPv4]
|
|
||||||
other = "启用DDNS IPv4"
|
|
||||||
|
|
||||||
[EnableIpv6]
|
|
||||||
other = "启用DDNS IPv6"
|
|
||||||
|
|
||||||
[DDNSDomain]
|
[DDNSDomain]
|
||||||
other = "DDNS域名"
|
other = "DDNS域名"
|
||||||
|
|
||||||
[DDNSProfile]
|
|
||||||
other = "DDNS配置名"
|
|
||||||
|
|
||||||
[Feature]
|
[Feature]
|
||||||
other = "功能"
|
other = "功能"
|
||||||
|
|
||||||
@@ -643,17 +631,5 @@ other = "主题"
|
|||||||
[Stat]
|
[Stat]
|
||||||
other = "信息"
|
other = "信息"
|
||||||
|
|
||||||
[Temperature]
|
|
||||||
other = "温度"
|
|
||||||
|
|
||||||
[DisableSwitchTemplateInFrontend]
|
[DisableSwitchTemplateInFrontend]
|
||||||
other = "禁止前台切换模板"
|
other = "禁止前台切换模板"
|
||||||
|
|
||||||
[ServersOnWorldMap]
|
|
||||||
other = "服务器世界分布图"
|
|
||||||
|
|
||||||
[NAT]
|
|
||||||
other = "内网穿透"
|
|
||||||
|
|
||||||
[NetworkSpiterList]
|
|
||||||
other = "网络监控"
|
|
||||||
|
|||||||
Vendored
-24
@@ -331,9 +331,6 @@ other = "前台界面主題"
|
|||||||
[CustomCodes]
|
[CustomCodes]
|
||||||
other = "自定義代碼(包括 style 和 script)"
|
other = "自定義代碼(包括 style 和 script)"
|
||||||
|
|
||||||
[CustomCodesDashboard]
|
|
||||||
other = "Custom Codes for Dashboard"
|
|
||||||
|
|
||||||
[AccessPassword]
|
[AccessPassword]
|
||||||
other = "前台訪問密碼"
|
other = "前台訪問密碼"
|
||||||
|
|
||||||
@@ -622,18 +619,9 @@ other = "在服務中顯示"
|
|||||||
[EnableDDNS]
|
[EnableDDNS]
|
||||||
other = "啟用DDNS"
|
other = "啟用DDNS"
|
||||||
|
|
||||||
[EnableIPv4]
|
|
||||||
other = "啟用DDNS IPv4"
|
|
||||||
|
|
||||||
[EnableIpv6]
|
|
||||||
other = "啟用DDNS IPv6"
|
|
||||||
|
|
||||||
[DDNSDomain]
|
[DDNSDomain]
|
||||||
other = "DDNS網域"
|
other = "DDNS網域"
|
||||||
|
|
||||||
[DDNSProfile]
|
|
||||||
other = "DDNS設定名"
|
|
||||||
|
|
||||||
[Feature]
|
[Feature]
|
||||||
other = "功能"
|
other = "功能"
|
||||||
|
|
||||||
@@ -643,17 +631,5 @@ other = "主題"
|
|||||||
[Stat]
|
[Stat]
|
||||||
other = "信息"
|
other = "信息"
|
||||||
|
|
||||||
[Temperature]
|
|
||||||
other = "溫度"
|
|
||||||
|
|
||||||
[DisableSwitchTemplateInFrontend]
|
[DisableSwitchTemplateInFrontend]
|
||||||
other = "禁止前台切換主題"
|
other = "禁止前台切換主題"
|
||||||
|
|
||||||
[ServersOnWorldMap]
|
|
||||||
other = "伺服器世界分布圖"
|
|
||||||
|
|
||||||
[NAT]
|
|
||||||
other = "NAT"
|
|
||||||
|
|
||||||
[NetworkSpiterList]
|
|
||||||
other = "網絡監控"
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
.ui.container {
|
|
||||||
width: 95vw !important;
|
|
||||||
max-width: 1680px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
html[nz-theme='dark'] {
|
|
||||||
body {
|
|
||||||
background-color: #121212 !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.menu {
|
|
||||||
background-color: #282828 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.menu * {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.accordion {
|
|
||||||
background-color: #282828 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.accordion .title {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.card {
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.description {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.popup {
|
|
||||||
background-color: #575757 !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.table {
|
|
||||||
background-color: #282828 !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui thead th {
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.buttons .button {
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.modal {
|
|
||||||
background-color: #282828 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.modal * {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea,
|
|
||||||
input,
|
|
||||||
select,
|
|
||||||
.dropdown {
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.message {
|
|
||||||
background-color: unset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.dropdown .menu {
|
|
||||||
background-color: #575757 !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.modal>.header {
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.modal>.content {
|
|
||||||
background-color: #282828 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.modal>.actions {
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#alert {
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.form .field>label {
|
|
||||||
color: unset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.segment {
|
|
||||||
background-color: #3f3f3f !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.segment textarea,
|
|
||||||
input,
|
|
||||||
select,
|
|
||||||
.dropdown {
|
|
||||||
background-color: #575757 !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
form label {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.inverted.segment {
|
|
||||||
background-color: #121212 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.inverted.segment * {
|
|
||||||
color: #8b8b8b !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu .dropdown {
|
|
||||||
background-color: #282828 !important;
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.menu .ui.dropdown .menu>.item {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login .ui.message{
|
|
||||||
color: #8b8b8b !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -91,7 +91,6 @@ function showFormModal(modelSelector, formID, URL, getData) {
|
|||||||
item.name.endsWith("_id") ||
|
item.name.endsWith("_id") ||
|
||||||
item.name === "id" ||
|
item.name === "id" ||
|
||||||
item.name === "ID" ||
|
item.name === "ID" ||
|
||||||
item.name === "ServerID" ||
|
|
||||||
item.name === "RequestType" ||
|
item.name === "RequestType" ||
|
||||||
item.name === "RequestMethod" ||
|
item.name === "RequestMethod" ||
|
||||||
item.name === "TriggerMode" ||
|
item.name === "TriggerMode" ||
|
||||||
@@ -256,28 +255,6 @@ function addOrEditNotification(notification) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addOrEditNAT(nat) {
|
|
||||||
const modal = $(".nat.modal");
|
|
||||||
modal.children(".header").text((nat ? LANG.Edit : LANG.Add));
|
|
||||||
modal
|
|
||||||
.find(".nezha-primary-btn.button")
|
|
||||||
.html(
|
|
||||||
nat
|
|
||||||
? LANG.Edit + '<i class="edit icon"></i>'
|
|
||||||
: LANG.Add + '<i class="add icon"></i>'
|
|
||||||
);
|
|
||||||
modal.find("input[name=ID]").val(nat ? nat.ID : null);
|
|
||||||
modal.find("input[name=ServerID]").val(nat ? nat.ServerID : null);
|
|
||||||
modal.find("input[name=Name]").val(nat ? nat.Name : null);
|
|
||||||
modal.find("input[name=Host]").val(nat ? nat.Host : null);
|
|
||||||
modal.find("input[name=Domain]").val(nat ? nat.Domain : null);
|
|
||||||
showFormModal(
|
|
||||||
".nat.modal",
|
|
||||||
"#natForm",
|
|
||||||
"/api/nat"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function connectToServer(id) {
|
function connectToServer(id) {
|
||||||
post('/terminal', { Host: window.location.host, Protocol: window.location.protocol, ID: id })
|
post('/terminal', { Host: window.location.host, Protocol: window.location.protocol, ID: id })
|
||||||
}
|
}
|
||||||
@@ -326,7 +303,6 @@ function addOrEditServer(server, conf) {
|
|||||||
modal.find("input[name=name]").val(server ? server.Name : null);
|
modal.find("input[name=name]").val(server ? server.Name : null);
|
||||||
modal.find("input[name=Tag]").val(server ? server.Tag : null);
|
modal.find("input[name=Tag]").val(server ? server.Tag : null);
|
||||||
modal.find("input[name=DDNSDomain]").val(server ? server.DDNSDomain : null);
|
modal.find("input[name=DDNSDomain]").val(server ? server.DDNSDomain : null);
|
||||||
modal.find("input[name=DDNSProfile]").val(server ? server.DDNSProfile : null);
|
|
||||||
modal
|
modal
|
||||||
.find("input[name=DisplayIndex]")
|
.find("input[name=DisplayIndex]")
|
||||||
.val(server ? server.DisplayIndex : null);
|
.val(server ? server.DisplayIndex : null);
|
||||||
@@ -351,16 +327,6 @@ function addOrEditServer(server, conf) {
|
|||||||
} else {
|
} else {
|
||||||
modal.find(".ui.enableddns.checkbox").checkbox("set unchecked");
|
modal.find(".ui.enableddns.checkbox").checkbox("set unchecked");
|
||||||
}
|
}
|
||||||
if (server && server.EnableIPv4) {
|
|
||||||
modal.find(".ui.enableipv4.checkbox").checkbox("set checked");
|
|
||||||
} else {
|
|
||||||
modal.find(".ui.enableipv4.checkbox").checkbox("set unchecked");
|
|
||||||
}
|
|
||||||
if (server && server.EnableIpv6) {
|
|
||||||
modal.find(".ui.enableipv6.checkbox").checkbox("set checked");
|
|
||||||
} else {
|
|
||||||
modal.find(".ui.enableipv6.checkbox").checkbox("set unchecked");
|
|
||||||
}
|
|
||||||
showFormModal(".server.modal", "#serverForm", "/api/server");
|
showFormModal(".server.modal", "#serverForm", "/api/server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+60
-65
@@ -1,54 +1,54 @@
|
|||||||
/* 屏幕适配 */
|
/* 屏幕适配 */
|
||||||
@media only screen and (min-width:1200px) {
|
@media only screen and (min-width:1200px) {
|
||||||
.ui.container {
|
.ui.container {
|
||||||
width: 95% !important;
|
width:95% !important;
|
||||||
font-size: 90% !important;
|
font-size: 90% !important;
|
||||||
max-width: 1300px !important;
|
max-width: 1300px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width:767px) {
|
@media only screen and (max-width:767px) {
|
||||||
|
.ui.card>.content>.header:not(.ui),.ui.cards>.card>.content>.header:not(.ui) {
|
||||||
.ui.card>.content>.header:not(.ui),
|
margin-top:0.4em !important;
|
||||||
.ui.cards>.card>.content>.header:not(.ui) {
|
|
||||||
margin-top: 0.4em !important;
|
|
||||||
}
|
}
|
||||||
|
.ui.card>.content>.header,.ui.cards>.card>.content>.header {
|
||||||
.ui.menu .item>img:not(.ui) {
|
padding-top: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
color: rgba(0, 0, 0, .85);
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: .2em;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, .2);
|
||||||
|
}
|
||||||
|
.ui.menu .item>img:not(.ui){
|
||||||
width: 2.2rem;
|
width: 2.2rem;
|
||||||
}
|
}
|
||||||
|
.ui.menu .item:before{
|
||||||
.ui.menu .item:before {
|
width:0.5px;
|
||||||
width: 0.5px;
|
|
||||||
}
|
}
|
||||||
|
.ui.menu .item{
|
||||||
.ui.menu .item {
|
|
||||||
padding: 0.9rem 0.55rem;
|
padding: 0.9rem 0.55rem;
|
||||||
}
|
}
|
||||||
|
.ui.large.menu{
|
||||||
.ui.large.menu {
|
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i.icon {
|
i.icon {
|
||||||
color: #000;
|
color:#000;
|
||||||
width: 1.2em !important;
|
width:1.2em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
i.fi {
|
i.fi {
|
||||||
width: 0.9em;
|
width:0.9em;
|
||||||
margin: 0px 6px 0px 2px;
|
margin:0px 6px 0px 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
content: " " !important;
|
content:" " !important;
|
||||||
background: fixed !important;
|
background:fixed !important;
|
||||||
z-index: -1 !important;
|
z-index:-1 !important;
|
||||||
top: 0 !important;
|
top:0 !important;
|
||||||
right: 0 !important;
|
right:0 !important;
|
||||||
bottom: 0 !important;
|
bottom:0 !important;
|
||||||
left: 0 !important;
|
left:0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
@@ -73,80 +73,79 @@ td {
|
|||||||
padding-top: unset;
|
padding-top: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login.nb-container>.grid {
|
.login.nb-container > .grid {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login.nb-container>.grid .column {
|
.login.nb-container > .grid .column {
|
||||||
max-width: 450px;
|
max-width: 450px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.menu .item-right:before {
|
.ui.menu .item-right:before{
|
||||||
width: 0px;
|
width:0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .flag {
|
.status.cards .flag {
|
||||||
margin-right: 0 !important;
|
margin-right: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .header>.info.icon {
|
.status.cards .header > .info.icon {
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.grid {
|
.ui.grid {
|
||||||
margin-bottom: -0.5em
|
margin-bottom:-0.5em
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.card>.content>.header:not(.ui),
|
.ui.card>.content>.header:not(.ui), .ui.cards>.card>.content>.header:not(.ui){
|
||||||
.ui.cards>.card>.content>.header:not(.ui) {
|
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .wide.column {
|
.status.cards .wide.column {
|
||||||
padding-top: 0 !important;
|
padding-top: 0 !important;
|
||||||
padding-bottom: 0 !important;
|
padding-bottom: 0 !important;
|
||||||
height: 2.3rem !important;
|
height:2.3rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .wide.column:nth-child(1) {
|
.status.cards .wide.column:nth-child(1) {
|
||||||
margin-top: 1.2rem !important;
|
margin-top:1.2rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .wide.column:nth-child(2) {
|
.status.cards .wide.column:nth-child(2) {
|
||||||
margin-top: 1.2rem !important;
|
margin-top:1.2rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .three.wide.column {
|
.status.cards .three.wide.column {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 22% !important;
|
width: 22%!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .thirteen.wide.column {
|
.status.cards .thirteen.wide.column{
|
||||||
width: 78% !important;
|
width: 78%!important;
|
||||||
padding-left: 0;
|
padding-left:0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .description {
|
.status.cards .description {
|
||||||
padding-bottom: 0 !important;
|
padding-bottom:0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .flag {
|
.status.cards .flag {
|
||||||
margin-right: 0.5rem !important;
|
margin-right:0.5rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .header>.info.icon {
|
.status.cards .header > .info.icon {
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: 0 !important;
|
margin-right:0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.popup:before {
|
.ui.popup:before {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.closePopup {
|
.closePopup{
|
||||||
color: rgb(10, 148, 242) !important;
|
color:rgb(10, 148, 242) !important;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 7px;
|
top: 7px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
@@ -154,31 +153,27 @@ td {
|
|||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.temp-detail {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ui.content {
|
.ui.content {
|
||||||
margin: 0 !important;
|
margin:0 !important;
|
||||||
padding: 1em !important;
|
padding:1em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .ui.content.popup {
|
.status.cards .ui.content.popup {
|
||||||
min-width: calc(100%) !important;
|
min-width:calc(100%)!important;
|
||||||
line-height: 2rem !important;
|
line-height:2rem !important;
|
||||||
border-radius: 5px !important;
|
border-radius:5px !important;
|
||||||
border: 1px solid transparent !important;
|
border:1px solid transparent !important;
|
||||||
font-family: Arial, Helvetica, sans-serif !important;
|
font-family:Arial,Helvetica,sans-serif !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status.cards .outline.icon {
|
.status.cards .outline.icon {
|
||||||
margin-right: 1px !important;
|
margin-right:1px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.progress .bar {
|
.ui.progress .bar {
|
||||||
min-width: 1.8em !important;
|
min-width:1.8em !important;
|
||||||
border-radius: 5px !important;
|
border-radius:5px !important;
|
||||||
line-height: 1.65em !important;
|
line-height:1.65em !important;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding-right: 0.4em;
|
padding-right: 0.4em;
|
||||||
color: rgba(255, 255, 255, 0.7);
|
color: rgba(255, 255, 255, 0.7);
|
||||||
@@ -191,7 +186,7 @@ td {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-status .delay-today>i {
|
.service-status .delay-today > i {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 1.2em;
|
width: 1.2em;
|
||||||
height: 1.2em;
|
height: 1.2em;
|
||||||
@@ -228,4 +223,4 @@ td {
|
|||||||
|
|
||||||
.ui-alerts.top-center {
|
.ui-alerts.top-center {
|
||||||
z-index: 99999999;
|
z-index: 99999999;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ const mixinsVue = {
|
|||||||
adaptedTemplates: [
|
adaptedTemplates: [
|
||||||
{ key: 'default', name: 'Default', icon: 'th large' },
|
{ key: 'default', name: 'Default', icon: 'th large' },
|
||||||
{ key: 'angel-kanade', name: 'AngelKanade', icon: 'square' },
|
{ key: 'angel-kanade', name: 'AngelKanade', icon: 'square' },
|
||||||
{ key: 'server-status', name: 'ServerStatus', icon: 'list' }
|
{ key: 'server-status', name: 'SeverStatus', icon: 'list' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+79
-98
@@ -1,6 +1,5 @@
|
|||||||
body[theme="dark"] {
|
body[theme="dark"] {
|
||||||
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
|
background: #31363b;
|
||||||
background-color: rgba(49, 54, 59, 1);
|
|
||||||
color: #f1f1f1;
|
color: #f1f1f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8,9 +7,14 @@ body[theme="dark"] .navbar .navbar-brand {
|
|||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .navbar .navbar-brand {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
body[theme="dark"] .navbar .dropdown-menu {
|
body[theme="dark"] .navbar .dropdown-menu {
|
||||||
background-color: rgba(23, 26, 30, 1);
|
list-style-image: initial;
|
||||||
border-color: rgba(49, 54, 59, 1);
|
background-color: #171a1e;
|
||||||
|
border-color: #31363b;
|
||||||
box-shadow: rgba(0, 0, 0, 0.18) 0px 6px 12px;
|
box-shadow: rgba(0, 0, 0, 0.18) 0px 6px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,25 +24,31 @@ body[theme="dark"] .navbar .dropdown-menu > li > a {
|
|||||||
|
|
||||||
body[theme="dark"] .navbar .dropdown-menu > li > a:focus,
|
body[theme="dark"] .navbar .dropdown-menu > li > a:focus,
|
||||||
body[theme="dark"] .navbar .dropdown-menu > li > a:hover {
|
body[theme="dark"] .navbar .dropdown-menu > li > a:hover {
|
||||||
background-color: rgba(37, 40, 42, 1);
|
background-color: #25282a;
|
||||||
background-image: linear-gradient(rgba(28, 29, 38, 1) 0, rgba(28, 29, 38, 1) 100%);
|
background-image: linear-gradient(#1c1d26 0, #1c1d26 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .navbar .navbar-nav > .open > a:focus,
|
body[theme="dark"] .navbar .navbar-nav > .open > a:focus,
|
||||||
body[theme="dark"] .navbar .navbar-nav > .open > a:hover,
|
body[theme="dark"] .navbar .navbar-nav > .open > a:hover,
|
||||||
body[theme="dark"] .navbar .navbar-nav > .active > a,
|
body[theme="dark"] .navbar .navbar-nav > .active > a,
|
||||||
body[theme="dark"] .navbar .navbar-nav > .open > a{
|
body[theme="dark"] .navbar .navbar-nav > .open > a{
|
||||||
background-image: none;
|
background-image: none !important;
|
||||||
box-shadow: none;
|
box-shadow: none !important;
|
||||||
background-color: transparent;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .navbar .navbar-nav .open .dropdown-menu > li > a {
|
body[theme="dark"] .navbar .navbar-nav .open .dropdown-menu>li>a {
|
||||||
color: #f1f1f1;
|
color: #f1f1f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .toolbox i{
|
||||||
|
color: rgba(241,241,241,1);
|
||||||
|
background-color: rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
body[theme="dark"] .content {
|
body[theme="dark"] .content {
|
||||||
background-color: rgba(28, 29, 38, 1);
|
background-image: initial;
|
||||||
|
background-color: #1c1d26;
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
||||||
-webkit-box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
-webkit-box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
||||||
@@ -46,10 +56,58 @@ body[theme="dark"] .content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .table {
|
body[theme="dark"] .table {
|
||||||
background-color: rgba(28, 29, 38, 1);
|
background-image: initial;
|
||||||
|
background-color: #1c1d26;
|
||||||
border-color: #545b5e;
|
border-color: #545b5e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .table>thead>tr.node-group-tag>th {
|
||||||
|
background-color: #1c1d26;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .table-striped tbody > tr.even > td,
|
||||||
|
body[theme="dark"] .table-striped tbody > tr.even > th {
|
||||||
|
background-color: #1c1d26;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .table-striped tbody > tr.odd > td,
|
||||||
|
body[theme="dark"] .table-striped tbody > tr.odd > th {
|
||||||
|
background-color: #1c1d26;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .progress {
|
||||||
|
background-image: linear-gradient(#2c2c2c 0,#1c1d26 100%);
|
||||||
|
background-color: #1c1d26;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .progress-bar {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .progress-bar-success {
|
||||||
|
background-image: linear-gradient(#4d853a 0, #367e36 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .progress-offline .progress-bar-success {
|
||||||
|
background-image: linear-gradient(grey 0, grey 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .progress-bar-warning {
|
||||||
|
background-image: linear-gradient(#995f0d 0, #b5710f 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .progress-offline .progress-bar-warning {
|
||||||
|
background-image: linear-gradient(grey 0, grey 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .progress-bar-danger {
|
||||||
|
background-image: linear-gradient(#942320 0, #a12623 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
body[theme="dark"] .progress-offline .progress-bar-danger {
|
||||||
|
background-image: linear-gradient(grey 0, grey 100%);
|
||||||
|
}
|
||||||
|
|
||||||
body[theme="dark"] .table > tbody > tr > td:before,
|
body[theme="dark"] .table > tbody > tr > td:before,
|
||||||
body[theme="dark"] .table > tfoot > tr > td:before,
|
body[theme="dark"] .table > tfoot > tr > td:before,
|
||||||
body[theme="dark"] .table > thead > tr > td:before,
|
body[theme="dark"] .table > thead > tr > td:before,
|
||||||
@@ -57,75 +115,25 @@ body[theme="dark"] .table > thead > tr.node-group-cell > th:before{
|
|||||||
background-color: rgba(58, 62, 65, 1);
|
background-color: rgba(58, 62, 65, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .table-striped tbody > tr,
|
body[theme="dark"] .table > tbody > tr.expandRow > td:before,
|
||||||
body[theme="dark"] .table-striped tbody > tr.even > td,
|
body[theme="dark"] .table > thead > tr.node-group-tag > th:before{
|
||||||
body[theme="dark"] .table-striped tbody > tr.even > th {
|
background-color: #1c1d26;
|
||||||
background-color: rgba(28, 29, 38, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .table-striped tbody > tr,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.odd > td,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.odd > th {
|
|
||||||
background-color: rgba(34, 35, 46, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .table-hover > tbody > tr:hover{
|
|
||||||
background-color: unset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .table-hover > tbody > tr:not(.expandRow):hover > td {
|
body[theme="dark"] .table-hover > tbody > tr:not(.expandRow):hover > td {
|
||||||
background-color: rgba(48, 50, 65, 1);
|
background-color: #171a1e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* expandRow展开部分样式 */
|
body[theme="dark"] .table-striped > tbody > tr:nth-of-type(2n+1) {
|
||||||
body[theme="dark"] .table > tbody > tr.expandRow.odd > td:before{
|
background-color: #1c1d26;
|
||||||
background-color: rgba(34, 35, 46, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .table > tbody > tr.expandRow.even > td:before{
|
|
||||||
background-color: rgba(28, 29, 38, 1);
|
|
||||||
}
|
|
||||||
/* expandRow展开部分样式结束 */
|
|
||||||
|
|
||||||
body[theme="dark"] .progress {
|
|
||||||
background-image: linear-gradient(#2c2c2c 0,rgba(28, 29, 38, 1) 100%);
|
|
||||||
background-color: rgba(28, 29, 38, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-bar {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-bar-success {
|
|
||||||
background-image: linear-gradient(to right, rgba(77, 133, 58, 1) 0, rgba(54, 126, 54, 1) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-bar-warning {
|
|
||||||
background-image: linear-gradient(to right, rgba(153, 95, 13, 1) 0, rgba(181, 113, 15, 1) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-bar-danger {
|
|
||||||
background-image: linear-gradient(to right, rgba(145, 35, 32, 1) 0, rgba(161, 38, 35, 1) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-offline .progress-bar-success {
|
|
||||||
background-image: linear-gradient(rgba(128, 128, 128, 1) 0, rgba(128, 128, 128, 1) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-offline .progress-bar-warning {
|
|
||||||
background-image: linear-gradient(rgba(128, 128, 128, 1) 0, rgba(128, 128, 128, 1) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-offline .progress-bar-danger {
|
|
||||||
background-image: linear-gradient(rgba(128, 128, 128, 1) 0, rgba(128, 128, 128, 1) 100%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .node-cell.status .status-icon.online {
|
body[theme="dark"] .node-cell.status .status-icon.online {
|
||||||
background-image: linear-gradient(rgba(77, 133, 58, 1) 0, rgba(54, 126, 54, 1) 100%);
|
background-image: linear-gradient(#4d853a 0, #367e36 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .node-cell.status .status-icon.offline {
|
body[theme="dark"] .node-cell.status .status-icon.offline {
|
||||||
background-image: linear-gradient(rgba(155, 37, 34, 1) 0, rgba(161, 38, 35, 1) 100%);
|
background-image: linear-gradient(#9b2522 0, #9b2522 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .service-status .danger {
|
body[theme="dark"] .service-status .danger {
|
||||||
@@ -141,7 +149,7 @@ body[theme="dark"] .service-status .warning {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .service-day-status-icon {
|
body[theme="dark"] .service-day-status-icon {
|
||||||
background-color: rgba(128, 128, 128, 1);
|
background-color: grey;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] footer p a,
|
body[theme="dark"] footer p a,
|
||||||
@@ -149,30 +157,3 @@ body[theme="dark"] footer p a:hover {
|
|||||||
color: #f1f1f1;
|
color: #f1f1f1;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[theme="dark"] .modal-content{
|
|
||||||
background-color: rgba(28, 29, 38, 1);
|
|
||||||
color: #f1f1f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] #earthChartBox .modal-content{
|
|
||||||
background-color: rgba(0, 0, 0, 1);
|
|
||||||
color: #f1f1f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .modal-header{
|
|
||||||
border-bottom-color:#080808;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .modal-header i.xclose{
|
|
||||||
color: #f1f1f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .toolbox i{
|
|
||||||
color: rgba(241, 241, 241, 1);
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .network-box .network-box-header{
|
|
||||||
border-bottom: 1px solid rgba(110, 112, 121, 0.25);
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
body[theme="dark"]::before {
|
|
||||||
content: "";
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
background-image: url(/static/theme-server-status/img/bg.jpg);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 50% 50%;
|
|
||||||
background-size: cover;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] {
|
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
|
||||||
color: #f1f1f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .navbar {
|
|
||||||
/** 顶部导航条 背景 **/
|
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
|
||||||
box-shadow: none;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .navbar .navbar-brand {
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .navbar .dropdown-menu {
|
|
||||||
/** 二级导航下拉 背景 **/
|
|
||||||
background-color: rgba(0, 0, 0, 0.85);
|
|
||||||
border-top: none;
|
|
||||||
border-color: #31363b;
|
|
||||||
box-shadow: rgba(0, 0, 0, 0.18) 0px 6px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .navbar .dropdown-menu > li > a {
|
|
||||||
color: #c8c3bc;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .navbar .dropdown-menu > li > a:focus,
|
|
||||||
body[theme="dark"] .navbar .dropdown-menu > li > a:hover {
|
|
||||||
/** 二级导航鼠标悬停选中背景 **/
|
|
||||||
background-color: rgba(0, 0, 0, 0.95);
|
|
||||||
background-image: linear-gradient(#1c1d26 0, #1c1d26 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .navbar .navbar-nav .open .dropdown-menu > li > a {
|
|
||||||
color: #f1f1f1;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .table,
|
|
||||||
body[theme="dark"] .table-condensed > tbody > tr,
|
|
||||||
body[theme="dark"] .table-hover > tbody > tr,
|
|
||||||
body[theme="dark"] .table-hover > tbody > tr:hover,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.even,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.odd,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.even > td,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.even > th,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.odd > td,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.odd > th,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.even > td:hover,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.even > th:hover,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.odd > td:hover,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.odd > th:hover,
|
|
||||||
body[theme="dark"] .table-striped tbody > tr.expandRow:hover {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .content {
|
|
||||||
/** 主box 背景 **/
|
|
||||||
background-color: rgba(28, 29, 38, 0.8);
|
|
||||||
border: none;
|
|
||||||
box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
|
||||||
-webkit-box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
|
||||||
box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .table > thead > tr.node-group-tag > th,
|
|
||||||
body[theme="dark"] .table > thead > tr.node-group-tag > th:before {
|
|
||||||
background: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .table > tbody > tr > td:before,
|
|
||||||
body[theme="dark"] .table > tfoot > tr > td:before,
|
|
||||||
body[theme="dark"] .table > thead > tr > td:before,
|
|
||||||
body[theme="dark"] .table > thead > tr.node-group-cell > th:before{
|
|
||||||
/** border-bottom 颜色 **/
|
|
||||||
background-color: rgba(155, 155, 155, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .table-hover > tbody > tr:not(.expandRow):hover > td {
|
|
||||||
background-color: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* expandRow展开部分样式 */
|
|
||||||
body[theme="dark"] .table > tbody > tr.expandRow.odd > td:before{
|
|
||||||
background-color: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .table > tbody > tr.expandRow.even > td:before{
|
|
||||||
background-color: unset;
|
|
||||||
}
|
|
||||||
/* expandRow展开部分样式结束 */
|
|
||||||
|
|
||||||
body[theme="dark"] .progress {
|
|
||||||
background-image: none;
|
|
||||||
background-color: rgba(255, 255, 255, 0.075);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-bar-success {
|
|
||||||
background-image: linear-gradient(to right, rgba(77, 133, 58, 0.9) 0, rgba(54, 126, 54, 0.9) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-bar-warning {
|
|
||||||
background-image: linear-gradient(to right, rgba(153, 95, 13, 0.9) 0, rgba(181, 113, 15, 0.9) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="dark"] .progress-bar-danger {
|
|
||||||
background-image: linear-gradient(to right, rgba(145, 35, 32, 0.8) 0, rgba(161, 38, 35, 0.8) 100%);
|
|
||||||
}
|
|
||||||
+42
-119
File diff suppressed because one or more lines are too long
@@ -1,134 +0,0 @@
|
|||||||
body[theme="light"]::before {
|
|
||||||
content: "";
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
background-image: url(/static/theme-server-status/img/bg.jpg);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 50% 50%;
|
|
||||||
background-size: cover;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] {
|
|
||||||
background-image: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"]::after {
|
|
||||||
content: "";
|
|
||||||
position: fixed;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .navbar {
|
|
||||||
/** 顶部导航条 背景 **/
|
|
||||||
background-color: rgba(255, 255, 255, 0.9);
|
|
||||||
border-bottom: 1px #cecece solid;
|
|
||||||
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .navbar .dropdown-menu {
|
|
||||||
/** 二级导航下拉 **/
|
|
||||||
background-color: rgba(255, 255, 255, 0.8);
|
|
||||||
border-color: rgba(0, 0, 0, .05);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
body[theme="light"] .navbar .dropdown-menu > li > a:focus,
|
|
||||||
body[theme="light"] .navbar .dropdown-menu > li > a:hover{
|
|
||||||
/** 二级导航鼠标悬停选中背景 **/
|
|
||||||
background-color: rgba(0, 0, 0, .05);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .navbar .navbar-collapse{
|
|
||||||
border-color:rgba(0, 0, 0, 0.085);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .navbar .navbar-toggle .icon-bar{
|
|
||||||
background-color: rgba(0, 0, 0, 0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .navbar .navbar-toggle:focus,
|
|
||||||
body[theme="light"] .navbar .navbar-toggle:hover {
|
|
||||||
background-color: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .table,
|
|
||||||
body[theme="light"] .table-condensed > tbody > tr,
|
|
||||||
body[theme="light"] .table-hover > tbody > tr,
|
|
||||||
body[theme="light"] .table-hover > tbody > tr:hover,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.even,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.odd,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.even > td,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.even > th,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.odd > td,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.odd > th,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.even > td:hover,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.even > th:hover,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.odd > td:hover,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.odd > th:hover,
|
|
||||||
body[theme="light"] .table-striped tbody > tr.expandRow:hover {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .content {
|
|
||||||
/** 主box 背景 **/
|
|
||||||
background-color: rgba(245, 245, 245, 0.8);
|
|
||||||
border: none;
|
|
||||||
box-shadow: rgba(0, 0, 0, 0.5) 0 0.625em 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .table > thead > tr.node-group-tag > th,
|
|
||||||
body[theme="light"] .table > thead > tr.node-group-tag > th:before {
|
|
||||||
background: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .table > tbody > tr > td:before,
|
|
||||||
body[theme="light"] .table > tfoot > tr > td:before,
|
|
||||||
body[theme="light"] .table > thead > tr > td:before,
|
|
||||||
body[theme="light"] .table > thead > tr.node-group-cell > th:before{
|
|
||||||
/** border-bottom 颜色 **/
|
|
||||||
background-color: rgba(0, 0, 0, 0.075);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .table-hover > tbody > tr:not(.expandRow):hover > td {
|
|
||||||
background-color: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* expandRow展开部分样式 */
|
|
||||||
body[theme="light"] .table > tbody > tr.expandRow.odd > td:before{
|
|
||||||
background-color: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .table > tbody > tr.expandRow.even > td:before{
|
|
||||||
background-color: unset;
|
|
||||||
}
|
|
||||||
/* expandRow展开部分样式结束 */
|
|
||||||
|
|
||||||
body[theme="light"] .progress {
|
|
||||||
background-image: none;
|
|
||||||
background-color: rgba(0, 0, 0, 0.015);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .progress-bar-success {
|
|
||||||
background-image: linear-gradient(to right, rgba(50, 205, 50, 0.6) 0, rgba(68, 157, 68, 0.6) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .progress-bar-warning {
|
|
||||||
background-image: linear-gradient(to right, rgba(236, 151, 31, 0.6) 0, rgba(255, 125, 80, 0.6) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .progress-bar-danger {
|
|
||||||
background-image: linear-gradient(to right, rgba(255, 70, 0, 0.6) 0, rgba(201, 48, 44,0.6) 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[theme="light"] .toolbox i{
|
|
||||||
background-color: rgba(255, 255, 255, .55);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 767px) {
|
|
||||||
body[theme="light"] .navbar .navbar-nav .open .dropdown-menu {
|
|
||||||
background-color: rgba(235, 235, 235, 0.75);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+17
-224
@@ -3,22 +3,16 @@ body {
|
|||||||
padding-bottom: 30px !important;
|
padding-bottom: 30px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container-fluid{
|
|
||||||
max-width: 1680px;
|
|
||||||
width: 95vw;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nezha {
|
|
||||||
min-height: calc(100vh - 100px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导航部分 开始*/
|
/* 导航部分 开始*/
|
||||||
.navbar {
|
.navbar {
|
||||||
min-height: 40px !important;
|
min-height: 40px !important;
|
||||||
margin:0 auto;
|
margin:0 auto;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
z-index:99999999;
|
}
|
||||||
|
|
||||||
|
.navbar .container{
|
||||||
|
max-width: 95vw;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-inverse{
|
.navbar-inverse{
|
||||||
@@ -52,8 +46,8 @@ body {
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar .dropdown a{
|
.navbar .node-cell-expand-label {
|
||||||
cursor: pointer;
|
/*margin-right: 5px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar .dropdown .dropdown-toggle {
|
.navbar .dropdown .dropdown-toggle {
|
||||||
@@ -65,7 +59,7 @@ body {
|
|||||||
margin:0px -15px;
|
margin:0px -15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar .navbar-nav > li > a {
|
.navbar .navbar-nav>li>a {
|
||||||
color:#f1f1f1;
|
color:#f1f1f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,10 +70,12 @@ body {
|
|||||||
.navbar .navbar-collapse{
|
.navbar .navbar-collapse{
|
||||||
max-height: 500px;
|
max-height: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 导航部分 结束 */
|
/* 导航部分 结束 */
|
||||||
|
|
||||||
|
|
||||||
/* toolbox 开始 */
|
/* toolbox 开始 */
|
||||||
|
|
||||||
.toolbox {
|
.toolbox {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom:20px;
|
bottom:20px;
|
||||||
@@ -120,6 +116,7 @@ body {
|
|||||||
.toolbox .showGoTop i.goTop {
|
.toolbox .showGoTop i.goTop {
|
||||||
font-size: 1.55rem;
|
font-size: 1.55rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* toolbox 结束 */
|
/* toolbox 结束 */
|
||||||
|
|
||||||
|
|
||||||
@@ -136,10 +133,6 @@ body {
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-responsive{
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table th, .table td {
|
.table th, .table td {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
@@ -169,15 +162,6 @@ body {
|
|||||||
height: 0.7px;
|
height: 0.7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
table.monitor-detail{
|
|
||||||
margin:5px 0px 10px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
tr.accordion-toggle{
|
|
||||||
cursor:pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table .network-thead-tr th,
|
|
||||||
.table .node-group-tag th{
|
.table .node-group-tag th{
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
padding-bottom:15px;
|
padding-bottom:15px;
|
||||||
@@ -246,26 +230,12 @@ tr.accordion-toggle{
|
|||||||
max-width: 50px;
|
max-width: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.temp-detail {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*agent详情下拉速度*/
|
|
||||||
.collapsing{
|
|
||||||
-webkit-transition-property:height,visibility;
|
|
||||||
-o-transition-property:height,visibility;
|
|
||||||
transition-property:height,visibility;
|
|
||||||
-webkit-transition-duration:.15s;
|
|
||||||
-o-transition-duration:.15s;
|
|
||||||
transition-duration:.15s;
|
|
||||||
-webkit-transition-timing-function: linear;
|
|
||||||
-o-transition-timing-function: linear;
|
|
||||||
transition-timing-function: linear
|
|
||||||
}
|
|
||||||
/*正文结束*/
|
/*正文结束*/
|
||||||
|
|
||||||
/* 服务页 正文*/
|
/* 服务页 正文*/
|
||||||
.service-status {}
|
.service-status {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.service-status .service-status-th{
|
.service-status .service-status-th{
|
||||||
min-width:60px;
|
min-width:60px;
|
||||||
@@ -312,183 +282,28 @@ tr.accordion-toggle{
|
|||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
td.ping-network-quality {
|
|
||||||
width: 600px;
|
|
||||||
}
|
|
||||||
/* 服务页 正文结束 */
|
/* 服务页 正文结束 */
|
||||||
|
|
||||||
/* 网络页 正文*/
|
|
||||||
.network-box .btn-group.open .dropdown-toggle{
|
|
||||||
box-shadow:unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .network-box-header{
|
|
||||||
font-size: 18px;
|
|
||||||
padding: 5px 0px 15px 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .network-box-header .dropdown-menu {
|
|
||||||
max-height: 22.5em;
|
|
||||||
overflow-y: auto;
|
|
||||||
z-index:99999998;
|
|
||||||
min-width: 200px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .network-box-header .dropdown-menu::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .network-box-header .dropdown-menu li{
|
|
||||||
height: 2em;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .network-box-header .dropdown-menu li.input-group{
|
|
||||||
margin: 0 auto;
|
|
||||||
display: flex;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 99999997;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .network-box-header .dropdown-menu li.input-group input{
|
|
||||||
width: 100%;
|
|
||||||
height: 2em;
|
|
||||||
border-top: none;
|
|
||||||
border-left: none;
|
|
||||||
border-right: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .network-box-header .dropdown-menu li a {
|
|
||||||
padding: 5px 5px 5px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .network-box-header .dropdown-menu li.hidden {
|
|
||||||
height: 0;
|
|
||||||
display: none;
|
|
||||||
visibility:hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .network-box-header .dropdown-menu li.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .chartTitle {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 18px;
|
|
||||||
margin: 18px 0px 15px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.network-box .chartTitle i.chartCountryCode{
|
|
||||||
font-size: 16px;
|
|
||||||
border-radius: 12.5%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 网络页 正文结束 */
|
|
||||||
|
|
||||||
/* 地图版服务器分布图 */
|
|
||||||
#mapChartBox{
|
|
||||||
z-index: 999999999;
|
|
||||||
padding-left: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-open .modal{
|
|
||||||
overflow-x: hidden;
|
|
||||||
overflow-y: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-dialog-centered{
|
|
||||||
margin: 0 auto;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center; /* 垂直居中 */
|
|
||||||
justify-content: center; /* 水平居中 */
|
|
||||||
min-height: calc(100%) /* 确保模态框占据整个视口高度 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-content{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
pointer-events: auto;
|
|
||||||
border-radius: unset;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-header{
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-header h4{
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-header i.xclose{
|
|
||||||
cursor: pointer;
|
|
||||||
position: absolute;
|
|
||||||
font-size: 30px;
|
|
||||||
top: 12px;
|
|
||||||
right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body{
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.template-item, a.cdn-item{
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer{
|
|
||||||
padding-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer p{
|
|
||||||
text-align: center;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 1200px) {
|
@media only screen and (max-width: 1200px) {
|
||||||
.accordian-body{
|
.accordian-body{
|
||||||
margin: 5px 0px 5px 10px;
|
margin: 5px 0px 5px 10px;
|
||||||
}
|
}
|
||||||
table.monitor-detail{
|
|
||||||
margin:0px 0px 2px 0px;
|
|
||||||
}
|
|
||||||
.table .network-thead-tr th,
|
|
||||||
.table .node-group-tag th{
|
.table .node-group-tag th{
|
||||||
font-size:16px;
|
font-size:16px;
|
||||||
padding-bottom:6px;
|
padding-bottom:6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 彩虹旗 */
|
|
||||||
.fi-rb {
|
|
||||||
background-image: url(/static/theme-server-status/img/rb.png);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@media only screen and (max-width: 767px) {
|
@media only screen and (max-width: 767px) {
|
||||||
body {
|
body {
|
||||||
font-size: 10px !important;
|
font-size: 10px !important;
|
||||||
padding-top:60px !important;
|
padding-top:60px !important;
|
||||||
}
|
}
|
||||||
.nezha {
|
|
||||||
min-height: calc(100vh - 80px);
|
|
||||||
}
|
|
||||||
.content {
|
.content {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
footer{
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
.cycle-transfer-stats .dataTables_wrapper{
|
|
||||||
margin-bottom: -10px;
|
|
||||||
}
|
|
||||||
.navbar .navbar-nav .open .dropdown-menu>li>a {
|
.navbar .navbar-nav .open .dropdown-menu>li>a {
|
||||||
color: #f1f1f1;
|
color: #f1f1f1;
|
||||||
}
|
}
|
||||||
@@ -523,17 +338,10 @@ footer p{
|
|||||||
.accordian-body{
|
.accordian-body{
|
||||||
margin: 5px 0px 5px 10px;
|
margin: 5px 0px 5px 10px;
|
||||||
}
|
}
|
||||||
table.monitor-detail{
|
|
||||||
margin:0px 0px 2px 0px;
|
|
||||||
}
|
|
||||||
.table .network-thead-tr th,
|
|
||||||
.table .node-group-tag th{
|
.table .node-group-tag th{
|
||||||
font-size:14px;
|
font-size:16px;
|
||||||
padding-bottom:6px;
|
padding-bottom:6px;
|
||||||
}
|
}
|
||||||
.table tr.network td{
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.service-status .service-status-th{
|
.service-status .service-status-th{
|
||||||
min-width:30px;
|
min-width:30px;
|
||||||
}
|
}
|
||||||
@@ -557,21 +365,6 @@ footer p{
|
|||||||
.toolbox {
|
.toolbox {
|
||||||
right: 18px;
|
right: 18px;
|
||||||
}
|
}
|
||||||
td.ping-network-quality {
|
|
||||||
width: 110px;
|
|
||||||
}
|
|
||||||
.network-box .network-box-header {
|
|
||||||
margin: 8px 0px 0px 8px;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
.network-box .chartTitle {
|
|
||||||
font-size: 16px;
|
|
||||||
margin: 10px 0px 10px 0px;
|
|
||||||
}
|
|
||||||
.network-box .chartTitle i.chartCountryCode{
|
|
||||||
font-size: 15px;
|
|
||||||
border-radius: 12.5%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (min-width: 768px) {
|
@media only screen and (min-width: 768px) {
|
||||||
|
|||||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 262 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 5.8 KiB |
+326
@@ -0,0 +1,326 @@
|
|||||||
|
/**
|
||||||
|
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||||
|
*/
|
||||||
|
;(function(window, document) {
|
||||||
|
/*jshint evil:true */
|
||||||
|
/** version */
|
||||||
|
var version = '3.7.3';
|
||||||
|
|
||||||
|
/** Preset options */
|
||||||
|
var options = window.html5 || {};
|
||||||
|
|
||||||
|
/** Used to skip problem elements */
|
||||||
|
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
|
||||||
|
|
||||||
|
/** Not all elements can be cloned in IE **/
|
||||||
|
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||||
|
|
||||||
|
/** Detect whether the browser supports default html5 styles */
|
||||||
|
var supportsHtml5Styles;
|
||||||
|
|
||||||
|
/** Name of the expando, to work with multiple documents or to re-shiv one document */
|
||||||
|
var expando = '_html5shiv';
|
||||||
|
|
||||||
|
/** The id for the the documents expando */
|
||||||
|
var expanID = 0;
|
||||||
|
|
||||||
|
/** Cached data for each document */
|
||||||
|
var expandoData = {};
|
||||||
|
|
||||||
|
/** Detect whether the browser supports unknown elements */
|
||||||
|
var supportsUnknownElements;
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.innerHTML = '<xyz></xyz>';
|
||||||
|
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||||
|
supportsHtml5Styles = ('hidden' in a);
|
||||||
|
|
||||||
|
supportsUnknownElements = a.childNodes.length == 1 || (function() {
|
||||||
|
// assign a false positive if unable to shiv
|
||||||
|
(document.createElement)('a');
|
||||||
|
var frag = document.createDocumentFragment();
|
||||||
|
return (
|
||||||
|
typeof frag.cloneNode == 'undefined' ||
|
||||||
|
typeof frag.createDocumentFragment == 'undefined' ||
|
||||||
|
typeof frag.createElement == 'undefined'
|
||||||
|
);
|
||||||
|
}());
|
||||||
|
} catch(e) {
|
||||||
|
// assign a false positive if detection fails => unable to shiv
|
||||||
|
supportsHtml5Styles = true;
|
||||||
|
supportsUnknownElements = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}());
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a style sheet with the given CSS text and adds it to the document.
|
||||||
|
* @private
|
||||||
|
* @param {Document} ownerDocument The document.
|
||||||
|
* @param {String} cssText The CSS text.
|
||||||
|
* @returns {StyleSheet} The style element.
|
||||||
|
*/
|
||||||
|
function addStyleSheet(ownerDocument, cssText) {
|
||||||
|
var p = ownerDocument.createElement('p'),
|
||||||
|
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||||
|
|
||||||
|
p.innerHTML = 'x<style>' + cssText + '</style>';
|
||||||
|
return parent.insertBefore(p.lastChild, parent.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of `html5.elements` as an array.
|
||||||
|
* @private
|
||||||
|
* @returns {Array} An array of shived element node names.
|
||||||
|
*/
|
||||||
|
function getElements() {
|
||||||
|
var elements = html5.elements;
|
||||||
|
return typeof elements == 'string' ? elements.split(' ') : elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the built-in list of html5 elements
|
||||||
|
* @memberOf html5
|
||||||
|
* @param {String|Array} newElements whitespace separated list or array of new element names to shiv
|
||||||
|
* @param {Document} ownerDocument The context document.
|
||||||
|
*/
|
||||||
|
function addElements(newElements, ownerDocument) {
|
||||||
|
var elements = html5.elements;
|
||||||
|
if(typeof elements != 'string'){
|
||||||
|
elements = elements.join(' ');
|
||||||
|
}
|
||||||
|
if(typeof newElements != 'string'){
|
||||||
|
newElements = newElements.join(' ');
|
||||||
|
}
|
||||||
|
html5.elements = elements +' '+ newElements;
|
||||||
|
shivDocument(ownerDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data associated to the given document
|
||||||
|
* @private
|
||||||
|
* @param {Document} ownerDocument The document.
|
||||||
|
* @returns {Object} An object of data.
|
||||||
|
*/
|
||||||
|
function getExpandoData(ownerDocument) {
|
||||||
|
var data = expandoData[ownerDocument[expando]];
|
||||||
|
if (!data) {
|
||||||
|
data = {};
|
||||||
|
expanID++;
|
||||||
|
ownerDocument[expando] = expanID;
|
||||||
|
expandoData[expanID] = data;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a shived element for the given nodeName and document
|
||||||
|
* @memberOf html5
|
||||||
|
* @param {String} nodeName name of the element
|
||||||
|
* @param {Document|DocumentFragment} ownerDocument The context document.
|
||||||
|
* @returns {Object} The shived element.
|
||||||
|
*/
|
||||||
|
function createElement(nodeName, ownerDocument, data){
|
||||||
|
if (!ownerDocument) {
|
||||||
|
ownerDocument = document;
|
||||||
|
}
|
||||||
|
if(supportsUnknownElements){
|
||||||
|
return ownerDocument.createElement(nodeName);
|
||||||
|
}
|
||||||
|
if (!data) {
|
||||||
|
data = getExpandoData(ownerDocument);
|
||||||
|
}
|
||||||
|
var node;
|
||||||
|
|
||||||
|
if (data.cache[nodeName]) {
|
||||||
|
node = data.cache[nodeName].cloneNode();
|
||||||
|
} else if (saveClones.test(nodeName)) {
|
||||||
|
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||||
|
} else {
|
||||||
|
node = data.createElem(nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avoid adding some elements to fragments in IE < 9 because
|
||||||
|
// * Attributes like `name` or `type` cannot be set/changed once an element
|
||||||
|
// is inserted into a document/fragment
|
||||||
|
// * Link elements with `src` attributes that are inaccessible, as with
|
||||||
|
// a 403 response, will cause the tab/window to crash
|
||||||
|
// * Script elements appended to fragments will execute when their `src`
|
||||||
|
// or `text` property is set
|
||||||
|
return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a shived DocumentFragment for the given document
|
||||||
|
* @memberOf html5
|
||||||
|
* @param {Document} ownerDocument The context document.
|
||||||
|
* @returns {Object} The shived DocumentFragment.
|
||||||
|
*/
|
||||||
|
function createDocumentFragment(ownerDocument, data){
|
||||||
|
if (!ownerDocument) {
|
||||||
|
ownerDocument = document;
|
||||||
|
}
|
||||||
|
if(supportsUnknownElements){
|
||||||
|
return ownerDocument.createDocumentFragment();
|
||||||
|
}
|
||||||
|
data = data || getExpandoData(ownerDocument);
|
||||||
|
var clone = data.frag.cloneNode(),
|
||||||
|
i = 0,
|
||||||
|
elems = getElements(),
|
||||||
|
l = elems.length;
|
||||||
|
for(;i<l;i++){
|
||||||
|
clone.createElement(elems[i]);
|
||||||
|
}
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
|
||||||
|
* @private
|
||||||
|
* @param {Document|DocumentFragment} ownerDocument The document.
|
||||||
|
* @param {Object} data of the document.
|
||||||
|
*/
|
||||||
|
function shivMethods(ownerDocument, data) {
|
||||||
|
if (!data.cache) {
|
||||||
|
data.cache = {};
|
||||||
|
data.createElem = ownerDocument.createElement;
|
||||||
|
data.createFrag = ownerDocument.createDocumentFragment;
|
||||||
|
data.frag = data.createFrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ownerDocument.createElement = function(nodeName) {
|
||||||
|
//abort shiv
|
||||||
|
if (!html5.shivMethods) {
|
||||||
|
return data.createElem(nodeName);
|
||||||
|
}
|
||||||
|
return createElement(nodeName, ownerDocument, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
|
||||||
|
'var n=f.cloneNode(),c=n.createElement;' +
|
||||||
|
'h.shivMethods&&(' +
|
||||||
|
// unroll the `createElement` calls
|
||||||
|
getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
|
||||||
|
data.createElem(nodeName);
|
||||||
|
data.frag.createElement(nodeName);
|
||||||
|
return 'c("' + nodeName + '")';
|
||||||
|
}) +
|
||||||
|
');return n}'
|
||||||
|
)(html5, data.frag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shivs the given document.
|
||||||
|
* @memberOf html5
|
||||||
|
* @param {Document} ownerDocument The document to shiv.
|
||||||
|
* @returns {Document} The shived document.
|
||||||
|
*/
|
||||||
|
function shivDocument(ownerDocument) {
|
||||||
|
if (!ownerDocument) {
|
||||||
|
ownerDocument = document;
|
||||||
|
}
|
||||||
|
var data = getExpandoData(ownerDocument);
|
||||||
|
|
||||||
|
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
|
||||||
|
data.hasCSS = !!addStyleSheet(ownerDocument,
|
||||||
|
// corrects block display not defined in IE6/7/8/9
|
||||||
|
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
|
||||||
|
// adds styling not present in IE6/7/8/9
|
||||||
|
'mark{background:#FF0;color:#000}' +
|
||||||
|
// hides non-rendered elements
|
||||||
|
'template{display:none}'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!supportsUnknownElements) {
|
||||||
|
shivMethods(ownerDocument, data);
|
||||||
|
}
|
||||||
|
return ownerDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `html5` object is exposed so that more elements can be shived and
|
||||||
|
* existing shiving can be detected on iframes.
|
||||||
|
* @type Object
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* // options can be changed before the script is included
|
||||||
|
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
|
||||||
|
*/
|
||||||
|
var html5 = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array or space separated string of node names of the elements to shiv.
|
||||||
|
* @memberOf html5
|
||||||
|
* @type Array|String
|
||||||
|
*/
|
||||||
|
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* current version of html5shiv
|
||||||
|
*/
|
||||||
|
'version': version,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag to indicate that the HTML5 style sheet should be inserted.
|
||||||
|
* @memberOf html5
|
||||||
|
* @type Boolean
|
||||||
|
*/
|
||||||
|
'shivCSS': (options.shivCSS !== false),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is equal to true if a browser supports creating unknown/HTML5 elements
|
||||||
|
* @memberOf html5
|
||||||
|
* @type boolean
|
||||||
|
*/
|
||||||
|
'supportsUnknownElements': supportsUnknownElements,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
|
||||||
|
* methods should be overwritten.
|
||||||
|
* @memberOf html5
|
||||||
|
* @type Boolean
|
||||||
|
*/
|
||||||
|
'shivMethods': (options.shivMethods !== false),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A string to describe the type of `html5` object ("default" or "default print").
|
||||||
|
* @memberOf html5
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
'type': 'default',
|
||||||
|
|
||||||
|
// shivs the document according to the specified `html5` object options
|
||||||
|
'shivDocument': shivDocument,
|
||||||
|
|
||||||
|
//creates a shived element
|
||||||
|
createElement: createElement,
|
||||||
|
|
||||||
|
//creates a shived documentFragment
|
||||||
|
createDocumentFragment: createDocumentFragment,
|
||||||
|
|
||||||
|
//extends list of elements
|
||||||
|
addElements: addElements
|
||||||
|
};
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// expose html5
|
||||||
|
window.html5 = html5;
|
||||||
|
|
||||||
|
// shiv the document
|
||||||
|
shivDocument(document);
|
||||||
|
|
||||||
|
if(typeof module == 'object' && module.exports){
|
||||||
|
module.exports = html5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}(typeof window !== "undefined" ? window : this, document));
|
||||||
+53
-64
@@ -1,37 +1,40 @@
|
|||||||
const mixinsVue = {
|
const mixinsVue = {
|
||||||
data: {
|
data: {
|
||||||
cache: [],
|
cache: [],
|
||||||
isMobile: false,
|
|
||||||
theme: "light",
|
theme: "light",
|
||||||
isSystemTheme: false,
|
isSystemTheme: false,
|
||||||
showGroup: false,
|
showGroup: false,
|
||||||
showGoTop: false,
|
showGoTop: false,
|
||||||
showTools: false,
|
|
||||||
preferredTemplate: null,
|
preferredTemplate: null,
|
||||||
semiTransparent: false,
|
isMobile: false,
|
||||||
staticUrl: '/static/theme-server-status',
|
|
||||||
adaptedTemplates: [
|
adaptedTemplates: [
|
||||||
{ key: 'default', name: 'Default', icon: 'th large' },
|
{ key: 'default', name: 'Default', icon: 'th large' },
|
||||||
{ key: 'angel-kanade', name: 'AngelKanade', icon: 'square' },
|
{ key: 'angel-kanade', name: 'AngelKanade', icon: 'square' },
|
||||||
{ key: 'server-status', name: 'ServerStatus', icon: 'list' }
|
{ key: 'server-status', name: 'SeverStatus', icon: 'list' }
|
||||||
],
|
]
|
||||||
colors: [],
|
|
||||||
colorsDark: ['#4992FF', '#08C091', '#FDDD5F', '#FF6E76', '#58D9F9', '#7CFFB2', '#FF8A44', '#8D48E3', '#DD79FF', '#5470C6', '#3BA272', '#FAC758', '#EE6666', '#72C0DE', '#91CC76', '#FB8352', '#9A60B4', '#EA7BCC'],
|
|
||||||
colorsLight: ['#5470C6', '#3BA272', '#FAC758', '#EE6666', '#72C0DE', '#91CC76', '#FB8352', '#9A60B4', '#EA7BCC', '#4992FF', '#08C091', '#FDDD5F', '#FF6E76', '#58D9F9', '#7CFFB2', '#FF8A44', '#8D48E3', '#DD79FF'],
|
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.isMobile = this.checkIsMobile();
|
this.isMobile = this.checkIsMobile();
|
||||||
this.theme = this.initTheme();
|
this.initTheme();
|
||||||
this.showGroup = this.initShowGroup();
|
this.storedShowGroup();
|
||||||
this.semiTransparent = this.initSemiTransparent();
|
|
||||||
this.preferredTemplate = this.getCookie('preferred_theme') ? this.getCookie('preferred_theme') : this.$root.defaultTemplate;
|
this.preferredTemplate = this.getCookie('preferred_theme') ? this.getCookie('preferred_theme') : this.$root.defaultTemplate;
|
||||||
this.colors = this.theme == "dark" ? this.colorsDark : this.colorsLight;
|
|
||||||
window.addEventListener('scroll', this.handleScroll);
|
window.addEventListener('scroll', this.handleScroll);
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
window.removeEventListener('scroll', this.handleScroll);
|
window.removeEventListener('scroll', this.handleScroll);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
toggleView() {
|
||||||
|
this.showGroup = !this.showGroup;
|
||||||
|
localStorage.setItem("showGroup", JSON.stringify(this.showGroup));
|
||||||
|
return this.showGroup;
|
||||||
|
},
|
||||||
|
storedShowGroup() {
|
||||||
|
const storedShowGroup = localStorage.getItem("showGroup");
|
||||||
|
if (storedShowGroup !== null) {
|
||||||
|
this.showGroup = JSON.parse(storedShowGroup);
|
||||||
|
}
|
||||||
|
},
|
||||||
toggleTemplate(template) {
|
toggleTemplate(template) {
|
||||||
if( template != this.preferredTemplate){
|
if( template != this.preferredTemplate){
|
||||||
this.preferredTemplate = template;
|
this.preferredTemplate = template;
|
||||||
@@ -39,56 +42,6 @@ const mixinsVue = {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleShowTools() {
|
|
||||||
this.showTools = !this.showTools;
|
|
||||||
},
|
|
||||||
initTheme() {
|
|
||||||
const storedTheme = localStorage.getItem("theme");
|
|
||||||
const theme = (storedTheme === 'dark' || storedTheme === 'light') ? storedTheme : (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
|
||||||
this.setTheme(theme);
|
|
||||||
return theme;
|
|
||||||
},
|
|
||||||
setTheme(theme) {
|
|
||||||
document.body.setAttribute("theme", theme);
|
|
||||||
this.theme = theme;
|
|
||||||
localStorage.setItem("theme", theme);
|
|
||||||
// 重新赋值全局调色
|
|
||||||
this.colors = this.theme == "dark" ? this.colorsDark : this.colorsLight;
|
|
||||||
|
|
||||||
if(this.$root.page == 'index' || this.$root.page == 'network') {
|
|
||||||
this.reloadCharts(); // 重新载入echarts图表
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initShowGroup() {
|
|
||||||
const storedShowGroup = localStorage.getItem("showGroup");
|
|
||||||
const showGroup = storedShowGroup !== null ? JSON.parse(storedShowGroup) : false;
|
|
||||||
if (storedShowGroup === null) {
|
|
||||||
localStorage.setItem("showGroup", showGroup);
|
|
||||||
}
|
|
||||||
return showGroup;
|
|
||||||
},
|
|
||||||
toggleShowGroup() {
|
|
||||||
this.showGroup = !this.showGroup;
|
|
||||||
localStorage.setItem("showGroup", this.showGroup);
|
|
||||||
if (this.$root.page == 'service') {
|
|
||||||
this.$root.initTooltip();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
initSemiTransparent() {
|
|
||||||
const storedSemiTransparent = localStorage.getItem("semiTransparent");
|
|
||||||
const semiTransparent = storedSemiTransparent !== null ? JSON.parse(storedSemiTransparent) : false;
|
|
||||||
if (storedSemiTransparent === null) {
|
|
||||||
localStorage.setItem("semiTransparent", semiTransparent);
|
|
||||||
}
|
|
||||||
return semiTransparent;
|
|
||||||
},
|
|
||||||
toggleSemiTransparent(){
|
|
||||||
this.semiTransparent = !this.semiTransparent;
|
|
||||||
localStorage.setItem("semiTransparent", this.semiTransparent);
|
|
||||||
if(this.$root.page == 'index' || this.$root.page == 'network') {
|
|
||||||
this.reloadCharts(); // 重新载入echarts图表
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateCookie(name, value) {
|
updateCookie(name, value) {
|
||||||
document.cookie = name + "=" + value +"; path=/";
|
document.cookie = name + "=" + value +"; path=/";
|
||||||
},
|
},
|
||||||
@@ -104,6 +57,43 @@ const mixinsVue = {
|
|||||||
}
|
}
|
||||||
return cookieValue;
|
return cookieValue;
|
||||||
},
|
},
|
||||||
|
setTheme(title, store = false) {
|
||||||
|
this.theme = title;
|
||||||
|
document.body.setAttribute("theme", title);
|
||||||
|
if (store) {
|
||||||
|
localStorage.setItem("theme", title);
|
||||||
|
this.isSystemTheme = false;
|
||||||
|
if(this.$root.page == 'index') {
|
||||||
|
this.$root.reloadCharts(); //重新载入echarts图表
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setSystemTheme() {
|
||||||
|
localStorage.removeItem("theme");
|
||||||
|
this.initTheme();
|
||||||
|
this.isSystemTheme = true;
|
||||||
|
},
|
||||||
|
initTheme() {
|
||||||
|
const storeTheme = localStorage.getItem("theme");
|
||||||
|
if (storeTheme === 'dark' || storeTheme === 'light') {
|
||||||
|
this.setTheme(storeTheme, true);
|
||||||
|
} else {
|
||||||
|
this.isSystemTheme = true
|
||||||
|
const handleChange = (mediaQueryListEvent) => {
|
||||||
|
if (localStorage.getItem("theme")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (mediaQueryListEvent.matches) {
|
||||||
|
this.setTheme('dark');
|
||||||
|
} else {
|
||||||
|
this.setTheme('light');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const mediaQueryListDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
|
this.setTheme(mediaQueryListDark.matches ? 'dark' : 'light');
|
||||||
|
mediaQueryListDark.addEventListener("change", handleChange);
|
||||||
|
}
|
||||||
|
},
|
||||||
toFixed2(f) {
|
toFixed2(f) {
|
||||||
return f.toFixed(2)
|
return f.toFixed(2)
|
||||||
},
|
},
|
||||||
@@ -131,7 +121,6 @@ const mixinsVue = {
|
|||||||
},
|
},
|
||||||
handleScroll() {
|
handleScroll() {
|
||||||
this.showGoTop = window.scrollY >= 100;
|
this.showGoTop = window.scrollY >= 100;
|
||||||
if(this.showTools) this.showTools = false;
|
|
||||||
},
|
},
|
||||||
groupingData(data, field) {
|
groupingData(data, field) {
|
||||||
let map = new Map();
|
let map = new Map();
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
|
||||||
|
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
|
||||||
|
* */
|
||||||
|
|
||||||
|
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-245
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+4
-4
@@ -6,11 +6,11 @@
|
|||||||
{{.Version}}</small>
|
{{.Version}}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://unpkg.com/jquery@3.7.1/dist/jquery.min.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/jquery/3.6.0/jquery.min.js"></script>
|
||||||
<script src="https://unpkg.com/semantic-ui@2.4.0/dist/semantic.min.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/semantic-ui/2.4.1/semantic.min.js"></script>
|
||||||
<script src="/static/semantic-ui-alerts.min.js"></script>
|
<script src="/static/semantic-ui-alerts.min.js"></script>
|
||||||
<script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/vue/2.6.14/vue.min.js"></script>
|
||||||
<script src="/static/main.js?v20240714"></script>
|
<script src="/static/main.js?v20240224"></script>
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
updateLang({{.LANG }});
|
updateLang({{.LANG }});
|
||||||
|
|||||||
Vendored
+9
-10
@@ -1,22 +1,21 @@
|
|||||||
{{define "common/header"}}
|
{{define "common/header"}}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{.Conf.Language}}">
|
<html lang="{{.Conf.Language}}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<meta content="telephone=no" name="format-detection">
|
<meta content="telephone=no" name="format-detection">
|
||||||
<title>{{.Title}}</title>
|
<title>{{.Title}}</title>
|
||||||
<link rel="shortcut icon" type="image/png" href="/static/logo.svg?v20210804" />
|
<link rel="stylesheet" type="text/css"
|
||||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/semantic-ui@2.4.0/dist/semantic.min.css">
|
href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/semantic-ui/2.4.1/semantic.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/font-logos@0.17.0/assets/font-logos.css">
|
<link href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/font-logos/0.17/font-logos.min.css" type="text/css"
|
||||||
|
rel="stylesheet" />
|
||||||
<link rel="stylesheet" type="text/css" href="/static/semantic-ui-alerts.min.css">
|
<link rel="stylesheet" type="text/css" href="/static/semantic-ui-alerts.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/static/main.css?v20240813">
|
<link rel="stylesheet" type="text/css" href="/static/main.css?v2022042314">
|
||||||
<link rel="stylesheet" type="text/css" href="/static/darkmode.css?v20240813">
|
<link rel="shortcut icon" type="image/png" href="/static/logo.svg?v20210804" />
|
||||||
<script>
|
|
||||||
document.documentElement.setAttribute('nz-theme', window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
{{if ts .CustomCodeDashboard}} {{.CustomCodeDashboard|safe}} {{end}}
|
|
||||||
<body>
|
<body>
|
||||||
{{end}}
|
{{end}}
|
||||||
Vendored
-1
@@ -9,7 +9,6 @@
|
|||||||
<a class='item{{if eq .MatchedPath "/monitor"}} active{{end}}' href="/monitor"><i class="rss icon"></i>{{tr "Services"}}</a>
|
<a class='item{{if eq .MatchedPath "/monitor"}} active{{end}}' href="/monitor"><i class="rss icon"></i>{{tr "Services"}}</a>
|
||||||
<a class='item{{if eq .MatchedPath "/cron"}} active{{end}}' href="/cron"><i class="clock icon"></i>{{tr "Task"}}</a>
|
<a class='item{{if eq .MatchedPath "/cron"}} active{{end}}' href="/cron"><i class="clock icon"></i>{{tr "Task"}}</a>
|
||||||
<a class='item{{if eq .MatchedPath "/notification"}} active{{end}}' href="/notification"><i class="bell icon"></i>{{tr "Notification"}}</a>
|
<a class='item{{if eq .MatchedPath "/notification"}} active{{end}}' href="/notification"><i class="bell icon"></i>{{tr "Notification"}}</a>
|
||||||
<a class='item{{if eq .MatchedPath "/nat"}} active{{end}}' href="/nat"><i class="exchange icon"></i>{{tr "NAT"}}</a>
|
|
||||||
<a class='item{{if eq .MatchedPath "/setting"}} active{{end}}' href="/setting">
|
<a class='item{{if eq .MatchedPath "/setting"}} active{{end}}' href="/setting">
|
||||||
<i class="settings icon"></i>{{tr "Settings"}}
|
<i class="settings icon"></i>{{tr "Settings"}}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Vendored
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class=" actions">
|
||||||
<div class="ui negative button">{{tr "Cancel"}}</div>
|
<div class="ui negative button">{{tr "Cancel"}}</div>
|
||||||
<button class="ui positive nezha-primary-btn right labeled icon button">{{tr "Confirm"}}<i class="checkmark icon"></i>
|
<button class="ui positive nezha-primary-btn right labeled icon button">{{tr "Confirm"}}<i class="checkmark icon"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
+1
-1
@@ -60,7 +60,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class=" actions">
|
||||||
<div class="ui negative button">{{tr "Cancel"}}</div>
|
<div class="ui negative button">{{tr "Cancel"}}</div>
|
||||||
<button class="ui positive nezha-primary-btn right labeled icon button">{{tr "Confirm"}}<i class="checkmark icon"></i>
|
<button class="ui positive nezha-primary-btn right labeled icon button">{{tr "Confirm"}}<i class="checkmark icon"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Vendored
-31
@@ -1,31 +0,0 @@
|
|||||||
{{define "component/nat"}}
|
|
||||||
<div class="ui tiny nat modal transition hidden">
|
|
||||||
<div class="header">Add</div>
|
|
||||||
<div class="content">
|
|
||||||
<form id="natForm" class="ui form">
|
|
||||||
<input type="hidden" name="ID">
|
|
||||||
<div class="field">
|
|
||||||
<label>{{tr "Name"}}</label>
|
|
||||||
<input type="text" name="Name">
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<label>Agent ID</label>
|
|
||||||
<input type="number" name="ServerID" placeholder="1">
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<label>内网服务</label>
|
|
||||||
<input type="text" name="Host" placeholder="192.168.1.1:80(带端口)">
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<label>绑定域名</label>
|
|
||||||
<input type="text" name="Domain" placeholder="router.app.yourdomain.com">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="actions">
|
|
||||||
<div class="ui negative button">{{tr "Cancel"}}</div>
|
|
||||||
<button class="ui positive nezha-primary-btn right labeled icon button">{{tr "Confirm"}}<i class="checkmark icon"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
+2
-18
@@ -32,26 +32,10 @@
|
|||||||
<label>{{tr "EnableDDNS"}}</label>
|
<label>{{tr "EnableDDNS"}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<div class="ui enableipv4 checkbox">
|
|
||||||
<input name="EnableIPv4" type="checkbox" tabindex="0" />
|
|
||||||
<label>{{tr "EnableIPv4"}}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
|
||||||
<div class="ui enableipv6 checkbox">
|
|
||||||
<input name="EnableIpv6" type="checkbox" tabindex="0" />
|
|
||||||
<label>{{tr "EnableIpv6"}}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>{{tr "DDNSDomain"}}</label>
|
<label>{{tr "DDNSDomain"}}</label>
|
||||||
<input type="text" name="DDNSDomain" placeholder="{{tr "DDNSDomain"}}">
|
<input type="text" name="DDNSDomain" placeholder="{{tr "DDNSDomain"}}">
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<label>{{tr "DDNSProfile"}}</label>
|
|
||||||
<input type="text" name="DDNSProfile" placeholder="{{tr "DDNSProfile"}}">
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>{{tr "Note"}}</label>
|
<label>{{tr "Note"}}</label>
|
||||||
<textarea name="Note"></textarea>
|
<textarea name="Note"></textarea>
|
||||||
@@ -61,7 +45,7 @@
|
|||||||
<div class="ui message">
|
<div class="ui message">
|
||||||
{{if .Conf.GRPCHost}}
|
{{if .Conf.GRPCHost}}
|
||||||
curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install.sh -o nezha.sh && chmod
|
curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install.sh -o nezha.sh && chmod
|
||||||
+x nezha.sh && ./nezha.sh install_agent <code class="command">{{.Conf.GRPCHost}}</code> <code
|
+x nezha.sh && sudo ./nezha.sh install_agent <code class="command">{{.Conf.GRPCHost}}</code> <code
|
||||||
class="command">{{if .Conf.ProxyGRPCPort}}{{.Conf.ProxyGRPCPort}}{{else}}{{.Conf.GRPCPort}}{{end}}</code> <code
|
class="command">{{if .Conf.ProxyGRPCPort}}{{.Conf.ProxyGRPCPort}}{{else}}{{.Conf.GRPCPort}}{{end}}</code> <code
|
||||||
class="command hostSecret"></code> <code class="command">{{if .Conf.TLS}}--tls{{end}}</code>
|
class="command hostSecret"></code> <code class="command">{{if .Conf.TLS}}--tls{{end}}</code>
|
||||||
{{else}}
|
{{else}}
|
||||||
@@ -71,7 +55,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class=" actions">
|
||||||
<div class="ui negative button">{{tr "Cancel"}}</div>
|
<div class="ui negative button">{{tr "Cancel"}}</div>
|
||||||
<button class="ui positive nezha-primary-btn right labeled icon button">{{tr "Confirm"}}<i class="checkmark icon"></i>
|
<button class="ui positive nezha-primary-btn right labeled icon button">{{tr "Confirm"}}<i class="checkmark icon"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="ui basic table">
|
<table class="ui very basic table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{tr "Token"}}</th>
|
<th>{{tr "Token"}}</th>
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="ui basic table">
|
<table class="ui very basic table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="ui basic table">
|
<table class="ui very basic table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
|
|||||||
-54
@@ -1,54 +0,0 @@
|
|||||||
{{define "dashboard-default/nat"}}
|
|
||||||
{{template "common/header" .}}
|
|
||||||
{{template "common/menu" .}}
|
|
||||||
<div class="nb-container">
|
|
||||||
<div class="ui container">
|
|
||||||
<div class="ui grid">
|
|
||||||
<div class="right floated right aligned twelve wide column">
|
|
||||||
<button class="ui right labeled nezha-primary-btn icon button" onclick="addOrEditNAT()"><i
|
|
||||||
class="add icon"></i> Add
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<table class="ui basic table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>{{tr "Name"}}</th>
|
|
||||||
<th>Agent ID</th>
|
|
||||||
<th>内网服务</th>
|
|
||||||
<th>绑定域名</th>
|
|
||||||
<th>{{tr "Administration"}}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{range $item := .NAT}}
|
|
||||||
<tr>
|
|
||||||
<td>{{$item.ID}}</td>
|
|
||||||
<td>{{$item.Name}}</td>
|
|
||||||
<td>{{$item.ServerID}}</td>
|
|
||||||
<td>{{$item.Host}}</td>
|
|
||||||
<td>{{$item.Domain}}</td>
|
|
||||||
<td>
|
|
||||||
<div class="ui mini icon buttons">
|
|
||||||
<button class="ui button" onclick="addOrEditNAT({{$item}})">
|
|
||||||
<i class="edit icon"></i>
|
|
||||||
</button>
|
|
||||||
<button class="ui button"
|
|
||||||
onclick="showConfirm('确定删除NAT隧道?','确认删除',deleteRequest,'/api/nat/'+{{$item.ID}})">
|
|
||||||
<i class="trash alternate outline icon"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{template "component/nat"}}
|
|
||||||
{{template "common/footer" .}}
|
|
||||||
<script>
|
|
||||||
$('.checkbox').checkbox()
|
|
||||||
</script>
|
|
||||||
{{end}}
|
|
||||||
+2
-2
@@ -10,7 +10,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="ui basic table">
|
<table class="ui very basic table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="ui basic table">
|
<table class="ui very basic table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
{{define "dashboard-default/redirect"}}
|
{{define "dashboard-default/redirect"}}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{.Conf.Language}}">
|
<html lang="{{.Conf.Language}}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Redirecting..</title>
|
<title>Redirecting..</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<p>If you are not redirected, please click <a href="{{.URL}}">here</a>.</p>
|
<p>If you are not redirected, please click <a href="{{.URL}}">here</a>.</p>
|
||||||
<script>window.location.href = "{{.URL}}"</script>
|
<script>window.location.href = "{{.URL}}"</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
{{end}}
|
{{end}}
|
||||||
+3
-12
@@ -19,7 +19,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="ui basic table">
|
<table class="ui very basic table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><button onclick="checkAllServer()" class="ui mini nezha-primary-btn button">{{tr "SelectAll"}}</button></th>
|
<th><button onclick="checkAllServer()" class="ui mini nezha-primary-btn button">{{tr "SelectAll"}}</button></th>
|
||||||
@@ -30,8 +30,6 @@
|
|||||||
<th>{{tr "VersionNumber"}}</th>
|
<th>{{tr "VersionNumber"}}</th>
|
||||||
<th>{{tr "HideForGuest"}}</th>
|
<th>{{tr "HideForGuest"}}</th>
|
||||||
<th>{{tr "EnableDDNS"}}</th>
|
<th>{{tr "EnableDDNS"}}</th>
|
||||||
<th>{{tr "EnableIPv4"}}</th>
|
|
||||||
<th>{{tr "EnableIpv6"}}</th>
|
|
||||||
<th>{{tr "DDNSDomain"}}</th>
|
<th>{{tr "DDNSDomain"}}</th>
|
||||||
<th>{{tr "Secret"}}</th>
|
<th>{{tr "Secret"}}</th>
|
||||||
<th>{{tr "OneKeyInstall"}}</th>
|
<th>{{tr "OneKeyInstall"}}</th>
|
||||||
@@ -50,8 +48,6 @@
|
|||||||
<td>{{$server.Host.Version}}</td>
|
<td>{{$server.Host.Version}}</td>
|
||||||
<td>{{$server.HideForGuest}}</td>
|
<td>{{$server.HideForGuest}}</td>
|
||||||
<td>{{$server.EnableDDNS}}</td>
|
<td>{{$server.EnableDDNS}}</td>
|
||||||
<td>{{$server.EnableIPv4}}</td>
|
|
||||||
<td>{{$server.EnableIpv6}}</td>
|
|
||||||
<td>{{$server.DDNSDomain}}</td>
|
<td>{{$server.DDNSDomain}}</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="ui icon green mini button" data-clipboard-text="{{$server.Secret}}" data-tooltip="{{tr "ClickToCopy"}}">
|
<button class="ui icon green mini button" data-clipboard-text="{{$server.Secret}}" data-tooltip="{{tr "ClickToCopy"}}">
|
||||||
@@ -60,7 +56,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="ui icon green mini button"
|
<button class="ui icon green mini button"
|
||||||
data-clipboard-text="{{if $.Conf.GRPCHost}}{{if eq $.Conf.Language "zh-CN"}}curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install.sh{{else}}curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install_en.sh{{end}} -o nezha.sh && chmod +x nezha.sh && ./nezha.sh install_agent {{$.Conf.GRPCHost}} {{if $.Conf.ProxyGRPCPort}}{{$.Conf.ProxyGRPCPort}}{{else}}{{$.Conf.GRPCPort}}{{end}} {{$server.Secret}}{{if $.Conf.TLS}} --tls{{end}}{{else}}{{tr "NoDomainAlert"}}{{end}}"
|
data-clipboard-text="{{if $.Conf.GRPCHost}}{{if eq $.Conf.Language "zh-CN"}}curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install.sh{{else}}curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install_en.sh{{end}} -o nezha.sh && chmod +x nezha.sh && sudo ./nezha.sh install_agent {{$.Conf.GRPCHost}} {{if $.Conf.ProxyGRPCPort}}{{$.Conf.ProxyGRPCPort}}{{else}}{{$.Conf.GRPCPort}}{{end}} {{$server.Secret}}{{if $.Conf.TLS}} --tls{{end}}{{else}}{{tr "NoDomainAlert"}}{{end}}"
|
||||||
data-tooltip="{{tr "ClickToCopy"}}">
|
data-tooltip="{{tr "ClickToCopy"}}">
|
||||||
<i class="linux icon"></i>
|
<i class="linux icon"></i>
|
||||||
</button>
|
</button>
|
||||||
@@ -69,11 +65,6 @@
|
|||||||
data-tooltip="{{tr "ClickToCopy"}}">
|
data-tooltip="{{tr "ClickToCopy"}}">
|
||||||
<i class="windows icon"></i>
|
<i class="windows icon"></i>
|
||||||
</button>
|
</button>
|
||||||
<button class="ui icon green mini button"
|
|
||||||
data-clipboard-text="{{if $.Conf.GRPCHost}}curl -L https://raw.githubusercontent.com/naiba/nezha/master/script/install.command -o nezha.command && chmod +x nezha.command && sudo ./nezha.command install_agent {{$.Conf.GRPCHost}} {{if $.Conf.ProxyGRPCPort}}{{$.Conf.ProxyGRPCPort}}{{else}}{{$.Conf.GRPCPort}}{{end}} {{$server.Secret}}{{if $.Conf.TLS}} --tls{{end}}{{else}}{{tr "NoDomainAlert"}}{{end}}"
|
|
||||||
data-tooltip="{{tr "ClickToCopy"}}">
|
|
||||||
<i class="apple icon"></i>
|
|
||||||
</button>
|
|
||||||
</td>
|
</td>
|
||||||
<td style="word-break: break-word;white-space: pre-wrap;">{{$server.Note}}</td>
|
<td style="word-break: break-word;white-space: pre-wrap;">{{$server.Note}}</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -98,7 +89,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{template "component/server" .}}
|
{{template "component/server" .}}
|
||||||
{{template "common/footer" .}}
|
{{template "common/footer" .}}
|
||||||
<script src="https://unpkg.com/clipboard@2.0.11/dist/clipboard.min.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/clipboard.js/2.0.10/clipboard.min.js" type="application/javascript"></script>
|
||||||
<script>
|
<script>
|
||||||
var clipboard = new ClipboardJS('.ui.icon.green.mini.button');
|
var clipboard = new ClipboardJS('.ui.icon.green.mini.button');
|
||||||
const checkBoxList = document.querySelectorAll('tbody > tr > td > input.nezha-servers[type=checkbox]')
|
const checkBoxList = document.querySelectorAll('tbody > tr > td > input.nezha-servers[type=checkbox]')
|
||||||
|
|||||||
+3
-7
@@ -41,10 +41,6 @@
|
|||||||
<label>{{tr "CustomCodes"}}</label>
|
<label>{{tr "CustomCodes"}}</label>
|
||||||
<textarea name="CustomCode">{{.Conf.Site.CustomCode}}</textarea>
|
<textarea name="CustomCode">{{.Conf.Site.CustomCode}}</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
|
||||||
<label>{{tr "CustomCodesDashboard"}}</label>
|
|
||||||
<textarea name="CustomCodeDashboard">{{.Conf.Site.CustomCodeDashboard}}</textarea>
|
|
||||||
</div>
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>{{tr "AccessPassword"}}</label>
|
<label>{{tr "AccessPassword"}}</label>
|
||||||
<input type="text" name="ViewPassword" placeholder="" value="{{.Conf.Site.ViewPassword}}">
|
<input type="text" name="ViewPassword" placeholder="" value="{{.Conf.Site.ViewPassword}}">
|
||||||
@@ -132,13 +128,13 @@
|
|||||||
})
|
})
|
||||||
$('.checkbox').checkbox()
|
$('.checkbox').checkbox()
|
||||||
$('#settingForm').find("select[name=Cover]").val({{.Conf.Cover }});
|
$('#settingForm').find("select[name=Cover]").val({{.Conf.Cover }});
|
||||||
{{ if .Conf.EnableIPChangeNotification}}
|
{{if .Conf.EnableIPChangeNotification}}
|
||||||
$('.checkbox.ip-change').checkbox('set checked')
|
$('.checkbox.ip-change').checkbox('set checked')
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .Conf.EnablePlainIPInNotification}}
|
{{if .Conf.EnablePlainIPInNotification}}
|
||||||
$('.checkbox.plain-ip').checkbox('set checked')
|
$('.checkbox.plain-ip').checkbox('set checked')
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .Conf.DisableSwitchTemplateInFrontend }}
|
{{if .Conf.DisableSwitchTemplateInFrontend }}
|
||||||
$('.checkbox.disable-switch-template').checkbox('set checked')
|
$('.checkbox.disable-switch-template').checkbox('set checked')
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
+7
-11
@@ -8,8 +8,9 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>tty@{{.ServerName}} - {{.Title}}</title>
|
<title>tty@{{.ServerName}} - {{.Title}}</title>
|
||||||
<link rel="shortcut icon" type="image/png" href="/static/logo.svg?v20210804" />
|
<link rel="shortcut icon" type="image/png" href="/static/logo.svg?v20210804" />
|
||||||
<link type="text/css" rel="stylesheet" href="https://unpkg.com/[email protected]/css/xterm.css" />
|
<link href="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/xterm/4.11.0/xterm.css" type="text/css" rel="stylesheet"/>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
html,
|
html,
|
||||||
body,
|
body,
|
||||||
@@ -27,16 +28,14 @@
|
|||||||
|
|
||||||
<body onresize="onResize()">
|
<body onresize="onResize()">
|
||||||
<div id="terminal-container"></div>
|
<div id="terminal-container"></div>
|
||||||
<script src="https://unpkg.com/[email protected]/lib/xterm.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/xterm/4.11.0/xterm.js" type="application/javascript"></script>
|
||||||
<script src="https://unpkg.com/@xterm/[email protected]/lib/addon-fit.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/xterm/4.11.0/addons/attach/xterm-addon-attach.js"></script>
|
||||||
<script src="https://unpkg.com/@xterm/[email protected]/lib/addon-web-links.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/xterm/4.11.0/addons/fit/xterm-addon-fit.js"></script>
|
||||||
<script src="https://unpkg.com/[email protected]/lib/trzsz.js"></script>
|
|
||||||
<script>
|
<script>
|
||||||
let sendResizing = false;
|
let sendResizing = false;
|
||||||
|
|
||||||
function doResize() {
|
function doResize() {
|
||||||
fitAddon.fit()
|
fitAddon.fit()
|
||||||
|
|
||||||
const w = fitAddon.proposeDimensions();
|
const w = fitAddon.proposeDimensions();
|
||||||
const prefix = new Int8Array([1]);
|
const prefix = new Int8Array([1]);
|
||||||
const resizeMessage = new TextEncoder().encode(JSON.stringify({
|
const resizeMessage = new TextEncoder().encode(JSON.stringify({
|
||||||
@@ -74,13 +73,10 @@
|
|||||||
cursorBlink: true,
|
cursorBlink: true,
|
||||||
});
|
});
|
||||||
const socket = new WebSocket((window.location.protocol == 'https:' ? 'wss' : 'ws') + '://' + window.location.host + '/terminal/' + '{{.SessionID}}');
|
const socket = new WebSocket((window.location.protocol == 'https:' ? 'wss' : 'ws') + '://' + window.location.host + '/terminal/' + '{{.SessionID}}');
|
||||||
socket.binaryType = 'arraybuffer';
|
const attachAddon = new AttachAddon.AttachAddon(socket);
|
||||||
|
|
||||||
const trzszAddon = new TrzszAddon(socket);
|
|
||||||
term.loadAddon(trzszAddon);
|
|
||||||
const fitAddon = new FitAddon.FitAddon();
|
const fitAddon = new FitAddon.FitAddon();
|
||||||
|
term.loadAddon(attachAddon);
|
||||||
term.loadAddon(fitAddon);
|
term.loadAddon(fitAddon);
|
||||||
|
|
||||||
term.open(document.getElementById('terminal-container'));
|
term.open(document.getElementById('terminal-container'));
|
||||||
|
|
||||||
socket.onopen = () => {
|
socket.onopen = () => {
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/semantic-ui/2.4.1/semantic.min.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/semantic-ui/2.4.1/semantic.min.js"></script>
|
||||||
<script src="/static/semantic-ui-alerts.min.js"></script>
|
<script src="/static/semantic-ui-alerts.min.js"></script>
|
||||||
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/vue/2.6.14/vue.min.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/vue/2.6.14/vue.min.js"></script>
|
||||||
<script src="/static/main.js?v20240330"></script>
|
<script src="/static/main.js?v20240224"></script>
|
||||||
<script src="/static/theme-default/js/mixin.js?v20240302"></script>
|
<script src="/static/theme-default/js/mixin.js?v20240302"></script>
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
|
|||||||
@@ -24,9 +24,6 @@
|
|||||||
[<span
|
[<span
|
||||||
v-if="server.Host.Virtualization">@#server.Host.Virtualization#@:</span>@#server.Host.Arch#@]<br />
|
v-if="server.Host.Virtualization">@#server.Host.Virtualization#@:</span>@#server.Host.Arch#@]<br />
|
||||||
CPU: @#server.Host.CPU#@<br />
|
CPU: @#server.Host.CPU#@<br />
|
||||||
<template v-if="server.Host.GPU">
|
|
||||||
GPU: @#server.Host.GPU#@<br />
|
|
||||||
</template>
|
|
||||||
{{tr "DiskUsed"}}:
|
{{tr "DiskUsed"}}:
|
||||||
@#formatByteSize(server.State.DiskUsed)#@/@#formatByteSize(server.Host.DiskTotal)#@<br />
|
@#formatByteSize(server.State.DiskUsed)#@/@#formatByteSize(server.Host.DiskTotal)#@<br />
|
||||||
{{tr "MemUsed"}}:
|
{{tr "MemUsed"}}:
|
||||||
|
|||||||
@@ -24,9 +24,6 @@
|
|||||||
<i :class="item.icon + ' icon'"></i>@#item.name#@
|
<i :class="item.icon + ' icon'"></i>@#item.name#@
|
||||||
<i class="check icon" v-if="preferredTemplate === item.key"></i>
|
<i class="check icon" v-if="preferredTemplate === item.key"></i>
|
||||||
</a>
|
</a>
|
||||||
<a v-if="defaultTemplate === 'custom'" @click="toggleTemplate('custom')" class="item">
|
|
||||||
<i class="expand icon"></i>Custom
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
+317
-241
@@ -20,281 +20,357 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body data-theme="light" data-gridlist="grid">
|
<body data-theme="light" data-gridlist="grid">
|
||||||
<header>
|
<header>
|
||||||
<section class="nav-bar clearfix">
|
<section class="nav-bar clearfix">
|
||||||
<figure class="logo">
|
<figure class="logo">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
<img src="/static/logo.svg?v20210804" alt='{{tr "NezhaMonitoring"}}' width="50" height="50">
|
<img src="/static/logo.svg?v20210804" alt='{{tr "NezhaMonitoring"}}' width="50" height="50">
|
||||||
</a>
|
</a>
|
||||||
<a href="/">{{.Conf.Site.Brand}}</a>
|
<a href="/">{{.Conf.Site.Brand}}</a>
|
||||||
</figure>
|
</figure>
|
||||||
<div class="icon-container">
|
<div class="icon-container">
|
||||||
<div class="row cf">
|
<div class="row cf">
|
||||||
<div class="three col">
|
<div class="three col">
|
||||||
<div class="hamburger" id="hamburger-icon"><span class="line"></span><span
|
<div class="hamburger" id="hamburger-icon"><span class="line"></span><span
|
||||||
class="line"></span><span class="line"></span></div>
|
class="line"></span><span class="line"></span></div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav class="nav-menu">
|
|
||||||
<ul>
|
|
||||||
<li><a href="/">{{tr "Home"}}</a></li>
|
|
||||||
<li><a href="/service">{{tr "Services"}}</a></li>
|
|
||||||
<li><a href="/network">{{tr "NetworkSpiter"}}</a></li>
|
|
||||||
{{if .Admin}}
|
|
||||||
<li><a href="/server">{{tr "AdminPanel"}}</a></li>
|
|
||||||
{{else}}
|
|
||||||
<li><a href="/login">{{tr "Login"}}</a></li>
|
|
||||||
{{end}}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</section>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div id="network">
|
|
||||||
<div class="server-info-container" v-for='server in servers' :id="server.ID">
|
|
||||||
<div class="info-body" @click="redirectNetwork(server.ID)">
|
|
||||||
<ul class="server-info-body-container">
|
|
||||||
<li>
|
|
||||||
<h3>@#server.Name#@</h3>
|
|
||||||
</li>
|
|
||||||
<li><img :src="'/static/theme-daynight/img/flag/'+(server.Host&&server.Host.CountryCode?server.Host.CountryCode.toUpperCase():'CN')+'.png'"
|
|
||||||
:title="server.Host.CountryCode.toUpperCase()" /></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="network-chart" style="height: 800px;overflow: hidden">
|
<nav class="nav-menu">
|
||||||
<div id="monitor-info-container" style="height: 520px;max-width: 1400px">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="sidebar-container">
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><i class="fas fa-sun" title='{{tr "LightMode"}}'></i><span>{{tr "LightMode"}}</span></li>
|
<li><a href="/">{{tr "Home"}}</a></li>
|
||||||
<li><i class="fas fa-moon" title='{{tr "DarkMode"}}'></i><span>{{tr "DarkMode"}}</span></li>
|
<li><a href="/service">{{tr "Services"}}</a></li>
|
||||||
<li><i class="fas fa-th" title='{{tr "GridLayout"}}'></i><span>{{tr "GridLayout"}}</span></li>
|
<li><a href="/network">{{tr "NetworkSpiter"}}</a></li>
|
||||||
<li><i class="fas fa-list-ul" title='{{tr "ListLayout"}}'></i><span>{{tr "ListLayout"}}</span></li>
|
{{if .Admin}}
|
||||||
|
<li><a href="/server">{{tr "AdminPanel"}}</a></li>
|
||||||
|
{{else}}
|
||||||
|
<li><a href="/login">{{tr "Login"}}</a></li>
|
||||||
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</nav>
|
||||||
</main>
|
|
||||||
|
|
||||||
<section class="dark-light-toggle">
|
|
||||||
<label class="switcher">
|
|
||||||
<input type="checkbox" name="theme" id="dark-light" />
|
|
||||||
<div>
|
|
||||||
<i class="fas fa-adjust"></i>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<!-- Back to top button -->
|
<main>
|
||||||
<a id="back-to-top"></a>
|
<div id="network">
|
||||||
|
<div class="server-info-container" v-for='server in servers' :id="server.ID" style="font-size: .6em">
|
||||||
|
<div class="info-body" @click="redirectNetwork(server.ID)">
|
||||||
|
<ul class="server-info-body-container">
|
||||||
|
<li>
|
||||||
|
<h3>@#server.Name#@</h3>
|
||||||
|
</li>
|
||||||
|
<li><img :src="'/static/theme-daynight/img/flag/'+(server.Host&&server.Host.CountryCode?server.Host.CountryCode.toUpperCase():'CN')+'.png'"
|
||||||
|
:title="server.Host.CountryCode.toUpperCase()" /></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="network-chart" style="height: 800px;overflow: hidden">
|
||||||
|
<div id="monitor-info-container" style="height: 520px;max-width: 1400px">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-container">
|
||||||
|
<ul>
|
||||||
|
<li><i class="fas fa-sun" title='{{tr "LightMode"}}'></i><span>{{tr "LightMode"}}</span></li>
|
||||||
|
<li><i class="fas fa-moon" title='{{tr "DarkMode"}}'></i><span>{{tr "DarkMode"}}</span></li>
|
||||||
|
<li><i class="fas fa-th" title='{{tr "GridLayout"}}'></i><span>{{tr "GridLayout"}}</span></li>
|
||||||
|
<li><i class="fas fa-list-ul" title='{{tr "ListLayout"}}'></i><span>{{tr "ListLayout"}}</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
<footer>
|
<section class="dark-light-toggle">
|
||||||
<div class="footer-container">
|
<label class="switcher">
|
||||||
<div><a href="https://github.com/naiba/nezha" target="_blank">Powered by {{tr "NezhaMonitoring"}} ·
|
<input type="checkbox" name="theme" id="dark-light" />
|
||||||
{{.Version}}</a>
|
<div>
|
||||||
<p>© <span id="copyright-date">
|
<i class="fas fa-adjust"></i>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Back to top button -->
|
||||||
|
<a id="back-to-top"></a>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<div class="footer-container">
|
||||||
|
<div><a href="https://github.com/naiba/nezha" target="_blank">Powered by {{tr "NezhaMonitoring"}} · {{.Version}}</a>
|
||||||
|
<p>© <span id="copyright-date">
|
||||||
<script>document.getElementById('copyright-date').appendChild(document.createTextNode(new Date().getFullYear()))</script>
|
<script>document.getElementById('copyright-date').appendChild(document.createTextNode(new Date().getFullYear()))</script>
|
||||||
</span> · <a href="https://blog.jackiesung.com" target="_blank">Theme designed by Jackie Sung</a>
|
</span> · <a href="https://blog.jackiesung.com" target="_blank">Theme designed by Jackie Sung</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
<script src="/static/theme-daynight/js/main.js?v202102012266"></script>
|
<script src="/static/theme-daynight/js/main.js?v202102012266"></script>
|
||||||
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/vue/2.6.14/vue.min.js"></script>
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/vue/2.6.14/vue.min.js"></script>
|
||||||
<script
|
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/limonte-sweetalert2/11.4.4/sweetalert2.all.min.js"></script>
|
||||||
src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-y/limonte-sweetalert2/11.4.4/sweetalert2.all.min.js"></script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const monitorInfo = JSON.parse('{{.MonitorInfos}}');
|
const monitorInfo = JSON.parse('{{.MonitorInfos}}');
|
||||||
const initData = JSON.parse('{{.Servers}}').servers;
|
const initData = JSON.parse('{{.Servers}}').servers;
|
||||||
let MaxTCPPingValue = {{.Conf.MaxTCPPingValue}};
|
let MaxTCPPingValue = {{.Conf.MaxTCPPingValue}};
|
||||||
// 基于准备好的dom,初始化echarts实例
|
if (MaxTCPPingValue == null) {
|
||||||
const myChart = echarts.init(document.getElementById('monitor-info-container'));
|
MaxTCPPingValue = 1000;
|
||||||
|
}
|
||||||
// 使用刚指定的配置项和数据显示图表。
|
new Vue({
|
||||||
var statusCards = new Vue({
|
el: '#app',
|
||||||
el: '#network',
|
delimiters: ['@#', '#@'],
|
||||||
delimiters: ['@#', '#@'],
|
data: {
|
||||||
data: {
|
page: 'network',
|
||||||
servers: initData,
|
defaultTemplate: {{.Conf.Site.Theme}},
|
||||||
cache: [],
|
templates: {{.Themes}},
|
||||||
option: {
|
servers: initData,
|
||||||
tooltip: {
|
option: {
|
||||||
trigger: 'axis',
|
tooltip: {
|
||||||
position: function (pt) {
|
trigger: 'axis',
|
||||||
return [pt[0], '10%'];
|
position: function (pt) {
|
||||||
},
|
return [pt[0], '10%'];
|
||||||
formatter: function (params) {
|
|
||||||
let result = params[0].axisValueLabel + "<br />";
|
|
||||||
params.forEach(function (item) {
|
|
||||||
result += item.marker + item.seriesName + ": " + item.value[1].toFixed(2) + " ms<br />";
|
|
||||||
})
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
confine: true,
|
|
||||||
transitionDuration: 0
|
|
||||||
},
|
},
|
||||||
title: {
|
formatter: function(params){
|
||||||
left: 'center',
|
let result = params[0].axisValueLabel + "<br />";
|
||||||
text: "",
|
params.forEach(function(item){
|
||||||
textStyle: {}
|
result += item.marker + item.seriesName + ": " + item.value[1].toFixed(2) + " ms<br />";
|
||||||
|
})
|
||||||
|
return result;
|
||||||
},
|
},
|
||||||
legend: {
|
confine: true,
|
||||||
top: '5%',
|
transitionDuration: 0
|
||||||
data: [],
|
},
|
||||||
textStyle: {
|
title: {
|
||||||
fontSize: 14
|
left: 'center',
|
||||||
}
|
text: "",
|
||||||
},
|
textStyle: {}
|
||||||
toolbox: {
|
},
|
||||||
feature: {
|
legend: {
|
||||||
dataZoom: {
|
top: '5%',
|
||||||
yAxisIndex: 'none'
|
data: [],
|
||||||
},
|
textStyle: {
|
||||||
restore: {},
|
fontSize: 14
|
||||||
saveAsImage: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dataZoom: [
|
|
||||||
{
|
|
||||||
start: 94,
|
|
||||||
end: 100
|
|
||||||
}
|
|
||||||
],
|
|
||||||
xAxis: {
|
|
||||||
type: 'time',
|
|
||||||
boundaryGap: false
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
boundaryGap: [0, '100%']
|
|
||||||
},
|
|
||||||
series: [],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.DarkMode();
|
|
||||||
this.parseMonitorInfo(monitorInfo);
|
|
||||||
window.addEventListener('resize', this.resizeHandle);
|
|
||||||
},
|
|
||||||
destroyed() {
|
|
||||||
window.removeEventListener('resize', this.resizeHandle)
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
DarkMode() {
|
|
||||||
const hour = new Date(Date.now()).getHours()
|
|
||||||
if (hour > 17 || hour < 4) {
|
|
||||||
document.querySelector("input[name=theme]").checked = true;
|
|
||||||
document.getElementsByTagName("BODY")[0].setAttribute('data-theme', 'dark');
|
|
||||||
document.getElementById("monitor-info-container").style.backgroundColor = "#1E1E1E";
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
redirectNetwork(id) {
|
grid: {
|
||||||
|
left: '8%',
|
||||||
|
right: '8%',
|
||||||
|
},
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
||||||
|
toolbox: {
|
||||||
|
feature: {
|
||||||
|
dataZoom: {
|
||||||
|
yAxisIndex: 'none'
|
||||||
|
},
|
||||||
|
restore: {},
|
||||||
|
saveAsImage: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
start: 0,
|
||||||
|
end: 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
xAxis: {
|
||||||
|
type: 'time',
|
||||||
|
boundaryGap: false
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
boundaryGap: false
|
||||||
|
},
|
||||||
|
series: [],
|
||||||
|
},
|
||||||
|
chartOnOff: true,
|
||||||
|
},
|
||||||
|
mixins: [mixinsVue],
|
||||||
|
mounted() {
|
||||||
|
this.renderChart();
|
||||||
|
this.parseMonitorInfo(monitorInfo);
|
||||||
|
window.addEventListener('resize', this.resizeHandle);
|
||||||
|
},
|
||||||
|
destroyed () {
|
||||||
|
window.removeEventListener('resize', this.resizeHandle)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getFontLogoClass(str) {
|
||||||
|
if (["almalinux",
|
||||||
|
"alpine",
|
||||||
|
"aosc",
|
||||||
|
"apple",
|
||||||
|
"archlinux",
|
||||||
|
"archlabs",
|
||||||
|
"artix",
|
||||||
|
"budgie",
|
||||||
|
"centos",
|
||||||
|
"coreos",
|
||||||
|
"debian",
|
||||||
|
"deepin",
|
||||||
|
"devuan",
|
||||||
|
"docker",
|
||||||
|
"elementary",
|
||||||
|
"fedora",
|
||||||
|
"ferris",
|
||||||
|
"flathub",
|
||||||
|
"freebsd",
|
||||||
|
"gentoo",
|
||||||
|
"gnu-guix",
|
||||||
|
"illumos",
|
||||||
|
"kali-linux",
|
||||||
|
"linuxmint",
|
||||||
|
"mageia",
|
||||||
|
"mandriva",
|
||||||
|
"manjaro",
|
||||||
|
"nixos",
|
||||||
|
"openbsd",
|
||||||
|
"opensuse",
|
||||||
|
"pop-os",
|
||||||
|
"raspberry-pi",
|
||||||
|
"redhat",
|
||||||
|
"rocky-linux",
|
||||||
|
"sabayon",
|
||||||
|
"slackware",
|
||||||
|
"snappy",
|
||||||
|
"solus",
|
||||||
|
"tux",
|
||||||
|
"ubuntu",
|
||||||
|
"void",
|
||||||
|
"zorin"].indexOf(str)
|
||||||
|
> -1) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
if (['openwrt', 'linux', "immortalwrt"].indexOf(str) > -1) {
|
||||||
|
return 'tux';
|
||||||
|
}
|
||||||
|
if (str == 'amazon') {
|
||||||
|
return 'redhat';
|
||||||
|
}
|
||||||
|
if (str == 'arch') {
|
||||||
|
return 'archlinux';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
redirectNetwork(id) {
|
||||||
this.getMonitorHistory(id)
|
this.getMonitorHistory(id)
|
||||||
.then(function (monitorInfo) {
|
.then(function(monitorInfo) {
|
||||||
var vm = network.__vue__;
|
var vm = app.__vue__;
|
||||||
vm.parseMonitorInfo(monitorInfo);
|
vm.parseMonitorInfo(monitorInfo);
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function(error){
|
||||||
window.location.href = "/404";
|
window.location.href = "/404";
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getMonitorHistory(id) {
|
getMonitorHistory(id) {
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
url: "/api/v1/monitor/" + id,
|
url: "/api/v1/monitor/"+id,
|
||||||
method: "GET"
|
method: "GET"
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
parseMonitorInfo(monitorInfo) {
|
parseMonitorInfo(monitorInfo) {
|
||||||
let tSeries = [];
|
let tSeries = [];
|
||||||
let tLegendData = [];
|
let tLegendData = [];
|
||||||
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
|
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
|
||||||
for (let i = 0; i < monitorInfo.result.length; i++) {
|
let maxPing = 0;
|
||||||
var lcolor = lcolors[i % lcolors.length];
|
for (let i = 0; i < monitorInfo.result.length; i++) {
|
||||||
var rgbaColorMarker = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.5)';
|
for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
|
||||||
var rgbaColorBar = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.35)';
|
avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
|
||||||
let loss = 0;
|
if ( avgDelay < MaxTCPPingValue && avgDelay > maxPing) {
|
||||||
let data = [];
|
maxPing = avgDelay;
|
||||||
let datal = [];
|
|
||||||
for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
|
|
||||||
avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
|
|
||||||
if (avgDelay > 0 && avgDelay < MaxTCPPingValue) {
|
|
||||||
data.push([monitorInfo.result[i].created_at[j], avgDelay]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
loss += 1;
|
|
||||||
datal.push({
|
|
||||||
xAxis: monitorInfo.result[i].created_at[j],
|
|
||||||
label: { show: false },
|
|
||||||
emphasis: { disabled: true },
|
|
||||||
lineStyle: {
|
|
||||||
type: "solid",
|
|
||||||
color: rgbaColorBar
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
|
}
|
||||||
if (lossRate > 99) {
|
}
|
||||||
datal = [];
|
for (let i = 0; i < monitorInfo.result.length; i++) {
|
||||||
|
var lcolor = lcolors[i % lcolors.length];
|
||||||
|
var rgbaColorMarker = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.5)';
|
||||||
|
var rgbaColorBar = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.35)';
|
||||||
|
let loss = 0;
|
||||||
|
let data = [];
|
||||||
|
let datal = [];
|
||||||
|
for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
|
||||||
|
avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
|
||||||
|
if (avgDelay > 0 && avgDelay < MaxTCPPingValue) {
|
||||||
|
data.push([monitorInfo.result[i].created_at[j], avgDelay]);
|
||||||
}
|
}
|
||||||
legendName = monitorInfo.result[i].monitor_name + " " + lossRate + "%";
|
else {
|
||||||
tLegendData.push(legendName);
|
loss += 1;
|
||||||
tSeries.push({
|
datal.push([monitorInfo.result[i].created_at[j], maxPing]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
|
||||||
|
if (lossRate > 99) {
|
||||||
|
datal = [];
|
||||||
|
}
|
||||||
|
legendName = monitorInfo.result[i].monitor_name +" "+ lossRate + "%";
|
||||||
|
tLegendData.push(legendName);
|
||||||
|
tSeries.push({
|
||||||
name: legendName,
|
name: legendName,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
smooth: true,
|
smooth: true,
|
||||||
symbol: 'none',
|
symbol: 'none',
|
||||||
data: data,
|
data: data,
|
||||||
markLine: {
|
|
||||||
symbol: "none",
|
|
||||||
symbolSize: 0,
|
|
||||||
data: datal
|
|
||||||
},
|
|
||||||
markPoint: {
|
markPoint: {
|
||||||
data: [
|
data: [
|
||||||
{ type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } },
|
{ type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } },
|
||||||
{ type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8, offset: [0, 7.5] }, symbolRotate: 180 }
|
{ type: 'min', symbol: 'pin', name: 'Min', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8, offset: [0, 7.5] }, symbolRotate: 180 }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
tSeries.push({
|
||||||
this.option.title.text = monitorInfo.result[0].server_name;
|
name: legendName,
|
||||||
this.option.series = tSeries;
|
type: 'bar',
|
||||||
this.option.legend.data = tLegendData;
|
smooth: true,
|
||||||
myChart.clear();
|
symbol: 'none',
|
||||||
myChart.setOption(this.option);
|
data: datal,
|
||||||
},
|
itemStyle: { color: rgbaColorBar }
|
||||||
resizeHandle() {
|
});
|
||||||
myChart.resize();
|
}
|
||||||
},
|
this.option.title.text = monitorInfo.result[0].server_name;
|
||||||
}
|
this.option.series = tSeries;
|
||||||
});
|
this.option.legend.data = tLegendData;
|
||||||
</script>
|
this.myChart.clear();
|
||||||
|
this.myChart.setOption(this.option);
|
||||||
|
},
|
||||||
|
this.option.title.text = monitorInfo.result[0].server_name;
|
||||||
|
this.option.series = tSeries;
|
||||||
|
this.option.legend.data = tLegendData;
|
||||||
|
this.myChart.clear();
|
||||||
|
this.myChart.setOption(this.option);
|
||||||
|
},
|
||||||
|
isWindowsPlatform(str) {
|
||||||
|
return str.includes('Windows')
|
||||||
|
},
|
||||||
|
renderChart() {
|
||||||
|
this.myChart = echarts.init(this.$refs.chartDom);
|
||||||
|
this.myChart.setOption(this.option);
|
||||||
|
},
|
||||||
|
resizeHandle () {
|
||||||
|
this.myChart.resize();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.myChart.dispose();
|
||||||
|
this.myChart = null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
<style>
|
<style>
|
||||||
#network {
|
#network {
|
||||||
width: calc(100vw - 6em);
|
display: grid;
|
||||||
max-width: 1400px;
|
/*grid-template-columns: repeat(5, 1fr);*/
|
||||||
margin: 1em auto;
|
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
|
||||||
}
|
grid-gap: 1em;
|
||||||
|
width: 100%;
|
||||||
#monitor-info-container {
|
width: calc(100vw - 6em);
|
||||||
margin: 0em auto;
|
max-width: 1400px;
|
||||||
align-content: start;
|
margin: 1em auto;
|
||||||
background-color: #F1F1F2;
|
align-content: start;
|
||||||
}
|
}
|
||||||
|
#monitor-info-container{
|
||||||
.server-info-container {
|
margin: 0em auto;
|
||||||
font-size: .6em;
|
align-content: start;
|
||||||
width: fit-content;
|
background-color: #F1F1F2;
|
||||||
display: inline-block;
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -10,8 +10,8 @@
|
|||||||
{{ if not .Conf.DisableSwitchTemplateInFrontend }}
|
{{ if not .Conf.DisableSwitchTemplateInFrontend }}
|
||||||
<script>
|
<script>
|
||||||
function showSwitchTemplate(list, currentBackendTheme) {
|
function showSwitchTemplate(list, currentBackendTheme) {
|
||||||
// console.log(list, currentBackendTheme);
|
console.log(list, currentBackendTheme);
|
||||||
// console.log("currentBackendTheme:",currentBackendTheme);
|
console.log("currentBackendTheme:",currentBackendTheme);
|
||||||
}
|
}
|
||||||
showSwitchTemplate({{ .Themes }}, {{ .Conf.Site.Theme }})
|
showSwitchTemplate({{ .Themes }}, {{ .Conf.Site.Theme }})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
+11
-17
@@ -1,31 +1,25 @@
|
|||||||
{{define "theme-default/header"}}
|
{{define "theme-default/header"}}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{.Conf.Language}}">
|
<html lang="{{.Conf.Language}}">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<meta content="telephone=no" name="format-detection">
|
<meta content="telephone=no" name="format-detection">
|
||||||
<title>{{.Title}}</title>
|
<title>{{.Title}}</title>
|
||||||
<link rel="shortcut icon" type="image/png" href="/static/logo.svg" />
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.css">
|
||||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/semantic.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/assets/font-logos.css">
|
||||||
<link rel="stylesheet" href="https://unpkg.com/font-logos@0.17.0/assets/font-logos.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.min.css">
|
||||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/font/bootstrap-icons.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/lipis/[email protected]/css/flag-icons.min.css">
|
||||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/css/flag-icons.min.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/semantic-ui-alerts.min.css">
|
<link rel="stylesheet" type="text/css" href="/static/semantic-ui-alerts.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/static/theme-default/css/main.css?v20240616">
|
<link rel="stylesheet" type="text/css" href="/static/theme-default/css/main.css?v20240226">
|
||||||
<link rel="stylesheet" type="text/css" href="/static/darkmode.css?v20240813">
|
<link rel="shortcut icon" type="image/png" href="/static/logo.svg" />
|
||||||
<script src="https://unpkg.com/[email protected]/dist/jquery.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
|
||||||
<script src="https://unpkg.com/[email protected].0/dist/semantic.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/[email protected].1/dist/semantic.min.js"></script>
|
||||||
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
|
|
||||||
<script src="https://unpkg.com/[email protected]/dist/echarts.min.js"></script>
|
|
||||||
<script src="/static/semantic-ui-alerts.min.js"></script>
|
<script src="/static/semantic-ui-alerts.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
|
||||||
<script src="/static/theme-default/js/mixin.js?v20240302"></script>
|
<script src="/static/theme-default/js/mixin.js?v20240302"></script>
|
||||||
<script>
|
|
||||||
document.documentElement.setAttribute('nz-theme', window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{{end}}
|
{{end}}
|
||||||
+515
-615
File diff suppressed because it is too large
Load Diff
-3
@@ -27,9 +27,6 @@
|
|||||||
<i :class="item.icon + ' icon'"></i>@#item.name#@
|
<i :class="item.icon + ' icon'"></i>@#item.name#@
|
||||||
<i class="check icon" v-if="preferredTemplate === item.key"></i>
|
<i class="check icon" v-if="preferredTemplate === item.key"></i>
|
||||||
</a>
|
</a>
|
||||||
<a v-if="defaultTemplate === 'custom'" @click="toggleTemplate('custom')" class="item">
|
|
||||||
<i class="expand icon"></i>Custom
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
+22
-15
@@ -18,7 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui container">
|
<div class="ui container">
|
||||||
<div ref="chartDom" style="border-radius: 28px; margin-top: 15px;height: 520px;overflow: hidden"></div>
|
<div ref="chartDom" style="border-radius: 28px; margin-top: 15px;height: 520px;max-width: 1400px;overflow: hidden"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -28,6 +28,9 @@
|
|||||||
const monitorInfo = JSON.parse('{{.MonitorInfos}}');
|
const monitorInfo = JSON.parse('{{.MonitorInfos}}');
|
||||||
const initData = JSON.parse('{{.Servers}}').servers;
|
const initData = JSON.parse('{{.Servers}}').servers;
|
||||||
let MaxTCPPingValue = {{.Conf.MaxTCPPingValue}};
|
let MaxTCPPingValue = {{.Conf.MaxTCPPingValue}};
|
||||||
|
if (MaxTCPPingValue == null) {
|
||||||
|
MaxTCPPingValue = 1000;
|
||||||
|
}
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
delimiters: ['@#', '#@'],
|
delimiters: ['@#', '#@'],
|
||||||
@@ -183,6 +186,15 @@
|
|||||||
let tSeries = [];
|
let tSeries = [];
|
||||||
let tLegendData = [];
|
let tLegendData = [];
|
||||||
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
|
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
|
||||||
|
let maxPing = 0;
|
||||||
|
for (let i = 0; i < monitorInfo.result.length; i++) {
|
||||||
|
for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
|
||||||
|
avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
|
||||||
|
if ( avgDelay < MaxTCPPingValue && avgDelay > maxPing) {
|
||||||
|
maxPing = avgDelay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for (let i = 0; i < monitorInfo.result.length; i++) {
|
for (let i = 0; i < monitorInfo.result.length; i++) {
|
||||||
var lcolor = lcolors[i % lcolors.length];
|
var lcolor = lcolors[i % lcolors.length];
|
||||||
var rgbaColorMarker = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.5)';
|
var rgbaColorMarker = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.5)';
|
||||||
@@ -197,15 +209,7 @@
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
loss += 1;
|
loss += 1;
|
||||||
datal.push({
|
datal.push([monitorInfo.result[i].created_at[j], maxPing]);
|
||||||
xAxis: monitorInfo.result[i].created_at[j],
|
|
||||||
label: { show: false },
|
|
||||||
emphasis: { disabled: true },
|
|
||||||
lineStyle: {
|
|
||||||
type: "solid",
|
|
||||||
color: rgbaColorBar
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
|
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
|
||||||
@@ -220,11 +224,6 @@
|
|||||||
smooth: true,
|
smooth: true,
|
||||||
symbol: 'none',
|
symbol: 'none',
|
||||||
data: data,
|
data: data,
|
||||||
markLine: {
|
|
||||||
symbol: "none",
|
|
||||||
symbolSize :0,
|
|
||||||
data: datal
|
|
||||||
},
|
|
||||||
markPoint: {
|
markPoint: {
|
||||||
data: [
|
data: [
|
||||||
{ type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } },
|
{ type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } },
|
||||||
@@ -232,6 +231,14 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
tSeries.push({
|
||||||
|
name: legendName,
|
||||||
|
type: 'bar',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'none',
|
||||||
|
data: datal,
|
||||||
|
itemStyle: { color: rgbaColorBar }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.option.title.text = monitorInfo.result[0].server_name;
|
this.option.title.text = monitorInfo.result[0].server_name;
|
||||||
this.option.series = tSeries;
|
this.option.series = tSeries;
|
||||||
|
|||||||
+1
-1
@@ -221,7 +221,7 @@
|
|||||||
var disk = this.formatByteSize(server.State.DiskUsed) + '/' + this.formatByteSize(server.Host.DiskTotal);
|
var disk = this.formatByteSize(server.State.DiskUsed) + '/' + this.formatByteSize(server.Host.DiskTotal);
|
||||||
var upTime = this.secondToDate(server.State.Uptime);
|
var upTime = this.secondToDate(server.State.Uptime);
|
||||||
var tooltip =
|
var tooltip =
|
||||||
`{content: 'System: ${server.Host.Platform}-${server.Host.PlatformVersion}[${server.Host.Arch}]<br>CPU: ${server.Host.CPU}<br>GPU: ${server.Host.GPU}<br>Disk: ${disk}<br>Online: ${upTime}<br>Version: ${server.Host.Version}'}`;
|
`{content: 'System: ${server.Host.Platform}-${server.Host.PlatformVersion}[${server.Host.Arch}]<br>CPU: ${server.Host.CPU}<br>Disk: ${disk}<br>Online: ${upTime}<br>Version: ${server.Host.Version}'}`;
|
||||||
return tooltip
|
return tooltip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-14
@@ -55,6 +55,9 @@
|
|||||||
const monitorInfo = JSON.parse('{{.MonitorInfos}}');
|
const monitorInfo = JSON.parse('{{.MonitorInfos}}');
|
||||||
const initData = JSON.parse('{{.Servers}}').servers;
|
const initData = JSON.parse('{{.Servers}}').servers;
|
||||||
let MaxTCPPingValue = {{.Conf.MaxTCPPingValue}};
|
let MaxTCPPingValue = {{.Conf.MaxTCPPingValue}};
|
||||||
|
if (MaxTCPPingValue == null) {
|
||||||
|
MaxTCPPingValue = 1000;
|
||||||
|
}
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
delimiters: ['@#', '#@'],
|
delimiters: ['@#', '#@'],
|
||||||
@@ -206,6 +209,15 @@
|
|||||||
let tSeries = [];
|
let tSeries = [];
|
||||||
let tLegendData = [];
|
let tLegendData = [];
|
||||||
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
|
var lcolors = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'];
|
||||||
|
let maxPing = 0;
|
||||||
|
for (let i = 0; i < monitorInfo.result.length; i++) {
|
||||||
|
for (let j = 0; j < monitorInfo.result[i].created_at.length; j++) {
|
||||||
|
avgDelay = Math.round(monitorInfo.result[i].avg_delay[j]);
|
||||||
|
if ( avgDelay < MaxTCPPingValue && avgDelay > maxPing) {
|
||||||
|
maxPing = avgDelay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for (let i = 0; i < monitorInfo.result.length; i++) {
|
for (let i = 0; i < monitorInfo.result.length; i++) {
|
||||||
var lcolor = lcolors[i % lcolors.length];
|
var lcolor = lcolors[i % lcolors.length];
|
||||||
var rgbaColorMarker = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.5)';
|
var rgbaColorMarker = 'rgba(' + parseInt(lcolor.slice(1, 3), 16) + ',' + parseInt(lcolor.slice(3, 5), 16) + ',' + parseInt(lcolor.slice(5, 7), 16) + ',0.5)';
|
||||||
@@ -220,15 +232,7 @@
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
loss += 1;
|
loss += 1;
|
||||||
datal.push({
|
datal.push([monitorInfo.result[i].created_at[j], maxPing]);
|
||||||
xAxis: monitorInfo.result[i].created_at[j],
|
|
||||||
label: { show: false },
|
|
||||||
emphasis: { disabled: true },
|
|
||||||
lineStyle: {
|
|
||||||
type: "solid",
|
|
||||||
color: rgbaColorBar
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
|
lossRate = ((loss / monitorInfo.result[i].created_at.length) * 100).toFixed(1);
|
||||||
@@ -243,11 +247,6 @@
|
|||||||
smooth: true,
|
smooth: true,
|
||||||
symbol: 'none',
|
symbol: 'none',
|
||||||
data: data,
|
data: data,
|
||||||
markLine: {
|
|
||||||
symbol: "none",
|
|
||||||
symbolSize :0,
|
|
||||||
data: datal
|
|
||||||
},
|
|
||||||
markPoint: {
|
markPoint: {
|
||||||
data: [
|
data: [
|
||||||
{ type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } },
|
{ type: 'max', symbol: 'pin', name: 'Max', itemStyle: { color: rgbaColorMarker }, symbolSize: 30, label: { fontSize: 8 } },
|
||||||
@@ -255,6 +254,14 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
tSeries.push({
|
||||||
|
name: legendName,
|
||||||
|
type: 'bar',
|
||||||
|
smooth: true,
|
||||||
|
symbol: 'none',
|
||||||
|
data: datal,
|
||||||
|
itemStyle: { color: rgbaColorBar }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.option.title.text = monitorInfo.result[0].server_name;
|
this.option.title.text = monitorInfo.result[0].server_name;
|
||||||
this.option.series = tSeries;
|
this.option.series = tSeries;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{{define "theme-server-status/content-footer"}}
|
||||||
|
<footer class="container" style="padding-bottom: 2rem;">
|
||||||
|
<p style="text-align: center; font-size: 10px;">
|
||||||
|
{{ .Conf.Site.Brand }} | Theme ServerStatus | Powered by <a target="_blank" href="https://github.com/naiba/nezha">{{tr "NezhaMonitoring"}}</a> {{.Version}}
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
<aside class="toolbox">
|
||||||
|
<span class="toggleView">
|
||||||
|
<i v-if="showGroup" @click="toggleView" class="show-nogroup bi bi-justify"></i>
|
||||||
|
<i v-else @click="toggleView" class="show-group bi bi-view-stacked"></i>
|
||||||
|
</span>
|
||||||
|
<span class="setTheme">
|
||||||
|
<i v-if="theme === 'light'" @click="setTheme('dark', true)" class="setTheme-dark bi bi-moon-fill"></i>
|
||||||
|
<i v-else @click="setTheme('light', true)" class="setTheme-light bi bi-brightness-high-fill"></i>
|
||||||
|
</span>
|
||||||
|
<span v-if="showGoTop" class="showGoTop">
|
||||||
|
<i @click="goTop" class="goTop bi bi-arrow-up"></i>
|
||||||
|
</span>
|
||||||
|
</aside>
|
||||||
|
{{end}}
|
||||||
+3
-9
@@ -1,6 +1,6 @@
|
|||||||
{{define "theme-server-status/menu"}}
|
{{define "theme-server-status/content-nav"}}
|
||||||
<header role="navigation" class="navbar navbar-inverse navbar-fixed-top">
|
<header role="navigation" class="navbar navbar-inverse navbar-fixed-top" style="z-index:99999999;">
|
||||||
<div class="container-fluid">
|
<div class="container">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
<button data-target=".navbar-collapse" data-toggle="collapse" class="navbar-toggle" type="button">
|
<button data-target=".navbar-collapse" data-toggle="collapse" class="navbar-toggle" type="button">
|
||||||
<span class="sr-only">Toggle navigation</span>
|
<span class="sr-only">Toggle navigation</span>
|
||||||
@@ -39,11 +39,6 @@
|
|||||||
<i class="check icon" v-if="preferredTemplate === item.key"></i>
|
<i class="check icon" v-if="preferredTemplate === item.key"></i>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="defaultTemplate === 'custom'">
|
|
||||||
<a @click="toggleTemplate('custom')" class="item">
|
|
||||||
<i class="expand icon" style="font-size:1em"></i>Custom
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
@@ -64,6 +59,5 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div class="nezha">
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
@@ -1,38 +1,4 @@
|
|||||||
{{define "theme-server-status/footer"}}
|
{{define "theme-server-status/footer"}}
|
||||||
</div>
|
|
||||||
<footer class="container-fluid">
|
|
||||||
<p>{{ .Conf.Site.Brand }} | Theme ServerStatus | Powered by <a target="_blank" href="https://github.com/naiba/nezha">{{tr "NezhaMonitoring"}}</a> {{.Version}}</p>
|
|
||||||
</footer>
|
|
||||||
<aside class="toolbox">
|
|
||||||
<template v-if="showTools">
|
|
||||||
<span v-if="page=='index' && countryMapChartData.length!=0" class="showMapChart">
|
|
||||||
<i @click="showMapChart" data-toggle="modal" data-target="#mapChartBox" class="bi bi-geo-alt"></i>
|
|
||||||
</span>
|
|
||||||
<span class="toggleView">
|
|
||||||
<i v-if="showGroup" @click="toggleShowGroup" class="show-nogroup bi bi-justify"></i>
|
|
||||||
<i v-else @click="toggleShowGroup" class="show-group bi bi-view-stacked"></i>
|
|
||||||
</span>
|
|
||||||
<span class="toggleSemiTransparent" @click="toggleSemiTransparent">
|
|
||||||
<i class="bi" :class="semiTransparent ? 'bi-droplet' : 'bi-droplet-half'"></i>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<span v-if="!showTools">
|
|
||||||
<i @click="toggleShowTools" class="bi bi-three-dots"></i>
|
|
||||||
</span>
|
|
||||||
<span class="setTheme">
|
|
||||||
<i v-if="theme === 'light'" @click="setTheme('dark')" class="setTheme-dark bi bi-moon-fill"></i>
|
|
||||||
<i v-else @click="setTheme('light')" class="setTheme-light bi bi-brightness-high-fill"></i>
|
|
||||||
</span>
|
|
||||||
<span v-if="showGoTop" class="showGoTop">
|
|
||||||
<i @click="goTop" class="goTop bi bi-arrow-up"></i>
|
|
||||||
</span>
|
|
||||||
</aside>
|
|
||||||
<template v-if="semiTransparent">
|
|
||||||
<link rel="stylesheet" href="/static/theme-server-status/css/light.plus.css?v20240807">
|
|
||||||
<link rel="stylesheet" href="/static/theme-server-status/css/dark.plus.css?v20240807">
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
{{if ts .CustomCode}}{{.CustomCode|safe}}{{end}}
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
{{end}}
|
{{end}}
|
||||||
+23
-22
@@ -6,28 +6,29 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="/static/theme-server-status/css/bootstrap-theme.min.css">
|
||||||
|
<link rel="stylesheet" href="/static/theme-server-status/css/main.css?v20240225">
|
||||||
|
<link rel="stylesheet" href="/static/theme-server-status/css/dark.css">
|
||||||
|
<link rel="stylesheet" href="/static/theme-server-status/css/light.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/assets/font-logos.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/lipis/[email protected]/css/flag-icons.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/semantic.min.css">
|
||||||
<link rel="shortcut icon" type="image/png" href="/static/logo.svg" />
|
<link rel="shortcut icon" type="image/png" href="/static/logo.svg" />
|
||||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css">
|
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/font/bootstrap-icons.min.css">
|
<!--[if lt IE 9]>
|
||||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/assets/font-logos.css">
|
<script src="/static/theme-server-status/js/html5shiv.js"></script>
|
||||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/css/flag-icons.min.css">
|
<script src="/static/theme-server-status/js/respond.min.js"></script>
|
||||||
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/semantic.min.css">
|
<![endif]-->
|
||||||
<script src="https://unpkg.com/[email protected]/dist/jquery.min.js"></script>
|
{{if ts .CustomCode}}
|
||||||
<script src="https://unpkg.com/[email protected]/dist/js/bootstrap.min.js"></script>
|
{{.CustomCode|safe}}
|
||||||
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
|
{{end}}
|
||||||
<script src="https://unpkg.com/[email protected]/dist/echarts.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
|
||||||
<link rel="stylesheet" href="/static/theme-server-status/css/main.css?v202408011">
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
|
||||||
<link rel="stylesheet" href="/static/theme-server-status/css/dark.css?v202408011">
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
|
||||||
<link rel="stylesheet" href="/static/theme-server-status/css/light.css?v20240811">
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/echarts.min.js"></script>
|
||||||
<script src="/static/theme-server-status/js/mixin.js?v20240811"></script>
|
<script src="/static/theme-server-status/js/mixin.js?v20240302"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
{{end}}
|
||||||
{{end}}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user