use serde::Serialize;
use serde_with::skip_serializing_none;
use std::time::{SystemTime, UNIX_EPOCH};
#[skip_serializing_none]
#[derive(Clone, Debug, Default, Serialize)]
pub struct Activity {
#[serde(rename = "type")]
pub kind: ActivityType,
pub details: Option<String>,
pub state: Option<String>,
pub timestamps: Option<Timestamps>,
pub assets: Assets,
pub buttons: Option<Vec<Button>>,
pub party: Option<Party>,
pub secrets: Option<Secrets>,
pub instance: bool,
}
impl Activity {
pub fn new() -> Self {
Self::default()
}
pub fn kind(mut self, kind: ActivityType) -> Self {
self.kind = kind;
self
}
pub fn details(mut self, details: impl Into<String>) -> Self {
self.details = Some(details.into());
self
}
pub fn state(mut self, state: impl Into<String>) -> Self {
self.state = Some(state.into());
self
}
pub fn timestamps(mut self, timestamps: Timestamps) -> Self {
self.timestamps = Some(timestamps);
self
}
pub fn assets(mut self, assets: Assets) -> Self {
self.assets = assets;
self
}
pub fn button(mut self, button: Button) -> Self {
if let Some(ref mut buttons) = self.buttons {
if buttons.len() < 2 {
buttons.push(button);
}
} else {
self.buttons = Some(vec![button]);
}
self.secrets = None; self
}
pub fn party(mut self, party: Party) -> Self {
self.party = Some(party);
self
}
pub fn secrets(mut self, secrets: Secrets) -> Self {
self.secrets = Some(secrets);
self.buttons = None; self
}
pub fn instance(mut self, instance: bool) -> Self {
self.instance = instance;
self
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
#[serde(into = "u8")]
#[repr(u8)]
pub enum ActivityType {
#[default]
Playing = 0,
Listening = 2,
Watching = 3,
Competing = 5,
}
impl From<ActivityType> for u8 {
fn from(value: ActivityType) -> Self {
value as u8
}
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, Serialize)]
pub struct Timestamps {
pub start: Option<i64>,
pub end: Option<i64>,
}
impl Timestamps {
pub fn new() -> Self {
Self::default()
}
pub fn start(mut self, start: i64) -> Self {
self.start = Some(start);
self
}
pub fn start_now(mut self) -> Self {
self.start = Some(Self::now());
self
}
pub fn end(mut self, end: i64) -> Self {
self.end = Some(end);
self
}
pub fn end_now(mut self) -> Self {
self.end = Some(Self::now());
self
}
fn now() -> i64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs() as i64
}
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, Serialize)]
pub struct Assets {
pub large_image: Option<String>,
pub large_text: Option<String>,
pub small_image: Option<String>,
pub small_text: Option<String>,
}
impl Assets {
pub fn new() -> Self {
Self::default()
}
pub fn large_image<S: Into<String>>(mut self, image_key: S, text: Option<S>) -> Self {
self.large_image = Some(image_key.into());
self.large_text = text.map(|text| text.into());
self
}
pub fn small_image<S: Into<String>>(mut self, image_key: S, text: Option<S>) -> Self {
self.small_image = Some(image_key.into());
self.small_text = text.map(|text| text.into());
self
}
}
#[skip_serializing_none]
#[derive(Clone, Debug, Serialize)]
pub struct Button {
pub label: String,
pub url: String,
}
impl Button {
pub fn new(label: impl Into<String>, url: impl Into<String>) -> Self {
Button {
label: label.into(),
url: url.into(),
}
}
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, Serialize)]
pub struct Party {
pub id: Option<String>,
pub size: Option<[u32; 2]>,
}
impl Party {
pub fn new() -> Self {
Self::default()
}
pub fn id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
}
pub fn size(mut self, size: [u32; 2]) -> Self {
self.size = Some(size);
self
}
pub fn current_size(mut self, current_size: u32) -> Self {
if let Some(mut size) = self.size {
size[0] = current_size.max(1);
} else {
self.size = Some([current_size.max(1), 0])
}
self
}
pub fn max_size(mut self, max_size: u32) -> Self {
if let Some(mut size) = self.size {
size[1] = max_size.max(1);
} else {
self.size = Some([0, max_size.max(1)])
}
self
}
}
#[skip_serializing_none]
#[derive(Clone, Debug, Default, Serialize)]
pub struct Secrets {
pub join: Option<String>,
pub spectate: Option<String>,
#[serde(rename = "match")]
pub match_: Option<String>,
}
impl Secrets {
pub fn new() -> Self {
Self::default()
}
pub fn join(mut self, join: impl Into<String>) -> Self {
self.join = Some(join.into());
self
}
pub fn spectate(mut self, spectate: impl Into<String>) -> Self {
self.spectate = Some(spectate.into());
self
}
pub fn match_(mut self, match_: impl Into<String>) -> Self {
self.match_ = Some(match_.into());
self
}
}