Skip to main content

esi_openapi/groups/
military_campaigns.rs

1use crate::groups::Page;
2use crate::prelude::*;
3use uuid::Uuid;
4
5/// Endpoints for Military Campaigns
6pub struct MilitaryCampaignsGroup<'a> {
7    pub(crate) esi: &'a Esi,
8}
9
10/// The state of a campaign or objective.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
12pub enum CampaignState {
13    /// The state is not specified.
14    Unspecified,
15    /// In progress.
16    Active,
17    /// Completed.
18    Completed,
19    /// Expired.
20    Expired,
21    /// A state this version of the crate does not know about.
22    #[serde(other)]
23    Unrecognized,
24}
25
26/// A military campaign.
27#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
28#[allow(missing_docs)]
29pub struct Campaign {
30    pub finished: Option<String>,
31    pub id: Uuid,
32    pub progress: i64,
33    pub started: Option<String>,
34    pub state: CampaignState,
35}
36
37/// Participation counts of an objective.
38#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
39#[allow(missing_docs)]
40pub struct ObjectiveParticipants {
41    pub committed: i64,
42    pub contributors: i64,
43    pub total: i64,
44}
45
46/// An objective of a campaign.
47#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
48#[allow(missing_docs)]
49pub struct Objective {
50    pub finished: Option<String>,
51    pub id: Uuid,
52    pub last_modified: String,
53    pub participants: ObjectiveParticipants,
54    pub progress: i64,
55    pub started: Option<String>,
56    pub state: CampaignState,
57}
58
59#[derive(Debug, Deserialize)]
60struct CampaignList {
61    campaigns: Vec<Campaign>,
62}
63
64impl MilitaryCampaignsGroup<'_> {
65    /// List the military campaigns.
66    pub async fn list(&self) -> EsiResult<Vec<Campaign>> {
67        let path = self
68            .esi
69            .get_endpoint_for_op_id("GetMilitaryCampaignsListing")?;
70        let wrapper: CampaignList = self
71            .esi
72            .query("GET", RequestType::Public, &path, None, None)
73            .await?;
74        Ok(wrapper.campaigns)
75    }
76
77    api_get!(
78        /// Get a military campaign.
79        get_campaign,
80        "GetMilitaryCampaignsDetail",
81        RequestType::Public,
82        Campaign,
83        (campaign_id: Uuid) => "{campaign_id}"
84    );
85
86    api_get!(
87        /// List the objectives of a campaign. Use the cursor of the returned page
88        /// as `after` or `before` to walk through the list.
89        list_objectives,
90        "GetMilitaryCampaignsObjectivesListing",
91        RequestType::Public,
92        Page<Objective>,
93        (campaign_id: Uuid) => "{campaign_id}";
94        Optional(after: String) => "after",
95        Optional(before: String) => "before",
96        Optional(limit: i64) => "limit"
97    );
98
99    api_get!(
100        /// Get an objective of a campaign.
101        get_objective,
102        "GetMilitaryCampaignsObjectivesDetail",
103        RequestType::Public,
104        Objective,
105        (campaign_id: Uuid) => "{campaign_id}",
106        (objective_id: Uuid) => "{objective_id}"
107    );
108}
109
110#[cfg(test)]
111mod tests {
112    use super::{Campaign, CampaignState};
113    use crate::groups::{Objective, Page};
114
115    #[test]
116    fn test_parse_campaign() {
117        let json =
118            r#"{"id": "3868eaed-8278-4cb7-9709-7d7de9c20dc7", "progress": 40, "state": "Active"}"#;
119        let campaign: Campaign = serde_json::from_str(json).unwrap();
120        assert_eq!(campaign.state, CampaignState::Active);
121        assert!(campaign.started.is_none());
122    }
123
124    #[test]
125    fn test_parse_objectives_page_without_cursor() {
126        let json = r#"{"objectives": [{
127            "id": "3868eaed-8278-4cb7-9709-7d7de9c20dc7",
128            "last_modified": "2026-10-01T00:00:00Z",
129            "participants": {"committed": 1, "contributors": 2, "total": 3},
130            "progress": 5, "state": "Completed"
131        }]}"#;
132        let page: Page<Objective> = serde_json::from_str(json).unwrap();
133        assert!(page.cursor.is_none());
134        assert_eq!(page.items[0].participants.total, 3);
135    }
136}
137
138/// The participation of a character in a campaign objective.
139#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
140#[allow(missing_docs)]
141pub struct CharacterObjective {
142    pub campaign_id: Uuid,
143    pub contributed: i64,
144    pub id: Uuid,
145    pub is_committed: bool,
146    pub last_modified: String,
147}
148
149impl MilitaryCampaignsGroup<'_> {
150    api_get!(
151        /// List the campaign objectives a character takes part in.
152        list_character_objectives,
153        "GetCharactersMilitaryCampaignsObjectivesListing",
154        RequestType::Authenticated,
155        Page<CharacterObjective>,
156        (character_id: i64) => "{character_id}";
157        Optional(after: String) => "after",
158        Optional(before: String) => "before",
159        Optional(limit: i64) => "limit"
160    );
161
162    api_get!(
163        /// Get the participation of a character in one objective.
164        get_character_objective,
165        "GetCharactersMilitaryCampaignsObjectivesParticipation",
166        RequestType::Authenticated,
167        CharacterObjective,
168        (character_id: i64) => "{character_id}",
169        (objective_id: Uuid) => "{objective_id}"
170    );
171}