Skip to content

Commit ecc8f17

Browse files
committed
started download command
created simplify_json_release_data
1 parent abc8bf4 commit ecc8f17

7 files changed

Lines changed: 281 additions & 22 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ exclude = [".gitignore", ".github/*"]
1717
[dependencies]
1818
reqwest = { version = "0.12", features = ["json", "blocking"] }
1919
serde_json = "1.0"
20+
serde = "1.0"
2021

2122
[[bin]]
2223
name = "gstats"

info.json

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
Object {
2+
"assets": Array [
3+
Object {
4+
"browser_download_url": String("https://github.com/cqb13/Numby-hack/releases/download/1.0/Numb-hack-1.0.jar"),
5+
"content_type": String("application/octet-stream"),
6+
"created_at": String("2022-02-15T22:38:10Z"),
7+
"download_count": Number(52),
8+
"id": Number(56952940),
9+
"label": Null,
10+
"name": String("Numb-hack-1.0.jar"),
11+
"node_id": String("RA_kwDOG2eD984DZQhs"),
12+
"size": Number(91637),
13+
"state": String("uploaded"),
14+
"updated_at": String("2022-02-15T22:38:11Z"),
15+
"uploader": Object {
16+
"avatar_url": String("https://avatars.githubusercontent.com/u/74616162?v=4"),
17+
"events_url": String("https://api.github.com/users/cqb13/events{/privacy}"),
18+
"followers_url": String("https://api.github.com/users/cqb13/followers"),
19+
"following_url": String("https://api.github.com/users/cqb13/following{/other_user}"),
20+
"gists_url": String("https://api.github.com/users/cqb13/gists{/gist_id}"),
21+
"gravatar_id": String(""),
22+
"html_url": String("https://github.com/cqb13"),
23+
"id": Number(74616162),
24+
"login": String("cqb13"),
25+
"node_id": String("MDQ6VXNlcjc0NjE2MTYy"),
26+
"organizations_url": String("https://api.github.com/users/cqb13/orgs"),
27+
"received_events_url": String("https://api.github.com/users/cqb13/received_events"),
28+
"repos_url": String("https://api.github.com/users/cqb13/repos"),
29+
"site_admin": Bool(false),
30+
"starred_url": String("https://api.github.com/users/cqb13/starred{/owner}{/repo}"),
31+
"subscriptions_url": String("https://api.github.com/users/cqb13/subscriptions"),
32+
"type": String("User"),
33+
"url": String("https://api.github.com/users/cqb13"),
34+
},
35+
"url": String("https://api.github.com/repos/cqb13/Numby-hack/releases/assets/56952940"),
36+
},
37+
],
38+
"assets_url": String("https://api.github.com/repos/cqb13/Numby-hack/releases/59649363/assets"),
39+
"author": Object {
40+
"avatar_url": String("https://avatars.githubusercontent.com/u/74616162?v=4"),
41+
"events_url": String("https://api.github.com/users/cqb13/events{/privacy}"),
42+
"followers_url": String("https://api.github.com/users/cqb13/followers"),
43+
"following_url": String("https://api.github.com/users/cqb13/following{/other_user}"),
44+
"gists_url": String("https://api.github.com/users/cqb13/gists{/gist_id}"),
45+
"gravatar_id": String(""),
46+
"html_url": String("https://github.com/cqb13"),
47+
"id": Number(74616162),
48+
"login": String("cqb13"),
49+
"node_id": String("MDQ6VXNlcjc0NjE2MTYy"),
50+
"organizations_url": String("https://api.github.com/users/cqb13/orgs"),
51+
"received_events_url": String("https://api.github.com/users/cqb13/received_events"),
52+
"repos_url": String("https://api.github.com/users/cqb13/repos"),
53+
"site_admin": Bool(false),
54+
"starred_url": String("https://api.github.com/users/cqb13/starred{/owner}{/repo}"),
55+
"subscriptions_url": String("https://api.github.com/users/cqb13/subscriptions"),
56+
"type": String("User"),
57+
"url": String("https://api.github.com/users/cqb13"),
58+
},
59+
"body": String("Number81 On Top"),
60+
"created_at": String("2022-02-15T22:28:07Z"),
61+
"draft": Bool(false),
62+
"html_url": String("https://github.com/cqb13/Numby-hack/releases/tag/1.0"),
63+
"id": Number(59649363),
64+
"name": String("Numby hack"),
65+
"node_id": String("RE_kwDOG2eD984Dji1T"),
66+
"prerelease": Bool(false),
67+
"published_at": String("2022-02-15T22:38:13Z"),
68+
"tag_name": String("1.0"),
69+
"tarball_url": String("https://api.github.com/repos/cqb13/Numby-hack/tarball/1.0"),
70+
"target_commitish": String("main"),
71+
"upload_url": String("https://uploads.github.com/repos/cqb13/Numby-hack/releases/59649363/assets{?name,label}"),
72+
"url": String("https://api.github.com/repos/cqb13/Numby-hack/releases/59649363"),
73+
"zipball_url": String("https://api.github.com/repos/cqb13/Numby-hack/zipball/1.0"),
74+
},

src/commands/all.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,14 @@ use crate::utils::{pretty_dates, request, write_json_to_file};
22
use serde_json::Value;
33
use std::path::PathBuf;
44

5-
pub fn all(
6-
owner: String,
7-
repo: String,
8-
output: Option<PathBuf>,
9-
display: bool,
10-
) -> Result<(), Box<dyn std::error::Error>> {
5+
pub fn all_command(owner: String, repo: String, output: Option<PathBuf>, display: bool) {
116
let url = format!("https://api.github.com/repos/{}/{}", owner, repo);
127

13-
let json = request(url)?;
8+
let json = request(url).expect("Failed to request data");
149

1510
if &json["message"] == "Not Found" {
1611
println!("Repository not found.");
17-
return Ok(());
12+
std::process::exit(0)
1813
}
1914

2015
if !display {
@@ -33,8 +28,6 @@ pub fn all(
3328
}
3429
None => {}
3530
}
36-
37-
Ok(())
3831
}
3932

4033
fn simplify_and_display_json(json: &Value) {

src/commands/downloads.rs

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
use crate::utils::{pretty_dates, request, write_json_to_file};
2+
use serde::{Deserialize, Deserializer, Serialize};
3+
use serde_json::Value;
4+
use std::{path::PathBuf, vec};
5+
6+
pub struct DownloadData {
7+
pub name: String,
8+
pub tag: String,
9+
pub published_at: String,
10+
pub created_at: String,
11+
pub html_url: String,
12+
pub body: String,
13+
pub assets: Vec<Asset>,
14+
}
15+
16+
impl DownloadData {
17+
pub fn new(
18+
name: String,
19+
tag: String,
20+
published_at: String,
21+
created_at: String,
22+
html_url: String,
23+
body: String,
24+
) -> DownloadData {
25+
DownloadData {
26+
name,
27+
tag,
28+
published_at,
29+
created_at,
30+
html_url,
31+
body,
32+
assets: Vec::new(),
33+
}
34+
}
35+
}
36+
37+
pub struct Asset {
38+
pub download_url: String,
39+
pub created_at: String,
40+
pub downloads: i64,
41+
pub name: String,
42+
pub size: i64,
43+
pub updated_at: String,
44+
}
45+
46+
impl Asset {
47+
pub fn new(
48+
download_url: String,
49+
created_at: String,
50+
downloads: i64,
51+
name: String,
52+
size: i64,
53+
updated_at: String,
54+
) -> Asset {
55+
Asset {
56+
download_url,
57+
created_at,
58+
downloads,
59+
name,
60+
size,
61+
updated_at,
62+
}
63+
}
64+
}
65+
66+
pub fn downloads_command(
67+
owner: String,
68+
repo: String,
69+
individual: bool,
70+
link: bool,
71+
output: Option<PathBuf>,
72+
all: bool,
73+
display: bool,
74+
) {
75+
let url = format!("https://api.github.com/repos/{}/{}/releases", owner, repo);
76+
77+
let json = request(url).expect("Failed to request data");
78+
79+
if &json["message"] == "Not Found" {
80+
println!("Repository not found.");
81+
std::process::exit(0)
82+
}
83+
84+
if json.as_array().unwrap().is_empty() {
85+
println!("No releases found.");
86+
std::process::exit(0)
87+
}
88+
89+
let simple_data = simplify_json_release_data(&json);
90+
println!("amount: {}", simple_data.len());
91+
92+
if all && !display {
93+
println!("{:#?}", json);
94+
} else if all && display {
95+
// show the json without all, but in pretty format
96+
} else if !all && !display {
97+
// if individual, get latest download url, and sum all item count
98+
// {download_url: Vec<(String name, String link for each asset of latest)>, html_url: String, download_count: i32}
99+
}
100+
101+
match output {
102+
Some(path) => {
103+
let result = write_json_to_file(json, path);
104+
match result {
105+
Ok(_) => {}
106+
Err(err) => println!("{}", err),
107+
}
108+
}
109+
None => {}
110+
}
111+
}
112+
113+
fn simplify_json_release_data(json: &Value) -> Vec<DownloadData> {
114+
let mut download_data: Vec<DownloadData> = Vec::new();
115+
116+
for release in json.as_array().unwrap() {
117+
let name = &release["name"].as_str().unwrap_or("None").to_string();
118+
let tag = &release["tag_name"].as_str().unwrap_or("None").to_string();
119+
let published_at = &release["published_at"]
120+
.as_str()
121+
.unwrap_or("None")
122+
.to_string();
123+
let created_at = &release["created_at"].as_str().unwrap_or("None").to_string();
124+
let html_url = &release["html_url"].as_str().unwrap_or("None").to_string();
125+
let body = &release["body"].as_str().unwrap_or("None").to_string();
126+
127+
let mut download = DownloadData::new(
128+
name.to_string(),
129+
tag.to_string(),
130+
published_at.to_string(),
131+
created_at.to_string(),
132+
html_url.to_string(),
133+
body.to_string(),
134+
);
135+
136+
for asset in release["assets"].as_array().unwrap() {
137+
let download_url = &asset["browser_download_url"]
138+
.as_str()
139+
.unwrap_or("None")
140+
.to_string();
141+
let created_at = &asset["created_at"].as_str().unwrap_or("None").to_string();
142+
let downloads = &asset["download_count"].as_i64().unwrap_or(0);
143+
let name = &asset["name"].as_str().unwrap_or("None").to_string();
144+
let size = &asset["size"].as_i64().unwrap_or(0);
145+
let updated_at = &asset["updated_at"].as_str().unwrap_or("None").to_string();
146+
147+
let asset = Asset::new(
148+
download_url.to_string(),
149+
created_at.to_string(),
150+
downloads.to_owned(),
151+
name.to_string(),
152+
size.to_owned(),
153+
updated_at.to_string(),
154+
);
155+
156+
download.assets.push(asset);
157+
}
158+
159+
download_data.push(download);
160+
}
161+
162+
download_data
163+
}

src/commands/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
pub mod all;
2+
pub mod downloads;

src/main.rs

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ pub mod commands;
33
pub mod utils;
44

55
use crate::cli::{Arg, Cli, Command};
6-
use crate::commands::all::all;
6+
use crate::commands::all::all_command;
7+
use crate::commands::downloads::downloads_command;
78
use crate::utils::validate_and_convert_path;
89

910
fn main() {
@@ -81,6 +82,13 @@ fn main() {
8182
.with_value_name("OUTPUT")
8283
.with_help("File path to save the json"),
8384
)
85+
.with_arg(
86+
Arg::new()
87+
.with_name("all")
88+
.with_short('a')
89+
.with_long("all")
90+
.with_help("All json from request"),
91+
)
8492
.with_arg(
8593
Arg::new()
8694
.with_name("display")
@@ -116,6 +124,13 @@ fn main() {
116124
.with_value_name("OUTPUT")
117125
.with_help("File path to save the json"),
118126
)
127+
.with_arg(
128+
Arg::new()
129+
.with_name("all")
130+
.with_short('a')
131+
.with_long("all")
132+
.with_help("All json from request"),
133+
)
119134
.with_arg(
120135
Arg::new()
121136
.with_name("display")
@@ -136,34 +151,45 @@ fn main() {
136151
let output = command.get_value_of("output").to_option();
137152
let display = command.has("display");
138153

139-
let output = match output {
140-
Some(path) => match validate_and_convert_path(path) {
141-
Ok(real_path) => Some(real_path),
142-
Err(err) => {
143-
println!("{}", err);
144-
std::process::exit(0)
145-
}
146-
},
147-
None => None,
148-
};
154+
let output = output_to_path(output);
149155

150-
let _ = all(owner, repo, output, display);
156+
all_command(owner, repo, output, display);
151157
}
152158
"downloads" => {
153159
let owner = command.get_value_of("owner").throw_if_none();
154160
let repo = command.get_value_of("repository").throw_if_none();
155161
let individual = command.has("individual");
156162
let link = command.has("link");
157163
let output = command.get_value_of("output").to_option();
164+
let all = command.has("all");
158165
let display = command.has("display");
166+
167+
let output = output_to_path(output);
168+
169+
downloads_command(owner, repo, individual, link, output, all, display);
159170
}
160171
"releases" => {
161172
let owner = command.get_value_of("owner").throw_if_none();
162173
let repo = command.get_value_of("repository").throw_if_none();
163174
let output = command.get_value_of("output").to_option();
175+
let all = command.has("all");
164176
let display = command.has("display");
177+
165178
}
166179
"help" => cli.help(),
167180
_ => cli.help(),
168181
}
169182
}
183+
184+
fn output_to_path(output: Option<String>) -> Option<std::path::PathBuf> {
185+
match output {
186+
Some(path) => match validate_and_convert_path(path) {
187+
Ok(real_path) => Some(real_path),
188+
Err(err) => {
189+
println!("{}", err);
190+
std::process::exit(0)
191+
}
192+
},
193+
None => None,
194+
}
195+
}

0 commit comments

Comments
 (0)