2020-05-09 01:51:02 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-05-12 00:56:44 +02:00
|
|
|
"encoding/json"
|
2020-05-09 01:51:02 +02:00
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/Luzifer/rconfig"
|
|
|
|
gorilla "github.com/gorilla/mux"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"golang.org/x/oauth2"
|
|
|
|
)
|
|
|
|
|
|
|
|
var cfg = struct {
|
|
|
|
SettingsFile string `default:"settings.yml" flag:"settings-file" description:"Path to settings file"`
|
|
|
|
}{}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
rconfig.Parse(&cfg)
|
|
|
|
settingsUpdater()
|
|
|
|
|
|
|
|
loadUser()
|
2021-10-27 20:52:40 +02:00
|
|
|
go checkUserToken()
|
2020-05-09 01:51:02 +02:00
|
|
|
|
|
|
|
log.Infof("User: %+v", user)
|
|
|
|
|
|
|
|
mux := gorilla.NewRouter()
|
2020-05-12 00:56:44 +02:00
|
|
|
mux.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
|
2020-05-09 01:51:02 +02:00
|
|
|
mux.HandleFunc("/login", handleTwitchLogin)
|
|
|
|
mux.HandleFunc("/callback", handleTwitchCallback)
|
2020-05-12 00:56:44 +02:00
|
|
|
mux.HandleFunc("/data", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if user == nil {
|
|
|
|
http.NotFound(w, r)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
w.Header().Set("Access-Control-Allow-Headers", "*")
|
|
|
|
if err := json.NewEncoder(w).Encode(user.getWebUser()); err != nil {
|
|
|
|
log.WithError(err).Error("Unable to encode user data")
|
|
|
|
http.Error(w, "Unable to encode user data", http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
})
|
2020-05-09 01:51:02 +02:00
|
|
|
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.Write([]byte("Hi!"))
|
|
|
|
})
|
|
|
|
|
|
|
|
go func() {
|
2020-05-09 22:57:57 +02:00
|
|
|
if user != nil {
|
|
|
|
handleSaves()
|
2022-05-07 13:27:37 +02:00
|
|
|
}
|
|
|
|
interval := 20 * time.Second
|
|
|
|
if settings.UpdateInterval > 10*time.Second {
|
|
|
|
interval = settings.UpdateInterval
|
|
|
|
}
|
|
|
|
log.Infof("Update interval: %s", interval)
|
|
|
|
c := time.Tick(interval)
|
|
|
|
for range c {
|
|
|
|
if user == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
handleSaves()
|
2020-05-09 01:51:02 +02:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
log.Info("Starting webserver...")
|
2020-05-09 03:38:08 +02:00
|
|
|
log.Fatal(http.ListenAndServe(":"+settings.WebserverPort, mux))
|
2020-05-09 01:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func handleSaves() {
|
|
|
|
if user == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
getUser(user)
|
2022-05-07 13:27:37 +02:00
|
|
|
if user.TwitchUser != nil {
|
|
|
|
user.TwitchUser.SaveFiles()
|
|
|
|
}
|
|
|
|
|
|
|
|
getChannel(user)
|
|
|
|
if user.TwitchChannel != nil {
|
|
|
|
user.TwitchChannel.SaveFiles()
|
|
|
|
}
|
2020-05-09 01:51:02 +02:00
|
|
|
|
2020-08-19 23:26:26 +02:00
|
|
|
maxFollower := -1
|
|
|
|
if settings.MaxFollowers > 0 {
|
|
|
|
maxFollower = settings.MaxFollowers
|
|
|
|
}
|
2022-05-07 13:27:37 +02:00
|
|
|
|
2020-08-19 23:26:26 +02:00
|
|
|
log.Infof("Fetch max follower: %d", maxFollower)
|
|
|
|
getFollows(user, maxFollower)
|
2020-05-09 01:51:02 +02:00
|
|
|
if user.TwitchFollowers != nil {
|
|
|
|
user.TwitchFollowers.SaveFiles()
|
|
|
|
}
|
2022-05-07 13:27:37 +02:00
|
|
|
maxSubs := -1
|
|
|
|
if settings.MaxSubs > 0 {
|
|
|
|
maxSubs = settings.MaxSubs
|
|
|
|
}
|
|
|
|
log.Infof("Fetch max subs: %d", maxSubs)
|
|
|
|
getSubs(user, maxSubs)
|
|
|
|
if user.TwitchSubscriptions != nil {
|
|
|
|
user.TwitchSubscriptions.SaveFiles()
|
|
|
|
}
|
|
|
|
|
|
|
|
getStreams(user)
|
|
|
|
if user.TwitchStream != nil {
|
|
|
|
user.TwitchStream.SaveFiles()
|
|
|
|
}
|
2020-05-09 01:51:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func handleTwitchLogin(w http.ResponseWriter, r *http.Request) {
|
|
|
|
url := twitchOauthConfig.AuthCodeURL(settings.VerificationToken, oauth2.AccessTypeOffline)
|
|
|
|
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
|
|
|
|
}
|
|
|
|
|
|
|
|
func handleTwitchCallback(w http.ResponseWriter, r *http.Request) {
|
|
|
|
twitchAuthToToken(r.FormValue("state"), r.FormValue("code"), w, r)
|
|
|
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
|
|
|
}
|
|
|
|
|
|
|
|
func twitchAuthToToken(state string, code string, w http.ResponseWriter, r *http.Request) {
|
|
|
|
if state != settings.VerificationToken {
|
|
|
|
log.Fatal("invalid oauth state")
|
|
|
|
}
|
|
|
|
|
|
|
|
timeoutCtx, cancel := context.WithTimeout(oauth2.NoContext, 5*time.Second)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
token, err := twitchOauthConfig.Exchange(timeoutCtx, code, oauth2.AccessTypeOffline)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("code exchange failed")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
u, err := createUser(token)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Unable to get user")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
u.Token = token
|
|
|
|
user = u
|
|
|
|
log.Infof("User: %+v, User: %+v", user, user.TwitchUser)
|
|
|
|
saveUser()
|
|
|
|
}
|