@@ -14,13 +14,18 @@ use crate::{
14
14
download,
15
15
mod_entity:: { download_geode_file, Mod } ,
16
16
mod_gd_version:: { GDVersionEnum , VerPlatform } ,
17
- mod_version:: ModVersion ,
17
+ mod_version:: { self , ModVersion } ,
18
18
mod_version_status:: ModVersionStatusEnum ,
19
19
} ,
20
20
} ,
21
21
AppData ,
22
22
} ;
23
23
24
+ #[ derive( Deserialize ) ]
25
+ struct IndexPath {
26
+ id : String ,
27
+ }
28
+
24
29
#[ derive( Deserialize ) ]
25
30
pub struct GetOnePath {
26
31
id : String ,
@@ -56,6 +61,46 @@ struct GetOneQuery {
56
61
major : Option < u32 > ,
57
62
}
58
63
64
+ #[ derive( Deserialize ) ]
65
+ struct IndexQuery {
66
+ page : Option < i64 > ,
67
+ per_page : Option < i64 > ,
68
+ #[ serde( default ) ]
69
+ gd : Option < GDVersionEnum > ,
70
+ platforms : Option < String > ,
71
+ status : Option < ModVersionStatusEnum > ,
72
+ }
73
+
74
+ #[ get( "v1/mods/{id}/versions" ) ]
75
+ pub async fn get_version_index (
76
+ path : web:: Path < IndexPath > ,
77
+ data : web:: Data < AppData > ,
78
+ query : web:: Query < IndexQuery > ,
79
+ ) -> Result < impl Responder , ApiError > {
80
+ let platforms = VerPlatform :: parse_query_string ( & query. platforms . clone ( ) . unwrap_or_default ( ) ) ;
81
+ let mut pool = data. db . acquire ( ) . await . or ( Err ( ApiError :: DbAcquireError ) ) ?;
82
+ let mut result = ModVersion :: get_index (
83
+ mod_version:: IndexQuery {
84
+ mod_id : path. id . clone ( ) ,
85
+ page : query. page . unwrap_or ( 1 ) ,
86
+ per_page : query. per_page . unwrap_or ( 10 ) ,
87
+ gd : query. gd ,
88
+ platforms,
89
+ status : query. status . unwrap_or ( ModVersionStatusEnum :: Accepted ) ,
90
+ } ,
91
+ & mut pool,
92
+ )
93
+ . await ?;
94
+ for i in & mut result. data {
95
+ i. modify_download_link ( & data. app_url ) ;
96
+ }
97
+
98
+ Ok ( web:: Json ( ApiResponse {
99
+ payload : result,
100
+ error : "" . to_string ( ) ,
101
+ } ) )
102
+ }
103
+
59
104
#[ get( "v1/mods/{id}/versions/{version}" ) ]
60
105
pub async fn get_one (
61
106
path : web:: Path < GetOnePath > ,
@@ -74,29 +119,12 @@ pub async fn get_one(
74
119
None => None ,
75
120
} ;
76
121
77
- let mut platforms: Vec < VerPlatform > = vec ! [ ] ;
78
-
79
- if let Some ( p) = & query. platforms {
80
- for x in p. split ( ',' ) {
81
- match VerPlatform :: from_str ( x) {
82
- Ok ( v) => {
83
- if v == VerPlatform :: Android {
84
- platforms. push ( VerPlatform :: Android32 ) ;
85
- platforms. push ( VerPlatform :: Android64 ) ;
86
- } else {
87
- platforms. push ( v) ;
88
- }
89
- }
90
- Err ( _) => {
91
- return Err ( ApiError :: BadRequest ( "Invalid platform" . to_string ( ) ) ) ;
92
- }
93
- }
94
- }
95
- } ;
122
+ let platform_string = query. platforms . clone ( ) . unwrap_or_default ( ) ;
123
+ let platforms = VerPlatform :: parse_query_string ( & platform_string) ;
96
124
97
125
ModVersion :: get_latest_for_mod ( & path. id , gd, platforms, query. major , & mut pool) . await ?
98
126
} else {
99
- ModVersion :: get_one ( & path. id , & path. version , true , & mut pool) . await ?
127
+ ModVersion :: get_one ( & path. id , & path. version , true , false , & mut pool) . await ?
100
128
}
101
129
} ;
102
130
@@ -107,15 +135,33 @@ pub async fn get_one(
107
135
} ) )
108
136
}
109
137
138
+ #[ derive( Deserialize ) ]
139
+ struct DownloadQuery {
140
+ gd : Option < GDVersionEnum > ,
141
+ // platform1,platform2,...
142
+ platforms : Option < String > ,
143
+ major : Option < u32 > ,
144
+ }
145
+
110
146
#[ get( "v1/mods/{id}/versions/{version}/download" ) ]
111
147
pub async fn download_version (
112
148
path : web:: Path < GetOnePath > ,
113
149
data : web:: Data < AppData > ,
150
+ query : web:: Query < DownloadQuery > ,
114
151
info : ConnectionInfo ,
115
152
) -> Result < impl Responder , ApiError > {
116
153
let mut pool = data. db . acquire ( ) . await . or ( Err ( ApiError :: DbAcquireError ) ) ?;
117
- let mod_version = ModVersion :: get_one ( & path. id , & path. version , false , & mut pool) . await ?;
118
- let url = ModVersion :: get_download_url ( & path. id , & path. version , & mut pool) . await ?;
154
+ let mod_version = {
155
+ if path. version == "latest" {
156
+ let platform_str = query. platforms . clone ( ) . unwrap_or_default ( ) ;
157
+ let platforms = VerPlatform :: parse_query_string ( & platform_str) ;
158
+ ModVersion :: get_latest_for_mod ( & path. id , query. gd , platforms, query. major , & mut pool)
159
+ . await ?
160
+ } else {
161
+ ModVersion :: get_one ( & path. id , & path. version , false , false , & mut pool) . await ?
162
+ }
163
+ } ;
164
+ let url = mod_version. download_link ;
119
165
120
166
let ip = match info. realip_remote_addr ( ) {
121
167
None => return Err ( ApiError :: InternalError ) ,
@@ -124,8 +170,25 @@ pub async fn download_version(
124
170
let net: IpNetwork = ip. parse ( ) . or ( Err ( ApiError :: InternalError ) ) ?;
125
171
126
172
if download:: create_download ( net, mod_version. id , & mut pool) . await ? {
127
- ModVersion :: calculate_cached_downloads ( mod_version. id , & mut pool) . await ?;
128
- Mod :: calculate_cached_downloads ( & mod_version. mod_id , & mut pool) . await ?;
173
+ let name = mod_version. mod_id . clone ( ) ;
174
+ let version = mod_version. version . clone ( ) ;
175
+ tokio:: spawn ( async move {
176
+ if let Err ( e) = ModVersion :: calculate_cached_downloads ( mod_version. id , & mut pool) . await
177
+ {
178
+ log:: error!(
179
+ "Failed to calculate cached downloads for mod version {}. Error: {}" ,
180
+ version,
181
+ e
182
+ ) ;
183
+ }
184
+ if let Err ( e) = Mod :: calculate_cached_downloads ( & mod_version. mod_id , & mut pool) . await {
185
+ log:: error!(
186
+ "Failed to calculate cached downloads for mod {}. Error: {}" ,
187
+ name,
188
+ e
189
+ ) ;
190
+ }
191
+ } ) ;
129
192
}
130
193
131
194
Ok ( HttpResponse :: Found ( )
0 commit comments