pobsd_parser/
store_links.rs

1//! Provides a representations for the store links associated to each game.
2use regex::Regex;
3
4/// Represents the store in which the game is available
5#[derive(Serialize, Clone, Default, Debug, PartialEq, Eq)]
6pub enum Store {
7    /// For steam games
8    Steam,
9    /// For Gog games
10    Gog,
11    /// For games on other stores
12    #[default]
13    Unknown,
14}
15
16/// Represent a store link
17#[derive(Serialize, Clone, Default, Debug, PartialEq, Eq)]
18pub struct StoreLink {
19    /// Store related to the link
20    pub store: Store,
21    /// Link where the game can be found
22    pub url: String,
23    /// Id of the game for the store
24    pub id: Option<usize>,
25}
26
27impl StoreLink {
28    /// Create a StoreLink given an url.
29    /// At the moment, it only handles Gog and Steam games.
30    pub fn from(url: &str) -> Self {
31        if url.contains("steampowered") {
32            Self {
33                store: Store::Steam,
34                url: url.to_string(),
35                id: get_steam_id(url),
36            }
37        } else if url.contains("gog.com") {
38            Self {
39                store: Store::Gog,
40                url: url.to_string(),
41                id: None,
42            }
43        } else {
44            Self {
45                store: Store::Unknown,
46                url: url.to_string(),
47                id: None,
48            }
49        }
50    }
51}
52
53// Return the steam id from a store url
54fn get_steam_id(url: &str) -> Option<usize> {
55    let re = Regex::new(r"https://store.steampowered.com/app/(\d+)(/?.+)?").unwrap();
56    if let Some(cap) = re.captures(url) {
57        if let Some(cap) = cap.get(1) {
58            return cap.as_str().parse::<usize>().ok();
59        };
60    };
61    None
62}
63
64/// Represent a collection of store links
65#[derive(Serialize, Clone, Default, Debug, PartialEq, Eq)]
66pub struct StoreLinks(pub Vec<StoreLink>);
67
68impl StoreLinks {
69    /// Create a StoreLinks with the given items
70    pub fn new(items: Vec<StoreLink>) -> Self {
71        Self(items)
72    }
73    /// Add a StoreLink to the collection
74    pub fn push(&mut self, store: StoreLink) {
75        self.0.push(store)
76    }
77    /// Return a imutable reference to the vector of StoreLink.
78    pub fn inner_ref(&self) -> &Vec<StoreLink> {
79        &self.0
80    }
81    /// Return a mutable reference to the vector of StoreLink.
82    pub fn inner_mut_ref(&mut self) -> &mut Vec<StoreLink> {
83        &mut self.0
84    }
85    /// Return the vector of StoreLink.
86    pub fn into_inner(self) -> Vec<StoreLink> {
87        self.0
88    }
89    /// Return true if a Steam game is present, false otherwise
90    pub fn has_steam(&self) -> bool {
91        let links = self.inner_ref();
92        let res: Vec<&StoreLink> = links.iter().filter(|a| a.store.eq(&Store::Steam)).collect();
93        !res.is_empty()
94    }
95    /// Return true if a Steam game is present, false otherwise
96    pub fn has_gog(&self) -> bool {
97        let links = self.inner_ref();
98        let res: Vec<&StoreLink> = links.iter().filter(|a| a.store.eq(&Store::Gog)).collect();
99        !res.is_empty()
100    }
101}
102
103#[cfg(test)]
104mod store_link_tests {
105    use super::*;
106    #[test]
107    fn test_get_id_steam() {
108        let store = StoreLink::from("https://store.steampowered.com/app/1878910/LoupLaine/");
109        assert_eq!(store.id, Some(1878910));
110
111        let store = StoreLink::from("https://store.steampowered.com/app/1878910");
112        assert_eq!(store.id, Some(1878910));
113
114        let store = StoreLink::from("https://store.steampowered.com/app/1878910/");
115        assert_eq!(store.id, Some(1878910));
116
117        let store = StoreLink::from("https://store.steampowered.com/app/1878910/LoupLaine");
118        assert_eq!(store.id, Some(1878910));
119    }
120    #[test]
121    fn test_get_id_gog() {
122        let store = StoreLink::from("https://gog.com/app/1878910/LoupLaine/");
123        assert_eq!(store.id, None);
124    }
125}