From 50f6bc808253239165043bc5e3e69b9f405f8a45 Mon Sep 17 00:00:00 2001 From: chenxv399 Date: Mon, 25 Nov 2024 14:03:39 +0800 Subject: [PATCH] First Commit --- .gitignore | 1 + .go-version | 1 + README.md | 0 go.mod | 30 ++++++ go.sum | 93 +++++++++++++++++++ main.go | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tasks.db | Bin 0 -> 12288 bytes 7 files changed, 386 insertions(+) create mode 100644 .gitignore create mode 100644 .go-version create mode 100644 README.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 tasks.db diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..adf57ff --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/flinkvertify \ No newline at end of file diff --git a/.go-version b/.go-version new file mode 100644 index 0000000..ac1df3f --- /dev/null +++ b/.go-version @@ -0,0 +1 @@ +1.23.3 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c6a7a21 --- /dev/null +++ b/go.mod @@ -0,0 +1,30 @@ +module flinkvertify + +go 1.23 + +require ( + github.com/gocolly/colly v1.2.0 + gorm.io/driver/sqlite v1.5.6 + gorm.io/gorm v1.25.12 +) + +require ( + github.com/PuerkitoBio/goquery v1.10.0 // indirect + github.com/andybalholm/cascadia v1.3.2 // indirect + github.com/antchfx/htmlquery v1.3.3 // indirect + github.com/antchfx/xmlquery v1.4.2 // indirect + github.com/antchfx/xpath v1.3.2 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/kennygrant/sanitize v1.2.4 // indirect + github.com/mattn/go-sqlite3 v1.14.24 // indirect + github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect + github.com/temoto/robotstxt v1.1.2 // indirect + golang.org/x/net v0.31.0 // indirect + golang.org/x/text v0.20.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.35.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2c239c0 --- /dev/null +++ b/go.sum @@ -0,0 +1,93 @@ +github.com/PuerkitoBio/goquery v1.10.0 h1:6fiXdLuUvYs2OJSvNRqlNPoBm6YABE226xrbavY5Wv4= +github.com/PuerkitoBio/goquery v1.10.0/go.mod h1:TjZZl68Q3eGHNBA8CWaxAN7rOU1EbDz3CWuolcO5Yu4= +github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= +github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/antchfx/htmlquery v1.3.3 h1:x6tVzrRhVNfECDaVxnZi1mEGrQg3mjE/rxbH2Pe6dNE= +github.com/antchfx/htmlquery v1.3.3/go.mod h1:WeU3N7/rL6mb6dCwtE30dURBnBieKDC/fR8t6X+cKjU= +github.com/antchfx/xmlquery v1.4.2 h1:MZKd9+wblwxfQ1zd1AdrTsqVaMjMCwow3IqkCSe00KA= +github.com/antchfx/xmlquery v1.4.2/go.mod h1:QXhvf5ldTuGqhd1SHNvvtlhhdQLks4dD0awIVhXIDTA= +github.com/antchfx/xpath v1.3.2 h1:LNjzlsSjinu3bQpw9hWMY9ocB80oLOWuQqFvO6xt51U= +github.com/antchfx/xpath v1.3.2/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gocolly/colly v1.2.0 h1:qRz9YAn8FIH0qzgNUw+HT9UN7wm1oF9OBAilwEWpyrI= +github.com/gocolly/colly v1.2.0/go.mod h1:Hof5T3ZswNVsOHYmba1u03W65HDWgpV5HifSuueE0EA= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o= +github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak= +github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= +github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA= +github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/temoto/robotstxt v1.1.2 h1:W2pOjSJ6SWvldyEuiFXNxz3xZ8aiWX5LbfDiOFd7Fxg= +github.com/temoto/robotstxt v1.1.2/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +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-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-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +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/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +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-20220520151302-bc2c85ada10a/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.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +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.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +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.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE= +gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= +gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= +gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= diff --git a/main.go b/main.go new file mode 100644 index 0000000..4d83384 --- /dev/null +++ b/main.go @@ -0,0 +1,261 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "log" + "math/rand" + "net/http" + "net/url" + "strings" + "sync" + "time" + + "github.com/gocolly/colly" + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +// Task 结构体 +type Task struct { + ID string `gorm:"primaryKey"` + URL string `json:"url"` + Status string `json:"status"` // processing, success, failure + Result bool `json:"result"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +// 全局变量 +var ( + db *gorm.DB + taskMu sync.Mutex // 保护任务状态更新的锁 + apiKey string // API密钥 + keyword1 string //关键词1 + keyword2 string //关键词2 +) + +// 初始化数据库 +func initDB() { + var err error + db, err = gorm.Open(sqlite.Open("tasks.db"), &gorm.Config{}) + if err != nil { + log.Fatalf("Failed to connect to database: %s", err) + } + if err = db.AutoMigrate(&Task{}); err != nil { + log.Fatalf("Failed to migrate database: %s", err) + } +} + +// 初始化随机API密钥 +func generateAPIKey() string { + key := make([]byte, 16) + rand.Seed(time.Now().UnixNano()) + for i := range key { + key[i] = byte(rand.Intn(26) + 65) // 随机生成A-Z的大写字母 + } + return string(key) +} + +// 随机UA池 +var userAgents = []string{ + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Mobile/15E148 Safari/604.1", + "Mozilla/5.0 (Linux; Android 10; SM-G973F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Mobile Safari/537.36", +} + +func getRandomUserAgent() string { + rand.Seed(time.Now().UnixNano()) + return userAgents[rand.Intn(len(userAgents))] +} + +// 伪装Cookies生成 +func generateFakeCookies(domain string) []*http.Cookie { + return []*http.Cookie{ + { + Name: "session_id", + Value: fmt.Sprintf("fake-session-%d", time.Now().UnixNano()), + Domain: domain, + Path: "/", + HttpOnly: true, + Secure: true, + }, + { + Name: "user_pref", + Value: "lang=zh-CN", + Domain: domain, + Path: "/", + HttpOnly: false, + }, + } +} + +// 抓取任务处理 +func processTask(task *Task) { + c := colly.NewCollector() + + // 随机UA和伪装Cookies + c.OnRequest(func(r *colly.Request) { + ua := getRandomUserAgent() + r.Headers.Set("User-Agent", ua) + + u, err := url.Parse(r.URL.String()) + if err == nil { + cookies := generateFakeCookies(u.Host) + c.SetCookies(u.Host, cookies) + } + + log.Printf("[INFO] Requesting URL: %s with User-Agent: %s", r.URL.String(), ua) + }) + + // 页面解析1.0 + /*var foundGood, foundBad bool + c.OnHTML("body", func(e *colly.HTMLElement) { + if strings.Contains(e.Text, "你的网站名称") { + foundGood = true + } + if strings.Contains(e.Text, "你的网站简介") { + foundBad = true + } + })*/ + + // 页面解析2.0 + c.OnHTML("body", func(e *colly.HTMLElement) { + text := strings.ToLower(e.Text) + if strings.Contains(text, strings.ToLower(keyword1)) && strings.Contains(text, strings.ToLower(keyword2)) { + task.Result = true + task.Status = "success" + } else { + task.Result = false + task.Status = "success" + } + }) + + // 错误处理 + c.OnError(func(r *colly.Response, err error) { + log.Printf("[ERROR] Failed to request URL: %s, Status Code: %d, Error: %s", r.Request.URL, r.StatusCode, err) + }) + + // 抓取页面 + err := c.Visit(task.URL) + if err != nil { + log.Printf("[ERROR] Failed to visit URL: %s, Error: %s", task.URL, err) + task.Result = false + task.Status = "failure" + updateTask(task) + return + } + + updateTask(task) + + // 结果判断 + /*task.Result = foundGood && foundBad + task.Status = "success" + if !task.Result { + task.Status = "failure" + } + updateTask(task)*/ +} + +// 更新任务状态 +func updateTask(task *Task) { + taskMu.Lock() + defer taskMu.Unlock() + db.Save(task) +} + +// API处理:提交任务 +func handlePostTask(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("X-API-KEY") != apiKey { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + var req struct { + URL string `json:"url"` + } + if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.URL == "" { + http.Error(w, "Invalid request body", http.StatusBadRequest) + return + } + + taskID := fmt.Sprintf("%d", time.Now().UnixNano()) + task := Task{ID: taskID, URL: req.URL, Status: "processing", CreatedAt: time.Now()} + db.Create(&task) + + go func() { + timeout := time.After(5 * time.Minute) + done := make(chan struct{}) + go func() { + processTask(&task) + close(done) + }() + select { + case <-done: + return + case <-timeout: + taskMu.Lock() + task.Status = "failure" + task.Result = false + db.Save(&task) + taskMu.Unlock() + } + }() + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]string{"task_id": taskID}) +} + +// API处理:查询任务 +func handleGetTask(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("X-API-KEY") != apiKey { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + taskID := r.URL.Query().Get("task_id") + if taskID == "" { + http.Error(w, "Missing task_id", http.StatusBadRequest) + return + } + + var task Task + if err := db.First(&task, "id = ?", taskID).Error; err != nil { + http.Error(w, "Task not found", http.StatusNotFound) + return + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]interface{}{ + "task_id": task.ID, + "status": task.Status, + "result": task.Result, + }) +} + +func main() { + var k1, k2, port string + flag.StringVar(&k1, "n", "example", "网站名称") + flag.StringVar(&k2, "d", "domain", "网站简介") + flag.StringVar(&port, "p", "8080", "程序运行端口") + flag.Parse() + + log.Printf("检测网站名称: %s\n", k1) + log.Printf("检测网站简介: %s\n", k2) + log.Printf("运行端口: %s\n", port) + + keyword1 = k1 + keyword2 = k2 + // 初始化 + initDB() + apiKey = generateAPIKey() + log.Printf("Server started with API Key: %s", apiKey) + + http.HandleFunc("/api/task", handlePostTask) // POST任务 + http.HandleFunc("/api/result", handleGetTask) // GET结果 + + log.Fatal(http.ListenAndServe(":"+port, nil)) +} diff --git a/tasks.db b/tasks.db new file mode 100644 index 0000000000000000000000000000000000000000..78a2569f7b98d43b933f17525df195d647c05973 GIT binary patch literal 12288 zcmeI2KX21O6u|AYB`s1hOUaM{4-B-lm-}b?Yzc{iB2>|;^v}{Mc9V;0ku<4&mI`7i zQU|^Td>}qZH%3Ozc0xiMQL&VPch<#s&+py4_q#0b*#~>uv66Ookn|&EGvlFQn#K#; zHVk7$_c`6i&D4YW@kHPA`E6~*Kp)PQtsh3kS~ILQ>)UMx@EiyL0U!VbfB+Bx0zd!= z00AHX1c1Q5C2(Pz)mp7)etN8;|(PG~E6 zuGYgW>5YflL}lrCmdG^gsn9;n`Z9^z>tQ>Qk&>NOq=g+lQgL5u`(Zx5CVjiVwX?Z@ zWWQ-1mCjaIS1b2w&ugX;pLXPVde+mKeJje;pqRIcjkQQ|%k%ohoaeIcrgdppmk*xg z*YcNK3JnMV0U!VbfB+Bx0zd!=00AHX1n!i;#r(pBxlm#cn`7G%}mzH&+md2=2Lb6stbp@2tKw z#!a}#eI{I=`+wn=2aKbU*-XD$!O?zw&nNCjv-;kwG9B#RL4L*#VT}47_J~8M^XrWN z7%X7{rvdg+Va8nNhSySqU?eDanP6CyD))83rgddlSJv0!`h2JVaBv0$fB+Bx0zd!= z00AHX1b_e#00KbZ{~}PEW9Ez!&%%^^y6%#Hi2u6O|E)HXzu0e#