mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
Support both bearer + consumer tokens for Twitter modules
* Add support to both the twitter and twitterstats modules for authenticating using both bearer tokens as well as consumer key + secret. * A bearer token is defaulted to if it's supplied * Add this support to both the twitterstats module as well as to the existing twitter module, modifying its functionality to re-use the same HTTP client and handle authentication upfront via oauth2
This commit is contained in:
parent
d82eda1933
commit
a99af9a091
@ -1,9 +1,14 @@
|
|||||||
package twitter
|
package twitter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
"golang.org/x/oauth2/clientcredentials"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* NOTE: Currently single application ONLY
|
/* NOTE: Currently single application ONLY
|
||||||
@ -12,19 +17,37 @@ import (
|
|||||||
|
|
||||||
// Client represents the data required to connect to the Twitter API
|
// Client represents the data required to connect to the Twitter API
|
||||||
type Client struct {
|
type Client struct {
|
||||||
apiBase string
|
apiBase string
|
||||||
bearerToken string
|
count int
|
||||||
count int
|
screenName string
|
||||||
screenName string
|
httpClient *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates and returns a new Twitter client
|
// NewClient creates and returns a new Twitter client
|
||||||
func NewClient(settings *Settings) *Client {
|
func NewClient(settings *Settings) *Client {
|
||||||
|
var httpClient *http.Client
|
||||||
|
// If a bearer token is supplied, use that directly. Otherwise, let the Oauth client fetch a token
|
||||||
|
// using the consumer key and secret.
|
||||||
|
if settings.bearerToken == "" {
|
||||||
|
conf := &clientcredentials.Config{
|
||||||
|
ClientID: settings.consumerKey,
|
||||||
|
ClientSecret: settings.consumerSecret,
|
||||||
|
TokenURL: "https://api.twitter.com/oauth2/token",
|
||||||
|
}
|
||||||
|
httpClient = conf.Client(oauth2.NoContext)
|
||||||
|
} else {
|
||||||
|
ctx := context.Background()
|
||||||
|
httpClient = oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{
|
||||||
|
AccessToken: settings.bearerToken,
|
||||||
|
TokenType: "Bearer",
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
client := Client{
|
client := Client{
|
||||||
apiBase: "https://api.twitter.com/1.1/",
|
apiBase: "https://api.twitter.com/1.1/",
|
||||||
count: settings.count,
|
count: settings.count,
|
||||||
screenName: "",
|
screenName: "",
|
||||||
bearerToken: settings.bearerToken,
|
httpClient: httpClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &client
|
return &client
|
||||||
@ -53,7 +76,7 @@ func (client *Client) tweets() (tweets []Tweet, err error) {
|
|||||||
strconv.Itoa(client.count),
|
strconv.Itoa(client.count),
|
||||||
)
|
)
|
||||||
|
|
||||||
data, err := Request(client.bearerToken, apiURL)
|
data, err := Request(client.httpClient, apiURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return tweets, err
|
return tweets, err
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,11 @@ package twitter
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Request(bearerToken string, apiURL string) ([]byte, error) {
|
func Request(httpClient *http.Client, apiURL string) ([]byte, error) {
|
||||||
req, err := http.NewRequest("GET", apiURL, nil)
|
resp, err := httpClient.Get(apiURL)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expected authorization format for single-application twitter dev accounts
|
|
||||||
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", bearerToken))
|
|
||||||
|
|
||||||
client := &http.Client{}
|
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,22 @@ const (
|
|||||||
type Settings struct {
|
type Settings struct {
|
||||||
common *cfg.Common
|
common *cfg.Common
|
||||||
|
|
||||||
bearerToken string
|
bearerToken string
|
||||||
count int
|
consumerKey string
|
||||||
screenNames []interface{}
|
consumerSecret string
|
||||||
|
count int
|
||||||
|
screenNames []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings {
|
func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings {
|
||||||
settings := Settings{
|
settings := Settings{
|
||||||
common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig),
|
common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig),
|
||||||
|
|
||||||
bearerToken: ymlConfig.UString("bearerToken", os.Getenv("WTF_TWITTER_BEARER_TOKEN")),
|
bearerToken: ymlConfig.UString("bearerToken", os.Getenv("WTF_TWITTER_BEARER_TOKEN")),
|
||||||
count: ymlConfig.UInt("count", 5),
|
consumerKey: ymlConfig.UString("consumerKey", os.Getenv("WTF_TWITTER_CONSUMER_KEY")),
|
||||||
screenNames: ymlConfig.UList("screenName"),
|
consumerSecret: ymlConfig.UString("consumerSecret", os.Getenv("WTF_TWITTER_CONSUMER_SECRET")),
|
||||||
|
count: ymlConfig.UInt("count", 5),
|
||||||
|
screenNames: ymlConfig.UList("screenName"),
|
||||||
}
|
}
|
||||||
|
|
||||||
return &settings
|
return &settings
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package twitterstats
|
package twitterstats
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -15,6 +16,7 @@ import (
|
|||||||
type Client struct {
|
type Client struct {
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
screenNames []string
|
screenNames []string
|
||||||
|
bearerToken string
|
||||||
}
|
}
|
||||||
|
|
||||||
// TwitterStats Represents a stats snapshot for a single Twitter user at a point in time
|
// TwitterStats Represents a stats snapshot for a single Twitter user at a point in time
|
||||||
@ -37,12 +39,23 @@ func NewClient(settings *Settings) *Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := &clientcredentials.Config{
|
var httpClient *http.Client
|
||||||
ClientID: settings.consumerKey,
|
// If a bearer token is supplied, use that directly. Otherwise, let the Oauth client fetch a token
|
||||||
ClientSecret: settings.consumerSecret,
|
// using the consumer key and secret.
|
||||||
TokenURL: "https://api.twitter.com/oauth2/token",
|
if settings.bearerToken == "" {
|
||||||
|
conf := &clientcredentials.Config{
|
||||||
|
ClientID: settings.consumerKey,
|
||||||
|
ClientSecret: settings.consumerSecret,
|
||||||
|
TokenURL: "https://api.twitter.com/oauth2/token",
|
||||||
|
}
|
||||||
|
httpClient = conf.Client(oauth2.NoContext)
|
||||||
|
} else {
|
||||||
|
ctx := context.Background()
|
||||||
|
httpClient = oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{
|
||||||
|
AccessToken: settings.bearerToken,
|
||||||
|
TokenType: "Bearer",
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
httpClient := conf.Client(oauth2.NoContext)
|
|
||||||
|
|
||||||
client := Client{
|
client := Client{
|
||||||
httpClient: httpClient,
|
httpClient: httpClient,
|
||||||
|
@ -15,6 +15,7 @@ const (
|
|||||||
type Settings struct {
|
type Settings struct {
|
||||||
common *cfg.Common
|
common *cfg.Common
|
||||||
|
|
||||||
|
bearerToken string
|
||||||
consumerKey string
|
consumerKey string
|
||||||
consumerSecret string
|
consumerSecret string
|
||||||
screenNames []interface{}
|
screenNames []interface{}
|
||||||
@ -24,6 +25,7 @@ func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *co
|
|||||||
settings := Settings{
|
settings := Settings{
|
||||||
common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig),
|
common: cfg.NewCommonSettingsFromModule(name, defaultTitle, defaultFocusable, ymlConfig, globalConfig),
|
||||||
|
|
||||||
|
bearerToken: ymlConfig.UString("bearerToken", os.Getenv("WTF_TWITTER_BEARER_TOKEN")),
|
||||||
consumerKey: ymlConfig.UString("consumerKey", os.Getenv("WTF_TWITTER_CONSUMER_KEY")),
|
consumerKey: ymlConfig.UString("consumerKey", os.Getenv("WTF_TWITTER_CONSUMER_KEY")),
|
||||||
consumerSecret: ymlConfig.UString("consumerSecret", os.Getenv("WTF_TWITTER_CONSUMER_SECRET")),
|
consumerSecret: ymlConfig.UString("consumerSecret", os.Getenv("WTF_TWITTER_CONSUMER_SECRET")),
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user