Advertisement
Guest User

BirdCoins.java

a guest
Sep 24th, 2016
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.49 KB | None | 0 0
  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.io.OutputStream;
  5. import java.net.HttpURLConnection;
  6. import java.net.SocketTimeoutException;
  7. import java.net.URL;
  8. import java.util.ArrayList;
  9. import java.util.Arrays;
  10. import java.util.Collections;
  11. import java.util.Comparator;
  12. import java.util.HashMap;
  13. import java.util.List;
  14. import java.util.Map;
  15.  
  16. /**
  17.  * A program that can be used to collect bird coins for an Angry Birds Friends account.
  18.  *
  19.  * <p>Usage:
  20.  *
  21.  * <ol>
  22.  *   <li>Comment out the redeemGifts() method, and run the program to see how many gifts you have.
  23.  *   <li>Configure the number of gifts to redeem, number of connections, and authentication params.
  24.  *   <li>Run again with redeemGifts() uncommented to perform the collection.
  25.  * </ol>
  26.  */
  27. public class BirdCoins {
  28.  
  29.   /**
  30.    * Number of gifts to redeem with this collection. If this is less than the total number of
  31.    * available gifts, the ones closest to expiration will be redeemed first.
  32.    */
  33.   private static final int GIFTS_TO_REDEEM = 1;
  34.  
  35.   /**
  36.    * The number of simultaneous connections to make when redeeming gifts. A higher number will
  37.    * generally result in a bigger collection. Depending on your computer specs and network
  38.    * connection speed, you might want to set this somewhere between about 100 and 1000.
  39.    */
  40.   private static final int NUM_CONNECTIONS = 150;
  41.  
  42.   /**
  43.    * Authentication query parameters to append to requests. HTTP 403 is returned if these are not
  44.    * included. To learn how to find the auth params for your account, see
  45.    * https://docs.google.com/document/d/1uBLHVlG-t_fOlQYXjnMkIIEqOWyAvoF-jBXDS1rXCFY/edit
  46.    */
  47.   static final String AUTH_PARAMS = "hash=123-456&st=123abcDEF";
  48.  
  49.   private static final String USER_AGENT =
  50.       "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36";
  51.  
  52.   private static final String URL_BASE = "https://angrybirds-facebook.appspot.com/";
  53.   private static final String ACCEPT_GIFTS_URL = URL_BASE + "acceptrequest/";
  54.   private static final String READ_GIFTS_URL = URL_BASE + "/getrequests";
  55.  
  56.   /**
  57.    * Timeout in ms for opening a collect connection. Most of the time it takes roughly 40ms to open
  58.    * a connection, but occasionally it takes many seconds. Give each connection CONNECT_TIMEOUT_MS
  59.    * before just giving up waiting and starting a new one instead. This makes the time to open
  60.    * connections 2-3 times faster in practice.
  61.    */
  62.   private static final int CONNECT_TIMEOUT_MS = 100;
  63.  
  64.   /** Collection read timeout. A value of 0 means to let the collection take as long as it needs. */
  65.   private static final int READ_TIMEOUT_MS = 0;
  66.  
  67.   public static void main(String[] args) throws Exception {
  68.     System.out.println("Number of available gifts: " + parseGifts(readGifts()).length);
  69.     // redeemGifts();
  70.   }
  71.  
  72.   private static void redeemGifts() throws Exception {
  73.  
  74.     String postBody = getPostBody();
  75.  
  76.     URL acceptUrl = new URL(ACCEPT_GIFTS_URL + "?" + AUTH_PARAMS);
  77.  
  78.     HashMap<HttpURLConnection, OutputStream> connections = new HashMap<>();
  79.  
  80.     System.out.println("About to open connections");
  81.  
  82.     long t0 = System.currentTimeMillis();
  83.     int numTimeout = 0;
  84.     while (connections.size() < NUM_CONNECTIONS) {
  85.       HttpURLConnection con = (HttpURLConnection) acceptUrl.openConnection();
  86.       con.setConnectTimeout(CONNECT_TIMEOUT_MS);
  87.       con.setReadTimeout(READ_TIMEOUT_MS);
  88.       long t = System.currentTimeMillis();
  89.       try {
  90.         OutputStream os = getOutputStream(con); // this blocks for ~40ms
  91.         System.out.println(
  92.             "Took this many ms to open one connection: " + (System.currentTimeMillis() - t));
  93.         connections.put(con, os);
  94.       } catch (SocketTimeoutException ste) {
  95.         numTimeout++;
  96.       }
  97.     }
  98.  
  99.     System.out.println("This many connections timed out: " + numTimeout);
  100.  
  101.     long t1 = System.currentTimeMillis();
  102.     System.out.println("Took this many ms: " + (t1 - t0));
  103.     System.out.println();
  104.     System.out.println("About to write");
  105.  
  106.     for (Map.Entry<HttpURLConnection, OutputStream> connection : connections.entrySet()) {
  107.       OutputStream os = connection.getValue();
  108.       os.write(postBody.getBytes());
  109.     }
  110.  
  111.     long t2 = System.currentTimeMillis();
  112.     System.out.println("Took this many ms: " + (t2 - t1));
  113.     System.out.println();
  114.     System.out.println("About to flush");
  115.  
  116.     for (Map.Entry<HttpURLConnection, OutputStream> connection : connections.entrySet()) {
  117.       OutputStream os = connection.getValue();
  118.       os.flush();
  119.     }
  120.  
  121.     long t3 = System.currentTimeMillis();
  122.     System.out.println("Took this many ms: " + (t3 - t2));
  123.     System.out.println();
  124.     System.out.println("About to close");
  125.  
  126.     for (Map.Entry<HttpURLConnection, OutputStream> connection : connections.entrySet()) {
  127.       OutputStream os = connection.getValue();
  128.       os.close();
  129.     }
  130.  
  131.     final long t4 = System.currentTimeMillis();
  132.     System.out.println("Took this many ms: " + (t4 - t3));
  133.     System.out.println();
  134.     System.out.println("About to create threads");
  135.  
  136.     for (Map.Entry<HttpURLConnection, OutputStream> connection : connections.entrySet()) {
  137.       final HttpURLConnection httpUrlConnection = connection.getKey();
  138.       Thread t = new Thread() {
  139.         HttpURLConnection con = httpUrlConnection;
  140.  
  141.         public void run() {
  142.           try {
  143.             int responseCode = con.getResponseCode();
  144.             System.out.println(responseCode + " at time " + (System.currentTimeMillis() - t4));
  145.           } catch (Exception e) {
  146.             // e.printStackTrace();
  147.           }
  148.         }
  149.       };
  150.       t.start();
  151.     }
  152.  
  153.     long t5 = System.currentTimeMillis();
  154.     System.out.println("Took this many ms: " + (t5 - t4));
  155.     System.out.println();
  156.   }
  157.  
  158.   private static String getPostBody() throws Exception {
  159.     List<String> gifts = getOldestGifts(parseGifts(readGifts()), GIFTS_TO_REDEEM);
  160.     return "[\"" + String.join("\",\"", gifts) + "\"]";
  161.   }
  162.  
  163.   private static String readGifts() throws Exception {
  164.     String urlString = READ_GIFTS_URL + "?" + AUTH_PARAMS;
  165.     return read(urlString);
  166.   }
  167.  
  168.   static String read(String urlString) throws Exception {
  169.     URL url = new URL(urlString);
  170.     HttpURLConnection con = (HttpURLConnection) url.openConnection();
  171.  
  172.     con.setRequestMethod("GET");
  173.  
  174.     con.setRequestProperty("User-Agent", USER_AGENT);
  175.  
  176.     int responseCode = con.getResponseCode();
  177.     System.out.println("Sending GET request to URL: " + urlString);
  178.     System.out.println("Response code: " + responseCode);
  179.  
  180.     BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
  181.     String inputLine;
  182.     StringBuffer response = new StringBuffer();
  183.  
  184.     while ((inputLine = in.readLine()) != null) {
  185.       response.append(inputLine);
  186.     }
  187.     in.close();
  188.  
  189.     return response.toString();
  190.   }
  191.  
  192.   private static String[] parseGifts(String gifts) {
  193.     return parseJson(gifts, "r");
  194.   }
  195.  
  196.   static String[] parseJson(String gifts, String id) {
  197.     String quotedId = "\"" + id + "\"";
  198.     ArrayList<String> giftsList = new ArrayList<String>();
  199.     String remainingGifts = gifts;
  200.  
  201.     while (remainingGifts.indexOf(quotedId) != -1) {
  202.       int giftStart = remainingGifts.indexOf(quotedId) + 4 + id.length();
  203.       int giftEnd = giftStart + remainingGifts.substring(giftStart).indexOf("\"");
  204.       giftsList.add(remainingGifts.substring(giftStart, giftEnd));
  205.       remainingGifts = remainingGifts.substring(giftEnd);
  206.     }
  207.  
  208.     return giftsList.toArray(new String[0]);
  209.   }
  210.  
  211.   /**
  212.    * Returns the specified number of gifts from the provided list that are the oldest (closest to
  213.    * expiration).
  214.    */
  215.   private static final List<String> getOldestGifts(String[] gifts, int numGiftsToRedeem) {
  216.     List<String> giftsList = Arrays.asList(gifts);
  217.     Collections.sort(giftsList, new Comparator<String>() {
  218.       @Override
  219.       public int compare(String o1, String o2) {
  220.         int year1 = getGiftYear(o1);
  221.         int year2 = getGiftYear(o2);
  222.         int month1 = getGiftMonth(o1);
  223.         int month2 = getGiftMonth(o2);
  224.         int day1 = getGiftDay(o1);
  225.         int day2 = getGiftDay(o2);
  226.  
  227.         if (year1 < year2) {
  228.           return -1;
  229.         } else if (year1 > year2) {
  230.           return 1;
  231.         } else if (month1 < month2) {
  232.           return -1;
  233.         } else if (month1 > month2) {
  234.           return 1;
  235.         } else if (day1 < day2) {
  236.           return -1;
  237.         } else if (day1 > day2) {
  238.           return 1;
  239.         } else {
  240.           return 0;
  241.         }
  242.       }
  243.     });
  244.     if (giftsList.size() > numGiftsToRedeem) {
  245.       return giftsList.subList(0, numGiftsToRedeem);
  246.     }
  247.     return giftsList;
  248.   }
  249.  
  250.   private static final int getGiftYear(String gift) {
  251.     return Integer.parseInt(gift.substring(gift.length() - 8, gift.length() - 4));
  252.   }
  253.  
  254.   private static final int getGiftMonth(String gift) {
  255.     return Integer.parseInt(gift.substring(gift.length() - 4, gift.length() - 2));
  256.   }
  257.  
  258.   private static final int getGiftDay(String gift) {
  259.     return Integer.parseInt(gift.substring(gift.length() - 2, gift.length()));
  260.   }
  261.  
  262.   private static OutputStream getOutputStream(HttpURLConnection con) throws IOException {
  263.     con.setRequestMethod("POST");
  264.     con.setRequestProperty("user-agent", USER_AGENT);
  265.     con.setRequestProperty("content-type", "application/json; charset=utf-8");
  266.     con.setDoOutput(true);
  267.     return con.getOutputStream();
  268.   }
  269. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement