takos-book

Final Product:

Attempts At Jokes Printed Version PDF
Link to Twitter bot version

14885807_1317431678280588_2032725612_n14877263_1317431571613932_1400395020_n
14914742_1317431461613943_1562010121_n14881410_1317431348280621_2078194419_o

Video of the professor flipping through my book:


Process:
My joke book is a one hundred and twenty five pages, with three hundred and sixty six jokes, with three jokes per page, an intro page – which gives a one sentence blurb on what the contents are, and a title page. Its printed on cream paper and machine bound. It is a collection of jokes based on tweets that where posted at around the same time and combined into a question and answer format to achieve a somewhat coherent, sometimes humorous joke.

For my generative book I wanted I wanted to do something with jokes. I wanted to follow a well known joke format so that they could be somewhat identifiable,the original thing that came to mind was “why did the chicken cross the road?” But I thought that was to specific so I generalized it to just a “why did what is and the idea that I thought up to do it was to combine different tweets into question and answer format. I then erased everything before the word “before” and before “why did” in the question and answer. I had a hard time getting the tweets and the author text to not overlap in the pdf, but overall i think it worked successfully, and I’m happy with the result of using the cream paper instead of white paper even though I’d originally had my doubts about it. I don’t like my joke separator choice of using “-” and think it would have looked better with a thinner version, or simply without one. I am happy with the results of my generator, and think that the twitter version allows me to edit the code to see possible outcomes in a more successful way, and look forward to developing it further.

(note: I didn’t include a picture from my sketchbook because i did not do any image based work.)

The first of my Processing programs uses the Temboo API to find tweets that contain the phrase “Why did”. The second code retrieves tweets with “Because”. The third takes the tweets and gathers the relevant data and also cleans up the text to isolate the relevant parts. The 3rd program below is my inDesign (Basil.js) script, which prints 3 jokes per page. My last program combines the first 3 codes and cleans them up differently in order to match up to the 140 character limit on twitter, and then uses Temboo to tweet the valid ‘jokes’ every time i run my program.

Code:
Processing:

This code retrieves tweets contain the phrase “why did”

import com.temboo.core.*;
import com.temboo.Library.Twitter.Search.*;

// Create a session using your Temboo account application details
TembooSession session = new TembooSession("takos", "myFirstApp", REDACTED);
int x = 209;
void setup() {
  // Run the Tweets Choreo function
  runTweetsChoreo();
}

void runTweetsChoreo() {
  // Create the Choreo object using your Temboo session
  Tweets tweetsChoreo = new Tweets(session);
  tweetsChoreo.setResultType("recent");

  // Set inputs
  String myQuery  = "\"why did\"";
  tweetsChoreo.setQuery(myQuery);
  tweetsChoreo.setAccessToken(REDACTED);
  tweetsChoreo.setConsumerKey(REDACTED);
  tweetsChoreo.setConsumerSecret(REDACTED);
  tweetsChoreo.setAccessTokenSecret(REDACTED);

  // Run the Choreo and store the results
  TweetsResultSet tweetsResults = tweetsChoreo.run();
  
  // Print results
  println(tweetsResults.getLimit());
  println(tweetsResults.getRemaining());
  println(tweetsResults.getReset());
  //println(tweetsResults.getResponse());

  String[] result = {tweetsResults.getResponse()};
  //println(result);
  String name =  "..\\data\\wdt" + x + ".json";
  saveStrings(name,result);
}

This code retrieves tweets that contain the word “because”

import com.temboo.core.*;
import com.temboo.Library.Twitter.Search.*;

// Create a session using your Temboo account application details
TembooSession session = new TembooSession("takos", "myFirstApp", REDACTED);
int x = 209;
void setup() {
  // Run the Tweets Choreo function
  runTweetsChoreo();
}

