from django.db import models from django.db.models import CASCADE from zerver.models.users import UserProfile # Interfaces for services # They provide additional functionality like parsing message to obtain query URL, data to be sent to URL, # and parsing the response. GENERIC_INTERFACE = "GenericService" SLACK_INTERFACE = "SlackOutgoingWebhookService" # A Service corresponds to either an outgoing webhook bot or an embedded bot. # The type of Service is determined by the bot_type field of the referenced # UserProfile. # # If the Service is an outgoing webhook bot: # - name is any human-readable identifier for the Service # - base_url is the address of the third-party site # - token is used for authentication with the third-party site # # If the Service is an embedded bot: # - name is the canonical name for the type of bot (e.g. 'xkcd' for an instance # of the xkcd bot); multiple embedded bots can have the same name, but all # embedded bots with the same name will run the same code # - base_url and token are currently unused class Service(models.Model): name = models.CharField(max_length=UserProfile.MAX_NAME_LENGTH) # Bot user corresponding to the Service. The bot_type of this user # determines the type of service. If non-bot services are added later, # user_profile can also represent the owner of the Service. user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) base_url = models.TextField() token = models.TextField() # Interface / API version of the service. interface = models.PositiveSmallIntegerField(default=1) # Valid interfaces are {generic, zulip_bot_service, slack} GENERIC = 1 SLACK = 2 ALLOWED_INTERFACE_TYPES = [ GENERIC, SLACK, ] # N.B. If we used Django's choice=... we would get this for free (kinda) _interfaces: dict[int, str] = { GENERIC: GENERIC_INTERFACE, SLACK: SLACK_INTERFACE, } def interface_name(self) -> str: # Raises KeyError if invalid return self._interfaces[self.interface] def get_bot_services(user_profile_id: int) -> list[Service]: return list(Service.objects.filter(user_profile_id=user_profile_id)) def get_service_profile(user_profile_id: int, service_name: str) -> Service: return Service.objects.get(user_profile_id=user_profile_id, name=service_name) class BotStorageData(models.Model): bot_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) key = models.TextField(db_index=True) value = models.TextField() class Meta: unique_together = ("bot_profile", "key") class BotConfigData(models.Model): bot_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) key = models.TextField(db_index=True) value = models.TextField() class Meta: unique_together = ("bot_profile", "key")