2023-09-24 20:57:56 +00:00
|
|
|
// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2023-09-21 18:03:21 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/csv"
|
2023-09-26 19:32:07 +00:00
|
|
|
"errors"
|
2023-09-21 18:03:21 +00:00
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/microcosm-cc/bluemonday"
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
Model struct {
|
|
|
|
Projects []project
|
|
|
|
}
|
|
|
|
|
|
|
|
project struct {
|
|
|
|
URL string
|
|
|
|
Name string
|
|
|
|
Forge string
|
|
|
|
Running string
|
|
|
|
Releases []release
|
|
|
|
}
|
|
|
|
|
|
|
|
release struct {
|
|
|
|
Tag string
|
|
|
|
Content string
|
|
|
|
URL string
|
|
|
|
Date time.Time
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
req = make(chan struct{})
|
|
|
|
manualRefresh = make(chan struct{})
|
|
|
|
res = make(chan []project)
|
|
|
|
m = Model{
|
|
|
|
Projects: []project{},
|
|
|
|
}
|
|
|
|
bmUGC = bluemonday.UGCPolicy()
|
|
|
|
bmStrict = bluemonday.StrictPolicy()
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
file, err := os.Open("projects.csv")
|
|
|
|
if err != nil {
|
2023-09-26 20:13:18 +00:00
|
|
|
if os.IsNotExist(err) {
|
|
|
|
file, err = os.Create("projects.csv")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
_, err = file.WriteString("url,name,forge,running\nhttps://git.sr.ht/~amolith/earl,earl,sourcehut,v0.0.1-rc0\n")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
2023-09-21 18:03:21 +00:00
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
reader := csv.NewReader(file)
|
|
|
|
|
|
|
|
records, err := reader.ReadAll()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
m.Projects = []project{}
|
|
|
|
if len(records) > 0 {
|
|
|
|
for i, record := range records {
|
|
|
|
if i == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
m.Projects = append(m.Projects, project{
|
|
|
|
URL: record[0],
|
|
|
|
Name: record[1],
|
|
|
|
Forge: record[2],
|
|
|
|
Running: record[3],
|
|
|
|
Releases: []release{},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
go refreshLoop(manualRefresh, req, res)
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
|
|
|
|
httpServer := &http.Server{
|
|
|
|
Addr: "0.0.0.0:1337",
|
|
|
|
Handler: mux,
|
|
|
|
}
|
|
|
|
|
|
|
|
mux.HandleFunc("/", rootHandler)
|
|
|
|
mux.HandleFunc("/static", staticHandler)
|
|
|
|
mux.HandleFunc("/new", newHandler)
|
|
|
|
|
2023-09-26 19:32:07 +00:00
|
|
|
if err := httpServer.ListenAndServe(); errors.Is(err, http.ErrServerClosed) {
|
2023-09-21 18:03:21 +00:00
|
|
|
log.Println("Web server closed")
|
|
|
|
} else {
|
|
|
|
log.Fatalln(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func refreshLoop(manualRefresh, req chan struct{}, res chan []project) {
|
|
|
|
ticker := time.NewTicker(time.Second * 3600)
|
|
|
|
|
2023-09-26 19:33:43 +00:00
|
|
|
fetch := func() []project {
|
2023-09-21 18:03:21 +00:00
|
|
|
projects := make([]project, len(m.Projects))
|
|
|
|
copy(projects, m.Projects)
|
|
|
|
for i, project := range projects {
|
|
|
|
project, err := getReleases(project)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
projects[i] = project
|
|
|
|
}
|
|
|
|
sort.Slice(projects, func(i, j int) bool { return strings.ToLower(projects[i].Name) < strings.ToLower(projects[j].Name) })
|
|
|
|
return projects
|
|
|
|
}
|
|
|
|
|
2023-09-26 19:33:43 +00:00
|
|
|
projects := fetch()
|
2023-09-21 18:03:21 +00:00
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ticker.C:
|
2023-09-26 19:33:43 +00:00
|
|
|
projects = fetch()
|
2023-09-21 18:03:21 +00:00
|
|
|
case <-manualRefresh:
|
|
|
|
ticker.Reset(time.Second * 3600)
|
2023-09-26 19:33:43 +00:00
|
|
|
projects = fetch()
|
2023-09-21 18:03:21 +00:00
|
|
|
case <-req:
|
|
|
|
projectsCopy := make([]project, len(projects))
|
|
|
|
copy(projectsCopy, projects)
|
|
|
|
res <- projectsCopy
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|