+1
-1
.air.toml
+1
-1
.air.toml
+11
-107
cmd/handlers.go
+11
-107
cmd/handlers.go
···
15
15
"github.com/teal-fm/piper/session"
16
16
)
17
17
18
+
type HomeParams struct {
19
+
IsLoggedIn bool
20
+
LastFMUsername *string
21
+
}
22
+
18
23
func home(database *db.DB, pages *pages.Pages) http.HandlerFunc {
19
24
return func(w http.ResponseWriter, r *http.Request) {
20
25
···
33
38
log.Printf("Error fetching user %d details for home page: %v", userID, err)
34
39
}
35
40
}
36
-
37
-
html := `
38
-
<html>
39
-
<head>
40
-
<title>Piper - Spotify & Last.fm Tracker</title>
41
-
<style>
42
-
body {
43
-
font-family: Arial, sans-serif;
44
-
max-width: 800px;
45
-
margin: 0 auto;
46
-
padding: 20px;
47
-
line-height: 1.6;
48
-
}
49
-
h1 {
50
-
color: #1DB954; /* Spotify green */
51
-
}
52
-
.nav {
53
-
display: flex;
54
-
flex-wrap: wrap; /* Allow wrapping on smaller screens */
55
-
margin-bottom: 20px;
56
-
}
57
-
.nav a {
58
-
margin-right: 15px;
59
-
margin-bottom: 5px; /* Add spacing below links */
60
-
text-decoration: none;
61
-
color: #1DB954;
62
-
font-weight: bold;
63
-
}
64
-
.card {
65
-
border: 1px solid #ddd;
66
-
border-radius: 8px;
67
-
padding: 20px;
68
-
margin-bottom: 20px;
69
-
}
70
-
.service-status {
71
-
font-style: italic;
72
-
color: #555;
73
-
}
74
-
</style>
75
-
</head>
76
-
<body>
77
-
<h1>Piper - Multi-User Spotify & Last.fm Tracker via ATProto</h1>
78
-
<div class="nav">
79
-
<a href="/">Home</a>`
80
-
81
-
if isLoggedIn {
82
-
html += `
83
-
<a href="/current-track">Spotify Current</a>
84
-
<a href="/history">Spotify History</a>
85
-
<a href="/link-lastfm">Link Last.fm</a>` // Link to Last.fm page
86
-
if lastfmUsername != "" {
87
-
html += ` <a href="/lastfm/recent">Last.fm Recent</a>` // Show only if linked
88
-
}
89
-
html += `
90
-
<a href="/api-keys">API Keys</a>
91
-
<a href="/login/spotify">Connect Spotify Account</a>
92
-
<a href="/logout">Logout</a>`
93
-
} else {
94
-
html += `
95
-
<a href="/login/atproto">Login with ATProto</a>`
41
+
params := HomeParams{
42
+
IsLoggedIn: isLoggedIn,
43
+
LastFMUsername: &lastfmUsername,
96
44
}
97
-
98
-
html += `
99
-
</div>
100
-
101
-
<div class="card">
102
-
<h2>Welcome to Piper</h2>
103
-
<p>Piper is a multi-user application that records what you're listening to on Spotify and Last.fm, saving your listening history.</p>`
104
-
105
-
if !isLoggedIn {
106
-
html += `
107
-
<p>Login with ATProto to get started!</p>
108
-
<form action="/login/atproto">
109
-
<label for="handle">handle:</label>
110
-
<input type="text" id="handle" name="handle" >
111
-
<input type="submit" value="submit">
112
-
</form>`
113
-
} else {
114
-
html += `
115
-
<p>You're logged in!</p>
116
-
<ul>
117
-
<li><a href="/login/spotify">Connect your Spotify account</a> to start tracking.</li>
118
-
<li><a href="/link-lastfm">Link your Last.fm account</a> to track scrobbles.</li>
119
-
</ul>
120
-
<p>Once connected, you can check out your:</p>
121
-
<ul>
122
-
<li><a href="/current-track">Spotify current track</a> or <a href="/history">listening history</a>.</li>`
123
-
if lastfmUsername != "" {
124
-
html += `<li><a href="/lastfm/recent">Last.fm recent tracks</a>.</li>`
125
-
}
126
-
html += `
127
-
</ul>
128
-
<p>You can also manage your <a href="/api-keys">API keys</a> for programmatic access.</p>`
129
-
if lastfmUsername != "" {
130
-
html += fmt.Sprintf("<p class='service-status'>Last.fm Username: %s</p>", lastfmUsername)
131
-
} else {
132
-
html += "<p class='service-status'>Last.fm account not linked.</p>"
133
-
}
134
-
45
+
err := pages.Execute("home", w, params)
46
+
if err != nil {
47
+
log.Printf("Error executing template: %v", err)
135
48
}
136
-
137
-
html += `
138
-
</div> <!-- Close card div -->
139
-
</body>
140
-
</html>
141
-
`
142
-
pages.Execute("home", w, nil)
143
-
144
-
//w.Write([]byte(html))
145
49
}
146
50
}
147
51
+1
-1
cmd/main.go
+1
-1
cmd/main.go
···
107
107
spotifyService: spotifyService,
108
108
atprotoService: atprotoService,
109
109
playingNowService: playingNowService,
110
-
pages: pages.NewPages(false),
110
+
pages: pages.NewPages(),
111
111
}
112
112
113
113
trackerInterval := time.Duration(viper.GetInt("tracker.interval")) * time.Second
+8
-19
pages/pages.go
+8
-19
pages/pages.go
···
1
1
package pages
2
2
3
+
// inspired from tangled's implementation
4
+
//https://tangled.org/@tangled.org/core/blob/master/appview/pages/pages.go
5
+
3
6
import (
4
7
"embed"
5
8
"html/template"
6
9
"io"
7
10
"io/fs"
8
-
"os"
9
11
"strings"
10
12
"time"
11
13
)
···
13
15
//go:embed templates/*
14
16
var Files embed.FS
15
17
16
-
// inspired from tangled's implementation
17
-
//https://tangled.org/@tangled.org/core/blob/master/appview/pages/pages.go
18
-
19
18
type Pages struct {
20
19
cache *TmplCache[string, *template.Template]
21
-
dev bool
22
20
templateDir string // Path to templates on disk for dev mode
23
21
embedFS fs.FS
24
22
}
25
23
26
-
func NewPages(dev bool) *Pages {
27
-
pages := &Pages{
28
-
cache: NewTmplCache[string, *template.Template](),
29
-
dev: dev,
30
-
templateDir: "templates",
31
-
}
32
-
if pages.dev {
33
-
pages.embedFS = os.DirFS(pages.templateDir)
34
-
} else {
35
-
pages.embedFS = Files
24
+
func NewPages() *Pages {
25
+
return &Pages{
26
+
cache: NewTmplCache[string, *template.Template](),
27
+
embedFS: Files,
36
28
}
37
-
38
-
return pages
39
29
}
40
30
41
31
func (p *Pages) fragmentPaths() ([]string, error) {
···
99
89
func (p *Pages) parse(stack ...string) (*template.Template, error) {
100
90
key := strings.Join(stack, "|")
101
91
102
-
// never cache in dev mode
103
-
if cached, exists := p.cache.Get(key); !p.dev && exists {
92
+
if cached, exists := p.cache.Get(key); exists {
104
93
return cached, nil
105
94
}
106
95
+58
-1
pages/templates/home.gohtml
+58
-1
pages/templates/home.gohtml
···
1
1
2
2
{{ define "content" }}
3
3
4
-
<h1>Test</h1>
4
+
<h1>Piper - Multi-User Spotify & Last.fm Tracker via ATProto</h1>
5
+
<div class="nav">
6
+
<a href="/">Home</a>
7
+
8
+
{{if .IsLoggedIn}}
9
+
<a href="/current-track">Spotify Current</a>
10
+
<a href="/history">Spotify History</a>
11
+
<a href="/link-lastfm">Link Last.fm</a>
12
+
{{ if .LastFMUsername }}
13
+
<a href="/lastfm/recent">Last.fm Recent</a>
14
+
{{ end }}
15
+
<a href="/api-keys">API Keys</a>
16
+
<a href="/login/spotify">Connect Spotify Account</a>
17
+
<a href="/logout">Logout</a>
18
+
{{ else }}
19
+
<a href="/login/atproto">Login with ATProto</a>
20
+
{{ end }}
21
+
</div>
22
+
23
+
<div class="card">
24
+
<h2>Welcome to Piper</h2>
25
+
<p>Piper is a multi-user application that records what you're listening to on Spotify and Last.fm, saving your listening history.</p>
26
+
27
+
{{if .IsLoggedIn}}
28
+
<p>You're logged in!</p>
29
+
<ul>
30
+
<li><a href="/login/spotify">Connect your Spotify account</a> to start tracking.</li>
31
+
<li><a href="/link-lastfm">Link your Last.fm account</a> to track scrobbles.</li>
32
+
</ul>
33
+
<p>Once connected, you can check out your:</p>
34
+
<ul>
35
+
<li><a href="/current-track">Spotify current track</a> or <a href="/history">listening history</a>.</li>
36
+
{{ if .LastFMUsername }}
37
+
<li><a href="/lastfm/recent">Last.fm recent tracks</a>.</li>
38
+
{{ end }}
39
+
40
+
</ul>
41
+
<p>You can also manage your <a href="/api-keys">API keys</a> for programmatic access.</p>
42
+
43
+
{{ if .LastFMUsername }}
44
+
<p class='service-status'>Last.fm Username: {{ .LastFMUsername }}</p>
45
+
{{else }}
46
+
<p class='service-status'>Last.fm account not linked.</p>
47
+
{{end}}
48
+
49
+
50
+
{{ else }}
51
+
52
+
<p>Login with ATProto to get started!</p>
53
+
<form action="/login/atproto">
54
+
<label for="handle">handle:</label>
55
+
<input type="text" id="handle" name="handle" >
56
+
<input type="submit" value="submit">
57
+
</form>
58
+
59
+
60
+
{{ end }}
61
+
</div> <!-- Close card div -->
5
62
6
63
{{ end }}