diff --git a/cronjob.py b/cronjob.py new file mode 100755 index 0000000..986d007 --- /dev/null +++ b/cronjob.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +from fosspay.objects import * +from fosspay.database import db +from fosspay.config import _cfg +from fosspay.email import send_thank_you, send_declined + +from datetime import datetime, timedelta + +import stripe + +stripe.api_key = _cfg("stripe-secret") + +print("Processing monthly donations") + +donations = Donation.query \ + .filter(Donation.type == DonationType.monthly) \ + .filter(Donation.active) \ + .all() + +limit = datetime.now() - timedelta(days=30) + +for donation in donations: + if donation.updated < limit: + print("Charging {}".format(donation)) + user = donation.user + customer = stripe.Customer.retrieve(user.stripe_customer) + try: + charge = stripe.Charge.create( + amount=donation.amount, + currency="usd", + customer=user.stripe_customer, + description="Donation to " + _cfg("your-name") + ) + except stripe.error.CardError as e: + donation.active = False + db.commit() + send_declined(user, donation.amount) + print("Declined") + continue + + send_thank_you(user, donation.amount, donation.type == DonationType.monthly) + donation.updated = datetime.now() + db.commit() + else: + print("Skipping {}".format(donation)) + +print("Done. {} records processed.".format(len(donations))) diff --git a/emails/declined b/emails/declined new file mode 100644 index 0000000..7cf6fdc --- /dev/null +++ b/emails/declined @@ -0,0 +1,12 @@ +An attempt was just made to charge your card for your monthly donation to +{{your_name}} for ${{amount}}. Unfortunately, your card was declined. + +The donation has been disabled. If you would like to, you may create a new +recurring donation here: + +{{root}} + +Thanks! + +-- +{{your_name}} diff --git a/fosspay/email.py b/fosspay/email.py index 561d61c..49834f4 100644 --- a/fosspay/email.py +++ b/fosspay/email.py @@ -51,3 +51,23 @@ def send_password_reset(user): message['To'] = user.email smtp.sendmail(_cfg("smtp-from"), [ user.email ], message.as_string()) smtp.quit() + +def send_declined(user, amount): + if _cfg("smtp-host") == "": + return + smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port")) + smtp.login(_cfg("smtp-user"), _cfg("smtp-password")) + with open("emails/declined") as f: + message = MIMEText(html.parser.HTMLParser().unescape(\ + pystache.render(f.read(), { + "user": user, + "root": _cfg("protocol") + "://" + _cfg("domain"), + "your_name": _cfg("your-name"), + "amount": "{:.2f}".format(amount / 100) + }))) + message['X-MC-PreserveRecipients'] = "false" + message['Subject'] = "Your monthly donation was declined." + message['From'] = _cfg("smtp-from") + message['To'] = user.email + smtp.sendmail(_cfg("smtp-from"), [ user.email ], message.as_string()) + smtp.quit()