Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.synyx.matrix.bot.domain.MatrixTextMessage;
import org.synyx.matrix.bot.domain.MatrixUserId;
import org.synyx.matrix.bot.internal.api.dto.ClientEventDto;
import org.synyx.matrix.bot.internal.api.dto.MembershipStateDto;
import org.synyx.matrix.bot.internal.api.dto.StrippedStateEventDto;
import org.synyx.matrix.bot.internal.api.dto.SyncResponseDto;
import org.synyx.matrix.bot.internal.api.dto.event.MemberEventContentDto;
Expand Down Expand Up @@ -184,15 +185,29 @@ private void notifyAboutMemberEvent(MatrixState state, MatrixRoom room, ClientEv
throw new RuntimeException(e);
}

final var maybePreviousContent = getPreviousContent(event, MemberEventContentDto.class);

// > If not present, the user's previous membership must be assumed as leave.
final var previousMembership =
maybePreviousContent
.flatMap(
memberEventContentDto -> Optional.ofNullable(memberEventContentDto.membership()))
.filter(membershipStateDto -> membershipStateDto != MembershipStateDto.UNKNOWN)
.orElse(MembershipStateDto.LEAVE);

final var sender = MatrixUserId.from(event.sender()).orElseThrow(IllegalStateException::new);

try {
if (content.membership() == MemberEventContentDto.MembershipState.LEAVE
|| content.membership() == MemberEventContentDto.MembershipState.BAN) {
consumer.onUserLeaveRoom(state, room, sender);
} else if (content.membership() == MemberEventContentDto.MembershipState.JOIN
if (content.membership() == MembershipStateDto.LEAVE
|| content.membership() == MembershipStateDto.BAN) {
if (previousMembership == MembershipStateDto.JOIN) {
consumer.onUserLeaveRoom(state, room, sender);
}
} else if (content.membership() == MembershipStateDto.JOIN
&& !sender.equals(state.getOwnUserId())) {
consumer.onUserJoinRoom(state, room, sender);
if (previousMembership == MembershipStateDto.LEAVE) {
consumer.onUserJoinRoom(state, room, sender);
}
}
} catch (Exception e) {
LOG.error("Uncaught exception when consuming member event", e);
Expand All @@ -213,7 +228,7 @@ private void notifyAboutInviteEvent(
throw new RuntimeException(e);
}

if (messageEventContent.membership() != MemberEventContentDto.MembershipState.INVITE) {
if (messageEventContent.membership() != MembershipStateDto.INVITE) {
return;
}

Expand All @@ -235,4 +250,22 @@ private void notifyAboutInviteEvent(
LOG.error("Uncaught exception when consuming room invite", e);
}
}

private <T> Optional<T> getPreviousContent(ClientEventDto event, Class<T> clazz) {

final var maybeJson =
Optional.ofNullable(event)
.flatMap(clientEventDto -> Optional.ofNullable(clientEventDto.unsigned()))
.flatMap(unsignedDataDto -> Optional.ofNullable(unsignedDataDto.prevContent()));

if (maybeJson.isEmpty()) {
return Optional.empty();
}

try {
return Optional.ofNullable(objectMapper.treeToValue(maybeJson.get(), clazz));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.synyx.matrix.bot.domain.MatrixUser;
import org.synyx.matrix.bot.domain.MatrixUserId;
import org.synyx.matrix.bot.internal.api.dto.ClientEventDto;
import org.synyx.matrix.bot.internal.api.dto.MembershipStateDto;
import org.synyx.matrix.bot.internal.api.dto.StrippedStateEventDto;
import org.synyx.matrix.bot.internal.api.dto.SyncResponseDto;
import org.synyx.matrix.bot.internal.api.dto.event.CanonicalAliasEventContentDto;
Expand Down Expand Up @@ -156,13 +157,13 @@ private void handleCanonicalAliasEvent(MatrixRoom room, CanonicalAliasEventConte
private void handleMemberEvent(
MatrixRoom room, MatrixUserId sender, MemberEventContentDto content) {

if (content.membership() == MemberEventContentDto.MembershipState.JOIN) {
if (content.membership() == MembershipStateDto.JOIN) {
final var user = getOrCreateUserInRoom(room, sender);
if (content.displayName() != null) {
user.setDisplayName(content.displayName());
}
} else if (content.membership() == MemberEventContentDto.MembershipState.LEAVE
|| content.membership() == MemberEventContentDto.MembershipState.BAN) {
} else if (content.membership() == MembershipStateDto.LEAVE
|| content.membership() == MembershipStateDto.BAN) {
room.getRoomUsers().removeIf(user -> user.getId().equals(sender));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public record ClientEventDto(
@JsonProperty("origin_server_ts") long originServerTs,
String sender,
@JsonProperty("state_key") String stateKey,
String type) {}
String type,
UnsignedDataDto unsigned) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.synyx.matrix.bot.internal.api.dto;

import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import com.fasterxml.jackson.annotation.JsonProperty;

public enum MembershipStateDto {
@JsonEnumDefaultValue
UNKNOWN,

@JsonProperty("invite")
INVITE,
@JsonProperty("join")
JOIN,
@JsonProperty("leave")
LEAVE,
@JsonProperty("ban")
BAN,
@JsonProperty("knock")
KNOCK
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.synyx.matrix.bot.internal.api.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;

public record UnsignedDataDto(
long age,
MembershipStateDto membership,
@JsonProperty("prev_content") JsonNode prevContent,
@JsonProperty("transaction_id") String transactionId) {}
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
package org.synyx.matrix.bot.internal.api.dto.event;

import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.synyx.matrix.bot.internal.api.dto.MembershipStateDto;

public record MemberEventContentDto(
@JsonProperty("displayname") String displayName, MembershipState membership) {
@JsonProperty("displayname") String displayName, MembershipStateDto membership) {

public static final String TYPE = "m.room.member";

public enum MembershipState {
@JsonEnumDefaultValue
UNKNOWN,

@JsonProperty("invite")
INVITE,
@JsonProperty("join")
JOIN,
@JsonProperty("leave")
LEAVE,
@JsonProperty("ban")
BAN,
@JsonProperty("knock")
KNOCK
}
}