¡Hola a todos! El tema de la creación de bots para Telegram está algo trillado y se han escrito muchas guías (por ejemplo, esta ) . Por lo tanto, será mejor que analicemos más de cerca cómo trabajar con alguna API de terceros, ya que esta es una habilidad crítica para cualquier desarrollador web. Diré de inmediato que la aplicación no se propuso proporcionar el pronóstico más funcional y útil; no tiene sentido competir con sitios meteorológicos; era importante aprender a trabajar con conexiones remotas y análisis de datos usando Java. Entonces, averigüemos qué necesitamos primero. Nuestra aplicación consta esencialmente de tres partes lógicas:
- aceptar mensaje del usuario
- procesar el mensaje y, si es un comando válido, preparar datos para la respuesta. En nuestro caso, preparar un pronóstico del tiempo si el usuario ingresó la ciudad correcta
- enviar información lista al usuario en el chat
https://api.openweathermap.org/data/2.5/forecast?q=(город)&APPID=(уникальный токен, полученный при регистрации)
Puedes ver cómo se ve la respuesta a dicha solicitud en el navegador. Ya hemos descubierto que, de hecho, basta con seguir el enlace correcto y el servidor le proporcionará los datos necesarios. Todo lo que queda es aprender a hacer esto usando Java. Una solicitud GET simple en Java se ve así:
//создаём строку со ссылкой на нужную página,
//я тут её склеиваю из заранее определённых констант, меняя только сам город
String urlString = API_CALL_TEMPLATE + city + API_KEY_TEMPLATE;
//создаём un objeto который будет содержать ссылку
URL urlObject = new URL(urlString);
//создаём соединение, используя un objeto
HttpURLConnection connection = (HttpURLConnection) urlObject.openConnection();
//выбираем тип pedidoа (GET)
connection.setRequestMethod("GET");
//тут мы указываем, данные о себе, что мы можем принять всё то,
//что примет и любой современный браузер
connection.setRequestProperty("User-Agent", "Mozilla/5.0");
//В начало ответа servidor всегда вставляет число, по которому можно судить, прошло ли всё хорошо.
//200 - значит OK
int responseCode = connection.getResponseCode();
//на несуществующий город o город с опечаткой, servidor выдаст código ответа 404,
//бросаем на него исключение, чтобы обработать на уровне повыше и предложить
//пользователю ввести город заново
if (responseCode == 404) {
throw new IllegalArgumentException();
}
// создаём поток, вычитываем все строки, и склеиваем в одну большую строку,
//которую будем потом обрабатывать в других методах
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
Si la solicitud fue correcta y el servidor estaba disponible, recibiremos una hoja de datos en la que se mezcla información útil con información que no es necesaria ahora. Para extraer cómodamente los datos necesarios de JSON y XML, se han escrito toneladas de bibliotecas para Java para todos los gustos. Como prefería JSON, elegí una biblioteca muy popular llamada Jackson para procesarlo. Por cierto, se estudia un poco en JavaRush en algunos niveles altos. Para procesar grandes cantidades de datos JSON, es importante comprender la estructura del documento. Sitios útiles como este vienen al rescate . A la izquierda tenemos el JSON original, a la derecha el estructurado: Se puede ver que la respuesta consta de 5 objetos JSON de nivel superior, 2 de los cuales son complejos y son nodos para las siguientes ramas. Los datos que nos interesan se almacenan en el nodo de lista . Dentro de la lista hay una matriz de 38 líneas JSON, cada una de las cuales describe el clima en un momento determinado. Es decir, es una especie de estructura arbórea, donde hay raíz, ramas, ramitas e incluso hojas :) Y en los nodos se produce la ramificación. Afortunadamente, Jackson puede representar cualquier JSON válido como un árbol. Así, sabiendo el nombre del atributo que necesitamos (por ejemplo, temperatura del aire), y en qué nivel del árbol se encuentra, conseguirlo no será un gran problema. Primero, extraje todas las líneas de la matriz "lista" y las agregué a una lista separada. En términos generales, corté la hoja con los datos en pedazos, cada uno de los cuales es un pronóstico separado. Las piezas pequeñas son más fáciles de recordar y operar.
//JsonNode - это один из узлов в древовидной иерархии, от которого идут ветви
//получаем узел, который называется "list"
JsonNode arrNode = new ObjectMapper().readTree(data).get("list");
//если это действительно массив узлов
if (arrNode.isArray()) {
//выполняем для каждого узла, который содержится в массиве
for (final JsonNode objNode : arrNode) {
//в атрибуте "dt_txt" каждого маленького узла хранилось время прогноза, я отобрал данные за 9 утра и 6 вечера
String forecastTime = objNode.get("dt_txt").toString();
if (forecastTime.contains("09:00") || forecastTime.contains("18:00")) {
weatherList.add(objNode.toString());
}
}
}
Entonces obtuvimos una lista de cadenas, en la que cada línea representa un informe meteorológico JSON en un momento determinado. Ya sólo queda extraer lo que quieras y formatearlo. Si tenemos una línea como esta:
"main":{"temp":261.45,"temp_min":259.086,"temp_max":261.45,"pressure":1023.48,"sea_level":1045.39,"grnd_level":1023.48,"humidity":79,"temp_kf":2.37}
entonces este es un nodo llamado "principal". Para obtener datos de él, por ejemplo el nivel del mar, es suficiente el siguiente código:
ObjectMapper objectMapper = new ObjectMapper();
//line - это наша JSON-строка
mainNode = objectMapper.readTree(line).get("main");
String seaLevel = mainNode.get("sea_level");
Jackson le permite representar datos inmediatamente en formato numérico:
double seaLevel = mainNode.get("sea_level").asDouble();
Ahora podemos extraer cualquier dato del pronóstico, y solo queda pegarlo como queramos y enviárselo al usuario en Telegram. El código fuente completo está en mi github , pero puedes probar el bot en acción usando el enlace o buscando @denifoBot en la búsqueda de Telegram. El nombre de la ciudad debe estar escrito en transliteración latina, por ejemplo "Kiev" o "Moscú". Gracias, si llegaste hasta el final, acepto críticas razonables, ya que apenas estoy aprendiendo y desarrollando proyectos simples en GitHub para poder competir con talentos hambrientos de mi ciudad :) ¡Adiós a todos! PD: Creo que puede haber errores tipográficos aquí, así que puedes enviar todo en un mensaje privado, o en un comentario si estás realmente enojado :)
GO TO FULL VERSION