1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00

Add twitter module - Single Application account only at the moment

This commit is contained in:
Kenny Wu 2018-07-31 19:14:35 -07:00
parent 9ddd514631
commit 39fc6fdab3
6 changed files with 190 additions and 0 deletions

View File

@ -43,6 +43,7 @@ import (
"github.com/senorprogrammer/wtf/todoist"
"github.com/senorprogrammer/wtf/travisci"
"github.com/senorprogrammer/wtf/trello"
"github.com/senorprogrammer/wtf/twitter"
"github.com/senorprogrammer/wtf/weatherservices/prettyweather"
"github.com/senorprogrammer/wtf/weatherservices/weather"
"github.com/senorprogrammer/wtf/wtf"
@ -233,6 +234,8 @@ func addWidget(app *tview.Application, pages *tview.Pages, widgetName string) {
widgets = append(widgets, travisci.NewWidget())
case "trello":
widgets = append(widgets, trello.NewWidget())
case "twitter":
widgets = append(widgets, twitter.NewWidget())
case "weather":
widgets = append(widgets, weather.NewWidget(app, pages))
case "zendesk":

64
twitter/client.go Normal file
View File

@ -0,0 +1,64 @@
package twitter
import (
"encoding/json"
"fmt"
"os"
"strconv"
)
/* NOTE: Currently single application ONLY
* bearer tokens are only supported for applications, not single-users
*/
// Client represents the data required to connect to the Twitter API
type Client struct {
apiBase string
bearerToken string
count int
screenName string
}
// NewClient creates and returns a new Twitter client
func NewClient(url string) *Client {
client := Client{
apiBase: url,
screenName: "wtfutil",
count: 5,
bearerToken: os.Getenv("WTF_TWITTER_BEARER_TOKEN"),
}
return &client
}
/* -------------------- Public Functions -------------------- */
// Tweets returns a list of tweets of a user
func (client *Client) Tweets() []Tweet {
tweets, err := client.tweets()
if err != nil {
return []Tweet{}
}
return tweets
}
/* -------------------- Private Functions -------------------- */
// tweets is the private interface for retrieving the list of user sweets
func (client *Client) tweets() (tweets []Tweet, err error) {
apiURL := fmt.Sprintf(
"%s/statuses/user_timeline.json?screen_name=%s&count=%s",
client.apiBase,
client.screenName,
strconv.Itoa(client.count),
)
data, err := Request(client.bearerToken, apiURL)
if err != nil {
return tweets, err
}
err = json.Unmarshal(data, &tweets)
return
}

41
twitter/request.go Normal file
View File

@ -0,0 +1,41 @@
package twitter
import (
"bytes"
"fmt"
"net/http"
)
func Request(bearerToken string, apiURL string) ([]byte, error) {
req, err := http.NewRequest("GET", apiURL, nil)
if err != nil {
return nil, err
}
req.Header.Add("Authorization",
fmt.Sprintf("Bearer %s", bearerToken))
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := ParseBody(resp)
if err != nil {
return nil, err
}
return data, err
}
func ParseBody(resp *http.Response) ([]byte, error) {
var buffer bytes.Buffer
_, err := buffer.ReadFrom(resp.Body)
if err != nil {
return nil, err
}
return buffer.Bytes(), nil
}

26
twitter/tweet.go Normal file
View File

@ -0,0 +1,26 @@
package twitter
import (
"fmt"
"github.com/senorprogrammer/wtf/wtf"
)
type Tweet struct {
User User `json:"user"`
Text string `json:"text"`
CreatedAt string `json:"created_at"`
}
func (tweet *Tweet) String() string {
return fmt.Sprintf("Tweet: %s at %s by %s", tweet.Text, tweet.CreatedAt, tweet.User.ScreenName)
}
/* -------------------- Exported Functions -------------------- */
func (tweet *Tweet) Username() string {
return fmt.Sprint(tweet.User.ScreenName)
}
func (tweet *Tweet) PrettyStart() string {
return wtf.PrettyDate(tweet.CreatedAt)
}

6
twitter/user.go Normal file
View File

@ -0,0 +1,6 @@
package twitter
// User is used as part of the Tweet struct to get user information
type User struct {
ScreenName string `json:"screen_name"`
}

50
twitter/widget.go Normal file
View File

@ -0,0 +1,50 @@
package twitter
import (
"fmt"
"github.com/senorprogrammer/wtf/wtf"
)
type Widget struct {
wtf.TextWidget
}
func NewWidget() *Widget {
widget := Widget{
TextWidget: wtf.NewTextWidget("Twitter", "twitter", false),
}
return &widget
}
/* -------------------- Exported Functions -------------------- */
func (widget *Widget) Refresh() {
client := NewClient("https://api.twitter.com/1.1/")
userTweets := client.Tweets()
widget.UpdateRefreshedAt()
widget.View.SetTitle(widget.ContextualTitle(widget.Name))
widget.View.SetText(widget.contentFrom(userTweets))
}
/* -------------------- Unexported Functions -------------------- */
func (widget *Widget) contentFrom(tweets []Tweet) string {
if len(tweets) == 0 {
return fmt.Sprintf("\n\n\n\n\n\n\n\n%s", wtf.CenterText("[grey]No Tweets[white]", 50))
}
str := ""
for _, tweet := range tweets {
str = str + widget.format(tweet)
}
return str
}
func (widget *Widget) format(tweet Tweet) string {
return fmt.Sprintf(" [white]%s[grey]\n [grey]%s - %s[white]\n\n", tweet.Text, tweet.Username(), tweet.CreatedAt)
}