88 lines
3.1 KiB
Java
88 lines
3.1 KiB
Java
package com.leohabrom.discordrpc;
|
|
|
|
import com.leohabrom.discord.DiscordActivity;
|
|
import com.leohabrom.discord.DiscordBridge;
|
|
import com.leohabrom.discord.DiscordBridgeAdapter;
|
|
|
|
import java.util.concurrent.*;
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
public class Bridge implements DiscordBridgeAdapter {
|
|
private final DiscordBridge bridge;
|
|
private final BlockingQueue<Boolean> feedbackQueue = new ArrayBlockingQueue<>(1);
|
|
|
|
// Scheduling tools
|
|
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
|
|
private final AtomicLong lastSendTime = new AtomicLong(0);
|
|
private final AtomicReference<DiscordActivity> pendingActivity = new AtomicReference<>();
|
|
private final AtomicReference<ScheduledFuture<?>> scheduledTask = new AtomicReference<>();
|
|
|
|
private DiscordActivity lastSentActivity = null;
|
|
|
|
public Bridge(long appId) {
|
|
this.bridge = new DiscordBridge();
|
|
this.bridge.init(appId);
|
|
this.bridge.setAdapter(this);
|
|
this.bridge.start();
|
|
}
|
|
|
|
/**
|
|
* Updates the activity. If called too fast, it buffers the latest
|
|
* request and sends it as soon as the rate limit allows.
|
|
*/
|
|
public void update(DiscordActivity activity) {
|
|
pendingActivity.set(activity);
|
|
|
|
long now = System.currentTimeMillis();
|
|
long timeSinceLastSend = now - lastSendTime.get();
|
|
long delayNeeded = 1000 - timeSinceLastSend;
|
|
|
|
if (delayNeeded <= 0) {
|
|
sendNow();
|
|
} else {
|
|
// If a task is already scheduled, don't create another one.
|
|
// The scheduled task will naturally pick up the "latest" pendingActivity.
|
|
if (scheduledTask.get() == null || scheduledTask.get().isDone()) {
|
|
ScheduledFuture<?> task = scheduler.schedule(this::sendNow, delayNeeded, TimeUnit.MILLISECONDS);
|
|
scheduledTask.set(task);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void sendNow() {
|
|
DiscordActivity activity = pendingActivity.getAndSet(null);
|
|
if (activity != null) {
|
|
if (activity.equals(lastSentActivity)) {
|
|
return;
|
|
}
|
|
lastSentActivity = activity;
|
|
lastSendTime.set(System.currentTimeMillis());
|
|
bridge.update(activity);
|
|
}
|
|
}
|
|
|
|
public boolean updateWithFeedback(DiscordActivity activity) {
|
|
feedbackQueue.clear();
|
|
update(activity);
|
|
try {
|
|
// We wait a bit longer because the update might be delayed by the scheduler
|
|
Boolean result = feedbackQueue.poll(3, TimeUnit.SECONDS);
|
|
return result != null && result;
|
|
} catch (InterruptedException e) {
|
|
Thread.currentThread().interrupt();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onMessage(String message) {
|
|
if (message == null) return;
|
|
String msg = message.toLowerCase();
|
|
if (msg.contains("sent") || msg.contains("success")) {
|
|
feedbackQueue.offer(true);
|
|
} else if (msg.contains("fail") || msg.contains("error")) {
|
|
feedbackQueue.offer(false);
|
|
}
|
|
}
|
|
} |