Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Some recipes for the Twitter API for twurl +jq, and other useful Twitter code snippets and tools

The basics

This is a collection of basic "recipes", many using twurl (the Swiss Army Knife for the Twitter API!) and jq to query the Twitter API and format the results. Also, some scripts to test or automate common actions.

twurl "/1.1/users/show.json?screen_name=andypiper" | jq '. | {id: .id_str, name: .name, screen_name: .screen_name, bio: .description, location: .location}'

{
  "id": "786491",
  "name": "andy piper (pipes)",
  "screen_name": "andypiper",
  "bio": "I'm the lead @TwitterDev @twitterapi platform team - find the best help via https://t.co/T2vkQoJ64f. Code, community, & respect. ⌨️ 🌈 🙇 #HeForShe 🏳️‍🌈",
  "location": "Kingston upon Thames, London"
}

twurl "/1.1/users/lookup.json?screen_name=andypiper,evilpiper,airatair" | jq '[.[] | {user_id: .id_str, screen_name: .screen_name}]'

[
  {
    "user_id": "786491",
    "screen_name": "andypiper"
  },
  {
    "user_id": "54931584",
    "screen_name": "evilpiper"
  },
  {
    "user_id": "509867806",
    "screen_name": "AiratAir"
  }
]

twurl "/1.1/search/tweets.json?q=%23lego2016&count=200" | jq '[.statuses[]] | length'

-> 6

(i.e. put the statuses into a new array and count the length of that)

twurl -t -A "Content-Type: application/json" -d '{"id": "custom-543399461108469761","changes": [{ "op": "add", "tweet_id": "390897780949925889"},{ "op": "add", "tweet_id": "390853164611555329"}]}' "/1.1/collections/entries/curate.json"

‼️ REQUIRES twurl 0.9.3 (or Content-Type will be ignored -> fail)

twurl "/1.1/users/show.json?screen_name=andypiper&exclude_status=true" | jq '. | {followers: .followers_count}'

{
  "followers": 14815
}

$ twurl -t -H stream.twitter.com -A "Accept-encoding: none" -d follow=54931584 -X POST "/1.1/statuses/filter.json"

‼️ use Accept-encoding: none to avoid gzipped data

‼️ must add params to -d since this is a POST

#!/bin/sh
# count members in Twitter list
twurl "/1.1/lists/show.json?slug=$1&owner_screen_name=andypiper" | jq '. | {count: .member_count}'
#!/bin/sh
# remove from Twitter list
twurl -q -d "screen_name=$2&slug=$1&owner_screen_name=andypiper" "/1.1/lists/members/destroy.json"
#!/bin/bash
# get an app-only auth token
# pass in consumer key and secret as parameters
TOKEN=$(echo -n "$1:$2" | openssl base64 -A)
curl --verbose "https://api.twitter.com/oauth2/token" --header "Authorization: Basic $TOKEN" --header "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -d "grant_type=client_credentials"

twurl -H publish.twitter.com "/oembed?url=https://twitter.com/andypiper&limit=5"

{
  "url": "https://twitter.com/andypiper",
  "title": "",
  "html": "<a class=\"twitter-timeline\" data-tweet-limit=\"5\" href=\"https://twitter.com/andypiper\">Tweets by andypiper</a>\n<script async src=\"//platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>",
  "width": null,
  "height": null,
  "type": "rich",
  "cache_age": "3153600000",
  "provider_name": "Twitter",
  "provider_url": "https://twitter.com",
  "version": "1.0"
}

Handy shell alias for making twurl output more readable...

jsonator () {
	ruby -rubygems -r pp -e 'require "json"; ARGF.each {|l| puts JSON.pretty_generate(JSON.parse(l))}'
}

jtwurl () {
	twurl $@ | jsonator
}

twurl "/1.1/statuses/user_timeline.json?count=5" | jq '[.[] | { text: .text, source: .source, time: .created_at}]'

[
  {
    "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque interdum rutrum sodales. Nullam mattis fermen… https://t.co/kb5SVo14NR",
    "source": "<a href=\"http://wibble.org\" rel=\"nofollow\">simpletester123</a>",
    "time": "Wed Jul 26 10:12:53 +0000 2017"
  },
  {
    "text": "test https://t.co/76eZnhqKj4",
    "source": "<a href=\"http://wibble.org\" rel=\"nofollow\">simpletester123</a>",
    "time": "Wed Jul 26 10:11:44 +0000 2017"
  },
  {
    "text": "Well done @LastWeekTonight 👏🏻 https://t.co/DyHKpUKGy1",
    "source": "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter for iPhone</a>",
    "time": "Mon Jul 24 19:19:16 +0000 2017"
  },
  {
    "text": "Test https://t.co/wBZ9lp9kCR",
    "source": "<a href=\"https://fabric.io\" rel=\"nofollow\">PhotoboothDemoiOS</a>",
    "time": "Fri Jun 30 12:25:50 +0000 2017"
  },
  {
    "text": "just a test\nlook at this\n😎 https://t.co/gYEcopskOR",
    "source": "<a href=\"https://fabric.io\" rel=\"nofollow\">PhotoboothDemoiOS</a>",
    "time": "Thu Jun 29 17:26:21 +0000 2017"
  }
]

twurl "/1.1/lists/members.json?slug=First-50&owner_screen_name=andypiper&count=5000&skip_status=1&include_entities=false" | jq '[.users[] | {id: .id_str, name: .name, screen_name: .screen_name}]' > peeps.json

$ FILE=$(base64 unnamed.png)

$ echo $FILE // just to prove that worked...

$ twurl -X POST "/1.1/account/update_profile_image.json?image=$FILE"

twurl "/1.1/users/search.json?q=andypiper" | jq '[.[] | {id: .id_str, name: .name, screen_name: .screen_name}]'

[
  {
    "id": "786491",
    "name": "Pipes",
    "screen_name": "andypiper"
  },
  {
    "id": "77825609",
    "name": "Andy Piper",
    "screen_name": "andypiper8"
  },
  {
    "id": "455565439",
    "name": "Andrew St",
    "screen_name": "Andypip14"
  },
  {
    "id": "332796322",
    "name": "Andy Pipe",
    "screen_name": "andypipe38"
  },
  {
    "id": "424300699",
    "name": "Felipe Basto",
    "screen_name": "Andypipe98Basto"
  },
  {
    "id": "2894986614",
    "name": "Andy Piper",
    "screen_name": "AndyAndypiper"
  },
  {
    "id": "244145232",
    "name": "andres felipe",
    "screen_name": "andypipe7"
  },
  {
    "id": "427650744",
    "name": "andy pipe",
    "screen_name": "andypipe3"
  },
  {
    "id": "295296501",
    "name": "ANDRES FELIPE BOTINA",
    "screen_name": "andypipe2011"
  },
  {
    "id": "3119979580",
    "name": "andres cardenas",
    "screen_name": "andypipe1207"
  },
  {
    "id": "175910590",
    "name": "Anderson Felipe",
    "screen_name": "andypipe_"
  },
  {
    "id": "2215376413",
    "name": "andy.pip",
    "screen_name": "andypip1"
  },
  {
    "id": "156437723",
    "name": "andres felipe pinzon",
    "screen_name": "andypipe29"
  },
  {
    "id": "4774876672",
    "name": "andy",
    "screen_name": "andypip69"
  },
  {
    "id": "268190008",
    "name": "Philip Piper",
    "screen_name": "andypiper3971"
  },
  {
    "id": "915079999",
    "name": "Andy Piper",
    "screen_name": "andypiper1985"
  },
  {
    "id": "1388227916",
    "name": "andres felipe garzon",
    "screen_name": "andypipe22"
  },
  {
    "id": "1570721150",
    "name": "AndyPipe",
    "screen_name": "daniandi2002"
  },
  {
    "id": "180432443",
    "name": "Andres Felipe",
    "screen_name": "andypipe206"
  },
  {
    "id": "236309993",
    "name": "AndyPipes",
    "screen_name": "xcellxx"
  }
]
// use the twitter-text library to parse and validate a Tweet string
// npm install twitter-text
// node ./validate-tweet.js
var twitter = require('twitter-text');
//var tweet = "123 @andypiper 123456 @mauropiano #winning $TWTR 8901789zz #gnip 0123456789... http://blog.rust-lang.org/2016/05/26/Rust-1.9.html more at http://localhost:3000/notes/595";
//var tweet = "@juandoming Dallas teachers improved student performance by 20% w/mobile video messaging. Would this be useful to you? stars.now"
var tweet = "testing testing #blog https://andypiper.co.uk"
var chars = twitter.getTweetLength(tweet);
var remain = 140 - chars;
var usernames = twitter.extractMentions(tweet);
var urls = twitter.extractUrls(tweet);
var hash = twitter.extractHashtags(tweet);
var cash = twitter.extractCashtags(tweet);
var valid = twitter.isInvalidTweet(tweet);
if (!valid) {
valid = "OK!";
}
console.log("text: " + tweet);
console.log("");
console.log("validity: " + valid);
console.log("");
console.log("length: " + chars + " (" + remain + ")");
console.log("users: " + usernames);
console.log("links: " + urls);
console.log("hashtags: " + hash);
console.log("cashtags: " + cash);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment