Skip to content

Instantly share code, notes, and snippets.

@kwelch
Last active June 25, 2019 17:06
Show Gist options
  • Save kwelch/cf580a0f45d5b4c436211b760a1217e6 to your computer and use it in GitHub Desktop.
Save kwelch/cf580a0f45d5b4c436211b760a1217e6 to your computer and use it in GitHub Desktop.
script to pull drawing based on twitter RTs

Twitter Drawing Script

These scripts work together to allow you to select a specific number of winners for a twitter drawing.

It uses a tweet ID to find the retweeters and followers of that account to determine eligable winners. It also accepts the number of winners to select.

Prerequisites

  • twurl - Should be setup and authorized
    • install via gem install twurl
  • jq
    • install via brew install jq

Usage

  • Download both files to the same directory
  • Open a terminal in that directory
  • chmod +x ./twitter-* # makes the files executable
  • ./twitter-drawing.sh <twitter-id> <number-of-winners>

Results will be displayed as:

[
  <screen_name>,
  <screen_name>,
]

Bugs

Unforunately, this is not perfect. Given that I wrote it in an 1.5 hours I didn't expect it to be.

Here are the known issues:

Potentially returns less results than requested This is not actually an error in the logic as it is more an error in the final conversion of id to handle and the twitter API returns an unknown response for the user ID.

(On a more nitpicky note) I am really not a fan of having to use two different scripts for this but twurl made the API calls so easy and JavaScript made the filter and random so easy that I had to use what worked simple and easy for the occasion.

Maybe if I do another one of these I will pick a single language and stick to it. Maybe someone in the comments will show me how terrible this all is and write me a whole new one, until then, this worked well enough for me.

How it works

It pulls creates files in local temp directories that include a list of followers and retweeters of based on the tweet id passed in.

Then it passed it that data over to the js script which will create a Set using randomly generated indexes based on the length of the list. That is then console logged to be picked back up in the parent shell script.

The list is then passed back to twitter to convert the IDs to handles.

#!/bin/bash
# set errors to loud, so as soon as we hit one the script ends
set -e
TWEET_ID=$1
WINNER_COUNT=$2
# make a temp dir
temp_dir=$(mktemp -d)
# load the retweeters, select only the ids and output them to a file
twurl "/1.1/statuses/retweeters/ids.json?id=${TWEET_ID}" | jq .ids > "${temp_dir}/retweeters.json"
# retrieve the screen name that sent the origin tweet
screen_name=$(twurl "/1.1/statuses/show.json?id=${TWEET_ID}" | jq -r .user.screen_name)
# load the followers, select only the ids and output them to a file
twurl "/1.1/followers/ids.json?screen_name=${screen_name}" | jq .ids > "${temp_dir}/followers.json"
# call into the JS file with the location of the temp directory and pass along the count requested
# should return a comma deliminted list of userIds
winners=$(./twitter-select.js "$temp_dir" "$WINNER_COUNT")
# take the userId winner list and convert it to screen_names
twurl "/1.1/users/lookup.json?user_id=${winners}" | jq 'map(.screen_name)'
#!/usr/bin/env node
const {resolve} = require('path');
// parse the incoming parameters
const [tempDir, winnerCount] = process.argv.slice(2);
// load the files created from the parent script
const retweeters = require(resolve(tempDir, "retweeters.json"));
const followers = require(resolve(tempDir, "followers.json"));
// filter the retweeters list to ensure they are also followers
const validWinners = retweeters.filter(userId => followers.includes(userId));
const generateRandomNumber = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
const getUniqueValueForList = (list, count) => {
// initialize a set
const winners = new Set();
// the size will only increase as we successfully add to the set (sets are unique)
while (winners.size < count) {
// pull a random index
let randomIndex = generateRandomNumber(0, list.length);
// add them to the list, the set will determine it is unqiue
winners.add(list[randomIndex]);
}
// return the set as an array
return Array.from(winners);
}
const winners = getUniqueValueForList(validWinners, winnerCount);
// output to the console will be consumed by the parent script
console.log(winners.join(','));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment