теперь сервер раз в 30 секунд обновляет последний прослушанный трек, добавил поле под него в app

design
serr 2025-05-19 17:03:18 +03:00
parent 9aa39d8f65
commit 8c5c5d6150
7 changed files with 98 additions and 51 deletions

16
main.go
View File

@ -8,6 +8,7 @@ import (
"main/mvc/models" "main/mvc/models"
"main/tools" "main/tools"
"net/http" "net/http"
"time"
) )
func main() { func main() {
@ -25,6 +26,19 @@ func main() {
// Настройка маршрутов // Настройка маршрутов
router := setupRoutes(app) router := setupRoutes(app)
// Запуск тикеров
{
// Обновление последнего прослушанного трека ластфм
tools.Ticker(func() {
var lastTrack string
if lastTrack, err = models.LastFMGetLastTrack(app.Cfg.LastFMUsername, app.Cfg.LastFMToken); err != nil {
log.Println(err)
return
}
app.LastfmLastTrack = lastTrack
}, time.Second*app.Cfg.LastFMUpdateInterval)
}
// Запуск сервера // Запуск сервера
if ok, err := tools.IsIPInUse(app.Cfg.ServerIP); err != nil { if ok, err := tools.IsIPInUse(app.Cfg.ServerIP); err != nil {
log.Fatal(err) log.Fatal(err)
@ -61,7 +75,7 @@ func setupRoutes(app *models.App) *http.ServeMux {
// Api // Api
{ {
router.Handle("/api/lastfm", m(controllers.LastfmHandler(app))) router.Handle("/api/lastfm", m(controllers.LastFMHandler(app)))
} }
return router return router

View File

@ -2,35 +2,19 @@ package controllers
import ( import (
"fmt" "fmt"
"log"
"main/mvc/models" "main/mvc/models"
"net/http" "net/http"
) )
// Обработчик главной страницы // Обработчик главной страницы
func LastfmHandler(app *models.App) http.HandlerFunc { func LastFMHandler(app *models.App) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var err error sendLastFM(w, app.LastfmLastTrack)
resp, err := models.GetRecentTracks(app.Cfg.LastfmUsername, app.Cfg.LastfmToken)
if err != nil {
log.Println(err)
}
var data string
if len(resp.RecentTracks.Track) > 0 {
track := resp.RecentTracks.Track[0]
data = fmt.Sprintf("%s - %s", track.Name, track.Artist.Name)
} else {
data = "lastfm strange error..."
}
sendLastfm(w, data)
}) })
} }
// Отправляет страницу // Отправляет страницу
func sendLastfm(w http.ResponseWriter, data string) { func sendLastFM(w http.ResponseWriter, data string) {
w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
fmt.Fprint(w, data) fmt.Fprint(w, data)

View File

@ -11,6 +11,7 @@ type App struct {
Posts models_pages.Posts // Посты Posts models_pages.Posts // Посты
Templates *template.Template // Шаблоны страниц Templates *template.Template // Шаблоны страниц
PagesCache *Cache // Кэш (отрендеренные странички) PagesCache *Cache // Кэш (отрендеренные странички)
LastfmLastTrack string // Последний трек, полученный с ластфм
Version int64 // Время запуска Version int64 // Время запуска
} }
@ -36,5 +37,7 @@ func InitApp() (*App, error) {
} }
// Инициализация кэша // Инициализация кэша
app.PagesCache = initCache() app.PagesCache = initCache()
// Строка по умолчанию для последнего прослушанного трека
app.LastfmLastTrack = "None"
return app, nil return app, nil
} }

View File

@ -3,6 +3,7 @@ package models
import ( import (
"encoding/json" "encoding/json"
"os" "os"
"time"
) )
const ( const (
@ -20,8 +21,9 @@ type Config struct {
ServerPort string ServerPort string
ServerDomain string ServerDomain string
Port string Port string
LastfmUsername string LastFMUsername string
LastfmToken string LastFMToken string
LastFMUpdateInterval time.Duration
} }
func loadConfig(configPath string) (*Config, error) { func loadConfig(configPath string) (*Config, error) {

View File

@ -7,9 +7,7 @@ import (
"net/http" "net/http"
) )
type LastFMResponse struct { type LastFMTrack struct {
RecentTracks struct {
Track []struct {
Name string `json:"name"` Name string `json:"name"`
Artist struct { Artist struct {
Name string `json:"#text"` Name string `json:"#text"`
@ -20,11 +18,15 @@ type LastFMResponse struct {
Date struct { Date struct {
Unix string `json:"#text"` Unix string `json:"#text"`
} `json:"date"` } `json:"date"`
} `json:"track"` }
type LastFMResponse struct {
RecentTracks struct {
Tracks []LastFMTrack `json:"track"`
} `json:"recenttracks"` } `json:"recenttracks"`
} }
func GetRecentTracks(username, apiKey string) (*LastFMResponse, error) { func LastFMGetRecentTracks(username, apiKey string) (*LastFMResponse, error) {
url := fmt.Sprintf("https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=%s&api_key=%s&format=json", username, apiKey) url := fmt.Sprintf("https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=%s&api_key=%s&format=json", username, apiKey)
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
@ -42,3 +44,18 @@ func GetRecentTracks(username, apiKey string) (*LastFMResponse, error) {
return &lastFMResponse, nil return &lastFMResponse, nil
} }
func LastFMGetLastTrack(username, apiKey string) (string, error) {
resp, err := LastFMGetRecentTracks(username, apiKey)
if err != nil {
return "", err
}
var data string
if len(resp.RecentTracks.Tracks) > 0 {
track := resp.RecentTracks.Tracks[0]
data = fmt.Sprintf("%s - %s", track.Name, track.Artist.Name)
} else {
return "", fmt.Errorf("len(resp.RecentTracks.Tracks) <= 0")
}
return data, nil
}

View File

@ -43,7 +43,7 @@
updateLastfm(); updateLastfm();
setInterval(updateLastfm, 20000); setInterval(updateLastfm, 30000);
</script> </script>
</header> </header>
{{ end }} {{ end }}

27
tools/ticker.go Normal file
View File

@ -0,0 +1,27 @@
package tools
import "time"
// Ticker запускает функцию fn с указанным интервалом в отдельной горутине
// Возвращает канал для остановки тикера
func Ticker(fn func(), interval time.Duration) chan struct{} {
if interval <= 0 {
interval = time.Second
}
ticker := time.NewTicker(interval)
stopChan := make(chan struct{})
fn()
go func() {
for {
select {
case <-ticker.C:
fn()
case <-stopChan:
ticker.Stop()
return
}
}
}()
return stopChan
}