Esempio n. 1
0
    def __init__(
        self,
        id=None,
        creation_time=None,
        scope='',
        remote_origin='127.0.0.1',
        subject_id='',
        object_id='',
    ):
        self.id, self.id_bytes = generate_or_parse_id(id)

        if None == creation_time:
            creation_time = time.time()
        self.creation_time = int(creation_time)
        self.creation_datetime = datetime.fromtimestamp(
            self.creation_time,
            timezone.utc,
        )

        self.scope = str(scope)

        self.remote_origin = ip_address(remote_origin)

        self.subject_id, self.subject_id_bytes = parse_id(subject_id)
        self.subject = None

        self.object_id, self.object_id_bytes = parse_id(object_id)
        self.object = None
Esempio n. 2
0
	def __init__(
			self,
			id=None,
			placement_time=None,
			subject_id='',
			user_id='',
			sticker_id='',
			position_x=0.0,
			position_y=0.0,
			rotation=0.0,
			scale=0.0,
		):
		self.id, self.id_bytes = generate_or_parse_id(id)

		if None == placement_time:
			placement_time = time.time()
		self.placement_time = int(placement_time)
		self.placement_datetime = datetime.fromtimestamp(
			self.placement_time,
			timezone.utc,
		)

		self.subject_id, self.subject_id_bytes = generate_or_parse_id(subject_id)
		self.user_id, self.user_id_bytes = parse_id(user_id)
		self.sticker_id, self.sticker_id_bytes = parse_id(sticker_id)

		self.position_x = float(position_x)
		self.position_y = float(position_y)
		self.rotation = float(rotation)
		self.scale = float(scale)

		self.sticker = None
Esempio n. 3
0
	def get_subject_sticker_placement_counts(self, subject_ids):
		if list != type(subject_ids):
			subject_ids = [subject_ids]
		conditions = []
		for subject_id in subject_ids:
			subject_id, subject_id_bytes = parse_id(subject_id)
			conditions.append(
				self.sticker_placements.c.subject_id == subject_id_bytes
			)
		statement = self.sticker_placements.select().where(
			or_(*conditions)
		).with_only_columns(
			[
				self.sticker_placements.c.subject_id,
				func.count(self.sticker_placements.c.id),
			]
		).group_by(
			self.sticker_placements.c.subject_id
		)
		result = self.connection.execute(statement).fetchall()
		subject_sticker_placement_counts = {}
		for row in result:
			subject_id, count = row
			subject_id, subject_id_bytes = parse_id(subject_id)
			subject_sticker_placement_counts[subject_id] = count
		return subject_sticker_placement_counts
Esempio n. 4
0
    def __init__(
        self,
        id=None,
        creation_time=None,
        remote_origin='192.0.2.0',
        scope='',
        reason='',
        note='',
        expiration_time=0,
        view_time=0,
        created_by_user_id='',
        user_id='',
    ):
        self.id, self.id_bytes = generate_or_parse_id(id)

        current_time = time.time()

        if None == creation_time:
            creation_time = current_time
        self.creation_time = int(creation_time)
        self.creation_datetime = datetime.fromtimestamp(
            self.creation_time,
            timezone.utc,
        )

        self.remote_origin = ip_address(remote_origin)

        self.scope = scope

        self.reason = reason
        self.note = note

        self.expiration_time = int(expiration_time)
        self.expiration_datetime = datetime.fromtimestamp(
            self.expiration_time,
            timezone.utc,
        )

        self.view_time = int(view_time)
        self.view_datetime = datetime.fromtimestamp(
            self.view_time,
            timezone.utc,
        )

        self.created_by_user_id, self.created_by_user_id_bytes = parse_id(
            created_by_user_id)
        self.created_by_user = None

        self.user_id, self.user_id_bytes = parse_id(user_id)
        self.user = None

        self.expired = False
        if self.expiration_time and self.expiration_time < current_time:
            self.expired = True
Esempio n. 5
0
def generate_or_parse_id(id):
    if not id:
        id_bytes = uuid.uuid4().bytes
        id = base64_url_encode(id_bytes)
    else:
        id, id_bytes = parse_id(id)
    return (id, id_bytes)
Esempio n. 6
0
 def __contains__(self, needle):
     if hasattr(needle, 'id'):
         return needle.id in self.ids_to_objects
     try:
         id, id_bytes = parse_id(needle)
     except TypeError:
         return False
     except ValueError:
         return False
     else:
         return id in self.ids_to_objects
