Example #1
0
def send_new_donation(user, donation):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/new_donation") 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": currency.amount("{:.2f}".format(
                    donation.amount / 100)),
                "frequency": (" per month"
                    if donation.type == DonationType.monthly else ""),
                "comment": donation.comment or "",
            })))
    message['Subject'] = "New donation on fosspay!"
    message['From'] = _cfg("smtp-from")
    message['To'] = f"{_cfg('your-name')} <{_cfg('your-email')}>"
    message['Date'] = format_datetime(localtime())
    smtp.sendmail(_cfg("smtp-from"), [_cfg('your-email')], message.as_string())
    smtp.quit()
Example #2
0
def send_thank_you(user, amount, monthly):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/thank-you") 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),
                        "monthly": monthly,
                        "your_email": _cfg("your-email"),
                    },
                )
            )
        )
    message["Subject"] = "Thank you for your donation!"
    message["From"] = _cfg("smtp-from")
    message["To"] = user.email
    smtp.sendmail(_cfg("smtp-from"), [user.email], message.as_string())
    smtp.quit()
Example #3
0
def send_password_reset(user):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/reset-password") as f:
        message = MIMEText(
            html.parser.HTMLParser().unescape(
                pystache.render(
                    f.read(),
                    {
                        "user": user,
                        "root": _cfg("protocol") + "://" + _cfg("domain"),
                        "your_name": _cfg("your-name"),
                        "your_email": _cfg("your-email"),
                    },
                )
            )
        )
    message["Subject"] = "Reset your donor password"
    message["From"] = _cfg("smtp-from")
    message["To"] = user.email
    smtp.sendmail(_cfg("smtp-from"), [user.email], message.as_string())
    smtp.quit()
Example #4
0
def index():
    if User.query.count() == 0:
        load_config()
        return render_template("setup.html")
    projects = sorted(Project.query.all(), key=lambda p: p.name)
    avatar = "//www.gravatar.com/avatar/" + hashlib.md5(
        _cfg("your-email").encode("utf-8")).hexdigest()
    selected_project = request.args.get("project")
    if selected_project:
        try:
            selected_project = int(selected_project)
        except:
            selected_project = None
    active_recurring = (Donation.query.filter(
        Donation.type == DonationType.monthly).filter(
            Donation.active == True).filter(Donation.hidden == False))
    recurring_count = active_recurring.count()
    recurring_sum = sum([d.amount for d in active_recurring])

    access_token = _cfg("patreon-access-token")
    campaign = _cfg("patreon-campaign")
    if access_token and campaign:
        try:
            import patreon
            client = patreon.API(access_token)
            campaign = client.fetch_campaign()
            attrs = campaign.json_data["data"][0]["attributes"]
            patreon_count = attrs["patron_count"]
            patreon_sum = attrs["pledge_sum"]
        except:
            patreon_count = 0
            patreon_sum = 0
    else:
        patreon_count = 0
        patreon_sum = 0

    liberapay = _cfg("liberapay-campaign")
    if liberapay:
        lp = (requests.get(
            "https://liberapay.com/{}/public.json".format(liberapay))).json()
        lp_count = lp['npatrons']
        lp_sum = int(float(lp['receiving']['amount']) * 100)
        # Convert from weekly to monthly
        lp_sum = lp_sum * 52 // 12
    else:
        lp_count = 0
        lp_sum = 0

    return render_template("index.html",
                           projects=projects,
                           avatar=avatar,
                           selected_project=selected_project,
                           recurring_count=recurring_count,
                           recurring_sum=recurring_sum,
                           patreon_count=patreon_count,
                           patreon_sum=patreon_sum,
                           lp_count=lp_count,
                           lp_sum=lp_sum,
                           currency=currency)
Example #5
0
def inject():
    return {
        'root': _cfg("protocol") + "://" + _cfg("domain"),
        'domain': _cfg("domain"),
        'protocol': _cfg("protocol"),
        'len': len,
        'any': any,
        'request': request,
        'locale': locale,
        'url_for': url_for,
        'file_link': file_link,
        'user': current_user,
        '_cfg': _cfg,
        '_cfgi': _cfgi,
        'debug': app.debug,
        'str': str
    }
Example #6
0
def inject():
    return {
        'root': _cfg("protocol") + "://" + _cfg("domain"),
        'domain': _cfg("domain"),
        'protocol': _cfg("protocol"),
        'len': len,
        'any': any,
        'request': request,
        'locale': locale,
        'url_for': url_for,
        'file_link': file_link,
        'user': current_user,
        '_cfg': _cfg,
        '_cfgi': _cfgi,
        'debug': app.debug,
        'str': str,
        'int': int
    }
Example #7
0
def send_password_reset(user):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    message = MIMEText(
        render_template("emails/reset-password",
                        user=user,
                        root=_cfg("protocol") + "://" + _cfg("domain"),
                        your_name=_cfg("your-name"),
                        your_email=_cfg("your-email")))
    message['Subject'] = "Reset your donor password"
    message['From'] = _cfg("smtp-from")
    message['To'] = user.email
    message['Date'] = format_datetime(localtime())
    smtp.sendmail(_cfg("smtp-from"), [user.email], message.as_string())
    smtp.quit()
Example #8
0
def send_password_reset(user):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/reset-password") as f:
        message = MIMEText(html.parser.HTMLParser().unescape(\
            pystache.render(f.read(), {
                "user": user,
                "root": _cfg("protocol") + "://" + _cfg("domain"),
                "your_name": _cfg("your-name"),
                "your_email": _cfg("your-email")
            })))
    message['Subject'] = "Reset your donor password"
    message['From'] = _cfg("smtp-from")
    message['To'] = user.email
    message['Date'] = format_datetime(localtime())
    smtp.sendmail(_cfg("smtp-from"), [user.email], message.as_string())
    smtp.quit()
Example #9
0
def send_cancellation_notice(user, donation):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    message = MIMEText(
        render_template(
            "emails/cancelled",
            user=user,
            root=_cfg("protocol") + "://" + _cfg("domain"),
            your_name=_cfg("your-name"),
            amount=currency.amount("{:.2f}".format(donation.amount / 100)),
        ))
    message['Subject'] = "A monthly donation on ShleePay has been cancelled"
    message['From'] = _cfg("smtp-from")
    message['To'] = f"{_cfg('your-name')} <{_cfg('your-email')}>"
    message['Date'] = format_datetime(localtime())
    smtp.sendmail(_cfg("smtp-from"), [_cfg('your-email')], message.as_string())
    smtp.quit()
Example #10
0
def send_thank_you(user, amount, monthly):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    message = MIMEText(
        render_template("emails/thank-you",
                        user=user,
                        root=_cfg("protocol") + "://" + _cfg("domain"),
                        your_name=_cfg("your-name"),
                        amount=currency.amount("{:.2f}".format(amount / 100)),
                        monthly=monthly,
                        your_email=_cfg("your-email")))
    message['Subject'] = "Thank you for your donation!"
    message['From'] = _cfg("smtp-from")
    message['To'] = user.email
    message['Date'] = format_datetime(localtime())
    smtp.sendmail(_cfg("smtp-from"), [user.email], message.as_string())
    smtp.quit()
Example #11
0
def send_cancellation_notice(user, donation):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/cancelled") 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": currency.amount("{:.2f}".format(
                    donation.amount / 100)),
            })))
    message['Subject'] = "A monthly donation on fosspay has been cancelled"
    message['From'] = _cfg("smtp-from")
    message['To'] = f"{_cfg('your-name')} <{_cfg('your-email')}>"
    message['Date'] = format_datetime(localtime())
    smtp.sendmail(_cfg("smtp-from"), [_cfg('your-email')], message.as_string())
    smtp.quit()
Example #12
0
def index():
    if User.query.count() == 0:
        load_config()
        return render_template("setup.html")
    projects = sorted(Project.query.all(), key=lambda p: p.name)
    avatar = "//www.gravatar.com/avatar/" + hashlib.md5(_cfg("your-email").encode("utf-8")).hexdigest()
    selected_project = request.args.get("project")
    if selected_project:
        try:
            selected_project = int(selected_project)
        except:
            selected_project = None
    return render_template("index.html", projects=projects, avatar=avatar, selected_project=selected_project)
