Exemplo n.º 1
0
def send(to,
         template,
         subject,
         ns={},
         sender='*****@*****.**',
         cc=[],
         bcc=[]):
    """
    Used to send a transactional email through Postmark's API.

    to          - the recipient's email address.
    template    - a string template path (relative to the app's template root)
    subject     - the subject of the email
    ns          - the template namespace used to render the email content
    sender      - the sender fo the email
    cc          - a list of cc recipients
    bcc         - a list of bcc recipients
    """

    email = EmailTemplate(template, '%s/emails' % conf.app.template_path)

    # If necessary, convert lists to comma-delimited strings
    def _flatten(s):
        return ','.join(s) if isinstance(s, list) else s

    mail = postmark.PMMail(api_key=conf.postmark.api_key,
                           to=_flatten(to),
                           cc=_flatten(cc),
                           bcc=_flatten(bcc),
                           subject=subject,
                           sender=sender,
                           html_body=email.html(ns),
                           text_body=email.text(ns))
    mail.send()
Exemplo n.º 2
0
    def post(self):
        user = self.get_current_user_object()
        if user.stripe_customer_id:
            token_id = self.get_argument("token")
            try:
                customer = stripe.Customer.retrieve(user.stripe_customer_id)
                if customer:
                    customer.source = token_id
                    customer.save()

                    if options.postmark_api_key:
                        pm = postmark.PMMail(
                            api_key=options.postmark_api_key,
                            sender="*****@*****.**",
                            to="*****@*****.**",
                            subject="%s has updated their payment info" %
                            (user.display_name()),
                            text_body=
                            "Buyer Name:%s\nBuyer Email:%s\nUser ID:%s\n" %
                            (user.display_name(), user.email, user.id))
                        pm.send()

                    return self.redirect('/account/settings?update=1')

            except stripe.error.InvalidRequestError:
                pass

        return self.redirect('/account/settings')
Exemplo n.º 3
0
    def post(self):
        user = self.get_current_user_object()
        sub = user.active_paid_subscription()
        if sub:
            try:
                # TBD:
                customer = stripe.Customer.retrieve(user.stripe_customer_id)
                if customer:
                    subscription = customer.subscriptions.retrieve(sub["id"])
                    if subscription:
                        subscription.delete()

                user.is_paid = 0
                user.save()

                if options.postmark_api_key:
                    pm = postmark.PMMail(
                        api_key=options.postmark_api_key,
                        sender="*****@*****.**",
                        to="*****@*****.**",
                        subject="%s has cancelled a subscription" %
                        (user.display_name()),
                        text_body=
                        "Subscription ID: %s\nBuyer Name:%s\nBuyer Email:%s\nUser ID:%s\n"
                        %
                        (sub["id"], user.display_name(), user.email, user.id))
                    pm.send()

                payment_notifications(user, 'cancellation')
            except stripe.error.InvalidRequestError:
                pass
        self.redirect('/account/settings')
Exemplo n.º 4
0
    def post(self):
        user = self.get_current_user_object()
        if user.stripe_customer_id:
            try:
                customer = stripe.Customer.retrieve(user.stripe_customer_id)
                if customer and customer.subscriptions.total_count > 0:
                    subscription = customer.subscriptions.data[0]
                    if subscription:
                        subscription.delete(at_period_end=True)
                        user.stripe_plan_id = user.stripe_plan_id + "-canceled"
                        user.stripe_plan_rate = None
                        user.save()

                        if options.postmark_api_key:
                            pm = postmark.PMMail(
                                api_key=options.postmark_api_key,
                                sender="*****@*****.**",
                                to="*****@*****.**",
                                subject="%s has cancelled a subscription" %
                                (user.display_name()),
                                text_body=
                                "Subscription ID: %s\nBuyer Name:%s\nBuyer Email:%s\nUser ID:%s\n"
                                % (sub["id"], user.display_name(), user.email,
                                   user.id))
                            pm.send()

                        payment_notifications(user, 'cancellation')
            except stripe.error.InvalidRequestError:
                pass
        return self.redirect('/account/settings?cancel=1')
Exemplo n.º 5
0
    def create_reset_password_token(self):
        """
        This function will set the reset token and email the user
        """

        h = hashlib.sha1()
        h.update("%s" % (time.time()))
        h.update("%s" % (random.random()))
        self.reset_password_token = h.hexdigest()
        self.save()
        body = """
Hi there,

We just received a password reset request for this email address (user: %s). If you want to change your password just click this link:
https://%s/account/reset-password/%s

Thanks for using the site!
[email protected]

(If you're having problems with your account, please mail us! We are happy to help.)
""" % (self.name, options.app_host, self.reset_password_token)
        if not options.debug:
            pm = postmark.PMMail(api_key=options.postmark_api_key,
                                 sender="*****@*****.**",
                                 to=self.email,
                                 subject="[mltshp] Password change request",
                                 text_body=body)
            pm.send()
