use std::fmt;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum ChannelProvider {
Telegram,
Whatsapp,
Discord,
Slack,
}
impl fmt::Display for ChannelProvider {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::Telegram => "telegram",
Self::Whatsapp => "whatsapp",
Self::Discord => "discord",
Self::Slack => "slack",
})
}
}
impl std::str::FromStr for ChannelProvider {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"telegram" => Ok(Self::Telegram),
"whatsapp" => Ok(Self::Whatsapp),
"discord" => Ok(Self::Discord),
"slack" => Ok(Self::Slack),
other => Err(format!("unknown channel provider: {other}")),
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(rename_all = "snake_case")]
pub enum ChatType {
Private,
Group,
Supergroup,
Channel,
}
impl fmt::Display for ChatType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::Private => "private",
Self::Group => "group",
Self::Supergroup => "supergroup",
Self::Channel => "channel",
})
}
}
impl std::str::FromStr for ChatType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"private" => Ok(Self::Private),
"group" => Ok(Self::Group),
"supergroup" => Ok(Self::Supergroup),
"channel" => Ok(Self::Channel),
other => Err(format!("unknown chat type: {other}")),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum TriggerMode {
All,
OnMention,
}
impl Default for TriggerMode {
fn default() -> Self {
TriggerMode::All
}
}
impl TriggerMode {
pub fn as_str(&self) -> &'static str {
match self {
TriggerMode::All => "all",
TriggerMode::OnMention => "on_mention",
}
}
}
impl fmt::Display for TriggerMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl std::str::FromStr for TriggerMode {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"all" => Ok(Self::All),
"on_mention" => Ok(Self::OnMention),
other => Err(format!("unknown trigger mode: {other}")),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PlatformAuthScope {
Open,
WorkspaceScoped,
}
impl ChannelProvider {
pub fn platform_auth_scope(&self) -> PlatformAuthScope {
match self {
ChannelProvider::Telegram | ChannelProvider::Whatsapp => PlatformAuthScope::Open,
ChannelProvider::Slack | ChannelProvider::Discord => PlatformAuthScope::WorkspaceScoped,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bot {
pub id: Uuid,
pub workspace_id: Uuid,
pub created_by_user_id: Uuid,
pub provider: ChannelProvider,
pub bot_username: Option<String>,
pub bot_token: Option<String>,
pub webhook_secret: Option<String>,
pub agent_id: String,
pub trigger_mode: TriggerMode,
pub active: bool,
#[serde(default)]
pub is_system: bool,
}
#[derive(Debug, Clone)]
pub struct NewBot {
pub id: Uuid,
pub workspace_id: Uuid,
pub created_by_user_id: Uuid,
pub provider: ChannelProvider,
pub bot_username: Option<String>,
pub bot_token: Option<String>,
pub webhook_secret: Option<String>,
pub agent_id: String,
pub trigger_mode: TriggerMode,
pub active: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Channel {
pub id: Uuid,
pub bot_id: Uuid,
pub chat_id: String,
pub chat_type: ChatType,
pub thread_id: Option<String>,
pub verbose: bool,
pub verified: bool,
pub created_by_identity_id: Option<Uuid>,
}
#[derive(Debug, Clone)]
pub struct NewChannel {
pub bot_id: Uuid,
pub chat_id: String,
pub chat_type: ChatType,
pub thread_id: Option<String>,
pub verbose: bool,
pub verified: bool,
pub created_by_identity_id: Option<Uuid>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BotConnection {
pub bot_id: Uuid,
pub connection_id: Uuid,
pub requires_setup: bool,
pub position: i32,
pub created_at: chrono::DateTime<chrono::Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChannelVerification {
pub id: Uuid,
pub channel_id: Uuid,
pub connection_id: Uuid,
pub verified_by_user_id: Uuid,
pub external_user_id: Option<String>,
pub metadata: serde_json::Value,
pub created_at: chrono::DateTime<chrono::Utc>,
pub last_seen_at: Option<chrono::DateTime<chrono::Utc>>,
}
#[derive(Debug, Clone)]
pub struct PlatformUser {
pub provider: ChannelProvider,
pub platform_id: String,
pub platform_username: Option<String>,
pub platform_display_name: Option<String>,
}
#[derive(Debug, Clone)]
pub struct ChannelIdentity {
pub id: Uuid,
pub user_id: Uuid,
pub provider: ChannelProvider,
pub platform_id: String,
pub platform_username: Option<String>,
pub platform_display_name: Option<String>,
}
#[derive(Debug, Clone)]
pub struct AuthenticatedChannelUser {
pub user_id: Uuid,
pub identity: ChannelIdentity,
pub channel_id: Uuid,
pub bot_id: Uuid,
pub workspace_id: Uuid,
pub auth: AuthProof,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AuthProof {
PlatformVerified,
Open,
GatedBy { connection_id: Uuid },
}
#[derive(Debug, Clone)]
pub enum ResolveOutcome {
Authenticated(AuthenticatedChannelUser),
NeedsVerification { url: String, gate_kind: GateKind },
Denied { reason: String },
Rejected,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum GateKind {
DistriNative,
External { connection_id: Uuid },
}