update
1. add youtube command 2. add google webhook 3. add twitch oauth route 4. add api checkSession middleware
This commit is contained in:
parent
3318352135
commit
e8db6fdab5
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
config.yml
|
config.yml
|
||||||
.vscode
|
.vscode
|
||||||
|
.idea
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
type Account struct {
|
type Account struct {
|
||||||
ID string `db:"id" cc:"id"`
|
ID string `db:"id" cc:"id"`
|
||||||
Account string `db:"account" cc:"account"`
|
Account string `db:"account" cc:"account"`
|
||||||
Password string `db:"password" cc:"password"`
|
Password string `db:"password" cc:"-"`
|
||||||
Ctime time.Time `db:"ctime" cc:"ctime"`
|
Ctime time.Time `db:"ctime" cc:"ctime"`
|
||||||
Mtime time.Time `db:"mtime" cc:"ctime"`
|
Mtime time.Time `db:"mtime" cc:"ctime"`
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// TwitchGroup -
|
// TwitchGroup -
|
||||||
type TwitchGroup struct {
|
type TwitchGroup struct {
|
||||||
@ -32,6 +35,24 @@ func GetJoinChatChannel() (channels []*TwitchChannel, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTwitchChannelWithName -
|
||||||
|
func GetTwitchChannelWithName(name string) (ch *TwitchChannel, err error) {
|
||||||
|
if len(name) == 0 {
|
||||||
|
return nil, errors.New("name empty")
|
||||||
|
}
|
||||||
|
err = x.Get(&ch, `select * from "public"."twitch_channel" where "name" = $1`, name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTwitchChannelWithID -
|
||||||
|
func GetTwitchChannelWithID(id string) (ch *TwitchChannel, err error) {
|
||||||
|
if len(id) == 0 {
|
||||||
|
return nil, errors.New("id empty")
|
||||||
|
}
|
||||||
|
err = x.Get(&ch, `select * from "public"."twitch_channel" where "id" = $1`, id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// GetWithName -
|
// GetWithName -
|
||||||
func (p *TwitchChannel) GetWithName() (err error) {
|
func (p *TwitchChannel) GetWithName() (err error) {
|
||||||
stmt, err := x.PrepareNamed(`select * from "public"."twitch_channel" where "name" = :name`)
|
stmt, err := x.PrepareNamed(`select * from "public"."twitch_channel" where "name" = :name`)
|
||||||
@ -45,7 +66,7 @@ func (p *TwitchChannel) GetWithName() (err error) {
|
|||||||
|
|
||||||
// Add -
|
// Add -
|
||||||
func (p *TwitchChannel) Add() (err error) {
|
func (p *TwitchChannel) Add() (err error) {
|
||||||
stmt, err := x.PrepareNamed(`insert into "public"."twitch_channel" ("name", "laststream", "join", "opayid") values (:name, :laststream, :join, :opayid) returning *`)
|
stmt, err := x.PrepareNamed(`insert into "public"."twitch_channel" ("id", "name", "laststream", "join", "opayid") values (:id, :name, :laststream, :join, :opayid) returning *`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -64,6 +85,16 @@ func (p *TwitchChannel) UpdateStream(streamID string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateName -
|
||||||
|
func (p *TwitchChannel) UpdateName(name string) (err error) {
|
||||||
|
_, err = x.Exec(`update "public"."twitch_channel" set "name" = $1 where "id" = $2`, name, p.ID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.Name = name
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// GetGroups -
|
// GetGroups -
|
||||||
func (p *TwitchChannel) GetGroups() (err error) {
|
func (p *TwitchChannel) GetGroups() (err error) {
|
||||||
query := `select g.*, rt.tmpl as tmpl from "public"."twitch_channel" tw
|
query := `select g.*, rt.tmpl as tmpl from "public"."twitch_channel" tw
|
||||||
|
@ -25,6 +25,16 @@ func GetYoutubeChannelWithID(id string) (yt *YoutubeChannel, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add -
|
||||||
|
func (p *YoutubeChannel) Add() (err error) {
|
||||||
|
stmt, err := x.PrepareNamed(`insert into "public"."youtube_channel" ("id", "name") values (:id, :name) returning *`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = stmt.Get(p, p)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateLastVideo -
|
// UpdateLastVideo -
|
||||||
func (p *YoutubeChannel) UpdateLastVideo(vid string) (err error) {
|
func (p *YoutubeChannel) UpdateLastVideo(vid string) (err error) {
|
||||||
p.LastVideo = vid
|
p.LastVideo = vid
|
||||||
|
@ -37,6 +37,12 @@ var objs = map[string]*ResObject{
|
|||||||
"message": "input data format error",
|
"message": "input data format error",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"LoginFirst": &ResObject{
|
||||||
|
Status: 401,
|
||||||
|
Obj: map[string]string{
|
||||||
|
"message": "login first",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRes -
|
// GetRes -
|
||||||
|
157
module/apis/google/google.go
Normal file
157
module/apis/google/google.go
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.trj.tw/golang/mtfosbot/module/apis"
|
||||||
|
|
||||||
|
"git.trj.tw/golang/mtfosbot/module/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var baseURL = "https://www.googleapis.com"
|
||||||
|
|
||||||
|
func getURL(p string, querystring ...interface{}) (string, bool) {
|
||||||
|
u, err := url.Parse(baseURL)
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
ref, err := u.Parse(p)
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
if len(querystring) > 0 {
|
||||||
|
switch querystring[0].(type) {
|
||||||
|
case string:
|
||||||
|
ref, err = ref.Parse(fmt.Sprintf("?%s", (querystring[0].(string))))
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str := ref.String()
|
||||||
|
return str, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHeaders(token ...interface{}) map[string]string {
|
||||||
|
m := make(map[string]string)
|
||||||
|
m["Content-Type"] = "application/json"
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
type channelItem struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Sinppet channelSinppet `json:"sinppet"`
|
||||||
|
}
|
||||||
|
type channelSinppet struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
CustomURL string `json:"customUrl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryYoutubeName -
|
||||||
|
func QueryYoutubeName(id string) (n string, err error) {
|
||||||
|
conf := config.GetConf()
|
||||||
|
if len(id) == 0 {
|
||||||
|
return "", errors.New("id is empty")
|
||||||
|
}
|
||||||
|
qs := url.Values{}
|
||||||
|
qs.Add("id", id)
|
||||||
|
qs.Add("key", conf.Google.APIKey)
|
||||||
|
qs.Add("part", "snippet")
|
||||||
|
|
||||||
|
apiURL, ok := getURL("/youtube/v3/channels", qs.Encode())
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("url parser fail")
|
||||||
|
}
|
||||||
|
reqObj := apis.RequestObj{
|
||||||
|
Method: "GET",
|
||||||
|
URL: apiURL,
|
||||||
|
Headers: getHeaders(),
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := apis.GetRequest(reqObj)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 || !strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") {
|
||||||
|
return "", errors.New("api response fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
apiRes := struct {
|
||||||
|
Items []channelItem `json:"items"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(bodyBytes, &apiRes)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(apiRes.Items) == 0 {
|
||||||
|
return "", errors.New("channel data not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range apiRes.Items {
|
||||||
|
if v.ID == id {
|
||||||
|
return v.Sinppet.Title, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("channel data not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubscribeYoutube -
|
||||||
|
func SubscribeYoutube(id string) {
|
||||||
|
if len(id) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
conf := config.GetConf()
|
||||||
|
apiURL := "https://pubsubhubbub.appspot.com/subscribe"
|
||||||
|
cbURL, err := url.Parse(conf.URL)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cbURL, err = cbURL.Parse(fmt.Sprintf("/google/youtube/webhook?id=%s", id))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
qs := url.Values{}
|
||||||
|
qs.Add("hub.mode", "subscribe")
|
||||||
|
qs.Add("hub.verify", "async")
|
||||||
|
qs.Add("hub.topic", fmt.Sprintf("https://www.youtube.com/xml/feeds/videos.xml?channel_id=%s", id))
|
||||||
|
qs.Add("hub.callback", cbURL.String())
|
||||||
|
qs.Add("hub.lease_seconds", "86400")
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", apiURL, strings.NewReader(qs.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
return
|
||||||
|
}
|
@ -2,6 +2,7 @@ package twitch
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -234,3 +235,66 @@ func GetUserStreamStatus(ids []string) (info []*StreamInfo) {
|
|||||||
|
|
||||||
return apiData.Data
|
return apiData.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TwitchTokenData -
|
||||||
|
type TwitchTokenData struct {
|
||||||
|
AccessToken string `json:"access_token" cc:"access_token"`
|
||||||
|
RefreshToken string `json:"refresh_token" cc:"refresh_token"`
|
||||||
|
ExpiresIn int64 `json:"expires_in" cc:"expires_in"`
|
||||||
|
Scope string `json:"scope" cc:"scope"`
|
||||||
|
TokenType string `json:"token_type" cc:"token_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTokenData -
|
||||||
|
func GetTokenData(code string) (token *TwitchTokenData, err error) {
|
||||||
|
if len(code) == 0 {
|
||||||
|
return nil, errors.New("code is empty")
|
||||||
|
}
|
||||||
|
conf := config.GetConf()
|
||||||
|
twitchURL := "https://id.twitch.tv/oauth2/token"
|
||||||
|
redirectTo := strings.TrimRight(conf.URL, "/") + "/twitch/oauth"
|
||||||
|
|
||||||
|
qs := url.Values{}
|
||||||
|
qs.Add("client_id", conf.Twitch.ClientID)
|
||||||
|
qs.Add("client_secret", conf.Twitch.ClientSecret)
|
||||||
|
qs.Add("code", code)
|
||||||
|
qs.Add("grant_type", "authorization_code")
|
||||||
|
qs.Add("redirect_uri", redirectTo)
|
||||||
|
|
||||||
|
u, err := url.Parse(twitchURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
u, err = u.Parse(qs.Encode())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
reqObj := apis.RequestObj{
|
||||||
|
URL: u.String(),
|
||||||
|
Method: "POST",
|
||||||
|
}
|
||||||
|
req, err := apis.GetRequest(reqObj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 || strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") {
|
||||||
|
return nil, errors.New("api response error")
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(bodyBytes, &token)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
@ -35,6 +35,12 @@ func (c *Context) CustomRes(status int, msg interface{}) {
|
|||||||
c.AbortWithStatusJSON(status, msg)
|
c.AbortWithStatusJSON(status, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoginFirst -
|
||||||
|
func (c *Context) LoginFirst(msg interface{}) {
|
||||||
|
obj := apimsg.GetRes("LoginFirst", msg)
|
||||||
|
c.AbortWithStatusJSON(obj.Status, obj.Obj)
|
||||||
|
}
|
||||||
|
|
||||||
// NotFound -
|
// NotFound -
|
||||||
func (c *Context) NotFound(msg interface{}) {
|
func (c *Context) NotFound(msg interface{}) {
|
||||||
obj := apimsg.GetRes("NotFound", msg)
|
obj := apimsg.GetRes("NotFound", msg)
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"git.trj.tw/golang/mtfosbot/module/apis/twitch"
|
"git.trj.tw/golang/mtfosbot/module/apis/twitch"
|
||||||
|
|
||||||
"git.trj.tw/golang/mtfosbot/model"
|
"git.trj.tw/golang/mtfosbot/model"
|
||||||
|
googleapi "git.trj.tw/golang/mtfosbot/module/apis/google"
|
||||||
lineobj "git.trj.tw/golang/mtfosbot/module/line-message/line-object"
|
lineobj "git.trj.tw/golang/mtfosbot/module/line-message/line-object"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -173,13 +174,19 @@ func addTwitchChannel(sub, txt string, s *lineobj.SourceObject) (res string) {
|
|||||||
return "get twitch user id fail"
|
return "get twitch user id fail"
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := &model.TwitchChannel{
|
ch, err := model.GetTwitchChannelWithName(args[0])
|
||||||
ID: info.ID,
|
|
||||||
Name: info.DisplayName,
|
|
||||||
}
|
|
||||||
err = ch.Add()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "add twitch channel fail"
|
return "check channel fail"
|
||||||
|
}
|
||||||
|
if ch == nil {
|
||||||
|
ch = &model.TwitchChannel{
|
||||||
|
ID: info.ID,
|
||||||
|
Name: info.DisplayName,
|
||||||
|
}
|
||||||
|
err = ch.Add()
|
||||||
|
if err != nil {
|
||||||
|
return "add twitch channel fail"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rt := &model.LineTwitchRT{
|
rt := &model.LineTwitchRT{
|
||||||
@ -239,3 +246,50 @@ func delTwitchChannel(sub, txt string, s *lineobj.SourceObject) (res string) {
|
|||||||
|
|
||||||
return "Success"
|
return "Success"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addYoutubeChannel(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||||
|
// args = youtubeID tmpl
|
||||||
|
ok, err := checkGroupOwner(s)
|
||||||
|
if err != nil {
|
||||||
|
return "check group fail"
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return "not owner"
|
||||||
|
}
|
||||||
|
|
||||||
|
args := strings.Split(strings.Trim(txt, " "), " ")
|
||||||
|
if len(args) < 2 {
|
||||||
|
return "command arg not match"
|
||||||
|
}
|
||||||
|
ytName, err := googleapi.QueryYoutubeName(args[0])
|
||||||
|
if err != nil || len(ytName) == 0 {
|
||||||
|
return "get youtube channel name fail"
|
||||||
|
}
|
||||||
|
|
||||||
|
ytData, err := model.GetYoutubeChannelWithID(args[0])
|
||||||
|
if err != nil {
|
||||||
|
return "check youtube fail"
|
||||||
|
}
|
||||||
|
if ytData == nil {
|
||||||
|
ytData = &model.YoutubeChannel{
|
||||||
|
ID: args[0],
|
||||||
|
Name: ytName,
|
||||||
|
}
|
||||||
|
err = ytData.Add()
|
||||||
|
if err != nil {
|
||||||
|
return "add youtube channel fail"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rt := &model.LineYoutubeRT{
|
||||||
|
Line: s.GroupID,
|
||||||
|
Youtube: args[0],
|
||||||
|
Tmpl: strings.Join(args[1:], " "),
|
||||||
|
}
|
||||||
|
err = rt.AddRT()
|
||||||
|
if err != nil {
|
||||||
|
return "add youtube channel rt fail"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Success"
|
||||||
|
}
|
||||||
|
@ -2,12 +2,47 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.trj.tw/golang/mtfosbot/model"
|
"git.trj.tw/golang/mtfosbot/model"
|
||||||
|
"git.trj.tw/golang/mtfosbot/module/apis/twitch"
|
||||||
"git.trj.tw/golang/mtfosbot/module/context"
|
"git.trj.tw/golang/mtfosbot/module/context"
|
||||||
"git.trj.tw/golang/mtfosbot/module/utils"
|
|
||||||
"github.com/gin-gonic/contrib/sessions"
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CheckSession -
|
||||||
|
func CheckSession(c *context.Context) {
|
||||||
|
session := sessions.Default(c.Context)
|
||||||
|
userData := session.Get("user")
|
||||||
|
loginType := session.Get("loginType")
|
||||||
|
if userData == nil || loginType == nil {
|
||||||
|
c.LoginFirst(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var name string
|
||||||
|
var ltype string
|
||||||
|
var ok bool
|
||||||
|
switch userData.(type) {
|
||||||
|
case model.Account:
|
||||||
|
name = userData.(model.Account).Account
|
||||||
|
case twitch.UserInfo:
|
||||||
|
name = userData.(twitch.UserInfo).DisplayName
|
||||||
|
default:
|
||||||
|
c.LoginFirst(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ltype, ok = loginType.(string); !ok {
|
||||||
|
c.LoginFirst(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loginUser := map[string]string{
|
||||||
|
"name": name,
|
||||||
|
"type": ltype,
|
||||||
|
}
|
||||||
|
session.Set("loginUser", loginUser)
|
||||||
|
session.Save()
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
// UserLogin - system user login
|
// UserLogin - system user login
|
||||||
func UserLogin(c *context.Context) {
|
func UserLogin(c *context.Context) {
|
||||||
bodyArg := struct {
|
bodyArg := struct {
|
||||||
@ -32,11 +67,10 @@ func UserLogin(c *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accInt := utils.ToMap(acc)
|
|
||||||
delete(accInt, "password")
|
|
||||||
session := sessions.Default(c.Context)
|
session := sessions.Default(c.Context)
|
||||||
|
|
||||||
session.Set("user", accInt)
|
acc.Password = ""
|
||||||
|
session.Set("user", acc)
|
||||||
session.Set("loginType", "system")
|
session.Set("loginType", "system")
|
||||||
session.Save()
|
session.Save()
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"git.trj.tw/golang/mtfosbot/router/api"
|
"git.trj.tw/golang/mtfosbot/router/api"
|
||||||
"git.trj.tw/golang/mtfosbot/router/google"
|
"git.trj.tw/golang/mtfosbot/router/google"
|
||||||
"git.trj.tw/golang/mtfosbot/router/line"
|
"git.trj.tw/golang/mtfosbot/router/line"
|
||||||
|
"git.trj.tw/golang/mtfosbot/router/twitch"
|
||||||
"github.com/gin-contrib/cors"
|
"github.com/gin-contrib/cors"
|
||||||
"github.com/gin-gonic/contrib/sessions"
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -44,6 +45,7 @@ func SetRoutes(r *gin.Engine) {
|
|||||||
apiGroup := r.Group("/api")
|
apiGroup := r.Group("/api")
|
||||||
{
|
{
|
||||||
apiGroup.POST("/login", context.PatchCtx(api.UserLogin))
|
apiGroup.POST("/login", context.PatchCtx(api.UserLogin))
|
||||||
|
apiGroup.POST("/logout", context.PatchCtx(api.UserLogout))
|
||||||
}
|
}
|
||||||
|
|
||||||
lineApis := r.Group("/line")
|
lineApis := r.Group("/line")
|
||||||
@ -56,4 +58,10 @@ func SetRoutes(r *gin.Engine) {
|
|||||||
googleApis.GET("/youtube/webhook", context.PatchCtx(google.VerifyWebhook))
|
googleApis.GET("/youtube/webhook", context.PatchCtx(google.VerifyWebhook))
|
||||||
googleApis.POST("/youtube/webhook", context.PatchCtx(google.GetNotifyWebhook))
|
googleApis.POST("/youtube/webhook", context.PatchCtx(google.GetNotifyWebhook))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
twitchApis := r.Group("/twitch")
|
||||||
|
{
|
||||||
|
twitchApis.GET("/login", context.PatchCtx(twitch.OAuthLogin))
|
||||||
|
twitchApis.GET("/oauth", context.PatchCtx(twitch.OAuthProc))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
103
router/twitch/twitch.go
Normal file
103
router/twitch/twitch.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package twitch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.trj.tw/golang/mtfosbot/model"
|
||||||
|
twitchapi "git.trj.tw/golang/mtfosbot/module/apis/twitch"
|
||||||
|
"git.trj.tw/golang/mtfosbot/module/config"
|
||||||
|
"git.trj.tw/golang/mtfosbot/module/context"
|
||||||
|
"github.com/gin-gonic/contrib/sessions"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OAuthLogin -
|
||||||
|
func OAuthLogin(c *context.Context) {
|
||||||
|
session := sessions.Default(c.Context)
|
||||||
|
conf := config.GetConf()
|
||||||
|
redirectTo := strings.TrimRight(conf.URL, "/")
|
||||||
|
redirectTo += "/twitch/oauth"
|
||||||
|
qs := url.Values{}
|
||||||
|
qs.Add("client_id", conf.Twitch.ClientID)
|
||||||
|
qs.Add("redirect_uri", redirectTo)
|
||||||
|
qs.Add("response_type", "code")
|
||||||
|
qs.Add("scope", "user:read:email")
|
||||||
|
|
||||||
|
toURL, ok := c.GetQuery("tourl")
|
||||||
|
if ok && len(toURL) > 0 {
|
||||||
|
session.Set("backUrl", toURL)
|
||||||
|
session.Save()
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse(redirectTo)
|
||||||
|
if err != nil {
|
||||||
|
c.ServerError(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
finalURL, err := u.Parse(qs.Encode())
|
||||||
|
if err != nil {
|
||||||
|
c.ServerError(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Redirect(301, finalURL.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// OAuthProc -
|
||||||
|
func OAuthProc(c *context.Context) {
|
||||||
|
code, ok := c.GetQuery("code")
|
||||||
|
if !ok || len(code) == 0 {
|
||||||
|
c.DataFormat(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenData, err := twitchapi.GetTokenData(code)
|
||||||
|
if err != nil {
|
||||||
|
c.DataFormat(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
session := sessions.Default(c.Context)
|
||||||
|
|
||||||
|
userData := twitchapi.GetUserDataByToken(tokenData.AccessToken)
|
||||||
|
if userData == nil {
|
||||||
|
c.ServerError(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
session.Set("token", tokenData)
|
||||||
|
session.Set("user", userData)
|
||||||
|
session.Set("loginType", "twitch")
|
||||||
|
|
||||||
|
chData, err := model.GetTwitchChannelWithID(userData.ID)
|
||||||
|
if err != nil {
|
||||||
|
c.ServerError(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if chData == nil {
|
||||||
|
chData = &model.TwitchChannel{
|
||||||
|
ID: userData.ID,
|
||||||
|
Name: userData.DisplayName,
|
||||||
|
}
|
||||||
|
err = chData.Add()
|
||||||
|
if err != nil {
|
||||||
|
c.ServerError(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if userData.DisplayName != chData.Name {
|
||||||
|
chData.UpdateName(userData.DisplayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := config.GetConf()
|
||||||
|
goURL := strings.TrimRight(conf.URL, "/") + "/web"
|
||||||
|
tourl := session.Get("backUrl")
|
||||||
|
if tourl != nil {
|
||||||
|
if str, ok := tourl.(string); ok {
|
||||||
|
goURL = str
|
||||||
|
session.Delete("backUrl")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session.Save()
|
||||||
|
c.Redirect(301, goURL)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user