Files
services/twitter/handler/twitter.go
2021-09-15 16:01:52 +01:00

174 lines
4.7 KiB
Go

package handler
import (
"context"
"github.com/dghubble/go-twitter/twitter"
"github.com/micro/micro/v3/service/config"
"github.com/micro/micro/v3/service/errors"
"github.com/micro/micro/v3/service/logger"
pb "github.com/micro/services/twitter/proto"
"golang.org/x/oauth2"
"golang.org/x/oauth2/clientcredentials"
)
type Twitter struct {
Client *twitter.Client
}
func New() *Twitter {
v, err := config.Get("twitter.api_key")
if err != nil {
logger.Fatalf("twitter.api_key config not found: %v", err)
}
apiKey := v.String("")
if len(apiKey) == 0 {
logger.Fatal("twitter.api_key config not found")
}
v, err = config.Get("twitter.api_secret")
if err != nil {
logger.Fatalf("twitter.api_secret config not found: %v", err)
}
apiSecret := v.String("")
if len(apiSecret) == 0 {
logger.Fatal("twitter.api_secret config not found")
}
// oauth2 configures a client that uses app credentials to keep a fresh token
config := &clientcredentials.Config{
ClientID: apiKey,
ClientSecret: apiSecret,
TokenURL: "https://api.twitter.com/oauth2/token",
}
// http.Client will automatically authorize Requests
httpClient := config.Client(oauth2.NoContext)
// Twitter client
client := twitter.NewClient(httpClient)
return &Twitter{
Client: client,
}
}
func (t *Twitter) Timeline(ctx context.Context, req *pb.TimelineRequest, rsp *pb.TimelineResponse) error {
if len(req.Username) == 0 {
return errors.BadRequest("twitter.timeline", "missing username")
}
if req.Limit <= 0 {
req.Limit = 20
}
tweets, _, err := t.Client.Timelines.UserTimeline(&twitter.UserTimelineParams{
ScreenName: req.Username,
Count: int(req.Limit),
})
if err != nil {
logger.Errorf("Failed to retrieve tweets for %v: %v", req.Username, err)
return errors.InternalServerError("twitter.timeline", "Failed to retrieve tweets for %v: %v", req.Username, err)
}
for _, tweet := range tweets {
rsp.Tweets = append(rsp.Tweets, &pb.Tweet{
Id: tweet.ID,
Text: tweet.Text,
CreatedAt: tweet.CreatedAt,
FavouritedCount: int64(tweet.FavoriteCount),
RetweetedCount: int64(tweet.RetweetCount),
Username: tweet.User.ScreenName,
})
}
return nil
}
func (t *Twitter) Search(ctx context.Context, req *pb.SearchRequest, rsp *pb.SearchResponse) error {
if len(req.Query) == 0 {
return errors.BadRequest("twitter.query", "missing query")
}
if req.Limit <= 0 {
req.Limit = 20
}
searchRsp, _, err := t.Client.Search.Tweets(&twitter.SearchTweetParams{
Query: req.Query,
Count: int(req.Limit),
})
if err != nil {
logger.Errorf("Failed to retrieve tweets for %v: %v", req.Query, err)
return errors.InternalServerError("twitter.search", "Failed to retrieve tweets for %v: %v", req.Query, err)
}
for _, tweet := range searchRsp.Statuses {
rsp.Tweets = append(rsp.Tweets, &pb.Tweet{
Id: tweet.ID,
Text: tweet.Text,
CreatedAt: tweet.CreatedAt,
FavouritedCount: int64(tweet.FavoriteCount),
RetweetedCount: int64(tweet.RetweetCount),
Username: tweet.User.ScreenName,
})
}
return nil
}
func (t *Twitter) User(ctx context.Context, req *pb.UserRequest, rsp *pb.UserResponse) error {
if len(req.Username) == 0 {
return errors.BadRequest("twitter.user", "missing username")
}
user, _, err := t.Client.Users.Show(&twitter.UserShowParams{
ScreenName: req.Username,
})
if err != nil {
logger.Errorf("Failed to retrieve user profile for %v: %v", req.Username, err)
return errors.InternalServerError("twitter.user", "Failed to retrieve user profile for %v: %v", req.Username, err)
}
rsp.Status = &pb.Tweet{
Id: user.Status.ID,
Text: user.Status.Text,
CreatedAt: user.Status.CreatedAt,
FavouritedCount: int64(user.Status.FavoriteCount),
RetweetedCount: int64(user.Status.RetweetCount),
Username: req.Username,
}
rsp.Profile = &pb.Profile{
Id: user.ID,
Name: user.Name,
Username: user.ScreenName,
CreatedAt: user.CreatedAt,
Description: user.Description,
Followers: int64(user.FollowersCount),
Private: user.Protected,
Verified: user.Verified,
ImageUrl: user.ProfileImageURL,
}
return nil
}
func (t *Twitter) Trends(ctx context.Context, req *pb.TrendsRequest, rsp *pb.TrendsResponse) error {
trendRsp, _, err := t.Client.Trends.Place(1, &twitter.TrendsPlaceParams{WOEID: 1})
if err != nil {
logger.Errorf("Failed to retrieve trends: %v", err)
return errors.InternalServerError("twitter.trends", "Failed to retrieve trends")
}
for _, list := range trendRsp {
for _, trend := range list.Trends {
rsp.Trends = append(rsp.Trends, &pb.Trend{
Name: trend.Name,
Url: trend.URL,
TweetVolume: trend.TweetVolume,
})
}
}
return nil
}