package mobileCheckiner;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.StatusLine;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import util.Util;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CodingErrorAction;
import java.util.ArrayList;
import java.util.List;
public class MobileCheckiner
{
private static Logger logger;
private String email;
private String password;
private URI xiamiHomeURI;
private DefaultHttpClient client;
private CookieStore cookies;
public MobileCheckiner(String email, String password) throws URISyntaxException
{
logger = LogManager.getLogger("mobileCheckiner.MobileCheckiner");
this.email = email;
this.password = password;
this.client = new DefaultHttpClient();
this.cookies = new BasicCookieStore();
this.client.setCookieStore(this.cookies);
URIBuilder builder = new URIBuilder();
builder.setScheme("http").setHost("www.xiami.com").setPath("/");
this.xiamiHomeURI = builder.build();
File logDir = new File("log");
if (!logDir.exists())
{
logDir.mkdir();
}
}
public void checkin() throws ClientProtocolException, URISyntaxException, IOException
{
logger.trace("------------------------------------------");
logger.info("Start xiami checkin process...");
try
{
this.loginToXiami();
String homePageResponse = this.gotoHomePage();
if(!this.isAlreadyCheckedIn(homePageResponse))
{
this.sendCheckinRequest(this.extractCheckinUrl(homePageResponse));
if(this.isAlreadyCheckedIn(this.gotoHomePage()))
{
logger.info("Checkin successful!");
}
}
}
catch (HttpResponseIndicatesErrorException e)
{
logger.error(e.getMessage());
}
catch (CheckinUrlExtractionFailure e)
{
logger.error(e.getMessage());
}
finally
{
logger.info("Xiami checkin process ended.");
logger.trace("------------------------------------------");
}
}
private void loginToXiami() throws URISyntaxException, ClientProtocolException, IOException, HttpResponseIndicatesErrorException
{
logger.info("Login to xiami...");
URIBuilder builder = new URIBuilder(this.xiamiHomeURI);
builder.setPath("/web/login");
List<NameValuePair> formParams = new ArrayList<NameValuePair>();
formParams.add(new BasicNameValuePair("email", this.email));
formParams.add(new BasicNameValuePair("password", this.password));
formParams.add(new BasicNameValuePair("LoginButton", "%E7%99%BB%E5%BD%95"));
UrlEncodedFormEntity contentEntity = new UrlEncodedFormEntity(formParams, "UTF-8");
contentEntity.setContentType("application/x-www-form-urlencoded");
HttpPost request = new HttpPost(builder.build());
this.addUserAgentHeaderToRequest(request);
request.setEntity(contentEntity);
this.writeHtmlToFile(Util.filePathCombine("log", "LoginPageRequest.html"), this.getRequestAllHeadersAndContentAsString(request));
HttpResponse response = this.client.execute(request);
StatusLine responseStatusLine = response.getStatusLine();
if(this.isError(responseStatusLine))
{
throw new HttpResponseIndicatesErrorException(String.format("Login response indicates error! Status line: %s", responseStatusLine.toString()));
}
this.writeHtmlToFile(Util.filePathCombine("log", "LoginPageResponse.html"), this.getResponseAllHeadersAndContentAsString(response));
request.releaseConnection();
logger.info("Login successful.");
}
private void sendCheckinRequest(String checkinUrl) throws URISyntaxException, ClientProtocolException, IOException, HttpResponseIndicatesErrorException
{
logger.info("Send checkin request...");
URIBuilder builder = new URIBuilder(this.xiamiHomeURI);
builder.setPath(checkinUrl);
HttpGet request = new HttpGet(builder.build());
this.addUserAgentHeaderToRequest(request);
HttpResponse response = this.client.execute(request);
StatusLine responseStatusLine = response.getStatusLine();
if(this.isError(responseStatusLine))
{
throw new HttpResponseIndicatesErrorException(String.format("Checkin response indicates error! Status line: %s", responseStatusLine.toString()));
}
this.writeHtmlToFile(Util.filePathCombine("log", "CheckinResponse.html"), this.getResponseAllHeadersAndContentAsString(response));
request.releaseConnection();
logger.info("Got checkin response.");
}
private String gotoHomePage() throws URISyntaxException, ClientProtocolException, IOException, HttpResponseIndicatesErrorException
{
logger.info("Requesting home page...");
URIBuilder builder = new URIBuilder(this.xiamiHomeURI);
builder.setPath("/web");
HttpGet request = new HttpGet(builder.build());
this.addUserAgentHeaderToRequest(request);
HttpResponse response = this.client.execute(request);
StatusLine responseStatusLine = response.getStatusLine();
if(this.isError(responseStatusLine))
{
throw new HttpResponseIndicatesErrorException(String.format("Home page response indicates error! Status line: %s", responseStatusLine.toString()));
}
String responseAsString = this.getResponseAllHeadersAndContentAsString(response);
this.writeHtmlToFile(Util.filePathCombine("log", "HomePageResponse.html"), responseAsString);
request.releaseConnection();
logger.info("Got home page response.");
return responseAsString;
}
private boolean isAlreadyCheckedIn(String homePageResponseAsString)
{
Pattern pattern = Pattern.compile("<div class=\"idh\">已连续签到(\\d+)天</div>");
Matcher matcher = pattern.matcher(homePageResponseAsString);
if(matcher.find())
{
logger.info(String.format("Already checked in today, %s days in total!", matcher.group(1)));
return true;
}
else
{
Pattern pattern1 = Pattern.compile("t_sign_auth=([^;]+);");
Matcher matcher1 = pattern1.matcher(homePageResponseAsString);
if(matcher1.find())
{
logger.info(String.format("Not checked in today yet, already checked in for %s days!", matcher1.group(1)));
}
else
{
logger.info("Not checked in today yet, don't know how many days already checked in!");
}
return false;
}
}
private String extractCheckinUrl(String homePageResponseAsString) throws CheckinUrlExtractionFailure
{
logger.info("Extracting checkin url...");
Pattern pattern = Pattern.compile("<a class=\"check_in\" href=\"([^\"]+)\">");
Matcher matcher = pattern.matcher(homePageResponseAsString);
if(matcher.find())
{
logger.info("Checkin url obtained.");
return matcher.group(1);
}
else
{
throw new CheckinUrlExtractionFailure("Fail to extract checkin url!");
}
}
private boolean isError(StatusLine responseStatusLine)
{
int statusCode = responseStatusLine.getStatusCode();
return statusCode >= 400 && statusCode < 600;
}
private void addUserAgentHeaderToRequest(HttpRequestBase request)
{
request.addHeader("User-Agent", "Mozilla/5.0");
}
private String getRequestAllHeadersAndContentAsString(HttpEntityEnclosingRequestBase request) throws ParseException, IOException
{
StringBuffer requestAsString = new StringBuffer();
for(Header header : request.getAllHeaders())
{
requestAsString.append((header.toString()));
requestAsString.append("\r\n");
}
HttpEntity contentEntity = request.getEntity();
requestAsString.append(EntityUtils.toString(contentEntity));
return requestAsString.toString();
}
private String getResponseAllHeadersAndContentAsString(HttpResponse response) throws ParseException, IOException
{
StringBuffer responseAsString = new StringBuffer(response.getStatusLine().toString());
responseAsString.append("\r\n");
for(Header header : response.getAllHeaders())
{
responseAsString.append(header.toString());
responseAsString.append("\r\n");
}
HttpEntity contentEntity = response.getEntity();
responseAsString.append(EntityUtils.toString(contentEntity));
return responseAsString.toString();
}
private void writeHtmlToFile(String filePath, String content) throws IOException
{
CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
encoder.onMalformedInput(CodingErrorAction.REPORT);
encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath, false), encoder));
out.write(content);
out.close();
}
}