modio/client/
methods.rs

1use std::path::Path;
2
3use bytes::Bytes;
4use futures_util::TryStream;
5
6use crate::request::auth::external::Provider;
7use crate::request::auth::{EmailExchange, EmailRequest, ExternalAuth, GetTerms, Logout};
8use crate::request::files::multipart::{
9    AddMultipartUploadFile, AddMultipartUploadPart, CompleteMultipartUploadSession, ContentRange,
10    CreateMultipartUploadSession, DeleteMultipartUploadSession, GetMultipartUploadParts,
11    GetMultipartUploadSessions,
12};
13use crate::request::files::{
14    AddFile, DeleteFile, EditFile, GetFile, GetFiles, ManagePlatformStatus,
15};
16use crate::request::games::tags::{AddGameTags, DeleteGameTags, GetGameTags, RenameGameTag};
17use crate::request::games::{AddGameMedia, GetGame, GetGameStats, GetGames};
18use crate::request::mods::comments::{
19    AddModComment, DeleteModComment, EditModComment, GetModComment, GetModComments,
20    UpdateModCommentKarma,
21};
22use crate::request::mods::dependencies::{
23    AddModDependencies, DeleteModDependencies, GetModDependencies,
24};
25use crate::request::mods::events::{GetModEvents, GetModsEvents};
26use crate::request::mods::media::{AddModMedia, DeleteModMedia, ReorderModMedia};
27use crate::request::mods::metadata::{AddModMetadata, DeleteModMetadata, GetModMetadata};
28use crate::request::mods::stats::{GetModStats, GetModsStats};
29use crate::request::mods::subscribe::{SubscribeToMod, UnsubscribeFromMod};
30use crate::request::mods::tags::{AddModTags, DeleteModTags, GetModTags};
31use crate::request::mods::{
32    AddMod, DeleteMod, EditMod, GetMod, GetModTeamMembers, GetMods, SubmitModRating,
33};
34use crate::request::user::{
35    GetAuthenticatedUser, GetMutedUsers, GetUserEvents, GetUserFiles, GetUserGames, GetUserMods,
36    GetUserRatings, GetUserSubscriptions, MuteUser, UnmuteUser,
37};
38use crate::request::SubmitReport;
39use crate::types::files::multipart::UploadId;
40use crate::types::games::TagType;
41use crate::types::id::{CommentId, FileId, GameId, ModId, ResourceId, UserId};
42use crate::types::mods::MetadataMap;
43
44use super::Client;
45
46impl Client {
47    /// Get text and links for user agreement and consent prior to authentication. [required: apikey]
48    ///
49    /// See the [mod.io docs](https://docs.mod.io/restapiref/#terms) for more information.
50    pub const fn get_terms(&self) -> GetTerms<'_> {
51        GetTerms::new(self)
52    }
53
54    /// Request a security code be sent to the email of the user. [required: apikey]
55    pub const fn request_code<'a>(&'a self, email: &'a str) -> EmailRequest<'a> {
56        EmailRequest::new(self, email)
57    }
58
59    /// Get the access token for a security code. [required: apikey]
60    pub const fn request_token<'a>(&'a self, security_code: &'a str) -> EmailExchange<'a> {
61        EmailExchange::new(self, security_code)
62    }
63
64    /// Authenticate via external services (Steam, GOG, Switch, Xbox, Discord, Oculus, Google etc.).
65    ///
66    /// See the [mod.io docs](https://docs.mod.io/restapiref/#authentication-2) for more information.
67    ///
68    /// # Examples
69    ///
70    /// ```no_run
71    /// # use modio::Client;
72    /// #
73    /// # #[tokio::main]
74    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
75    /// #    let client = Client::builder("api-key".to_owned()).build()?;
76    /// use modio::request::auth::external::Steam;
77    /// let response = client.external_auth(Steam::new("ticket")).await?;
78    /// let token = response.data().await?;
79    ///
80    /// use modio::request::auth::external::PSN;
81    /// let response = client.external_auth(PSN::new("auth_code")).env(1).await?;
82    /// let token = response.data().await?;
83    ///
84    /// use modio::request::auth::external::Discord;
85    /// let response = client
86    ///     .external_auth(Discord::new("token"))
87    ///     .email("john@example.com")
88    ///     .await?;
89    /// let token = response.data().await?;
90    /// #     Ok(())
91    /// # }
92    /// ```
93    pub const fn external_auth<T: Provider>(&self, external: T) -> ExternalAuth<'_, T> {
94        ExternalAuth::new(self, external)
95    }
96
97    /// Log out by revoking the current access token.
98    pub const fn logout(&self) -> Logout<'_> {
99        Logout::new(self)
100    }
101}
102
103impl Client {
104    /// Get all games.
105    pub const fn get_games(&self) -> GetGames<'_> {
106        GetGames::new(self)
107    }
108
109    /// Get a game.
110    pub const fn get_game(&self, game_id: GameId) -> GetGame<'_> {
111        GetGame::new(self, game_id)
112    }
113
114    /// Return the statistics for a game.
115    pub const fn get_game_stats(&self, game_id: GameId) -> GetGameStats<'_> {
116        GetGameStats::new(self, game_id)
117    }
118
119    /// Return the tag options for a game.
120    pub const fn get_game_tags(&self, game_id: GameId) -> GetGameTags<'_> {
121        GetGameTags::new(self, game_id)
122    }
123
124    /// Add tags which can applied to mods. [required: token]
125    pub const fn add_game_tags<'a>(
126        &'a self,
127        game_id: GameId,
128        name: &'a str,
129        kind: TagType,
130        tags: &'a [&'a str],
131    ) -> AddGameTags<'a> {
132        AddGameTags::new(self, game_id, name, kind, tags)
133    }
134
135    /// Delete an entire group of tags or individual tags. [required: token]
136    pub const fn delete_game_tags<'a>(
137        &'a self,
138        game_id: GameId,
139        name: &'a str,
140    ) -> DeleteGameTags<'a> {
141        DeleteGameTags::new(self, game_id, name)
142    }
143
144    /// Rename an existing tag, updating all mods in the progress. [required: token]
145    pub const fn rename_game_tag<'a>(
146        &'a self,
147        game_id: GameId,
148        from: &'a str,
149        to: &'a str,
150    ) -> RenameGameTag<'a> {
151        RenameGameTag::new(self, game_id, from, to)
152    }
153
154    /// Add new media to a game. [required: token]
155    pub const fn add_game_media(&self, game_id: GameId) -> AddGameMedia<'_> {
156        AddGameMedia::new(self, game_id)
157    }
158}
159
160impl Client {
161    /// Get all mods for a game.
162    ///
163    /// See [Filters and sorting](crate::request::mods::filters)
164    ///
165    /// # Examples
166    ///
167    /// ```no_run
168    /// # #[tokio::main]
169    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
170    /// #     let client = modio::Client::builder("key".to_owned()).build()?;
171    /// use modio::request::filter::prelude::*;
172    /// use modio::request::mods::filters::Name;
173    /// use modio::types::id::Id;
174    ///
175    /// let list = client
176    ///     .get_mods(Id::new(51))
177    ///     .filter(Name::eq("the-x-com-files"))
178    ///     .await?
179    ///     .data()
180    ///     .await?;
181    /// #     Ok(())
182    /// # }
183    /// ```
184    pub const fn get_mods(&self, game_id: GameId) -> GetMods<'_> {
185        GetMods::new(self, game_id)
186    }
187
188    /// Get the Modio mod object that this refers to.
189    pub const fn get_mod(&self, game_id: GameId, mod_id: ModId) -> GetMod<'_> {
190        GetMod::new(self, game_id, mod_id)
191    }
192
193    /// Add a mod and return the newly created Modio mod object. [required: token]
194    pub fn add_mod<'a>(
195        &'a self,
196        game_id: GameId,
197        name: &'a str,
198        summary: &'a str,
199        logo: impl AsRef<Path>,
200    ) -> AddMod<'a> {
201        AddMod::new(self, game_id, name, summary, logo)
202    }
203
204    /// Edit details for a mod. [required: token]
205    pub const fn edit_mod(&self, game_id: GameId, mod_id: ModId) -> EditMod<'_> {
206        EditMod::new(self, game_id, mod_id)
207    }
208
209    /// Delete a mod. [required: token]
210    pub const fn delete_mod(&self, game_id: GameId, mod_id: ModId) -> DeleteMod<'_> {
211        DeleteMod::new(self, game_id, mod_id)
212    }
213
214    /// Add new media to a mod. [required: token]
215    pub const fn add_mod_media(&self, game_id: GameId, mod_id: ModId) -> AddModMedia<'_> {
216        AddModMedia::new(self, game_id, mod_id)
217    }
218
219    /// Delete media from a mod. [required: token]
220    pub const fn delete_mod_media(&self, game_id: GameId, mod_id: ModId) -> DeleteModMedia<'_> {
221        DeleteModMedia::new(self, game_id, mod_id)
222    }
223
224    /// Reorder the media of a mod. [required: token]
225    pub const fn reorder_mod_media(&self, game_id: GameId, mod_id: ModId) -> ReorderModMedia<'_> {
226        ReorderModMedia::new(self, game_id, mod_id)
227    }
228
229    /// Subscribe the authenticated user to a mod. [required: token]
230    pub const fn subscribe_to_mod(&self, game_id: GameId, mod_id: ModId) -> SubscribeToMod<'_> {
231        SubscribeToMod::new(self, game_id, mod_id)
232    }
233
234    /// Unsubscribe the authenticated user from a mod. [required: token]
235    pub const fn unsubscribe_from_mod(
236        &self,
237        game_id: GameId,
238        mod_id: ModId,
239    ) -> UnsubscribeFromMod<'_> {
240        UnsubscribeFromMod::new(self, game_id, mod_id)
241    }
242
243    /// Submit a rating for a mod. [required: token]
244    pub const fn rate_mod(&self, game_id: GameId, mod_id: ModId) -> SubmitModRating<'_> {
245        SubmitModRating::new(self, game_id, mod_id)
246    }
247
248    /// Get all users that are part of a mod team.
249    pub const fn get_mod_team_members(
250        &self,
251        game_id: GameId,
252        mod_id: ModId,
253    ) -> GetModTeamMembers<'_> {
254        GetModTeamMembers::new(self, game_id, mod_id)
255    }
256}
257
258impl Client {
259    /// Get all tags for a mod.
260    pub const fn get_mod_tags(&self, game_id: GameId, mod_id: ModId) -> GetModTags<'_> {
261        GetModTags::new(self, game_id, mod_id)
262    }
263
264    /// Add tags to a mod. [required: token]
265    pub const fn add_mod_tags<'a>(
266        &'a self,
267        game_id: GameId,
268        mod_id: ModId,
269        tags: &'a [&'a str],
270    ) -> AddModTags<'a> {
271        AddModTags::new(self, game_id, mod_id, tags)
272    }
273
274    /// Delete tags from a mod. [required: token]
275    pub const fn delete_mod_tags<'a>(
276        &'a self,
277        game_id: GameId,
278        mod_id: ModId,
279        tags: &'a [&'a str],
280    ) -> DeleteModTags<'a> {
281        DeleteModTags::new(self, game_id, mod_id, tags)
282    }
283}
284
285impl Client {
286    /// Get all mod events for a game sorted by latest first.
287    pub const fn get_mods_events(&self, game_id: GameId) -> GetModsEvents<'_> {
288        GetModsEvents::new(self, game_id)
289    }
290
291    /// Get all mod statistics for a game.
292    pub const fn get_mods_stats(&self, game_id: GameId) -> GetModsStats<'_> {
293        GetModsStats::new(self, game_id)
294    }
295
296    /// Get the event log for a mod, showing changes made sorted by latest first.
297    pub const fn get_mod_events(&self, game_id: GameId, mod_id: ModId) -> GetModEvents<'_> {
298        GetModEvents::new(self, game_id, mod_id)
299    }
300
301    /// Get the statistics for a mod.
302    pub const fn get_mod_stats(&self, game_id: GameId, mod_id: ModId) -> GetModStats<'_> {
303        GetModStats::new(self, game_id, mod_id)
304    }
305}
306
307impl Client {
308    /// Get all metadata key value pairs.
309    pub const fn get_mod_metadata(&self, game_id: GameId, mod_id: ModId) -> GetModMetadata<'_> {
310        GetModMetadata::new(self, game_id, mod_id)
311    }
312
313    /// Add metadata for a mod as key value pairs. [required: token]
314    pub const fn add_mod_metadata(
315        &self,
316        game_id: GameId,
317        mod_id: ModId,
318        metadata: MetadataMap,
319    ) -> AddModMetadata<'_> {
320        AddModMetadata::new(self, game_id, mod_id, metadata)
321    }
322
323    /// Delete metadata key value pairs for a mod. [required: token]
324    pub const fn delete_mod_metadata(
325        &self,
326        game_id: GameId,
327        mod_id: ModId,
328        metadata: MetadataMap,
329    ) -> DeleteModMetadata<'_> {
330        DeleteModMetadata::new(self, game_id, mod_id, metadata)
331    }
332}
333
334impl Client {
335    /// Get all dependencies a mod has selected.
336    pub const fn get_mod_dependencies(
337        &self,
338        game_id: GameId,
339        mod_id: ModId,
340    ) -> GetModDependencies<'_> {
341        GetModDependencies::new(self, game_id, mod_id)
342    }
343
344    /// Add mod dependencies required by a mod. [required: token]
345    pub const fn add_mod_dependencies<'a>(
346        &'a self,
347        game_id: GameId,
348        mod_id: ModId,
349        deps: &'a [ModId],
350    ) -> AddModDependencies<'a> {
351        AddModDependencies::new(self, game_id, mod_id, deps)
352    }
353
354    /// Delete mod dependencies a mod requires. [required: token]
355    pub const fn delete_mod_dependencies<'a>(
356        &'a self,
357        game_id: GameId,
358        mod_id: ModId,
359        deps: &'a [ModId],
360    ) -> DeleteModDependencies<'a> {
361        DeleteModDependencies::new(self, game_id, mod_id, deps)
362    }
363}
364
365impl Client {
366    /// Get all comments posted on a mod's profile.
367    pub const fn get_mod_comments(&self, game_id: GameId, mod_id: ModId) -> GetModComments<'_> {
368        GetModComments::new(self, game_id, mod_id)
369    }
370
371    /// Get a comment posted on a mod's profile.
372    pub const fn get_mod_comment(
373        &self,
374        game_id: GameId,
375        mod_id: ModId,
376        comment_id: CommentId,
377    ) -> GetModComment<'_> {
378        GetModComment::new(self, game_id, mod_id, comment_id)
379    }
380
381    /// Add a comment on a mod's profile. [required: token]
382    pub const fn add_mod_comment<'a>(
383        &'a self,
384        game_id: GameId,
385        mod_id: ModId,
386        content: &'a str,
387    ) -> AddModComment<'a> {
388        AddModComment::new(self, game_id, mod_id, content)
389    }
390
391    /// Edit a comment on a mod's profile. [required: token]
392    pub const fn edit_mod_comment<'a>(
393        &'a self,
394        game_id: GameId,
395        mod_id: ModId,
396        comment_id: CommentId,
397        content: &'a str,
398    ) -> EditModComment<'a> {
399        EditModComment::new(self, game_id, mod_id, comment_id, content)
400    }
401
402    /// Delete a comment from a mod's profile. [required: token]
403    pub const fn delete_mod_comment(
404        &self,
405        game_id: GameId,
406        mod_id: ModId,
407        comment_id: CommentId,
408    ) -> DeleteModComment<'_> {
409        DeleteModComment::new(self, game_id, mod_id, comment_id)
410    }
411
412    /// Update the karma rating for a comment. [required: token]
413    pub const fn update_mod_comment_karma(
414        &self,
415        game_id: GameId,
416        mod_id: ModId,
417        comment_id: CommentId,
418    ) -> UpdateModCommentKarma<'_> {
419        UpdateModCommentKarma::new(self, game_id, mod_id, comment_id)
420    }
421}
422
423impl Client {
424    /// Get all files from a mod.
425    pub const fn get_files(&self, game_id: GameId, mod_id: ModId) -> GetFiles<'_> {
426        GetFiles::new(self, game_id, mod_id)
427    }
428
429    /// Get a file from a mod.
430    pub const fn get_file(&self, game_id: GameId, mod_id: ModId, file_id: FileId) -> GetFile<'_> {
431        GetFile::new(self, game_id, mod_id, file_id)
432    }
433
434    /// Add file to a mod. [required: token]
435    pub const fn add_file(&self, game_id: GameId, mod_id: ModId) -> AddFile<'_> {
436        AddFile::new(self, game_id, mod_id)
437    }
438
439    /// Edit the details of a published file. [required: token]
440    pub const fn edit_file(&self, game_id: GameId, mod_id: ModId, file_id: FileId) -> EditFile<'_> {
441        EditFile::new(self, game_id, mod_id, file_id)
442    }
443
444    /// Delete a mod file. [required: token]
445    pub const fn delete_file(
446        &self,
447        game_id: GameId,
448        mod_id: ModId,
449        file_id: FileId,
450    ) -> DeleteFile<'_> {
451        DeleteFile::new(self, game_id, mod_id, file_id)
452    }
453
454    /// Manage the platform status of a particular mod file. [required: token]
455    pub const fn manage_platform_status(
456        &self,
457        game_id: GameId,
458        mod_id: ModId,
459        file_id: FileId,
460    ) -> ManagePlatformStatus<'_> {
461        ManagePlatformStatus::new(self, game_id, mod_id, file_id)
462    }
463}
464
465impl Client {
466    /// Get all upload sessions. [required: token]
467    pub const fn get_multipart_upload_sessions(
468        &self,
469        game_id: GameId,
470        mod_id: ModId,
471    ) -> GetMultipartUploadSessions<'_> {
472        GetMultipartUploadSessions::new(self, game_id, mod_id)
473    }
474
475    /// Create a new multipart upload session. [required: token]
476    pub const fn create_multipart_upload_session<'a>(
477        &'a self,
478        game_id: GameId,
479        mod_id: ModId,
480        filename: &'a str,
481    ) -> CreateMultipartUploadSession<'a> {
482        CreateMultipartUploadSession::new(self, game_id, mod_id, filename)
483    }
484
485    /// Get the upload parts of the session. [required: token]
486    pub const fn get_multipart_upload_parts(
487        &self,
488        game_id: GameId,
489        mod_id: ModId,
490        upload_id: UploadId,
491    ) -> GetMultipartUploadParts<'_> {
492        GetMultipartUploadParts::new(self, game_id, mod_id, upload_id)
493    }
494
495    /// Add a new part to an existing upload session. [required: token]
496    pub const fn add_multipart_upload_part<S>(
497        &self,
498        game_id: GameId,
499        mod_id: ModId,
500        upload_id: UploadId,
501        range: ContentRange,
502        stream: S,
503    ) -> AddMultipartUploadPart<'_, S>
504    where
505        S: TryStream + Send + 'static,
506        S::Ok: Into<Bytes>,
507        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
508    {
509        AddMultipartUploadPart::new(self, game_id, mod_id, upload_id, range, stream)
510    }
511
512    /// Complete an active upload session after uploading all parts with
513    /// [`Client::add_multipart_upload_part`]. [required: token]
514    pub const fn complete_multipart_upload_session(
515        &self,
516        game_id: GameId,
517        mod_id: ModId,
518        upload_id: UploadId,
519    ) -> CompleteMultipartUploadSession<'_> {
520        CompleteMultipartUploadSession::new(self, game_id, mod_id, upload_id)
521    }
522
523    /// Terminate an active upload session. [required: token]
524    pub const fn delete_multipart_upload_session(
525        &self,
526        game_id: GameId,
527        mod_id: ModId,
528        upload_id: UploadId,
529    ) -> DeleteMultipartUploadSession<'_> {
530        DeleteMultipartUploadSession::new(self, game_id, mod_id, upload_id)
531    }
532
533    /// Finalize the upload with file details. [required: token]
534    ///
535    /// # Example
536    ///
537    /// ```no_run
538    /// # use modio::types::files::multipart::{UploadId, UploadSession};
539    /// #
540    /// # #[tokio::main]
541    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
542    /// #     let client = modio::Client::builder("key".to_owned()).build()?;
543    /// #     let session: UploadSession = unimplemented!();
544    /// use modio::types::files::File;
545    /// use modio::types::id::Id;
546    ///
547    /// let game_id = Id::new(51);
548    /// let mod_id = Id::new(1041);
549    /// let UploadSession { id: upload_id, .. } = session;
550    ///
551    /// let file: File = client
552    ///     .add_multipart_upload_file(game_id, mod_id, upload_id)
553    ///     .version("1.0")
554    ///     .active(true)
555    ///     .await?
556    ///     .data()
557    ///     .await?;
558    /// #     Ok(())
559    /// # }
560    /// ```
561    pub const fn add_multipart_upload_file(
562        &self,
563        game_id: GameId,
564        mod_id: ModId,
565        upload_id: UploadId,
566    ) -> AddMultipartUploadFile<'_> {
567        AddMultipartUploadFile::new(self, game_id, mod_id, upload_id)
568    }
569}
570
571impl Client {
572    /// Get the authenticated user details. [required: token]
573    pub const fn get_authenticated_user(&self) -> GetAuthenticatedUser<'_> {
574        GetAuthenticatedUser::new(self)
575    }
576
577    /// Get all games the authenticated user added or is a team member of. [required: token]
578    pub const fn get_user_games(&self) -> GetUserGames<'_> {
579        GetUserGames::new(self)
580    }
581
582    /// Get all mods the authenticated user added or is a team member of. [required: token]
583    pub const fn get_user_mods(&self) -> GetUserMods<'_> {
584        GetUserMods::new(self)
585    }
586
587    /// Get all mod files the authenticated user uploaded. [required: token]
588    pub const fn get_user_files(&self) -> GetUserFiles<'_> {
589        GetUserFiles::new(self)
590    }
591
592    /// Get all mod ratings the authenticated user submitted. [required: token]
593    pub const fn get_user_ratings(&self) -> GetUserRatings<'_> {
594        GetUserRatings::new(self)
595    }
596
597    /// Get all mods the authenticated user is subscribed to. [required: token]
598    pub const fn get_user_subscriptions(&self) -> GetUserSubscriptions<'_> {
599        GetUserSubscriptions::new(self)
600    }
601
602    /// Get events that have been fired specific to the user. [required: token]
603    pub const fn get_user_events(&self) -> GetUserEvents<'_> {
604        GetUserEvents::new(self)
605    }
606}
607
608impl Client {
609    /// Get all user muted by the authenticated user. [required: token]
610    pub const fn get_muted_users(&self) -> GetMutedUsers<'_> {
611        GetMutedUsers::new(self)
612    }
613
614    /// Mute a user. [required: token]
615    pub const fn mute_user(&self, user_id: UserId) -> MuteUser<'_> {
616        MuteUser::new(self, user_id)
617    }
618
619    /// Unmute a previously muted user. [required: token]
620    pub const fn unmute_user(&self, user_id: UserId) -> UnmuteUser<'_> {
621        UnmuteUser::new(self, user_id)
622    }
623}
624
625impl Client {
626    /// Report a resource (game, guide, mod or user) on mod.io.
627    pub fn report<'a>(
628        &'a self,
629        resource: &'a str,
630        id: ResourceId,
631        kind: u8,
632        summary: &'a str,
633    ) -> SubmitReport<'a> {
634        SubmitReport::new(self, resource, id, kind, summary)
635    }
636}