// This tests against the example Twitter themselves walk you through, once // you've obtained an access token. // // https://dev.twitter.com/docs/auth/creating-signature func (oa OAuthSuite) TestTwitterSignatureExample(c *gocheck.C) { logger := logging.GetLogMaster(false, true, false) o := OAuth1{&logger, "xvz1evFS4wEEPTGEFPHBog", "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw"} url := "https://api.twitter.com/1/statuses/update.json" method := "POST" urlParams := map[string]string{"include_entities": "true"} bodyParams := map[string]string{"status": "Hello Ladies + Gentlemen, a signed OAuth request!"} authParams := map[string]string{ "oauth_consumer_key": "xvz1evFS4wEEPTGEFPHBog", "oauth_nonce": "kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg", "oauth_signature_method": "HMAC-SHA1", "oauth_timestamp": "1318622958", "oauth_token": "370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb", "oauth_version": "1.0"} token := Token{"370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb", "LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"} // check signature base string baseStringExpected := "POST&https%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&include_entities%3Dtrue%26oauth_consumer_key%3Dxvz1evFS4wEEPTGEFPHBog%26oauth_nonce%3DkYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1318622958%26oauth_token%3D370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb%26oauth_version%3D1.0%26status%3DHello%2520Ladies%2520%252B%2520Gentlemen%252C%2520a%2520signed%2520OAuth%2520request%2521" c.Assert(o.makeSignatureBaseString(urlParams, bodyParams, authParams, url, method), gocheck.Equals, baseStringExpected) // check signature req := o.authorizedRequestWithParams(url, method, urlParams, bodyParams, authParams, &token) authstring := req.Header.Get("Authorization") regex, _ := regexp.Compile("oauth_signature=\"([^\"]+)\"") signature := regex.FindStringSubmatch(authstring)[1] c.Assert(signature, gocheck.Equals, percentEncode("tnnArxj06cWHq44gCs1OSKk/jLY=")) }
// Making this example from the OAuth tool for update.json, since it's still getting hung up on it. func (oa OAuthSuite) TestAuthOnUpdate(c *gocheck.C) { logger := logging.GetLogMaster(false, true, false) o := OAuth1{&logger, "MxIkjx9eCC3j1JC8kTig", "IgOkwoh5m7AS4LplszxcPaF881vjvZYZNCAvvUz1x0"} url := "https://api.twitter.com/1.1/statuses/update.json" method := "POST" urlParams := map[string]string{} bodyParams := map[string]string{"status": "IMMATWEET"} authParams := map[string]string{ "oauth_consumer_key": "MxIkjx9eCC3j1JC8kTig", "oauth_nonce": "1bd818f5d8e62ceb172aad5bae030fd3", "oauth_signature_method": "HMAC-SHA1", "oauth_token": "27082544-JW0JZKi69R6OloylRBbs85By30kvZ7IfoGmGoiFvt", "oauth_timestamp": "1349163796", "oauth_version": "1.0"} token := Token{"27082544-JW0JZKi69R6OloylRBbs85By30kvZ7IfoGmGoiFvt", "R2ieHCPMIECQnDhXMLOh3zL0w2CC484gFKVdBq6E"} baseStringExpected := "POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json&oauth_consumer_key%3DMxIkjx9eCC3j1JC8kTig%26oauth_nonce%3D1bd818f5d8e62ceb172aad5bae030fd3%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1349163796%26oauth_token%3D27082544-JW0JZKi69R6OloylRBbs85By30kvZ7IfoGmGoiFvt%26oauth_version%3D1.0%26status%3DIMMATWEET" c.Assert(o.makeSignatureBaseString(urlParams, bodyParams, authParams, url, method), gocheck.Equals, baseStringExpected) // check signature req := o.authorizedRequestWithParams(url, method, urlParams, bodyParams, authParams, &token) authstring := req.Header.Get("Authorization") regex, _ := regexp.Compile("oauth_signature=\"([^\"]+)\"") signature := regex.FindStringSubmatch(authstring)[1] c.Assert(signature, gocheck.Equals, "Jk3epY305uVOD9dRFdqpioYBXHA%3D") }
func (oa OAuthSuite) TestGetTimelineWithAuthorization(c *gocheck.C) { logger := logging.GetLogMaster(false, true, false) o := OAuth1{&logger, "MxIkjx9eCC3j1JC8kTig", "IgOkwoh5m7AS4LplszxcPaF881vjvZYZNCAvvUz1x0"} url := "https://api.twitter.com/1.1/statuses/user_timeline.json" method := "GET" urlParams := map[string]string{"screen_name": "theletterjeff"} bodyParams := map[string]string{} authParams := map[string]string{ "oauth_consumer_key": "MxIkjx9eCC3j1JC8kTig", "oauth_nonce": "e0420a453875a19723a3873c9d6af3f0", "oauth_signature_method": "HMAC-SHA1", "oauth_token": "27082544-QJA8iu2G4s7xG9OBRFKLlPntzJakmxidUgrlYtlIy", "oauth_timestamp": "1349331540", "oauth_version": "1.0"} token := Token{"27082544-QJA8iu2G4s7xG9OBRFKLlPntzJakmxidUgrlYtlIy", "yuNeA8Z2DPLu8wwU7zYlsxIGIEyMqqxzaczCafdtvYY"} baseStringExpected := "GET&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fuser_timeline.json&oauth_consumer_key%3DMxIkjx9eCC3j1JC8kTig%26oauth_nonce%3De0420a453875a19723a3873c9d6af3f0%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1349331540%26oauth_token%3D27082544-QJA8iu2G4s7xG9OBRFKLlPntzJakmxidUgrlYtlIy%26oauth_version%3D1.0%26screen_name%3Dtheletterjeff" c.Assert(o.makeSignatureBaseString(urlParams, bodyParams, authParams, url, method), gocheck.Equals, baseStringExpected) req := o.authorizedRequestWithParams(url, method, urlParams, bodyParams, authParams, &token) checkSignature(req, "J8pKvAeHfse6dhv8Z06epOEOArQ%3D", c) }
func (oa OAuthSuite) TestStatusUpdateWithoutEncoding(c *gocheck.C) { logger := logging.GetLogMaster(false, true, false) o := OAuth1{&logger, "MxIkjx9eCC3j1JC8kTig", "IgOkwoh5m7AS4LplszxcPaF881vjvZYZNCAvvUz1x0"} url := "https://api.twitter.com/1.1/statuses/update.json" method := "POST" urlParams := map[string]string{} bodyParams := map[string]string{"status": "IMMATWEET"} authParams := map[string]string{ "oauth_consumer_key": "MxIkjx9eCC3j1JC8kTig", "oauth_nonce": "ef1efdb1c6b03c70ae2800543caae04d", "oauth_signature_method": "HMAC-SHA1", "oauth_token": "27082544-JW0JZKi69R6OloylRBbs85By30kvZ7IfoGmGoiFvt", "oauth_timestamp": "1349229371", "oauth_version": "1.0"} token := Token{"27082544-JW0JZKi69R6OloylRBbs85By30kvZ7IfoGmGoiFvt", "R2ieHCPMIECQnDhXMLOh3zL0w2CC484gFKVdBq6E"} baseStringExpected := "POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json&oauth_consumer_key%3DMxIkjx9eCC3j1JC8kTig%26oauth_nonce%3Def1efdb1c6b03c70ae2800543caae04d%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1349229371%26oauth_token%3D27082544-JW0JZKi69R6OloylRBbs85By30kvZ7IfoGmGoiFvt%26oauth_version%3D1.0%26status%3DIMMATWEET" c.Assert(o.makeSignatureBaseString(urlParams, bodyParams, authParams, url, method), gocheck.Equals, baseStringExpected) req := o.authorizedRequestWithParams(url, method, urlParams, bodyParams, authParams, &token) checkSignature(req, "P6IKBc5LPV7Cz%2F%2FXnjpQuCisgek%3D", c) }
func (oa OAuthSuite) TestTokenStringParsing(c *gocheck.C) { logger := logging.GetLogMaster(false, true, false) o := OAuth1{&logger, "xvz1evFS4wEEPTGEFPHBog", "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw"} testcase := "oauth_token=NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0&oauth_token_secret=veNRnAWe6inFuo8o2u8SLLZLjolYDmDP7SzL0YfYI&oauth_callback_confirmed=true" token := o.parseTokenData(testcase) c.Assert(token.OAuthToken, gocheck.Equals, "NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0") c.Assert(token.OAuthTokenSecret, gocheck.Equals, "veNRnAWe6inFuo8o2u8SLLZLjolYDmDP7SzL0YfYI") }
func (oa OAuthSuite) TestMakingSigningKey(c *gocheck.C) { logger := logging.GetLogMaster(false, true, false) o := OAuth1{&logger, "xvz1evFS4wEEPTGEFPHBog", "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw"} token := Token{"370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb", "LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"} // With a valid token c.Assert(o.makeSigningKey(&token), gocheck.Equals, "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw&LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE") // With a nil token c.Assert(o.makeSigningKey(nil), gocheck.Equals, "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw&") }
// This example comes from // // https://dev.twitter.com/docs/auth/implementing-sign-twitter // // when requesting a request token, before you get an "oauth_token" value. func (oa OAuthSuite) TestSecondTwitterExample(c *gocheck.C) { logger := logging.GetLogMaster(false, true, false) o := OAuth1{&logger, "cChZNFj6T5R0TigYB9yd1w", "L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg"} url := "https://api.twitter.com/oauth/request_token" method := "POST" urlParams := map[string]string{} bodyParams := map[string]string{} authParams := map[string]string{ "oauth_callback": "http://localhost/sign-in-with-twitter/", "oauth_consumer_key": "cChZNFj6T5R0TigYB9yd1w", "oauth_nonce": "ea9ec8429b68d6b77cd5600adbbb0456", "oauth_signature_method": "HMAC-SHA1", "oauth_timestamp": "1318467427", "oauth_version": "1.0"} req := o.authorizedRequestWithParams(url, method, urlParams, bodyParams, authParams, nil) checkSignature(req, "F1Li3tvehgcraF8DMJ7OyxO4w9Y%3D", c) }
// Starts the service func main() { var debug, timestamps, silent bool var port, keyFile string flag.BoolVar(&silent, "silent", false, "Generate only the tweets, without other status information.") flag.BoolVar(&debug, "debug", false, "Print debugging information.") flag.BoolVar(×tamps, "timestamps", false, "Print log/debug with timestamps.") flag.StringVar(&port, "port", "8998", "Port to run the server on.") flag.StringVar(&keyFile, "keyfile", "keys.txt", "File containing the application keys assigned to you by Twitter.") flag.Parse() rand.Seed(time.Now().UnixNano()) // Silent default to false, since there isn't really an aesthetic need to do so logger := logging.GetLogMaster(silent, debug, timestamps) dh := getDataHandle("./ebooker_tweets.db", &logger) defer dh.Cleanup() applicationKey, applicationSecret := oauth1.ParseFromFile(keyFile) oauth1 := oauth1.CreateOAuth1(&logger, applicationKey, applicationSecret) tf := getTweetFetcher(&logger, &oauth1) bots := make(map[string]*Bot) logger.StatusWrite("Welcome to EBOOKER -- let's make some nonsense ^_^\n") logger.StatusWrite("Registering Ebooker RPC...\n") eb := Ebooker{bots, &logger, &dh, &oauth1, &tf} rpc.Register(&eb) rpc.HandleHTTP() logger.StatusWrite("Starting up on port %s\n", port) l, e := net.Listen("tcp", ":"+port) if e != nil { logger.StatusWrite("Listen error: %v.\nTerminating...", e) os.Exit(1) } http.Serve(l, nil) }
func main() { var port, userlist, sched, token, botName, keyFile string var numTweets, prefixLen int var reps, generate, newBot, cancel, del, list bool flag.StringVar(&port, "port", "8998", "Port to server location.") flag.StringVar(&userlist, "users", "SrPablo,__MICHAELJ0RDAN", "Comma-seperated list of users to read from (no spaces)") flag.IntVar(&numTweets, "numTweets", 15, "Number of tweets to generate.") flag.IntVar(&prefixLen, "prefixLen", 2, "Length of generation prefix. Smaller = more random, Larger = more accurate.") flag.BoolVar(&reps, "representations", false, "Treat all forms of a text (.e.g \"It's/ITS/its'\") as equivalent.") flag.BoolVar(&generate, "generate", true, "Generate tweets and print them to stdout. Overrides \"newbot\".") flag.BoolVar(&newBot, "newBot", false, "Creates a new bot to run on the server. Must set \"generate\" to false.") flag.StringVar(&botName, "botName", "SrPablo_ebooks", "The name for your new bot.") flag.StringVar(&sched, "sched", "0 11,19 * * *", "cron-formatted string for how often the new bot will tweet. NOT IMPLEMENTED.") flag.StringVar(&token, "token", "", "Comma-separated pair of token & token secret. If not provided, we require you to complete a Twitter PIN-based authentication") flag.StringVar(&keyFile, "keyfile", "keys.txt", "File containing the application keys assigned to you by Twitter.") flag.BoolVar(&cancel, "cancelBot", false, "Must be used with botName -- sets the named bot to no longer tweet.") flag.BoolVar(&del, "deleteBot", false, "Must be used with botName -- removes the bot entirely from the server.") flag.BoolVar(&list, "listBots", false, "Prints a list of all the bots on this server") flag.Parse() client, err := rpc.DialHTTP("tcp", "127.0.0.1:"+port) defer client.Close() if err != nil { log.Fatal("dialing:", err) } var authArgs defs.AuthParams if token == "" { lm := logging.GetLogMaster(false, true, false) applicationKey, applicationSecret := oauth1.ParseFromFile(keyFile) oauth := oauth1.CreateOAuth1(&lm, applicationKey, applicationSecret) requestToken := oauth.ObtainRequestToken() tokenObj := oauth.ObtainAccessToken(requestToken) lm.StatusWrite("Your access token is %v\n", tokenObj) authArgs = defs.AuthParams{botName, tokenObj.OAuthToken, tokenObj.OAuthTokenSecret} } else { components := strings.Split(token, ",") authArgs = defs.AuthParams{botName, components[0], components[1]} } genArgs := defs.GenParams{strings.Split(userlist, ","), numTweets, reps, prefixLen, authArgs} if generate { resp := make([]string, numTweets) err = client.Call("Ebooker.GenerateTweets", &genArgs, &resp) if err != nil { log.Fatal("generate tweets error:", err) } for i := range resp { fmt.Printf("%v\n", resp[i]) } } else if newBot && !generate { var resp string schedArgs := defs.Schedule{sched} args := defs.NewBotParams{genArgs, authArgs, schedArgs} err = client.Call("Ebooker.NewBot", &args, &resp) if err != nil { log.Fatal("new bot error:", err) } fmt.Println(resp) } else if !generate && list { var toPrint []string err := client.Call("Ebooker.ListBots", "", &toPrint) if err != nil { log.Fatal("listBots error:", err) } fmt.Println(toPrint) } else if !generate && cancel { var msg string err := client.Call("Ebooker.CancelBot", botName, &msg) if err != nil { log.Fatal("cancelBot error:", err) } fmt.Println(msg) } else if !generate && del { var msg string err := client.Call("Ebooker.DeleteBot", botName, &msg) if err != nil { log.Fatal("deleteBot error:", err) } fmt.Println(msg) } }