d23273590f
Multi-tenant system to fetch and store restaurant lists from Beli accounts. Each user can connect up to 3 Beli profiles; a nightly Cronicle job (1–5 AM, randomised) refreshes the 3 stalest profiles using the reverse-engineered Beli API (mirrored at git.torrtle.co/ryan/beli-api). Rankings (been) and bookmarks (want-to-try) are stored in Postgres and queryable via a new LangChain agent tool. Beli passwords and refresh tokens are stored Fernet-encrypted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
54 lines
2.0 KiB
Python
54 lines
2.0 KiB
Python
import enum
|
|
import uuid
|
|
|
|
from tortoise import fields
|
|
from tortoise.models import Model
|
|
|
|
from blueprints.email.crypto_service import EncryptedTextField
|
|
|
|
|
|
class BeliStatus(str, enum.Enum):
|
|
BEEN = "been"
|
|
WANT_TO_TRY = "want_to_try"
|
|
|
|
|
|
class BeliProfile(Model):
|
|
id = fields.UUIDField(primary_key=True, default=uuid.uuid4)
|
|
user = fields.ForeignKeyField("models.User", related_name="beli_profiles")
|
|
beli_email = fields.CharField(max_length=255)
|
|
beli_password = EncryptedTextField()
|
|
beli_user_id = fields.CharField(max_length=255, null=True)
|
|
# refresh token lasts 7 days; we store it encrypted to avoid re-authenticating each run
|
|
beli_refresh_token = EncryptedTextField(null=True)
|
|
last_refreshed_at = fields.DatetimeField(null=True)
|
|
last_error = fields.TextField(null=True)
|
|
enabled = fields.BooleanField(default=True)
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
updated_at = fields.DatetimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
table = "beli_profiles"
|
|
unique_together = (("user", "beli_email"),)
|
|
|
|
|
|
class BeliRestaurant(Model):
|
|
id = fields.UUIDField(primary_key=True, default=uuid.uuid4)
|
|
profile = fields.ForeignKeyField("models.BeliProfile", related_name="restaurants")
|
|
beli_business_id = fields.CharField(max_length=255)
|
|
name = fields.CharField(max_length=500)
|
|
city = fields.CharField(max_length=255, null=True)
|
|
neighborhood = fields.CharField(max_length=255, null=True)
|
|
cuisine = fields.JSONField(default=list)
|
|
price_range = fields.CharField(max_length=10, null=True)
|
|
status = fields.CharEnumField(enum_type=BeliStatus, max_length=20)
|
|
rank_index = fields.IntField(null=True)
|
|
score = fields.DecimalField(max_digits=5, decimal_places=2, null=True)
|
|
notes = fields.TextField(null=True)
|
|
tags = fields.JSONField(default=list)
|
|
fetched_at = fields.DatetimeField(auto_now=True)
|
|
created_at = fields.DatetimeField(auto_now_add=True)
|
|
|
|
class Meta:
|
|
table = "beli_restaurants"
|
|
unique_together = (("profile", "beli_business_id", "status"),)
|