matrix/keepalive.go
2024-11-21 20:09:48 +08:00

195 lines
4.3 KiB
Go

package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"os/exec"
"strings"
"time"
"golang.org/x/net/html"
)
// Config represents the configuration structure
type Config struct {
Username string `json:"username"`
Password string `json:"password"`
Domain string `json:"domain"`
}
func main() {
// Load or create the configuration file
config, err := readOrCreateConfig("config.json")
if err != nil {
fmt.Println("配置文件处理出错:", err)
return
}
// Schedule a task to run every 5 seconds
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
// Check if baidu.com is reachable
if !ping("180.101.50.242") {
fmt.Println("keep alive no res")
if err := performLogin(config); err != nil {
fmt.Println("执行登录操作出错:", err)
}
}
}
}
}
// performLogin performs the login operation
func performLogin(config Config) error {
// Fetch the HTML content
resp, err := http.Get("http://211.70.248.14/srun_portal_pc.php?ac_id=9&")
if err != nil {
return fmt.Errorf("GET请求出错: %w", err)
}
defer resp.Body.Close()
// Read the response body
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("读取响应出错: %w", err)
}
htmlContent := string(body)
// Parse HTML to extract form information
action, acID, userIP := parseForm(htmlContent)
action = "http://211.70.248.14/srun_portal_pc.php?ac_id=9&"
fmt.Printf("Form Info:\nAction: %s\nAC_ID: %s\nUser_IP: %s\n", action, acID, userIP)
// Construct POST data
formData := url.Values{
"action": {"login"},
"ac_id": {acID},
"user_ip": {userIP},
"username": {config.Username},
"password": {config.Password},
}
// Set domain based on the configuration
switch config.Domain {
case "CT":
formData.Add("domain", "@telcom")
case "CM":
formData.Add("domain", "@cmcc")
default:
formData.Add("domain", "")
}
// Send POST request
resp, err = http.PostForm(action, formData)
if err != nil {
return fmt.Errorf("POST请求出错: %w", err)
}
defer resp.Body.Close()
return nil
}
// readOrCreateConfig reads or creates the configuration file
func readOrCreateConfig(filePath string) (Config, error) {
var config Config
// Try reading the configuration file
configFile, err := ioutil.ReadFile(filePath)
if err == nil {
// File exists, parse the configuration file
err = json.Unmarshal(configFile, &config)
if err != nil {
return config, fmt.Errorf("解析配置文件出错: %w", err)
}
return config, nil
}
// File does not exist, create a default configuration file
if os.IsNotExist(err) {
defaultConfig := Config{
Username: "your_username",
Password: "your_password",
Domain: "CT",
}
configJSON, _ := json.MarshalIndent(defaultConfig, "", " ")
err = ioutil.WriteFile(filePath, configJSON, 0644)
if err != nil {
return config, fmt.Errorf("创建配置文件出错: %w", err)
}
fmt.Println("配置文件已创建,使用默认值。请编辑配置文件以更新信息。")
return defaultConfig, nil
}
return config, fmt.Errorf("读取配置文件出错: %w", err)
}
// parseForm parses the HTML content to extract form information
func parseForm(htmlContent string) (action, acID, userIP string) {
doc, err := html.Parse(strings.NewReader(htmlContent))
if err != nil {
fmt.Println("解析HTML出错:", err)
return
}
var parse func(*html.Node)
parse = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "form" {
for _, a := range n.Attr {
if a.Key == "action" {
action = a.Val
}
}
}
if n.Type == html.ElementNode && n.Data == "input" {
for _, a := range n.Attr {
if a.Key == "name" {
switch a.Val {
case "ac_id":
acID = getInputValue(n)
case "user_ip":
userIP = getInputValue(n)
}
}
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
parse(c)
}
}
parse(doc)
return
}
// getInputValue gets the value of an input element
func getInputValue(n *html.Node) string {
for _, a := range n.Attr {
if a.Key == "value" {
return a.Val
}
}
return ""
}
// ping checks if the given host is reachable
func ping(host string) bool {
cmd := exec.Command("ping", "-c", "1", host)
err := cmd.Run()
if err != nil {
fmt.Println("Ping 错误:", err)
return false
}
return true
}