157 lines
5.7 KiB
Java
157 lines
5.7 KiB
Java
package auctiora;
|
|
|
|
import javax.mail.Authenticator;
|
|
import javax.mail.Message.RecipientType;
|
|
import javax.mail.PasswordAuthentication;
|
|
import javax.mail.Session;
|
|
import javax.mail.Transport;
|
|
import javax.mail.internet.InternetAddress;
|
|
import javax.mail.internet.MimeMessage;
|
|
import java.awt.SystemTray;
|
|
import java.awt.Toolkit;
|
|
import java.awt.TrayIcon;
|
|
import java.awt.TrayIcon.MessageType;
|
|
import java.util.Date;
|
|
import java.util.Properties;
|
|
/**
|
|
* Service for sending notifications via desktop notifications and/or email.
|
|
* Supports free notification methods:
|
|
* 1. Desktop notifications (Windows/Linux/macOS system tray)
|
|
* 2. Email via Gmail SMTP (free, requires app password)
|
|
*
|
|
* Configuration:
|
|
* - For email: Set notificationEmail to your Gmail address
|
|
* - Enable 2FA in Gmail and create an App Password
|
|
* - Use format "smtp:username:appPassword:toEmail" for credentials
|
|
* - Or use "desktop" for desktop-only notifications
|
|
*/
|
|
class NotificationService {
|
|
|
|
private final boolean useDesktop;
|
|
private final boolean useEmail;
|
|
private final String smtpUsername;
|
|
private final String smtpPassword;
|
|
private final String toEmail;
|
|
|
|
/**
|
|
* Creates a notification service.
|
|
*
|
|
* @param config "desktop" for desktop only, or "smtp:username:password:toEmail" for email
|
|
* @param unusedParam Kept for compatibility (can pass empty string)
|
|
*/
|
|
NotificationService(String config, String unusedParam) {
|
|
|
|
if ("desktop".equalsIgnoreCase(config)) {
|
|
this.useDesktop = true;
|
|
this.useEmail = false;
|
|
this.smtpUsername = null;
|
|
this.smtpPassword = null;
|
|
this.toEmail = null;
|
|
} else if (config.startsWith("smtp:")) {
|
|
var parts = config.split(":", 4);
|
|
if (parts.length != 4) {
|
|
throw new IllegalArgumentException("Email config must be 'smtp:username:password:toEmail'");
|
|
}
|
|
this.useDesktop = true; // Always include desktop
|
|
this.useEmail = true;
|
|
this.smtpUsername = parts[1];
|
|
this.smtpPassword = parts[2];
|
|
this.toEmail = parts[3];
|
|
} else {
|
|
throw new IllegalArgumentException("Config must be 'desktop' or 'smtp:username:password:toEmail'");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sends notification via configured channels.
|
|
*
|
|
* @param message The message body
|
|
* @param title Message title
|
|
* @param priority Priority level (0=normal, 1=high)
|
|
*/
|
|
void sendNotification(String message, String title, int priority) {
|
|
if (useDesktop) {
|
|
sendDesktopNotification(title, message, priority);
|
|
}
|
|
if (useEmail) {
|
|
sendEmailNotification(title, message, priority);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sends a desktop notification using system tray.
|
|
* Works on Windows, macOS, and Linux with desktop environments.
|
|
*/
|
|
private void sendDesktopNotification(String title, String message, int priority) {
|
|
try {
|
|
if (SystemTray.isSupported()) {
|
|
var tray = SystemTray.getSystemTray();
|
|
var image = Toolkit.getDefaultToolkit()
|
|
.createImage(new byte[0]); // Empty image
|
|
|
|
var trayIcon = new TrayIcon(image, "Troostwijk Scraper");
|
|
trayIcon.setImageAutoSize(true);
|
|
|
|
var messageType = priority > 0
|
|
? MessageType.WARNING
|
|
: MessageType.INFO;
|
|
|
|
tray.add(trayIcon);
|
|
trayIcon.displayMessage(title, message, messageType);
|
|
|
|
// Remove icon after 2 seconds to avoid clutter
|
|
Thread.sleep(2000);
|
|
tray.remove(trayIcon);
|
|
|
|
Console.println("Desktop notification sent: " + title);
|
|
} else {
|
|
Console.println("Desktop notifications not supported, logging: " + title + " - " + message);
|
|
}
|
|
} catch (Exception e) {
|
|
System.err.println("Desktop notification failed: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sends email notification via Gmail SMTP (free).
|
|
* Uses Gmail's SMTP server with app password authentication.
|
|
*/
|
|
private void sendEmailNotification(String title, String message, int priority) {
|
|
try {
|
|
var props = new Properties();
|
|
props.put("mail.smtp.auth", "true");
|
|
props.put("mail.smtp.starttls.enable", "true");
|
|
props.put("mail.smtp.host", "smtp.gmail.com");
|
|
props.put("mail.smtp.port", "587");
|
|
props.put("mail.smtp.ssl.trust", "smtp.gmail.com");
|
|
|
|
var session = Session.getInstance(props,
|
|
new Authenticator() {
|
|
|
|
protected PasswordAuthentication getPasswordAuthentication() {
|
|
return new PasswordAuthentication(smtpUsername, smtpPassword);
|
|
}
|
|
});
|
|
|
|
var msg = new MimeMessage(session);
|
|
msg.setFrom(new InternetAddress(smtpUsername));
|
|
msg.setRecipients(RecipientType.TO,
|
|
InternetAddress.parse(toEmail));
|
|
msg.setSubject("[Troostwijk] " + title);
|
|
msg.setText(message);
|
|
msg.setSentDate(new Date());
|
|
|
|
if (priority > 0) {
|
|
msg.setHeader("X-Priority", "1");
|
|
msg.setHeader("Importance", "High");
|
|
}
|
|
|
|
Transport.send(msg);
|
|
Console.println("Email notification sent: " + title);
|
|
|
|
} catch (Exception e) {
|
|
System.err.println("Email notification failed: " + e.getMessage());
|
|
}
|
|
}
|
|
}
|