Split into multiple files

This commit is contained in:
Anton Reinhard 2023-06-02 15:47:33 +02:00
parent f25e48d084
commit 8aa255b91a
5 changed files with 231 additions and 183 deletions

92
functions.go Normal file
View File

@ -0,0 +1,92 @@
package main
import (
"bufio"
"encoding/json"
"fmt"
"html/template"
"net/http"
"os"
"strconv"
"strings"
"time"
)
func readWebsitesFromFile(filepath string) ([]WebsiteStatus, error) {
file, err := os.Open(filepath)
if err != nil {
return nil, err
}
defer file.Close()
var websites []WebsiteStatus
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
fields := strings.Split(line, ",")
if len(fields) != 4 {
continue
}
hasIcon, _ := strconv.ParseBool(fields[2])
website := WebsiteStatus{
WebsiteURL: fields[0],
Description: fields[1],
HasIcon: hasIcon,
IconURL: fields[3],
}
websites = append(websites, website)
}
if err := scanner.Err(); err != nil {
return nil, err
}
return websites, nil
}
func checkWebsite(website string) error {
client := &http.Client{
Timeout: 5 * time.Second, // Set a timeout for the request
}
response, err := client.Head(website)
if err != nil {
return err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return fmt.Errorf("status code: %d", response.StatusCode)
}
return nil
}
func handleCheck(w http.ResponseWriter, r *http.Request) {
url := r.URL.Query().Get("url")
isUp := checkWebsite(url) == nil
response := struct {
IsUp bool `json:"isUp"`
}{
IsUp: isUp,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
func renderTemplate(w http.ResponseWriter, statuses []WebsiteStatus) {
t, err := template.ParseFiles("template.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
err = t.Execute(w, statuses)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module home_server_status
go 1.20

188
main.go
View File

@ -1,29 +1,22 @@
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"text/template"
"time"
)
type WebsiteStatus struct {
WebsiteUrl string
WebsiteURL string
Description string
HasIcon bool
IconUrl string
IconURL string
}
func main() {
websites := []WebsiteStatus{
{WebsiteUrl: "https://media.woubery.com", Description: "Jellyfin Server", HasIcon: true, IconUrl: "jellyfin.webp"},
{WebsiteUrl: "https://printing.woubery.com", Description: "OctoPrint", HasIcon: true, IconUrl: "octoprint.png"},
{WebsiteUrl: "https://code.woubery.com", Description: "Gitea Server", HasIcon: true, IconUrl: "gitea.png"},
{WebsiteUrl: "https://stream.woubery.com", Description: "Owncast Server", HasIcon: true, IconUrl: "owncast.png"},
{WebsiteUrl: "https://julia.woubery.com", Description: "Julia JupyterHub Notebook", HasIcon: true, IconUrl: "julia.png"},
{WebsiteUrl: "https://cloud.woubery.com", Description: "Cloud Server", HasIcon: false, IconUrl: ""},
websites, err := readWebsitesFromFile("websites.conf")
if err != nil {
log.Fatal(err)
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
@ -36,174 +29,3 @@ func main() {
log.Fatal(http.ListenAndServe(":8080", nil))
}
func checkWebsite(website string) error {
client := &http.Client{
Timeout: 5 * time.Second, // Set a timeout for the request
}
response, err := client.Head(website)
if err != nil {
return err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return fmt.Errorf("status code: %d", response.StatusCode)
}
return nil
}
func handleCheck(w http.ResponseWriter, r *http.Request) {
url := r.URL.Query().Get("url")
isUp := checkWebsite(url) == nil
response := struct {
IsUp bool `json:"isUp"`
}{
IsUp: isUp,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
func renderTemplate(w http.ResponseWriter, statuses []WebsiteStatus) {
tmpl := `
<html>
<head>
<title>Website Status</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f3f3f3;
padding: 20px;
margin: 0;
}
h1 {
color: #333;
text-align: center;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.website {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
background-color: #f8f8f8;
}
.status {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 2px;
margin-right: 5px;
}
.status-green {
background-color: #27ae60;
}
.status-red {
background-color: #e74c3c;
}
.website-text {
display: flex;
align-items: center;
}
.website-description {
margin-left: 10px;
font-weight: bold;
}
.website-url {
margin-left: 10px;
color: #333;
text-decoration: none;
}
.website-url:hover {
text-decoration: underline;
}
.icon {
width: 20px;
height: 20px;
margin-right: 5px;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
$(".website").each(function() {
var website = $(this);
var url = website.find(".website-url").attr("href");
$.ajax({
url: "/check?url=" + encodeURIComponent(url),
success: function(response) {
var isUp = response.isUp;
var statusElement = website.find(".status");
statusElement.removeClass("status-green status-red");
statusElement.addClass(isUp ? "status-green" : "status-red");
},
error: function() {
var statusElement = website.find(".status");
statusElement.removeClass("status-green");
statusElement.addClass("status-red");
}
});
});
});
</script>
</head>
<body>
<div class="container">
<h1>Ruby's Home Server Status</h1>
{{range .}}
<div class="website">
<div class="website-text">
<div class="status"></div>
<div class="website-description" href="{{.WebsiteUrl}}">
{{.Description}}
</div>
</div>
<a class="website-url" href="{{.WebsiteUrl}}" target="_blank">
{{.WebsiteUrl}}
{{if .HasIcon}}
<img class="icon" src="/static/{{.IconUrl}}" alt="Icon">
{{end}}
</a>
</div>
{{end}}
</div>
</body>
</html>`
t, err := template.New("webpage").Parse(tmpl)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
err = t.Execute(w, statuses)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}

125
template.html Normal file
View File

@ -0,0 +1,125 @@
<html>
<head>
<title>Website Status</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f3f3f3;
padding: 20px;
margin: 0;
}
h1 {
color: #333;
text-align: center;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.website {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
padding: 10px;
border-radius: 5px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
background-color: #f8f8f8;
}
.status {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 2px;
margin-right: 5px;
}
.status-green {
background-color: #27ae60;
}
.status-red {
background-color: #e74c3c;
}
.website-text {
display: flex;
align-items: center;
}
.website-description {
margin-left: 10px;
font-weight: bold;
}
.website-url {
margin-left: 10px;
color: #333;
text-decoration: none;
}
.website-url:hover {
text-decoration: underline;
}
.icon {
width: 20px;
height: 20px;
margin-right: 5px;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
$(".website").each(function() {
var website = $(this);
var url = website.find(".website-url").attr("href");
$.ajax({
url: "/check?url=" + encodeURIComponent(url),
success: function(response) {
var isUp = response.isUp;
var statusElement = website.find(".status");
statusElement.removeClass("status-green status-red");
statusElement.addClass(isUp ? "status-green" : "status-red");
},
error: function() {
var statusElement = website.find(".status");
statusElement.removeClass("status-green");
statusElement.addClass("status-red");
}
});
});
});
</script>
</head>
<body>
<div class="container">
<h1>Ruby's Home Server Status</h1>
{{range .}}
<div class="website">
<div class="website-text">
<div class="status"></div>
<div class="website-description" href="{{.WebsiteURL}}">
{{.Description}}
</div>
</div>
<a class="website-url" href="{{.WebsiteURL}}" target="_blank">
{{.WebsiteURL}}
{{if .HasIcon}}
<img class="icon" src="/static/{{.IconURL}}" alt="Icon">
{{end}}
</a>
</div>
{{end}}
</div>
</body>
</html>

6
websites.conf Normal file
View File

@ -0,0 +1,6 @@
https://media.woubery.com,Jellyfin Server,true,jellyfin.webp
https://printing.woubery.com,OctoPrint,true,octoprint.png
https://code.woubery.com,Gitea Server,true,gitea.png
https://stream.woubery.com,Owncast Server,true,owncast.png
https://julia.woubery.com,Julia JupyterHub Notebook,true,julia.png
https://cloud.woubery.com,Cloud Server,false,