octx/
releases.rs

1use chrono::{DateTime, Utc};
2use octocrab::models::repos::Asset;
3use reqwest::Url;
4use serde::*;
5
6use crate::*;
7
8// use octocrab::models::repos::Release;
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11pub struct Release {
12    pub url: Url,
13    pub html_url: Url,
14    pub assets_url: Url,
15    pub upload_url: Url,
16    pub tarball_url: Option<Url>,
17    pub zipball_url: Option<Url>,
18    pub id: i64,
19    pub node_id: String,
20    pub tag_name: String,
21    pub target_commitish: String,
22    pub name: Option<String>,
23    pub body: Option<String>,
24    pub draft: bool,
25    pub prerelease: bool,
26    pub created_at: DateTime<Utc>,
27    pub published_at: Option<DateTime<Utc>>,
28    pub author: Option<octocrab::models::User>,
29    pub assets: Vec<Asset>,
30}
31
32#[derive(Serialize, Debug)]
33pub struct ReleaseRec {
34    pub url: Url,
35    pub html_url: Url,
36    pub assets_url: Url,
37    pub upload_url: Url,
38    pub tarball_url: Option<Url>,
39    pub zipball_url: Option<Url>,
40    pub id: i64,
41    pub node_id: String,
42    pub tag_name: String,
43    pub target_commitish: String,
44    pub name: Option<String>,
45    pub body: Option<String>,
46    pub draft: bool,
47    pub prerelease: bool,
48    pub created_at: DateTime<Utc>,
49    pub published_at: Option<DateTime<Utc>>,
50    pub author_id: Option<i64>,
51    pub assets: String,
52
53    pub sdc_repository: String,
54}
55
56impl From<Release> for ReleaseRec {
57    fn from(from: Release) -> Self {
58        Self {
59            url: from.url,
60            html_url: from.html_url,
61            assets_url: from.assets_url,
62            upload_url: from.upload_url,
63            tarball_url: from.tarball_url,
64            zipball_url: from.zipball_url,
65            id: from.id,
66            node_id: from.node_id,
67            tag_name: from.tag_name,
68            target_commitish: from.target_commitish,
69            name: from.name,
70            body: from.body,
71            draft: from.draft,
72            prerelease: from.prerelease,
73            created_at: from.created_at,
74            published_at: from.published_at,
75            author_id: from.author.map(|u| u.id),
76            assets: from
77                .assets
78                .iter()
79                .map(|v| format!("{};{};{}", v.id, v.name, v.browser_download_url))
80                .collect::<Vec<String>>()
81                .join(","),
82
83            sdc_repository: String::default(),
84        }
85    }
86}
87
88impl RepositryAware for ReleaseRec {
89    fn set_repository(&mut self, name: String) {
90        self.sdc_repository = name;
91    }
92}
93
94pub struct ReleaseFetcher {
95    owner: String,
96    name: String,
97    octocrab: octocrab::Octocrab,
98}
99
100impl ReleaseFetcher {
101    pub fn new(owner: String, name: String, octocrab: octocrab::Octocrab) -> Self {
102        Self {
103            owner,
104            name,
105            octocrab,
106        }
107    }
108}
109
110impl UrlConstructor for ReleaseFetcher {
111    fn reponame(&self) -> String {
112        format!("{}/{}", self.owner, self.name)
113    }
114
115    fn entrypoint(&self) -> Option<Url> {
116        let param = Params::default();
117
118        let route = format!(
119            "repos/{owner}/{repo}/releases?{query}",
120            owner = &self.owner,
121            repo = &self.name,
122            query = param.to_query(),
123        );
124        self.octocrab.absolute_url(route).ok()
125    }
126}
127
128impl LoopWriter for ReleaseFetcher {
129    type Model = Release;
130    type Record = ReleaseRec;
131}
132
133impl ReleaseFetcher {
134    pub async fn fetch<T: std::io::Write>(&self, mut wtr: csv::Writer<T>) -> octocrab::Result<()> {
135        let mut next: Option<Url> = self.entrypoint();
136
137        while let Some(page) = self.octocrab.get_page(&next).await? {
138            next = self.write_and_continue(page, &mut wtr);
139        }
140
141        Ok(())
142    }
143}