Exemplo n.º 6
0
    def create_for_email(self, email, user_id):
        """
        Creates a voucher for an email address.
        """
        h = hashlib.sha1()
        h.update("%s" % (time.time()))
        h.update("%s" % (email))
        voucher_key = h.hexdigest()
        sending_user = user.User.get('id = %s', user_id)
        voucher = Voucher(offered_by_user_id=user_id,
            voucher_key=voucher_key, email_address=email,
            claimed_by_user_id=0)
        voucher.save()
        if not options.debug:
            text_body = """Hi there. A user on MLTSHP named %s has sent you this invitation to join the site.

You can claim it at this URL:

http://mltshp.com/create-account?key=%s

Be sure to check out the incoming page for fresh files being uploaded, when you find someone you want to keep track of, click the "follow" button on their profile to see their files when you first sign in.

We're adding features and making updates daily so please check back often.

Once you have your account set up, check out:
http://mltshp.com/tools/plugins (browser plugins for saving images)
http://mltshp.com/tools/twitter (connecting your phone's Twitter app to use MLTSHP instead of Twitpic or yFrog)
http://twitter.com/mltshp (our twitter account)
http://mltshp.tumblr.com/ (our blog)

- MLTSHP""" % (sending_user.name, voucher_key)
            html_body = """<p>Hi there. A user on MLTSHP named <a href="http://mltshp.com/user/%s">%s</a> has sent you this invitation to join the site.</p>

<p>You can claim it at this URL:</p>

<p><a href="http://mltshp.com/create-account?key=%s">http://mltshp.com/create-account?key=%s</a></p>

<p>Be sure to check out the <a href="http://mltshp.com/incoming">incoming</a> page for fresh files being uploaded, when you find someone you want to keep track of, click the "follow" button on their profile to see their files when you first sign in.</p>

<p>We&#39;re adding features and making updates daily so please check back often.</p>

<p>Once you have your account set up, check out:</p>
<p>
<a href="http://mltshp.com/tools/plugins">http://mltshp.com/tools/plugins</a> (browser plugins for saving images)<br>
<a href="http://mltshp.com/tools/twitter">http://mltshp.com/tools/twitter</a> (connecting your phone's Twitter app to use MLTSHP instead of Twitpic or yFrog)<br>
<a href="http://twitter.com/mltshp">http://twitter.com/mltshp</a> (our twitter account)<br>
<a href="http://mltshp.tumblr.com/">http://mltshp.tumblr.com/</a> (our blog)
</p>
<p>
- MLTSHP
</p>""" % (sending_user.name,sending_user.name, voucher_key, voucher_key)

            pm = postmark.PMMail(api_key=options.postmark_api_key, 
                sender="*****@*****.**", to=email, 
                subject="An Invitation To MLTSHP", 
                text_body=text_body,
                html_body=html_body)
            pm.send()
        return voucher
Exemplo n.º 7
0
def disabled_notification(addr):
    message = render_template('email/disabled.txt')
    mail = postmark.PMMail(
        api_key=POSTMARK_KEY,
        sender=POSTMARK_SENDER,
        to=addr,
        subject='Ack! A small problem with your Sunlight Foundation API key',
        text_body=message,
    )
    mail.send()
Exemplo n.º 8
0
def contact():

    if request.method == 'POST':

        # verify captcha

        captcha_url = "http://www.google.com/recaptcha/api/verify"

        params = {
            "privatekey": RECAPTCHA_PRIVATE,
            "remoteip": "",
            "challenge": request.form['recaptcha_challenge_field'],
            "response": request.form['recaptcha_response_field'],
        }

        response = requests.post(captcha_url, params=params)

        print response.text

        if not response.text.startswith("true"):
            context = {"form": request.form}
            flash('Sorry, your captcha was incorrect. Please try again.')
            return render_template('contact.html', **context)

        # send email

        msg = "%s <%s>\n" % (request.form['name'], request.form['email'])
        if request.form['organization']:
            msg += "%s\n" % request.form['organization']
        msg += "\n%s\n" % request.form['message']

        kwargs = {
            'api_key':
            POSTMARK_KEY,
            'sender':
            '*****@*****.**',
            'reply_to':
            '%s' % request.form['email'],
            'to':
            '[email protected], [email protected], [email protected], [email protected], [email protected], [email protected]',
            'bcc':
            '*****@*****.**',
            'subject':
            '[OpeningParliament.org] contact: %s <%s>' %
            (request.form['name'], request.form['email']),
            'text_body':
            msg,
        }

        postmark.PMMail(**kwargs).send()

        flash('Your message has been sent. Thank you for contacting us!')
        return redirect('/contact')

    return render_template('contact.html')
Exemplo n.º 9
0
    def send_email(self, **kwargs):
        subject = kwargs.get('subject')
        body = kwargs.get('body')
        to = kwargs.get('to')
        postsig = opt.postmark_signature
        postemail = opt.postmark_sendemail

        sender = postmark.PMMail()
        sender.sender = postemail
        sender.api_key = postsig
        sender.to = to
        sender.html_body = body
        sender.subject = subject
        sender.send(test=False)
