This commit is contained in:
2026-05-31 13:36:33 +05:00
parent 19f6475573
commit 94d47092af
7 changed files with 208 additions and 0 deletions

4
.gitignore vendored
View File

@@ -38,3 +38,7 @@ pyvenv.cfg
.venv .venv
pip-selfcheck.json pip-selfcheck.json
currency_log.csv
.vscode

31
CsvWriter.java Normal file
View File

@@ -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();
}
}
}

35
CurrencyAnalyzer.java Normal file
View File

@@ -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 = "<b>Мониторинг курса USD запущен</b>\n" +
"Текущий курс: <b>" + current + "</b> ₽";
TelegramNotifier.sendMessage(start_msg);
System.out.println("Начальное значение USD: " + current);
return;
}
String msg = "";
if (current > last_value) {
msg = "Курс доллара <b>вырос ↑</b>";
} else if (current < last_value) {
msg = "Курс доллара <b>упал ↓</b>";
} else {
return;
}
String telegram_msg = msg + "\n" +
"Было: <b>" + last_value + "</b> ₽\n" +
"Стало: <b>" + current + "</b> ₽";
TelegramNotifier.sendMessage(telegram_msg);
System.out.println(msg.replace("<b>", "").replace("</b>", "") +
" (было " + last_value + ", стало " + current + ")");
last_value = current;
}
}

25
CurrencyParser.java Normal file
View File

@@ -0,0 +1,25 @@
import java.util.regex.*;
public class CurrencyParser {
public static double parseUSD(String html) {
Pattern pattern = Pattern.compile(
"<td>USD</td>\\s*" +
"<td>1</td>\\s*" +
"<td>Доллар США</td>\\s*" +
"<td>([0-9,]+)</td>",
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;
}
}

38
Main.java Normal file
View File

@@ -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();
}
}
}
}

45
TelegramNotifier.java Normal file
View File

@@ -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();
}
}
}

30
WebLoader.java Normal file
View File

@@ -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<String> response = CLIENT.send(
request,
HttpResponse.BodyHandlers.ofString());
return response.body();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
return "";
}
}
}