mirror of
https://github.com/aNNiMON/ffmpegbot
synced 2024-09-19 22:54:20 +03:00
Admin command to manage sessions
This commit is contained in:
parent
856cd15358
commit
6e58de0049
@ -40,7 +40,7 @@ public class MainBotHandler extends BotHandler {
|
|||||||
commands.registerBundle(mediaProcessingBundle);
|
commands.registerBundle(mediaProcessingBundle);
|
||||||
commands.registerBundle(new InputParametersBundle(sessions));
|
commands.registerBundle(new InputParametersBundle(sessions));
|
||||||
commands.registerBundle(new YtDlpCommandBundle(sessions));
|
commands.registerBundle(new YtDlpCommandBundle(sessions));
|
||||||
commands.registerBundle(new AdminCommandBundle());
|
commands.registerBundle(new AdminCommandBundle(sessions));
|
||||||
commands.register(new HelpCommand());
|
commands.register(new HelpCommand());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ public class HelpCommand implements TextCommand {
|
|||||||
<b>yt-dlp</b>
|
<b>yt-dlp</b>
|
||||||
/dl link [format] — download a media using yt-dlp
|
/dl link [format] — download a media using yt-dlp
|
||||||
<code>link</code> — a link to download (it must be supported by yt-dlp)
|
<code>link</code> — a link to download (it must be supported by yt-dlp)
|
||||||
<code>format</code> — (optional) a download format. Can be "audio", "240", "360", "480", "720" or "1080"
|
<code>format</code> — (optional) a download format. Can be "best", "audio", "240", "360", "480", "720" or "1080"
|
||||||
""".stripIndent()).enableHtml().callAsync(ctx.sender);
|
""".stripIndent()).enableHtml().callAsync(ctx.sender);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.annimon.ffmpegbot.commands.admin;
|
package com.annimon.ffmpegbot.commands.admin;
|
||||||
|
|
||||||
|
import com.annimon.ffmpegbot.session.Sessions;
|
||||||
import com.annimon.tgbotsmodule.commands.CommandBundle;
|
import com.annimon.tgbotsmodule.commands.CommandBundle;
|
||||||
import com.annimon.tgbotsmodule.commands.CommandRegistry;
|
import com.annimon.tgbotsmodule.commands.CommandRegistry;
|
||||||
import com.annimon.tgbotsmodule.commands.authority.For;
|
import com.annimon.tgbotsmodule.commands.authority.For;
|
||||||
@ -7,9 +8,17 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
|
|
||||||
public class AdminCommandBundle implements CommandBundle<For> {
|
public class AdminCommandBundle implements CommandBundle<For> {
|
||||||
|
|
||||||
|
private final Sessions sessions;
|
||||||
|
|
||||||
|
public AdminCommandBundle(Sessions sessions) {
|
||||||
|
this.sessions = sessions;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(@NotNull CommandRegistry commands) {
|
public void register(@NotNull CommandRegistry commands) {
|
||||||
commands.register(new RunCommand());
|
commands.register(new RunCommand());
|
||||||
commands.register(new ClearCommand());
|
commands.register(new ClearCommand());
|
||||||
|
commands.register(new SessionsCommand(sessions));
|
||||||
|
commands.register(new SessionsClearCommand(sessions));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.annimon.ffmpegbot.commands.admin;
|
||||||
|
|
||||||
|
import com.annimon.ffmpegbot.Permissions;
|
||||||
|
import com.annimon.ffmpegbot.session.Sessions;
|
||||||
|
import com.annimon.tgbotsmodule.commands.CallbackQueryCommand;
|
||||||
|
import com.annimon.tgbotsmodule.commands.authority.For;
|
||||||
|
import com.annimon.tgbotsmodule.commands.context.CallbackQueryContext;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
|
||||||
|
public class SessionsClearCommand implements CallbackQueryCommand {
|
||||||
|
static final String CALLBACK_NAME = "sessions_clear";
|
||||||
|
private final Sessions sessions;
|
||||||
|
|
||||||
|
public SessionsClearCommand(Sessions sessions) {
|
||||||
|
this.sessions = sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String command() {
|
||||||
|
return CALLBACK_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public EnumSet<For> authority() {
|
||||||
|
return Permissions.SUPERUSERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(@NotNull CallbackQueryContext ctx) {
|
||||||
|
final int size = sessions.getSize();
|
||||||
|
sessions.clear();
|
||||||
|
ctx.editMessage("%d sessions cleared".formatted(size))
|
||||||
|
.setReplyMarkup(null)
|
||||||
|
.callAsync(ctx.sender);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package com.annimon.ffmpegbot.commands.admin;
|
||||||
|
|
||||||
|
import com.annimon.ffmpegbot.Permissions;
|
||||||
|
import com.annimon.ffmpegbot.TextUtils;
|
||||||
|
import com.annimon.ffmpegbot.session.MediaSession;
|
||||||
|
import com.annimon.ffmpegbot.session.Session;
|
||||||
|
import com.annimon.ffmpegbot.session.Sessions;
|
||||||
|
import com.annimon.ffmpegbot.session.YtDlpSession;
|
||||||
|
import com.annimon.tgbotsmodule.commands.TextCommand;
|
||||||
|
import com.annimon.tgbotsmodule.commands.authority.For;
|
||||||
|
import com.annimon.tgbotsmodule.commands.context.MessageContext;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class SessionsCommand implements TextCommand {
|
||||||
|
private final Sessions sessions;
|
||||||
|
|
||||||
|
public SessionsCommand(Sessions sessions) {
|
||||||
|
this.sessions = sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String command() {
|
||||||
|
return "/sessions";
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public EnumSet<For> authority() {
|
||||||
|
return Permissions.SUPERUSERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(@NotNull MessageContext ctx) {
|
||||||
|
final int size = sessions.getSize();
|
||||||
|
if (size == 0) {
|
||||||
|
ctx.replyToMessage("No sessions found").callAsync(ctx.sender);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (ctx.argument(1).equals("clear")) {
|
||||||
|
sessions.clear();
|
||||||
|
ctx.replyToMessage("%d sessions cleared".formatted(size)).callAsync(ctx.sender);
|
||||||
|
} else {
|
||||||
|
final var sessionsInfo = sessions.sessions()
|
||||||
|
.sorted(Comparator.comparing(Session::getInstant).reversed())
|
||||||
|
.map(this::formatSession)
|
||||||
|
.limit(30)
|
||||||
|
.collect(Collectors.joining("\n"));
|
||||||
|
ctx.replyToMessage(("%d active sessions:\n%s").formatted(size, sessionsInfo))
|
||||||
|
.disableWebPagePreview()
|
||||||
|
.setSingleRowInlineKeyboard(InlineKeyboardButton.builder()
|
||||||
|
.text("Clear").callbackData(SessionsClearCommand.CALLBACK_NAME)
|
||||||
|
.build())
|
||||||
|
.callAsync(ctx.sender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatSession(Session session) {
|
||||||
|
long chatId = session.getChatId();
|
||||||
|
if (session instanceof MediaSession ms) {
|
||||||
|
return String.join(" ", str(chatId), str(ms.getOriginalFilename()),
|
||||||
|
str(ms.getFileSize(), TextUtils::readableFileSize),
|
||||||
|
str(ms.getDuration(), TextUtils::readableDuration));
|
||||||
|
} else if (session instanceof YtDlpSession ys) {
|
||||||
|
return String.join(" ", str(chatId), str(ys.getUrl()));
|
||||||
|
}
|
||||||
|
return str(chatId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String str(Object obj) {
|
||||||
|
return obj == null ? "" : Objects.toString(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> String str(T obj, Function<? super T, String> func) {
|
||||||
|
return obj == null ? "" : str(func.apply(obj));
|
||||||
|
}
|
||||||
|
}
|
@ -54,14 +54,26 @@ public final class MediaSession extends Session {
|
|||||||
this.originalFilename = originalFilename;
|
this.originalFilename = originalFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getOriginalFilename() {
|
||||||
|
return originalFilename;
|
||||||
|
}
|
||||||
|
|
||||||
public void setFileSize(Long fileSize) {
|
public void setFileSize(Long fileSize) {
|
||||||
this.fileSize = fileSize;
|
this.fileSize = fileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getFileSize() {
|
||||||
|
return fileSize;
|
||||||
|
}
|
||||||
|
|
||||||
public void setDuration(Integer duration) {
|
public void setDuration(Integer duration) {
|
||||||
this.duration = duration;
|
this.duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
public void setResolution(Integer width, Integer height) {
|
public void setResolution(Integer width, Integer height) {
|
||||||
if (width == null && height == null) {
|
if (width == null && height == null) {
|
||||||
this.resolution = null;
|
this.resolution = null;
|
||||||
|
@ -2,6 +2,7 @@ package com.annimon.ffmpegbot.session;
|
|||||||
|
|
||||||
import com.annimon.ffmpegbot.parameters.InputParameters;
|
import com.annimon.ffmpegbot.parameters.InputParameters;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
public abstract sealed class Session permits MediaSession, YtDlpSession {
|
public abstract sealed class Session permits MediaSession, YtDlpSession {
|
||||||
@ -10,6 +11,8 @@ public abstract sealed class Session permits MediaSession, YtDlpSession {
|
|||||||
protected int messageId;
|
protected int messageId;
|
||||||
// Parameters
|
// Parameters
|
||||||
protected final InputParameters inputParams = new InputParameters();
|
protected final InputParameters inputParams = new InputParameters();
|
||||||
|
// Meta
|
||||||
|
private final Instant instant = Instant.now();
|
||||||
|
|
||||||
public long getChatId() {
|
public long getChatId() {
|
||||||
return chatId;
|
return chatId;
|
||||||
@ -31,5 +34,9 @@ public abstract sealed class Session permits MediaSession, YtDlpSession {
|
|||||||
return inputParams;
|
return inputParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Instant getInstant() {
|
||||||
|
return instant;
|
||||||
|
}
|
||||||
|
|
||||||
abstract StringJoiner describe();
|
abstract StringJoiner describe();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.annimon.ffmpegbot.session;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class Sessions {
|
public class Sessions {
|
||||||
private final Map<String, Session> sessions;
|
private final Map<String, Session> sessions;
|
||||||
@ -10,6 +11,18 @@ public class Sessions {
|
|||||||
sessions = new ConcurrentHashMap<>();
|
sessions = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
sessions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return sessions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<Session> sessions() {
|
||||||
|
return sessions.values().stream();
|
||||||
|
}
|
||||||
|
|
||||||
public Session get(long chatId, long messageId) {
|
public Session get(long chatId, long messageId) {
|
||||||
return sessions.get(mapKey(chatId, messageId));
|
return sessions.get(mapKey(chatId, messageId));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user