Example #13
0
def send_thank_you(user, amount, monthly):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    with open("emails/thank-you") 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": currency.amount("{:.2f}".format(amount / 100)),
                "monthly": monthly,
                "your_email": _cfg("your-email")
            })))
    message['Subject'] = "Thank you for your donation!"
    message['From'] = _cfg("smtp-from")
    message['To'] = user.email
    message['Date'] = format_datetime(localtime())
    smtp.sendmail(_cfg("smtp-from"), [user.email], message.as_string())
    smtp.quit()
Example #14
0
def send_new_donation(user, donation):
    if _cfg("smtp-host") == "":
        return
    smtp = smtplib.SMTP(_cfg("smtp-host"), _cfgi("smtp-port"))
    smtp.ehlo()
    smtp.starttls()
    smtp.login(_cfg("smtp-user"), _cfg("smtp-password"))
    message = MIMEText(
        render_template(
            "emails/new_donation",
            user=user,
            root=_cfg("protocol") + "://" + _cfg("domain"),
            your_name=_cfg("your-name"),
            amount=currency.amount("{:.2f}".format(donation.amount / 100)),
            frequency=(" per month"
                       if donation.type == DonationType.monthly else ""),
            comment=donation.comment or ""))
    message['Subject'] = "New donation on ShleePay!"
    message['From'] = _cfg("smtp-from")
    message['To'] = f"{_cfg('your-name')} <{_cfg('your-email')}>"
    message['Date'] = format_datetime(localtime())
    smtp.sendmail(_cfg("smtp-from"), [_cfg('your-email')], message.as_string())
    smtp.quit()
Example #15
0
import sys

from fosspay.app import app
from fosspay.objects import *
from fosspay.database import db
from fosspay.config import _cfg
from fosspay.email import send_thank_you, send_declined
from fosspay.currency import currency

from datetime import datetime, timedelta

import requests
import stripe

with app.app_context():
    stripe.api_key = _cfg("stripe-secret")

# Date in global standard
print("Processing monthly donations @ {}".format(
    datetime.now().strftime('%d-%m-%Y %H:%M:%S')))

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))
Example #16
0
from fosspay.config import _cfg


class Currency:
    def __init__(self, symbol, position):
        self.symbol = symbol
        self.position = position

    def amount(self, amount):
        if self.position == "right":
            return amount + self.symbol
        else:
            return self.symbol + amount


currencies = {
    'usd': Currency("$", "left"),
    'eur': Currency("€", "right")
    # ... More currencies can be added here
}

currency = currencies[_cfg("currency")]
Example #17
0
#!/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 requests
import stripe
import subprocess

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",
Example #18
0
#!/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,
Example #19
0
def file_link(path):
    return _cfg("protocol") + "://" + _cfg("domain") + "/" + path
Example #20
0
def logout():
    logout_user()
    return redirect(_cfg("protocol") + "://" + _cfg("domain"))
Example #21
0
def disown_link(path):
    return _cfg("protocol") + "://"  + _cfg("domain") + "/disown?filename=" + path
Example #22
0
#!/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 " +
Example #23
0
import sys
import os
import locale
import stripe

from fosspay.config import _cfg, _cfgi
from fosspay.database import db, init_db
from fosspay.objects import User
from fosspay.common import *
from fosspay.network import *

from fosspay.blueprints.html import html

app = Flask(__name__)
app.secret_key = _cfg("secret-key")
app.jinja_env.cache = None
init_db()
login_manager = LoginManager()
login_manager.init_app(app)

app.jinja_loader = ChoiceLoader([
    FileSystemLoader("overrides"),
    FileSystemLoader("templates"),
])

stripe.api_key = _cfg("stripe-secret")

@login_manager.user_loader
def load_user(email):
    return User.query.filter(User.email == email).first()
Example #24
0
import sys
import os
import locale
import stripe

from fosspay.config import _cfg, _cfgi
from fosspay.database import db, init_db
from fosspay.objects import User
from fosspay.common import *
from fosspay.network import *

from fosspay.blueprints.html import html

app = Flask(__name__)
app.secret_key = _cfg("secret-key")
app.jinja_env.cache = None
init_db()
login_manager = LoginManager()
login_manager.init_app(app)

app.jinja_loader = ChoiceLoader([
    FileSystemLoader("overrides"),
    FileSystemLoader("templates"),
])

stripe.api_key = _cfg("stripe-secret")

@login_manager.user_loader
def load_user(email):
    return User.query.filter(User.email == email).first()
