package de.mrbesen.telegram.commands; import de.mrbesen.telegram.AsyncHandler; import de.mrbesen.telegram.MessageBuilder; import de.mrbesen.telegram.TelegramAPI; import de.mrbesen.telegram.event.events.UserCallbackEvent; import de.mrbesen.telegram.event.events.UserSendMessageEvent; import de.mrbesen.telegram.objects.TInlineKeyboardMarkup; import de.mrbesen.telegram.objects.TMessage; import de.mrbesen.telegram.objects.TUser; import lombok.Setter; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.function.Function; public class FeedbackCommand implements JSONCommandHandler { protected final TInlineKeyboardMarkup cancelMarkup = TInlineKeyboardMarkup.makeSingleButton("❌ cancel", CANCELFEEDBACK); protected final Map awaitingFeedback = new TreeMap<>(); //maps users chat id -> message that said "please send feedback" TODO: make persistent? protected final Map answer = new TreeMap<>(); // chatid -> [chatid, messageid] to answer to; next message from key will be fwd to value[0] and reply to value[1] protected final TelegramAPI api; protected final List admins; protected final static String CANCELFEEDBACK = "cancelfeedback", REPLYFEEDBACK = "replyFeedback "; @Setter private Function feedbackCallback = null; public FeedbackCommand(TelegramAPI api, List admins) { this.api = api; this.admins = (admins == null ? new LinkedList<>() : admins); } @Override public boolean onCommand(TUser sender, String cmd, String[] args, TMessage json) { if(json.getChatID() < 0) return false; //do not handle group chats if(cmd.equalsIgnoreCase("feedback")) { removeMsg(sender.getID(), null); awaitingFeedback.put(sender.getID(), null); MessageBuilder mb = new MessageBuilder(); mb.setAsync().setReciver(sender).setMarkup(cancelMarkup).setText("Your next message will be forwarded to the admins.") .setCallback(new AsyncHandler.Callback() { @Override public Object call(TMessage msg) { awaitingFeedback.put(sender.getID(), msg); return null; } }); api.sendMessage(mb.build()); return true; } return false; } public boolean onMsg(UserSendMessageEvent e) { TUser user = e.getUser(); TMessage msg = e.getMsg(); if (awaitingFeedback.containsKey(user.getID())) { //user send a feedback removeMsg(user.getID(), e.getMsg()); if(isFeedback(msg.getText())) { //fwd to admins admins.forEach(a -> TMessage.forwardAsync(api, a, msg)); MessageBuilder mb = createInfo(user, msg.getMessageID(), true); admins.forEach(a -> api.sendMessage(mb.setReciver(a).build())); } else { System.out.println("feedback omitted: " + msg.getText()); } return true; } else { //reply to a message Long[] rplymsg = answer.remove(user.getID()); if(rplymsg != null) { if(admins.contains(user.getID())) { System.out.println("admin answered feedback!"); //admin to user -> copy text send as new msg from bot to disguise admin TInlineKeyboardMarkup mu = new TInlineKeyboardMarkup(1); mu.addCallbackButton("↩ reply", buildRplyCallback(user.getID(), msg.getMessageID()), 1); MessageBuilder mb = new MessageBuilder().setAsync().setReciver(rplymsg[0]) .setReplyTo(Math.toIntExact(rplymsg[1])).setText(msg.getText()).setMarkup(mu); api.sendMessage(mb.build()); } else { System.out.println("user answered feedback!"); //user to admin -> fwd message TMessage.forwardAsync(api, rplymsg[0], msg); //send info MessageBuilder mb = createInfo(user, msg.getMessageID(), false); api.sendMessage(mb.setReciver(rplymsg[0]).setReplyTo(Math.toIntExact(rplymsg[1])).build()); } System.out.println("Feedback reply from " + user.getID() + " to " + rplymsg[0] + ":" + rplymsg[1] + " send."); return true; } } return false; } protected MessageBuilder createInfo(TUser u, int msgid, boolean firstmsg) { String info = "Feedbackinfo:\n" + "userid: " + u.getID() + "\nusername: " + u.getName() + "\nfullname: " + u.getFirstName() + ' ' + u.getLastName(); MessageBuilder mb = new MessageBuilder().setAsync(); if(firstmsg && feedbackCallback != null) { try { info += '\n' + feedbackCallback.apply(u); mb.setNoWebView(true); } catch (Throwable t) { info += "\nError getting information: " + t.getMessage(); t.printStackTrace(); } } TInlineKeyboardMarkup markup = new TInlineKeyboardMarkup(1); markup.addUrlButton("chat with user", "https://t.me/" + u.getName(), 1); markup.addCallbackButton("↩ reply", buildRplyCallback(u.getID(), msgid), 1); return mb.setText(info).setFormatting(MessageBuilder.Formatting.HTML).setMarkup(markup); } public boolean onCallback(UserCallbackEvent e) { if(e.getData().equals(CANCELFEEDBACK)) { removeMsg(e.getUser().getID(), e.getMsg()); api.answerCallbackQuery(e.getID(), "Cancelled", true); return true; } else if(e.getData().startsWith(REPLYFEEDBACK)) { String rest = e.getData().substring(REPLYFEEDBACK.length()); long chatid = 0; long msgid = -1; try { String[] spl = rest.split(" ",2); long adminid = Long.parseLong(spl[0]); msgid = Integer.parseInt(spl[1]); //convert admin id to chat id if(adminid <= 0) { chatid = admins.get((int) -adminid); } else chatid = adminid; } catch (NumberFormatException ex) { api.answerCallbackQuery(e.getID(), "Error. Sorry :/", true); ex.printStackTrace(); } if(msgid > -1) { answer.put(e.getUser().getID(), new Long[]{chatid, msgid}); api.answerCallbackQuery(e.getID(), "Write a Message", true); } return true; } return false; } /** * looks up msg from awaiting feedback map, if not present try to use fallback_msg * is Async * removes user from awaitingFeedback * */ protected void removeMsg(long chat, TMessage fallback_msg) { TMessage msg = awaitingFeedback.remove(chat); if(msg == null) msg = fallback_msg; if(msg != null) TMessage.delete(api, msg.getChatID(), msg.getMessageID(), true); } /** * check if a message is allowed as feedback * @param msg * @return */ protected boolean isFeedback(String msg) { msg = msg.trim(); return (!msg.startsWith("/")) && (msg.length() > 5) && (!msg.startsWith("http")); } protected int getAdminID(long adminchat) { for(int i = 0; i < admins.size(); i++) { if(admins.get(i) == adminchat) return i; } return -1; } protected String buildRplyCallback(long user, int msgid) { int adminid = getAdminID(user); if(adminid >= 0) user = -adminid; return REPLYFEEDBACK + user + " " + msgid; } }