from .bits import Reader
from .iab_tcf import base64_decode
[docs]class ConsentV1:
"""Represents a v1.1 consent with all the information extracted.
:param consent: The consent to process in bytes.
"""
def __init__(self, consent: bytes):
self._reader: Reader = Reader(consent)
self.version = self._reader.read_int(6)
self.created = self._reader.read_time()
self.last_updated = self._reader.read_time()
self.cmp_id = self._reader.read_int(12)
self.cmp_version = self._reader.read_int(12)
self.consent_screen = self._reader.read_int(6)
self.consent_language = self._reader.read_string(2)
self.vendor_list_version = self._reader.read_int(12)
self.purposes_allowed = self._reader.read_bitfield(24)
self.max_vendor_id = self._reader.read_int(16)
self.is_range_encoding = self._reader.read_bool()
if self.is_range_encoding:
self.default_consent = self._reader.read_bool()
self.num_entries = self._reader.read_int(12)
self.range_entries = self._reader.read_range(self.num_entries)
else:
self.consented_vendors = self._reader.read_bitfield(self.max_vendor_id)
[docs] def is_purpose_allowed(self, id: int) -> bool:
"""Checks if a purpose is allowed or not.
:param id: Purpose id to check if it's allowed or not.
"""
if id in self.purposes_allowed:
return self.purposes_allowed[id]
return False
[docs] def is_vendor_allowed(self, id: int) -> bool:
"""Checks if a vendor is allowed or not.
:param id: Vendor id to check if it's allowed or not.
"""
if self.is_range_encoding:
for (start, end) in self.range_entries:
if start <= id and id <= end:
return not self.default_consent
return self.default_consent
return False if id not in self.consented_vendors else self.consented_vendors[id]
[docs]def decode_v1(consent: str):
"""Decodes a v1.1 consent string that it's encoded in base64.
:param consent: base64 encoded consent string.
"""
return ConsentV1(base64_decode(consent))