/******************************************************************************* * Copyright (c) 2013 Hani Naguib. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Hani Naguib - initial API and implementation ******************************************************************************/ package com.gvmax.google.voice; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.json.JSONException; import org.json.JSONObject; import com.gvmax.common.util.Constants; import com.gvmax.common.util.NetUtil; import com.gvmax.common.util.PhoneUtil; public class GoogleVoice { private static final Logger logger = Logger.getLogger(GoogleVoice.class); private String email; private String password; private String auth; private String rnr; private String phoneNumber; private List<GoogleVoicePhone> phones = new ArrayList<GoogleVoicePhone>(); public GoogleVoice(String email, String password) { this.email = email; this.password = password; } public void login() throws IOException { Map<String,String> params = new HashMap<String, String>(); params.put("accountType", "HOSTED_OR_GOOGLE"); params.put("Email", email); params.put("Passwd", password); params.put("service", "grandcentral"); params.put("source", "GOOGLE"); auth = extractAuth(NetUtil.doPost("https://www.google.com/accounts/ClientLogin", params)); extractJsonInfo(); } public String getPhoneNumber() throws IOException { ensureLoggedIn(); return phoneNumber; } public List<GoogleVoicePhone> getPhones() throws IOException { ensureLoggedIn(); return phones; } public void sendSMS(String number, String text) throws IOException { ensureLoggedIn(); Map<String, String> params = new HashMap<String, String>(); params.put("_rnr_se", rnr); params.put("c", "undefined"); params.put("id", "undefined"); params.put("smstext", text); params.put("number", PhoneUtil.normalizeNumber(number)); Map<String, String> reqProps = new HashMap<String, String>(); reqProps.put("Authorization", "GoogleLogin auth=" + auth); String res = NetUtil.doPost("https://www.google.com/voice/m/sendsms", params, reqProps); if (!res.contains("Text sent")) { throw new IOException("Error sending SMS"); } } public void sendSMS(final String[] numbers, final String text) throws IOException { ensureLoggedIn(); if (numbers == null || numbers.length == 0) { return; } sendSMS(numbers[0], text); if (numbers.length > 1) { new Thread() { @Override public void run() { for (int x = 1; x < numbers.length; x++) { try { logger.info("Sending SMS # " + x); sendSMS(numbers[x], text); Thread.sleep(10000); } catch (Exception e) { logger.warn("Unable to send SMS : "+e.getMessage()); } } } }.start(); } } public void call(final String number, final String forwardPhoneNumber) throws IOException { ensureLoggedIn(); boolean validPhone = false; for (GoogleVoicePhone phone : phones) { if (PhoneUtil.numbersMatch(phone.getNumber(), forwardPhoneNumber)) { validPhone = true; break; } } if (!validPhone) { throw new IOException("Invalid forwarding phone"); } Map<String, String> params = new HashMap<String, String>(); params.put("_rnr_se", rnr); params.put("number", PhoneUtil.normalizeNumber(number)); params.put("phone", forwardPhoneNumber); Map<String, String> reqProps = new HashMap<String, String>(); reqProps.put("Authorization", "GoogleLogin auth=" + auth); String res = NetUtil.doPost("https://www.google.com/voice/m/sendcall", params, reqProps); if (!res.contains("This may take a few seconds")) { throw new IOException("Error placing call"); } } // ------------------ // UTILS // ------------------ private String load(String location) throws IOException { Map<String, String> reqProps = new HashMap<String, String>(); reqProps.put("Authorization", "GoogleLogin auth="+auth); return NetUtil.doGet(location,null,reqProps,Constants.UTF8); } private String extractAuth(String res) throws IOException { String retVal = null; BufferedReader reader = new BufferedReader(new StringReader(res)); String line = null; while ((line = reader.readLine()) != null) { if (line.contains("Auth=")) { retVal = line.split("=", 2)[1].trim(); } } if (retVal == null) { throw new IOException("Unable to login to GoogleVoice [1]"); } return retVal; } private void extractJsonInfo() throws IOException { String json = load("https://www.google.com/voice/"); json = json.substring(json.indexOf("_gcData = ") + 10); json = json.substring(0, json.indexOf("};") + 1); try { JSONObject jobj = new JSONObject(json); rnr = jobj.getString("_rnr_se"); phoneNumber = PhoneUtil.normalizeNumber(jobj.getJSONObject("number").getString("formatted")); JSONObject jphones = jobj.getJSONObject("phones"); @SuppressWarnings("unchecked") Iterator<String> phoneKeys = jphones.keys(); while (phoneKeys.hasNext()) { String phoneKey = phoneKeys.next(); JSONObject jphone = jphones.getJSONObject(phoneKey); GoogleVoicePhone phone = new GoogleVoicePhone(); phone.setName(jphone.getString("name")); phone.setNumber(PhoneUtil.normalizeNumber(jphone.getString("phoneNumber"))); phone.setType("" + jphone.getInt("type")); phones.add(phone); } } catch (JSONException e) { throw new IOException(e); } } protected void ensureLoggedIn() throws IOException { if (auth == null) { login(); } } }