import org.asamk.Signal;
import org.asamk.signal.DbusConfig;
import org.asamk.signal.manager.Manager;
+import org.asamk.signal.manager.api.AlreadyReceivingException;
import org.asamk.signal.manager.api.AttachmentInvalidException;
import org.asamk.signal.manager.api.CaptchaRequiredException;
import org.asamk.signal.manager.api.Configuration;
import org.asamk.signal.manager.api.UpdateGroup;
import org.asamk.signal.manager.api.UpdateProfile;
import org.asamk.signal.manager.api.UserStatus;
+import org.asamk.signal.manager.api.UsernameLinkUrl;
import org.freedesktop.dbus.DBusMap;
import org.freedesktop.dbus.DBusPath;
import org.freedesktop.dbus.connections.impl.DBusConnection;
import org.freedesktop.dbus.exceptions.DBusException;
+import org.freedesktop.dbus.exceptions.DBusExecutionException;
import org.freedesktop.dbus.interfaces.DBusInterface;
import org.freedesktop.dbus.interfaces.DBusSigHandler;
import org.freedesktop.dbus.types.Variant;
}
@Override
- public void updateAccountAttributes(final String deviceName) throws IOException {
+ public void updateAccountAttributes(
+ final String deviceName, final Boolean unrestrictedUnidentifiedSender
+ ) throws IOException {
if (deviceName != null) {
final var devicePath = signal.getThisDevice();
getRemoteObject(devicePath, Signal.Device.class).Set("org.asamk.Signal.Device", "Name", deviceName);
}
@Override
- public void updateConfiguration(Configuration newConfiguration) throws IOException {
+ public void updateConfiguration(Configuration newConfiguration) {
final var configuration = getRemoteObject(new DBusPath(signal.getObjectPath() + "/Configuration"),
Signal.Configuration.class);
newConfiguration.readReceipts()
}
@Override
- public String setUsername(final String username) throws IOException, InvalidUsernameException {
+ public String getUsername() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public UsernameLinkUrl getUsernameLink() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setUsername(final String username) throws IOException, InvalidUsernameException {
throw new UnsupportedOperationException();
}
public SendGroupMessageResults quitGroup(
final GroupId groupId, final Set<RecipientIdentifier.Single> groupAdmins
) throws GroupNotFoundException, IOException, NotAGroupMemberException, LastGroupAdminException {
- if (groupAdmins.size() > 0) {
+ if (!groupAdmins.isEmpty()) {
throw new UnsupportedOperationException();
}
final var group = getRemoteObject(signal.getGroup(groupId.serialize()), Signal.Group.class);
@Override
public Pair<GroupId, SendGroupMessageResults> joinGroup(final GroupInviteLinkUrl inviteLinkUrl) throws IOException, InactiveGroupLinkException {
- final var newGroupId = signal.joinGroup(inviteLinkUrl.getUrl());
- return new Pair<>(GroupId.unknownVersion(newGroupId), new SendGroupMessageResults(0, List.of()));
+ try {
+ final var newGroupId = signal.joinGroup(inviteLinkUrl.getUrl());
+ return new Pair<>(GroupId.unknownVersion(newGroupId), new SendGroupMessageResults(0, List.of()));
+ } catch (DBusExecutionException e) {
+ throw new IOException("Failed to join group: " + e.getMessage() + " (" + e.getClass().getSimpleName() + ")",
+ e);
+ }
}
@Override
@Override
public SendMessageResults sendMessage(
- final Message message, final Set<RecipientIdentifier> recipients
+ final Message message, final Set<RecipientIdentifier> recipients, final boolean notifySelf
) throws IOException, AttachmentInvalidException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException {
return handleMessage(recipients,
numbers -> signal.sendMessage(message.messageText(), message.attachments(), numbers),
return new SendMessageResults(0, Map.of());
}
+ public void hideRecipient(final RecipientIdentifier.Single recipient) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public void deleteRecipient(final RecipientIdentifier.Single recipient) {
signal.deleteRecipient(recipient.getIdentifier());
if (isWeakListener) {
weakHandlers.add(handler);
} else {
- if (messageHandlers.size() == 0) {
+ if (messageHandlers.isEmpty()) {
installMessageHandlers();
}
messageHandlers.add(handler);
synchronized (messageHandlers) {
weakHandlers.remove(handler);
messageHandlers.remove(handler);
- if (messageHandlers.size() == 0) {
+ if (messageHandlers.isEmpty()) {
uninstallMessageHandlers();
}
}
@Override
public boolean isReceiving() {
synchronized (messageHandlers) {
- return messageHandlers.size() > 0;
+ return !messageHandlers.isEmpty();
}
}
+ private Thread receiveThread;
+
@Override
public void receiveMessages(
Optional<Duration> timeout, Optional<Integer> maxMessages, ReceiveMessageHandler handler
- ) throws IOException {
+ ) throws IOException, AlreadyReceivingException {
+ if (receiveThread != null) {
+ throw new AlreadyReceivingException("Already receiving message.");
+ }
+ receiveThread = Thread.currentThread();
+
final var remainingMessages = new AtomicInteger(maxMessages.orElse(-1));
final var lastMessage = new AtomicLong(System.currentTimeMillis());
final var thread = Thread.currentThread();
}
Thread.sleep(sleepTimeRemaining);
} catch (InterruptedException ignored) {
+ break;
}
}
} else {
}
removeReceiveHandler(receiveHandler);
+ receiveThread = null;
+ }
+
+ @Override
+ public void stopReceiveMessages() {
+ if (receiveThread != null) {
+ receiveThread.interrupt();
+ }
}
@Override
return null;
}
final var contactName = signal.getContactName(n);
- if (onlyContacts && contactName.length() == 0) {
+ if (onlyContacts && contactName.isEmpty()) {
return null;
}
if (name.isPresent() && !name.get().equals(contactName)) {
}
return Recipient.newBuilder()
.withAddress(new RecipientAddress(null, n))
- .withContact(new Contact(contactName, null, null, 0, contactBlocked, false, false))
+ .withContact(new Contact(contactName, null, null, 0, contactBlocked, false, false, false))
.build();
}).filter(Objects::nonNull).toList();
}
this.notify();
}
synchronized (messageHandlers) {
- if (messageHandlers.size() > 0) {
+ if (!messageHandlers.isEmpty()) {
uninstallMessageHandlers();
}
weakHandlers.clear();
.map(RecipientIdentifier.Single.class::cast)
.map(RecipientIdentifier.Single::getIdentifier)
.toList();
- if (singleRecipients.size() > 0) {
+ if (!singleRecipients.isEmpty()) {
timestamp = recipientsHandler.apply(singleRecipients);
}
Optional.empty(),
Optional.empty(),
List.of(),
- List.of(),
+ getMentions(extras),
List.of(),
List.of())),
Optional.empty(),
Optional.empty(),
Optional.empty(),
List.of(),
- List.of(),
+ getMentions(extras),
List.of(),
List.of()))),
Optional.empty(),
Optional.empty(),
Optional.empty(),
List.of(),
- List.of(),
+ getMentions(extras),
List.of(),
List.of())),
Optional.empty(),
};
connection.addSigHandler(Signal.SyncMessageReceivedV2.class, signal, this.dbusSyncHandler);
} catch (DBusException e) {
- e.printStackTrace();
+ throw new RuntimeException(e);
}
signal.subscribeReceive();
}
connection.removeSigHandler(Signal.ReceiptReceivedV2.class, signal, this.dbusRcptHandler);
connection.removeSigHandler(Signal.SyncMessageReceivedV2.class, signal, this.dbusSyncHandler);
} catch (DBusException e) {
- e.printStackTrace();
+ throw new RuntimeException(e);
}
}
}).toList();
}
+ private List<MessageEnvelope.Data.Mention> getMentions(final Map<String, Variant<?>> extras) {
+ if (!extras.containsKey("mentions")) {
+ return List.of();
+ }
+
+ final List<DBusMap<String, Variant<?>>> mentions = getValue(extras, "mentions");
+ return mentions.stream()
+ .map(a -> new MessageEnvelope.Data.Mention(new RecipientAddress(null, getValue(a, "recipient")),
+ getValue(a, "start"),
+ getValue(a, "length")))
+ .toList();
+ }
+
@Override
public InputStream retrieveAttachment(final String id) throws IOException {
throw new UnsupportedOperationException();