first
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -38,3 +38,7 @@ pyvenv.cfg
|
||||
.venv
|
||||
pip-selfcheck.json
|
||||
|
||||
|
||||
|
||||
currency_log.csv
|
||||
.vscode
|
||||
31
CsvWriter.java
Normal file
31
CsvWriter.java
Normal 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
35
CurrencyAnalyzer.java
Normal 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
25
CurrencyParser.java
Normal 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
38
Main.java
Normal 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
45
TelegramNotifier.java
Normal 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
30
WebLoader.java
Normal 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 "";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user