rubenlagus / TelegramBots

Java library to create bots using Telegram Bots API
https://telegram.me/JavaBotsApi
MIT License
4.68k stars 1.18k forks source link

WebHook problems! #688

Open X3nX3n opened 4 years ago

X3nX3n commented 4 years ago

Hey guys, i'm trying to make webhooks work, but somthing is going crazy wrong) Can you help me out? I dont really understand how do i connect grizzly to nginx External webhook adress and port should be nginx while internal should be grizzly on localhost? Or am i getting it wrong And i somehow need to tell nginx to redirect posts to grizzly or i dont? And why your example @SnowcrashBot WebHooks bot does not work?

X3nX3n commented 4 years ago

Grizzly run but not working.

torvicv commented 3 years ago

I made my app with apache tomcat, I just set internal url, and it worked to me.

LegendaryZer0 commented 3 years ago

I made my app with apache tomcat, I just set internal url, and it worked to me.

Can you show how you did it?

torvicv commented 3 years ago

Excuse me for my english.

This is my code:

ControllerBot.java

`import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.telegram.telegrambots.meta.api.methods.BotApiMethod; import org.telegram.telegrambots.meta.api.objects.Update;

@RestController public class ControladorBot {

@Autowired
TelegramSpringWebhookBot telegramSpringWebhookBot;

/**
 * Página que se encarga del envío automatizado de los mensajes de telegram y email.
 * @ResponseStatus con el valor HttpStatus.OK para indicar que a pesar de estar en 
 * un controlador no devolverá nada.
 */
@PostMapping("/url")
public BotApiMethod<?> postEnvioAutomatizado(@RequestBody Update update) {
    return telegramSpringWebhookBot.onWebhookUpdateReceived(update);
}

}`

TelegramSpringWebhookBot.java

