Skip to content

Instantly share code, notes, and snippets.

@Erezbiox1
Created November 8, 2017 10:50
Show Gist options
  • Save Erezbiox1/68c1b453269ef5b24bac25714414022e to your computer and use it in GitHub Desktop.
Save Erezbiox1/68c1b453269ef5b24bac25714414022e to your computer and use it in GitHub Desktop.
package com.erezbiox1.lidorclient.Utils;
import com.samczsun.skype4j.Skype;
import com.samczsun.skype4j.exceptions.ConnectionException;
import com.samczsun.skype4j.exceptions.InvalidCredentialsException;
import com.samczsun.skype4j.exceptions.NotParticipatingException;
import com.samczsun.skype4j.exceptions.handler.ErrorHandler;
import com.samczsun.skype4j.exceptions.handler.ErrorSource;
import com.samczsun.skype4j.internal.Endpoints;
import com.samczsun.skype4j.internal.SkypeThreadFactory;
import com.samczsun.skype4j.internal.client.FullClient;
import com.samczsun.skype4j.internal.threads.AuthenticationChecker;
import com.samczsun.skype4j.internal.threads.ServerPingThread;
import okhttp3.*;
import org.apache.commons.lang3.StringEscapeUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import java.net.HttpURLConnection;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
public class MSFTSkypeClient extends FullClient {
public MSFTSkypeClient(String skypeToken, String skypeId,
Set<String> resources, Logger customLogger,
List<ErrorHandler> errorHandlers) {
super(skypeId, null, resources, customLogger, errorHandlers);
setSkypeToken(skypeToken);
}
@Override
public void login() {
try {
HttpURLConnection asmResponse = null;
try {
asmResponse = this.getAsmToken();
} catch (ConnectionException e) {
throw new RuntimeException(e);
}
String[] setCookie = asmResponse.getHeaderField("Set-Cookie").split(";")[0].split("=");
//this.cookies.put(setCookie[0], setCookie[1]);
loadAllContacts();
try {
this.getContactRequests(false);
} catch (Exception var2) {
this.handleError(ErrorSource.UPDATING_CONTACT_LIST, var2, false);
}
try {
this.registerWebSocket();
} catch (Exception var2) {
this.handleError(ErrorSource.REGISTERING_WEBSOCKET, var2, false);
}
registerEndpoint();
Endpoints.ELIGIBILITY_CHECK.open(this, new Object[0]).expect(200, "You are not eligible to use Skype for Web!").get();
this.loggedIn.set(true);
if(this.serverPingThread != null) {
this.serverPingThread.kill();
this.serverPingThread = null;
}
if(this.reauthThread != null) {
this.reauthThread.kill();
this.reauthThread = null;
}
if(this.scheduler != null) {
this.scheduler.shutdownNow();
while(true) {
if(!this.scheduler.isTerminated()) {
continue;
}
}
}
this.shutdownThread = Executors.newSingleThreadExecutor(new SkypeThreadFactory(this, "Shutdown"));
this.scheduler = Executors.newFixedThreadPool(4, new SkypeThreadFactory(this, "Poller"));
(this.serverPingThread = new ServerPingThread(this)).start();
(this.reauthThread = new AuthenticationChecker(this)).start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// I override this for high-level login stuff
@Override
public void reauthenticate() throws ConnectionException, InvalidCredentialsException, NotParticipatingException {
doShutdown();
login();
if(subscribed.get())
subscribe();
}
public static class Builder {
private final String skypeToken;
private final String skypeId;
private Set<String> resources = new HashSet();
private List<ErrorHandler> errorHandlers = new ArrayList();
private Logger customLogger;
public Builder(String skypeToken, String skypeId) {
this.skypeToken = skypeToken;
this.skypeId = skypeId;
}
public Builder withAllResources() {
this.resources.addAll(Arrays.asList(new String[]{"/v1/users/ME/conversations/ALL/properties", "/v1/users/ME/conversations/ALL/messages", "/v1/users/ME/contacts/ALL", "/v1/threads/ALL"}));
return this;
}
public Builder withResource(String resource) {
this.resources.add(resource);
return this;
}
public Builder withLogger(Logger logger) {
this.customLogger = logger;
return this;
}
public Builder withExceptionHandler(ErrorHandler errorHandler) {
this.errorHandlers.add(errorHandler);
return this;
}
public Skype build() {
if(this.resources.isEmpty()) {
throw new IllegalArgumentException("No resources selected");
} else if(this.skypeToken != null) {
return new MSFTSkypeClient(this.skypeToken, this.skypeId, this.resources, this.customLogger, this.errorHandlers);
} else {
throw new IllegalArgumentException("No skype token specified");
}
}
}
static class LiveLoginHelper {
protected static class FailureReason extends Exception {
private final String reason;
private final String code;
protected FailureReason(String reason, String code) {
this.reason = reason;
this.code = code;
}
public String getCode() {
return code;
}
public String getReason() {
return reason;
}
@Override
public String getMessage() {
return String.format("%s: %s", this.code, this.reason);
}
}
private static Map<String, String> parsePayload(String payload) throws Exception {
JSONObject response = org.json.XML
.toJSONObject(payload)
.getJSONObject("S:Envelope")
.getJSONObject("S:Body");
if (!(response.isNull("S:Fault"))) {
String reason = response
.getJSONObject("S:Fault")
.getJSONObject("S:Reason")
.getJSONObject("S:Text")
.getString("content");
String code = response
.getJSONObject("S:Fault")
.getJSONObject("S:Detail")
.getJSONObject("psf:error")
.getString("psf:value");
throw new FailureReason(reason, code);
}
JSONObject a = response
.getJSONObject("wst:RequestSecurityTokenResponseCollection");
JSONArray array = a.get("wst:RequestSecurityTokenResponse") instanceof JSONArray
? (JSONArray) a.get("wst:RequestSecurityTokenResponse")
: new JSONArray(Arrays.asList(a.get("wst:RequestSecurityTokenResponse")));
Map<String, String> tokens = new LinkedHashMap<>();
array.forEach((Object obj) -> {
JSONObject json = (JSONObject) obj;
String content = json.getJSONObject("wst:RequestedSecurityToken")
.getJSONObject("wsse:BinarySecurityToken")
.getString("content")
.replaceAll("&p=", "")
.replaceAll("t=", "");
String key = json.getJSONObject("wsp:AppliesTo")
.getJSONObject("wsa:EndpointReference")
.getString("wsa:Address")
.replaceAll("&p=", "")
.replaceAll("t=", "");
tokens.put(key, content);
});
return tokens;
}
private static JSONObject getXTokenObjectFromAccess(String s) throws Exception {
Connection.Response response = Jsoup.connect(RPS)
.method(Connection.Method.POST)
.data("scopes", "client")
.data("clientVersion", "0/7.18.0.112//")
.data("access_token", s)
.data("partner", "999")
.data("site_name", "lw")
.ignoreContentType(true)
.execute();
return new JSONObject(response.body());
}
public static JSONObject getXTokenObject(String email, String password) throws Exception {
OkHttpClient client = new OkHttpClient();
MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("application/json; charset=utf-8");
String created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.format(new Date(System.currentTimeMillis()));
String expires = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.format(new Date(System.currentTimeMillis() + (1000L * 60L * 60L * 24L * 14L)));
String payload = String.format(LiveLoginHelper.SOAP_PAYLOAD,
StringEscapeUtils.escapeXml11(email),
StringEscapeUtils.escapeXml11(password),
StringEscapeUtils.escapeXml11(created),
StringEscapeUtils.escapeXml11(expires)
);
Request request = new Request.Builder()
.url(LiveLoginHelper.SOAP_URL)
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, payload))
.build();
Response response = client.newCall(request).execute();
if (response.code() == 200) {
Map<String, String> parsedTokens = parsePayload(response.body().string());
if (parsedTokens.containsKey(SCOPE)) {
return getXTokenObjectFromAccess(parsedTokens.get(SCOPE));
} else {
throw new Exception("Deprecated key");
}
} else {
throw new Exception("Bad response");
}
}
//<editor-fold desc="Constants">
public static final String SCOPE = "lw.skype.com";
public static final String RPS = "https://api.skype.com/rps/skypetoken";
public static final String SOAP_URL = "https://login.live.com:443/RST2.srf";
public static final String SOAP_PAYLOAD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" xmlns:wsa=\"http://www.w3.org/2005/08/addressing\" xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2005/02/sc\" xmlns:wst=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">\n" +
" <s:Header>\n" +
" <wsa:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>\n" +
" <wsa:To s:mustUnderstand=\"1\">HTTPS://login.live.com:443//RST2.srf</wsa:To>\n" +
" <wsa:MessageID>0</wsa:MessageID>\n" +
" <ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">\n" +
" <ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>\n" +
" <ps:BinaryVersion>5</ps:BinaryVersion>\n" +
" <ps:UIVersion>1</ps:UIVersion>\n" +
" <ps:Cookies />\n" +
" <ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>\n" +
" </ps:AuthInfo>\n" +
" <wsse:Security>\n" +
" <wsse:UsernameToken Id=\"user\">\n" +
" <wsse:Username>%s</wsse:Username>\n" +
" <wsse:Password>%s</wsse:Password>\n" +
" </wsse:UsernameToken>\n" +
" <wsu:Timestamp Id=\"Timestamp\">\n" +
" <wsu:Created>%s</wsu:Created>\n" +
" <wsu:Expires>%s</wsu:Expires>\n" +
" </wsu:Timestamp>\n" +
" </wsse:Security>\n" +
" </s:Header>\n" +
" <s:Body>\n" +
" <ps:RequestMultipleSecurityTokens xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"RSTS\">\n" +
" <wst:RequestSecurityToken Id=\"RST0\">\n" +
" <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>\n" +
" <wsp:AppliesTo>\n" +
" <wsa:EndpointReference>\n" +
" <wsa:Address>" + SCOPE + "</wsa:Address>\n" +
" </wsa:EndpointReference>\n" +
" </wsp:AppliesTo>\n" +
" <wsp:PolicyReference URI=\"MBI_SSL\" />\n" +
" </wst:RequestSecurityToken>\n" +
" </ps:RequestMultipleSecurityTokens>\n" +
" </s:Body>\n" +
"</s:Envelope>";
//</editor-fold>
}
public static Skype login(String email, String password){
Skype client = null;
try {
JSONObject object = LiveLoginHelper.getXTokenObject(email, password);
String skypeToken = object.getString("skypetoken");
String skypeId = object.getString("skypeid");
client = new MSFTSkypeClient.Builder(skypeToken, skypeId)
.withLogger(Logger.getGlobal())
//.withExceptionHandler(handler)
.withAllResources().build();
}catch (Exception e){
e.printStackTrace();
}
return client;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment