foukoapi 0.1.0-alpha.1

Cross-platform bot framework in Rust. Write your handlers once, run the same bot on Telegram and Discord with shared accounts, embeds, keyboards and SQLite storage.
Documentation
//! Platform descriptors.
//!
//! A [`Platform`] is just a thin description of which adapter to spin up and
//! with what credentials. The actual driving logic lives in
//! [`crate::adapters`].

use std::fmt;

/// Which chat platform an update came from / should be dispatched to.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum PlatformKind {
    /// Telegram (MTProto Bot API).
    Telegram,
    /// Discord (gateway + REST).
    Discord,
}

impl fmt::Display for PlatformKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match self {
            Self::Telegram => "telegram",
            Self::Discord => "discord",
        })
    }
}

/// A platform the [`Bot`](crate::Bot) should run on.
///
/// Built through the short constructors: [`Platform::telegram`],
/// [`Platform::discord`]. Each one returns a `Platform` even if that
/// platform's feature is turned off at compile time - the missing
/// adapter will simply log a warning and be skipped when the bot
/// starts, instead of failing the build.
#[derive(Debug, Clone)]
pub struct Platform {
    pub(crate) kind: PlatformKind,
    pub(crate) config: PlatformConfig,
}

#[derive(Debug, Clone)]
#[non_exhaustive]
#[allow(dead_code)] // Fields are read only when the corresponding adapter feature is on.
pub(crate) enum PlatformConfig {
    /// Telegram bot token from @BotFather.
    Telegram { token: String },
    /// Discord bot token.
    Discord { token: String },
}

impl Platform {
    /// Add a Telegram bot. `token` is whatever BotFather gives you.
    pub fn telegram(token: impl Into<String>) -> Self {
        Self {
            kind: PlatformKind::Telegram,
            config: PlatformConfig::Telegram {
                token: token.into(),
            },
        }
    }

    /// Add a Discord bot.
    pub fn discord(token: impl Into<String>) -> Self {
        Self {
            kind: PlatformKind::Discord,
            config: PlatformConfig::Discord {
                token: token.into(),
            },
        }
    }

    /// Which kind of platform this descriptor points at.
    pub fn kind(&self) -> PlatformKind {
        self.kind
    }
}