void runTweetsChoreo() {
  // Create the Choreo object using your Temboo session
  Tweets tweetsChoreo = new Tweets(session);
  tweetsChoreo.setResultType("recent");
  // Set inputs
  String myQuery  = "\"because\"";
  tweetsChoreo.setQuery(myQuery);
  tweetsChoreo.setAccessToken(REDACTED);
  tweetsChoreo.setConsumerKey(REDACTED);
  tweetsChoreo.setConsumerSecret(REDACTED);
  tweetsChoreo.setAccessTokenSecret(REDACTED
  // Run the Choreo and store the results
  TweetsResultSet tweetsResults = tweetsChoreo.run();
  
  // Print results
  println(tweetsResults.getLimit());
  println(tweetsResults.getRemaining());
  println(tweetsResults.getReset());
  //println(tweetsResults.getResponse());

  String[] result = {tweetsResults.getResponse()};
  println(result);
  String name = "..\\data\\bc" + x + ".json";
  saveStrings(name,result);
  //saveStrings(myQuery+".json",result);
}

This code strips both tweets and saves the relevant text selection of “Why” & “Because” into a JSON file with other rewlevant data from the tweets, including Authors and time.

import com.temboo.core.*;
import com.temboo.Library.Twitter.Search.*;

JSONArray tweets;
int number = 201;

void setup() {
  String aJsonFilename = "wdt" + number + ".json";
  JSONObject json = loadJSONObject(aJsonFilename);
  
  String bJsonFilename = "bc" + number + ".json";
  JSONObject bjson = loadJSONObject(bJsonFilename);
  
  tweets = new JSONArray();
  if (json == null || bjson ==null) 
  {
    println("JSONObject could not be loaded!");
  }
  else 
  {
    JSONArray statuses = json.getJSONArray("statuses");
    JSONArray statusesb = bjson.getJSONArray("statuses");
    for (int i=0; i<statuses.size(); i++) { JSONObject aTweet = statuses.getJSONObject(i); String aText = aTweet.getString("text"); String aTime = aTweet.getString("created_at"); JSONObject aUser = aTweet.getJSONObject("user"); String aScreenName = aUser.getString("screen_name"); String aName = aUser.getString("name"); String aColor = aUser.getString("profile_background_color"); println(i + "\t" + aText); JSONObject tweet = new JSONObject(); tweet.setString("text", aText +" "); tweet.setString("name", aName); tweet.setString("color", aColor); tweet.setString("screenName",aScreenName); tweet.setString("date", aTime); //tweets.setJSONObject(i, tweet); JSONObject bTweet = statusesb.getJSONObject(i); String bText = bTweet.getString("text"); String bTime = bTweet.getString("created_at"); JSONObject bUser = bTweet.getJSONObject("user"); String bScreenName = bUser.getString("screen_name"); String bName = bUser.getString("name"); String bColor = bUser.getString("profile_background_color"); println(i + "\t" + bText); tweet.setString("textB", bText +" "); tweet.setString("nameB", bName); tweet.setString("colorB", bColor); tweet.setString("screenNameB",bScreenName); tweet.setString("dateB", bTime); tweet.setString("credits", "By " + aName + " and " + bName + "."); tweets.setJSONObject(i, tweet); tweet.setString("question", getQuestion(aText)+"?"); tweet.setString("answer",getAnswer(bText)); tweet.setString("by",aName + " & " + bName ); saveJSONArray(tweets, number + ".json"); } }} String getQuestion(String text) { int index = (text.toLowerCase()).indexOf("why did"); String cleared = text.substring(index); if((cleared.toLowerCase()).indexOf("http") > 0){
    cleared = cleared.substring(0, ((cleared.toLowerCase()).indexOf("http")));}
  if((cleared.toLowerCase()).indexOf("?") > 0){
    cleared = cleared.substring(0, ((cleared.toLowerCase()).indexOf("?")));}
    
  return cleared; 
}

String getAnswer(String text)
{
  String lowercasedText = text.toLowerCase();
  int indexOfBecause = lowercasedText.indexOf("because");
  String textStartingFromBecause = text.substring(indexOfBecause);
  String textStartingFromBecauseLowercased = textStartingFromBecause.toLowerCase();
  if (textStartingFromBecauseLowercased.indexOf("http") > 0){
    return text.substring(indexOfBecause, (lowercasedText.indexOf("http")));
  }
  return text.substring(indexOfBecause); 
}
  

Indesign Code:

#includepath "~/Documents/;%USERPROFILE%Documents";
#include "basiljs/bundle/basil.js";

var jsonString = b.loadString("all-2.json");
var jsonData;

//--------------------------------------------------------
function setup() {
    
  b.clear (b.doc()); // Clear the document at the very start. 
  var pageNum = 0;    
  var pgW = 6*72;        
  var pgH= 9*72;

  var doc=b.doc();
  with(b.doc().documentPreferences) {
    pageWidth = pgW + "pt";
    pageHeight = pgH + "pt";
    b.width = pgW;
    b.height = pgH;
  }
    

  // Make a title page. 
  b.fill(0,0,0);
  b.textSize(24);
  b.textFont("Helvetica","Light"); 
  b.textAlign(Justification.RIGHT_ALIGN ); 
  b.text("Attempts at Jokes", 72,72,360,36);
  b.textSize(12);
  b.text("Takos & Twitter", 72,108,360,36);
  
  // Parse the JSON file into the jsonData array
  jsonData = b.JSON.decode( jsonString );
  b.println("Number of elements in JSON: " + jsonData.length);

  // Initialize some variables for element placement positions.
  // Remember that the units are "points", 72 points = 1 inch.
  var titleX = 36; 
  var titleY = 76;
  var titleW = 72*5;
 
  var titleH = 24;

  // These are the header fields from the tweet CSV:
  // tweet_id,in_reply_to_status_id,in_reply_to_user_id,timestamp,source,text,
  // retweeted_status_id,retweeted_status_user_id,,retweeted_status_timestamp,
  // expanded_urls

  var textW=pgW*0.75;
  var textOffs=(pgW-textW)/2;
  var textOffsY=72;
  var x=textOffs;
  var y=pgH*0.25;
    
  var textSize1=8;
  var textSize2=30;
  var tweetDist=textSize2*2;
    
  var whiteSpaceStr=" ";

  var elements=[];
    
  var doNewPage=false;
  var w = 0;
  // Loop over every element of the book content array
  for (var i = 0; i <jsonData.length; i+=3){ // 10; i+=3){ //jsonData.length; i+=3) { // Create the next page. b.addPage(); b.noStroke(); // no border around image, please. b.fill(0,0,0); var textY = titleY; var fontA = "Itallic"; var fontB = "Regular"; var size1 = 14; var size2 = 8; var font = "Helvetica"; pageNum = pageNum +1; b.textSize(size1); b.textAlign(Justification.CENTER_ALIGN); b.textFont(font,fontB); b.text("-", 216-20, 228, 40, 40); b.text("-", 216-20, 420, 40, 40); // b.textSize(size2); // b.text(pageNum, 216-20, 612, 40, 40); b.textSize(size1); w = 0; if (jsonData[i].question.length > 57){
        w = 15;
    }
    if (jsonData[i].question.length > 114){
        w = 30;
    }  
    b.color(0,0,0);    
    b.textFont(font,fontB); 
    b.textAlign(Justification.LEFT_ALIGN );
    b.text(jsonData[i].question, titleX,textY,titleW,titleH*3); textY+=titleH;//+15; 
      
    b.color(80,80,80);    
    b.textSize(size2);
    b.textFont(font,fontA); 
    b.text(jsonData[i].name,       titleX,textY+w,titleW,titleH); textY+=titleH*1.5;
    
      
          
    w =0; 
      
    if (jsonData[i].answer.length > 57){
        w = 15;
    }
    if (jsonData[i].answer.length > 114){
        w = 30;
    }  
        
    b.color(0,0,0);      
    b.textSize(size1);
    b.textFont(font,fontB); 
    b.textAlign(Justification.RIGHT_ALIGN );
    b.text(jsonData[i].answer, titleX,textY,titleW,titleH*3); textY+=titleH;//+15;
    b.color(80,80,80);
    b.textSize(size2);
    b.textFont(font,fontA); 
    b.text(jsonData[i].nameB,       titleX,textY+w,titleW,titleH); textY+=titleH*1.5; 
   
      
    w = 0;
    if (jsonData[i+1].question.length > 57){
        w = 15;
    }
    if (jsonData[i+1].question.length > 114){
        w = 30;
    }    
    b.color(0,0,0);
    textY = (pgH-2*titleY)*(1/3)+titleY*1.5;
    b.textSize(size1);
    b.textFont(font,fontB); 
    b.textAlign(Justification.LEFT_ALIGN );
    b.text(jsonData[i+1].question, titleX,textY,titleW,titleH*3); textY+=titleH;//+15; 
    b.color(80,80,80);      
    b.textSize(size2);
    b.textFont(font,fontA); 
    b.text(jsonData[i+1].name,       titleX,textY+w,titleW,titleH); textY+=titleH*1.5;//2;
    
      
    w =0; 
      
    if (jsonData[i+1].answer.length > 57){
        w = 15;
    }
    if (jsonData[i+1].answer.length > 114){
        w = 30;
    }  
      
    b.color(0,0,0);      
    b.textSize(size1);
    b.textFont(font,fontB);
    b.textAlign(Justification.RIGHT_ALIGN );
    b.text(jsonData[i+1].answer, titleX,textY,titleW,titleH*3); textY+=titleH;//+15;
    b.color(80,80,80);
    b.textSize(size2);
    b.textFont(font,fontA); 
    b.text(jsonData[i+1].nameB,       titleX,textY+w,titleW,titleH); textY+=titleH*1.5;//2; 
    w = 0;
    if (jsonData[i+2].question.length > 57){
        w = 15;
    }
    if (jsonData[i+2].question.length > 114){
        w = 30;
    }
    b.color(0,0,0);      
    textY = (pgH-2*titleY)*(2/3)+titleY*2;
    b.textSize(size1);
    b.textFont(font,fontB); 
    b.textAlign(Justification.LEFT_ALIGN );
    b.text(jsonData[i+2].question, titleX,textY,titleW,titleH*3); textY+=titleH;//+15; 
    b.color(80,80,80);      
    b.textSize(size2);
    b.textFont(font,fontA); 
    b.text(jsonData[i+2].name,       titleX,textY+w,titleW,titleH); textY+=titleH*1.5;//2;
    
    w =0; 
      
    if (jsonData[i+2].answer.length > 57){
        w = 15;
    }
    if (jsonData[i+2].answer.length > 114){
        w = 30;
    }
    b.color(0,0,0);      
    b.textSize(size1);
    b.textFont(font,fontB); 
    b.textAlign(Justification.RIGHT_ALIGN );      
    b.text(jsonData[i+2].answer, titleX,textY,titleW,titleH*3); textY+=titleH;//+15;
    b.color(80,80,80);
    b.textSize(size2);
    b.textFont(font,fontA); 
    b.text(jsonData[i+2].nameB,       titleX,textY+w,titleW,titleH); textY+=titleH*1.5;//2; 
 

  };
}

// This makes it all happen:
b.go(); 

Code For Twitter Bot

import com.temboo.core.*;
import com.temboo.Library.Twitter.Search.*;
import com.temboo.Library.Twitter.Tweets.*;
TembooSession session = new TembooSession("takos", "myFirstApp", "");

JSONArray tweets;
String finAnswer;
String finQuestion;
String finCredits;
String mode = "recent";

void whyDid() {
  // Create the Choreo object using your Temboo session
  Tweets tweetsChoreo = new Tweets(session);
  tweetsChoreo.setResultType(mode);

  // Set inputs
  String myQuery = "\"why did\"";
  tweetsChoreo.setQuery(myQuery);
  tweetsChoreo.setAccessToken("-");
  tweetsChoreo.setConsumerKey("");
  tweetsChoreo.setConsumerSecret("");
  tweetsChoreo.setAccessTokenSecret("");

  // Run the Choreo and store the results
  TweetsResultSet tweetsResults = tweetsChoreo.run();

  String[] result = {tweetsResults.getResponse()};
  String name = "wdt.json";
  saveStrings(name, result);
}

void because() {
  // Create the Choreo object using your Temboo session
  Tweets tweetsChoreo = new Tweets(session);
  tweetsChoreo.setResultType(mode);
  // Set inputs
  String myQuery = "because";
  tweetsChoreo.setQuery(myQuery);
  tweetsChoreo.setAccessToken();
  tweetsChoreo.setConsumerKey();
  tweetsChoreo.setConsumerSecret();
  tweetsChoreo.setAccessTokenSecret();

  // Run the Choreo and store the results
  TweetsResultSet tweetsResults = tweetsChoreo.run();

  String[] result = {tweetsResults.getResponse()};
  String name = "bc.json";
  saveStrings(name, result);
}

void tweetIt() {
  StatusesUpdate statusesUpdateChoreo = new StatusesUpdate(session);
  String currentTweet = finQuestion + "\n" + "\n" + finAnswer + "\n" + "\n" + finCredits;

  if (currentTweet.length() <
  = 140) {
    statusesUpdateChoreo.setStatusUpdate(currentTweet);
    statusesUpdateChoreo.setAccessToken();
    statusesUpdateChoreo.setConsumerKey();
    statusesUpdateChoreo.setConsumerSecret();
    statusesUpdateChoreo.setAccessTokenSecret();

    StatusesUpdateResultSet statusesUpdateResults = statusesUpdateChoreo.run();
    //println(statusesUpdateResults.getResponse());'
  } else
  { 
    println(currentTweet);
  }
}

void setup() {

  whyDid();
  because();
  String aJsonFilename = "wdt.json";
  JSONObject json = loadJSONObject(aJsonFilename);

  String bJsonFilename = "bc.json";
  JSONObject bjson = loadJSONObject(bJsonFilename);

  tweets = new JSONArray();
  if (json == null || bjson ==null)
  {
    println("JSONObject could not be loaded!");
  } else
  {
    JSONArray statuses = json.getJSONArray("statuses");
    JSONArray statusesb = bjson.getJSONArray("statuses");
    for (int i=0; i< statuses.size(); i++) { 
      JSONObject aTweet = statuses.getJSONObject(i); 
      String aText = aTweet.getString("text"); 
      String aTime = aTweet.getString("created_at"); 
      JSONObject aUser = aTweet.getJSONObject("user"); 
      String aScreenName = aUser.getString("screen_name"); 
      String aName = aUser.getString("name"); 
      JSONObject bTweet = statusesb.getJSONObject(i); 
      String bText = bTweet.getString("text"); 
      String bTime = bTweet.getString("created_at"); 
      JSONObject bUser = bTweet.getJSONObject("user"); 
      String bScreenName = bUser.getString("screen_name"); 
      String bName = bUser.getString("name"); 
      finAnswer=getAnswer(bText); 
      finQuestion =getQuestion(aText); 
      finCredits = aScreenName + "&" + bScreenName; 
      Cleanup(); 
      tweetIt();
    }
  }
} 
void Cleanup() { 
  finAnswer=endsInAt(clearAmp(finAnswer)); 
  finQuestion =endsInAt(clearAmp(finQuestion)) + "?"; 
  finCredits = clearQ(finCredits);
} 
String getQuestion(String text) { 
  int index = (text.toLowerCase()).indexOf("why did"); 
  String cleared = text.substring(index); 
  if ((cleared.toLowerCase()).indexOf("http") > 
  0) {
    cleared = cleared.substring(0, ((cleared.toLowerCase()).indexOf("http")));
  }
  if ((cleared.toLowerCase()).indexOf("?") > 
  0) {
    cleared = cleared.substring(0, ((cleared.toLowerCase()).indexOf("?")));
  }
  if ((cleared.toLowerCase()).indexOf("\n") > 
  0) {
    cleared = cleared.substring(0, ((cleared.toLowerCase()).indexOf("?")));
  }
  return cleared;
}

String getAnswer(String text)
{
  int index = (text.toLowerCase()).indexOf("because");
  String cleared = text.substring(index);
  if ((cleared.toLowerCase()).indexOf("http") > 
  0) {
    cleared = cleared.substring(0, ((cleared.toLowerCase()).indexOf("http")));
  }
  if ((cleared.toLowerCase()).indexOf("...") > 
  0) {
    cleared = cleared.substring(0, ((cleared.toLowerCase()).indexOf("...")));
  }
  if ((cleared.toLowerCase()).indexOf("\n") > 
  0) {
    cleared = cleared.substring(0, ((cleared.toLowerCase()).indexOf("?")));
  }
  if ((cleared.toLowerCase()).indexOf("!") > 
  0) {
    cleared = cleared.substring(0, ((cleared.toLowerCase()).indexOf("?")));
  }

  return cleared;
}

String clearAmp(String input) {
  int index = input.indexOf("&");
  while (index != -1) {
    input = input.substring(0, index) + input.substring(index+5, input.length());
    index = input.indexOf("&");
  }
  index = input.indexOf(">");
  while (index != -1) {
    input = input.substring(0, index) + input.substring(index+4, input.length());
    index = input.indexOf(">");
  }
  return input;
}

String endsInAt(String input) {
  int index = input.indexOf("@");
  if (index>
  -1 &&
  (input.substring(index, input.length())).indexOf(" ") > -1) {
    input = input.substring(0, index);
  }
  return input;
}

String clearSpace(String input) {
  int index = input.indexOf(" ");
  while (index != -1) {
    input = input.substring(0, index) + input.substring(index+2, input.length());
    index = input.indexOf(" ");
  }
  return input;
}

String clearQ(String input) {
  int index = input.indexOf("?");
  while (index != -1) {
    input = input.substring(0, index) + input.substring(index+2, input.length());
    index = input.indexOf("?");
  }
  return input;
}