Commit e99d95e9 authored by 贾浩@五瓣科技's avatar 贾浩@五瓣科技

update tw task

parent 7461b1b4
...@@ -7,10 +7,11 @@ import ( ...@@ -7,10 +7,11 @@ import (
) )
type Config struct { type Config struct {
Debug bool `toml:"debug"` Debug bool `toml:"debug"`
PGSQL PGSQLConfig `toml:"pgsql"` PGSQL PGSQLConfig `toml:"pgsql"`
Server ServerConfig `toml:"server"` Server ServerConfig `toml:"server"`
TGTask TGTaskConfig `toml:"tg_task"` TGTask TGTaskConfig `toml:"tg_task"`
TweeterTask TweeterTaskConfig `toml:"tweeter_task"`
} }
type SupabaseConfig struct { type SupabaseConfig struct {
...@@ -35,6 +36,10 @@ type TGTaskConfig struct { ...@@ -35,6 +36,10 @@ type TGTaskConfig struct {
URL string `toml:"url"` URL string `toml:"url"`
} }
type TweeterTaskConfig struct {
URL string `toml:"url"`
}
type ServerConfig struct { type ServerConfig struct {
Listen string `toml:"listen"` Listen string `toml:"listen"`
} }
......
...@@ -64,3 +64,9 @@ var TaskAction = map[string][]string{ ...@@ -64,3 +64,9 @@ var TaskAction = map[string][]string{
TaskPlatformTelegram: {TaskActionJoin, TaskActionActive}, TaskPlatformTelegram: {TaskActionJoin, TaskActionActive},
TaskPlatformTwitter: {TaskActionFollow, TaskActionLike, TaskActionReply, TaskActionRetweet}, TaskPlatformTwitter: {TaskActionFollow, TaskActionLike, TaskActionReply, TaskActionRetweet},
} }
const (
TwitterAPIActionRetweeter = "retweeters"
TwitterAPIActionLike = "like"
TwitterAPIActionFollow = "follow"
)
package dao
import (
dbModel "sdk_api/model/db"
"gorm.io/gorm"
)
func (d *Dao) GetProviderId(userId, platform string) (providerId string, err error) {
var temp dbModel.Identity
err = d.db.Model(&dbModel.Identity{}).Where("user_id = ? and provider = ?", userId, platform).First(&temp).Error
if err == gorm.ErrRecordNotFound {
return
}
return temp.ProviderId, nil
}
...@@ -13,8 +13,8 @@ import ( ...@@ -13,8 +13,8 @@ import (
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
) )
func (d *Dao) CheckTGJoin(userId, chatId int) (ok bool, err error) { func (d *Dao) CheckTGJoin(userId string, chatId int) (ok bool, err error) {
url := fmt.Sprintf("%s/api/v1/user/joined?chatId=%d&userId=%d", strings.TrimSuffix(d.c.TGTask.URL, "/"), chatId, userId) url := fmt.Sprintf("%s/api/v1/user/joined?chatId=%d&userId=%s", strings.TrimSuffix(d.c.TGTask.URL, "/"), chatId, userId)
log.WithField("url", url).Debug("check tg join") log.WithField("url", url).Debug("check tg join")
data, err := httpGet(url) data, err := httpGet(url)
if err != nil { if err != nil {
...@@ -29,8 +29,8 @@ func (d *Dao) CheckTGJoin(userId, chatId int) (ok bool, err error) { ...@@ -29,8 +29,8 @@ func (d *Dao) CheckTGJoin(userId, chatId int) (ok bool, err error) {
return gjson.Get(string(data), "data.joined").Bool(), nil return gjson.Get(string(data), "data.joined").Bool(), nil
} }
func (d *Dao) CheckTGActive(userId, chatId int) (ok bool, err error) { func (d *Dao) CheckTGActive(userId string, chatId int) (ok bool, err error) {
url := fmt.Sprintf("%s/api/v1/user/active?chatId=%d&userId=%d", strings.TrimSuffix(d.c.TGTask.URL, "/"), chatId, userId) url := fmt.Sprintf("%s/api/v1/user/active?chatId=%d&userId=%s", strings.TrimSuffix(d.c.TGTask.URL, "/"), chatId, userId)
log.WithField("url", url).Debug("check tg active") log.WithField("url", url).Debug("check tg active")
data, err := httpGet(url) data, err := httpGet(url)
if err != nil { if err != nil {
...@@ -59,3 +59,18 @@ func httpGet(url string) ([]byte, error) { ...@@ -59,3 +59,18 @@ func httpGet(url string) ([]byte, error) {
defer resp.Body.Close() defer resp.Body.Close()
return io.ReadAll(resp.Body) return io.ReadAll(resp.Body)
} }
func httpPost(url string, body io.Reader) ([]byte, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "POST", url, body)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
package dao
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
)
func (d *Dao) CreateTwitterProject(apiKey, apiSecret, accessToken, accessSecret, token, projectName string) (tweetId, tweetHandle, tweetName string, err error) {
body := map[string]string{
"api_key": apiKey,
"api_secret": apiSecret,
"access_token": accessToken,
"access_token_secret": accessSecret,
"token": token,
"project": projectName,
}
buf := new(bytes.Buffer)
err = json.NewEncoder(buf).Encode(body)
if err != nil {
return
}
resp, err := httpPost(fmt.Sprintf("%s/project", strings.TrimRight(d.c.TweeterTask.URL, "/")), buf)
if err != nil {
return
}
respTemp := struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
UserID string `json:"user_id"`
Username string `json:"username"`
Name string `json:"name"`
} `json:"data"`
}{}
err = json.Unmarshal(resp, &respTemp)
if err != nil {
return
}
if respTemp.Code != 200 && respTemp.Msg != "task already existed" {
err = errors.New(string(resp))
return
}
return respTemp.Data.UserID, respTemp.Data.Username, respTemp.Data.Name, nil
}
func (d *Dao) DoTweetTask(tweetUserId, tweetId, action string, start bool) (err error) {
body := map[string]string{
"user_id": tweetUserId,
"task_id": tweetId,
"task_type": action,
}
buf := new(bytes.Buffer)
err = json.NewEncoder(buf).Encode(body)
if err != nil {
return
}
url := fmt.Sprintf("%s/task/add", strings.TrimRight(d.c.TweeterTask.URL, "/"))
if !start {
url = fmt.Sprintf("%s/task/stop", strings.TrimRight(d.c.TweeterTask.URL, "/"))
}
resp, err := httpPost(url, buf)
if err != nil {
return
}
if gjson.Get(string(resp), "code").Int() != 200 {
return errors.New(string(resp))
}
return
}
func (d *Dao) CheckTweeterFollow(userId, followerId string) (ok bool, err error) {
url := fmt.Sprintf("%s/verify/follow?user_id=%s&follower_id=%s", strings.TrimSuffix(d.c.TweeterTask.URL, "/"), userId, followerId)
log.WithField("url", url).Debug("check tweet follow")
data, err := httpGet(url)
if err != nil {
return false, err
}
if gjson.Get(string(data), "code").Int() != 200 {
return false, errors.New(string(data))
}
return gjson.Get(string(data), "data.ok").Bool(), nil
}
func (d *Dao) CheckTweeterLike(tweetId, userId string, begin, end int) (ok bool, err error) {
url := fmt.Sprintf("%s/verify/like?tweet_id=%s&user_id=%s", strings.TrimSuffix(d.c.TweeterTask.URL, "/"), tweetId, userId)
if begin != 0 && end != 0 {
url += fmt.Sprintf("&begin=%s&end=%s", time.Unix(int64(begin), 0).Format(time.RFC3339), time.Unix(int64(end), 0).Format(time.RFC3339))
}
log.WithField("url", url).Debug("check tweet like")
data, err := httpGet(url)
if err != nil {
return false, err
}
if gjson.Get(string(data), "code").Int() != 200 {
return false, errors.New(string(data))
}
return gjson.Get(string(data), "data.ok").Bool(), nil
}
func (d *Dao) CheckTweeterRetweet(tweetId, userId string, begin, end int) (ok bool, err error) {
url := fmt.Sprintf("%s/verify/retweeter?tweet_id=%s&retweeter_id=%s", strings.TrimSuffix(d.c.TweeterTask.URL, "/"), tweetId, userId)
if begin != 0 && end != 0 {
url += fmt.Sprintf("&begin=%s&end=%s", time.Unix(int64(begin), 0).Format(time.RFC3339), time.Unix(int64(end), 0).Format(time.RFC3339))
}
log.WithField("url", url).Debug("check tweet retweet")
data, err := httpGet(url)
if err != nil {
return false, err
}
if gjson.Get(string(data), "code").Int() != 200 {
return false, errors.New(string(data))
}
return gjson.Get(string(data), "data.ok").Bool(), nil
}
...@@ -11,11 +11,13 @@ require ( ...@@ -11,11 +11,13 @@ require (
github.com/sirupsen/logrus v1.9.0 github.com/sirupsen/logrus v1.9.0
github.com/supabase-community/supabase-go v0.0.4 github.com/supabase-community/supabase-go v0.0.4
github.com/tidwall/gjson v1.17.1 github.com/tidwall/gjson v1.17.1
gorm.io/datatypes v1.2.1
gorm.io/driver/postgres v1.5.9 gorm.io/driver/postgres v1.5.9
gorm.io/gorm v1.25.10 gorm.io/gorm v1.25.10
) )
require ( require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect
...@@ -25,10 +27,11 @@ require ( ...@@ -25,10 +27,11 @@ require (
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-json v0.10.2 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect github.com/jackc/pgx/v5 v5.5.5 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
...@@ -58,4 +61,5 @@ require ( ...@@ -58,4 +61,5 @@ require (
golang.org/x/text v0.15.0 // indirect golang.org/x/text v0.15.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.5.6 // indirect
) )
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
...@@ -30,10 +32,17 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn ...@@ -30,10 +32,17 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
...@@ -41,8 +50,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= ...@@ -41,8 +50,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
...@@ -67,6 +76,10 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= ...@@ -67,6 +76,10 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
...@@ -141,8 +154,17 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV ...@@ -141,8 +154,17 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/datatypes v1.2.1 h1:r+g0bk4LPCW2v4+Ls7aeNgGme7JYdNDQ2VtvlNUfBh0=
gorm.io/datatypes v1.2.1/go.mod h1:hYK6OTb/1x+m96PgoZZq10UXJ6RvEBb9kRDQ2yyhzGs=
gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8=
gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8= gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8=
gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
......
package api_model package api_model
type CreateProjectRequest struct { type CreateProjectRequest struct {
ProjectName string `json:"projectName" binding:"required"` ProjectName string `json:"projectName" binding:"required"`
Description string `json:"description" binding:"required"` Description string `json:"description" binding:"required"`
TweeterAPIKey string `json:"tweeterAPIKey" binding:"required"`
TweeterAPISecret string `json:"tweeterAPISecret" binding:"required"`
TweeterAccessToken string `json:"tweeterAccessToken" binding:"required"`
TweeterAccessSecret string `json:"tweeterAccessSecret" binding:"required"`
TweeterToken string `json:"tweeterToken" binding:"required"`
TelegramChatId int `json:"telegramChatId" binding:"required"`
} }
type GetProjectResponse struct { type GetProjectResponse struct {
ProjectName string `json:"projectName"` TelegramChatId int `json:"telegramChatId"`
TelegramChatId int `json:"telegramChatId"` TwitterHandle string `json:"twitterHandle"`
TwitterHandle string `json:"twitterHandle"` TweeterName string `json:"tweeterName"`
TweeterUserId string `json:"tweeterUserId"`
ProjectName string `json:"projectName"`
Description string `json:"description"`
TweeterAPIKey string `json:"tweeterAPIKey,omitempty"`
TweeterAPISecret string `json:"tweeterAPISecret,omitempty"`
TweeterAccessToken string `json:"tweeterAccessToken,omitempty"`
TweeterAccessSecret string `json:"tweeterAccessSecret,omitempty"`
TweeterToken string `json:"tweeterToken,omitempty"`
} }
type CreateGroupRequest struct { type CreateGroupRequest struct {
...@@ -22,9 +36,9 @@ type Task struct { ...@@ -22,9 +36,9 @@ type Task struct {
Platform string `json:"platform" binding:"required"` Platform string `json:"platform" binding:"required"`
Action string `json:"action" binding:"required"` Action string `json:"action" binding:"required"`
Url string `json:"url" binding:"required"` Url string `json:"url" binding:"required"`
TwitterUserId int `json:"twitterUserId"` TwitterUserId string `json:"twitterUserId"`
TelegramChatId int `json:"telegramChatId"` TelegramChatId int `json:"telegramChatId"`
TweetId int `json:"tweetId"` TweetId string `json:"tweetId"`
Description string `json:"description" binding:"required"` Description string `json:"description" binding:"required"`
Reward int `json:"reward" binding:"required"` Reward int `json:"reward" binding:"required"`
Start int `json:"start" binding:"required"` Start int `json:"start" binding:"required"`
......
package db_model
import (
"time"
"gorm.io/datatypes"
"gorm.io/gorm"
)
type Identity struct {
Id string `gorm:"primaryKey;type:uuid;not null;comment:用户id"`
ProviderId string `gorm:"type:text;not null;comment:第三方用户id"`
UserId string `gorm:"type:uuid;not null;comment:用户id"`
IdentityData datatypes.JSON `gorm:"type:json;not null;comment:用户身份数据"`
Provider string `gorm:"type:text;not null;comment:第三方用户平台"`
LastSignInAt time.Time `gorm:"type:timestamp;not null;comment:最后登录时间"`
Email string `gorm:"type:text;not null;comment:用户邮箱"`
gorm.Model
}
func (*Identity) TableName() string {
return "auth.identities"
}
...@@ -16,9 +16,18 @@ func (t *TaskAction) TableName() string { ...@@ -16,9 +16,18 @@ func (t *TaskAction) TableName() string {
} }
type Project struct { type Project struct {
Id int `gorm:"primaryKey;autoIncrement:false"` Id int `gorm:"primaryKey;autoIncrement:false"`
Name string `gorm:"type:text;not null;comment:项目名称"` Name string `gorm:"type:text;not null;comment:项目名称"`
Description string `gorm:"type:text;not null;comment:项目描述"` Description string `gorm:"type:text;not null;comment:项目描述"`
TweeterAPIKey string `gorm:"type:text;not null;comment:tweet api key"`
TweeterAPISecret string `gorm:"type:text;not null;comment:tweet api secret"`
TweeterAccessToken string `gorm:"type:text;not null;comment:tweet access token"`
TweeterAccessSecret string `gorm:"type:text;not null;comment:tweet access secret"`
TweeterToken string `gorm:"type:text;not null;comment:tweet token"`
TweeterHandle string `gorm:"type:text;not null;comment:tweet handle"`
TweeterName string `gorm:"type:text;not null;comment:tweet name"`
TweeterUserId string `gorm:"type:text;not null;comment:tweet user id"`
TelegramChatId int `gorm:"type:int;not null;comment:telegram chat id"`
gorm.Model gorm.Model
Groups []*TaskGroup Groups []*TaskGroup
...@@ -45,8 +54,8 @@ type Task struct { ...@@ -45,8 +54,8 @@ type Task struct {
Platform string `gorm:"type:text;not null;comment:任务平台"` Platform string `gorm:"type:text;not null;comment:任务平台"`
Action string `gorm:"type:text;not null;comment:任务动作"` Action string `gorm:"type:text;not null;comment:任务动作"`
Url string `gorm:"type:text;not null;comment:任务链接"` Url string `gorm:"type:text;not null;comment:任务链接"`
TweeterUserId int `gorm:"type:int;not null;comment:tweet用户id,用于关注"` TweeterUserId string `gorm:"type:int;not null;comment:tweet用户id,用于关注"`
TweetId int `gorm:"type:int;not null;comment:推文id,用于转发点赞等"` TweetId string `gorm:"type:int;not null;comment:推文id,用于转发点赞"`
TelegramChatId int `gorm:"type:int;not null;comment:telegram群id"` TelegramChatId int `gorm:"type:int;not null;comment:telegram群id"`
Description string `gorm:"type:text;not null;comment:任务描述"` Description string `gorm:"type:text;not null;comment:任务描述"`
Reward int `gorm:"type:int;not null;comment:任务奖励"` Reward int `gorm:"type:int;not null;comment:任务奖励"`
......
...@@ -36,11 +36,16 @@ func createGroup(c *gin.Context) { ...@@ -36,11 +36,16 @@ func createGroup(c *gin.Context) {
c.JSON(200, withError(constant.InvalidParam)) c.JSON(200, withError(constant.InvalidParam))
return return
} }
if task.Platform == constant.TaskPlatformTelegram && task.TelegramChatId == 0 { // if task.Platform == constant.TaskPlatformTelegram && task.TelegramChatId == 0 {
c.JSON(200, withError(constant.InvalidParam)) // c.JSON(200, withError(constant.InvalidParam))
return // return
} // }
if task.Platform == constant.TaskPlatformTwitter && task.TweetId == 0 && task.TwitterUserId == 0 { // if task.Platform == constant.TaskPlatformTwitter && task.TweetId == 0 && task.TwitterUserId == 0 {
// c.JSON(200, withError(constant.InvalidParam))
// return
// }
if task.Platform == constant.TaskPlatformTwitter && task.Action == constant.TaskActionFollow && task.TweetId == "" {
c.JSON(200, withError(constant.InvalidParam)) c.JSON(200, withError(constant.InvalidParam))
return return
} }
......
...@@ -17,12 +17,17 @@ func checkTask(c *gin.Context) { ...@@ -17,12 +17,17 @@ func checkTask(c *gin.Context) {
return return
} }
done, expired, err := srv.CheckTask(taskId, userId) exist, done, expired, err := srv.CheckTask(taskId, userId)
if err != nil { if err != nil {
c.JSON(200, withError(constant.InternalError)) c.JSON(200, withError(constant.InternalError))
return return
} }
if !exist {
c.JSON(200, withError("task not found"))
return
}
if done || expired { if done || expired {
c.JSON(200, withSuccess(gin.H{"done": done})) c.JSON(200, withSuccess(gin.H{"done": done}))
} }
......
package service package service
import ( import (
"sdk_api/constant"
apiModel "sdk_api/model/api" apiModel "sdk_api/model/api"
dbModel "sdk_api/model/db" dbModel "sdk_api/model/db"
"sdk_api/util" "sdk_api/util"
...@@ -20,26 +21,61 @@ func (s *Service) CreateGroup(req *apiModel.CreateGroupRequest) (gid int, err er ...@@ -20,26 +21,61 @@ func (s *Service) CreateGroup(req *apiModel.CreateGroupRequest) (gid int, err er
return return
} }
project, err := s.GetProject(req.ProjectId)
if err != nil {
log.WithError(err).Error("get project error")
return 0, err
}
for _, task := range req.Tasks { for _, task := range req.Tasks {
daily := 0 daily := 0
if task.Daily { if task.Daily {
daily = 1 daily = 1
} }
gt := &dbModel.Task{ gt := &dbModel.Task{
Id: util.GenFlakeID(), Id: util.GenFlakeID(),
GroupId: g.Id, GroupId: g.Id,
Platform: task.Platform, Platform: task.Platform,
Action: task.Action, Action: task.Action,
Url: task.Url, Url: task.Url,
Description: task.Description, Description: task.Description,
Reward: task.Reward, Reward: task.Reward,
Start: task.Start, Start: task.Start,
End: task.End, End: task.End,
Daily: daily, Daily: daily,
TweeterUserId: task.TwitterUserId,
TweetId: task.TweetId,
TelegramChatId: task.TelegramChatId,
} }
if task.Platform == constant.TaskPlatformTwitter {
if task.Action == constant.TaskActionFollow {
gt.TweeterUserId = project.TweeterUserId
} else {
gt.TweetId = task.TweetId
}
var twitterAPIAction string
switch task.Action {
case constant.TaskActionFollow:
twitterAPIAction = constant.TwitterAPIActionFollow
case constant.TaskActionLike:
twitterAPIAction = constant.TwitterAPIActionLike
case constant.TaskActionRetweet:
twitterAPIAction = constant.TwitterAPIActionRetweeter
}
tweetId := gt.TweetId
if task.Action == constant.TaskActionFollow {
tweetId = gt.TweeterUserId
}
// 推特任务中心,启动任务
err = s.d.DoTweetTask(gt.TweeterUserId, tweetId, twitterAPIAction, true)
if err != nil {
log.WithError(err).Error("do tweet task error")
return 0, err
}
}
if task.Platform == constant.TaskPlatformTelegram {
gt.TelegramChatId = project.TelegramChatId
}
err = s.d.CreateGroupTask(gt) err = s.d.CreateGroupTask(gt)
if err != nil { if err != nil {
log.WithError(err).Error("create group task error") log.WithError(err).Error("create group task error")
......
...@@ -9,9 +9,25 @@ import ( ...@@ -9,9 +9,25 @@ import (
) )
func (s *Service) CreateProject(req *apiModel.CreateProjectRequest) (pid int, err error) { func (s *Service) CreateProject(req *apiModel.CreateProjectRequest) (pid int, err error) {
tweetId, tweetHandle, tweetName, err := s.d.CreateTwitterProject(req.TweeterAPIKey, req.TweeterAPISecret, req.TweeterAccessToken, req.TweeterAccessSecret, req.TweeterToken, req.ProjectName)
if err != nil {
log.WithError(err).Error("create twitter project error")
return
}
p := &dbModel.Project{ p := &dbModel.Project{
Id: util.GenFlakeID(), Id: util.GenFlakeID(),
Name: req.ProjectName, Name: req.ProjectName,
Description: req.Description,
TweeterAPIKey: req.TweeterAPIKey,
TweeterAPISecret: req.TweeterAPISecret,
TweeterAccessToken: req.TweeterAccessToken,
TweeterAccessSecret: req.TweeterAccessSecret,
TweeterToken: req.TweeterToken,
TweeterHandle: tweetHandle,
TweeterName: tweetName,
TweeterUserId: tweetId,
TelegramChatId: req.TelegramChatId,
} }
err = s.d.CreateProject(p) err = s.d.CreateProject(p)
if err != nil { if err != nil {
...@@ -30,7 +46,11 @@ func (s *Service) GetProjectList(page, pageSize int) (resp []*apiModel.GetProjec ...@@ -30,7 +46,11 @@ func (s *Service) GetProjectList(page, pageSize int) (resp []*apiModel.GetProjec
resp = make([]*apiModel.GetProjectResponse, 0) resp = make([]*apiModel.GetProjectResponse, 0)
for _, v := range list { for _, v := range list {
resp = append(resp, &apiModel.GetProjectResponse{ resp = append(resp, &apiModel.GetProjectResponse{
ProjectName: v.Name, TelegramChatId: v.TelegramChatId,
TwitterHandle: v.TweeterHandle,
TweeterName: v.TweeterName,
TweeterUserId: v.TweeterUserId,
Description: v.Description,
}) })
} }
return return
...@@ -48,6 +68,16 @@ func (s *Service) GetProject(pid int) (resp *apiModel.GetProjectResponse, err er ...@@ -48,6 +68,16 @@ func (s *Service) GetProject(pid int) (resp *apiModel.GetProjectResponse, err er
} }
return &apiModel.GetProjectResponse{ return &apiModel.GetProjectResponse{
ProjectName: p.Name, TelegramChatId: p.TelegramChatId,
TwitterHandle: p.TweeterHandle,
TweeterName: p.TweeterName,
TweeterUserId: p.TweeterUserId,
ProjectName: p.Name,
Description: p.Description,
// TweeterAPIKey: p.TweeterAPIKey,
// TweeterAPISecret: p.TweeterAPISecret,
// TweeterAccessToken: p.TweeterAccessToken,
// TweeterAccessSecret: p.TweeterAccessSecret,
// TweeterToken: p.TweeterToken,
}, nil }, nil
} }
...@@ -8,22 +8,15 @@ import ( ...@@ -8,22 +8,15 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
func (s *Service) CheckTask(taskId int, userId string) (done bool, expired bool, err error) { func (s *Service) CheckTask(taskId int, userId string) (exist, done bool, expired bool, err error) {
done, err = s.d.IsTaskDone(taskId, userId) exist = true
if err != nil {
log.WithError(err).Error("is task done error")
return
}
if done {
return
}
task, err := s.d.GetTaskDetail(taskId) task, err := s.d.GetTaskDetail(taskId)
if err != nil { if err != nil {
log.WithError(err).Error("get task error") log.WithError(err).Error("get task error")
return return
} }
if task == nil { if task == nil {
exist = false
return return
} }
...@@ -31,6 +24,13 @@ func (s *Service) CheckTask(taskId int, userId string) (done bool, expired bool, ...@@ -31,6 +24,13 @@ func (s *Service) CheckTask(taskId int, userId string) (done bool, expired bool,
if int64(task.Start) > time.Now().Unix() || int64(task.End) < time.Now().Unix() { if int64(task.Start) > time.Now().Unix() || int64(task.End) < time.Now().Unix() {
expired = true expired = true
} }
done, err = s.d.IsTaskDone(taskId, userId)
if err != nil {
log.WithError(err).Error("is task done error")
return
}
return return
} }
...@@ -43,19 +43,33 @@ func (s *Service) SyncTask(taskId int, userId string) (done bool, err error) { ...@@ -43,19 +43,33 @@ func (s *Service) SyncTask(taskId int, userId string) (done bool, err error) {
if task == nil { if task == nil {
return return
} }
// todo get tg user id by userId
var tgUserId int = 5428144618
switch task.Platform { switch task.Platform {
case constant.TaskPlatformTelegram: case constant.TaskPlatformTelegram:
telegramUserId, err := s.d.GetProviderId(userId, constant.TaskPlatformTelegram)
if err != nil {
log.WithError(err).Error("get provider telegram user id error")
return false, err
}
if telegramUserId == "" {
return false, nil
}
switch task.Action { switch task.Action {
case constant.TaskActionJoin: case constant.TaskActionJoin, constant.TaskActionActive:
// 加入群组 var taskDone bool
joined, err := s.d.CheckTGJoin(tgUserId, task.TelegramChatId) if task.Action == constant.TaskActionJoin {
taskDone, err = s.d.CheckTGJoin(telegramUserId, task.TelegramChatId)
} else {
taskDone, err = s.d.CheckTGActive(telegramUserId, task.TelegramChatId)
}
if err != nil { if err != nil {
log.WithError(err).Error("check tg join error") log.WithError(err).Errorf("check tg %s error", task.Action)
return false, err return false, err
} }
if !joined { if !taskDone {
return false, nil return false, nil
} }
err = s.d.CreateTaskHistory(taskId, userId, task.Daily == 1) err = s.d.CreateTaskHistory(taskId, userId, task.Daily == 1)
...@@ -64,14 +78,24 @@ func (s *Service) SyncTask(taskId int, userId string) (done bool, err error) { ...@@ -64,14 +78,24 @@ func (s *Service) SyncTask(taskId int, userId string) (done bool, err error) {
return false, err return false, err
} }
return true, nil return true, nil
case constant.TaskActionActive: default:
// 今日活跃 return false, fmt.Errorf("unknown task action: %s", task.Action)
activated, err := s.d.CheckTGActive(tgUserId, task.TelegramChatId) }
case constant.TaskPlatformTwitter:
twitterUserId, err := s.d.GetProviderId(userId, constant.TaskPlatformTwitter)
if err != nil {
log.WithError(err).Error("get provider twitter user id error")
return false, err
}
switch task.Action {
case constant.TaskActionFollow:
followed, err := s.d.CheckTweeterFollow(task.TweeterUserId, twitterUserId)
if err != nil { if err != nil {
log.WithError(err).Error("check tg active error") log.WithError(err).Error("check tweeter follow error")
return false, err return false, err
} }
if !activated { if !followed {
return false, nil return false, nil
} }
err = s.d.CreateTaskHistory(taskId, userId, task.Daily == 1) err = s.d.CreateTaskHistory(taskId, userId, task.Daily == 1)
...@@ -80,11 +104,27 @@ func (s *Service) SyncTask(taskId int, userId string) (done bool, err error) { ...@@ -80,11 +104,27 @@ func (s *Service) SyncTask(taskId int, userId string) (done bool, err error) {
return false, err return false, err
} }
return true, nil return true, nil
default: case constant.TaskActionLike, constant.TaskActionRetweet, constant.TaskActionReply:
return false, fmt.Errorf("unknown task action: %s", task.Action) var taskDone bool
} if task.Action == constant.TaskActionLike {
case constant.TaskPlatformTwitter: taskDone, err = s.d.CheckTweeterLike(task.TweetId, twitterUserId, 0, 0)
switch task.Action { } else {
taskDone, err = s.d.CheckTweeterRetweet(task.TweetId, twitterUserId, 0, 0)
}
if err != nil {
log.WithError(err).Errorf("check tweeter %s error", task.Action)
return false, err
}
if !taskDone {
return false, nil
}
err = s.d.CreateTaskHistory(taskId, userId, task.Daily == 1)
if err != nil {
log.WithError(err).Error("create task history error")
return false, err
}
return true, nil
default: default:
return false, fmt.Errorf("unknown task action: %s", task.Action) return false, fmt.Errorf("unknown task action: %s", task.Action)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment