Merge branch 'dev' into feature/blog
This commit is contained in:
commit
053faeb493
25 changed files with 789 additions and 182 deletions
|
@ -77,5 +77,9 @@ func handleConfigOverrides(config *model.Config) error {
|
|||
if env, has := os.LookupEnv("ARIMELODY_DISCORD_CLIENT_ID"); has { config.Discord.ClientID = env }
|
||||
if env, has := os.LookupEnv("ARIMELODY_DISCORD_SECRET"); has { config.Discord.Secret = env }
|
||||
|
||||
if env, has := os.LookupEnv("ARIMELODY_TWITCH_BROADCASTER"); has { config.Twitch.Broadcaster = env }
|
||||
if env, has := os.LookupEnv("ARIMELODY_TWITCH_CLIENT_ID"); has { config.Twitch.ClientID = env }
|
||||
if env, has := os.LookupEnv("ARIMELODY_TWITCH_SECRET"); has { config.Twitch.Secret = env }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
|
||||
"github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
@ -33,69 +29,6 @@ const (
|
|||
HIGH
|
||||
)
|
||||
|
||||
func noDepsGenerateQRCode() (string, error) {
|
||||
version := 1
|
||||
|
||||
size := 0
|
||||
size = 21 + version * 4
|
||||
if version > 10 {
|
||||
return "", errors.New(fmt.Sprintf("QR version %d not supported", version))
|
||||
}
|
||||
|
||||
img := image.NewGray(image.Rect(0, 0, size + margin * 2, size + margin * 2))
|
||||
|
||||
// fill white
|
||||
for y := range size + margin * 2 {
|
||||
for x := range size + margin * 2 {
|
||||
img.Set(x, y, color.White)
|
||||
}
|
||||
}
|
||||
|
||||
// draw alignment squares
|
||||
drawLargeAlignmentSquare(margin, margin, img)
|
||||
drawLargeAlignmentSquare(margin, margin + size - 7, img)
|
||||
drawLargeAlignmentSquare(margin + size - 7, margin, img)
|
||||
drawSmallAlignmentSquare(size - 5, size - 5, img)
|
||||
/*
|
||||
if version > 4 {
|
||||
space := version * 3 - 2
|
||||
end := size / space
|
||||
for y := range size / space + 1 {
|
||||
for x := range size / space + 1 {
|
||||
if x == 0 && y == 0 { continue }
|
||||
if x == 0 && y == end { continue }
|
||||
if x == end && y == 0 { continue }
|
||||
if x == end && y == end { continue }
|
||||
drawSmallAlignmentSquare(
|
||||
x * space + margin + 4,
|
||||
y * space + margin + 4,
|
||||
img,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// draw timing bits
|
||||
for i := margin + 6; i < size - 4; i++ {
|
||||
if (i % 2 == 0) {
|
||||
img.Set(i, margin + 6, color.Black)
|
||||
img.Set(margin + 6, i, color.Black)
|
||||
}
|
||||
}
|
||||
img.Set(margin + 8, size - 4, color.Black)
|
||||
|
||||
var imgBuf bytes.Buffer
|
||||
err := png.Encode(&imgBuf, img)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
base64Img := base64.StdEncoding.EncodeToString(imgBuf.Bytes())
|
||||
|
||||
return "data:image/png;base64," + base64Img, nil
|
||||
}
|
||||
|
||||
func drawLargeAlignmentSquare(x int, y int, img *image.Gray) {
|
||||
for yi := range 7 {
|
||||
for xi := range 7 {
|
||||
|
|
94
controller/twitch.go
Normal file
94
controller/twitch.go
Normal file
|
@ -0,0 +1,94 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"arimelody-web/model"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
const TWITCH_API_BASE = "https://api.twitch.tv/helix/"
|
||||
|
||||
func TwitchSetup(app *model.AppState) error {
|
||||
app.Twitch = &model.TwitchState{}
|
||||
err := RefreshTwitchToken(app)
|
||||
return err
|
||||
}
|
||||
|
||||
func RefreshTwitchToken(app *model.AppState) error {
|
||||
if app.Twitch != nil && app.Twitch.Token != nil && time.Now().UTC().After(app.Twitch.Token.ExpiresAt) {
|
||||
return nil
|
||||
}
|
||||
|
||||
requestUrl, _ := url.Parse("https://id.twitch.tv/oauth2/token")
|
||||
req, _ := http.NewRequest(http.MethodPost, requestUrl.String(), bytes.NewBuffer([]byte(url.Values{
|
||||
"client_id": []string{ app.Config.Twitch.ClientID },
|
||||
"client_secret": []string{ app.Config.Twitch.Secret },
|
||||
"grant_type": []string{ "client_credentials" },
|
||||
}.Encode())))
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
type TwitchOAuthToken struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
TokenType string `json:"token_type"`
|
||||
}
|
||||
oauthResponse := TwitchOAuthToken{}
|
||||
err = json.NewDecoder(res.Body).Decode(&oauthResponse)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
app.Twitch.Token = &model.TwitchOAuthToken{
|
||||
AccessToken: oauthResponse.AccessToken,
|
||||
ExpiresAt: time.Now().UTC().Add(time.Second * time.Duration(oauthResponse.ExpiresIn)).UTC(),
|
||||
TokenType: oauthResponse.TokenType,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var lastStreamState *model.TwitchStreamInfo
|
||||
var lastStreamStateAt time.Time
|
||||
|
||||
func GetTwitchStatus(app *model.AppState, broadcaster string) (*model.TwitchStreamInfo, error) {
|
||||
if lastStreamState != nil && time.Now().UTC().Before(lastStreamStateAt.Add(time.Minute)) {
|
||||
return lastStreamState, nil
|
||||
}
|
||||
|
||||
requestUrl, _ := url.Parse(TWITCH_API_BASE + "streams")
|
||||
requestUrl.RawQuery = url.Values{
|
||||
"user_login": []string{ broadcaster },
|
||||
}.Encode()
|
||||
req, _ := http.NewRequest(http.MethodGet, requestUrl.String(), nil)
|
||||
req.Header.Set("Client-Id", app.Config.Twitch.ClientID)
|
||||
req.Header.Set("Authorization", "Bearer " + app.Twitch.Token.AccessToken)
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type StreamsResponse struct {
|
||||
Data []model.TwitchStreamInfo `json:"data"`
|
||||
}
|
||||
streamInfo := StreamsResponse{}
|
||||
err = json.NewDecoder(res.Body).Decode(&streamInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(streamInfo.Data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
lastStreamState = &streamInfo.Data[0]
|
||||
lastStreamStateAt = time.Now().UTC()
|
||||
return lastStreamState, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue