1
- use std:: path:: Path ;
1
+ use anyhow;
2
+ use regex;
2
3
use rusoto_core:: HttpClient ;
3
4
use rusoto_s3:: S3 ;
4
- use tokio:: { self , io:: { AsyncReadExt , BufReader } } ;
5
- use regex;
6
- use serde_yaml;
7
5
use serde;
8
- use anyhow;
6
+ use serde_yaml;
7
+ use std:: path:: Path ;
9
8
use structopt:: StructOpt ;
9
+ use tokio:: {
10
+ self ,
11
+ io:: { AsyncReadExt , BufReader } ,
12
+ } ;
10
13
11
14
#[ derive( StructOpt ) ]
12
15
struct Input {
@@ -18,15 +21,25 @@ struct Input {
18
21
backend_url : String ,
19
22
#[ structopt( short = "t" , long = "token" , help = "Token" , required = true ) ]
20
23
backend_token : String ,
21
- #[ structopt( short = "a" , long = "ACCESS_KEY_ID" , help = "ACCESS_KEY_ID" , required = true ) ]
24
+ #[ structopt(
25
+ short = "a" ,
26
+ long = "ACCESS_KEY_ID" ,
27
+ help = "ACCESS_KEY_ID" ,
28
+ required = true
29
+ ) ]
22
30
assess_key_id : String ,
23
- #[ structopt( short = "s" , long = "SECRET_ACCESS_KEY" , help = "SECRET_ACCESS_KEY" , required = true ) ]
31
+ #[ structopt(
32
+ short = "s" ,
33
+ long = "SECRET_ACCESS_KEY" ,
34
+ help = "SECRET_ACCESS_KEY" ,
35
+ required = true
36
+ ) ]
24
37
secret_access_key : String ,
25
38
#[ structopt( short = "c" , long = "bucket" , help = "bucket name" , required = true ) ]
26
39
bucket : String ,
27
40
}
28
41
29
- #[ derive( serde:: Deserialize ) ]
42
+ #[ derive( serde:: Deserialize , Debug ) ]
30
43
enum Type {
31
44
#[ serde( rename = "test" ) ]
32
45
Test ,
@@ -36,26 +49,25 @@ enum Type {
36
49
Doc ,
37
50
}
38
51
39
- #[ derive( serde:: Deserialize ) ]
52
+ #[ derive( serde:: Deserialize , Debug ) ]
40
53
#[ serde( untagged) ]
41
54
enum Data {
42
55
Test ( Test ) ,
43
56
Book ( Book ) ,
44
57
Doc ( Doc ) ,
45
-
46
58
}
47
59
48
- #[ derive( serde:: Deserialize ) ]
60
+ #[ derive( serde:: Deserialize , Debug ) ]
49
61
#[ allow( dead_code) ]
50
62
struct MetaData {
51
63
id : String ,
52
64
url : String ,
53
65
#[ serde( rename = "type" ) ]
54
66
type_ : Type ,
55
- data : Data
67
+ data : Data ,
56
68
}
57
69
58
- #[ derive( serde:: Deserialize ) ]
70
+ #[ derive( serde:: Deserialize , Debug ) ]
59
71
#[ allow( dead_code) ]
60
72
struct Test {
61
73
title : String ,
@@ -66,15 +78,15 @@ struct Test {
66
78
content : Vec < String > ,
67
79
}
68
80
69
- #[ derive( serde:: Deserialize ) ]
81
+ #[ derive( serde:: Deserialize , Debug ) ]
70
82
#[ allow( dead_code) ]
71
83
struct Course {
72
84
#[ serde( rename = "type" ) ]
73
85
type_ : Option < String > ,
74
86
name : Option < String > ,
75
87
}
76
88
77
- #[ derive( serde:: Deserialize ) ]
89
+ #[ derive( serde:: Deserialize , Debug ) ]
78
90
#[ allow( dead_code) ]
79
91
struct Book {
80
92
title : String ,
@@ -86,7 +98,7 @@ struct Book {
86
98
filetype : String ,
87
99
}
88
100
89
- #[ derive( serde:: Deserialize ) ]
101
+ #[ derive( serde:: Deserialize , Debug ) ]
90
102
#[ allow( dead_code) ]
91
103
struct Doc {
92
104
title : String ,
@@ -95,7 +107,7 @@ struct Doc {
95
107
content : Vec < DocContent > ,
96
108
}
97
109
98
- #[ derive( serde:: Deserialize ) ]
110
+ #[ derive( serde:: Deserialize , Debug ) ]
99
111
#[ serde( rename_all = "PascalCase" ) ]
100
112
enum DocContent {
101
113
思维导图,
@@ -146,7 +158,10 @@ async fn main() -> anyhow::Result<()> {
146
158
147
159
let end_point = input. s3_url ;
148
160
let http_client = HttpClient :: new ( ) ?;
149
- let credentials = rusoto_core:: credential:: StaticProvider :: new_minimal ( input. assess_key_id , input. secret_access_key ) ;
161
+ let credentials = rusoto_core:: credential:: StaticProvider :: new_minimal (
162
+ input. assess_key_id ,
163
+ input. secret_access_key ,
164
+ ) ;
150
165
let region = rusoto_core:: Region :: Custom {
151
166
name : "byr" . to_owned ( ) ,
152
167
endpoint : end_point,
@@ -157,25 +172,41 @@ async fn main() -> anyhow::Result<()> {
157
172
..Default :: default ( )
158
173
} ;
159
174
let result = s3_client. list_objects_v2 ( request) . await ?;
160
- let s3_file_list = result. contents . unwrap ( ) . iter ( ) . map ( |item| item. key . clone ( ) . unwrap ( ) ) . collect :: < Vec < _ > > ( ) ;
175
+ let s3_file_list = result
176
+ . contents
177
+ . unwrap ( )
178
+ . iter ( )
179
+ . map ( |item| item. key . clone ( ) . unwrap ( ) )
180
+ . collect :: < Vec < _ > > ( ) ;
161
181
162
182
let backend_client = reqwest:: Client :: new ( ) ;
163
- let temp_files = backend_client. get ( format ! ( "{}/api/file/notPublished" , input. backend_url) )
183
+ let temp_files = backend_client
184
+ . get ( format ! ( "{}/api/file/notPublished" , input. backend_url) )
164
185
. bearer_auth ( input. backend_token )
165
186
. send ( )
166
187
. await ?
167
188
. json :: < ApiResult > ( )
168
189
. await ?;
169
190
191
+ let mut success_book = 0 ;
192
+ let mut success_test = 0 ;
193
+ let mut success_doc = 0 ;
194
+ let mut total = 0 ;
170
195
let dir_path = Path :: new ( & input. dir ) ;
196
+
171
197
for entry in dir_path. read_dir ( ) ? {
198
+ total += 1 ;
172
199
let entry = entry?;
200
+ if !entry. file_name ( ) . to_str ( ) . unwrap ( ) . ends_with ( ".yml" ) {
201
+ continue ;
202
+ }
173
203
let path = entry. path ( ) ;
174
204
if path. is_file ( ) {
175
-
176
205
let file = std:: fs:: File :: open ( & path) ?;
177
206
let metadata: MetaData = serde_yaml:: from_reader ( file) ?;
178
- let url_regex = regex:: Regex :: new ( r"^https://byrdocs\.org/files/[a-fA-F0-9]{32}\.(pdf|zip)$" ) . unwrap ( ) ;
207
+ let url_regex =
208
+ regex:: Regex :: new ( r"^https://byrdocs\.org/files/[a-fA-F0-9]{32}\.(pdf|zip)$" )
209
+ . unwrap ( ) ;
179
210
if !url_regex. is_match ( & metadata. url ) | !metadata. url . contains ( metadata. id . as_str ( ) ) {
180
211
println ! ( "Invalid URL or id: {}" , path. display( ) ) ;
181
212
continue ;
@@ -190,7 +221,9 @@ async fn main() -> anyhow::Result<()> {
190
221
}
191
222
192
223
for temp_file in & temp_files. files {
193
- if temp_file. file_name . as_str ( ) == format ! ( "{}.pdf" , metadata. id) || temp_file. file_name . as_str ( ) == format ! ( "{}.zip" , metadata. id) {
224
+ if temp_file. file_name . as_str ( ) == format ! ( "{}.pdf" , metadata. id)
225
+ || temp_file. file_name . as_str ( ) == format ! ( "{}.zip" , metadata. id)
226
+ {
194
227
match temp_file. status {
195
228
Status :: Published => {
196
229
println ! ( "Published: {}" , path. display( ) ) ;
@@ -215,19 +248,28 @@ async fn main() -> anyhow::Result<()> {
215
248
}
216
249
}
217
250
match metadata. data {
218
- Data :: Test ( test ) => {
219
- println ! ( "Test: {}" , test . title ) ;
251
+ Data :: Test ( _test ) => {
252
+ success_test += 1 ;
220
253
}
221
- Data :: Book ( book ) => {
222
- println ! ( "Book: {}" , book . title ) ;
254
+ Data :: Book ( _book ) => {
255
+ success_book += 1 ;
223
256
}
224
- Data :: Doc ( doc ) => {
225
- println ! ( "Doc: {}" , doc . title ) ;
257
+ Data :: Doc ( _doc ) => {
258
+ success_doc += 1 ;
226
259
}
227
260
}
228
261
}
229
262
}
230
-
231
-
263
+ println ! (
264
+ "Total: {}, Success: {}, Book: {}, Test: {}, Doc: {}" ,
265
+ total,
266
+ success_book + success_test + success_doc,
267
+ success_book,
268
+ success_test,
269
+ success_doc
270
+ ) ;
271
+ if total != success_book + success_test + success_doc {
272
+ return Err ( anyhow:: anyhow!( "Some files are invalid" ) ) ;
273
+ }
232
274
Ok ( ( ) )
233
- }
275
+ }
0 commit comments