-
Notifications
You must be signed in to change notification settings - Fork 67
Expand file tree
/
Copy pathChatModel.java
More file actions
120 lines (102 loc) · 4.35 KB
/
Copy pathChatModel.java
File metadata and controls
120 lines (102 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package com.example;
import javafx.application.Platform;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ChatModel {
private final String sendUrl;
private final String subscribeUrl;
private final String clientId;
private final Set<String> sentMessages = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final HttpClient httpClient;
private final Consumer<Runnable> platformRunner;
public ChatModel() {
this(HttpClient.newHttpClient(), Platform::runLater);
}
public ChatModel(HttpClient httpClient, Consumer<Runnable> platformRunner) {
String topic = System.getenv().getOrDefault("NTFY_TOPIC", "https://ntfy.sh/newchatroom3");
this.sendUrl = topic;
this.subscribeUrl = topic + "/sse";
this.clientId = UUID.randomUUID().toString();
this.httpClient = httpClient;
this.platformRunner = platformRunner;
}
public void sendMessage(String message) {
sentMessages.add(message);
new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException ignored) {
}
sentMessages.remove(message);
}, "SentMessageCleaner").start();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(sendUrl))
.header("Content-Type", "application/json")
.header("X-Client-ID", clientId)
.header("Title", "Friend: ")
.POST(HttpRequest.BodyPublishers.ofString(message))
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenAccept(response -> System.out.println("Sent, status=" + response.statusCode()))
.exceptionally(e -> {
e.printStackTrace();
return null;
});
}
public void subscribe(Consumer<String> onMessageReceived) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(subscribeUrl))
.header("Accept", "text/event-stream")
.build();
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream())
.thenAccept(response -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.body()))) {
String line;
// boolean firstMessageSkipped = false;
while ((line = reader.readLine()) != null) {
if (line.startsWith("data:")) {
// if (!firstMessageSkipped) {
// firstMessageSkipped = true;
// continue;
// }
String raw = line.substring(5).trim();
String msg = parseMessage(raw);
if (msg != null && !sentMessages.contains(msg)) {
platformRunner.accept(() -> onMessageReceived.accept(msg));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
})
.exceptionally(e -> { e.printStackTrace(); return null; });
}
public String parseMessage(String data) {
try {
Matcher eventMatcher = Pattern.compile("\"event\"\\s*:\\s*\"(.*?)\"").matcher(data);
if (eventMatcher.find()) {
String event = eventMatcher.group(1);
if (!"message".equals(event)) {
return null;
}
}
Matcher msgMatcher = Pattern.compile("\"message\"\\s*:\\s*\"(.*?)\"").matcher(data);
if (msgMatcher.find()) {
return msgMatcher.group(1).replace("\\\"", "\"");
}
} catch (Exception ignored) {}
return null;
}
}