Example #25
0
def file_link(path):
    return _cfg("protocol") + "://" + _cfg("domain") + "/" + path
Example #26
0
def index():
    if User.query.count() == 0:
        load_config()
        return render_template("setup.html")
    projects = sorted(Project.query.all(), key=lambda p: p.name)

    if os.path.exists('static/logo.png'):
        avatar = os.path.join('static/logo.png')
    else:
        avatar = "//www.gravatar.com/avatar/" + hashlib.md5(_cfg("your-email").encode("utf-8")).hexdigest()

    selected_project = request.args.get("project")
    if selected_project:
        try:
            selected_project = int(selected_project)
        except:
            selected_project = None
    active_recurring = (Donation.query
            .filter(Donation.type == DonationType.monthly)
            .filter(Donation.active == True)
            .filter(Donation.hidden == False))
    recurring_count = active_recurring.count()
    recurring_sum = sum([d.amount for d in active_recurring])

    access_token = _cfg("patreon-access-token")
    campaign = _cfg("patreon-campaign")
    if access_token and campaign:
        try:
            import patreon
            client = patreon.API(access_token)
            campaign = client.fetch_campaign()
            attrs = campaign.json_data["data"][0]["attributes"]
            patreon_count = attrs["patron_count"]
            patreon_sum = attrs["pledge_sum"]
        except:
            import traceback
            traceback.print_exc()
            patreon_count = 0
            patreon_sum = 0
    else:
        patreon_count = 0
        patreon_sum = 0

    liberapay = _cfg("liberapay-campaign")
    if liberapay:
        lp = (requests
                .get("https://liberapay.com/{}/public.json".format(liberapay))
            ).json()
        lp_count = lp['npatrons']
        lp_sum = int(float(lp['receiving']['amount']) * 100)
        # Convert from weekly to monthly
        lp_sum = lp_sum * 52 // 12
    else:
        lp_count = 0
        lp_sum = 0
    
    opencollective = _cfg("opencollective-campaign")
    if opencollective:
        oc = requests.get("https://opencollective.com/{}.json".format(opencollective)).json()
        oc_count = oc['backersCount']
        oc_sum = int(oc['yearlyIncome'])
        # Convert from yearly to monthly
        oc_sum = oc_sum // 12
    else:
        oc_count = 0
        oc_sum = 0

    github_token = _cfg("github-token")
    if github_token:
        query = """
        {
            viewer {
                login
                sponsorsListing {
                    tiers(first:100) {
                        nodes {
                            monthlyPriceInCents
                            adminInfo {
                                sponsorships(includePrivate:true) {
                                    totalCount
                                }
                            }
                        }
                    }
                }
            }
        }
        """
        r = requests.post("https://api.github.com/graphql", json={
            "query": query
        }, headers={
            "Authorization": "bearer {}".format(github_token)
        })
        result = r.json()
        nodes = result["data"]["viewer"]["sponsorsListing"]["tiers"]["nodes"]
        cnt = lambda n: n["adminInfo"]["sponsorships"]["totalCount"]
        gh_count = sum(cnt(n) for n in nodes)
        gh_sum = sum(n["monthlyPriceInCents"] * cnt(n) for n in nodes)
        gh_user = result["data"]["viewer"]["login"]
    else:
        gh_count = 0
        gh_sum = 0
        gh_user = 0

    return render_template("index.html", projects=projects,
            avatar=avatar, selected_project=selected_project,
            recurring_count=recurring_count, recurring_sum=recurring_sum,
            patreon_count=patreon_count, patreon_sum=patreon_sum,
            lp_count=lp_count, lp_sum=lp_sum,
            gh_count=gh_count, gh_sum=gh_sum, gh_user=gh_user,
            oc_count=oc_count, oc_sum=oc_sum,
            currency=currency)
