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