From 9c565598f95bba22032b34a8baad2de3d31d55d7 Mon Sep 17 00:00:00 2001 From: Thiflict <121az348@gmail.com> Date: Mon, 20 Apr 2026 20:35:07 +0500 Subject: [PATCH 1/4] =?UTF-8?q?#4=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=B8=D0=BD=D0=B4=D0=B8=D0=BA=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B5=20=D0=BE=20=D1=84=D0=B0=D0=BD=D1=82=D0=BE?= =?UTF-8?q?=D0=BC=D0=BD=D0=BE=D0=B9=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B5?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=20=D1=80=D0=B0=D0=B7=D0=BC=D0=BE=D0=BD?= =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8=20=D1=83?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B9=D1=81=D1=82=D0=B2=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/Main.kt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index de75146..5f007f7 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -274,7 +274,11 @@ class USBVirusScanner { currentState = SystemState.IDLE - } catch (e: Exception) { + } catch (e: kotlinx.coroutines.CancellationException) { + currentState = SystemState.IDLE + println(if (isDebug) "Программа получила CancellationException. Возврат к состоянию IDLE." else "") + } + catch (e: Exception) { println(if (isDebug) "❌ Критическая ошибка: ${e.message}" else "") e.printStackTrace() currentState = SystemState.ERROR @@ -513,7 +517,7 @@ class USBVirusScanner { } } - + fun shutdown() { println(if (isDebug) "\nЗавершение работы..." else "") isRunning = false @@ -649,7 +653,8 @@ fun main(args: Array) { } } catch (e: Exception) { println(if (isDebug) "❌ Критическая ошибка: ${e.message}" else "") - e.printStackTrace() + if (isDebug) e.printStackTrace() + if (isDebug) println("Общий Exception") scanner.shutdown() exitProcess(1) } From 68d2678305605ce0068f316809ef6e6f9343944c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=88=D0=BA=D0=BE=D1=84=D0=BB=D0=B8=D0=BA?= =?UTF-8?q?=D1=82?= <121az348@gmail.com> Date: Mon, 20 Apr 2026 15:36:18 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B8=D1=82=D1=8C?= =?UTF-8?q?=20install=5Fscript.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Удалён из-за ненадобности. Signed-off-by: Кошкофликт <121az348@gmail.com> --- install_script.sh | 81 ----------------------------------------------- 1 file changed, 81 deletions(-) delete mode 100644 install_script.sh diff --git a/install_script.sh b/install_script.sh deleted file mode 100644 index 9f72b39..0000000 --- a/install_script.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/bash -# Description: Скрипт для корректной загрузки и установки программы RPIVirusScanner -# Author: Шафеев "Thiflict" Марат -# Date: 2026-04-14 - -# Так как скрипт не тестировался должным образом, необходимо запросить у пользователя о его намерениях продолжать выполнение скрипта. -read -p "ВНИМАНИЕ!!! Данный скрипт установки не тестировался должным образом! Это значит, что скрипт может поломать некоторые конфиги ClamAV и Samba КАК МИНИМУМ! Для продолжения введите: 'i understand all the risks and want to continue'. Это будет означать, что вы понимаете риски и хотите продолжить выполнение программы! " answer -answer=${answer,,} - -if [[ "$answer" != "i understand all the risks and want to continue" ]]; then - echo "Неправильно набрана фраза для продолжения. Отменяю..." - exit 0 -fi -echo "Выполняю..." - -# Обновление списков пакетов и зарузка зависимостей -apt update; -apt install openjdk-21-jdk gpiod libgpiod-dev clamav clamav-daemon ntfs-3g usbmount samba -y; # Загрузка нужных пактов - -# Настройка либы для взаимодействия с GPIO -echo "Подготовка библиотек взаимодействия с GPIO..." -sudo usermod -a -G gpio,spi,i2c $USER; -newgrp gpio; - -# Настройка ClamAV -echo "Настройка ClamAV" -{ - echo "PrivateMirror https://clamav-mirror.ru"; - echo "PrivateMirror https://mirror.truenetwork.ru/clamav/"; - echo "PrivateMirror http://mirror.truenetwork.ru/clamav/"; - echo "ScriptedUpdates no"; -} >> /etc/clamav/freshclam.conf; -rm /var/lib/clamav/freshclam.dat; -freshclam -vvv; - -CONFIG_FILE="/etc/clamav/clamd.conf"; # Путь к файлу конфига -NEW_VALUE_MT="10"; # Новое значение MaxThreads -NEW_VALUE_MF="10M"; # Новое значение MaxFileSize -NEW_VALUE_MS="30M"; # Новое значение MaxScanSize - -cp "$CONFIG_FILE" "$CONFIG_FILE.bak"; # Создание бекапа конфига -sed -i -E " - s/^(MaxThreads[[:space:]]+).*/\1$NEW_VALUE_MT/ - s/^(MaxFileSize[[:space:]]+).*/\1$NEW_VALUE_MF/ - s/^(MaxScanSize[[:space:]]+).*/\1$NEW_VALUE_MS/ -" "$CONFIG_FILE"; # Изменение конфига - -# Загрузка временных файлов -echo "Загрузка необходиых временных файлов..." -rm -rf /tmp/rpivs; -mkdir /tmp/rpivs; -wget https://static1.thiflict.ru/raspberrypi_virus_scanner/v2.0/smb_conf -o /tmp/rpivs/smb.conf -wget https://static1.thiflict.ru/raspberrypi_virus_scanner/v2.0/rpivirusscanner.jar -o /tmp/rpivs/rpivirusscanner.jar; -wget https://static1.thiflict.ru/raspberrypi_virus_scanner/v2.0/rpi_virus_scanner_service -o /tmp/rpivs/rpi_virus_scanner.service; - -# Настройка Samba -echo "Выполняется настройка Samba" -systemctl stop smbd -systemctl disable smbd -cp /tmp/rpivs/smb.conf /etc/samba/smb.conf -testparm # Для дебага - -# Установка программы -echo "Установка программы..." -rm -rf /opt/thiflict-dev/rpi-virus-scanner/ -mkdir -p /opt/thiflict-dev/rpi-virus-scanner/ -mv /tmp/rpivs/rpivirusscanner.jar /opt/thiflict-dev/rpi-virus-scanner/; - -# Создание демона -echo "Создание демона RPIVirusScanner..." -mv /tmp/rpivs/rpi_virus_scanner.service /etc/systemd/system/; -systemctl daemon-reload; -systemctl enable rpi_virus_scanner.service; - -# Авторство: -echo "RaspberryPi успешно установлен! Рекомендуется перезагрузить устройство."; -echo " "; -echo "==== Об авторе: ===="; -echo "Репозиторий проекта: https://git.ds1.thiflict.ru/Shafeev-CourseWork/Practice-Part"; -echo "Телеграм-канал: https://t.me/Thiflict_tg"; -echo "YouTube канал: https://youtube.com/@Thiflict"; \ No newline at end of file From d25f82d0f1d19c9f9cd2a9b240c78fbb2cbb9d83 Mon Sep 17 00:00:00 2001 From: Thiflict <121az348@gmail.com> Date: Mon, 20 Apr 2026 20:41:04 +0500 Subject: [PATCH 3/4] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3:=20=D0=B1=D0=B5=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D1=89=D0=B0=D0=B4=D0=BD=D0=BE=20=D0=B2=D1=8B=D1=80=D0=B5=D0=B7?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=20=D1=83=D0=BF=D0=BE=D0=BC=D0=B8=D0=BD=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BE=20=D1=81=D0=BA=D1=80=D0=B8=D0=BF?= =?UTF-8?q?=D1=82=D0=B5=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B2=20readme.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readme.md | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/readme.md b/readme.md index 8a231f8..98f17c9 100644 --- a/readme.md +++ b/readme.md @@ -32,15 +32,4 @@ > - Первый контакт тактовой кнопки: GPIO 24 (Физический пин 18) -> - Второй контакт тактовой кнопки: Любой из GND (Физические пины: 6, 9, 14, 20, 25, 30, 34, 39) - -Для загрузки можно также воспользоваться скриптом установки. **(НЕ ТЕСТИРОВАН!)** -Для этого его необходимо загрузить из релиза или из исходника, затем сделать его executable - -```bash -sudo chmod +x install_script.sh -``` -Затем, выполнить его от имени суперпользователя: -```bash -sudo ./install_script.sh -``` \ No newline at end of file +> - Второй контакт тактовой кнопки: Любой из GND (Физические пины: 6, 9, 14, 20, 25, 30, 34, 39) \ No newline at end of file From 851e5c25eb2d4d4a6f97d9d17f9a56b00dfa1d4b Mon Sep 17 00:00:00 2001 From: Thiflict <121az348@gmail.com> Date: Mon, 20 Apr 2026 21:21:07 +0500 Subject: [PATCH 4/4] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3:=20=D0=A7=D0=B8=D1=81=D1=82=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=BA=D0=BE=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/ButtonListener.kt | 26 +---- src/main/kotlin/GPIOController.kt | 25 ++--- src/main/kotlin/Main.kt | 161 +++++++----------------------- 3 files changed, 46 insertions(+), 166 deletions(-) diff --git a/src/main/kotlin/ButtonListener.kt b/src/main/kotlin/ButtonListener.kt index fd38e1e..08bf776 100644 --- a/src/main/kotlin/ButtonListener.kt +++ b/src/main/kotlin/ButtonListener.kt @@ -6,6 +6,7 @@ import ru.thiflict.PinConfig.BUTTON import java.io.BufferedReader import java.io.InputStreamReader import java.util.concurrent.atomic.AtomicBoolean +import kotlin.time.Duration.Companion.milliseconds class ButtonClickEvent class ButtonLongPressEvent @@ -31,18 +32,10 @@ class ButtonListener( clickListeners.add(listener) } - fun removeClickListener(listener: ButtonClickListener) { - clickListeners.remove(listener) - } - fun addLongPressListener(listener: ButtonLongPressListener) { longPressListeners.add(listener) } - fun removeLongPressListener(listener: ButtonLongPressListener) { - longPressListeners.remove(listener) - } - private fun notifyClick() { println("=== [CLICK] Короткое нажатие ===") val event = ButtonClickEvent() @@ -93,7 +86,6 @@ class ButtonListener( onStateChange?.invoke(false) println(if (isDebug) "Кнопка отпущена, длительность: ${pressDuration}ms" else "") - // Определяем тип нажатия по длительности when { pressDuration >= longPressThresholdMs -> { println(if (isDebug) "Длинное нажатие (${pressDuration}ms)" else "") @@ -118,10 +110,9 @@ class ButtonListener( println("Процесс завершён ($exitCode)") isListening.set(false) - // Автоматически перезапускаем прослушивание, если оно должно быть активно if (isListening.get()) { println("Перезапуск прослушивания...") - delay(100) + delay(100.milliseconds) startListeningInternal(onStateChange) } } @@ -130,17 +121,4 @@ class ButtonListener( isListening.set(false) } } - - fun stopListening() { - isListening.set(false) - listenerJob?.cancel() - process?.destroy() - process = null - } - - fun restartListening(onStateChange: ((Boolean) -> Unit)? = null) { - stopListening() - Thread.sleep(200) - startListening(onStateChange) - } } \ No newline at end of file diff --git a/src/main/kotlin/GPIOController.kt b/src/main/kotlin/GPIOController.kt index f4278fc..4c48568 100644 --- a/src/main/kotlin/GPIOController.kt +++ b/src/main/kotlin/GPIOController.kt @@ -6,18 +6,15 @@ class GPIOController(private val pin: Int) { fun setValue(value: Int) { try { - // Пробуем разные варианты синтаксиса gpioset val commands = listOf("gpioset", "--chip=0", "$pin=$value") - - try { - val process = ProcessBuilder(commands) - .redirectErrorStream(true) - .start() - Thread.sleep(50) - process.destroy() - } catch (e: Exception) { - // Пробуем следующую команду - } + try { + val process = ProcessBuilder(commands) + .redirectErrorStream(true) + .start() + Thread.sleep(30) + process.destroy() + } catch (_: Exception) { + } } catch (e: Exception) { println(if (isDebug) "Ошибка установки GPIO $pin = $value: ${e.message}" else "") @@ -38,10 +35,4 @@ class GPIOController(private val pin: Int) { 0 } } - - fun close() { - // Ничего не делаем - } - - } \ No newline at end of file diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 5f007f7..4803df4 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -10,7 +10,6 @@ import java.util.* import java.util.concurrent.* import kotlin.time.Duration.Companion.milliseconds -// Конфигурация GPIO (BCM номера) object PinConfig { const val GREEN_LED = 17 const val YELLOW_LED = 27 @@ -26,7 +25,6 @@ object DebugMode { } } -// Состояния системы enum class SystemState { IDLE, SCANNING, CLEAN, INFECTED, ERROR, INIT, SAMBA } @@ -48,22 +46,19 @@ class USBVirusScanner { println(if (isDebug) "Инициализация..." else "") try { - // Проверяем доступность gpiod - checkLibgpiod() + checkLibgpiod() // Проверка установленных библиотек greenLed = GPIOController(PinConfig.GREEN_LED) yellowLed = GPIOController(PinConfig.YELLOW_LED) redLed = GPIOController(PinConfig.RED_LED) - // Выключаем все светодиоды greenLed.setValue(0) yellowLed.setValue(0) redLed.setValue(0) - // Запускаем индикацию состояния - startStateIndication() + startStateIndication() // Запуск системы индикации - antivirusDatabaseUpdater() + antivirusDatabaseUpdater() // Первоначальная проверка обновлений антивирусных баз данных Thread.sleep(1000) @@ -73,7 +68,7 @@ class USBVirusScanner { } catch (e: Exception) { currentState = SystemState.ERROR - println(if (isDebug) "❌ Ошибка инициализации: ${e.message}" else "") + println(if (isDebug) "Ошибка инициализации: ${e.message}" else "") e.printStackTrace() throw e } @@ -89,30 +84,16 @@ class USBVirusScanner { } val output = process.inputStream.bufferedReader().readText() - println(if (isDebug) "✅ libgpiod найден" else "") + println(if (isDebug) "libgpiod найден" else "") if (output.isNotBlank()) { println(if (isDebug) "Доступные чипы: ${output.trim()}" else "") } - } catch (e: Exception) { - throw Exception(if (isDebug) "libgpiod Не установлен!" else "") + } catch (_: Exception) { + throw Exception(if (isDebug) "libgpiod Не установлен" else "") } } - fun buttonPress(defaultButtonState: Boolean): Boolean { - var finalButtonState = defaultButtonState - println(if (isDebug) "Начало finalButtonState: $finalButtonState" else "") - - val buttonListener = ButtonListener() - val initialState = buttonListener.startListening { isPressed -> - if (isPressed) { - finalButtonState = true - } - } - println(if (isDebug) "finalButtonState: $finalButtonState" else "") - return finalButtonState - } - private fun startStateIndication() { indicationJob = scope.launch { while (isRunning) { @@ -205,7 +186,7 @@ class USBVirusScanner { return@launch } - println(if (isDebug) "📀 Найдены USB-устройства:" else "") + println(if (isDebug) "Найдены USB-устройства:" else "") usbDevices.forEach { device -> println(" - ${device.mountPoint}") } @@ -215,31 +196,28 @@ class USBVirusScanner { val scanResults = mutableListOf() for (device in usbDevices) { - println(if (isDebug) "🔍 Сканирование: ${device.mountPoint}" else "") + println(if (isDebug) "Сканирование: ${device.mountPoint}" else "") val result = scanWithClamAV(device.mountPoint) scanResults.add(result) if (result.isInfected) { hasVirus = true - println(if (isDebug) "⚠️ ВНИМАНИЕ! Найдены угрозы!" else "") + println(if (isDebug) "ВНИМАНИЕ! Найдены угрозы!" else "") result.infectedFiles.take(10).forEach { file -> - println(" 🦠 ${file.take(100)}") + println(" - ${file.take(100)}") } if (result.infectedFiles.size > 10) { println(if (isDebug) " ... и ещё ${result.infectedFiles.size - 10} файлов" else "") } unmount() } else if (result.error != null) { - println(if (isDebug) "❌ Ошибка сканирования: ${result.error}" else "") + println(if (isDebug) "Ошибка сканирования: ${result.error}" else "") } else { - println(if (isDebug) "✅ Сканирование завершено: угроз не найдено" else "") + println(if (isDebug) "Сканирование завершено: угроз не найдено" else "") } println() } - // Сохраняем лог - saveScanLog(scanResults) - currentState = if (hasVirus) { SystemState.INFECTED } else { @@ -247,14 +225,13 @@ class USBVirusScanner { } val message = if (hasVirus) { - if (isDebug) "🦠 Найдены вирусы! Красный LED горит" else "" + if (isDebug) "Debug: Найдены вирусы" else "" } else { - if (isDebug) "✅ Флешка чиста! Зелёный LED горит" else "" + if (isDebug) "Debug: Флешка чиста" else "" } println(if (isDebug) message else "") - // Держим состояние 5 секунд - delay(10000.milliseconds) + delay(10000.milliseconds) // Удерживание состояния на 10 секунд if (!hasVirus) { currentState = SystemState.SAMBA @@ -263,7 +240,7 @@ class USBVirusScanner { val buttonListener = ButtonListener() var isEventHappened = false - buttonListener.addLongPressListener { event -> + buttonListener.addLongPressListener { _ -> isEventHappened = true } buttonListener.startListening() @@ -274,12 +251,12 @@ class USBVirusScanner { currentState = SystemState.IDLE - } catch (e: kotlinx.coroutines.CancellationException) { + } catch (_: kotlinx.coroutines.CancellationException) { currentState = SystemState.IDLE println(if (isDebug) "Программа получила CancellationException. Возврат к состоянию IDLE." else "") } catch (e: Exception) { - println(if (isDebug) "❌ Критическая ошибка: ${e.message}" else "") + println(if (isDebug) "Критическая ошибка: ${e.message}" else "") e.printStackTrace() currentState = SystemState.ERROR delay(10000.milliseconds) @@ -293,8 +270,7 @@ class USBVirusScanner { private fun findUSBDevices(): List { val devices = mutableListOf() - try { - // Проверяем /media директории + try { // Проверка директории /media val mediaDirs = listOf("/media", "/media/pi") for (mediaDirPath in mediaDirs) { @@ -319,7 +295,7 @@ class USBVirusScanner { } } - // Проверяем /proc/mounts для дополнительных точек монтирования + // Проверка /proc/mounts не предмет дополнительных точек монтирования val mountsFile = File("/proc/mounts") if (mountsFile.exists()) { mountsFile.readLines().forEach { line -> @@ -351,7 +327,7 @@ class USBVirusScanner { try { // Проверяем установлен ли ClamAV - val checkProcess = ProcessBuilder("which", "clamscan").start() + val checkProcess = ProcessBuilder("which", "clamdscan").start() val checkExitCode = checkProcess.waitFor() if (checkExitCode != 0) { @@ -360,11 +336,11 @@ class USBVirusScanner { infectedFiles = emptyList(), virusNames = emptyMap(), exitCode = -1, - error = if (isDebug) "ClamAV не установлен. Установите: sudo apt install clamav" else "" + error = if (isDebug) "ClamAV не установлен." else "" ) } - // Проверяем существование пути + // Проверка существования пути val pathFile = File(path) if (!pathFile.exists() || !pathFile.isDirectory) { return ScanResult( @@ -376,9 +352,9 @@ class USBVirusScanner { ) } - println(if (isDebug) " Запуск clamscan (это может занять некоторое время)..." else "") + println(if (isDebug) " Запуск clamdcan..." else "") - // Запускаем ClamAV + // Запуск непосредственной антивирусной проверки val processBuilder = ProcessBuilder( "clamdscan", "--multiscan", @@ -393,7 +369,7 @@ class USBVirusScanner { val output = process.inputStream.bufferedReader().readText() val exitCode = process.waitFor() - // Парсим вывод + // Парс вывода output.lines().forEach { line -> if (line.contains(" FOUND")) { val colonIndex = line.indexOf(": ") @@ -415,7 +391,7 @@ class USBVirusScanner { ) } catch (e: Exception) { - println(if (isDebug) "Ошибка при выполнении clamscan: ${e.message}" else "") + println(if (isDebug) "Ошибка при выполнении clamdscan: ${e.message}" else "") return ScanResult( isInfected = false, infectedFiles = emptyList(), @@ -426,47 +402,6 @@ class USBVirusScanner { } } - private fun saveScanLog(results: List) { - try { - val logDir = File("/home/${System.getProperty("user.name")}/usb-scanner-logs") - if (!logDir.exists()) { - logDir.mkdirs() - } - - val timestamp = System.currentTimeMillis() - val logFile = File(logDir, "scan_$timestamp.log") - - logFile.bufferedWriter().use { writer -> - writer.write("=== USB Virus Scanner Log ===\n") - writer.write("Time: ${java.time.LocalDateTime.now()}\n\n") - - results.forEachIndexed { index, result -> - writer.write("Device ${index + 1}:\n") - if (result.isInfected) { - writer.write("Status: INFECTED\n") - writer.write("Found ${result.infectedFiles.size} infected files:\n") - result.infectedFiles.take(20).forEach { file -> - writer.write(" $file: ${result.virusNames[file]}\n") - } - if (result.infectedFiles.size > 20) { - writer.write(" ... and ${result.infectedFiles.size - 20} more files\n") - } - } else if (result.error != null) { - writer.write("Status: ERROR\n") - writer.write("Error: ${result.error}\n") - } else { - writer.write("Status: CLEAN\n") - } - writer.write("\n") - } - } - - println(if (isDebug) "📝 Лог сохранён: ${logFile.absolutePath}" else "") - } catch (e: Exception) { - println(if (isDebug) "Ошибка сохранения лога: ${e.message}" else "") - } - } - suspend fun sambaStartSharing() { try { currentState = SystemState.SAMBA @@ -496,10 +431,9 @@ class USBVirusScanner { process = processBuilder.start() scanJob?.cancel() currentState = SystemState.IDLE - } catch (e: Exception) {} + } catch (_: Exception) {} } - fun unmount() { for (i in 0..9) { val path = if (i == 0) "/media/usb" else "/media/usb$i" @@ -517,7 +451,7 @@ class USBVirusScanner { } } - + fun shutdown() { println(if (isDebug) "\nЗавершение работы..." else "") isRunning = false @@ -527,17 +461,13 @@ class USBVirusScanner { scope.cancel() - // Выключаем все светодиоды try { if (::greenLed.isInitialized) { greenLed.setValue(0) yellowLed.setValue(0) redLed.setValue(0) } - } catch (e: Exception) { - // Игнорируем ошибки при закрытии - } - + } catch (_: Exception) {} println(if (isDebug) "✅ Система остановлена" else "") } } @@ -581,7 +511,7 @@ fun scheduleUpdaterAt3AM() { TimeUnit.MILLISECONDS ) - println("Планировщик запущен. Первый запуск через ${initialDelay / 1000 / 60} минут") + println(if (isDebug) "Планировщик обновления антивирусных баз запущен." else "") } fun antivirusDatabaseUpdater() { @@ -605,14 +535,7 @@ fun main(args: Array) { if (args.contains("--debug")) { DebugMode.enableDebugging() } - scheduleUpdaterAt3AM() - - println(if (isDebug) "Зелёный - ${PinConfig.GREEN_LED}" else "") - println(if (isDebug) "Жёлтый - ${PinConfig.YELLOW_LED}" else "") - println(if (isDebug) "Красный - ${PinConfig.RED_LED}" else "") - println(if (isDebug) "Кнопка - ${PinConfig.BUTTON}" else "") - val scanner = USBVirusScanner() Runtime.getRuntime().addShutdownHook(Thread { @@ -623,36 +546,24 @@ fun main(args: Array) { scanner.initialize() val buttonListener = ButtonListener() - - buttonListener.addClickListener { event -> + buttonListener.addClickListener { _ -> scanner.startScan() } - - buttonListener.addLongPressListener { event -> + buttonListener.addLongPressListener { _ -> scanner.sambaShutdown() } buttonListener.startListening() println( - if (isDebug) """ - ═══════════════════════════════════════ - USB Virus Scanner готов к работе - ═══════════════════════════════════════ - 📌 Вставьте флешку и нажмите кнопку - 📌 Зелёный LED мигает - режим ожидания - 📌 Жёлтый LED мигает - идёт проверка - 📌 Зелёный LED горит - флешка чиста - 📌 Красный LED горит - найдены вирусы - 📌 Для выхода нажмите Ctrl+C - """.trimIndent() else "" + if (isDebug) "!!! ПРОГРАММА ПОЛНОСТЬЮ ГОТОВА К РАБОТЕ !!!" else "" ) while (true) { Thread.sleep(1000) } } catch (e: Exception) { - println(if (isDebug) "❌ Критическая ошибка: ${e.message}" else "") + println(if (isDebug) "Критическая ошибка: ${e.message}" else "") if (isDebug) e.printStackTrace() if (isDebug) println("Общий Exception") scanner.shutdown()