-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: config via flag or env + refactor (#8)
- Loading branch information
Showing
7 changed files
with
466 additions
and
349 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,24 @@ | ||
# rastermimimi | ||
|
||
Schaut sich die diversen Programmraster Quellen an und macht mimimi. | ||
|
||
## Usage | ||
|
||
``` | ||
Usage of rastermimimi: | ||
-duration int | ||
How far ahead to check in days (default 60) | ||
-libretime string | ||
URL of Libretime Instance to compare (default "https://airtime.service.int.rabe.ch") | ||
-listen-addr string | ||
listen address (default ":8080") | ||
-url string | ||
URL of RaBe Website (default "https://rabe.ch") | ||
``` | ||
|
||
## Development | ||
|
||
Run mimimi to test changes: | ||
``` | ||
go run . | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"html" | ||
"io/ioutil" | ||
"log" | ||
"net/http" | ||
"sort" | ||
"sync/atomic" | ||
"time" | ||
) | ||
|
||
type App struct { | ||
config AppConfig | ||
|
||
errors atomic.Value | ||
} | ||
|
||
func NewApp(config AppConfig) *App { | ||
return &App{config: config} | ||
} | ||
|
||
func (a *App) Load() { | ||
grid := make(map[string]gridSlot) | ||
errors := make(gridErrors, 0) | ||
|
||
grid, errors = a.loadWebsite(grid, errors) | ||
grid = a.loadLibretime(grid) | ||
|
||
errors = a.checkForErrors(grid, errors) | ||
|
||
log.Printf("Loaded %d grid entries and %d errors.\n", len(grid), len(errors)) | ||
|
||
a.errors.Store(errors) | ||
} | ||
|
||
func (a *App) GetErrors() gridErrors { | ||
return a.errors.Load().(gridErrors) | ||
} | ||
|
||
func (a *App) appendError(errors gridErrors, message string, start LocalTime, slot gridSlot) gridErrors { | ||
errors = append(errors, gridError{ | ||
Message: message, | ||
Time: start.GetTime(), | ||
Slot: slot, | ||
}) | ||
return errors | ||
} | ||
|
||
func (a *App) loadWebsite(grid map[string]gridSlot, errors gridErrors) (map[string]gridSlot, gridErrors) { | ||
// get config | ||
url := a.config.websiteURL | ||
duration := a.config.duration | ||
|
||
start := time.Now() | ||
end := start.AddDate(0, 0, duration) | ||
resp, err := http.Get( | ||
fmt.Sprintf( | ||
"%s/wp-admin/admin-ajax.php?action=eventorganiser-fullcal&start=%s&end=%s&timeformat=%s", | ||
url, | ||
start.Format("2006-01-02"), | ||
end.Format("2006-01-02"), | ||
"G%3Ai", | ||
), | ||
) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
defer resp.Body.Close() | ||
body, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
// parse JSON | ||
var events []WebsiteEventOrganizerCalendarEvent | ||
err = json.Unmarshal(body, &events) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
for _, event := range events { | ||
start := event.Start.String() | ||
slot, ok := grid[start] | ||
if ok { | ||
if slot.WebsiteEventOrganizerCalendarEvent.Title != "" { | ||
errors = a.appendError( | ||
errors, | ||
fmt.Sprintf("Mehrfacheintrag auf Webseite: %s (neu: %s)", | ||
slot.WebsiteEventOrganizerCalendarEvent.Title, event.Title), | ||
slot.WebsiteEventOrganizerCalendarEvent.Start, slot) | ||
} | ||
slot.WebsiteEventOrganizerCalendarEvent = event | ||
grid[start] = slot | ||
} else { | ||
grid[start] = gridSlot{ | ||
WebsiteEventOrganizerCalendarEvent: event, | ||
} | ||
} | ||
} | ||
return grid, errors | ||
} | ||
|
||
func (a *App) loadLibretime(grid map[string]gridSlot) map[string]gridSlot { | ||
// get config | ||
url := a.config.libretimeURL | ||
duration := a.config.duration | ||
|
||
// read from libretime calendar | ||
resp, err := http.Get(fmt.Sprintf("%s/api/live-info-v2?days=%d&shows=600000000", url, duration+1)) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
defer resp.Body.Close() | ||
body, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
// parse JSON | ||
var liveInfo LibreTimeLiveInfoV2 | ||
err = json.Unmarshal(body, &liveInfo) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
liveInfo.Shows.Next = append(liveInfo.Shows.Next, liveInfo.Shows.Current) | ||
for _, ltShow := range liveInfo.Shows.Next { | ||
start := ltShow.Starts.String() | ||
slot, ok := grid[start] | ||
|
||
if ok { | ||
if slot.LibreTimeLiveInfoV2Show.Name != "" { | ||
log.Panicf("slot %s already has a libretime title", start) | ||
} | ||
ltShow.Name = html.UnescapeString(ltShow.Name) | ||
slot.LibreTimeLiveInfoV2Show = ltShow | ||
grid[start] = slot | ||
} else { | ||
grid[start] = gridSlot{ | ||
LibreTimeLiveInfoV2Show: ltShow, | ||
} | ||
} | ||
} | ||
return grid | ||
} | ||
|
||
func (a *App) checkForErrors(grid map[string]gridSlot, errors gridErrors) gridErrors { | ||
for _, slot := range grid { | ||
// skip past events | ||
if slot.WebsiteEventOrganizerCalendarEvent.Title != "" && slot.WebsiteEventOrganizerCalendarEvent.Start.Before(time.Now()) { | ||
continue | ||
} | ||
if slot.WebsiteEventOrganizerCalendarEvent.Title != "" && slot.LibreTimeLiveInfoV2Show.Name == "" { | ||
if slot.WebsiteEventOrganizerCalendarEvent.Title != "Klangbecken" { | ||
errors = a.appendError(errors, | ||
fmt.Sprintf("%s fehlt in LibreTime.", | ||
slot.WebsiteEventOrganizerCalendarEvent.Title), | ||
slot.WebsiteEventOrganizerCalendarEvent.Start, slot) | ||
} | ||
} else if slot.LibreTimeLiveInfoV2Show.Name != "" && slot.WebsiteEventOrganizerCalendarEvent.Title == "" { | ||
if slot.LibreTimeLiveInfoV2Show.Name != "Klangbecken" { | ||
errors = a.appendError(errors, | ||
fmt.Sprintf("%s fehlt auf Web Seite.", | ||
slot.LibreTimeLiveInfoV2Show.Name), | ||
slot.LibreTimeLiveInfoV2Show.Starts, slot) | ||
} | ||
} else if slot.WebsiteEventOrganizerCalendarEvent.Title != slot.LibreTimeLiveInfoV2Show.Name { | ||
errors = a.appendError(errors, | ||
fmt.Sprintf("Titel auf Webseite (%s) stimmt nicht mit LibreTime (%s) überein.", | ||
slot.WebsiteEventOrganizerCalendarEvent.Title, slot.LibreTimeLiveInfoV2Show.Name), | ||
slot.WebsiteEventOrganizerCalendarEvent.Start, slot) | ||
} | ||
|
||
// skip events not on both sides for further checks | ||
if slot.WebsiteEventOrganizerCalendarEvent.Title == "" || slot.LibreTimeLiveInfoV2Show.Name == "" { | ||
continue | ||
} | ||
|
||
if slot.LibreTimeLiveInfoV2Show.URL != slot.WebsiteEventOrganizerCalendarEvent.URL { | ||
if slot.WebsiteEventOrganizerCalendarEvent.URL == "#" { | ||
errors = a.appendError(errors, | ||
fmt.Sprintf("Keine URL für Sendung %s auf Website hinterlegt.", | ||
slot.WebsiteEventOrganizerCalendarEvent.Title), | ||
slot.WebsiteEventOrganizerCalendarEvent.Start, slot) | ||
} else { | ||
errors = a.appendError(errors, | ||
fmt.Sprintf("URL auf Webseite (%s) stimmt nicht mit LibreTime (%s) überein.", | ||
slot.WebsiteEventOrganizerCalendarEvent.URL, slot.LibreTimeLiveInfoV2Show.URL), | ||
slot.WebsiteEventOrganizerCalendarEvent.Start, slot) | ||
} | ||
} | ||
|
||
// we allow a difference of > 10 minutes at the end to account for preproduced broadcasts that go into overtime | ||
if !slot.LibreTimeLiveInfoV2Show.Ends.Equal(slot.WebsiteEventOrganizerCalendarEvent.End.Time) && slot.LibreTimeLiveInfoV2Show.Ends.Time.Sub(slot.WebsiteEventOrganizerCalendarEvent.End.Time) > time.Minute*10 { | ||
errors = a.appendError(errors, | ||
fmt.Sprintf("Ende auf Webseite (%s) stimmt nicht mit LibreTime (%s) überein.", | ||
slot.WebsiteEventOrganizerCalendarEvent.End.Format("02 Jan 2006 15:04:05"), | ||
slot.LibreTimeLiveInfoV2Show.Ends.Format("02 Jan 2006 15:04:05")), | ||
slot.WebsiteEventOrganizerCalendarEvent.Start, slot) | ||
} | ||
|
||
} | ||
sort.Sort(errors) | ||
return errors | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<!DOCTYPE html> | ||
<title>Raster Mimimi</title> | ||
<style> | ||
html, body { | ||
font-family: sans-serif; | ||
font-size: 0.9em; | ||
} | ||
@media (prefers-color-scheme: dark) { | ||
html, body { | ||
background-color: black; | ||
color: lightgray; | ||
} | ||
:link { | ||
color: mediumpurple; | ||
} | ||
} | ||
article { | ||
border: 1px solid gray; | ||
padding: 1em; | ||
margin-bottom: 0.5em; | ||
} | ||
section { | ||
margin-left: 2em; | ||
} | ||
section.lead { | ||
font-size: 1.5em; | ||
margin-left: 0; | ||
} | ||
</style> | ||
<script> | ||
window.onbeforeprint = function(event) { | ||
document.body.style.display = 'none'; | ||
window.alert('ja nid usdrucke!, so vowäge umwäut!') | ||
}; | ||
window.onafterprint = function(event) { | ||
document.body.style.display = '' | ||
}; | ||
</script> | ||
<h1>technisches Programmraster Mimimi</h1> | ||
<nav><a href="/refresh">Refresh...</a> | <a href="#" onclick="alert('ja nid usdrucke!, so vowäge umwäut!')">Drucken...</a> | <a href="https://github.com/radiorabe/rastermimimi">GitHub...</a></nav> | ||
<p>Dieses Tool hat in den nächsten 60 Tagen {{.|len}} Mimimis gefunden.</p> | ||
{{$otime := "02 Jan 2006 15:04:05"}} | ||
{{range .}} | ||
{{$time := .Time.Format "02 Jan 2006 15:04:05"}} | ||
{{if ne $time $otime}} | ||
<hr> | ||
<h2>{{$time}}</h2> | ||
{{end}} | ||
<article> | ||
<section class="lead">{{.Message}}</section> | ||
<!-- {{.}} --> | ||
{{if .Slot.WebsiteEventOrganizerCalendarEvent.Title}} | ||
<section> | ||
<h3>Web: {{.Slot.WebsiteEventOrganizerCalendarEvent.Title}}</h3> | ||
<p>{{.Slot.WebsiteEventOrganizerCalendarEvent.Start.Format "02 Jan 2006 15:04:05"}} - {{.Slot.WebsiteEventOrganizerCalendarEvent.End.Format "02 Jan 2006 15:04:05"}}</p> | ||
<p><b>URL:</b> <code>{{.Slot.WebsiteEventOrganizerCalendarEvent.URL}}</code></p> | ||
</section> | ||
{{end}} | ||
{{if .Slot.LibreTimeLiveInfoV2Show.Name}} | ||
<section> | ||
<h3>LibreTime: {{.Slot.LibreTimeLiveInfoV2Show.Name}}</h3> | ||
<p>{{.Slot.LibreTimeLiveInfoV2Show.Starts.Format "02 Jan 2006 15:04:05"}} - {{.Slot.LibreTimeLiveInfoV2Show.Ends.Format "02 Jan 2006 15:04:05"}}</p> | ||
<p><b>URL:</b> <code>{{.Slot.LibreTimeLiveInfoV2Show.URL}}</code></p> | ||
</section> | ||
{{end}} | ||
</article> | ||
{{$otime = $time}} | ||
{{end}} |
Oops, something went wrong.