1use serde::ser::{Serialize, SerializeMap, Serializer};
4use serde_derive::Serialize;
5
6use crate::prelude::*;
7use crate::types::id::{CommentId, GameId, ModId};
8pub use crate::types::mods::Comment;
9
10#[derive(Clone)]
12pub struct Comments {
13 modio: Modio,
14 game: GameId,
15 mod_id: ModId,
16}
17
18impl Comments {
19 pub(crate) fn new(modio: Modio, game: GameId, mod_id: ModId) -> Self {
20 Self {
21 modio,
22 game,
23 mod_id,
24 }
25 }
26
27 pub fn search(&self, filter: Filter) -> Query<Comment> {
31 let route = Route::GetModComments {
32 game_id: self.game,
33 mod_id: self.mod_id,
34 };
35 Query::new(self.modio.clone(), route, filter)
36 }
37
38 pub async fn get(self, id: CommentId) -> Result<Comment> {
40 let route = Route::GetModComment {
41 game_id: self.game,
42 mod_id: self.mod_id,
43 comment_id: id,
44 };
45 self.modio.request(route).send().await
46 }
47
48 pub async fn add<S>(self, content: S, reply_id: Option<CommentId>) -> Result<Comment>
50 where
51 S: Into<String>,
52 {
53 let route = Route::AddModComment {
54 game_id: self.game,
55 mod_id: self.mod_id,
56 };
57 let content = content.into();
58 let data = CommentOptions { content, reply_id };
59 self.modio.request(route).form(&data).send().await
60 }
61
62 pub async fn edit<S>(self, id: CommentId, content: S) -> Result<Comment>
64 where
65 S: Into<String>,
66 {
67 let route = Route::EditModComment {
68 game_id: self.game,
69 mod_id: self.mod_id,
70 comment_id: id,
71 };
72 let data = CommentOptions {
73 content: content.into(),
74 reply_id: None,
75 };
76 self.modio.request(route).form(&data).send().await
77 }
78
79 pub async fn delete(self, id: CommentId) -> Result<()> {
81 let route = Route::DeleteModComment {
82 game_id: self.game,
83 mod_id: self.mod_id,
84 comment_id: id,
85 };
86 self.modio.request(route).send().await
87 }
88
89 pub async fn karma(self, id: CommentId, karma: Karma) -> Result<Editing<Comment>> {
91 let route = Route::AddModCommentKarma {
92 game_id: self.game,
93 mod_id: self.mod_id,
94 comment_id: id,
95 };
96 self.modio
97 .request(route)
98 .form(&karma)
99 .send()
100 .await
101 .map(Editing::Entity)
102 .or_else(|e| match (e.status(), e.error_ref()) {
103 (Some(StatusCode::FORBIDDEN), Some(15059)) => Ok(Editing::NoChanges),
104 _ => Err(e),
105 })
106 }
107}
108
109#[rustfmt::skip]
141pub mod filters {
142 #[doc(inline)]
143 pub use crate::filter::prelude::Fulltext;
144 #[doc(inline)]
145 pub use crate::filter::prelude::Id;
146 #[doc(inline)]
147 pub use crate::filter::prelude::ModId;
148 #[doc(inline)]
149 pub use crate::filter::prelude::DateAdded;
150 #[doc(inline)]
151 pub use crate::filter::prelude::SubmittedBy;
152
153 filter!(ReplyId, REPLY_ID, "reply_id", Eq, NotEq, In, Cmp);
154 filter!(ThreadPosition, THREAD_POSITION, "thread_position", Eq, NotEq, In, Like);
155 filter!(Karma, KARMA, "karma", Eq, NotEq, In, Cmp);
156 filter!(Content, CONTENT, "content", Eq, NotEq, Like);
157}
158
159pub enum Karma {
160 Positive,
161 Negative,
162}
163
164impl Serialize for Karma {
165 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
166 let mut s = serializer.serialize_map(Some(1))?;
167 match self {
168 Self::Positive => s.serialize_entry("karma", &1)?,
169 Self::Negative => s.serialize_entry("karma", &-1)?,
170 }
171 s.end()
172 }
173}
174
175#[derive(Serialize)]
176struct CommentOptions {
177 content: String,
178 #[serde(skip_serializing_if = "Option::is_none")]
179 reply_id: Option<CommentId>,
180}