16 Commits

20 changed files with 241 additions and 450 deletions

3
.gitignore vendored
View File

@@ -16,8 +16,9 @@ manifest/output/
temp/ temp/
temp.yaml temp.yaml
bin bin
**/config/config.yaml
v1.0.0/ v1.0.0/
config/local.yaml config/local.yaml
main.exe~ main.exe~
download/ download/
version.txt
internal/packed/build_pack_data.go

View File

@@ -1,11 +1 @@
package v1 package v1
import "github.com/gogf/gf/v2/frame/g"
type UpdateReq struct {
g.Meta `path:"/system/update" tags:"system" method:"get" sm:"更新服务端"`
Url string `json:"url" dc:"更新地址"`
Version string `json:"version" dc:"当前版本"`
}
type UpdateRes struct {
}

View File

@@ -1,50 +1,42 @@
package main package main
import (
"image"
"os"
"github.com/icza/icox" // 替换为icox库
"github.com/nfnt/resize"
)
func main() { func main() {
// 1. 读取PNG文件 //// 1. 读取PNG文件
inputPath := "manifest/images/logo.png" // 输入PNG路径 //inputPath := "manifest/images/logo.png" // 输入PNG路径
outputPath := "manifest/images/favicon.ico" // 输出ICO路径 //outputPath := "manifest/images/favicon.ico" // 输出ICO路径
//
pngFile, err := os.Open(inputPath) //pngFile, err := os.Open(inputPath)
if err != nil { //if err != nil {
panic("无法打开PNG文件: " + err.Error()) // panic("无法打开PNG文件: " + err.Error())
} //}
defer pngFile.Close() //defer pngFile.Close()
//
// 2. 解码PNG为image.Image对象 //// 2. 解码PNG为image.Image对象
img, _, err := image.Decode(pngFile) //img, _, err := image.Decode(pngFile)
if err != nil { //if err != nil {
panic("PNG解码失败: " + err.Error()) // panic("PNG解码失败: " + err.Error())
} //}
//
// 3. 定义ICO需要包含的尺寸常见尺寸 //// 3. 定义ICO需要包含的尺寸常见尺寸
sizes := []uint{16, 32, 64, 128} // 可根据需求添加更多尺寸 //sizes := []uint{16, 32, 64, 128} // 可根据需求添加更多尺寸
var icoImages []image.Image //var icoImages []image.Image
//
// 4. 缩放图像到每个目标尺寸并收集 //// 4. 缩放图像到每个目标尺寸并收集
for _, size := range sizes { //for _, size := range sizes {
// 使用Lanczos3算法缩放高质量 // // 使用Lanczos3算法缩放高质量
resized := resize.Resize(size, size, img, resize.Lanczos3) // resized := resize.Resize(size, size, img, resize.Lanczos3)
icoImages = append(icoImages, resized) // icoImages = append(icoImages, resized)
} //}
//
// 5. 编码为ICO并写入文件关键修改使用icox.Encode //// 5. 编码为ICO并写入文件关键修改使用icox.Encode
icoFile, err := os.Create(outputPath) //icoFile, err := os.Create(outputPath)
if err != nil { //if err != nil {
panic("无法创建ICO文件: " + err.Error()) // panic("无法创建ICO文件: " + err.Error())
} //}
defer icoFile.Close() //defer icoFile.Close()
//
// icox.Encode直接支持多尺寸切片[]image.Image //// icox.Encode直接支持多尺寸切片[]image.Image
if err := icox.Encode(icoFile, icoImages); err != nil { //if err := icox.Encode(icoFile, icoImages); err != nil {
panic("ICO编码失败: " + err.Error()) // panic("ICO编码失败: " + err.Error())
} //}
} }

18
go.mod
View File

@@ -1,19 +1,19 @@
module github.com/ayflying/p2p module github.com/ayflying/p2p
go 1.24.0 go 1.24.8
toolchain go1.24.9
require ( require (
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 github.com/ayflying/update-github-release v0.0.4
github.com/dop251/goja v0.0.0-20250630131328-58d95d85e994 github.com/dop251/goja v0.0.0-20250630131328-58d95d85e994
github.com/getlantern/systray v1.2.2 github.com/getlantern/systray v1.2.2
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.3 github.com/gogf/gf/v2 v2.9.4
github.com/gogf/gf/v2 v2.9.3
github.com/google/uuid v1.6.0
github.com/gorilla/websocket v1.5.3 github.com/gorilla/websocket v1.5.3
github.com/libp2p/go-libp2p v0.43.0 github.com/libp2p/go-libp2p v0.43.0
github.com/libp2p/go-libp2p-kad-dht v0.35.1 github.com/libp2p/go-libp2p-kad-dht v0.35.1
github.com/minio/minio-go/v7 v7.0.95
github.com/multiformats/go-multiaddr v0.16.1 github.com/multiformats/go-multiaddr v0.16.1
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
) )
require ( require (
@@ -24,7 +24,6 @@ require (
github.com/clbanning/mxj/v2 v2.7.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dlclark/regexp2 v1.11.4 // indirect github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emirpasic/gods v1.18.1 // indirect github.com/emirpasic/gods v1.18.1 // indirect
@@ -47,6 +46,7 @@ require (
github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-json v0.10.5 // indirect
github.com/google/gopacket v1.1.19 // indirect github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect github.com/google/pprof v0.0.0-20230405160723-4a4c7d95572b // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grokify/html-strip-tags-go v0.1.0 // indirect github.com/grokify/html-strip-tags-go v0.1.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/huin/goupnp v1.3.0 // indirect github.com/huin/goupnp v1.3.0 // indirect
@@ -81,7 +81,6 @@ require (
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/crc64nvme v1.0.2 // indirect github.com/minio/crc64nvme v1.0.2 // indirect
github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.95 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect
@@ -97,7 +96,7 @@ require (
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
github.com/olekukonko/errors v1.1.0 // indirect github.com/olekukonko/errors v1.1.0 // indirect
github.com/olekukonko/ll v0.1.1 // indirect github.com/olekukonko/ll v0.1.1 // indirect
github.com/olekukonko/tablewriter v1.0.9 // indirect github.com/olekukonko/tablewriter v1.1.0 // indirect
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/philhofer/fwd v1.2.0 // indirect github.com/philhofer/fwd v1.2.0 // indirect
@@ -128,7 +127,6 @@ require (
github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.54.0 // indirect github.com/quic-go/quic-go v0.54.0 // indirect
github.com/quic-go/webtransport-go v0.9.0 // indirect github.com/quic-go/webtransport-go v0.9.0 // indirect
github.com/redis/go-redis/v9 v9.12.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/rs/xid v1.6.0 // indirect github.com/rs/xid v1.6.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect

24
go.sum
View File

@@ -10,21 +10,17 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGy
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9 h1:1ltqoej5GtaWF8jaiA49HwsZD459jqm9YFz9ZtMFpQA=
github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/ayflying/update-github-release v0.0.4 h1:iJ09jieBFW/t96N3NqcFA6tS7hxKx4fnETp5VC7jSbo=
github.com/ayflying/update-github-release v0.0.4/go.mod h1:9ctXuagiEKABWLaS4ocRCUcnN77jdYm7zir7NQ+rIeM=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -42,8 +38,6 @@ github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo= github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dop251/goja v0.0.0-20250630131328-58d95d85e994 h1:aQYWswi+hRL2zJqGacdCZx32XjKYV8ApXFGntw79XAM= github.com/dop251/goja v0.0.0-20250630131328-58d95d85e994 h1:aQYWswi+hRL2zJqGacdCZx32XjKYV8ApXFGntw79XAM=
@@ -98,10 +92,8 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.3 h1:VTbeHq8XpBCWFIwBGmuBl+jP8AepULnpgNz8GPBKBRQ= github.com/gogf/gf/v2 v2.9.4 h1:6vleEWypot9WBPncP2GjbpgAUeG6Mzb1YESb9nPMkjY=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.9.3/go.mod h1:gcidgAYn4IWbx08QUThg7jw6bz3KklXI9/5zg8jnVHY= github.com/gogf/gf/v2 v2.9.4/go.mod h1:Ukl+5HUH9S7puBmNLR4L1zUqeRwi0nrW4OigOknEztU=
github.com/gogf/gf/v2 v2.9.3 h1:qjN4s55FfUzxZ1AE8vUHNDX3V0eIOUGXhF2DjRTVZQ4=
github.com/gogf/gf/v2 v2.9.3/go.mod h1:w6rcfD13SmO7FKI80k9LSLiSMGqpMYp50Nfkrrc2sEE=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
@@ -273,16 +265,14 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc=
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0=
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
github.com/olekukonko/ll v0.1.1 h1:9Dfeed5/Mgaxb9lHRAftLK9pVfYETvHn+If6lywVhJc= github.com/olekukonko/ll v0.1.1 h1:9Dfeed5/Mgaxb9lHRAftLK9pVfYETvHn+If6lywVhJc=
github.com/olekukonko/ll v0.1.1/go.mod h1:2dJo+hYZcJMLMbKwHEWvxCUbAOLc/CXWS9noET22Mdo= github.com/olekukonko/ll v0.1.1/go.mod h1:2dJo+hYZcJMLMbKwHEWvxCUbAOLc/CXWS9noET22Mdo=
github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8= github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY=
github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo= github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
@@ -355,8 +345,6 @@ github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQB
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY= github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
github.com/quic-go/webtransport-go v0.9.0 h1:jgys+7/wm6JarGDrW+lD/r9BGqBAmqY/ssklE09bA70= github.com/quic-go/webtransport-go v0.9.0 h1:jgys+7/wm6JarGDrW+lD/r9BGqBAmqY/ssklE09bA70=
github.com/quic-go/webtransport-go v0.9.0/go.mod h1:4FUYIiUc75XSsF6HShcLeXXYZJ9AGwo/xh3L8M/P1ao= github.com/quic-go/webtransport-go v0.9.0/go.mod h1:4FUYIiUc75XSsF6HShcLeXXYZJ9AGwo/xh3L8M/P1ao=
github.com/redis/go-redis/v9 v9.12.1 h1:k5iquqv27aBtnTm2tIkROUDp8JBXhXZIVu1InSgvovg=
github.com/redis/go-redis/v9 v9.12.1/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=

39
internal/boot/boot.go Normal file
View File

@@ -0,0 +1,39 @@
package boot
import (
"context"
updateGithub "github.com/ayflying/update-github-release"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcron"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gfile"
)
func Boot() {
getDev, _ := g.Cfg().GetWithEnv(gctx.New(), "dev")
if !getDev.Bool() {
var update = updateGithub.New("https://api.github.com/repos/ayflying/p2p/releases/latest")
gfile.PutContents("version.txt", "v0.0.9")
// 每天0点检查更新
gcron.Add(gctx.New(), "0 0 0 * * *", func(ctx context.Context) {
err := update.CheckUpdate(true)
if err != nil {
g.Log().Errorf(ctx, "检查更新失败:%v", err)
}
})
go func() {
//在协程中检查更新,预防主程序阻塞
err := update.CheckUpdate(true)
if err != nil {
g.Log().Errorf(gctx.New(), "检查更新失败:%v", err)
}
}()
} else {
g.Log().Debugf(gctx.New(), "开发模式,不检查更新")
}
}

View File

@@ -5,9 +5,9 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/ayflying/p2p/internal/boot"
"github.com/ayflying/p2p/internal/consts" "github.com/ayflying/p2p/internal/consts"
"github.com/ayflying/p2p/internal/controller/p2p" "github.com/ayflying/p2p/internal/controller/p2p"
"github.com/ayflying/p2p/internal/controller/system"
"github.com/ayflying/p2p/internal/service" "github.com/ayflying/p2p/internal/service"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/net/ghttp"
@@ -18,7 +18,7 @@ import (
) )
func init() { func init() {
err := Main.AddCommand(&Main, &Debug, &Update) err := Main.AddCommand(&Main, &Debug)
if err != nil { if err != nil {
g.Log().Error(gctx.GetInitCtx(), err) g.Log().Error(gctx.GetInitCtx(), err)
return return
@@ -32,6 +32,10 @@ var (
Brief: "start http server", Brief: "start http server",
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
g.Log().Debug(ctx, "开始执行main") g.Log().Debug(ctx, "开始执行main")
// 初始化服务器
boot.Boot()
Version, err := g.Cfg("hack").Get(ctx, "gfcli.build.version") Version, err := g.Cfg("hack").Get(ctx, "gfcli.build.version")
g.Log().Debugf(ctx, "当前启动的版本为:%v", Version) g.Log().Debugf(ctx, "当前启动的版本为:%v", Version)
@@ -69,7 +73,6 @@ var (
group.Middleware(ghttp.MiddlewareHandlerResponse) group.Middleware(ghttp.MiddlewareHandlerResponse)
group.Bind( group.Bind(
p2p.NewV1(), p2p.NewV1(),
system.NewV1(),
) )
}) })

View File

@@ -1,109 +0,0 @@
package cmd
import (
"bytes"
"context"
"fmt"
"path"
"runtime"
systemV1 "github.com/ayflying/p2p/api/system/v1"
"github.com/ayflying/p2p/internal/service"
"github.com/gogf/gf/v2/crypto/gsha1"
"github.com/gogf/gf/v2/encoding/gcompress"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
)
var (
Update = gcmd.Command{
Name: "update",
Usage: "update",
Brief: "更新版本",
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
g.Log().Info(ctx, "准备上传更新文件")
//加载编辑配置文件
g.Cfg("hack").GetAdapter().(*gcfg.AdapterFile).SetFileName("hack/config.yaml")
//获取文件名
getName, err := g.Cfg("hack").Get(ctx, "gfcli.build.name")
name := getName.String()
getPath, err := g.Cfg("hack").Get(ctx, "gfcli.build.path")
pathMain := getPath.String()
//获取版本号
getVersion, err := g.Cfg("hack").Get(ctx, "gfcli.build.version")
version := getVersion.String()
// 拼接操作系统和架构格式OS_ARCH
platform := fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)
rootDir := "server_update"
var versionFile = make(map[string]string)
var filePath = path.Join(pathMain, version, platform, name)
dirList, _ := gfile.ScanDir(path.Join(pathMain, version), "*", false)
for _, v := range dirList {
updatePlatform := gfile.Name(v)
updateFilePath := path.Join(rootDir, name, version, updatePlatform)
var obj bytes.Buffer
g.Log().Debugf(ctx, "读取目录成功:%v", v)
fileMian := path.Join(v, name)
g.Log().Debugf(ctx, "判断当前文件是否存在:%v", fileMian)
if gfile.IsFile(fileMian) {
// 写入文件哈希
versionFile[updatePlatform] = gsha1.MustEncryptFile(fileMian)
err = gcompress.GzipPathWriter(fileMian, &obj)
service.S3().PutObject(ctx, &obj, updateFilePath+".gz")
g.Log().Debugf(ctx, "成功上传文件到:%v", updateFilePath+".gz")
}
if gfile.IsFile(fileMian + ".exe") {
// 写入文件哈希
versionFile[updatePlatform] = gsha1.MustEncryptFile(fileMian + ".exe")
err = gcompress.GzipPathWriter(fileMian+".exe", &obj)
service.S3().PutObject(ctx, &obj, updateFilePath+".gz")
g.Log().Debugf(ctx, "成功上传文件到:%v", updateFilePath+".gz")
}
// 写入文件版本文件
fileByte := gjson.MustEncode(versionFile)
service.S3().PutObject(ctx, bytes.NewReader(fileByte), path.Join(rootDir, name, "version.json"))
if err != nil {
g.Log().Error(ctx, err)
}
}
g.Log().Debugf(ctx, "当前获取到的地址为:%v", filePath)
versionUrl := service.S3().GetCdnUrl(path.Join(rootDir, name))
listVar := g.Cfg().MustGet(ctx, "message.list")
var p2pItem []struct {
Host string `json:"host"`
Port int `json:"port"`
SSL bool `json:"ssl"`
Ws string `json:"ws"`
}
listVar.Scan(&p2pItem)
for _, v := range p2pItem {
url := "http"
if v.SSL == true {
url = "https"
}
url = fmt.Sprintf("%s://%s:%d/system/update", url, v.Host, v.Port)
g.Log().Debugf(ctx, "开始上传到服务器:%v,file=%v", url, versionUrl)
_, err := g.Client().Get(ctx, url, systemV1.UpdateReq{
Url: versionUrl,
Version: version,
})
if err != nil {
g.Log().Error(ctx, err)
}
}
return
}}
)

View File

@@ -4,12 +4,4 @@
package system package system
import (
"github.com/ayflying/p2p/api/system"
)
type ControllerV1 struct{} type ControllerV1 struct{}
func NewV1() system.ISystemV1 {
return &ControllerV1{}
}

View File

@@ -1,70 +0,0 @@
package system
import (
"context"
"net/url"
"path"
"github.com/ayflying/p2p/api/system/v1"
"github.com/ayflying/p2p/internal/service"
"github.com/gogf/gf/v2/crypto/gsha1"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
)
func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) {
getRunFile := gcmd.GetArg(0).String()
fileSha, err := gsha1.EncryptFile(getRunFile)
g.Log().Debugf(ctx, "当前文件哈希值:%v", fileSha)
versionUrl, _ := url.JoinPath(req.Url, "version.json")
resp, err := g.Client().Get(ctx, versionUrl)
var version map[string]string
gjson.DecodeTo(resp.ReadAll(), &version)
for k, _ := range version {
//downloadUrl, _ := url.QueryUnescape(v)
downloadUrl, _ := url.JoinPath(req.Url, req.Version, k+".gz")
fileByte, err2 := g.Client().Get(ctx, downloadUrl)
if err2 != nil {
g.Log().Error(ctx, err2)
continue
}
putFile := path.Join("download", gfile.Basename(downloadUrl))
err2 = gfile.PutBytes(putFile, fileByte.ReadAll())
if err2 != nil {
g.Log().Error(ctx, err2)
continue
}
}
type DataType struct {
File []byte `json:"file"`
Name string `json:"name"`
}
//var GatewayMessage *message.GatewayMessage
var msgData = struct {
Files []*DataType `json:"files"`
}{}
msgData.Files = []*DataType{}
files, _ := gfile.ScanDir("download", "*.gz")
for _, v := range files {
msgData.Files = append(msgData.Files, &DataType{
File: gfile.GetBytes(v),
Name: gfile.Basename(v),
})
}
service.P2P().SendAll("update", msgData)
//更新自己的文件
//err = service.System().Update(ctx)
return
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gres"
) )
// 引入 Windows API 函数 // 引入 Windows API 函数
@@ -20,9 +21,20 @@ var (
kernel32 = syscall.NewLazyDLL("kernel32.dll") kernel32 = syscall.NewLazyDLL("kernel32.dll")
showWindow = user32.NewProc("ShowWindow") showWindow = user32.NewProc("ShowWindow")
getConsoleWnd = kernel32.NewProc("GetConsoleWindow") getConsoleWnd = kernel32.NewProc("GetConsoleWindow")
freeConsole = kernel32.NewProc("FreeConsole")
attachConsole = kernel32.NewProc("AttachConsole")
allocConsole = kernel32.NewProc("AllocConsole")
setConsoleCtrlHandler = kernel32.NewProc("SetConsoleCtrlHandler")
consoleCtrlHandler uintptr
)
const (
ctrlCloseEvent = 2
) )
func (s *sOS) start() { func (s *sOS) start() {
// 注册控制台关闭事件处理:点击叉叉仅隐藏控制台而不退出程序
s.setupConsoleCloseHandler()
// 系统托盘初始化(设置图标、右键菜单) // 系统托盘初始化(设置图标、右键菜单)
go systray.Run(s.onSystrayReady, s.onSystrayExit) go systray.Run(s.onSystrayReady, s.onSystrayExit)
@@ -30,9 +42,21 @@ func (s *sOS) start() {
// 系统托盘初始化(设置图标、右键菜单) // 系统托盘初始化(设置图标、右键菜单)
func (s *sOS) onSystrayReady() { func (s *sOS) onSystrayReady() {
//s.hideConsole() // s.hideConsole()
var iconByte []byte
if !gfile.Exists(s.systray.Icon) {
iconByte = gres.GetContent(s.systray.Icon)
gfile.PutBytes(s.systray.Icon, iconByte)
}
iconByte = gfile.GetBytes(s.systray.Icon)
//if gres.Contains(s.systray.Icon) {
// iconByte = gres.GetContent(s.systray.Icon)
// gfile.PutBytes(s.systray.Icon, iconByte)
//} else {
// iconByte = gfile.GetBytes(s.systray.Icon)
//}
iconByte := gfile.GetBytes(s.systray.Icon)
systray.SetIcon(iconByte) systray.SetIcon(iconByte)
systray.SetTitle(s.systray.Title) systray.SetTitle(s.systray.Title)
systray.SetTooltip(s.systray.Tooltip) systray.SetTooltip(s.systray.Tooltip)
@@ -46,6 +70,7 @@ func (s *sOS) onSystrayReady() {
select { select {
case <-mQuit.ClickedCh: case <-mQuit.ClickedCh:
systray.Quit() systray.Quit()
case <-mShow.ClickedCh: case <-mShow.ClickedCh:
// 显示窗口 // 显示窗口
s.showConsole() s.showConsole()
@@ -77,13 +102,12 @@ func (s *sOS) update(version, server string) {
// 隐藏控制台窗口 // 隐藏控制台窗口
func (s *sOS) hideConsole() { func (s *sOS) hideConsole() {
// 获取当前控制台窗口句柄 // 仅隐藏控制台窗口(保留现有缓冲区以便后续显示时保留历史日志)
hWnd, _, _ := getConsoleWnd.Call() hWnd, _, _ := getConsoleWnd.Call()
if hWnd == 0 { if hWnd != 0 {
return // 无控制台窗口如编译为GUI子系统时
}
// SW_HIDE = 0隐藏窗口 // SW_HIDE = 0隐藏窗口
showWindow.Call(hWnd, 0) showWindow.Call(hWnd, 0)
}
} }
// 显示控制台窗口 // 显示控制台窗口
@@ -91,8 +115,40 @@ func (s *sOS) showConsole() {
// 获取当前控制台窗口句柄 // 获取当前控制台窗口句柄
hWnd, _, _ := getConsoleWnd.Call() hWnd, _, _ := getConsoleWnd.Call()
if hWnd == 0 { if hWnd == 0 {
return // 如果当前进程没有控制台,尝试附加到父进程控制台
// ATTACH_PARENT_PROCESS = (DWORD)-1
ret, _, _ := attachConsole.Call(uintptr(^uint32(0)))
if ret == 0 {
// 附加失败则分配一个新的控制台窗口
allocConsole.Call()
} }
// 重新获取控制台窗口句柄
hWnd, _, _ = getConsoleWnd.Call()
}
if hWnd != 0 {
// SW_SHOW = 5显示窗口 // SW_SHOW = 5显示窗口
showWindow.Call(hWnd, 5) showWindow.Call(hWnd, 5)
}
}
// 注册控制台关闭事件处理器,将关闭事件转换为隐藏行为
func (s *sOS) setupConsoleCloseHandler() {
if consoleCtrlHandler != 0 {
return
}
consoleCtrlHandler = syscall.NewCallback(func(ctrlType uint32) uintptr {
if ctrlType == ctrlCloseEvent {
// 用户点击控制台窗口的关闭按钮(X):仅隐藏,不退出
hWnd, _, _ := getConsoleWnd.Call()
if hWnd != 0 {
// SW_HIDE = 0
showWindow.Call(hWnd, 0)
}
// 返回 TRUE 表示事件已处理,阻止默认终止行为
return 1
}
// 其他事件交由系统默认处理
return 0
})
setConsoleCtrlHandler.Call(consoleCtrlHandler, uintptr(1))
} }

View File

@@ -178,6 +178,7 @@ func (s *sP2P) register() error {
addrs[i] = addr.String() addrs[i] = addr.String()
} }
ports, _ := s.getLocalTCPPorts(s.client.host)
// 构建注册消息 // 构建注册消息
msg := GatewayMessage{ msg := GatewayMessage{
Type: MsgTypeRegister, Type: MsgTypeRegister,
@@ -185,6 +186,7 @@ func (s *sP2P) register() error {
Data: gjson.MustEncode(g.Map{ Data: gjson.MustEncode(g.Map{
"peer_id": s.client.host.ID().String(), "peer_id": s.client.host.ID().String(),
"addrs": addrs, "addrs": addrs,
"ports": ports,
}), }),
} }
@@ -456,7 +458,7 @@ func (s *sP2P) receiveGatewayMessages(ctx context.Context) {
g.Log().Info(ctx, "文件接收完成") g.Log().Info(ctx, "文件接收完成")
// 开始覆盖文件与重启 // 开始覆盖文件与重启
err = service.System().Update(ctx) err = service.System().Update(ctx, "")
//// 调用不同系统的更新服务 //// 调用不同系统的更新服务
//service.OS().Update(msgData.Version, msgData.Server) //service.OS().Update(msgData.Version, msgData.Server)

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net"
"strings" "strings"
"time" "time"
@@ -104,6 +105,7 @@ func (s *sP2P) handleRegister(ctx context.Context, conn *websocket.Conn, msg *Ga
var data struct { var data struct {
PeerID string `json:"peer_id"` PeerID string `json:"peer_id"`
Addrs []string `json:"addrs"` Addrs []string `json:"addrs"`
Ports []int `json:"ports"`
} }
if err := json.Unmarshal(msg.Data, &data); err != nil { if err := json.Unmarshal(msg.Data, &data); err != nil {
@@ -111,18 +113,20 @@ func (s *sP2P) handleRegister(ctx context.Context, conn *websocket.Conn, msg *Ga
return return
} }
//// 追加公网ip // 追加公网ip
//publicIp, _, _ := net.SplitHostPort(conn.RemoteAddr().String()) publicIp, _, _ := net.SplitHostPort(conn.RemoteAddr().String())
//ParseIP := net.ParseIP(publicIp) ParseIP := net.ParseIP(publicIp)
//var ipType string var ipType string
//if ParseIP.To4() != nil { if ParseIP.To4() != nil {
// ipType = "ip4" ipType = "ip4"
//} else { } else {
// ipType = "ip6" ipType = "ip6"
//} }
//port2 := 53533 //port2 := 53533
//data.Addrs = append(data.Addrs, fmt.Sprintf("/%s/%s/tcp/%d", ipType, publicIp, port2)) for _, port2 := range data.Ports {
//data.Addrs = append(data.Addrs, fmt.Sprintf("/%s/%s/udp/%d/quic-v1", ipType, publicIp, port2)) data.Addrs = append(data.Addrs, fmt.Sprintf("/%s/%s/tcp/%d", ipType, publicIp, port2))
data.Addrs = append(data.Addrs, fmt.Sprintf("/%s/%s/udp/%d/quic-v1", ipType, publicIp, port2))
}
// 过滤回环地址 // 过滤回环地址
data.Addrs = s.filterLoopbackAddrs(data.Addrs) data.Addrs = s.filterLoopbackAddrs(data.Addrs)

View File

@@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"math/rand" "math/rand"
"net" "net"
"net/http"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -80,46 +79,6 @@ func init() {
ip, _ = service.P2P().GetIPv4PublicIP() ip, _ = service.P2P().GetIPv4PublicIP()
} }
// 获取公网IP并判断类型ipv4/ipv6
func (s *sP2P) getPublicIPAndType() (ip string, ipType string, err error) {
// 公网IP查询接口多个备用
client := http.Client{Timeout: 5 * time.Second}
for _, api := range ipAPIs {
resp, err := client.Get(api)
if err != nil {
continue
}
defer resp.Body.Close()
// 读取响应纯IP字符串
buf := make([]byte, 128)
n, err := resp.Body.Read(buf)
if err != nil {
continue
}
ip = strings.TrimSpace(string(buf[:n]))
if ip == "" {
continue
}
// 判断IP类型
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
continue // 无效IP格式
}
if parsedIP.To4() != nil {
return ip, "ipv4", nil // IPv4
} else if parsedIP.To16() != nil {
return ip, "ipv6", nil // IPv6
}
}
return "", "", fmt.Errorf("所有公网IP查询接口均失败")
}
// 只获取IPv4公网IP过滤IPv6结果 // 只获取IPv4公网IP过滤IPv6结果
func (s *sP2P) GetIPv4PublicIP() (string, error) { func (s *sP2P) GetIPv4PublicIP() (string, error) {
ctx := gctx.New() ctx := gctx.New()
@@ -188,9 +147,10 @@ func (s *sP2P) removeDuplicates(strs []string) []string {
return result return result
} }
const privKeyPath = "runtime/p2p.key"
// 生成固定密钥(核心:通过固定种子生成相同密钥) // 生成固定密钥(核心:通过固定种子生成相同密钥)
func (s *sP2P) generateFixedKey() (crypto.PrivKey, error) { func (s *sP2P) generateFixedKey() (crypto.PrivKey, error) {
privKeyPath := "runtime/message.key"
if ok := gfile.Exists(privKeyPath); ok { if ok := gfile.Exists(privKeyPath); ok {
// 从文件读取密钥 // 从文件读取密钥
keyBytes := gfile.GetBytes(privKeyPath) keyBytes := gfile.GetBytes(privKeyPath)

View File

@@ -1,9 +1,5 @@
package system package system
import (
"github.com/ayflying/p2p/internal/service"
)
type sSystem struct{} type sSystem struct{}
func New() *sSystem { func New() *sSystem {
@@ -11,7 +7,7 @@ func New() *sSystem {
} }
func init() { func init() {
service.RegisterSystem(New())
} }
func (system *sSystem) Init() {} func (s *sSystem) Init() {}

View File

@@ -1,98 +0,0 @@
package system
import (
"context"
"fmt"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"time"
"github.com/ayflying/p2p/internal/service"
"github.com/gogf/gf/v2/encoding/gcompress"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
)
func (s *sSystem) Update(ctx context.Context) (err error) {
//拼接操作系统和架构格式OS_ARCH
platform := fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)
runFile := gcmd.GetArg(0).String()
oldFile, err := service.System().RenameRunningFile(runFile)
g.Log().Debugf(ctx, "执行文件改名为%v", oldFile)
gz := path.Join("download", platform+".gz")
err = gcompress.UnGzipFile(gz, runFile)
go func() {
log.Println("5秒后开始重启...")
time.Sleep(5 * time.Second)
if err = service.System().RestartSelf(); err != nil {
log.Fatalf("重启失败:%v", err)
}
}()
return
}
// RestartSelf 实现 Windows 平台下的程序自重启
func (s *sSystem) RestartSelf() error {
// 1. 获取当前程序的绝对路径
exePath, err := os.Executable()
if err != nil {
return err
}
// 处理路径中的符号链接(确保路径正确)
exePath, err = filepath.EvalSymlinks(exePath)
if err != nil {
return err
}
// 2. 获取命令行参数os.Args[0] 是程序名,实际参数从 os.Args[1:] 开始)
args := os.Args[1:]
// 3. 构建新进程命令(路径为当前程序,参数为原参数)
cmd := exec.Command(exePath, args...)
// 设置新进程的工作目录与当前进程一致
cmd.Dir, err = os.Getwd()
if err != nil {
return err
}
// 新进程的输出继承当前进程的标准输出(可选,根据需求调整)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
// 4. 启动新进程非阻塞Start() 后立即返回)
if err := cmd.Start(); err != nil {
return err
}
// 5. 新进程启动成功后,退出当前进程
os.Exit(0)
return nil // 理论上不会执行到这里
}
// RenameRunningFile 重命名正在运行的程序文件(如 message.exe → message.exe~
func (s *sSystem) RenameRunningFile(exePath string) (string, error) {
// 目标备份文件名message.exe → message.exe~
backupPath := exePath + "~"
// 先删除已存在的备份文件(若有)
if _, err := os.Stat(backupPath); err == nil {
if err := os.Remove(backupPath); err != nil {
return "", fmt.Errorf("删除旧备份文件失败: %v", err)
}
}
// 重命名正在运行的 exe 文件
// 关键Windows 允许对锁定的文件执行重命名操作
if err := os.Rename(exePath, backupPath); err != nil {
return "", fmt.Errorf("重命名运行中文件失败: %v", err)
}
return backupPath, nil
}

View File

@@ -1 +1,2 @@
package packed package packed

View File

@@ -12,11 +12,12 @@ import (
type ( type (
ISystem interface { ISystem interface {
Init() Init()
Update(ctx context.Context) (err error) Update(ctx context.Context, gzFile string) (err error)
// RestartSelf 实现 Windows 平台下的程序自重启 // RestartSelf 实现 Windows 平台下的程序自重启
RestartSelf() error RestartSelf() error
// RenameRunningFile 重命名正在运行的程序文件(如 message.exe → message.exe~ // RenameRunningFile 重命名正在运行的程序文件(如 message.exe → message.exe~
RenameRunningFile(exePath string) (string, error) RenameRunningFile(exePath string) (string, error)
CheckUpdate() (err error)
} }
) )

View File

@@ -10,9 +10,8 @@ import (
"github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
//步骤1加载驱动 //步骤1加载驱动
_ "github.com/gogf/gf/contrib/nosql/redis/v2" //_ "github.com/gogf/gf/contrib/nosql/redis/v2"
"github.com/ayflying/p2p/internal/cmd" "github.com/ayflying/p2p/internal/cmd"
"github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gctx"
@@ -24,7 +23,7 @@ var (
func main() { func main() {
g.Log().Infof(ctx, "启动文件最后修改时间:%v", gtime.New(gfile.MTime(gcmd.GetArg(0).String())).String()) g.Log().Infof(ctx, "启动文件最后修改时间:%v", gtime.New(gfile.MTime(gcmd.GetArg(0).String())).String())
g.Dump("v1.0.0.2") //g.Dump("v1.0.0.2")
if ok := gfile.Exists("runtime"); !ok { if ok := gfile.Exists("runtime"); !ok {
gfile.Mkdir("runtime") gfile.Mkdir("runtime")

View File

@@ -0,0 +1,46 @@
module:
server: true
client: true
# https://goframe.org/docs/web/server-config-file-template
server:
address: "51888"
# openapiPath: "/api.json"
# swaggerPath: "/swagger"
dumpRouterMap: false
graceful: true
# https://goframe.org/docs/core/glog-config
logger:
level : "all"
stdout: true
# https://goframe.org/docs/core/gdb-config-file
database:
default:
link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
redis:
default:
address: "ay.cname.com:6379"
db: 15
pass: "12345678"
cache:
address: "ay.cname.com:6379"
db: 15
pass: "12345678"
p2p:
list:
- host: "host.yunloli.cn"
port: 51888
ssl: false
ws: ws
- host: "ay.cname.com"
port: 51888
ssl: false
ws: ws