Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
hatboysam committed Dec 30, 2013
0 parents commit c76fa5b
Show file tree
Hide file tree
Showing 7 changed files with 590 additions and 0 deletions.
14 changes: 14 additions & 0 deletions .gitignore
@@ -0,0 +1,14 @@
# Ignore Images
*.jpg

# Mac
.DS_Store

# IntelliJ
.idea/
*.iml
*.iws

# Maven
log/
target/
24 changes: 24 additions & 0 deletions pom.xml
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.habosa</groupId>
<artifactId>JavaSnap</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>com.mashape.unirest</groupId>
<artifactId>unirest-java</artifactId>
<version>1.3.3</version>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
</project>
100 changes: 100 additions & 0 deletions src/main/java/com/habosa/javasnap/Encryption.java
@@ -0,0 +1,100 @@
package com.habosa.javasnap;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

/**
* Author: samstern
* Date: 12/28/13
*/
public class Encryption {

private static final String KEY_ALG = "AES";
private static final String AES_KEY = "M02cnQ51Ji97vwT4";
private static final String CIPHER_MODE = "AES/ECB/PKCS5Padding";

public static byte[] encrypt(byte[] data) throws EncryptionException {

// Get AES-ECB with the right padding
Cipher cipher = null;
try {
cipher = Cipher.getInstance(CIPHER_MODE);
} catch (NoSuchAlgorithmException e) {
throw new EncryptionException(e);
} catch (NoSuchPaddingException e) {
throw new EncryptionException(e);
}

// Set the key
byte[] keyBytes = AES_KEY.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, KEY_ALG);

// Initialize the Cipher
try {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
} catch (InvalidKeyException e) {
throw new EncryptionException(e);
}

// Encrypt the data
try {
byte[] result = cipher.doFinal(data);
return result;
} catch (IllegalBlockSizeException e) {
throw new EncryptionException(e);
} catch (BadPaddingException e) {
throw new EncryptionException(e);
}
}

public static byte[] decrypt(byte[] data) throws EncryptionException {

Cipher cipher = null;
try {
cipher = Cipher.getInstance(CIPHER_MODE);
} catch (NoSuchAlgorithmException e) {
throw new EncryptionException(e);
} catch (NoSuchPaddingException e) {
throw new EncryptionException(e);
}

byte[] keyBytes = AES_KEY.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, KEY_ALG);

// Only difference from encrypt method
try {
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
} catch (InvalidKeyException e) {
throw new EncryptionException(e);
}

try {
byte[] result = cipher.doFinal(data);
return result;
} catch (IllegalBlockSizeException e) {
throw new EncryptionException(e);
} catch (BadPaddingException e) {
throw new EncryptionException(e);
}
}

public static class EncryptionException extends Exception {

private Exception cause;

public EncryptionException(Exception e) {
this.cause = e;
}

@Override
public void printStackTrace() {
cause.printStackTrace();
this.printStackTrace();
}
}

}
40 changes: 40 additions & 0 deletions src/main/java/com/habosa/javasnap/Main.java
@@ -0,0 +1,40 @@
package com.habosa.javasnap;

import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Scanner;

public class Main {

public static void main(String[] args) throws Exception {
// Get username and password
Scanner scanner = new Scanner(System.in);
System.out.println("Snapchat username: ");
String username = scanner.nextLine();
System.out.println("Snapchat password: ");
String password = scanner.nextLine();

// Test logging in
System.out.println("Logging in...");
JSONObject loginObj = Snapchat.login(username, password);
String token = loginObj.getString(Snapchat.AUTH_TOKEN_KEY);

// Try fetching all snaps
System.out.println("Fetching snaps...");
Snap[] snapObjs = Snapchat.getSnaps(loginObj);
Snap[] downloadable = Snap.filterDownloadable(snapObjs);
for (Snap s : downloadable) {
byte[] snapBytes = Snapchat.getSnap(s, username, token);
// TODO(samstern): Support video
if (s.isImage()) {
System.out.println("Downloading snap from " + s.getSender());
File snapFile = new File(s.getSender() + "-" + s.getId() + ".jpg");
FileOutputStream snapOs = new FileOutputStream(snapFile);
snapOs.write(snapBytes);
snapOs.close();
}
}
}
}
168 changes: 168 additions & 0 deletions src/main/java/com/habosa/javasnap/Snap.java
@@ -0,0 +1,168 @@
package com.habosa.javasnap;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Arrays;

