Skip to content

Commit c1241bf

Browse files
committed
Add method for adding reactions
1 parent 66cd528 commit c1241bf

File tree

3 files changed

+146
-98
lines changed

3 files changed

+146
-98
lines changed

src/main/java/org/synyx/matrix/bot/MatrixClient.java

Lines changed: 107 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -7,144 +7,153 @@
77
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
88
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
99
import lombok.extern.slf4j.Slf4j;
10+
import org.synyx.matrix.bot.domain.MatrixEventId;
1011
import org.synyx.matrix.bot.domain.MatrixRoomId;
1112
import org.synyx.matrix.bot.domain.MatrixUserId;
1213
import org.synyx.matrix.bot.internal.MatrixAuthentication;
1314
import org.synyx.matrix.bot.internal.MatrixEventNotifier;
1415
import org.synyx.matrix.bot.internal.MatrixStateSynchronizer;
1516
import org.synyx.matrix.bot.internal.api.MatrixApi;
1617
import org.synyx.matrix.bot.internal.api.dto.MessageDto;
18+
import org.synyx.matrix.bot.internal.api.dto.ReactionDto;
19+
import org.synyx.matrix.bot.internal.api.dto.ReactionRelatesToDto;
1720

1821
import java.util.Optional;
1922

2023
@Slf4j
2124
public class MatrixClient {
2225

23-
private final MatrixAuthentication authentication;
24-
private final ObjectMapper objectMapper;
25-
private final MatrixApi api;
26-
private MatrixState state;
27-
private MatrixStateSynchronizer stateSynchronizer;
28-
private MatrixPersistedState persistedState;
29-
private MatrixEventNotifier eventNotifier;
30-
private boolean interruptionRequested;
31-
32-
public MatrixClient(String hostname, String username, String password) {
33-
34-
this.authentication = new MatrixAuthentication(username, password);
35-
this.objectMapper = JsonMapper.builder()
36-
.addModule(new Jdk8Module())
37-
.addModule(new JavaTimeModule())
38-
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
39-
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
40-
.build();
41-
this.api = new MatrixApi(hostname, authentication, objectMapper);
42-
this.state = null;
43-
this.eventNotifier = null;
44-
this.interruptionRequested = false;
26+
private final MatrixAuthentication authentication;
27+
private final ObjectMapper objectMapper;
28+
private final MatrixApi api;
29+
private MatrixState state;
30+
private MatrixStateSynchronizer stateSynchronizer;
31+
private MatrixPersistedState persistedState;
32+
private MatrixEventNotifier eventNotifier;
33+
private boolean interruptionRequested;
34+
35+
public MatrixClient(String hostname, String username, String password) {
36+
37+
this.authentication = new MatrixAuthentication(username, password);
38+
this.objectMapper = JsonMapper.builder()
39+
.addModule(new Jdk8Module())
40+
.addModule(new JavaTimeModule())
41+
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
42+
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
43+
.build();
44+
this.api = new MatrixApi(hostname, authentication, objectMapper);
45+
this.state = null;
46+
this.eventNotifier = null;
47+
this.interruptionRequested = false;
48+
}
49+
50+
public void setEventCallback(MatrixEventConsumer eventConsumer) {
51+
52+
this.eventNotifier = MatrixEventNotifier.from(objectMapper, eventConsumer).orElse(null);
53+
}
54+
55+
public void setPersistedState(MatrixPersistedState persistedState) {
56+
57+
this.persistedState = persistedState;
58+
}
59+
60+
public void requestStopOfSync() {
61+
62+
interruptionRequested = true;
63+
api.terminateOpenConnections();
64+
}
65+
66+
public void syncContinuous() {
67+
68+
if (!authentication.isAuthenticated()) {
69+
if (api.login()) {
70+
log.info("Successfully logged in to matrix server as {}",
71+
authentication.getUserId()
72+
.map(MatrixUserId::toString)
73+
.orElse("UNKNOWN")
74+
);
75+
} else {
76+
return;
77+
}
4578
}
4679

47-
public void setEventCallback(MatrixEventConsumer eventConsumer) {
80+
state = new MatrixState(authentication.getUserId().orElseThrow(IllegalStateException::new));
81+
stateSynchronizer = new MatrixStateSynchronizer(state, objectMapper);
4882

49-
this.eventNotifier = MatrixEventNotifier.from(objectMapper, eventConsumer).orElse(null);
50-
}
51-
52-
public void setPersistedState(MatrixPersistedState persistedState) {
83+
var maybeSyncResponse = api.syncFull();
84+
String lastBatch;
85+
if (maybeSyncResponse.isPresent()) {
86+
final var syncResponse = maybeSyncResponse.get();
87+
lastBatch = syncResponse.nextBatch();
5388

54-
this.persistedState = persistedState;
89+
stateSynchronizer.synchronizeState(syncResponse);
90+
} else {
91+
log.error("Failed to perform initial sync");
92+
return;
5593
}
5694

57-
public void requestStopOfSync() {
58-
59-
interruptionRequested = true;
60-
api.terminateOpenConnections();
95+
if (eventNotifier != null) {
96+
eventNotifier.getConsumer().onConnected(state);
6197
}
6298

63-
public void syncContinuous() {
64-
65-
if (!authentication.isAuthenticated()) {
66-
if (api.login()) {
67-
log.info("Successfully logged in to matrix server as {}",
68-
authentication.getUserId()
69-
.map(MatrixUserId::toString)
70-
.orElse("UNKNOWN")
71-
);
72-
} else {
73-
return;
74-
}
75-
}
76-
77-
state = new MatrixState(authentication.getUserId().orElseThrow(IllegalStateException::new));
78-
stateSynchronizer = new MatrixStateSynchronizer(state, objectMapper);
99+
if (persistedState != null) {
100+
final var maybePersistedLastBatch = persistedState.getLastBatch();
101+
if (maybePersistedLastBatch.isPresent()) {
102+
lastBatch = maybePersistedLastBatch.get();
103+
} else {
104+
persistedState.setLastBatch(lastBatch);
105+
}
106+
}
79107

80-
var maybeSyncResponse = api.syncFull();
81-
String lastBatch;
82-
if (maybeSyncResponse.isPresent()) {
83-
final var syncResponse = maybeSyncResponse.get();
84-
lastBatch = syncResponse.nextBatch();
108+
while (!interruptionRequested) {
109+
maybeSyncResponse = api.sync(lastBatch);
110+
if (maybeSyncResponse.isPresent()) {
111+
final var syncResponse = maybeSyncResponse.get();
112+
lastBatch = syncResponse.nextBatch();
85113

86-
stateSynchronizer.synchronizeState(syncResponse);
87-
} else {
88-
log.error("Failed to perform initial sync");
89-
return;
90-
}
114+
stateSynchronizer.synchronizeState(syncResponse);
91115

92116
if (eventNotifier != null) {
93-
eventNotifier.getConsumer().onConnected(state);
117+
eventNotifier.notifyFromSynchronizationResponse(state, syncResponse);
94118
}
95119

96120
if (persistedState != null) {
97-
final var maybePersistedLastBatch = persistedState.getLastBatch();
98-
if (maybePersistedLastBatch.isPresent()) {
99-
lastBatch = maybePersistedLastBatch.get();
100-
} else {
101-
persistedState.setLastBatch(lastBatch);
102-
}
121+
persistedState.setLastBatch(lastBatch);
103122
}
123+
}
124+
}
104125

105-
while (!interruptionRequested) {
106-
maybeSyncResponse = api.sync(lastBatch);
107-
if (maybeSyncResponse.isPresent()) {
108-
final var syncResponse = maybeSyncResponse.get();
109-
lastBatch = syncResponse.nextBatch();
110-
111-
stateSynchronizer.synchronizeState(syncResponse);
112-
113-
if (eventNotifier != null) {
114-
eventNotifier.notifyFromSynchronizationResponse(state, syncResponse);
115-
}
126+
interruptionRequested = false;
127+
}
116128

117-
if (persistedState != null) {
118-
persistedState.setLastBatch(lastBatch);
119-
}
120-
}
121-
}
129+
public boolean isConnected() {
122130

123-
interruptionRequested = false;
124-
}
131+
return state != null;
132+
}
125133

126-
public boolean isConnected() {
134+
public Optional<MatrixState> getState() {
127135

128-
return state != null;
129-
}
136+
return Optional.ofNullable(state);
137+
}
130138

131-
public Optional<MatrixState> getState() {
139+
public boolean sendMessage(MatrixRoomId roomId, String messageBody) {
132140

133-
return Optional.ofNullable(state);
134-
}
141+
return api.sendEvent(roomId.getFormatted(), "m.room.message", new MessageDto(messageBody, "m.text"));
142+
}
135143

136-
public boolean sendMessage(MatrixRoomId roomId, String messageBody) {
144+
public boolean addReaction(MatrixRoomId roomId, MatrixEventId eventId, String reaction) {
137145

138-
return api.sendEvent(roomId.getFormatted(), "m.room.message", new MessageDto(messageBody, "m.text"));
139-
}
146+
final var reactionDto = new ReactionDto(new ReactionRelatesToDto(eventId.getFormatted(), reaction));
147+
return api.sendEvent(roomId.getFormatted(), "m.reaction", reactionDto);
148+
}
140149

141-
public boolean joinRoom(MatrixRoomId roomId) {
150+
public boolean joinRoom(MatrixRoomId roomId) {
142151

143-
return api.joinRoom(roomId.getFormatted(), "hello there");
144-
}
152+
return api.joinRoom(roomId.getFormatted(), "hello there");
153+
}
145154

146-
public boolean leaveRoom(MatrixRoomId roomId) {
155+
public boolean leaveRoom(MatrixRoomId roomId) {
147156

148-
return api.leaveRoom(roomId.getFormatted(), "bai");
149-
}
157+
return api.leaveRoom(roomId.getFormatted(), "bai");
158+
}
150159
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.synyx.matrix.bot.internal.api.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
@Data
9+
@NoArgsConstructor
10+
@AllArgsConstructor
11+
public class ReactionDto {
12+
13+
@JsonProperty("m.relates_to")
14+
private ReactionRelatesToDto relatesTo;
15+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.synyx.matrix.bot.internal.api.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
@Data
9+
@NoArgsConstructor
10+
@AllArgsConstructor
11+
public class ReactionRelatesToDto {
12+
13+
@JsonProperty("event_id")
14+
private String eventId;
15+
16+
@JsonProperty("key")
17+
private String key;
18+
19+
@JsonProperty("rel_type")
20+
public String getRelType() {
21+
22+
return "m.annotation";
23+
}
24+
}

0 commit comments

Comments
 (0)