Skip to content

Commit

Permalink
Big update
Browse files Browse the repository at this point in the history
1)  Начал добавлять основную логику к тг боту
2) Изменил структуру бд, и поэтому изменил юзерсервис и погодный сервис для корректного взаимодействия
  • Loading branch information
XyL1GaN4eG committed Jul 22, 2024
1 parent 8a263e7 commit dc9aed6
Show file tree
Hide file tree
Showing 27 changed files with 714 additions and 136 deletions.
16 changes: 16 additions & 0 deletions TgBotService/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,22 @@
<version>1.3.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple -->
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.google.cloud/google-cloud-translate -->
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-translate</artifactId>
<version>2.46.0</version>
</dependency>



</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package weatherproject.tgbotservice.clients;

import lombok.extern.slf4j.Slf4j;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

@Slf4j
@Service

public class GeocodingClient {

private static final String NOMINATIM_API_URL = "https://nominatim.openstreetmap.org/reverse?format=json";

private final RestTemplate restTemplate;

// Конструктор для инъекции RestTemplate
public GeocodingClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}

public String getCityByCoordinates(double latitude, double longitude) {
// Построение URI с параметрами запроса
String url = UriComponentsBuilder.fromHttpUrl(NOMINATIM_API_URL)
.queryParam("lat", latitude)
.queryParam("lon", longitude)
.toUriString();

try {
// Выполнение GET запроса и получение ответа в виде строки
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
if (response.getStatusCode().is2xxSuccessful()) {
// Обработка JSON ответа
return parseCityFromJson(response.getBody());
} else {
log.error("GET request failed with response code: {}", response.getStatusCode());
}
} catch (Exception e) {
log.error("Exception occurred while making request: {}", e.getMessage());
}
return null;
}

