diff --git a/.gitignore b/.gitignore index 7cad15f..8c67973 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,7 @@ pyvenv.cfg .venv pip-selfcheck.json + + +currency_log.csv +.vscode \ No newline at end of file diff --git a/CsvWriter.java b/CsvWriter.java new file mode 100644 index 0000000..210c188 --- /dev/null +++ b/CsvWriter.java @@ -0,0 +1,31 @@ +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class CsvWriter { + private static final String FILE_NAME = "currency_log.csv"; + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + private static boolean is_header_written = false; + + public static void write(double value) { + File file = new File(FILE_NAME); + boolean file_exists = file.exists(); + + try (FileWriter writer = new FileWriter(FILE_NAME, true)) { + if (!is_header_written && !file_exists) { + writer.write("Дата и время;Курс USD (руб.)\n"); + is_header_written = true; + } + + String timestamp = LocalDateTime.now().format(FORMATTER); + String line = timestamp + ";" + value + "\n"; + writer.write(line); + + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/CurrencyAnalyzer.java b/CurrencyAnalyzer.java new file mode 100644 index 0000000..7447d0e --- /dev/null +++ b/CurrencyAnalyzer.java @@ -0,0 +1,35 @@ +public class CurrencyAnalyzer { + private static double last_value = -1; + + public static void analyze(double current) { + if (last_value == -1) { + last_value = current; + + String start_msg = "Мониторинг курса USD запущен\n" + + "Текущий курс: " + current + " ₽"; + TelegramNotifier.sendMessage(start_msg); + + System.out.println("Начальное значение USD: " + current); + return; + } + + String msg = ""; + if (current > last_value) { + msg = "Курс доллара вырос ↑"; + } else if (current < last_value) { + msg = "Курс доллара упал ↓"; + } else { + return; + } + + String telegram_msg = msg + "\n" + + "Было: " + last_value + " ₽\n" + + "Стало: " + current + " ₽"; + TelegramNotifier.sendMessage(telegram_msg); + + System.out.println(msg.replace("", "").replace("", "") + + " (было " + last_value + ", стало " + current + ")"); + + last_value = current; + } +} \ No newline at end of file diff --git a/CurrencyParser.java b/CurrencyParser.java new file mode 100644 index 0000000..ddf0504 --- /dev/null +++ b/CurrencyParser.java @@ -0,0 +1,25 @@ +import java.util.regex.*; + +public class CurrencyParser { + public static double parseUSD(String html) { + Pattern pattern = Pattern.compile( + "USD\\s*" + + "1\\s*" + + "Доллар США\\s*" + + "([0-9,]+)", + Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + + Matcher matcher = pattern.matcher(html); + + if (matcher.find()) { + String rateStr = matcher.group(1).replace(',', '.'); + try { + return Double.parseDouble(rateStr); + } catch (NumberFormatException e) { + System.err.println("Ошибка парсинга числа: " + matcher.group(1)); + } + } + + return -1; + } +} \ No newline at end of file diff --git a/Main.java b/Main.java new file mode 100644 index 0000000..b3dc254 --- /dev/null +++ b/Main.java @@ -0,0 +1,38 @@ +public class Main { + public static void main(String[] args) { + String bot_token = System.getenv("BOT_TOKEN"); + String chat_id = System.getenv("CHAT_ID"); + + if (bot_token == null || bot_token.isBlank() || chat_id == null || chat_id.isBlank()) { + System.err.println("Не найдены environment BOT_TOKEN и CHAT_ID"); + return; + } + + TelegramNotifier.init(bot_token, chat_id); + System.out.println("Telegram-уведомления работают."); + + String url = "https://cbr.ru/currency_base/daily/"; + + while (true) { + try { + String html = WebLoader.loadPage(url); + + double usd = CurrencyParser.parseUSD(html); + + if (usd != -1) { + System.out.println("USD: " + usd); + + CsvWriter.write(usd); + CurrencyAnalyzer.analyze(usd); + } else { + System.err.println("Не удалось спарсить курс USD"); + } + + Thread.sleep(60 * 1000); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/TelegramNotifier.java b/TelegramNotifier.java new file mode 100644 index 0000000..d2b36a8 --- /dev/null +++ b/TelegramNotifier.java @@ -0,0 +1,45 @@ +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +public class TelegramNotifier { + private static String bot_token; + private static String chat_id; + + public static void init(String token, String chatId) { + TelegramNotifier.bot_token = token; + TelegramNotifier.chat_id = chatId; + } + + public static void sendMessage(String text) { + if (bot_token == null || chat_id == null || bot_token.isEmpty() || chat_id.isEmpty()) { + return; + } + + try { + String encoded_text = URLEncoder.encode(text, StandardCharsets.UTF_8); + + String url_string = "https://api.telegram.org/bot" + bot_token + + "/sendMessage?chat_id=" + chat_id + + "&text=" + encoded_text + + "&parse_mode=HTML"; + + URL url = new URL(url_string); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.setConnectTimeout(10000); + conn.setReadTimeout(10000); + + int response_code = conn.getResponseCode(); + + if (response_code != 200) { + System.err.println("Ошибка Telegram API: " + response_code); + } + + } catch (Exception e) { + System.err.println("Не удалось отправить сообщение в Telegram:"); + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/WebLoader.java b/WebLoader.java new file mode 100644 index 0000000..0c37502 --- /dev/null +++ b/WebLoader.java @@ -0,0 +1,30 @@ +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +public class WebLoader { + private static final HttpClient CLIENT = HttpClient.newHttpClient(); + + public static String loadPage(String urlString) { + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(urlString)) + .header("User-Agent", "Mozilla/5.0") + .GET() + .build(); + + HttpResponse response = CLIENT.send( + request, + HttpResponse.BodyHandlers.ofString()); + + return response.body(); + + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + + return ""; + } + } +} \ No newline at end of file