roblox-api 0.1.8

Roblox web api bindings
Documentation
use serde::{Deserialize, Serialize};

use crate::{DateTime, Paging, endpoint};

pub const URL: &str = "https://friends.roblox.com/v1";

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct FollowingStatus {
    #[serde(rename = "userId")]
    pub id: u64,
    pub is_following: bool,
    pub is_followed: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct FriendStatus {
    pub id: u64,
    pub status: String,
}

#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub enum FriendRequestSourceType {
    InGame,
    UserProfile,
    PlayerSearch,
    FriendRecommendations,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct FriendRequester {
    #[serde(rename = "senderId")]
    pub id: u64,
    #[serde(rename = "senderNickname")]
    pub display_name: String,
    pub contact_name: Option<String>,

    pub source_universe_id: Option<u64>,
    pub origin_source_type: FriendRequestSourceType,
    pub sent_at: DateTime,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct FriendRequest {
    pub id: u64,
    pub mutual_friends_list: Vec<String>,
    #[serde(rename = "friendRequest")]
    pub requester: FriendRequester,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct FriendRequests {
    #[serde(rename = "data")]
    pub requests: Vec<FriendRequest>,
    #[serde(rename = "nextPageCursor")]
    pub next_cursor: Option<String>,
    #[serde(rename = "previousPageCursor")]
    pub previous_cursor: Option<String>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct User {
    pub id: u64,
    #[serde(rename = "hasVerifiedBadge")]
    pub is_verified: Option<bool>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct Followers {
    #[serde(rename = "data")]
    pub users: Vec<User>,
    #[serde(rename = "nextPageCursor")]
    pub next_cursor: Option<String>,
    #[serde(rename = "previousPageCursor")]
    pub previous_cursor: Option<String>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "PascalCase")]
pub struct FriendsFind {
    #[serde(rename = "PageItems")]
    pub users: Vec<User>,
    pub next_cursor: Option<String>,
    pub previous_cursor: Option<String>,
    pub has_more: Option<bool>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct UserPresence {
    #[serde(rename = "UserPresenceType")]
    pub kind: String,
    #[serde(rename = "UserLocationType")]
    pub location_kind: String,

    #[serde(rename = "lastLocation")]
    pub status: String,
    pub last_online: DateTime,

    pub place_id: Option<u64>,
    pub root_place_id: Option<u64>,
    pub universe_id: Option<u64>,
    #[serde(rename = "gameInstanceId")]
    pub job_id: Option<String>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct FriendOnlineStatus {
    pub id: u64,
    #[serde(rename = "userPresence")]
    pub presence: UserPresence,
}

#[derive(Debug, Deserialize)]
struct CountResponse {
    count: u16,
}

endpoint! {
    friend_requests_count() -> u16 {
        GET "{URL}/user/friend-requests/count";
        map |r: CountResponse| r.count
    }

    new_friend_requests_count() -> u16 {
        GET "{URL}/my/new-friend-requests/count";
        map |r: CountResponse| r.count
    }

    user_friends_count(id: u64) -> u16 {
        GET "{URL}/users/{id}/friends/count";
        map |r: CountResponse| r.count
    }

    user_followings_count(id: u64) -> u16 {
        GET "{URL}/users/{id}/followings/count";
        map |r: CountResponse| r.count
    }

    user_followers_count(id: u64) -> u16 {
        GET "{URL}/users/{id}/followers/count";
        map |r: CountResponse| r.count
    }

    following_status(ids: &[u64]) -> Vec<FollowingStatus> {
        POST "{URL}/user/following-exists";
        types {
            Request<'a> {
                user_ids("targetUserIds"): &'a [u64],
            }
            Response {
                statuses("followings"): Vec<FollowingStatus>,
            }
        }
        body_serialize {
            &Request { user_ids: ids }
        }
        map |r: Response| r.statuses
    }

    friend_requests(paging: Paging<'_>) -> FriendRequests {
        GET "{URL}/my/friends/requests";
        paging_query { paging, limit = 18 }
    }

    user_followers(id: u64) -> Followers {
        GET "{URL}/users/{id}/followers";
    }

    user_followings(id: u64) -> Followers {
        GET "{URL}/users/{id}/followings";
    }

    user_friends_online(id: u64) -> Vec<FriendOnlineStatus> {
        GET "{URL}/users/{id}/friends/online";
        types {
            Response {
                online("data"): Vec<FriendOnlineStatus>,
            }
        }
        map |r: Response| r.online
    }

    user_friends_find(id: u64, paging: Paging<'_>) -> FriendsFind {
        GET "{URL}/users/{id}/friends/find";
        prelude {
            let limit = paging.limit.unwrap_or(18).to_string();
            let cursor = paging.cursor.unwrap_or("");
        }
        query {
            "cursor" => cursor,
            "limit" => &limit,
            "userSort" => "1",
        }
    }

    user_friends_search(id: u64, query: &str, paging: Paging<'_>) -> FriendsFind {
        GET "{URL}/users/{id}/friends/search";
        paging_query { paging, limit = 36 }
        query {
            "query" => query,
        }
    }

    user_friend_statuses(id: u64, friends: &[u64]) -> Vec<FriendStatus> {
        GET "{URL}/users/{id}/friends/statuses";
        types {
            Response {
                statuses("data"): Vec<FriendStatus>,
            }
        }
        prelude {
            let ids = friends
                .iter()
                .map(|x| x.to_string())
                .collect::<Vec<String>>()
                .join(",");
        }
        query {
            "userIds" => &ids,
        }
        map |r: Response| r.statuses
    }
}