/**
* Author: samstern
* Date: 12/30/13
*/
public class Snap {

public static int TYPE_IMAGE = 0;
public static int TYPE_VIDEO = 1;
public static int TYPE_VIDEO_NOAUDIO = 2;

public static int NONE = -1;
public static int SENT = 0;
public static int DELIVERED = 1;
public static int VIEWED = 2;
public static int SCREENSHOT = 3;

private static final String ID_KEY = "id";
private static final String SENDER_KEY = "sn";
private static final String RECIPENT_KEY = "rp";
private static final String TYPE_KEY = "m";
private static final String STATE_KEY = "st";
private static final String TIME_KEY = "t";

private String id;
private String sender;
private String recipient;
private int type;
private int state;
private int time;

public Snap(JSONObject snapObject) {
// Check for fields that always exist
try {
this.id = snapObject.getString(ID_KEY);
this.type = snapObject.getInt(TYPE_KEY);
this.state = snapObject.getInt(STATE_KEY);
} catch (JSONException e) {
e.printStackTrace();
return;
}

// Check sender or recipient separately
try {
this.sender = snapObject.getString(SENDER_KEY);
} catch (JSONException e) {
// Ignore
}
try {
this.recipient = snapObject.getString(RECIPENT_KEY);
} catch (JSONException e) {
// Ignore
}

// Check for time separately because it may not exist.
try {
this.time = snapObject.getInt(TIME_KEY);
} catch (JSONException e) {
return;
}
}

/**
* Take an array of Snaps and return only those that are downloadable.
*
* @param input the array of Snaps to filter.
* @return the snaps that are downloadable (media and unviewed).
*/
public static Snap[] filterDownloadable(Snap[] input) {
ArrayList<Snap> result = new ArrayList<Snap>();
for (Snap s : input) {
if (s.isMedia() && s.isIncoming() && !s.isViewed()) {
result.add(s);
}
}

return result.toArray(new Snap[result.size()]);
}

/**
* Determine if a Snap has already been viewed. If not, it can be downloaded.
*
* @return true if it has been viewed, false otherwise.
*/
public boolean isViewed() {
return (state == VIEWED);
}

/**
* Determine if a Snap is a still image.
*
* @return true if it is an image, false if it is a video or other.
*/
public boolean isImage() {
return (type == TYPE_IMAGE);
}

/**
* Determine if a Snap is a video.
*
* @return true if it is a video, false if it is an image or other.
*/
public boolean isVideo() {
return (type == TYPE_VIDEO || type == TYPE_VIDEO_NOAUDIO);
}

/**
* Determine if a Snap is a video or image. If not, can't be downloaded and viewed.
*
* @return true if it is a video or an image, false if other.
*/
public boolean isMedia() {
return (type <= TYPE_VIDEO);
}

/**
* Determine if a Snap is incoming or outgoing.
*
* @return true if a snap is incoming, false otherwise.
*/
public boolean isIncoming() {
return (id.endsWith("r"));
}

public String getId() {
return id;
}

public String getSender() {
return sender;
}

public String getRecipient() {
return recipient;
}

public int getType() {
return type;
}

public int getState() {
return state;
}

public int getTime() {
return time;
}

@Override
public String toString() {
String[] attrs = new String[]{
id,
sender,
recipient,
Integer.toString(type),
Integer.toString(state),
Integer.toString(time)
};
return Arrays.toString(attrs);
}
}

0 comments on commit c76fa5b

Please sign in to comment.