Exemplo n.º 10
0
def key_notification(key, addr):
    context = {
        'key': key,
        'email': addr,
    }
    message = render_template('email/success.txt', **context)
    mail = postmark.PMMail(
        api_key=POSTMARK_KEY,
        sender=POSTMARK_SENDER,
        to=addr,
        subject='Here is your brand new Sunlight API key!',
        text_body=message,
    )
    mail.send()
Exemplo n.º 11
0
    def new_subscriber(sender, receiver, action_id):
        """
        sender - user who created the subscription
        receiver - user who is being followed (their shake is)
        action_id - the subscription id
        """
        new_subscription = subscription.Subscription.get('id = %s', action_id)
        target_shake = shake.Shake.get('id = %s', new_subscription.shake_id)
        subscription_line = ""
        if target_shake.type == 'group':
            subscription_line = " called '%s'" % (target_shake.name)
        
        n = Notification(sender_id=sender.id, receiver_id=receiver.id, action_id=action_id, type='subscriber')

        text_message = """Hi, %s.
We wanted to let you know %s is now following your shake%s. If you want to check out their shake you can do so here:

http://mltshp.com/user/%s

You can change your preferences for receiving notifications on your settings page: http://mltshp.com/account/settings

Have a good day.
- MLTSHP
""" % (receiver.name, sender.name, subscription_line, sender.name)
        html_message = """<p>Hi, %s.</p>
<p>                        
We wanted to let you know <a href="http://mltshp.com/user/%s">%s</a> is now following your shake%s. If you want to check out their shake you can do so here:
</p>
<p>
<a href="http://mltshp.com/user/%s">http://mltshp.com/user/%s</a>
</p>
<p>
You can change your preferences for receiving notifications on your settings page: <a href="http://mltshp.com/account/settings">http://mltshp.com/account/settings</a>.
</p>
<p>
Have a good day.<br>
- MLTSHP
</p>
""" % (receiver.name, sender.name, sender.name, subscription_line, sender.name, sender.name)

        n.save()
        
        if not receiver.disable_notifications and not options.debug:
            pm = postmark.PMMail(api_key=options.postmark_api_key, 
                sender="*****@*****.**", to=receiver.email, 
                subject="%s is now following your shake!" % (sender.name), 
                text_body=text_message, 
                html_body=html_message)
            pm.send()
        return n
Exemplo n.º 12
0
    def post(self):
        """
        A method that sends an email requesting a
        zip file of all images.
        """
        user = self.get_current_user_object()

        self.set_secure_cookie('image_request', '1', expires_days=365)
        pm = postmark.PMMail(api_key=options.postmark_api_key,
            sender="*****@*****.**", to="*****@*****.**",
        subject="{0} requests images.".format(user.name),
        text_body="{0} requests images".format(user.name))
        pm.send()

        return self.redirect("/account/settings")
Exemplo n.º 13
0
 def invalidate_email(self):
     self.email_confirmed = 0
     h = hashlib.sha1()
     h.update("%s" % (time.time()))
     h.update("%s" % (random.random()))
     self.verify_email_token = h.hexdigest()
     self.save()
     if not options.debug:
         pm = postmark.PMMail(api_key=options.postmark_api_key,
             sender="*****@*****.**", to=self.email,
             subject="[mltshp] Please verify your email address",
             text_body="Hi there, could you visit this URL to verify your email address for us? Thanks. \n\nhttps://%s/verify-email/%s" % (
                 options.app_host, self.verify_email_token))
         pm.send()
         return True
     return False
Exemplo n.º 14
0
    def new_invitation(sender, receiver, action_id):
        """
        sender - user who created invitation
        receiver - user who is being invited
        action_id - the shake_id
        """
        new_shake = shake.Shake.get('id = %s', action_id)
        n = Notification(sender_id=sender.id, receiver_id=receiver.id, action_id=action_id, type='invitation')
        text_message = """Hi, %s.
We wanted to let you know %s has invited you to join "%s". Being a member of "%s" means you can upload files to the shake with others who are members.

You can agree to join here:

http://mltshp.com/%s

If you do join you'll notice a new shake name when you upload or save files.
""" % (receiver.name, sender.display_name(), new_shake.display_name(), new_shake.display_name(), new_shake.name)
        html_message = """<p>Hi, %s.</p>
<p>We wanted to let you know <a href="http://mltshp.com/user/%s">%s</a> has invited you to join "<a href="http://mltshp.com/%s">%s</a>". 
Being a member of "<a href="http://mltshp.com/%s">%s</a>" means you can upload files to the shake along with others who are members.</p>

<p>
You can agree to join here:
</p>
<p>
<a href="http://mltshp.com/%s">http://mltshp.com/%s</a>
</p>
<p>
If you do join you'll notice a new shake name when you upload or save files.
</p>
""" % (receiver.name, sender.name, sender.display_name(), new_shake.name, new_shake.display_name(), new_shake.name, new_shake.display_name(), 
            new_shake.name, new_shake.name)
            
        n.save()

        if not receiver.disable_notifications and not options.debug:
            pm = postmark.PMMail(api_key=options.postmark_api_key, 
                sender="*****@*****.**", to=receiver.email, 
                subject="%s has invited you to join %s!" % (sender.display_name(), new_shake.display_name()), 
                text_body=text_message, 
                html_body=html_message)
            pm.send()
        return n
Exemplo n.º 15
0
    def send_shake_member_removal(former_shake, former_member):
        """
        Sends an email informing someone they were removed from a shake.
        """
        text_message = """Hi %s.
This is a note to let you know you were removed as a member of "%s". 

You can still follow the shake, but the editor has decided to remove you as an image contributor.

Editors remove members for various reasons. Either the shake is shutting down or they want to do something different with it.

Thank you,
- MLTSHP
""" % (former_member.display_name(), former_shake.display_name())
        if not former_member.disable_notifications and not options.debug:
            pm = postmark.PMMail(api_key=options.postmark_api_key, 
                sender="*****@*****.**", to=former_member.email, 
                subject="Removal from %s shake" % (former_shake.display_name()), 
                text_body=text_message)
            pm.send()
Exemplo n.º 16
0
    def new_invitation_to_shake(sender, receiver, action_id):
        """
        sender - user making request
        receiver - user who owns the shake
        action_id - the shake_id
        """
        the_shake = shake.Shake.get('id=%s', action_id)
        
        n = Notification(sender_id=sender.id, receiver_id=receiver.id, action_id=action_id, type='invitation_request')
        text_message = """Hi, %s.
%s has requested to join "%s". This means they will be able to put files into the "%s" shake.

If you want to let %s do this, simply visit your shake and approve the request:

http://mltshp.com/%s

You can also ignore the request by deleting the notification.
""" % (receiver.display_name(), sender.display_name(), the_shake.display_name(), the_shake.display_name(), sender.display_name(), the_shake.name)
        html_message = """<p>Hi, %s.</p>
<p><a href="http://mltshp.com/user/%s">%s</a> has requested to join "<a href="http://mltshp.com/%s">%s</a>". This means they will be able to put files into the "%s" shake.</p>

<p>If you want to let %s do this, simply visit your shake and approve the request:</p>

<p><a href="http://mltshp.com/%s">http://mltshp.com/%s</a></p>

You can also ignore the request by deleting the notification.
""" % (receiver.display_name(), sender.name, sender.display_name(), the_shake.name, the_shake.display_name(), the_shake.display_name(), sender.display_name(), the_shake.name, the_shake.name)

        n.save()
        if not receiver.disable_notifications and not options.debug:
            pm = postmark.PMMail(api_key=options.postmark_api_key, 
                sender="*****@*****.**", to=receiver.email, 
                subject="%s has requested an invitation to %s!" % (sender.display_name(), the_shake.display_name()), 
                text_body=text_message, 
                html_body=html_message)
            pm.send()
        return n
Exemplo n.º 17
0
    def post(self):
        current_user = self.get_current_user_object()

        token_id = None
        if current_user.stripe_customer_id is None:
            token_id = self.get_argument("token")
            if token_id is None:
                # invalid request
                raise Exception("Invalid request")

        plan_id = self.get_argument("plan_id")
        if plan_id not in ("mltshp-single", "mltshp-double"):
            raise Exception("Invalid request")

        quantity = 1
        if plan_id == "mltshp-double":
            quantity = int(float(self.get_argument("quantity")))
            if quantity < 24 or quantity > 500:
                raise "Invalid request"

        customer = None
        sub = None
        stripe_customer_id = current_user.stripe_customer_id
        if stripe_customer_id is not None:
            try:
                customer = stripe.Customer.retrieve(stripe_customer_id)
            except stripe.error.InvalidRequestError:
                pass
            if customer and getattr(customer, "deleted", False):
                customer = None

        try:
            if customer is None:
                if token_id is None:
                    # FIXME: handle this more gracefully...
                    raise "Invalid request"

                # create a new customer object for this subscription
                customer = stripe.Customer.create(
                    description="MLTSHP user %s" % current_user.name,
                    email=current_user.email,
                    metadata={"mltshp_user": current_user.name},
                    source=token_id,
                )

            # if this works, we should have a customer with 1 subscription, this one
            if customer.subscriptions.total_count > 0:
                sub = customer.subscriptions.data[0]
                if sub.plan != plan_id:
                    sub.plan = plan_id
                    if plan_id == "mltshp-double":
                        sub.quantity = quantity
                    else:
                        sub.quantity = 1
                    sub.save()
            else:
                if plan_id == "mltshp-double":
                    sub = customer.subscriptions.create(plan=plan_id,
                                                        quantity=quantity)
                else:
                    sub = customer.subscriptions.create(plan=plan_id)
        except stripe.error.CardError as ex:
            return self.render("account/return-subscription-completed.html",
                               error=unicode(ex),
                               has_data_to_migrate=False)

        if not sub:
            raise Exception("Error issuing subscription")

        amount = "USD %0.2f" % ((sub.plan.amount / 100.0) * quantity)
        payment_log = PaymentLog(
            processor=PaymentLog.STRIPE,
            user_id=current_user.id,
            status="subscribed",
            reference_id=sub.id,  # ??
            transaction_id=sub.id,  # ??
            operation="order",
            transaction_date=datetime.datetime.fromtimestamp(
                sub.current_period_start).strftime("%Y-%m-%d %H:%M:%S"),
            next_transaction_date=datetime.datetime.fromtimestamp(
                sub.current_period_end).strftime("%Y-%m-%d %H:%M:%S"),
            buyer_email=current_user.email,
            buyer_name=current_user.display_name(),
            recipient_email="*****@*****.**",
            recipient_name="MLTSHP, Inc.",
            payment_reason="MLTSHP Membership",
            transaction_serial_number=1,
            subscription_id=sub.id,
            payment_method="CC",
            transaction_amount=amount,
        )
        payment_log.save()
        current_user.is_paid = 1
        current_user.stripe_plan_id = plan_id
        if plan_id == "mltshp-double":
            current_user.stripe_plan_rate = quantity
        else:
            current_user.stripe_plan_rate = None

        if current_user.stripe_customer_id != customer.id:
            current_user.stripe_customer_id = customer.id

        current_user.save()

        if options.postmark_api_key:
            pm = postmark.PMMail(
                api_key=options.postmark_api_key,
                sender="*****@*****.**",
                to="*****@*****.**",
                subject="%s has created a subscription" %
                (payment_log.buyer_name),
                text_body=
                "Subscription ID: %s\nBuyer Name:%s\nBuyer Email:%s\nUser ID:%s\n"
                % (payment_log.subscription_id, payment_log.buyer_name,
                   payment_log.buyer_email, current_user.id))
            pm.send()

        payment_notifications(current_user, "subscription", amount)

        has_data_to_migrate = not MigrationState.has_migrated(current_user.id)

        return self.render("account/return-subscription-completed.html",
                           has_data_to_migrate=has_data_to_migrate)
Exemplo n.º 18
0
def make_zip_file(for_user=None):
    """
    get all shared files, pull to /mnt, zip them into a file and then email the
    user in their user account.
    """
    if not for_user:
        sys.exit()

    s3_bucket = S3Bucket()

    user = models.User.get("name='{0}'".format(for_user))
    if not user:
        return json.dumps({'status': 'error', 'message': 'user not found'})

    os.mkdir("/mnt/backups/users/{0}".format(user.name))

    sfs = models.Sharedfile.where("user_id = %s and deleted=0 order by id",
                                  user.id)

    if sfs:
        print(len(sfs))
        for sf in sfs:
            source = sf.sourcefile()
            if source.type == 'link':
                sys.stdout.write('x')
                sys.stdout.flush()
                continue
            else:
                sys.stdout.write('.')
                sys.stdout.flush()
            file_object = s3_bucket.get_key("originals/{0}".format(
                source.file_key))
            extension = ""
            if sf.content_type == 'image/gif':
                extension = "gif"
            elif sf.content_type == 'image/jpg' or sf.content_type == 'image/jpeg':
                extension = "jpg"
            elif sf.content_type == 'image/png':
                extension = "png"

            if extension == "":
                print(sf.content_type)
                print("extension blank")
                sys.exit()

            file_object.get_contents_to_filename(
                "/mnt/backups/users/{0}/{1}.{2}".format(
                    user.name, sf.share_key, extension))

        #zip contents of directory and save to /users/id-name.zip
        subprocess.call([
            "zip", "-r", "/mnt/backups/users/{0}.zip".format(user.name),
            "/mnt/backups/users/{0}/".format(user.name)
        ])

        #upload to s3 as /bucket-name/account/id/images.zip
        k = Key(s3_bucket)
        k.key = "account/{0}/images.zip".format(user.id)
        k.set_contents_from_filename("/mnt/backups/users/{0}.zip".format(
            user.name),
                                     cb=percent_cb,
                                     num_cb=10)

        happy_url = k.generate_url(expires_in=72000)
        #email link to user email 8 hours
        pm = postmark.PMMail(api_key=options.postmark_api_key,
            sender="*****@*****.**", to=user.email,
            subject="[mltshp] Your Images Are Ready!",
            text_body="Hi, you requested to receive all of your images in a .zip file.\n" + \
            "Here they are! This link is good for the next TWENTY hours starting…now.\n\n" + \
            "{0}\n\n".format(happy_url) + \
            "Thanks for making MLTSHP so much fun. :D\n" + \
            "- MLTSHP")
        pm.send()
Exemplo n.º 19
0
    def post(self):
        current_user = self.get_current_user_object()
        # an existing, paying user can't subscribe again...
        # we also won't allow users with unconfirmed emails to subscribe
        # should we message here?
        if current_user.is_paid == 1 or current_user.email_confirmed != 1:
            return self.redirect("/account/settings")

        token_id = self.get_argument("token")
        if token_id is None:
            # invalid request
            raise "Invalid request"

        customer = None
        sub = None
        stripe_customer_id = current_user.stripe_customer_id
        if stripe_customer_id is not None:
            try:
                customer = stripe.Customer.retrieve(stripe_customer_id)
            except stripe.error.InvalidRequestError:
                pass
            if customer and getattr(customer, "deleted", False):
                customer = None

        try:
            if customer is None:
                # create a new customer object for this subscription
                customer = stripe.Customer.create(
                    description="MLTSHP user %s" % current_user.name,
                    email=current_user.email,
                    plan=options.stripe_annual_plan_id,
                    card=token_id,  # obtained with Checkout.js
                    metadata={"mltshp_user": current_user.name},
                )
                # if this works, we should have a customer with 1 subscription, this one
                if customer.subscriptions.total_count > 0:
                    sub = customer.subscriptions.data[0]
            else:
                sub = customer.subscriptions.create(
                    plan=options.stripe_annual_plan_id, card=token_id)
        except stripe.error.CardError as ex:
            return self.render("account/return-subscription-completed.html",
                               error=unicode(ex))

        if not sub:
            raise Exception("Error issuing subscription")

        amount = "USD %0.2f" % (sub.plan.amount / 100.0)
        payment_log = PaymentLog(
            processor=PaymentLog.STRIPE,
            user_id=current_user.id,
            status="subscribed",
            reference_id=sub.id,  # ??
            transaction_id=sub.id,  # ??
            operation="order",
            transaction_date=datetime.datetime.fromtimestamp(
                sub.current_period_start).strftime("%Y-%m-%d %H:%M:%S"),
            next_transaction_date=datetime.datetime.fromtimestamp(
                sub.current_period_end).strftime("%Y-%m-%d %H:%M:%S"),
            buyer_email=current_user.email,
            buyer_name=current_user.display_name(),
            recipient_email="*****@*****.**",
            recipient_name="MLTSHP, LLC",
            payment_reason="MLTSHP Paid Account",
            transaction_serial_number=1,
            subscription_id=sub.id,
            payment_method="CC",
            transaction_amount=amount,
        )
        payment_log.save()
        current_user.is_paid = 1

        if current_user.stripe_customer_id != customer.id:
            current_user.stripe_customer_id = customer.id

        current_user.save()

        if options.postmark_api_key:
            pm = postmark.PMMail(
                api_key=options.postmark_api_key,
                sender="*****@*****.**",
                to="*****@*****.**",
                subject="%s has created a subscription" %
                (payment_log.buyer_name),
                text_body=
                "Subscription ID: %s\nBuyer Name:%s\nBuyer Email:%s\nUser ID:%s\n"
                % (payment_log.subscription_id, payment_log.buyer_name,
                   payment_log.buyer_email, current_user.id))
            pm.send()

        payment_notifications(current_user, "subscription", amount)

        return self.render("account/return-subscription-completed.html")
Exemplo n.º 20
0
def migrate_for_user(user_id=0, **kwargs):
    """
    This tasks handles copying MLKSHK user data over to the MLTSHP tables.

    """
    db = Connection(options.database_host, options.database_name,
                    options.database_user, options.database_password)

    state = db.get("SELECT is_migrated FROM migration_state WHERE user_id=%s",
                   user_id)
    if not state or state["is_migrated"] == 1:
        logger.info("User %s already migrated" % str(user_id))
        db.close()
        return

    logger.info("Migrating user_id %s..." % str(user_id))

    logger.info("- app records")
    db.execute(
        """INSERT IGNORE INTO app (id, user_id, title, description, secret, redirect_url, deleted, created_at, updated_at) SELECT ma.id, ma.user_id, ma.title, ma.description, ma.secret, ma.redirect_url, 0, ma.created_at, ma.updated_at FROM mlkshk_app ma WHERE ma.user_id=%s AND ma.deleted=0""",
        user_id)

    # comments
    logger.info("- comment records")
    db.execute(
        """INSERT IGNORE INTO comment (id, user_id, sharedfile_id, body, deleted, created_at, updated_at) SELECT mc.id, mc.user_id, mc.sharedfile_id, mc.body, mc.deleted, mc.created_at, mc.updated_at FROM mlkshk_comment mc WHERE mc.user_id=%s AND mc.deleted=0""",
        user_id)

    # conversation
    logger.info("- conversation records")
    db.execute(
        """INSERT IGNORE INTO conversation (id, user_id, sharedfile_id, muted, created_at, updated_at) SELECT mc.id, mc.user_id, mc.sharedfile_id, mc.muted, mc.created_at, mc.updated_at FROM mlkshk_conversation mc WHERE mc.user_id=%s""",
        user_id)

    # favorites
    logger.info("- favorite records")
    db.execute(
        """INSERT IGNORE INTO favorite (id, user_id, sharedfile_id, deleted, created_at, updated_at) SELECT mf.id, mf.user_id, mf.sharedfile_id, mf.deleted, mf.created_at, mf.updated_at FROM mlkshk_favorite mf WHERE mf.user_id=%s AND mf.deleted=0""",
        user_id)

    # invitation_request
    logger.info("- invitation_request records")
    db.execute(
        """INSERT IGNORE INTO invitation_request (id, user_id, manager_id, shake_id, deleted, created_at, updated_at) SELECT mi.id, mi.user_id, mi.manager_id, mi.shake_id, mi.deleted, mi.created_at, mi.updated_at FROM mlkshk_invitation_request mi WHERE mi.user_id=%s AND mi.deleted=0""",
        user_id)

    # notification
    logger.info("- notification records")
    db.execute(
        """INSERT IGNORE INTO notification (id, sender_id, receiver_id, action_id, type, deleted, created_at) SELECT mn.id, mn.sender_id, mn.receiver_id, mn.action_id, mn.type, mn.deleted, mn.created_at FROM mlkshk_notification mn WHERE mn.receiver_id=%s AND mn.deleted=0""",
        user_id)

    # shake
    logger.info("- shake records")
    db.execute("""UPDATE shake SET deleted=0 WHERE user_id=%s""", user_id)

    # shake_manager
    logger.info("- shake_manager records")
    db.execute(
        """INSERT IGNORE INTO shake_manager (id, shake_id, user_id, deleted, created_at, updated_at) SELECT ms.id, ms.shake_id, ms.user_id, ms.deleted, ms.created_at, ms.updated_at FROM mlkshk_shake_manager ms WHERE ms.user_id=%s AND ms.deleted=0""",
        user_id)

    # shakesharedfile
    logger.info("- shakesharedfile records")
    db.execute(
        """INSERT IGNORE INTO shakesharedfile (id, shake_id, sharedfile_id, deleted, created_at) SELECT ms.id, ms.shake_id, ms.sharedfile_id, ms.deleted, ms.created_at FROM mlkshk_shakesharedfile ms WHERE ms.shake_id IN (SELECT DISTINCT id FROM shake WHERE deleted=0 AND user_id=%s) AND ms.deleted=0""",
        user_id)

    # sharedfile
    logger.info("- sharedfile records")
    db.execute(
        """INSERT IGNORE INTO sharedfile (id, source_id, user_id, name, title, source_url, description, share_key, content_type, size, activity_at, parent_id, original_id, deleted, like_count, save_count, view_count, updated_at, created_at) SELECT ms.id, ms.source_id, ms.user_id, ms.name, ms.title, ms.source_url, ms.description, ms.share_key, ms.content_type, ms.size, ms.activity_at, ms.parent_id, ms.original_id, ms.deleted, ms.like_count, ms.save_count, ms.view_count, ms.updated_at, ms.created_at FROM mlkshk_sharedfile ms WHERE ms.user_id=%s AND ms.deleted=0""",
        user_id)

    # nsfw_log
    logger.info("- nsfw_log records")
    db.execute(
        """INSERT IGNORE INTO nsfw_log (id, user_id, sharedfile_id, sourcefile_id, created_at) SELECT mn.id, mn.user_id, mn.sharedfile_id, mn.sourcefile_id, mn.created_at FROM mlkshk_nsfw_log mn WHERE mn.user_id=%s""",
        user_id)

    # magicfile
    logger.info("- magicfile records")
    db.execute(
        """INSERT IGNORE INTO magicfile (id, sharedfile_id, created_at) SELECT mm.id, mm.sharedfile_id, mm.created_at FROM mlkshk_magicfile mm WHERE mm.sharedfile_id IN (SELECT id FROM sharedfile WHERE user_id=%s)""",
        user_id)

    # subscription
    logger.info("- subscription records")
    db.execute(
        """INSERT IGNORE INTO subscription (id, user_id, shake_id, deleted, created_at, updated_at) SELECT ms.id, ms.user_id, ms.shake_id, ms.deleted, ms.created_at, ms.updated_at FROM mlkshk_subscription ms WHERE ms.user_id=%s AND ms.deleted=0""",
        user_id)

    # tagged_file
    logger.info("- tagged_file records")
    db.execute(
        """INSERT IGNORE INTO tagged_file (id, tag_id, sharedfile_id, deleted, created_at) SELECT mt.id, mt.tag_id, mt.sharedfile_id, mt.deleted, mt.created_at FROM mlkshk_tagged_file mt WHERE mt.sharedfile_id IN (SELECT DISTINCT id FROM sharedfile WHERE user_id=%s) AND mt.deleted=0""",
        user_id)

    # special handling for post table migration since that thing is so large (300mm rows)
    logger.info("- post records")
    db.execute(
        """INSERT IGNORE INTO post (id, user_id, sourcefile_id, sharedfile_id, seen, deleted, shake_id, created_at) SELECT mp.id, mp.user_id, mp.sourcefile_id, mp.sharedfile_id, mp.seen, mp.deleted, mp.shake_id, mp.created_at FROM mlkshk_post mp WHERE mp.user_id=%s""",
        user_id)
    # now delete any imported soft-deleted rows
    db.execute("""DELETE FROM post WHERE user_id=%s AND deleted=1""", user_id)

    # this should already be done by the web app, but we may running this
    # via a script
    logger.info("- user/migration_state update")
    db.execute("""UPDATE user SET deleted=0 WHERE deleted=2 and id=%s""",
               user_id)
    db.execute("""UPDATE migration_state SET is_migrated=1 WHERE user_id=%s""",
               user_id)

    logger.info("- Migration for user %s complete!" % str(user_id))

    user = db.get("SELECT name, email FROM user WHERE id=%s", user_id)

    db.close()

    if options.postmark_api_key and not options.debug_workers:
        pm = postmark.PMMail(
            api_key=options.postmark_api_key,
            sender="*****@*****.**",
            to=user["email"],
            subject="MLTSHP restore has finished!",
            text_body=
            """We'll keep this short and sweet. Your data should be available now!\n\n"""
            +
            ("""Head over to: https://mltshp.com/user/%s and check it out!""" %
             user["name"]))
        pm.send()
Exemplo n.º 21
0
    def post(self):
        # type of message is passed through "type" parameter
        json_response = json.loads(self.request.body)
        body_str = json.dumps(json_response).replace("\n", "\\n")

        stripe_customer_id = None
        period_start = None
        period_end = None
        checkout_id = None
        status = None
        subscription_id = None
        charge_id = None
        amount = 0
        operation = None

        evt = stripe.convert_to_stripe_object(json_response,
                                              options.stripe_secret_key, None)

        if evt.type == 'invoice.payment_failed':
            # subscription failed to be paid due to a problem
            # with the member's credit card or something
            # for now, just email [email protected] about this
            stripe_customer_id = evt.data.object.customer

            subscriber = User.get("stripe_customer_id=%s and deleted=0",
                                  stripe_customer_id)

            if subscriber and options.postmark_api_key:
                pm = postmark.PMMail(
                    api_key=options.postmark_api_key,
                    sender="*****@*****.**",
                    to="*****@*****.**",
                    subject="%s has a subscription failure" %
                    (subscriber.display_name()),
                    text_body=
                    "Subscription ID: %s\nBuyer Name:%s\nBuyer Email:%s\nUser ID:%s\n"
                    % (subscription_id, subscriber.display_name(),
                       subscriber.email, subscriber.id))
                pm.send()

            return self.finish("OK")

        elif evt.type == 'customer.subscription.created':
            # important properties
            #   customer - should be recorded already in account.stripe_customer_id
            #   current_period_start
            #   current_period_end
            #   plan.id (mltshp-annual)
            stripe_customer_id = evt.data.object.customer
            period_start = evt.data.object.current_period_start
            period_end = evt.data.object.current_period_end
            checkout_id = evt.data.object.id
            status = "subscribed"  # evt.type
            operation = "subscribe"
            subscription_id = evt.data.object.id
            amount = evt.data.object.plan.amount

        elif evt.type == "customer.subscription.deleted":
            stripe_customer_id = evt.data.object.customer
            period_start = evt.data.object.current_period_start
            period_end = evt.data.object.current_period_end
            status = "canceled"  # evt.type
            operation = "cancel"
            subscription_id = evt.data.object.id

        elif evt.type == 'invoice.payment_succeeded':
            #   customer
            #   date
            #   lines.subscriptions[0].plan.id
            #       period.start
            #       period.end
            #   total
            line_items = [
                item for item in evt.data.object.lines.data
                if item.type == "subscription" and item.plan.id in
                (options.stripe_annual_plan_id, options.stripe_monthly_plan_id)
            ]
            if line_items:
                line_item = line_items[0]
                stripe_customer_id = evt.data.object.customer
                period_start = line_item.period.start
                period_end = line_item.period.end
                checkout_id = evt.data.object.id
                status = "payment"  # evt.type
                operation = "pay"
                subscription_id = evt.data.object.subscription
                charge_id = evt.data.object.charge
                amount = evt.data.object.total

        else:
            # unsupported event type; just ignore it
            return self.finish("OK")

        subscriber = None
        if stripe_customer_id:
            subscriber = User.get("stripe_customer_id=%s and deleted=0",
                                  stripe_customer_id)

        if subscriber is None:
            # raise an exception for this...
            #raise Exception("failed to locate user for stripe_customer_id %s"
            #    % stripe_customer_id)
            return self.finish("OK")

        #create a payment log record
        amount = "USD %0.2f" % (amount / 100.0)
        pl = PaymentLog(user_id=subscriber.id,
                        status=status,
                        reference_id=checkout_id,
                        transaction_id=charge_id,
                        operation=operation,
                        transaction_date=datetime.datetime.fromtimestamp(
                            period_start).strftime("%Y-%m-%d %H:%M:%S"),
                        next_transaction_date=datetime.datetime.fromtimestamp(
                            period_end).strftime("%Y-%m-%d %H:%M:%S"),
                        buyer_email=subscriber.email,
                        buyer_name=subscriber.display_name(),
                        recipient_email="*****@*****.**",
                        recipient_name="MLTSHP, LLC",
                        payment_reason="MLTSHP Paid Account",
                        transaction_serial_number=1,
                        subscription_id=subscription_id,
                        payment_method='CC',
                        transaction_amount=amount,
                        processor=PaymentLog.STRIPE)
        pl.save()

        if evt.type == "customer.subscription.deleted":
            subscriber.is_paid = 0
        else:
            subscriber.is_paid = 1
        subscriber.save()

        return self.finish("OK")