Update libsignal-service
This commit is contained in:
		
							parent
							
								
									69a9b30732
								
							
						
					
					
						commit
						db2182aa7d
					
				| @ -90,6 +90,10 @@ | ||||
|   "name":"org.signal.libsignal.internal.CompletableFuture", | ||||
|   "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"complete","parameterTypes":["java.lang.Object"] }, {"name":"completeExceptionally","parameterTypes":["java.lang.Throwable"] }] | ||||
| }, | ||||
| { | ||||
|   "name":"org.signal.libsignal.internal.NativeHandleGuard$SimpleOwner", | ||||
|   "methods":[{"name":"unsafeNativeHandleWithoutGuard","parameterTypes":[] }] | ||||
| }, | ||||
| { | ||||
|   "name":"org.signal.libsignal.net.CdsiLookupResponse", | ||||
|   "methods":[{"name":"<init>","parameterTypes":["java.util.Map","int"] }] | ||||
|  | ||||
| @ -39,6 +39,9 @@ | ||||
| { | ||||
|   "name":"[Ljava.sql.Statement;" | ||||
| }, | ||||
| { | ||||
|   "name":"[Lorg.asamk.signal.commands.ListStickerPacksCommand$JsonStickerPack$JsonSticker;" | ||||
| }, | ||||
| { | ||||
|   "name":"[Lorg.asamk.signal.json.JsonAttachment;" | ||||
| }, | ||||
| @ -2302,7 +2305,7 @@ | ||||
|   "allDeclaredFields":true, | ||||
|   "allDeclaredMethods":true, | ||||
|   "allDeclaredConstructors":true, | ||||
|   "methods":[{"name":"getAnnouncementGroup","parameterTypes":[] }, {"name":"getChangeNumber","parameterTypes":[] }, {"name":"getDeleteSync","parameterTypes":[] }, {"name":"getGiftBadges","parameterTypes":[] }, {"name":"getPaymentActivation","parameterTypes":[] }, {"name":"getPni","parameterTypes":[] }, {"name":"getSenderKey","parameterTypes":[] }, {"name":"getStorage","parameterTypes":[] }, {"name":"getStorageServiceEncryptionV2","parameterTypes":[] }, {"name":"getStories","parameterTypes":[] }, {"name":"getVersionedExpirationTimer","parameterTypes":[] }] | ||||
|   "methods":[{"name":"getAnnouncementGroup","parameterTypes":[] }, {"name":"getAttachmentBackfill","parameterTypes":[] }, {"name":"getChangeNumber","parameterTypes":[] }, {"name":"getDeleteSync","parameterTypes":[] }, {"name":"getGiftBadges","parameterTypes":[] }, {"name":"getPaymentActivation","parameterTypes":[] }, {"name":"getPni","parameterTypes":[] }, {"name":"getSenderKey","parameterTypes":[] }, {"name":"getStorage","parameterTypes":[] }, {"name":"getStorageServiceEncryptionV2","parameterTypes":[] }, {"name":"getStories","parameterTypes":[] }, {"name":"getVersionedExpirationTimer","parameterTypes":[] }] | ||||
| }, | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.api.account.ChangePhoneNumberRequest", | ||||
| @ -2329,6 +2332,13 @@ | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.api.groupsv2.TemporalCredential[]" | ||||
| }, | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.api.keys.OneTimePreKeyCounts", | ||||
|   "allDeclaredFields":true, | ||||
|   "queryAllDeclaredMethods":true, | ||||
|   "queryAllDeclaredConstructors":true, | ||||
|   "methods":[{"name":"<init>","parameterTypes":[] }] | ||||
| }, | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.api.link.LinkedDeviceVerificationCodeResponse", | ||||
|   "allDeclaredFields":true, | ||||
| @ -2396,7 +2406,14 @@ | ||||
|   "name":"org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite", | ||||
|   "allDeclaredFields":true, | ||||
|   "allDeclaredMethods":true, | ||||
|   "allDeclaredConstructors":true | ||||
|   "allDeclaredConstructors":true, | ||||
|   "methods":[{"name":"<init>","parameterTypes":["java.lang.String","byte[]","byte[]","byte[]","byte[]","byte[]","boolean","boolean","byte[]","java.util.List"] }, {"name":"getAbout","parameterTypes":[] }, {"name":"getAboutEmoji","parameterTypes":[] }, {"name":"getAvatar","parameterTypes":[] }, {"name":"getBadgeIds","parameterTypes":[] }, {"name":"getCommitment","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPaymentAddress","parameterTypes":[] }, {"name":"getPhoneNumberSharing","parameterTypes":[] }, {"name":"getSameAvatar","parameterTypes":[] }, {"name":"getVersion","parameterTypes":[] }] | ||||
| }, | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.api.provisioning.ProvisioningMessage", | ||||
|   "allDeclaredFields":true, | ||||
|   "queryAllDeclaredMethods":true, | ||||
|   "queryAllDeclaredConstructors":true | ||||
| }, | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.api.push.ServiceId", | ||||
| @ -2441,6 +2458,12 @@ | ||||
|   "queryAllDeclaredConstructors":true, | ||||
|   "methods":[{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String"] }] | ||||
| }, | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.api.ratelimit.SubmitRecaptchaChallengePayload", | ||||
|   "allDeclaredFields":true, | ||||
|   "queryAllDeclaredMethods":true, | ||||
|   "queryAllDeclaredConstructors":true | ||||
| }, | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.api.storage.StorageAuthResponse", | ||||
|   "allDeclaredFields":true, | ||||
| @ -2965,6 +2988,7 @@ | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.internal.storage.protos.AccountRecord", | ||||
|   "allDeclaredFields":true, | ||||
|   "fields":[{"name":"avatarColor"}, {"name":"avatarUrlPath"}, {"name":"backupSubscriberData"}, {"name":"backupTier"}, {"name":"displayBadgesOnProfile"}, {"name":"e164"}, {"name":"familyName"}, {"name":"givenName"}, {"name":"hasBackup"}, {"name":"hasCompletedUsernameOnboarding"}, {"name":"hasSeenGroupStoryEducationSheet"}, {"name":"hasSetMyStoriesPrivacy"}, {"name":"hasViewedOnboardingStory"}, {"name":"keepMutedChatsArchived"}, {"name":"linkPreviews"}, {"name":"noteToSelfArchived"}, {"name":"noteToSelfMarkedUnread"}, {"name":"payments"}, {"name":"phoneNumberSharingMode"}, {"name":"pinnedConversations"}, {"name":"preferContactAvatars"}, {"name":"preferredReactionEmoji"}, {"name":"primarySendsSms"}, {"name":"profileKey"}, {"name":"readReceipts"}, {"name":"sealedSenderIndicators"}, {"name":"storiesDisabled"}, {"name":"storyViewReceiptsEnabled"}, {"name":"subscriberCurrencyCode"}, {"name":"subscriberId"}, {"name":"subscriptionManuallyCancelled"}, {"name":"typingIndicators"}, {"name":"universalExpireTimer"}, {"name":"unlistedPhoneNumber"}, {"name":"username"}, {"name":"usernameLink"}], | ||||
|   "methods":[{"name":"adapter","parameterTypes":[] }, {"name":"unknownFields","parameterTypes":[] }] | ||||
| }, | ||||
| { | ||||
| @ -3027,6 +3051,7 @@ | ||||
| { | ||||
|   "name":"org.whispersystems.signalservice.internal.storage.protos.GroupV2Record", | ||||
|   "allDeclaredFields":true, | ||||
|   "fields":[{"name":"archived"}, {"name":"avatarColor"}, {"name":"blocked"}, {"name":"dontNotifyForMentionsIfMuted"}, {"name":"hideStory"}, {"name":"markedUnread"}, {"name":"masterKey"}, {"name":"mutedUntilTimestamp"}, {"name":"storySendMode"}, {"name":"whitelisted"}], | ||||
|   "methods":[{"name":"adapter","parameterTypes":[] }, {"name":"unknownFields","parameterTypes":[] }] | ||||
| }, | ||||
| { | ||||
|  | ||||
| @ -10,7 +10,7 @@ slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } | ||||
| slf4j-jul = { module = "org.slf4j:jul-to-slf4j", version.ref = "slf4j" } | ||||
| logback = "ch.qos.logback:logback-classic:1.5.18" | ||||
| 
 | ||||
| signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_120" | ||||
| signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_121" | ||||
| sqlite = "org.xerial:sqlite-jdbc:3.49.1.0" | ||||
| hikari = "com.zaxxer:HikariCP:6.3.0" | ||||
| junit-jupiter = "org.junit.jupiter:junit-jupiter:5.12.0" | ||||
|  | ||||
| @ -30,7 +30,8 @@ public class ServiceConfig { | ||||
|     public static AccountAttributes.Capabilities getCapabilities(boolean isPrimaryDevice) { | ||||
|         final var deleteSync = !isPrimaryDevice; | ||||
|         final var storageEncryptionV2 = !isPrimaryDevice; | ||||
|         return new AccountAttributes.Capabilities(true, deleteSync, true, storageEncryptionV2); | ||||
|         final var attachmentBackfill = !isPrimaryDevice; | ||||
|         return new AccountAttributes.Capabilities(true, deleteSync, true, storageEncryptionV2, attachmentBackfill); | ||||
|     } | ||||
| 
 | ||||
|     public static ServiceEnvironmentConfig getServiceEnvironmentConfig( | ||||
|  | ||||
| @ -11,17 +11,19 @@ import org.signal.libsignal.protocol.state.PreKeyRecord; | ||||
| import org.signal.libsignal.protocol.state.SignedPreKeyRecord; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.whispersystems.signalservice.api.NetworkResultUtil; | ||||
| import org.whispersystems.signalservice.api.account.PreKeyUpload; | ||||
| import org.whispersystems.signalservice.api.keys.OneTimePreKeyCounts; | ||||
| import org.whispersystems.signalservice.api.push.ServiceIdType; | ||||
| import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; | ||||
| import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; | ||||
| import org.whispersystems.signalservice.internal.push.OneTimePreKeyCounts; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_STALE_AGE; | ||||
| import static org.asamk.signal.manager.config.ServiceConfig.SIGNED_PREKEY_ROTATE_AGE; | ||||
| import static org.asamk.signal.manager.util.Utils.handleResponseException; | ||||
| 
 | ||||
| public class PreKeyHelper { | ||||
| 
 | ||||
| @ -82,7 +84,7 @@ public class PreKeyHelper { | ||||
|     ) throws IOException { | ||||
|         OneTimePreKeyCounts preKeyCounts; | ||||
|         try { | ||||
|             preKeyCounts = dependencies.getAccountManager().getPreKeyCounts(serviceIdType); | ||||
|             preKeyCounts = handleResponseException(dependencies.getKeysApi().getAvailablePreKeyCounts(serviceIdType)); | ||||
|         } catch (AuthorizationFailedException e) { | ||||
|             logger.debug("Failed to get pre key count, ignoring: " + e.getClass().getSimpleName()); | ||||
|             preKeyCounts = new OneTimePreKeyCounts(0, 0); | ||||
| @ -143,7 +145,7 @@ public class PreKeyHelper { | ||||
|                 kyberPreKeyRecords); | ||||
|         var needsReset = false; | ||||
|         try { | ||||
|             dependencies.getAccountManager().setPreKeys(preKeyUpload); | ||||
|             NetworkResultUtil.toPreKeysLegacy(dependencies.getKeysApi().setPreKeys(preKeyUpload)); | ||||
|             try { | ||||
|                 if (preKeyRecords != null) { | ||||
|                     account.addPreKeys(serviceIdType, preKeyRecords); | ||||
|  | ||||
| @ -23,6 +23,7 @@ import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential; | ||||
| import org.signal.libsignal.zkgroup.profiles.ProfileKey; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.whispersystems.signalservice.api.NetworkResultUtil; | ||||
| import org.whispersystems.signalservice.api.crypto.SealedSenderAccess; | ||||
| import org.whispersystems.signalservice.api.profiles.AvatarUploadParams; | ||||
| import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; | ||||
| @ -196,9 +197,10 @@ public final class ProfileHelper { | ||||
|                         : avatar == null ? AvatarUploadParams.unchanged(true) : AvatarUploadParams.unchanged(false); | ||||
|                 final var paymentsAddress = Optional.ofNullable(newProfile.getMobileCoinAddress()) | ||||
|                         .map(address -> PaymentUtils.signPaymentsAddress(address, | ||||
|                                 account.getAciIdentityKeyPair().getPrivateKey())); | ||||
|                                 account.getAciIdentityKeyPair().getPrivateKey())) | ||||
|                         .orElse(null); | ||||
|                 logger.debug("Uploading new profile"); | ||||
|                 final var avatarPath = dependencies.getAccountManager() | ||||
|                 final var avatarPath = NetworkResultUtil.toSetProfileLegacy(dependencies.getProfileApi() | ||||
|                         .setVersionedProfile(account.getAci(), | ||||
|                                 account.getProfileKey(), | ||||
|                                 newProfile.getInternalServiceName(), | ||||
| @ -208,9 +210,9 @@ public final class ProfileHelper { | ||||
|                                 avatarUploadParams, | ||||
|                                 List.of(/* TODO implement support for badges */), | ||||
|                                 account.getConfigurationStore().getPhoneNumberSharingMode() | ||||
|                                         == PhoneNumberSharingMode.EVERYBODY); | ||||
|                                         == PhoneNumberSharingMode.EVERYBODY)); | ||||
|                 if (!avatarUploadParams.keepTheSame) { | ||||
|                     builder.withAvatarUrlPath(avatarPath.orElse(null)); | ||||
|                     builder.withAvatarUrlPath(avatarPath); | ||||
|                 } | ||||
|                 newProfile = builder.build(); | ||||
|             } | ||||
|  | ||||
| @ -18,6 +18,8 @@ import java.io.IOException; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| 
 | ||||
| import static org.asamk.signal.manager.util.Utils.handleResponseException; | ||||
| 
 | ||||
| public class UnidentifiedAccessHelper { | ||||
| 
 | ||||
|     private static final Logger logger = LoggerFactory.getLogger(UnidentifiedAccessHelper.class); | ||||
| @ -109,7 +111,8 @@ public class UnidentifiedAccessHelper { | ||||
|             return privacySenderCertificate.getSerialized(); | ||||
|         } | ||||
|         try { | ||||
|             final var certificate = dependencies.getAccountManager().getSenderCertificateForPhoneNumberPrivacy(); | ||||
|             final var certificate = handleResponseException(dependencies.getCertificateApi() | ||||
|                     .getSenderCertificateForPhoneNumberPrivacy()); | ||||
|             privacySenderCertificate = new SenderCertificate(certificate); | ||||
|             return certificate; | ||||
|         } catch (IOException | InvalidCertificateException e) { | ||||
| @ -125,7 +128,7 @@ public class UnidentifiedAccessHelper { | ||||
|             return senderCertificate.getSerialized(); | ||||
|         } | ||||
|         try { | ||||
|             final var certificate = dependencies.getAccountManager().getSenderCertificate(); | ||||
|             final var certificate = handleResponseException(dependencies.getCertificateApi().getSenderCertificate()); | ||||
|             this.senderCertificate = new SenderCertificate(certificate); | ||||
|             return certificate; | ||||
|         } catch (IOException | InvalidCertificateException e) { | ||||
|  | ||||
| @ -14,12 +14,17 @@ import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; | ||||
| import org.whispersystems.signalservice.api.SignalServiceMessageSender; | ||||
| import org.whispersystems.signalservice.api.SignalSessionLock; | ||||
| import org.whispersystems.signalservice.api.account.AccountApi; | ||||
| import org.whispersystems.signalservice.api.attachment.AttachmentApi; | ||||
| import org.whispersystems.signalservice.api.cds.CdsApi; | ||||
| import org.whispersystems.signalservice.api.certificate.CertificateApi; | ||||
| import org.whispersystems.signalservice.api.crypto.SignalServiceCipher; | ||||
| import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations; | ||||
| import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api; | ||||
| import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations; | ||||
| import org.whispersystems.signalservice.api.keys.KeysApi; | ||||
| import org.whispersystems.signalservice.api.link.LinkDeviceApi; | ||||
| import org.whispersystems.signalservice.api.message.MessageApi; | ||||
| import org.whispersystems.signalservice.api.profiles.ProfileApi; | ||||
| import org.whispersystems.signalservice.api.push.ServiceIdType; | ||||
| import org.whispersystems.signalservice.api.push.SignalServiceAddress; | ||||
| import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi; | ||||
| @ -68,6 +73,10 @@ public class SignalDependencies { | ||||
|     private RegistrationApi registrationApi; | ||||
|     private LinkDeviceApi linkDeviceApi; | ||||
|     private StorageServiceApi storageServiceApi; | ||||
|     private CertificateApi certificateApi; | ||||
|     private AttachmentApi attachmentApi; | ||||
|     private MessageApi messageApi; | ||||
|     private KeysApi keysApi; | ||||
|     private GroupsV2Operations groupsV2Operations; | ||||
|     private ClientZkOperations clientZkOperations; | ||||
| 
 | ||||
| @ -80,6 +89,7 @@ public class SignalDependencies { | ||||
| 
 | ||||
|     private List<SecureValueRecovery> secureValueRecovery; | ||||
|     private ProfileService profileService; | ||||
|     private ProfileApi profileApi; | ||||
| 
 | ||||
|     SignalDependencies( | ||||
|             final ServiceEnvironmentConfig serviceEnvironmentConfig, | ||||
| @ -174,7 +184,8 @@ public class SignalDependencies { | ||||
| 
 | ||||
|     public SignalServiceAccountManager getAccountManager() { | ||||
|         return getOrCreate(() -> accountManager, | ||||
|                 () -> accountManager = new SignalServiceAccountManager(getAccountApi(), | ||||
|                 () -> accountManager = new SignalServiceAccountManager(getAuthenticatedSignalWebSocket(), | ||||
|                         getAccountApi(), | ||||
|                         getPushServiceSocket(), | ||||
|                         getGroupsV2Operations())); | ||||
|     } | ||||
| @ -231,6 +242,27 @@ public class SignalDependencies { | ||||
|         return new StorageServiceRepository(getStorageServiceApi()); | ||||
|     } | ||||
| 
 | ||||
|     public CertificateApi getCertificateApi() { | ||||
|         return getOrCreate(() -> certificateApi, | ||||
|                 () -> certificateApi = new CertificateApi(getAuthenticatedSignalWebSocket())); | ||||
|     } | ||||
| 
 | ||||
|     public AttachmentApi getAttachmentApi() { | ||||
|         return getOrCreate(() -> attachmentApi, | ||||
|                 () -> attachmentApi = new AttachmentApi(getAuthenticatedSignalWebSocket(), getPushServiceSocket())); | ||||
|     } | ||||
| 
 | ||||
|     public MessageApi getMessageApi() { | ||||
|         return getOrCreate(() -> messageApi, | ||||
|                 () -> messageApi = new MessageApi(getAuthenticatedSignalWebSocket(), | ||||
|                         getUnauthenticatedSignalWebSocket())); | ||||
|     } | ||||
| 
 | ||||
|     public KeysApi getKeysApi() { | ||||
|         return getOrCreate(() -> keysApi, | ||||
|                 () -> keysApi = new KeysApi(getAuthenticatedSignalWebSocket(), getUnauthenticatedSignalWebSocket())); | ||||
|     } | ||||
| 
 | ||||
|     public GroupsV2Operations getGroupsV2Operations() { | ||||
|         return getOrCreate(() -> groupsV2Operations, | ||||
|                 () -> groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()), | ||||
| @ -289,8 +321,9 @@ public class SignalDependencies { | ||||
|                 () -> messageSender = new SignalServiceMessageSender(getPushServiceSocket(), | ||||
|                         dataStore, | ||||
|                         sessionLock, | ||||
|                         getAuthenticatedSignalWebSocket(), | ||||
|                         getUnauthenticatedSignalWebSocket(), | ||||
|                         getAttachmentApi(), | ||||
|                         getMessageApi(), | ||||
|                         getKeysApi(), | ||||
|                         Optional.empty(), | ||||
|                         executor, | ||||
|                         ServiceConfig.MAX_ENVELOPE_SIZE)); | ||||
| @ -304,10 +337,14 @@ public class SignalDependencies { | ||||
|                         .toList()); | ||||
|     } | ||||
| 
 | ||||
|     public ProfileApi getProfileApi() { | ||||
|         return getOrCreate(() -> profileApi, | ||||
|                 () -> profileApi = new ProfileApi(getAuthenticatedSignalWebSocket(), getPushServiceSocket())); | ||||
|     } | ||||
| 
 | ||||
|     public ProfileService getProfileService() { | ||||
|         return getOrCreate(() -> profileService, | ||||
|                 () -> profileService = new ProfileService(getClientZkProfileOperations(), | ||||
|                         getMessageReceiver(), | ||||
|                         getAuthenticatedSignalWebSocket(), | ||||
|                         getUnauthenticatedSignalWebSocket())); | ||||
|     } | ||||
|  | ||||
| @ -7,6 +7,7 @@ import org.signal.libsignal.protocol.fingerprint.NumericFingerprintGenerator; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.whispersystems.signalservice.api.NetworkResult; | ||||
| import org.whispersystems.signalservice.api.NetworkResultUtil; | ||||
| import org.whispersystems.signalservice.api.push.ServiceId; | ||||
| import org.whispersystems.signalservice.api.util.StreamDetails; | ||||
| 
 | ||||
| @ -154,19 +155,7 @@ public class Utils { | ||||
|     } | ||||
| 
 | ||||
|     public static <T> T handleResponseException(final NetworkResult<T> response) throws IOException { | ||||
|         final var throwableOptional = response.getCause(); | ||||
|         if (throwableOptional != null) { | ||||
|             if (throwableOptional instanceof IOException ioException) { | ||||
|                 throw ioException; | ||||
|             } else { | ||||
|                 throw new IOException(throwableOptional); | ||||
|             } | ||||
|         } | ||||
|         try { | ||||
|             return response.successOrThrow(); | ||||
|         } catch (Throwable e) { | ||||
|             throw new AssertionError(e); | ||||
|         } | ||||
|         return NetworkResultUtil.toBasicLegacy(response); | ||||
|     } | ||||
| 
 | ||||
|     public static ByteString firstNonEmpty(ByteString... strings) { | ||||
|  | ||||
| @ -141,6 +141,7 @@ exec 3> "$FIFO_FILE" | ||||
|   echo '{"jsonrpc":"2.0","id":"id","method":"listGroups"}' >&3 | ||||
|   echo '{"jsonrpc":"2.0","id":"id","method":"listDevices"}' >&3 | ||||
|   echo '{"jsonrpc":"2.0","id":"id","method":"listIdentities"}' >&3 | ||||
|   echo '{"jsonrpc":"2.0","id":"id","method":"listStickerPacks"}' >&3 | ||||
|   echo '{"jsonrpc":"2.0","id":"id","method":"sendSyncRequest"}' >&3 | ||||
|   echo '{"jsonrpc":"2.0","id":"id","method":"sendContacts"}' >&3 | ||||
|   echo '{"jsonrpc":"2.0","id":"id","method":"version"}' >&3 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 AsamK
						AsamK