Example #27
0
def donate():
    email = request.form.get("email")
    stripe_token = request.form.get("stripe_token")
    amount = request.form.get("amount")
    type = request.form.get("type")
    comment = request.form.get("comment")
    project_id = request.form.get("project")

    # validate and rejigger the form inputs
    if not email or not stripe_token or not amount or not type:
        return {"success": False, "reason": "Invalid request"}, 400
    try:
        if project_id is None or project_id == "null":
            project = None
        else:
            project_id = int(project_id)
            project = Project.query.filter(Project.id == project_id).first()

        if type == "once":
            type = DonationType.one_time
        else:
            type = DonationType.monthly

        amount = int(amount)
    except:
        return {"success": False, "reason": "Invalid request"}, 400

    new_account = False
    user = User.query.filter(User.email == email).first()
    if not user:
        new_account = True
        user = User(email, binascii.b2a_hex(os.urandom(20)).decode("utf-8"))
        user.password_reset = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        user.password_reset_expires = datetime.now() + timedelta(days=1)
        customer = stripe.Customer.create(email=user.email, card=stripe_token)
        user.stripe_customer = customer.id
        db.add(user)
    else:
        customer = stripe.Customer.retrieve(user.stripe_customer)
        new_source = customer.sources.create(source=stripe_token)
        customer.default_source = new_source.id
        customer.save()

    donation = Donation(user, type, amount, project, comment)
    db.add(donation)

    try:
        charge = stripe.Charge.create(amount=amount,
                                      currency=_cfg("currency"),
                                      customer=user.stripe_customer,
                                      description="Donation to " +
                                      _cfg("your-name"))
    except stripe.error.CardError as e:
        db.rollback()
        db.close()
        return {"success": False, "reason": "Your card was declined."}

    db.commit()

    send_thank_you(user, amount, type == DonationType.monthly)

    if new_account:
        return {
            "success": True,
            "new_account": new_account,
            "password_reset": user.password_reset
        }
    else:
        return {"success": True, "new_account": new_account}
Example #28
0
from fosspay.config import _cfg

import stripe

if _cfg("stripe-secret") != "":
    stripe.api_key = _cfg("stripe-secret")
Example #29
0
from fosspay.app import app
from fosspay.config import _cfg, _cfgi

import os

app.static_folder = os.path.join(os.getcwd(), "static")

import os

if __name__ == '__main__':
    app.run(host=_cfg("debug-host"), port=_cfgi('debug-port'), debug=True)
Example #30
0
def logout():
    logout_user()
    return redirect(_cfg("protocol") + "://" + _cfg("domain"))
Example #31
0
def disown_link(path):
    return _cfg("protocol") + "://" + _cfg(
        "domain") + "/disown?filename=" + path
Example #32
0
def donate():
    email = request.form.get("email")
    stripe_token = request.form.get("stripe_token")
    amount = request.form.get("amount")
    type = request.form.get("type")
    comment = request.form.get("comment")
    project_id = request.form.get("project")

    # validate and rejigger the form inputs
    if not email or not stripe_token or not amount or not type:
        return {"success": False, "reason": "Invalid request"}, 400
    try:
        if project_id is None or project_id == "null":
            project = None
        else:
            project_id = int(project_id)
            project = Project.query.filter(Project.id == project_id).first()

        if type == "once":
            type = DonationType.one_time
        else:
            type = DonationType.monthly

        amount = int(amount)
    except:
        return {"success": False, "reason": "Invalid request"}, 400

    new_account = False
    user = User.query.filter(User.email == email).first()
    if not user:
        new_account = True
        user = User(email, binascii.b2a_hex(os.urandom(20)).decode("utf-8"))
        user.password_reset = binascii.b2a_hex(os.urandom(20)).decode("utf-8")
        user.password_reset_expires = datetime.now() + timedelta(days=1)
        customer = stripe.Customer.create(email=user.email, card=stripe_token)
        user.stripe_customer = customer.id
        db.add(user)
    else:
        customer = stripe.Customer.retrieve(user.stripe_customer)
        new_source = customer.sources.create(source=stripe_token)
        customer.default_source = new_source.id
        customer.save()

    donation = Donation(user, type, amount, project, comment)
    db.add(donation)

    try:
        charge = stripe.Charge.create(
            amount=amount, currency="usd", customer=user.stripe_customer, description="Donation to " + _cfg("your-name")
        )
    except stripe.error.CardError as e:
        db.rollback()
        db.close()
        return {"success": False, "reason": "Your card was declined."}

    db.commit()

    send_thank_you(user, amount, type == DonationType.monthly)

    if new_account:
        return {"success": True, "new_account": new_account, "password_reset": user.password_reset}
    else:
        return {"success": True, "new_account": new_account}