` import org.telegram.telegrambots.bots.TelegramWebhookBot; import org.telegram.telegrambots.meta.api.methods.BotApiMethod; import org.telegram.telegrambots.meta.api.objects.Update; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.text.Normalizer; import java.time.LocalDateTime; import java.util.Iterator; import java.util.List; import java.util.MissingResourceException; import java.util.regex.Matcher; import java.util.regex.Pattern;

import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.telegram.telegrambots.meta.api.methods.send.SendMessage; import org.telegram.telegrambots.meta.api.objects.Message; import org.telegram.telegrambots.meta.exceptions.TelegramApiException;

@Component public class TelegramSpringWebhookBot extends TelegramWebhookBot { private static final Logger logger = LoggerFactory.getLogger(TelegramBot.class);

/**
 * Propiedad bufferedReader, de tipo BufferedReader.
 */
private BufferedReader bufferedReader;

/**
 * Propiedad iterator, iterador de tipo SeleccionarDeportes.
 */
private Iterator<Deportes> iterator;

/**
 * Propiedad messageCreate, de tipo StringBuilder, para guardar el mensaje
 * completo en un objeto.
 */
private StringBuilder messageCreate;

/**
 * Propiedad listaDeportes, lista de la clase SeleccionarDeportes.
 */
private List<Deportes> listaDeportes;

/**
 * Propiedad inyectada de tipo ServicioBD.
 */
@Autowired
ServicioBD servicioBD;

@Autowired UserRepository userRepository;

/**
 * Directorio base del tomcat
 */
private static final String tomcatHome = System.getProperty("catalina.base");

/**
 * Método para conseguir el token de telegram.
 */
@Override
public String getBotToken() {
    return "bot_token";
}

/**
 * Método para conseguir el nombre de usuario de telegram.
 */
@Override
public String getBotUsername() {
    return "bot_name";
}

/**
 * 
 * @param nombre, de tipo String. Nombre del usuario.
 * @param id,     de tipo Long. id del usuario.
 */
public void envioAutomatizado(String nombre, Long id) {
    // inicializamos el bufferedReader y e inicializamos response.
    SendMessage response = this.inicioBufferedReaderEInicioSendMessage();
    try {
        // conseguimos los deportes seleccionados por el usuario y los asignamos al iterador.
        this.iterator = this.conseguirDeportesSeleccionadosYAsignarAIterator(nombre);
    } catch (IllegalArgumentException e) {
        System.out.println(e.getMessage());
    }
    // inicializamos la propiedad.
    this.messageCreate = new StringBuilder();
    // conseguimos el registro de telegram correspondiente al usuario por su id.
    Telegram telegram = this.servicioBD.conseguirTelegramPorId(id);
    // si no son nulos telegram y listaDeportes
    if (telegram != null && this.listaDeportes != null)
        // si es verdadero es campo confirmar y listaDeportes no está vacia, y si el horario elegido
        // por el usuario coincide con la hora actual.
        if (telegram.isConfirmar() && !this.listaDeportes.isEmpty() &&
            this.servicioBD.conseguirHorario(nombre).equals(String.format("%02d", LocalDateTime.now().getHour()))) {
            // guardamos en response su chat id.
            response.setChatId(telegram.getChatId().toString());
            // establece el texto del envío
            response.setText(new String(this.asignarMensajeConseguido(this.messageCreate)));
            try {
                // ejecuta la respuesta.
                execute(response);
            } catch (TelegramApiException e) {
                logger.error("Failed to send message \"{}\" to {} due to error: {}", new String(messageCreate),
                        telegram.getChatId(), e.getMessage());
            }
        }
    // reiniciamos listaDeportes a nulo.
    this.listaDeportes = null;
}

/**
 * Método para inicializar el bufferedReader para la lectura del archivo
 * teledeporte2.txt e inicializar tambien la propiedad sendMessage.
 * 
 * @return response, de tipo SendMessage.
 */
private SendMessage inicioBufferedReaderEInicioSendMessage() {
    try {
        // producción
        this.bufferedReader = new BufferedReader(
            new InputStreamReader(new FileInputStream(new File(tomcatHome+"file.txt")), "UTF-8"));
    } catch (UnsupportedEncodingException e2) {
        e2.printStackTrace();
    } catch (FileNotFoundException e2) {
        e2.printStackTrace();
    }
    SendMessage response = new SendMessage();
    return response;
}

/**
 * Método para conseguir los deportes seleccionados por el usuario a partir de
 * su nombre, y crear un iterador a partir de esa lista de deportes.
 * 
 * @param nombre, de tipo String.
 * @return iterator, de tipo Iterator<SeleccionarDeportes>.
 */
private Iterator<Deportes> conseguirDeportesSeleccionadosYAsignarAIterator(String nombre) {
    // conseguimos los deportes seleccionados por su nombre.
    this.listaDeportes = this.servicioBD.mostrarDeportesSeleccionados(nombre);
    // creamos un iterador y le asignamos la listaDeportes.
    Iterator<Deportes> iterator = this.listaDeportes.iterator();
    // devolvemos el iterador.
    return iterator;
}

/**
 * Método para crear el mensaje que se enviará a telegram. Primero lee el
 * fichero .txt, después busca en ese fichero si alguna de las líneas tiene el
 * deporte o deportes que seleccionó el usuario.
 * 
 * @param messageCreate, de tipo StringBuilder.
 * @return messageCreate, de tipo StringBuilder.
 */
private StringBuilder asignarMensajeConseguido(StringBuilder messageCreate) {
    String linea = "";
    // bucle while que guarda en una variable cada linea leida con BufferedReader
    // del archivo
    try {
        // mientras haya una línea que leer en el fichero.
        while ((linea = bufferedReader.readLine()) != null) {
            // creamos un string donde guardamos cada linea, reemplazando los caracteres
            // especiales como &,%,~, etc...
            String reemplazar = linea.replaceAll("[^a-zA-Z0-9:-_áéíóúÁÉÍÓÚ\\s]", "");
            // eliminamos las " de " o " DE " para deportes que contengan esa expresión.
            reemplazar = reemplazar.replaceAll("(\\s{1}de\\s{1})|(\\s{1}DE\\s{1})", " ");
            // si el siguiente elemento no es nulo
            while (iterator.hasNext()) {
                // guardamos en un objeto de tipo SeleccionarDeportes cada iteración
                Deportes deporte = (Deportes) iterator.next();
                // reemplazamos todos los acentos por sus caracteres correspondientes.
                String reemplazarAcentos = Normalizer.normalize(reemplazar.toLowerCase(), Normalizer.Form.NFD)
                    .replaceAll("[^\\p{ASCII}]", "");
                String deporteSinAcentos = Normalizer.normalize(deporte.getNombre().toLowerCase(), Normalizer.Form.NFD)
                    .replaceAll("[^\\p{ASCII}]", "");
                // creamos un patrón para que nos busque el deporte (cualquier caracter cero o
                // más veces seguido de un espacio una o más veces seguido del nombre 
                // del deporte seguido de un espacio opcional)
                Pattern pattern = Pattern.compile(".*\\s*" + deporteSinAcentos + "\\s?");
                // busca el patrón en el string reemplazar.
                Matcher matcher = pattern.matcher(reemplazarAcentos);
                if (reemplazarAcentos.indexOf(deporteSinAcentos) != -1
                        && matcher.lookingAt()) {
                    messageCreate.append(linea);
                    messageCreate.append(System.lineSeparator());
                }
            }
            // reiniciamos el iterador
            iterator = this.listaDeportes.iterator();
        }
        // cerramos el BufferedReader.
        bufferedReader.close();

    } catch (IOException e1) {
        e1.printStackTrace();
    }
    return messageCreate;
}

@Override
public BotApiMethod<?> onWebhookUpdateReceived(Update update) {
    // si hay algún mensaje nuevo.
    if (update.hasMessage()) {
        // 
        SendMessage response = this.inicioBufferedReaderEInicioSendMessage();
        // conseguimos el mensaje.
        Message message = update.getMessage();
        // conseguimos el chatId
        Long chatId = message.getChatId();
        this.messageCreate = new StringBuilder();
        // si el mensaje que el usuario escribe son 9 números (código enviado para
        // suscribirse a telegram) y coincide con el que le hemos asignado entonces 
        // lo confirma y guardamos su chatId para enviarle las notificaciones.
        if (message.getText().matches("pattern")) {
            Telegram telegram = this.servicioBD.conseguirTelegram(message.getText());
            telegram.setChatId(chatId);
            telegram.setConfirmar(true);                
            this.servicioBD.establecerChatId(telegram);
        } else {
            try {
                this.iterator = this.conseguirDeportesSeleccionadosYAsignarAIterator(message.getText());
                response.setChatId(chatId.toString());
                response.setText(new String(this.asignarMensajeConseguido(this.messageCreate)));
            } catch (IllegalArgumentException|NullPointerException e) {
                // ponemos la url directamente por no funcionar el httpservletrequest.
                String base = "https://alertadeportes.ml/"; 
                response.setChatId(chatId.toString());
                // esto habilita usar las etiquetas para markdown en vez de texto plano.
                response.enableMarkdown(true);
                // establecemos el texto que se mostrará.
                response.setText(new String(e.getMessage()+" entra en la web [Alertas Deportes]("+ base + ") y elige tus deportes preferidos."));
            } catch (MissingResourceException e) {
                e.printStackTrace();
            }
        }
        return response;
    }
    return null;
}

@Override
public String getBotPath() {
    return null;
}

} `

DemoApplication.java: Into run method.

` @Autowired private TelegramSpringWebhookBot telegramBot; // webhook

TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class); SetWebhook setWebhook = new SetWebhook("https://alertadeportes.ml/path_to_url"); // BotController.java botsApi.registerBot(telegramBot, setWebhook); // webhook`