Skip to content

Commit

Permalink
Added back message quoting
Browse files Browse the repository at this point in the history
  • Loading branch information
Auties00 committed Jan 11, 2024
1 parent 911e1bf commit 8b98248
Show file tree
Hide file tree
Showing 16 changed files with 192 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ public static CompanionDevice web() {

public static CompanionDevice ios(boolean business) {
return new CompanionDevice(
"iPhone_X",
"iPhone_15_Pro_Max",
"Apple",
business ? PlatformType.IOS_BUSINESS : PlatformType.IOS,
"16.5.1"
"17.1.1"
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public ButtonsResponseMessage(String buttonId, String buttonText, ContextInfo co
public static ButtonsResponseMessage of(ChatMessageInfo quoted, Button button) {
return new ButtonsResponseMessageBuilder()
.buttonId(button.id())
.buttonText(button.bodyText().map(ButtonText::content))
.buttonText(button.bodyText().map(ButtonText::content).orElse(null))
.contextInfo(ContextInfo.of(quoted))
.responseType(button.bodyType() == ButtonBody.Type.TEXT ? ResponseType.SELECTED_DISPLAY_TEXT : ResponseType.UNKNOWN)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ public InteractiveMessage(InteractiveHeader header, InteractiveBody body, Intera
static InteractiveMessage simpleBuilder(InteractiveHeader header, String body, String footer, InteractiveMessageContent content, ContextInfo contextInfo) {
var builder = new InteractiveMessageBuilder()
.header(header)
.body(InteractiveBody.ofNullable(body))
.footer(InteractiveFooter.ofNullable(footer))
.body(InteractiveBody.ofNullable(body).orElse(null))
.footer(InteractiveFooter.ofNullable(footer).orElse(null))
.contextInfo(contextInfo);
switch (content) {
case InteractiveShop interactiveShop -> builder.contentShop(interactiveShop);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,10 +447,10 @@ public Message content() {
*
* @return a non-null Optional ContextualMessage
*/
public Optional<ContextualMessage> contentWithContext() {
public Optional<ContextualMessage<?>> contentWithContext() {
return Optional.of(content())
.filter(entry -> entry instanceof ContextualMessage)
.map(entry -> (ContextualMessage) entry);
.map(entry -> (ContextualMessage<?>) entry);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ public final class ContactMessage implements ContextualMessage<ContactMessage> {
@ProtobufProperty(index = 17, type = ProtobufType.OBJECT)
private ContextInfo contextInfo;

public static ContactMessage of(String name, ContactCard vcard) {
return new ContactMessage(name, vcard, null);
}

public ContactMessage(String name, ContactCard vcard, ContextInfo contextInfo) {
this.name = name;
this.vcard = vcard;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ public final class PollCreationMessage implements ContextualMessage<PollCreation
private ContextInfo contextInfo;

@ProtobufProperty(index = 999, type = ProtobufType.MAP, keyType = ProtobufType.STRING, valueType = ProtobufType.OBJECT)
private final Map<String, PollOption> selectableOptionsMap;
final Map<String, PollOption> selectableOptionsMap;

@ProtobufProperty(index = 1000, type = ProtobufType.OBJECT)
private final List<SelectedPollOption> selectedOptions;
final List<SelectedPollOption> selectedOptions;

public PollCreationMessage(byte[] encryptionKey, String title, List<PollOption> selectableOptions, int selectableOptionsCount, ContextInfo contextInfo, Map<String, PollOption> selectableOptionsMap, List<SelectedPollOption> selectedOptions) {
this.encryptionKey = encryptionKey;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package it.auties.whatsapp.model.response;

import com.fasterxml.jackson.annotation.JsonCreator;
import it.auties.whatsapp.model.signal.auth.Version;

import java.util.List;
import java.util.Map;
import java.util.Optional;

public final class IosVersionResponse {
private static final IosVersionResponse EMPTY = new IosVersionResponse(null);
private final Version version;
IosVersionResponse(Version version) {
this.version = version;
}

@SuppressWarnings("unchecked")
@JsonCreator
public static IosVersionResponse of(Map<String, Object> json) {
var results = (List<Map<String, Object>>) json.get("results");
if (results.isEmpty()) {
return EMPTY;
}

var result = (String) results.getFirst().get("version");
if(result == null) {
return EMPTY;
}

return new IosVersionResponse(Version.of("2." + result));
}

public Optional<Version> version() {
return Optional.of(version);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
import java.util.stream.Collectors;

public final class HttpRegistration {
static {
Authenticator.setDefault(new ProxyAuthenticator());
}

private static final int TIMEOUT_SECONDS = 10;

private final HttpClient httpClient;
Expand All @@ -53,7 +57,7 @@ public HttpRegistration(Store store, Keys keys, AsyncVerificationCodeSupplier co
this.method = method;
this.httpClient = createClient();
var platform = store.device().platform();
this.apnsClient = platform.isIOS() && method != VerificationCodeMethod.NONE ? new ApnsClient(store.proxy().orElse(null)) : null;
this.apnsClient = platform.isIOS() && method != VerificationCodeMethod.NONE ? new ApnsClient() : null;
}

public CompletableFuture<Void> registerPhoneNumber() {
Expand Down Expand Up @@ -309,7 +313,6 @@ private Entry<String, Object>[] getRequestVerificationCodeParameters(ExistsRespo
};
}


private CompletionStage<Void> onCodeRequestSent(ExistsResponse existsResponse, VerificationCodeError lastError, HttpResponse<String> result) {
if (result.statusCode() != HttpURLConnection.HTTP_OK) {
throw new RegistrationException(null, result.body());
Expand Down Expand Up @@ -350,20 +353,6 @@ public CompletableFuture<Void> sendVerificationCode() {
});
}

private String padCountryCodeValue(String inputString) {
if (inputString.length() >= 3) {
return inputString;
}

var stringBuilder = new StringBuilder();
while (stringBuilder.length() < 3 - inputString.length()) {
stringBuilder.append('0');
}

stringBuilder.append(inputString);
return stringBuilder.toString();
}

private void saveRegistrationStatus(Store store, Keys keys, boolean registered) {
keys.setRegistered(registered);
if (registered) {
Expand Down
81 changes: 61 additions & 20 deletions src/main/java/it/auties/whatsapp/registration/TokenProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import it.auties.whatsapp.model.business.BusinessVerifiedNameCertificateSpec;
import it.auties.whatsapp.model.business.BusinessVerifiedNameDetailsBuilder;
import it.auties.whatsapp.model.business.BusinessVerifiedNameDetailsSpec;
import it.auties.whatsapp.model.response.IosVersionResponse;
import it.auties.whatsapp.model.response.WebVersionResponse;
import it.auties.whatsapp.model.signal.auth.UserAgent;
import it.auties.whatsapp.model.signal.auth.UserAgent.PlatformType;
Expand Down Expand Up @@ -53,9 +54,10 @@ public final class TokenProvider {
}

private static volatile Version webVersion;
private static volatile Version iosVersion;
private static volatile WhatsappApk cachedApk;
private static volatile WhatsappApk cachedBusinessApk;
private static volatile Version personalIosVersion;
private static volatile Version businessIosVersion;
private static volatile WhatsappApk personalApk;
private static volatile WhatsappApk businessApk;

private static Path androidCache = Path.of(System.getProperty("user.home") + "/.cobalt/token/android");

Expand All @@ -72,33 +74,72 @@ public static CompletableFuture<Version> getVersion(UserAgent.PlatformType platf
return getVersion(platform, true);
}

private static CompletableFuture<Version> getVersion(UserAgent.PlatformType platform, boolean useJarCache) {
private static CompletableFuture<Version> getVersion(UserAgent.PlatformType platform, boolean useCache) {
return switch (platform) {
case WEB, WINDOWS, MACOS ->
getWebVersion();
case ANDROID, ANDROID_BUSINESS ->
getAndroidData(platform.isBusiness(), useJarCache).thenApply(WhatsappApk::version);
case IOS, IOS_BUSINESS ->
CompletableFuture.completedFuture(platform.isBusiness() ? Whatsapp.DEFAULT_MOBILE_BUSINESS_IOS_VERSION : Whatsapp.DEFAULT_MOBILE_IOS_VERSION); // Fetching the latest ios version is harder than one might hope
getAndroidData(platform.isBusiness(), useCache).thenApply(WhatsappApk::version);
case IOS ->
getIosVersion(false);
case IOS_BUSINESS ->
getIosVersion(true);
case KAIOS ->
CompletableFuture.completedFuture(Whatsapp.DEFAULT_MOBILE_KAIOS_VERSION);
default -> throw new IllegalStateException("Unsupported mobile os: " + platform);
};
}

private static CompletableFuture<Version> getWebVersion() {
private static CompletableFuture<Version> getIosVersion(boolean business) {
if (business && businessIosVersion != null) {
return CompletableFuture.completedFuture(businessIosVersion);
}

if (!business && personalIosVersion != null) {
return CompletableFuture.completedFuture(personalIosVersion);
}

try (var client = HttpClient.newHttpClient()) {
if (webVersion != null) {
return CompletableFuture.completedFuture(webVersion);
}
var request = HttpRequest.newBuilder()
.GET()
.header("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0")
.uri(URI.create(business ? Whatsapp.MOBILE_BUSINESS_IOS_URL : Whatsapp.MOBILE_IOS_URL))
.build();
return client.sendAsync(request, ofString())
.thenApplyAsync(response -> {
var result = Json.readValue(response.body(), IosVersionResponse.class)
.version()
.orElseThrow();
if(business) {
businessIosVersion = result;
}else {
personalIosVersion = result;
}
System.out.println("Result: " + result);

return result;
});
} catch (Throwable throwable) {
throw new RuntimeException("Cannot fetch latest web version", throwable);
}
}

private static CompletableFuture<Version> getWebVersion() {
if (webVersion != null) {
return CompletableFuture.completedFuture(webVersion);
}


try (var client = HttpClient.newHttpClient()) {
var request = HttpRequest.newBuilder()
.GET()
.uri(URI.create(Whatsapp.WEB_UPDATE_URL))
.build();
return client.sendAsync(request, ofString())
.thenApplyAsync(response -> Json.readValue(response.body(), WebVersionResponse.class))
.thenApplyAsync(version -> webVersion = Version.of(version.currentVersion()));
.thenApplyAsync(response -> {
var webVersionResponse = Json.readValue(response.body(), WebVersionResponse.class);
return webVersion = Version.of(webVersionResponse.currentVersion());
});
} catch (Throwable throwable) {
throw new RuntimeException("Cannot fetch latest web version", throwable);
}
Expand Down Expand Up @@ -165,12 +206,12 @@ private static String getAndroidToken(String phoneNumber, WhatsappApk whatsappDa
}

private static CompletableFuture<WhatsappApk> getAndroidData(boolean business, boolean useJarCache) {
if (!business && cachedApk != null) {
return CompletableFuture.completedFuture(cachedApk);
if (!business && personalApk != null) {
return CompletableFuture.completedFuture(personalApk);
}

if (business && cachedBusinessApk != null) {
return CompletableFuture.completedFuture(cachedBusinessApk);
if (business && businessApk != null) {
return CompletableFuture.completedFuture(businessApk);
}

return getCachedApk(business, useJarCache)
Expand All @@ -179,7 +220,7 @@ private static CompletableFuture<WhatsappApk> getAndroidData(boolean business, b
}

public static CompletableFuture<WhatsappApk> downloadWhatsappApk(boolean business) {
return Medias.downloadAsync(business ? Whatsapp.MOBILE_BUSINESS_DOWNLOAD_URL : Whatsapp.MOBILE_DOWNLOAD_URL)
return Medias.downloadAsync(business ? Whatsapp.MOBILE_BUSINESS_ANDROID_URL : Whatsapp.MOBILE_ANDROID_URL)
.thenApplyAsync(result -> getAndroidData(result, business));
}

Expand Down Expand Up @@ -227,12 +268,12 @@ private static WhatsappApk getAndroidData(byte[] apk, boolean business) {
if (business) {
var result = new WhatsappApk(version, md5Hash, secretKey.getEncoded(), certificates, true);
cacheWhatsappData(result);
return cachedBusinessApk = result;
return businessApk = result;
}

var result = new WhatsappApk(version, md5Hash, secretKey.getEncoded(), certificates, false);
cacheWhatsappData(result);
return cachedApk = result;
return personalApk = result;
} catch (IOException | GeneralSecurityException exception) {
throw new RuntimeException("Cannot extract certificates from APK", exception);
}
Expand Down
Loading

0 comments on commit 8b98248

Please sign in to comment.