Esempio n. 7
0
	def __init__(
			self,
			id=None,
			receive_time=None,
			user_id='',
			sticker_id='',
		):
		self.id, self.id_bytes = generate_or_parse_id(id)

		if None == receive_time:
			receive_time = time.time()
		self.receive_time = int(receive_time)
		self.receive_datetime = datetime.fromtimestamp(
			self.receive_time,
			timezone.utc,
		)

		self.user_id, self.user_id_bytes = parse_id(user_id)
		self.sticker_id, self.sticker_id_bytes = parse_id(sticker_id)

		self.sticker = None
Esempio n. 8
0
 def get(self, needle):
     if hasattr(needle, 'id'):
         if needle not in self:
             return None
         return self.ids_to_objects[needle.id]
     try:
         id, id_bytes = parse_id(needle)
     except TypeError:
         return None
     except ValueError:
         return None
     else:
         if id in self:
             return self.ids_to_objects[id]
         return None
Esempio n. 9
0
 def remove(self, needle):
     if hasattr(needle, 'id') and needle.id in self.ids_to_objects:
         del self.ids_to_objects[needle.id]
         self.ids.remove(needle.id)
         return
     try:
         id, id_bytes = parse_id(needle)
     except TypeError:
         return
     except ValueError:
         return
     else:
         if id_bytes in self:
             del self.ids_to_objects[id]
             self.ids.remove(id)
Esempio n. 10
0
 def edit_tier_permissions(
     self,
     client_id,
     tier_id,
     length,
     shareable,
     group_bits,
 ):
     #TODO i don't care about allowing independent length and shareable for each permission
     #TODO but this is where it would go
     client_id, client_id_bytes = parse_id(client_id)
     tier_id = int(tier_id)
     length = int(length)
     if shareable:
         shareable = 1
     else:
         shareable = 0
     self.connection.execute(self.tier_permissions.delete().where(
         and_(
             self.tier_permissions.c.client_id == client_id_bytes,
             self.tier_permissions.c.tier_id == tier_id,
         )))
     permissions = []
     for scope, bits in group_bits.items():
         if bytes == type(bits):
             bits = int.from_bytes(bits, 'big')
         else:
             bits = int(bits)
         if 0 == bits:
             continue
         permissions.append({
             'client_id': client_id_bytes,
             'tier_id': tier_id,
             'length': length,
             'shareable': shareable,
             'scope': str(scope),
             'group_bits': bits,
         })
     if permissions:
         # sqlite needs smaller chunks for mass insertion
         i = 0
         per_insert = 50
         while permissions:
             current_chunk = permissions[:50]
             self.connection.execute(
                 self.tier_permissions.insert().values(current_chunk))
             del permissions[:50]
Esempio n. 11
0
    def __init__(
        self,
        id=None,
        client_id='',
        campaign_id=0,
        tier_id=0,
        user_id=0,
        amount_cents=0,
        last_fulfill_time=0,
        last_charge_time=0,
        last_charge_status='',
        lifetime_support_cents=0,
        pledge_relationship_start_time=0,
        name='',
    ):
        self.id, self.id_bytes = generate_or_parse_id(id)

        self.client_id, self.client_id_bytes = parse_id(client_id)
        self.campaign_id = int(campaign_id)
        self.tier_id = int(tier_id)
        self.user_id = int(user_id)
        self.amount_cents = int(amount_cents)

        self.last_fulfill_time = int(last_fulfill_time)
        self.last_fulfill_datetime = datetime.fromtimestamp(
            self.last_fulfill_time,
            timezone.utc,
        )

        self.last_charge_time = int(last_charge_time)
        self.last_charge_datetime = datetime.fromtimestamp(
            self.last_charge_time,
            timezone.utc,
        )

        self.last_charge_status = str(last_charge_status)
        self.lifetime_support_cents = int(lifetime_support_cents)

        self.pledge_relationship_start_time = int(
            pledge_relationship_start_time)
        self.pledge_relationship_start_datetime = datetime.fromtimestamp(
            self.pledge_relationship_start_time,
            timezone.utc,
        )

        self.name = str(name)
Esempio n. 12
0
	def get_user_unique_sticker_placement_counts(self, user_id):
		user_id = get_id_bytes(user_id)
		statement = self.sticker_placements.select().where(
			self.sticker_placements.c.user_id == user_id
		).with_only_columns(
			[
				self.sticker_placements.c.sticker_id,
				func.count(distinct(self.sticker_placements.c.subject_id)),
			]
		).group_by(
			self.sticker_placements.c.sticker_id
		)
		result = self.connection.execute(statement).fetchall()
		unique_sticker_placement_counts = {}
		for row in result:
			sticker_id, count = row
			sticker_id, sticker_id_bytes = parse_id(sticker_id)
			unique_sticker_placement_counts[sticker_id] = count
		return unique_sticker_placement_counts
Esempio n. 13
0
 def set_members_last_fulfill_time(self,
                                   member_ids,
                                   last_fulfill_time=None):
     if not last_fulfill_time:
         last_fulfill_time = time.time()
     if list != type(member_ids):
         member_ids = [member_ids]
     conditions = []
     for member_id in member_ids:
         try:
             member_id, member_id_bytes = parse_id(member_id)
         except:
             # raise instead of consuming bad ids?
             continue
         conditions.append(self.members.c.id == member_id_bytes)
     if not conditions:
         # raise instead of early return for no valid ids?
         return
     self.connection.execute(self.members.update().values(
         last_fulfill_time=int(last_fulfill_time)).where(or_(*conditions)))
Esempio n. 14
0
    def refresh_client(self, client, redirect_uri):
        response = self.client_request(
            ('https://www.patreon.com/api/oauth2/v2/campaigns' + '?' +
             urllib.parse.quote_plus('fields[campaign]') + '=' +
             'creation_name'), client, redirect_uri)
        # parse included data
        campaigns = {}
        for row in response['data']:
            if 'campaign' == row['type']:
                campaigns[int(row['id'])] = row['attributes']['creation_name']
        # there should only be one campaign per client, right?
        campaign_id, creation_name = next(iter(campaigns.items()))
        # set campaign id/creation name for this client
        self.connection.execute(self.clients.update().values(
            campaign_id=int(campaign_id),
            creation_name=str(creation_name),
        ).where(self.clients.c.id == client.id_bytes))

        benefits = {}
        tiers = {}
        for campaign_id in campaigns.keys():
            # first page
            response = {
                'links': {
                    'next':
                    ('https://www.patreon.com/api/oauth2/v2/campaigns/' +
                     str(campaign_id) + '?include=' + 'tiers' + ',benefits' +
                     '&' + urllib.parse.quote_plus('fields[benefit]') + '=' +
                     'title' + ',rule_type' + ',next_deliverable_due_date' +
                     '&' + urllib.parse.quote_plus('fields[tier]') + '=' +
                     'title' + ',amount_cents' + ',unpublished_at')
                }
            }
            while ('links' in response and 'next' in response['links']
                   and response['links']['next']):
                response = self.client_request(response['links']['next'],
                                               client, redirect_uri)
                if ('data' in response
                        and 'campaign' == response['data']['type']
                        and 'included' in response):
                    # non-tier pledge
                    tiers[uuid.uuid4()] = {
                        'id': 0,
                        'client_id': client.id_bytes,
                        'campaign_id': campaign_id,
                        'amount_cents': 1,
                        'title': 'Non-tier Pledge',
                        'amount_cents': 1,
                        'unpublished': 0,
                    }
                    for resource in response['included']:
                        if ('attributes' not in resource
                                or 'id' not in resource
                                or 'type' not in resource):
                            continue
                        resource_id = int(resource['id'])
                        if 'benefit' == resource['type']:
                            # parse string datetime into timestamp
                            try:
                                parsed = dateutil.parser.parse(
                                    resource['attributes']
                                    ['next_deliverable_due_date'])
                            except ValueError:
                                next_deliverable_due_time = 0
                            except TypeError:
                                next_deliverable_due_time = 0
                            else:
                                next_deliverable_due_time = int(
                                    parsed.timestamp())
                            benefits[resource_id] = {
                                'id':
                                resource_id,
                                'client_id':
                                client.id_bytes,
                                'campaign_id':
                                campaign_id,
                                'title':
                                str(resource['attributes']['title']),
                                'rule_type':
                                str(resource['attributes']['rule_type']),
                                'next_deliverable_due_time':
                                next_deliverable_due_time,
                            }
                        elif 'tier' == resource['type']:
                            tiers[resource_id] = {
                                'id':
                                resource_id,
                                'client_id':
                                client.id_bytes,
                                'campaign_id':
                                campaign_id,
                                'title':
                                str(resource['attributes']['title']),
                                'amount_cents':
                                int(resource['attributes']['amount_cents']),
                                'unpublished':
                                0,
                            }
                            if ('unpublished_at' in resource['attributes'] and
                                    resource['attributes']['unpublished_at']):
                                tiers[resource_id]['unpublished'] = 1
            members = {}
            # first page
            response = {
                'links': {
                    'next':
                    ('https://www.patreon.com/api/oauth2/v2/campaigns/' +
                     str(campaign_id) + '/members' + '?include=' +
                     'currently_entitled_tiers' + ',user' + '&' +
                     urllib.parse.quote_plus('fields[user]') + '=' +
                     'full_name' + '&' +
                     urllib.parse.quote_plus('fields[member]') + '=' +
                     'patron_status' + ',pledge_relationship_start' +
                     ',lifetime_support_cents' +
                     ',currently_entitled_amount_cents' + ',last_charge_date' +
                     ',last_charge_status')
                }
            }
            while ('links' in response and 'next' in response['links']
                   and response['links']['next']):
                response = self.client_request(response['links']['next'],
                                               client, redirect_uri)
                if ('data' not in response or 'included' not in response):
                    continue
                user_ids_to_names = {}
                for resource in response['included']:
                    if ('id' not in resource or 'type' not in resource
                            or 'user' != resource['type']
                            or 'attributes' not in resource
                            or 'full_name' not in resource['attributes']):
                        continue
                    resource_id = int(resource['id'])
                    user_ids_to_names[resource_id] = resource['attributes'][
                        'full_name']
                for member in response['data']:
                    if ('id' not in member or 'type' not in member
                            or 'member' != member['type']
                            or 'relationships' not in member
                            or 'user' not in member['relationships']
                            or 'data' not in member['relationships']['user']
                            or 'user' !=
                            member['relationships']['user']['data']['type']
                            or 'attributes' not in member
                            or 'currently_entitled_amount_cents'
                            not in member['attributes']
                            or 'last_charge_date' not in member['attributes']
                            or 'last_charge_status' not in member['attributes']
                            or 'lifetime_support_cents'
                            not in member['attributes']
                            or 'patron_status' not in member['attributes']
                            or 'active_patron' !=
                            member['attributes']['patron_status']
                            or 'pledge_relationship_start'
                            not in member['attributes']):
                        continue
                    # parse member uuid
                    member_uuid = uuid.UUID(member['id'])
                    member_id, member_id_bytes = parse_id(member_uuid.bytes)
                    if ('currently_entitled_tiers'
                            not in member['relationships'] or 'data' not in
                            member['relationships']['currently_entitled_tiers']
                            or not member['relationships']
                        ['currently_entitled_tiers']['data']
                            or 'tier' != member['relationships']
                        ['currently_entitled_tiers']['data'][0]['type']
                            or 'id' not in member['relationships']
                        ['currently_entitled_tiers']['data'][0]):
                        tier_id = 0
                    else:
                        tier_id = int(
                            member['relationships']['currently_entitled_tiers']
                            ['data'][0]['id'])
                    user_id = int(
                        member['relationships']['user']['data']['id'])
                    if tier_id < 1:
                        tier_id = 0
                    # parse string datetime into timestamp
                    try:
                        parsed = dateutil.parser.parse(
                            member['attributes']['pledge_relationship_start'])
                    except ValueError:
                        pledge_relationship_start_time = 0
                    except TypeError:
                        pledge_relationship_start_time = 0
                    else:
                        pledge_relationship_start_time = int(
                            parsed.timestamp())
                    try:
                        parsed = dateutil.parser.parse(
                            member['attributes']['last_charge_date'])
                    except ValueError:
                        last_charge_time = 0
                    except TypeError:
                        last_charge_time = 0
                    else:
                        last_charge_time = int(parsed.timestamp())
                    members[member_id] = {
                        'id':
                        member_id_bytes,
                        'client_id':
                        client.id_bytes,
                        'campaign_id':
                        campaign_id,
                        'tier_id':
                        tier_id,
                        'user_id':
                        user_id,
                        'amount_cents':
                        int(member['attributes']
                            ['currently_entitled_amount_cents']),
                        'last_charge_time':
                        last_charge_time,
                        'last_charge_status':
                        str(member['attributes']['last_charge_status']),
                        'lifetime_support_cents':
                        int(member['attributes']['lifetime_support_cents']),
                        'pledge_relationship_start_time':
                        pledge_relationship_start_time,
                        'name':
                        '',
                    }
                    if user_id in user_ids_to_names:
                        members[member_id]['name'] = user_ids_to_names[user_id]
        # get existing member last_fulfill_time values to add before insertion
        fulfilled_members = self.search_members(
            filter={'last_fulfilled_after': 0})
        # delete stale info and insert new infor for this client
        for table in ['benefits', 'tiers', 'members']:
            self.connection.execute(
                getattr(self, table).delete().where(
                    getattr(self, table).c.client_id == client.id_bytes))
        if benefits:
            self.connection.execute(self.benefits.insert().values(
                list(benefits.values())))
        if tiers:
            self.connection.execute(self.tiers.insert().values(
                list(tiers.values())))
        if members:
            # not using indexed dict for insert
            members = list(members.values())
            # add last_fulfill_time to members that were previously fulfilled
            for member in members:
                if member['id'] in fulfilled_members:
                    fulfilled_member = fulfilled_members.get(member['id'])
                    member[
                        'last_fulfill_time'] = fulfilled_member.last_fulfill_time
            # sqlite needs smaller chunks for mass insertion
            i = 0
            per_insert = 50
            while members:
                current_chunk = members[:50]
                self.connection.execute(
                    self.members.insert().values(current_chunk))
                del members[:50]