Skip to main content

ponys_ai_resources/
lib.rs

1//! Official Ponys.ai public resource helpers.
2
3pub mod characters;
4
5pub const CHARACTER_CATALOG_JSON: &str = include_str!("../data/characters.json");
6pub const CHARACTERS: &[(&str, &str)] = &[
7    ("aaliyah-banks", "https://ponys.ai/characters/aaliyah-banks"),
8    ("adrian", "https://ponys.ai/characters/adrian"),
9    ("aeroha", "https://ponys.ai/characters/aeroha"),
10    ("akari", "https://ponys.ai/characters/akari"),
11    ("amanda", "https://ponys.ai/characters/amanda"),
12    ("anthea", "https://ponys.ai/characters/anthea"),
13    ("ari", "https://ponys.ai/characters/ari"),
14    ("astrid", "https://ponys.ai/characters/astrid"),
15    ("aubrey", "https://ponys.ai/characters/aubrey"),
16    ("ava", "https://ponys.ai/characters/ava"),
17    ("camila-duarte", "https://ponys.ai/characters/camila-duarte"),
18    ("camila-reyes", "https://ponys.ai/characters/camila-reyes"),
19    ("change", "https://ponys.ai/characters/change"),
20    (
21        "character-43449110",
22        "https://ponys.ai/characters/character-43449110",
23    ),
24    ("chloe-monroe", "https://ponys.ai/characters/chloe-monroe"),
25    ("clarissa", "https://ponys.ai/characters/clarissa"),
26    ("coco", "https://ponys.ai/characters/coco"),
27    ("darius", "https://ponys.ai/characters/darius"),
28    ("dasha", "https://ponys.ai/characters/dasha"),
29    (
30        "dr-lucia-moreno",
31        "https://ponys.ai/characters/dr-lucia-moreno",
32    ),
33    ("eira", "https://ponys.ai/characters/eira"),
34    ("eli", "https://ponys.ai/characters/eli"),
35    ("elsie-bloom", "https://ponys.ai/characters/elsie-bloom"),
36    ("emberveil", "https://ponys.ai/characters/emberveil"),
37    ("emma", "https://ponys.ai/characters/emma"),
38    (
39        "ethan-caldwell",
40        "https://ponys.ai/characters/ethan-caldwell",
41    ),
42    ("eve", "https://ponys.ai/characters/eve"),
43    ("guixiang", "https://ponys.ai/characters/guixiang"),
44    ("haitang", "https://ponys.ai/characters/haitang"),
45    ("han-so-yeon", "https://ponys.ai/characters/han-so-yeon"),
46    ("hana", "https://ponys.ai/characters/hana"),
47    ("hassan", "https://ponys.ai/characters/hassan"),
48    ("hatice", "https://ponys.ai/characters/hatice"),
49    ("hina", "https://ponys.ai/characters/hina"),
50    ("hiokimi", "https://ponys.ai/characters/hiokimi"),
51    ("jace", "https://ponys.ai/characters/jace"),
52    ("jaxon", "https://ponys.ai/characters/jaxon"),
53    ("ji-hoon", "https://ponys.ai/characters/ji-hoon"),
54    ("joe", "https://ponys.ai/characters/joe"),
55    ("kai", "https://ponys.ai/characters/kai"),
56    ("kiara", "https://ponys.ai/characters/kiara"),
57    ("kirishima", "https://ponys.ai/characters/kirishima"),
58    ("kurose", "https://ponys.ai/characters/kurose"),
59    ("leo", "https://ponys.ai/characters/leo"),
60    ("liana", "https://ponys.ai/characters/liana"),
61    ("lynne", "https://ponys.ai/characters/lynne"),
62    ("lyra", "https://ponys.ai/characters/lyra"),
63    ("maribel-cruz", "https://ponys.ai/characters/maribel-cruz"),
64    ("marisol-vega", "https://ponys.ai/characters/marisol-vega"),
65    ("marlene-hart", "https://ponys.ai/characters/marlene-hart"),
66    ("mason", "https://ponys.ai/characters/mason"),
67    ("mei", "https://ponys.ai/characters/mei"),
68    ("meow", "https://ponys.ai/characters/meow"),
69    ("miko", "https://ponys.ai/characters/miko"),
70    ("mila", "https://ponys.ai/characters/mila"),
71    ("miyuki", "https://ponys.ai/characters/miyuki"),
72    ("mizuki", "https://ponys.ai/characters/mizuki"),
73    ("monique", "https://ponys.ai/characters/monique"),
74    ("moretti", "https://ponys.ai/characters/moretti"),
75    ("mulan", "https://ponys.ai/characters/mulan"),
76    ("na1", "https://ponys.ai/characters/na1"),
77    ("na2", "https://ponys.ai/characters/na2"),
78    ("na3", "https://ponys.ai/characters/na3"),
79    ("na4", "https://ponys.ai/characters/na4"),
80    ("nana", "https://ponys.ai/characters/nana"),
81    ("naomi", "https://ponys.ai/characters/naomi"),
82    ("natalie", "https://ponys.ai/characters/natalie"),
83    ("nefara", "https://ponys.ai/characters/nefara"),
84    ("noah", "https://ponys.ai/characters/noah"),
85    ("noxie", "https://ponys.ai/characters/noxie"),
86    ("nuwa", "https://ponys.ai/characters/nuwa"),
87    ("nyx", "https://ponys.ai/characters/nyx"),
88    ("odette", "https://ponys.ai/characters/odette"),
89    ("phuwin", "https://ponys.ai/characters/phuwin"),
90    ("pixi-vayne", "https://ponys.ai/characters/pixi-vayne"),
91    ("rami", "https://ponys.ai/characters/rami"),
92    ("rika", "https://ponys.ai/characters/rika"),
93    ("rin", "https://ponys.ai/characters/rin"),
94    ("roro", "https://ponys.ai/characters/roro"),
95    ("rosario", "https://ponys.ai/characters/rosario"),
96    ("rovie", "https://ponys.ai/characters/rovie"),
97    ("rowan", "https://ponys.ai/characters/rowan"),
98    ("ruby", "https://ponys.ai/characters/ruby"),
99    ("safira", "https://ponys.ai/characters/safira"),
100    ("sera-park", "https://ponys.ai/characters/sera-park"),
101    ("sofia-maren", "https://ponys.ai/characters/sofia-maren"),
102    ("sophie", "https://ponys.ai/characters/sophie"),
103    ("soyeon", "https://ponys.ai/characters/soyeon"),
104    ("sue", "https://ponys.ai/characters/sue"),
105    (
106        "summer-st-claire",
107        "https://ponys.ai/characters/summer-st-claire",
108    ),
109    ("suzuki", "https://ponys.ai/characters/suzuki"),
110    ("tessa", "https://ponys.ai/characters/tessa"),
111    ("valeria", "https://ponys.ai/characters/valeria"),
112    ("vanessa", "https://ponys.ai/characters/vanessa"),
113    ("vava", "https://ponys.ai/characters/vava"),
114    ("vincent", "https://ponys.ai/characters/vincent"),
115    ("wen", "https://ponys.ai/characters/wen"),
116    ("yui", "https://ponys.ai/characters/yui"),
117    ("yuna", "https://ponys.ai/characters/yuna"),
118    ("yuwei", "https://ponys.ai/characters/yuwei"),
119    ("zaria-cole", "https://ponys.ai/characters/zaria-cole"),
120    ("zhixia", "https://ponys.ai/characters/zhixia"),
121    ("zoey", "https://ponys.ai/characters/zoey"),
122    ("zuri-bennett", "https://ponys.ai/characters/zuri-bennett"),
123];
124
125pub fn character_url(slug: &str) -> Option<&'static str> {
126    CHARACTERS
127        .iter()
128        .find(|(candidate, _)| *candidate == slug)
129        .map(|(_, url)| *url)
130}
131
132#[derive(Clone, Copy, Debug, Eq, PartialEq)]
133pub enum Product {
134    Homepage,
135    Discover,
136    Create,
137    CharacterGenerator,
138    ImageGenerator,
139    VideoGenerator,
140    AiGirlfriend,
141    AiBoyfriend,
142}
143
144pub fn product_url(product: Product) -> &'static str {
145    match product {
146        Product::Homepage => "https://ponys.ai/",
147        Product::Discover => "https://ponys.ai/discover",
148        Product::Create => "https://ponys.ai/create",
149        Product::CharacterGenerator => "https://ponys.ai/ai-character-generator",
150        Product::ImageGenerator => "https://ponys.ai/ai-image-generator",
151        Product::VideoGenerator => "https://ponys.ai/ai-video-generator",
152        Product::AiGirlfriend => "https://ponys.ai/ai-girlfriend",
153        Product::AiBoyfriend => "https://ponys.ai/ai-boyfriend",
154    }
155}
156
157pub fn feed_url(locale: &str, format: &str) -> Result<String, &'static str> {
158    if !["en", "ja", "ko", "zh-tw", "zh-cn", "es", "pt-br"].contains(&locale) {
159        return Err("unsupported locale");
160    }
161    if !["json", "xml"].contains(&format) {
162        return Err("format must be json or xml");
163    }
164    Ok(format!("https://feeds.ponys.ai/feeds/{locale}.{format}"))
165}
166
167pub fn character_feed_url(locale: &str) -> Result<String, &'static str> {
168    if !["en", "ja", "ko", "zh-tw", "zh-cn", "es", "pt-br"].contains(&locale) {
169        return Err("unsupported locale");
170    }
171    Ok(format!("https://feeds.ponys.ai/characters/{locale}.json"))
172}
173
174pub fn widget_manifest_url() -> &'static str {
175    "https://feeds.ponys.ai/api/benchmark-widget.json"
176}
177
178pub fn open_data_catalog_url() -> &'static str {
179    "https://feeds.ponys.ai/open-data/catalog.json"
180}
181
182#[cfg(test)]
183mod tests {
184    use super::*;
185
186    #[test]
187    fn resolves_product_and_feed() {
188        assert_eq!(product_url(Product::Discover), "https://ponys.ai/discover");
189        assert_eq!(
190            feed_url("ja", "json").unwrap(),
191            "https://feeds.ponys.ai/feeds/ja.json"
192        );
193        assert_eq!(
194            character_feed_url("ko").unwrap(),
195            "https://feeds.ponys.ai/characters/ko.json"
196        );
197        assert_eq!(
198            widget_manifest_url(),
199            "https://feeds.ponys.ai/api/benchmark-widget.json"
200        );
201        assert_eq!(
202            open_data_catalog_url(),
203            "https://feeds.ponys.ai/open-data/catalog.json"
204        );
205        assert_eq!(
206            character_url("sera-park"),
207            Some("https://ponys.ai/characters/sera-park")
208        );
209        assert_eq!(CHARACTERS.len(), 104);
210    }
211}