private String parseCityFromJson(String jsonResponse) {
String city = null;
try {
// Создаем JSONParser для парсинга строки
JSONParser parser = new JSONParser();
JSONObject jsonObject = (JSONObject) parser.parse(jsonResponse);

// Получаем объект address из jsonObject
JSONObject address = (JSONObject) jsonObject.get("address");

// Извлекаем название города из объекта address
city = (String) address.get("city");

// Если не найдено значение "city", пробуем найти "town" или "village"
if (city == null) {
city = (String) address.get("town");
}
if (city == null) {
city = (String) address.get("village");
}

} catch (ParseException e) {
log.error("Ошибка парсинга JSON от openstreetmap: {}", e.getMessage());
}
return city;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package weatherproject.tgbotservice.clients;

import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

@Slf4j
public class GoogleTranslateClient {
private boolean isRussian(String text) {
return text.matches("[а-яА-ЯёЁ\\s]+");
}

private boolean isEnglish(String text) {
return text.matches("[a-aA-Z\\s]+");
}

public static String translateEngToRussian(String text) {
return translateFromTo("en", "ru", text);
}

public static String translateRuToEng(String text) {
return translateFromTo("ru", "en", text);
}

private static String translateFromTo(String langFrom, String langTo, String text) {
try {
String urlStr = "https://script.google.com/macros/s/AKfycbzO8nojwkOWKi3DjljSEf8byUYIwzNHIIhSRcPn4lGkE_1-m_LuqwU1s5SLJ0TRiarj/exec" +
"?q=" + URLEncoder.encode(text, "UTF-8") +
"&target=" + langTo +
"&source=" + langFrom;
URL url = new URL(urlStr);
StringBuilder response = new StringBuilder();
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("User-Agent", "Mozilla/5.0");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
} catch (IOException e) {
log.error("Произошла ошибка при переводе с {} на {} следующего текста: {}. Подробности: {}", langFrom, langTo, text, e.getMessage());
return "null";
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package weatherproject.tgbotservice.clients;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import weatherproject.tgbotservice.dto.UserDTO;

import java.util.List;

import org.springframework.http.ResponseEntity;

import java.util.List;

@Service
public class UserServiceClient {

private final RestTemplate restTemplate;
private final String baseUrl;

@Autowired
public UserServiceClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
//TODO: убрать хардкод и вынести в application.yml
this.baseUrl = "http://localhost:8080/users";
}

public List<UserDTO> getAllUsers() {
ResponseEntity<UserDTO[]> response = restTemplate.getForEntity(baseUrl, UserDTO[].class);
return List.of(response.getBody());
}

public UserDTO getUserById(Long id) {
String url = baseUrl + "/" + id;
return restTemplate.getForObject(url, UserDTO.class);
}

public List<UserDTO> getUserByCity(String city) {
String url = baseUrl + "/city?city=" + city;
ResponseEntity<UserDTO[]> response = restTemplate.getForEntity(url, UserDTO[].class);
return List.of(response.getBody());
}

public void createUser(UserDTO userDTO) {
restTemplate.postForObject(baseUrl, userDTO, Void.class);
}

public void deleteUser(Long id) {
String url = baseUrl + "/" + id;
restTemplate.delete(url);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package weatherproject.tgbotservice.clients;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
@RequiredArgsConstructor
public class WeatherServiceClient {

private final RestTemplate restTemplate;

// URL для обращения к Weather API Service
private final String baseUrl = "http://localhost:8081/weather";

/**
* Получение погоды для всех городов.
*
* @return Список объектов CityWeather
*/
// public List<Object[]> getAllCitiesWeather() {
// String url = baseUrl;
// Object[] response = restTemplate.getForObject(url, Object[].class);
// return Arrays.asList(response);
// }

/**
* Получение погоды по названию города.
*
* @param city Название города
* @return Массив объектов погоды
*/
public Object[] getWeatherByCity(String city) {
String url = baseUrl + "/city?city=" + city;
return restTemplate.getForObject(url, Object[].class);
}

public String getFormattedWeatherByCity(String city) {
var unformattedWeather = getWeatherByCity(city);

//TODO: вынести в константы "текущая погода" и "погода не найдена"
if (unformattedWeather != null) {
return String.format("Текущая погода в городе %s: %s, %s", city, unformattedWeather[1], unformattedWeather[2]);
}
return String.format("Погода в городе %s не найдена", city);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package weatherproject.tgbotservice.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApiConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
@AllArgsConstructor
public class UserDTO {
private Long chatId;
private String name;
private Long city;
private String city;
private String state;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package weatherproject.tgbotservice.telegram;

import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.model.Update;
import com.pengrad.telegrambot.request.SendMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import weatherproject.tgbotservice.clients.GeocodingClient;
import weatherproject.tgbotservice.clients.UserServiceClient;
import weatherproject.tgbotservice.clients.WeatherServiceClient;
import weatherproject.tgbotservice.dto.UserDTO;
import weatherproject.tgbotservice.telegram.callbacks.CallbackHandler;

import static weatherproject.tgbotservice.utils.Constants.*;

@Service
@Slf4j
@RequiredArgsConstructor
public class BotHandler {
private final TelegramBot bot;
private final UserServiceClient userServiceClient;
private final WeatherServiceClient weatherServiceClient;
private final CallbackHandler callbackHandler;

public void handleUpdate(Update update) {
var chatId = update.message().chat().id();

var currentUser = userServiceClient.getUserById(chatId);
UserState currentState = UserState.valueOf(currentUser.getState());

var text = update.message().text();
//TODO: вынести свитч кейс в отдельный класс обработчик команды
//Проверяем если введена слеш команда
switch (text) {
case "/start":
if (currentUser.getState().equals("ALREADY_USER")) {
//Если у пользователя уже выставлен город, то говорим текущую погоду и предлагаем поставить новый город
bot.execute(new SendMessage(chatId, ALREADY_USER.replace("{city}", currentUser.getCity())));
} else {
//Если нет, то просто добавляем пользователя в бд и ставим нулл город
userServiceClient.createUser(new UserDTO(chatId, "null", UserState.START.toString()));
}
break;

case "/help":
bot.execute(new SendMessage(chatId, HELP_MESSAGE));
break;

case "/update":
//Если у пользователя нет города, то выводим сообщение, что город not set
if (currentUser.getCity().equals("null")) {
bot.execute(new SendMessage(chatId, CITY_NOT_SET));
} else {
//в ином случае предоставляем текущую погоду о городе
bot.execute(new SendMessage(chatId, weatherServiceClient.getFormattedWeatherByCity(currentUser.getCity())));
}
break;
default: {
callbackHandler.handleCallback(currentUser, update);
}
}


}
}

Loading

0 comments on commit dc9aed6

Please sign in to comment.