Skip to content

Commit

Permalink
Deprecated php support and added totp
Browse files Browse the repository at this point in the history
  • Loading branch information
tobychui committed Oct 5, 2023
1 parent 6215fce commit a7f627e
Show file tree
Hide file tree
Showing 10 changed files with 788 additions and 427 deletions.
213 changes: 32 additions & 181 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,45 +1,23 @@
package main

import (
"encoding/json"
"embed"
"flag"
"io/ioutil"
"io/fs"
"log"
"net/http"
"os"
"time"

"imuslab.com/utm/pkg/utils"
)

/*
Simple uptime monitor
by tobychui
*/
Uptime Monitor ToolBox
Author: tobychui
type Record struct {
Timestamp int64
ID string
Name string
URL string
Protocol string
Online bool
StatusCode int
Latency int64
}
This is a generic tool for hosting basic information required for my server daily operations
type Target struct {
ID string
Name string
URL string
Protocol string
}
type Config struct {
Targets []*Target
Interval int
RecordsInJson int
LogToFile bool
}
*/

//go:embed web/*
var content embed.FS

// Default configs
var configFilepath = "config.json"
Expand All @@ -53,172 +31,45 @@ var exampleTarget = Target{
var usingConfig *Config
var onlineStatusLog = map[string][]*Record{}

// TOTP configs
var totpConfig *TotpConfig

// Set this to true to use file system based UI files
var uiDebugMode = false

// Flags
var listeningPort = flag.String("p", ":8089", "Listening endpoint for http server")

func main() {
log.Println("-- Uptime Monitor Started --")
if !utils.FileExists(configFilepath) {
log.Println("config.json not found. Template created.")
template := Config{
Targets: []*Target{&exampleTarget},
Interval: 60,
}
js, _ := json.MarshalIndent(template, "", " ")
os.WriteFile(configFilepath, js, 0775)
os.Exit(0)
}

flag.Parse()

c, err := ioutil.ReadFile(configFilepath)
//Start the uptime monitor
err := UptimeMonitorInit()
if err != nil {
panic(err)
}

parsedConfig := Config{}
err = json.Unmarshal(c, &parsedConfig)
//Start TOTP resolver
err = totpInit()
if err != nil {
panic(err)
}

usingConfig = &parsedConfig

//Start the endpoint listener
ticker := time.NewTicker(time.Duration(usingConfig.Interval) * time.Second)
done := make(chan bool)

//Start the uptime check once first before entering loop
ExecuteUptimeCheck()

go func() {
for {
select {
case <-done:
return
case t := <-ticker.C:
log.Println("Uptime updated - ", t.Unix())
ExecuteUptimeCheck()
}
}
}()

http.HandleFunc("/", HandleUptimeLogRead)

//Start the web server interface
http.ListenAndServe(*listeningPort, nil)
}

func ExecuteUptimeCheck() {
for _, target := range usingConfig.Targets {
//For each target to check online, do the following
var thisRecord Record
if target.Protocol == "http" || target.Protocol == "https" {
online, laterncy, statusCode := getWebsiteStatusWithLatency(target.URL)
thisRecord = Record{
Timestamp: time.Now().Unix(),
ID: target.ID,
Name: target.Name,
URL: target.URL,
Protocol: target.Protocol,
Online: online,
StatusCode: statusCode,
Latency: laterncy,
}

//fmt.Println(thisRecord)

} else {
log.Println("Unknown protocol: " + target.Protocol + ". Skipping")
continue
}

thisRecords, ok := onlineStatusLog[target.ID]
if !ok {
//First record. Create the array
onlineStatusLog[target.ID] = []*Record{&thisRecord}
} else {
//Append to the previous record
thisRecords = append(thisRecords, &thisRecord)

//Check if the record is longer than the logged record. If yes, clear out the old records
if len(thisRecords) > usingConfig.RecordsInJson {
thisRecords = thisRecords[1:]
}

onlineStatusLog[target.ID] = thisRecords

}
}

//Write the results to a json file
if usingConfig.LogToFile {
//Log to file
js, _ := json.MarshalIndent(onlineStatusLog, "", " ")
os.WriteFile(logFilepath, js, 0775)
}
}
http.HandleFunc("/utm/update", HandleUptimeLogRead)
http.HandleFunc("/totp/update", HandleTOTPUpdate)

/*
Web Interface Handler
*/

func HandleUptimeLogRead(w http.ResponseWriter, r *http.Request) {
id, _ := utils.GetPara(r, "id")
if id == "" {
js, _ := json.Marshal(onlineStatusLog)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
var webfs, _ = fs.Sub(content, "web")
if uiDebugMode {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.FileServer(http.Dir("./web")).ServeHTTP(w, r)
})
} else {
//Check if that id exists
log, ok := onlineStatusLog[id]
if !ok {
http.NotFound(w, r)
return
}

js, _ := json.MarshalIndent(log, "", " ")
w.Header().Set("Content-Type", "application/json")
w.Write(js)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.FileServer(http.FS(webfs)).ServeHTTP(w, r)
})
}

}

/*
Utilities
*/

// Get website stauts with latency given URL, return is conn succ and its latency and status code
func getWebsiteStatusWithLatency(url string) (bool, int64, int) {
start := time.Now().UnixNano() / int64(time.Millisecond)
statusCode, err := getWebsiteStatus(url)
end := time.Now().UnixNano() / int64(time.Millisecond)
if err != nil {
return false, 0, 0
} else {
diff := end - start
succ := false
if statusCode >= 200 && statusCode < 300 {
//OK
succ = true
} else if statusCode >= 300 && statusCode < 400 {
//Redirection code
succ = true
} else {
succ = false
}

return succ, diff, statusCode
}

}
func getWebsiteStatus(url string) (int, error) {
resp, err := http.Get(url)
if err != nil {
return 0, err
}
status_code := resp.StatusCode

resp.Body.Close()
return status_code, nil
//Start the web server interface
log.Println("Listening on :8089")
http.ListenAndServe(*listeningPort, nil)
}
23 changes: 0 additions & 23 deletions php/api.php

This file was deleted.

Binary file removed php/favicon.psd
Binary file not shown.
Loading

0 comments on commit a7f627e

Please sign in to comment.