add youtube webhook
This commit is contained in:
parent
e954afe80b
commit
16190c49c4
@ -34,11 +34,11 @@ func GetFacebookPage(id string) (page *FacebookPage, err error) {
|
||||
|
||||
// AddPage -
|
||||
func (p *FacebookPage) AddPage() (err error) {
|
||||
rows, err := x.NamedQuery(`insert into "public"."facebook_page" ("id", "lastpost") values (:id, :lastpost) returning *`, p)
|
||||
stmt, err := x.PrepareNamed(`insert into "public"."facebook_page" ("id", "lastpost") values (:id, :lastpost) returning *`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = rows.StructScan(&p)
|
||||
err = stmt.Get(p, p)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -25,14 +25,42 @@ func (p *LineFacebookRT) AddRT() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// DelRT -
|
||||
func (p *LineFacebookRT) DelRT() (err error) {
|
||||
_, err = x.NamedExec(`delete from "public"."line_fb_rt" where "line" = :line and "facebook" = :facebook`, p)
|
||||
return
|
||||
}
|
||||
|
||||
// GetRT -
|
||||
func (p *LineFacebookRT) GetRT() (err error) {
|
||||
stmt, err := x.PrepareNamed(`select * from "public"."line_fb_rt" where "line" = :line and "facebook" = :facebook`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stmt.Get(p, p)
|
||||
return
|
||||
}
|
||||
|
||||
// AddRT - add twitch line rt
|
||||
func (p *LineTwitchRT) AddRT() (err error) {
|
||||
_, err = x.NamedExec(`insert into "public"."line_twitch_rt" ("line", "twitch", "type", "tmpl") values (:line, :twitch, :type, :tmpl)`, p)
|
||||
return
|
||||
}
|
||||
|
||||
// DelRT -
|
||||
func (p *LineTwitchRT) DelRT() (err error) {
|
||||
_, err = x.NamedExec(`delete from "public"."line_twitch_rt" where "line" = :line and "twitch" = :twitch and "type" = :type`, p)
|
||||
return
|
||||
}
|
||||
|
||||
// AddRT - add youtube line rt
|
||||
func (p *LineYoutubeRT) AddRT() (err error) {
|
||||
_, err = x.NamedExec(`insert into "public"."line_youtube_rt" ("line", "youtube", "tmpl") values (:line, :youtube, :tmpl)`, p)
|
||||
return
|
||||
}
|
||||
|
||||
// DelRT -
|
||||
func (p *LineYoutubeRT) DelRT() (err error) {
|
||||
_, err = x.NamedExec(`delete from "public"."line_youtube_rt" where "line" = :line and "youtube" = :youtube`, p)
|
||||
return
|
||||
}
|
||||
|
@ -32,13 +32,24 @@ func GetJoinChatChannel() (channels []*TwitchChannel, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Add -
|
||||
func (p *TwitchChannel) Add() (err error) {
|
||||
rows, err := x.NamedQuery(`insert into "public"."twitch_channel" ("name", "laststream", "join", "opayid") values (:name, :laststream, :join, :opayid) returning *`, p)
|
||||
// GetWithName -
|
||||
func (p *TwitchChannel) GetWithName() (err error) {
|
||||
stmt, err := x.PrepareNamed(`select * from "public"."twitch_channel" where "name" = :name`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = rows.StructScan(p)
|
||||
|
||||
err = stmt.Get(p, p)
|
||||
return
|
||||
}
|
||||
|
||||
// Add -
|
||||
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 *`)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = stmt.Get(p, p)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,55 @@ package model
|
||||
|
||||
import "time"
|
||||
|
||||
// YoutubeGroup -
|
||||
type YoutubeGroup struct {
|
||||
*LineGroup
|
||||
Tmpl string `db:"tmpl"`
|
||||
}
|
||||
|
||||
// YoutubeChannel -
|
||||
type YoutubeChannel struct {
|
||||
ID string `db:"id" cc:"id"`
|
||||
Name string `db:"name" cc:"name"`
|
||||
LastVideo string `db:"lastvideo" cc:"lastvideo"`
|
||||
Expire int32 `db:"expire" cc:"expire"`
|
||||
Expire int64 `db:"expire" cc:"expire"`
|
||||
Ctime time.Time `db:"ctime" cc:"ctime"`
|
||||
Mtime time.Time `db:"mtime" cc:"mtime"`
|
||||
Groups []*YoutubeGroup `db:"-"`
|
||||
}
|
||||
|
||||
// GetYoutubeChannelWithID -
|
||||
func GetYoutubeChannelWithID(id string) (yt *YoutubeChannel, err error) {
|
||||
err = x.Get(&yt, `select * from "public"."youtube_channel" where "id" = $1`, id)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateLastVideo -
|
||||
func (p *YoutubeChannel) UpdateLastVideo(vid string) (err error) {
|
||||
p.LastVideo = vid
|
||||
_, err = x.NamedExec(`update "public"."youtube_channel" set "lastvideo" = :lastvideo where "id" = :id`, p)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateExpire -
|
||||
func (p *YoutubeChannel) UpdateExpire(t int64) (err error) {
|
||||
p.Expire = t
|
||||
_, err = x.NamedExec(`update "public"."youtube_channel" set "expire" = :expire where "id" = :id`, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetGroups -
|
||||
func (p *YoutubeChannel) GetGroups() (err error) {
|
||||
query := `select g.*, rt.tmpl as tmpl from "public"."youtube_channel" yt
|
||||
left join "public"."line_youtube_rt" rt
|
||||
on rt.youtube = yt.id
|
||||
left join "public"."line_group" g
|
||||
on g.id = rt.line
|
||||
where
|
||||
yt.id = $1`
|
||||
err = x.Select(&p.Groups, query, p.ID)
|
||||
return
|
||||
}
|
||||
|
@ -18,6 +18,10 @@ func selectAct(cmd, sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
return addFacebookPage(sub, txt, s)
|
||||
case "addtwitch":
|
||||
return addTwitchChannel(sub, txt, s)
|
||||
case "delpage":
|
||||
return delFacebookPage(sub, txt, s)
|
||||
case "deltwitch":
|
||||
return delTwitchChannel(sub, txt, s)
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -48,18 +52,29 @@ func addLineGroup(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
return "Success"
|
||||
}
|
||||
|
||||
func addFacebookPage(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
// args = pageid tmpl
|
||||
func checkGroupOwner(s *lineobj.SourceObject) (ok bool, err error) {
|
||||
exists, err := model.CheckGroup(s.GroupID)
|
||||
if err != nil {
|
||||
return "run check group error"
|
||||
return false, err
|
||||
}
|
||||
if !exists {
|
||||
return "group not exists"
|
||||
return false, nil
|
||||
}
|
||||
ok, err := model.CheckGroupOwner(s.UserID, s.GroupID)
|
||||
ok, err = model.CheckGroupOwner(s.UserID, s.GroupID)
|
||||
if err != nil {
|
||||
return "run check group owner fail"
|
||||
return false, err
|
||||
}
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func addFacebookPage(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
// args = pageid tmpl
|
||||
ok, err := checkGroupOwner(s)
|
||||
if err != nil {
|
||||
return "check group fail"
|
||||
}
|
||||
if !ok {
|
||||
return "not owner"
|
||||
@ -98,18 +113,47 @@ func addFacebookPage(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
return "Success"
|
||||
}
|
||||
|
||||
func delFacebookPage(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
// args = pageid
|
||||
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) < 1 {
|
||||
return "commage arg not match"
|
||||
}
|
||||
|
||||
rt := &model.LineFacebookRT{
|
||||
Line: s.GroupID,
|
||||
Facebook: args[0],
|
||||
}
|
||||
err = rt.DelRT()
|
||||
if err != nil {
|
||||
return "remove facebook page fail"
|
||||
}
|
||||
|
||||
return "Success"
|
||||
}
|
||||
|
||||
func checkTwitchType(t string) bool {
|
||||
switch t {
|
||||
case "live":
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func addTwitchChannel(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
// args = twitchLogin type tmpl
|
||||
exists, err := model.CheckGroup(s.GroupID)
|
||||
ok, err := checkGroupOwner(s)
|
||||
if err != nil {
|
||||
return "run check group error"
|
||||
}
|
||||
if !exists {
|
||||
return "group not exists"
|
||||
}
|
||||
ok, err := model.CheckGroupOwner(s.UserID, s.GroupID)
|
||||
if err != nil {
|
||||
return "run check group owner fail"
|
||||
return "check group fail"
|
||||
}
|
||||
if !ok {
|
||||
return "not owner"
|
||||
@ -120,6 +164,10 @@ func addTwitchChannel(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
return "command args not match"
|
||||
}
|
||||
|
||||
if !checkTwitchType(args[1]) {
|
||||
return "type not allow"
|
||||
}
|
||||
|
||||
info := twitch.GetUserDataByName(args[0])
|
||||
if info == nil {
|
||||
return "get twitch user id fail"
|
||||
@ -137,6 +185,7 @@ func addTwitchChannel(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
rt := &model.LineTwitchRT{
|
||||
Line: s.GroupID,
|
||||
Twitch: info.ID,
|
||||
Type: args[1],
|
||||
Tmpl: strings.Join(args[2:], " "),
|
||||
}
|
||||
err = rt.AddRT()
|
||||
@ -146,3 +195,47 @@ func addTwitchChannel(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
|
||||
return "Success"
|
||||
}
|
||||
|
||||
func delTwitchChannel(sub, txt string, s *lineobj.SourceObject) (res string) {
|
||||
// args = twitchLogin type
|
||||
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"
|
||||
}
|
||||
|
||||
if !checkTwitchType(args[1]) {
|
||||
return "type not allow"
|
||||
}
|
||||
|
||||
ch := &model.TwitchChannel{
|
||||
Name: args[0],
|
||||
}
|
||||
err = ch.GetWithName()
|
||||
if err != nil {
|
||||
return "get channel data fail"
|
||||
}
|
||||
if ch == nil {
|
||||
return "Success"
|
||||
}
|
||||
|
||||
rt := &model.LineTwitchRT{
|
||||
Line: s.GroupID,
|
||||
Twitch: ch.ID,
|
||||
Type: args[1],
|
||||
}
|
||||
|
||||
err = rt.DelRT()
|
||||
if err != nil {
|
||||
return "delete rt fail"
|
||||
}
|
||||
|
||||
return "Success"
|
||||
}
|
||||
|
135
router/google/youtube.go
Normal file
135
router/google/youtube.go
Normal file
@ -0,0 +1,135 @@
|
||||
package google
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.trj.tw/golang/mtfosbot/model"
|
||||
lineapi "git.trj.tw/golang/mtfosbot/module/apis/line"
|
||||
"git.trj.tw/golang/mtfosbot/module/context"
|
||||
)
|
||||
|
||||
type feed struct {
|
||||
XMLName xml.Name `xml:"feed"`
|
||||
Entry []entry `xml:"entry"`
|
||||
}
|
||||
type entry struct {
|
||||
XMLName xml.Name `xml:"entry"`
|
||||
Title string `xml:"title"`
|
||||
ID string `xml:"id"`
|
||||
Link link `xml:"link"`
|
||||
Author []author `xml:"author"`
|
||||
}
|
||||
type link struct {
|
||||
XMLName xml.Name `xml:"link"`
|
||||
Href string `xml:"href,attr"`
|
||||
}
|
||||
type author struct {
|
||||
XMLName xml.Name `xml:"author"`
|
||||
Name string `xml:"name"`
|
||||
URI string `xml:"uri"`
|
||||
}
|
||||
|
||||
// VerifyWebhook -
|
||||
func VerifyWebhook(c *context.Context) {
|
||||
hubMode, ok := c.GetQuery("hub.mode")
|
||||
if !ok {
|
||||
c.DataFormat(nil)
|
||||
return
|
||||
}
|
||||
challenge, ok := c.GetQuery("hub.challenge")
|
||||
if !ok {
|
||||
c.DataFormat(nil)
|
||||
return
|
||||
}
|
||||
id, ok := c.GetQuery("id")
|
||||
if !ok {
|
||||
c.DataFormat(nil)
|
||||
return
|
||||
}
|
||||
if hubMode == "subscribe" {
|
||||
t := time.Now().Unix() + 86400
|
||||
yt, err := model.GetYoutubeChannelWithID(id)
|
||||
if err != nil {
|
||||
c.ServerError(nil)
|
||||
return
|
||||
}
|
||||
if yt == nil {
|
||||
c.NotFound("channel not found")
|
||||
return
|
||||
}
|
||||
err = yt.UpdateExpire(t)
|
||||
if err != nil {
|
||||
c.ServerError(nil)
|
||||
}
|
||||
}
|
||||
c.String(200, challenge)
|
||||
}
|
||||
|
||||
// GetNotifyWebhook -
|
||||
func GetNotifyWebhook(c *context.Context) {
|
||||
byteBody, err := ioutil.ReadAll(c.Request.Body)
|
||||
defer c.Request.Body.Close()
|
||||
if err != nil {
|
||||
c.DataFormat(nil)
|
||||
return
|
||||
}
|
||||
|
||||
id, ok := c.GetQuery("id")
|
||||
if !ok {
|
||||
c.DataFormat(nil)
|
||||
return
|
||||
}
|
||||
|
||||
hook := &feed{}
|
||||
err = xml.Unmarshal(byteBody, &hook)
|
||||
if err != nil {
|
||||
c.DataFormat(nil)
|
||||
return
|
||||
}
|
||||
|
||||
if len(hook.Entry) == 0 {
|
||||
c.Success(nil)
|
||||
return
|
||||
}
|
||||
|
||||
yt, err := model.GetYoutubeChannelWithID(id)
|
||||
if err != nil || yt == nil {
|
||||
c.ServerError(nil)
|
||||
return
|
||||
}
|
||||
|
||||
if hook.Entry[0].ID == yt.LastVideo {
|
||||
c.Success(nil)
|
||||
return
|
||||
}
|
||||
|
||||
err = yt.UpdateLastVideo(hook.Entry[0].ID)
|
||||
if err != nil {
|
||||
c.ServerError(nil)
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range yt.Groups {
|
||||
if v.Notify {
|
||||
str := v.Tmpl
|
||||
if len(str) == 0 {
|
||||
str = fmt.Sprintf("%s\n%s", hook.Entry[0].Title, hook.Entry[0].Link.Href)
|
||||
} else {
|
||||
str = strings.Replace(str, "{link}", hook.Entry[0].Link.Href, -1)
|
||||
str = strings.Replace(str, "{txt}", hook.Entry[0].Title, -1)
|
||||
}
|
||||
|
||||
msg := &lineapi.TextMessage{
|
||||
Text: str,
|
||||
}
|
||||
|
||||
lineapi.PushMessage(v.ID, msg)
|
||||
}
|
||||
}
|
||||
|
||||
c.Success(nil)
|
||||
}
|
@ -5,6 +5,8 @@ import (
|
||||
|
||||
"git.trj.tw/golang/mtfosbot/module/context"
|
||||
"git.trj.tw/golang/mtfosbot/router/api"
|
||||
"git.trj.tw/golang/mtfosbot/router/google"
|
||||
"git.trj.tw/golang/mtfosbot/router/line"
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
@ -43,4 +45,15 @@ func SetRoutes(r *gin.Engine) {
|
||||
{
|
||||
apiGroup.POST("/login", context.PatchCtx(api.UserLogin))
|
||||
}
|
||||
|
||||
lineApis := r.Group("/line")
|
||||
{
|
||||
lineApis.POST("/", context.PatchCtx(line.GetRawBody), context.PatchCtx(line.VerifyLine), context.PatchCtx(line.GetLineMessage))
|
||||
}
|
||||
|
||||
googleApis := r.Group("/google")
|
||||
{
|
||||
googleApis.GET("/youtube/webhook", context.PatchCtx(google.VerifyWebhook))
|
||||
googleApis.POST("/youtube/webhook", context.PatchCtx(google.GetNotifyWebhook))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user