теперь сервер раз в 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/tools"
"net/http"
"time"
)
func main() {
@ -25,6 +26,19 @@ func main() {
// Настройка маршрутов
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 {
log.Fatal(err)
@ -61,7 +75,7 @@ func setupRoutes(app *models.App) *http.ServeMux {
// Api
{
router.Handle("/api/lastfm", m(controllers.LastfmHandler(app)))
router.Handle("/api/lastfm", m(controllers.LastFMHandler(app)))
}
return router

View File

@ -2,35 +2,19 @@ package controllers
import (
"fmt"
"log"
"main/mvc/models"
"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) {
var err error
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)
sendLastFM(w, app.LastfmLastTrack)
})
}
// Отправляет страницу
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.WriteHeader(http.StatusOK)
fmt.Fprint(w, data)

View File

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

View File

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

View File

@ -7,9 +7,7 @@ import (
"net/http"
)
type LastFMResponse struct {
RecentTracks struct {
Track []struct {
type LastFMTrack struct {
Name string `json:"name"`
Artist struct {
Name string `json:"#text"`
@ -20,11 +18,15 @@ type LastFMResponse struct {
Date struct {
Unix string `json:"#text"`
} `json:"date"`
} `json:"track"`
}
type LastFMResponse struct {
RecentTracks struct {
Tracks []LastFMTrack `json:"track"`
} `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)
resp, err := http.Get(url)
if err != nil {
@ -42,3 +44,18 @@ func GetRecentTracks(username, apiKey string) (*LastFMResponse, error) {
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();
setInterval(updateLastfm, 20000);
setInterval(updateLastfm, 30000);
</script>
</header>
{{ 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
}