diff options
Diffstat (limited to 'subsonic-backend/src/main/java/net/sourceforge/subsonic/backend/service/LicenseGenerator.java')
-rw-r--r-- | subsonic-backend/src/main/java/net/sourceforge/subsonic/backend/service/LicenseGenerator.java | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/subsonic-backend/src/main/java/net/sourceforge/subsonic/backend/service/LicenseGenerator.java b/subsonic-backend/src/main/java/net/sourceforge/subsonic/backend/service/LicenseGenerator.java new file mode 100644 index 00000000..77376a8e --- /dev/null +++ b/subsonic-backend/src/main/java/net/sourceforge/subsonic/backend/service/LicenseGenerator.java @@ -0,0 +1,170 @@ +package net.sourceforge.subsonic.backend.service; + +import net.sourceforge.subsonic.backend.dao.PaymentDao; +import net.sourceforge.subsonic.backend.domain.Payment; +import org.apache.commons.codec.binary.Hex; +import org.apache.log4j.Logger; + +import javax.mail.MessagingException; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * Runs a task at regular intervals, checking for incoming donations and sending + * out license keys by email. + * + * @author Sindre Mehus + * @version $Id$ + */ +public class LicenseGenerator { + + private static final Logger LOG = Logger.getLogger(LicenseGenerator.class); + private static final long DELAY = 60; // One minute. + + private PaymentDao paymentDao; + private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + + public void init() { + Runnable task = new Runnable() { + public void run() { + try { + LOG.info("Starting license generator."); + processPayments(); + LOG.info("Completed license generator."); + } catch (Throwable x) { + LOG.error("Failed to process license emails.", x); + } + } + }; + executor.scheduleWithFixedDelay(task, DELAY, DELAY, TimeUnit.SECONDS); + LOG.info("Scheduled license generator to run every " + DELAY + " seconds."); + } + + private void processPayments() throws Exception { + List<Payment> payments = paymentDao.getPaymentsByProcessingStatus(Payment.ProcessingStatus.NEW); + LOG.info(payments.size() + " new payment(s)."); + if (payments.isEmpty()) { + return; + } + + EmailSession emailSession = new EmailSession(); + for (Payment payment : payments) { + processPayment(payment, emailSession); + } + } + + private void processPayment(Payment payment, EmailSession emailSession) { + try { + LOG.info("Processing " + payment); + String email = payment.getPayerEmail(); + if (email == null) { + throw new Exception("Missing email address."); + } + + boolean eligible = isEligible(payment); + boolean ignorable = isIgnorable(payment); + if (eligible) { + sendLicenseTo(email, emailSession); + LOG.info("Sent license key for " + payment); + } else { + LOG.info("Payment not eligible for " + payment); + } + + if (eligible || ignorable) { + payment.setProcessingStatus(Payment.ProcessingStatus.COMPLETED); + payment.setLastUpdated(new Date()); + paymentDao.updatePayment(payment); + } + + } catch (Throwable x) { + LOG.error("Failed to process " + payment, x); + } + } + + private boolean isEligible(Payment payment) { + String status = payment.getPaymentStatus(); + if ("echeck".equalsIgnoreCase(payment.getPaymentType())) { + return "Pending".equalsIgnoreCase(status) || "Completed".equalsIgnoreCase(status); + } + return "Completed".equalsIgnoreCase(status); + } + + private boolean isIgnorable(Payment payment) { + String status = payment.getPaymentStatus(); + return "Denied".equalsIgnoreCase(status) || + "Reversed".equalsIgnoreCase(status) || + "Refunded".equalsIgnoreCase(status); + } + + public void sendLicenseTo(String to, EmailSession emailSession) throws MessagingException { + emailSession.sendMessage("subsonic_donation@activeobjects.no", + Arrays.asList(to), + null, + Arrays.asList("subsonic_donation@activeobjects.no", "sindre@activeobjects.no"), + Arrays.asList("subsonic_donation@activeobjects.no"), + "Subsonic License", + createLicenseContent(to)); + LOG.info("Sent license to " + to); + } + + private String createLicenseContent(String to) { + String license = md5Hex(to.toLowerCase()); + + return "Dear Subsonic donor,\n" + + "\n" + + "Many thanks for your kind donation to Subsonic!\n" + + "Please find your license key below.\n" + + "\n" + + "Email: " + to + "\n" + + "License: " + license + " \n" + + "\n" + + "To install the license key, click the \"Donate\" link in the top right corner of the Subsonic web interface.\n" + + "\n" + + "More info here: http://subsonic.org/pages/getting-started.jsp#3\n" + + "\n" + + "This license is valid for personal, non-commercial of Subsonic. For commercial use, please contact us for licensing options.\n" + + "\n" + + "Thanks again for supporting the project!\n" + + "\n" + + "Best regards,\n" + + "The Subsonic team"; + } + + /** + * Calculates the MD5 digest and returns the value as a 32 character hex string. + * + * @param s Data to digest. + * @return MD5 digest as a hex string. + */ + private String md5Hex(String s) { + if (s == null) { + return null; + } + + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + return new String(Hex.encodeHex(md5.digest(s.getBytes("UTF-8")))); + } catch (Exception x) { + throw new RuntimeException(x.getMessage(), x); + } + } + + public void setPaymentDao(PaymentDao paymentDao) { + this.paymentDao = paymentDao; + } + + public static void main(String[] args) throws Exception { + String address = args[0]; +// String license = md5Hex(address.toLowerCase()); +// System.out.println("Email: " + address); +// System.out.println("License: " + license); + + LicenseGenerator generator = new LicenseGenerator(); + generator.sendLicenseTo(address, new EmailSession()); + } +} |