@ -1,224 +0,0 @@
|
|||||||
"""
|
|
||||||
This file consists in managing all things user related
|
|
||||||
"""
|
|
||||||
from utils.transport import CouchdbReader, CouchdbWriter
|
|
||||||
from threading import Thread
|
|
||||||
import json
|
|
||||||
class User :
|
|
||||||
def __init__(self,**args) :
|
|
||||||
"""
|
|
||||||
@param product identifier of the product we are working with
|
|
||||||
@param stripe stripe handler
|
|
||||||
@param store transport store (couchdb, ...)
|
|
||||||
"""
|
|
||||||
self.stripe = args["stripe"]
|
|
||||||
self.store = args['store']
|
|
||||||
|
|
||||||
self.store['dbname'] = str(args['product'])
|
|
||||||
self.product = str(args['product'])
|
|
||||||
|
|
||||||
self.me = {}
|
|
||||||
self.init()
|
|
||||||
|
|
||||||
def init(self):
|
|
||||||
lproducts = self.stripe.Product.list()
|
|
||||||
lproducts = [item for item in lproducts.auto_paging_iter() if item.name == self.product ]
|
|
||||||
if lproducts :
|
|
||||||
self.me['info'] = {"active":lproducts[0].active,"id":lproducts[0].id,"description":lproducts[0].statement_descriptor,"images":lproducts[0].images}
|
|
||||||
self.plans = self.stripe.Plan.list(product=lproducts[0].id)
|
|
||||||
self.plans = [item for item in self.plans.auto_paging_iter() ]
|
|
||||||
|
|
||||||
def init_customer(self,uid,pid):
|
|
||||||
"""
|
|
||||||
This function copies a customer to the internal database.
|
|
||||||
This would allow the object to be in sync with what is available in stripe and we will save the content later on ...
|
|
||||||
"""
|
|
||||||
customer = self.stripe.Customer.list(email=uid)
|
|
||||||
if customer :
|
|
||||||
customer = [item for item in customer if item.email == uid]
|
|
||||||
customer = customer[0]
|
|
||||||
|
|
||||||
#
|
|
||||||
# Insure the product is the one we are looking for ...
|
|
||||||
args = dict(self.store)
|
|
||||||
args['uid']=uid
|
|
||||||
reader = CouchdbReader(**args)
|
|
||||||
key = reader.view('users/uid_map',key=uid)
|
|
||||||
if not key :
|
|
||||||
self.store['uid'] = customer.id
|
|
||||||
self.update(_id=customer.id,emails=[uid])
|
|
||||||
#
|
|
||||||
# We need to update the user's subscription
|
|
||||||
#
|
|
||||||
product_id = self.me['info']['id']
|
|
||||||
info = {}
|
|
||||||
lsub = customer.subscriptions ;
|
|
||||||
|
|
||||||
info = {}
|
|
||||||
found = False
|
|
||||||
for sub in lsub.data :
|
|
||||||
if sub.plan.id == pid or sub.plan.product == product_id:
|
|
||||||
info[sub.plan.nickname] = sub.plan
|
|
||||||
self.update(subscriptions=info)
|
|
||||||
self.post()
|
|
||||||
#-- housekeeping work
|
|
||||||
else:
|
|
||||||
#
|
|
||||||
# The key exists we need to just read the user info in me
|
|
||||||
reader.uid = key
|
|
||||||
document = reader.read()
|
|
||||||
self.me = dict(self.me,**document)
|
|
||||||
self.user_key = customer.id
|
|
||||||
return customer
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def update(self,**args):
|
|
||||||
for key in args :
|
|
||||||
value = args[key]
|
|
||||||
if key in self.me :
|
|
||||||
if not isinstance(self.me[key],dict) or not isinstance(value,dict) :
|
|
||||||
if not isinstance(self.me[key],list) :
|
|
||||||
self.me[key] = [self.me[key],value]
|
|
||||||
elif isinstance(self.me[key],list):
|
|
||||||
self.me[key] += value if isinstance(value,list) else [value]
|
|
||||||
else:
|
|
||||||
self.me[key] = dict(self.me[key],**value)
|
|
||||||
else:
|
|
||||||
self.me[key] = value
|
|
||||||
|
|
||||||
def post(self,**args):
|
|
||||||
document = dict(self.me,**{})
|
|
||||||
|
|
||||||
args = dict(self.store)
|
|
||||||
args['create'] = True
|
|
||||||
|
|
||||||
writer = CouchdbWriter(**args)
|
|
||||||
writer.set(document)
|
|
||||||
|
|
||||||
# writer.close()
|
|
||||||
def get_key(self,uid):
|
|
||||||
reader = CouchdbReader(**self.store)
|
|
||||||
key = reader.view('users/uid_map',key=uid)
|
|
||||||
|
|
||||||
if key :
|
|
||||||
if isinstance(key,list) :
|
|
||||||
key = key[0]['value']
|
|
||||||
elif 'value' in key :
|
|
||||||
key = key['value']
|
|
||||||
else:
|
|
||||||
key = None
|
|
||||||
return key
|
|
||||||
def get(self,uid,key):
|
|
||||||
args = dict(self.store)
|
|
||||||
args['uid'] = self.get_key(uid)
|
|
||||||
if key not in self.me :
|
|
||||||
couchdb = CouchdbReader(**args)
|
|
||||||
document = couchdb.basic_read()
|
|
||||||
return document[key] if key in document else {}
|
|
||||||
else:
|
|
||||||
return self.me[key]
|
|
||||||
# def plans(self,free=False):
|
|
||||||
# lproducts = self.stripe.Product.list()
|
|
||||||
# plans = [item for item in lproducts.auto_paging_iter() if item.name == self.product ]
|
|
||||||
# if free == True :
|
|
||||||
# plans = [item for item in plans if item.amount == 0]
|
|
||||||
# return plans
|
|
||||||
def subscribe(self,uid,pid=None,stripeToken=None) :
|
|
||||||
"""
|
|
||||||
@param uid user's email
|
|
||||||
@param pid plan id
|
|
||||||
@param stripeToken stripe token to process payments
|
|
||||||
"""
|
|
||||||
customer = self.init_customer(uid,pid)
|
|
||||||
product_id = self.me['info']['id']
|
|
||||||
if pid is None :
|
|
||||||
#
|
|
||||||
# In this block we try to find the free plan if one isn't specified
|
|
||||||
# The informtion about the product is already known (constructor)
|
|
||||||
#
|
|
||||||
plans = [item for item in self.plans if item.amount == 0]
|
|
||||||
pid = None if not plans else plans[0].id
|
|
||||||
|
|
||||||
if not customer :
|
|
||||||
customer = self.stripe.Customer.create(email=uid)
|
|
||||||
self.update(_id=customer.id,emails=[uid])
|
|
||||||
elif not self.me['subscriptions']:
|
|
||||||
#
|
|
||||||
# We have a customer and subscription information that goes with it
|
|
||||||
#
|
|
||||||
mysub = {"plans":[]}
|
|
||||||
for rows in customer.subscriptions.data :
|
|
||||||
lsub = rows.items()
|
|
||||||
myplans = [ item[1]for item in lsub if 'plan' in item and item[1]['product'] == self.me['info']['id'] and item[1]['active'] ]
|
|
||||||
if myplans :
|
|
||||||
for plan in myplans :
|
|
||||||
plan['metadata'] = str(plan['metadata'])
|
|
||||||
|
|
||||||
self.me['subscriptions'] = {plan['nickname']: dict(plan)}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# print customer.subscriptions.data[0].items()]
|
|
||||||
# self.post(uid=customer.id)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# else:
|
|
||||||
# customer = customer
|
|
||||||
self.store['uid'] = customer.id
|
|
||||||
args = {"customer":customer.id,"items":[{"plan":pid}]}
|
|
||||||
if stripeToken:
|
|
||||||
args['source'] = stripeToken
|
|
||||||
|
|
||||||
sub = self.me['subscriptions']
|
|
||||||
found = len([1 for plan_key in sub if sub[plan_key]['id'] == pid]) > 0
|
|
||||||
if found is False :
|
|
||||||
sub = self.stripe.Subscription.create(**args)
|
|
||||||
info = {sub.plan.nickname:sub.plan}
|
|
||||||
self.update(subscriptions=info)
|
|
||||||
|
|
||||||
self.post(uid=customer.id)
|
|
||||||
#
|
|
||||||
# keep a copy of this on our servers ...
|
|
||||||
#
|
|
||||||
|
|
||||||
def refresh(self,uid):
|
|
||||||
parent = (self)
|
|
||||||
def _update(customer_id) :
|
|
||||||
|
|
||||||
customer = parent.stripe.Customer.retrieve(customer_id)
|
|
||||||
parent.store['uid'] = customer.id
|
|
||||||
lsub = customer.subscriptions
|
|
||||||
reader = CouchdbReader(**parent.store)
|
|
||||||
_me = reader.read()
|
|
||||||
if 'emails' not in parent.me :
|
|
||||||
parent.me['emails'] = []
|
|
||||||
emails = list(set(parent.me['emails']) | set(_me['emails']))
|
|
||||||
parent.me = dict(parent.me,**_me)
|
|
||||||
parent.me['emails'] = emails
|
|
||||||
|
|
||||||
product_id = parent.me['info']['id']
|
|
||||||
[parent.update(subscriptions={sub.plan.nickname:sub.plan}) for sub in lsub.auto_paging_iter() if sub.plan.product == product_id and sub.plan.active == True]
|
|
||||||
|
|
||||||
parent.post()
|
|
||||||
key = self.get_key(uid)
|
|
||||||
# reader = CouchdbReader(**self.store)
|
|
||||||
# key = reader.view('users/uid_map',key=uid)
|
|
||||||
|
|
||||||
# if key :
|
|
||||||
# if isinstance(key,list) :
|
|
||||||
# key = key[0]['value']
|
|
||||||
# elif 'value' in key :
|
|
||||||
# key = key['value']
|
|
||||||
if key :
|
|
||||||
thread = Thread(target=_update,args=(key,))
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
# thread.start()
|
|
||||||
|
|
||||||
def pay(self,uid,pid,stripeToken):
|
|
||||||
pass
|
|
||||||
|
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 443 KiB After Width: | Height: | Size: 443 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 631 KiB After Width: | Height: | Size: 631 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 775 B After Width: | Height: | Size: 775 B |
Before Width: | Height: | Size: 852 B After Width: | Height: | Size: 852 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 267 B After Width: | Height: | Size: 267 B |
Before Width: | Height: | Size: 187 B After Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 404 B After Width: | Height: | Size: 404 B |
Before Width: | Height: | Size: 849 B After Width: | Height: | Size: 849 B |
Before Width: | Height: | Size: 907 B After Width: | Height: | Size: 907 B |
Before Width: | Height: | Size: 745 B After Width: | Height: | Size: 745 B |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 720 B After Width: | Height: | Size: 720 B |
Before Width: | Height: | Size: 605 B After Width: | Height: | Size: 605 B |
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 381 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |