Add next broadcast timer and enhance web security
This commit is contained in:
parent
68ce2c88d2
commit
ae93557d15
@ -32,6 +32,8 @@ type DashboardData struct {
|
||||
TotalBroadcast int
|
||||
NewInLastHour int
|
||||
UnsummarizedCount int
|
||||
NextBroadcastIn string // Time until the next broadcast attempt
|
||||
LastBroadcastTime time.Time // When the last broadcast occurred
|
||||
NextUp []Article
|
||||
History []Article
|
||||
RecentLogs []LogEntry
|
||||
|
@ -186,6 +186,10 @@
|
||||
<div class="stat-label">Awaiting Summary</div>
|
||||
<div class="stat-number">{{.UnsummarizedCount}}</div>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="stat-label">Next Broadcast In</div>
|
||||
<div class="stat-number">{{.NextBroadcastIn}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
|
75
webserver.go
75
webserver.go
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strings"
|
||||
@ -19,8 +20,30 @@ func webServer(shutdown chan struct{}) {
|
||||
return
|
||||
}
|
||||
|
||||
// Define HTTP handlers
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
// Create a custom request handler with security headers
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Add security headers
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("X-Frame-Options", "DENY")
|
||||
w.Header().Set("Content-Security-Policy", "default-src 'self'; style-src 'self' 'unsafe-inline'")
|
||||
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
|
||||
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
|
||||
|
||||
// Enforce request method
|
||||
if r.Method != http.MethodGet {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
// Limit request body size (1MB)
|
||||
r.Body = http.MaxBytesReader(w, r.Body, 1<<20)
|
||||
|
||||
// Only serve the index page
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := getDashboardData()
|
||||
if err != nil {
|
||||
http.Error(w, "Error fetching data: "+err.Error(), http.StatusInternalServerError)
|
||||
@ -42,10 +65,14 @@ func webServer(shutdown chan struct{}) {
|
||||
}
|
||||
})
|
||||
|
||||
// Start the server
|
||||
// Configure server with appropriate timeouts
|
||||
server := &http.Server{
|
||||
Addr: ":8080",
|
||||
Handler: nil, // Use default mux
|
||||
Addr: ":8080",
|
||||
Handler: handler,
|
||||
ReadTimeout: 10 * time.Second, // Time to read the request
|
||||
WriteTimeout: 30 * time.Second, // Time to write the response
|
||||
IdleTimeout: 60 * time.Second, // Keep-alive connections timeout
|
||||
MaxHeaderBytes: 1 << 20, // 1MB max header size
|
||||
}
|
||||
|
||||
// Create a goroutine for the server
|
||||
@ -91,9 +118,15 @@ func getDashboardData() (DashboardData, error) {
|
||||
}
|
||||
|
||||
// Count broadcast articles, recent articles, and unsummarized articles
|
||||
var lastBroadcastTime time.Time
|
||||
for _, a := range articles {
|
||||
if !a.BroadcastTime.IsZero() && a.BroadcastTime.Unix() > 1 {
|
||||
data.TotalBroadcast++
|
||||
|
||||
// Track the most recent broadcast time
|
||||
if a.BroadcastTime.After(lastBroadcastTime) {
|
||||
lastBroadcastTime = a.BroadcastTime
|
||||
}
|
||||
}
|
||||
|
||||
if a.FirstSeen.After(hourAgo) {
|
||||
@ -105,6 +138,38 @@ func getDashboardData() (DashboardData, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Set the last broadcast time
|
||||
data.LastBroadcastTime = lastBroadcastTime
|
||||
|
||||
// Calculate time until next broadcast
|
||||
if lastBroadcastTime.IsZero() {
|
||||
data.NextBroadcastIn = "As soon as articles are summarized"
|
||||
} else {
|
||||
nextBroadcastTime := lastBroadcastTime.Add(BROADCAST_INTERVAL)
|
||||
if now.After(nextBroadcastTime) {
|
||||
// If we're past the interval but haven't broadcast yet,
|
||||
// likely waiting for articles to be summarized
|
||||
if data.UnsummarizedCount > 0 {
|
||||
data.NextBroadcastIn = "Waiting for articles to be summarized"
|
||||
} else {
|
||||
data.NextBroadcastIn = "Pending (checking every " + BROADCAST_CHECK_INTERVAL.String() + ")"
|
||||
}
|
||||
} else {
|
||||
// We're still within the interval, calculate remaining time
|
||||
timeUntilNextBroadcast := nextBroadcastTime.Sub(now)
|
||||
|
||||
// Format as hours and minutes
|
||||
hours := int(timeUntilNextBroadcast.Hours())
|
||||
minutes := int(timeUntilNextBroadcast.Minutes()) % 60
|
||||
|
||||
if hours > 0 {
|
||||
data.NextBroadcastIn = fmt.Sprintf("%dh %dm", hours, minutes)
|
||||
} else {
|
||||
data.NextBroadcastIn = fmt.Sprintf("%dm", minutes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get broadcast history (last 100)
|
||||
history, err := getBroadcastHistory(100)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user