Skip to main content

rship_entities/
file.rs

1use std::{
2    ffi::OsStr,
3    path::{self, Path, PathBuf},
4};
5
6use myko_macros::{myko_query, myko_query_handler, myko_report, Eventable};
7use partially::Partial;
8use serde::{Deserialize, Serialize};
9
10use myko_rs::query::QueryResult;
11#[derive(Partial, PartialEq, Eventable, Clone, Serialize, Deserialize, Debug)]
12#[serde(rename_all = "camelCase")]
13#[partially(derive(Clone, Serialize, Deserialize, Default))]
14pub struct File {
15    pub id: String,
16    pub hash: String,
17    pub machine_id: String,
18    pub asset_path: String,
19    pub local_path: String,
20    pub version: u32,
21}
22
23fn get_version(path: &Path) -> u32 {
24    let filename = path
25        .file_stem()
26        .expect("could not get file name")
27        .to_string_lossy()
28        .to_string()
29        .to_owned();
30
31    let version_tags = filename
32        .split('_')
33        .filter(|s| s.starts_with("v"))
34        .map(|s| s.replace("v", ""))
35        .filter_map(|s| s.parse::<u32>().ok())
36        .collect::<Vec<u32>>();
37    let version = version_tags.first();
38
39    match version {
40        Some(v) => v.to_owned(),
41        None => 0,
42    }
43}
44
45impl File {
46    pub fn new(path: &Path, machine_id: &String, base_path: &Path) -> Result<Self, String> {
47        let asset_path = path.strip_prefix(base_path).map_err(|e| e.to_string())?;
48
49        let file_name = asset_path
50            .file_stem()
51            .ok_or("File name is not valid")?
52            .to_string_lossy()
53            .to_string();
54
55        let file_name = file_name
56            .split('_')
57            .filter(|s| !s.starts_with("v"))
58            .collect::<Vec<&str>>()
59            .join("_");
60
61        let asset_path = change_file_name(asset_path, &file_name);
62
63        let asset_path = get_normal_path(&asset_path);
64        let local_path = get_normal_path(path);
65
66        Ok(File {
67            id: format!("{machine_id}:{local_path}"),
68            hash: uuid::Uuid::new_v4().to_string(),
69            machine_id: machine_id.to_string(),
70            local_path,
71            asset_path,
72            version: get_version(path),
73        })
74    }
75
76    pub fn local_path(&self) -> PathBuf {
77        get_local_path(&self.local_path)
78    }
79}
80
81fn change_file_name(path: impl AsRef<Path>, name: &str) -> PathBuf {
82    let path = path.as_ref();
83    let mut result = path.to_owned();
84    result.set_file_name(name);
85    if let Some(ext) = path.extension() {
86        result.set_extension(ext);
87    }
88    result
89}
90
91fn get_normal_path(path: &Path) -> String {
92    path.to_string_lossy()
93        .to_string()
94        .replace(path::MAIN_SEPARATOR, "/")
95}
96
97fn get_local_path(path: &str) -> PathBuf {
98    PathBuf::from(path.replace("/", std::path::MAIN_SEPARATOR_STR))
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(rename_all = "camelCase")]
103#[myko_query(File)]
104#[myko_query_handler(get_files_by_machine_id)]
105pub struct GetFilesByMachineId {
106    pub machine_id: String,
107}
108
109fn get_files_by_machine_id(
110    _q: GetFilesByMachineId,
111    tx: String,
112) -> impl tokio_stream::Stream<Item = QueryResult<File>> {
113    let files: Vec<File> = vec![];
114
115    let response = myko_rs::query::QueryResult::<File>::new(tx, files);
116    async_stream::stream! {
117        yield response;
118    }
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct AvailableVersionData {
123    pub min: u32,
124    pub max: u32,
125}
126
127#[cfg(feature = "mods")]
128#[derive(Debug, Clone, Serialize, Deserialize)]
129#[serde(rename_all = "camelCase")]
130#[myko_report(AvailableVersionData)]
131pub struct AvailableVersions {
132    pub asset_path: String,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
136#[serde(rename_all = "camelCase")]
137pub struct MissingAsset {
138    pub asset_path: String,
139    pub version: u32,
140    pub available_from: Vec<String>,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
144#[serde(rename_all = "camelCase")]
145pub struct Missing {
146    pub missing: Vec<MissingAsset>,
147}
148
149#[cfg(feature = "mods")]
150#[derive(Debug, Clone, Serialize, Deserialize)]
151#[serde(rename_all = "camelCase")]
152#[myko_report(Missing)]
153pub struct MissingFiles {
154    pub machine_id: String,
155}