теперь сервер раз в 30 секунд обновляет последний прослушанный трек, добавил поле под него в app
parent
9aa39d8f65
commit
8c5c5d6150
16
main.go
16
main.go
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -7,11 +7,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
Cfg *Config // Сонфиг
|
Cfg *Config // Сонфиг
|
||||||
Posts models_pages.Posts // Посты
|
Posts models_pages.Posts // Посты
|
||||||
Templates *template.Template // Шаблоны страниц
|
Templates *template.Template // Шаблоны страниц
|
||||||
PagesCache *Cache // Кэш (отрендеренные странички)
|
PagesCache *Cache // Кэш (отрендеренные странички)
|
||||||
Version int64 // Время запуска
|
LastfmLastTrack string // Последний трек, полученный с ластфм
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package models
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -10,18 +11,19 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
PostsDir string
|
PostsDir string
|
||||||
AssetsDir string
|
AssetsDir string
|
||||||
TemplatesDir string
|
TemplatesDir string
|
||||||
TemplatesExt string
|
TemplatesExt string
|
||||||
LocalIP string
|
LocalIP string
|
||||||
LocalPort string
|
LocalPort string
|
||||||
ServerIP string
|
ServerIP string
|
||||||
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) {
|
||||||
|
|
|
@ -7,24 +7,26 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type LastFMTrack struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Artist struct {
|
||||||
|
Name string `json:"#text"`
|
||||||
|
} `json:"artist"`
|
||||||
|
Album struct {
|
||||||
|
Name string `json:"#text"`
|
||||||
|
} `json:"album"`
|
||||||
|
Date struct {
|
||||||
|
Unix string `json:"#text"`
|
||||||
|
} `json:"date"`
|
||||||
|
}
|
||||||
|
|
||||||
type LastFMResponse struct {
|
type LastFMResponse struct {
|
||||||
RecentTracks struct {
|
RecentTracks struct {
|
||||||
Track []struct {
|
Tracks []LastFMTrack `json:"track"`
|
||||||
Name string `json:"name"`
|
|
||||||
Artist struct {
|
|
||||||
Name string `json:"#text"`
|
|
||||||
} `json:"artist"`
|
|
||||||
Album struct {
|
|
||||||
Name string `json:"#text"`
|
|
||||||
} `json:"album"`
|
|
||||||
Date struct {
|
|
||||||
Unix string `json:"#text"`
|
|
||||||
} `json:"date"`
|
|
||||||
} `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
|
||||||
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
updateLastfm();
|
updateLastfm();
|
||||||
|
|
||||||
setInterval(updateLastfm, 20000);
|
setInterval(updateLastfm, 30000);
|
||||||
</script>
|
</script>
|
||||||
</header>
|
</header>
|
||||||
{{ end }}
|
{{ end }}
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue