def main(): connection = None log('cron4', 'Starting') try: connection, db = connect() next_payments = NextPayments.find( db, {'action_date': {'$lte': datetime.now()}}, {'parrot_id':1,'account_id':1,'_id':1} ).sort([('_id', -1)]) for next_payment in next_payments: subscription = Subscriptions.findOne(db, {'account_id': next_payment.get('account_id'), 'parrot_id': next_payment.get('parrot_id')}) if subscription and subscription.active: created_message = Queue.insert( 'payments', { 'subscription_id': str(subscription.id), 'account_id': str(subscription.account_id), 'parrot_id': str(subscription.parrot_id) } ) if created_message: db.next_payments.remove({'_id': next_payment.get('_id')}) else: db.next_payments.remove({'_id': next_payment.get('_id')}) finally: if connection: connection.close() log('cron4', 'Finishing')
def process_payment(db, raw_message, payment_message): parrot = Parrots.findOne(db, {'_id': ObjectId(payment_message.get('parrot_id'))}) if parrot: message = get_message_to_share(db, payment_message) twitter_json = tweet_message(parrot, message, raw_message.id) payment = store_payment(db, twitter_json, payment_message, message, raw_message) if payment.success: if Queue.delete_message('payments', raw_message): log('cron2', 'Payments succeded', payment_message.get('subscription_id')) send_notification(db, payment, 'payment_success') log('cron2', 'Notification sent', payment_message.get('subscription_id')) create_next_payment(db, payment) log('cron2', 'Next payment created', payment_message.get('subscription_id')) add_payment_to_parrot(db, parrot, payment_message, twitter_json) else: log('cron2', 'ERROR: Couldnt delete message', payment_message.get('subscription_id')) else: total_payments_attempts = Payments.find(db, {'message_id_sqs': raw_message.id}).count() subscription = Subscriptions.findOne(db, {'account_id': payment.account_id, 'parrot_id': payment.parrot_id}) if subscription: if total_payments_attempts > 3: log('cron2', 'Too many payments attempts', payment_message.get('subscription_id')) subscription.update({'active': False}) if Queue.delete_message('payments', raw_message): send_notification(db, payment,'subscription_deactivated') else: log('cron2', 'ERROR: Couldnt delete message', payment_message.get('subscription_id')) else: log('cron2', 'Attempt %s' % total_payments_attempts, payment_message.get('subscription_id'))
def get_valid_parrot(db, account_id, parrot_id): account = Accounts.findOne(db,account_id) if account: subscription = Subscriptions.findOne(db, {'parrot_id': ObjectId(parrot_id), 'account_id': ObjectId(account_id)}) if subscription: parrot = Parrots.findOne(db, parrot_id) if parrot: return parrot
def test_cron4_no_subscription(self): account = Accounts(self.db, { 'email': '*****@*****.**', 'password': '******', 'name': 'Daniel', 'startup': 'Payparrot', 'url': 'http://payparrot.com/', 'callback_url': 'http://www.epistemonikos.org', 'notification_url': 'http://www.epistemonikos.org', }) account.insert() parrot = Parrots(self.db, { 'twitter_id': '123123123', 'oauth_token': 'asd', 'oauth_token_secret': 'asdf', 'twitter_info': {}, 'payments': [], 'twitter_info': { 'screen_name': 'danielgua' } }) parrot.insert() subscription = Subscriptions(self.db, {'account_id': account.id, 'active': False, 'parrot_id': parrot.id, 'twitter_screen_name': parrot.twitter_info.get("screen_name")}) subscription.insert() last_date = datetime.now(); next_action_date = last_date; next_payment = NextPayments(self.db, { 'account_id': account.id, 'parrot_id': parrot.id, 'action_date': next_action_date }); next_payment.insert() from payparrot_scripts.crons.cron4 import main as cron4 cron4() message = Queue.get_message('payments') self.assertFalse(message) self.assertEqual(0, self.db.next_payments.find({'_id': next_payment.id}).count())
def setUp(self): self.app = pp_tests.get_app() self.connection, self.db = pp_tests.connect_to_mongo() self.account = pp_tests.create_account_and_login(self.app, self.db, { 'email': '*****@*****.**', 'password': '******', 'name': 'Daniel', 'startup': 'Payparrot', 'url': 'http://payparrot.com/', 'callback_url': 'http://www.epistemonikos.org', 'notification_url': 'http://www.epistemonikos.org', }) self.parrot = Parrots(self.db, { 'twitter_id': '123123123', 'oauth_token': 'asd', 'oauth_token_secret': 'asdf', 'twitter_info': {}, 'payments': [], 'twitter_info': { 'screen_name': 'danielgua' } }) self.parrot.insert() self.subscription = Subscriptions(self.db, {'account_id': self.account.id, 'active': True, 'parrot_id': self.parrot.id, 'twitter_screen_name': self.parrot.twitter_info.get("screen_name")}) self.subscription.insert() self.parrot1 = Parrots(self.db, { 'twitter_id': '4322143214', 'oauth_token': 'asd', 'oauth_token_secret': 'asdf', 'twitter_info': {}, 'payments': [], 'twitter_info': { 'screen_name': 'blabla' } }) self.parrot1.insert() self.subscription1 = Subscriptions(self.db, {'account_id': self.account.id, 'active': True, 'parrot_id': self.parrot1.id,'twitter_screen_name': self.parrot1.twitter_info.get("screen_name")}) self.subscription1.insert()
def send_notification(db, payment, notification_type): subscription = Subscriptions.findOne(db, {'account_id': payment.account_id, 'parrot_id': payment.parrot_id}) if subscription: account = Accounts.findOne(db, payment.account_id) if account: notification = Notifications(db, { 'account_id': payment.account_id, 'parrot_id': payment.parrot_id, 'type': notification_type, 'subscription_id': subscription.id, 'external_id': subscription.external_id, 'request_url': account.notification_url }) notification.insert()
def parrots_finish(db): if request.query.denied: redirect('/twitter_denied.html') session = Sessions.findOne(db, {'oauth_token': request.query.oauth_token}) if session: account = Accounts.findOne(db, session.account_id) if not account: response.status = 404 return {'error': 'Invalid token'} twitter = Twitter() try: access_tokens = twitter.get_access_tokens(request.query.oauth_verifier,{'oauth_token': session.oauth_token, 'oauth_token_secret': session.oauth_token_secret}) twitter.create_client(access_tokens.get('oauth_token'),access_tokens.get('oauth_token_secret')) headers, body = twitter.get('https://api.twitter.com/1/account/verify_credentials.json') except: redirect('/twitter_auth_problem.html') return if headers.status == 200: body = json.loads(body) parrot = Parrots.findOne(db, {'twitter_id': body.get('id')}) if not parrot: new_parrot = Parrots(db, { 'twitter_info': body, 'twitter_id': body.get('id'), 'oauth_token': access_tokens.get('oauth_token'), 'oauth_token_secret': access_tokens.get('oauth_token_secret') }) new_parrot.insert() parrot = new_parrot else: parrot.update({ 'oauth_token': access_tokens.get('oauth_token'), 'oauth_token_secret': access_tokens.get('oauth_token_secret') }) subscription = Subscriptions.findOne(db, {'account_id': account.id, 'parrot_id': parrot.id}) subscription_parameters = { 'parrot_id': parrot.id, 'account_id': account.id, 'active': True, 'external_id': session.external_id, 'twitter_screen_name': body.get("screen_name") } if not subscription: subscription = Subscriptions(db, subscription_parameters) subscription.insert() else: subscription.update(subscription_parameters) notification_id = _create_notification(db, account, parrot, subscription) if notification_id: redirect_url = generate_redirect_url(account.callback_url, session.external_id, subscription.id, notification_id) redirect(redirect_url) else: response.status = 404 return {'error': 'Expired token'}
def main(): connection = None try: log('cron1', 'Starting') connection, db = connect() subscriptions = Subscriptions.find(db, {'active': True, 'first_tweet': False}) for subscription_raw in subscriptions: created_message = Queue.insert( 'payments', { 'subscription_id': str(subscription_raw['_id']), 'account_id': str(subscription_raw['account_id']), 'parrot_id': str(subscription_raw['parrot_id']) } ) log('cron1', 'Payment queued %s' % created_message.id, subscription_raw['_id']) db.subscriptions.update({'_id': subscription_raw['_id']}, {'$set': {'first_tweet': True}}) log('cron1', 'Subscription updated', subscription_raw['_id']) finally: if connection: connection.close() log('cron1', 'Finishing')
def store_payment(db, twitter_json, payment_message, message, raw_message): subscription = Subscriptions.findOne(db, {'account_id': ObjectId(payment_message.get('account_id')),'parrot_id': ObjectId(payment_message.get('parrot_id'))}) payment_data = { 'twitter_response': twitter_json, # action date means when this payment has to be tweeted 'action_date': datetime.now(), 'account_id': ObjectId(payment_message.get('account_id')), 'subscription_id': ObjectId(subscription.id), 'parrot_id': ObjectId(payment_message.get('parrot_id')), 'message_id': ObjectId(message.get('id')), 'message_id_sqs': raw_message.id, 'callback_url': message.get('url', ''), 'success': True } if twitter_json.get('error'): payment_data['success'] = False log('cron2', 'ERROR: Payment coulndt be processed because of twitter error %s' % json.dumps(twitter_json), payment_message.get('subscription_id')) else: log('cron2', 'Payment executed successfully', payment_message.get('subscription_id')) payment = Payments(db, payment_data) payment.insert() return payment
def get_parrots(account_id, db, secure = True): querystring = request.query; from_ = querystring.get("from") to_ = querystring.get("to") skip = int(querystring.get('skip', 0)) limit = int(querystring.get('limit', 0)) query_subscriptions = {'account_id': ObjectId(account_id), 'active': True} if from_ or to_: query_subscriptions['created_at'] = {} if from_: query_subscriptions['created_at']['$gte'] = datetime.strptime(from_, '%Y-%m-%d') if to_: query_subscriptions['created_at']['$lte'] = datetime.strptime(to_, '%Y-%m-%d') if querystring.screen_name: screen_name_regex = re.compile(querystring.screen_name,re.IGNORECASE) query_subscriptions['twitter_screen_name'] = screen_name_regex parrots_from_subscriptions = Subscriptions.find(db, query_subscriptions, {'parrot_id': True, '_id': False}).skip(skip).limit(limit).sort([('_id', -1)]) parrots_id = map(lambda x: x.get('parrot_id'), parrots_from_subscriptions) parrots = list(Parrots.find(db, {'_id': {'$in': parrots_id}})) for parrot in parrots: parrot['payments'] = filter(lambda x: x.get('account_id') == account_id, parrot.get('payments')) # TODO: fix this response.headers['Content-type'] = 'application/json' return json.dumps(map(lambda x: Parrots.toJSON(x), parrots))
class TestParrots(unittest.TestCase): def setUp(self): self.app = pp_tests.get_app() self.connection, self.db = pp_tests.connect_to_mongo() self.account = pp_tests.create_account_and_login(self.app, self.db, { 'email': '*****@*****.**', 'password': '******', 'name': 'Daniel', 'startup': 'Payparrot', 'url': 'http://payparrot.com/', 'callback_url': 'http://www.epistemonikos.org', 'notification_url': 'http://www.epistemonikos.org', }) self.parrot = Parrots(self.db, { 'twitter_id': '123123123', 'oauth_token': 'asd', 'oauth_token_secret': 'asdf', 'twitter_info': {}, 'payments': [], 'twitter_info': { 'screen_name': 'danielgua' } }) self.parrot.insert() self.subscription = Subscriptions(self.db, {'account_id': self.account.id, 'active': True, 'parrot_id': self.parrot.id, 'twitter_screen_name': self.parrot.twitter_info.get("screen_name")}) self.subscription.insert() self.parrot1 = Parrots(self.db, { 'twitter_id': '4322143214', 'oauth_token': 'asd', 'oauth_token_secret': 'asdf', 'twitter_info': {}, 'payments': [], 'twitter_info': { 'screen_name': 'blabla' } }) self.parrot1.insert() self.subscription1 = Subscriptions(self.db, {'account_id': self.account.id, 'active': True, 'parrot_id': self.parrot1.id,'twitter_screen_name': self.parrot1.twitter_info.get("screen_name")}) self.subscription1.insert() def tearDown(self): pp_tests.tear_down(self.db, self.app) self.connection.close() def test_invalid_token(self): response = self.app.get('/parrots/finish?oauth_token=lala', status = 404) self.assertEqual({'error': 'Expired token'}, response.json) def test_get_one_parrot_status(self): response = self.app.get('/accounts/%s/parrots/%s' % (self.account.id, self.parrot.id)) self.assertEqual(200, response.status_int) self.assertEqual(self.parrot.JSON(), response.json) def test_delete_one_parrot(self): response = self.app.delete('/accounts/%s/parrots/%s' % (str(self.account.id), str(self.parrot.id))) self.assertEqual(204, response.status_int) self.app.get('/accounts/%s/parrots/%s' % (self.account.id, self.parrot.id), status=404) def test_get_parrots_with_date_filter(self): one_day = timedelta(days=1) from_ = datetime.now()-one_day*7 from_text = str(from_) to_ = datetime.now() - one_day to_text = str(to_) #Hack to change date self.db.subscriptions.update({'parrot_id': self.parrot1.id},{'$set': {'created_at': from_+one_day*5}}) response = self.app.get('/accounts/%s/parrots?from=%s&to=%s' % (self.account.id, from_text.split(" ")[0], to_text.split(" ")[0])) self.assertEqual(200, response.status_int) self.assertEqual(1, len(response.json)) self.assertEqual(str(self.parrot1.id), response.json[0]['id']) def test_get_parrots_by_screen_name(self): response = self.app.get('/accounts/%s/parrots?screen_name=%s' % (self.account.id, 'danielgua')) self.assertEqual(200, response.status_int) self.assertEqual(1, len(response.json)) # self.assertEqual(str(self.parrot1.id), response.json[0]['id'])