forked from CrustyJew/RedditSharp-DEPRECATED-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPost.cs
More file actions
316 lines (275 loc) · 10.6 KB
/
Post.cs
File metadata and controls
316 lines (275 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Authentication;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RedditSharp.Extensions;
using System.Net;
using System.Reactive.Linq;
using System.Threading;
namespace RedditSharp.Things
{
/// <summary>
/// A post.
/// </summary>
public class Post : VotableThing
{
private const string CommentUrl = "/api/comment";
private const string GetCommentsUrl = "/comments/{0}.json";
private const string EditUserTextUrl = "/api/editusertext";
private const string HideUrl = "/api/hide";
private const string UnhideUrl = "/api/unhide";
private string SetFlairUrl => $"/r/{SubredditName}/api/flair";
private const string MarkNSFWUrl = "/api/marknsfw";
private const string UnmarkNSFWUrl = "/api/unmarknsfw";
private const string ContestModeUrl = "/api/set_contest_mode";
private const string StickyModeUrl = "/api/set_subreddit_sticky";
#pragma warning disable 1591
public Post(IWebAgent agent, JToken json) : base(agent, json)
{
}
#pragma warning restore 1591
/// <summary>
/// Author of this post.
/// </summary>
[JsonProperty("author")]
public new string AuthorName { get; private set; }
/// <summary>
/// Domain of this post.
/// </summary>
[JsonProperty("domain")]
public string Domain { get; private set; }
/// <summary>
/// Returns true if this is a self post.
/// </summary>
[JsonProperty("is_self")]
public bool IsSelfPost { get; private set; }
/// <summary>
/// Css class of the link flair.
/// </summary>
[JsonProperty("link_flair_css_class")]
public string LinkFlairCssClass { get; private set; }
/// <summary>
/// Text of the link flair.
/// </summary>
[JsonProperty("link_flair_text")]
public string LinkFlairText { get; private set; }
/// <summary>
/// Number of comments on this post.
/// </summary>
[JsonProperty("num_comments")]
public int CommentCount { get; private set; }
/// <summary>
/// Returns true if this post is marked not safe for work.
/// </summary>
[JsonProperty("over_18")]
public bool NSFW { get; private set; }
/// <summary>
/// Post permalink.
/// </summary>
[JsonProperty("permalink")]
[JsonConverter(typeof(UrlParser))]
public Uri Permalink { get; private set; }
/// <summary>
/// Post self text markdown.
/// </summary>
[JsonProperty("selftext")]
public string SelfText { get; private set; }
/// <summary>
/// Post self text html.
/// </summary>
[JsonProperty("selftext_html")]
public string SelfTextHtml { get; private set; }
/// <summary>
/// Uri to the thumbnail image of this post.
/// </summary>
[JsonProperty("thumbnail")]
[JsonConverter(typeof(UrlParser))]
public Uri Thumbnail { get; private set; }
/// <summary>
/// Post title.
/// </summary>
[JsonProperty("title")]
public string Title { get; private set; }
/// <summary>
/// Parent subreddit name.
/// </summary>
[JsonProperty("subreddit")]
public string SubredditName { get; private set; }
/// <summary>
/// Prefix for fullname. Includes trailing underscore
/// </summary>
public static string KindPrefix { get { return "t3_"; } }
/// <summary>
/// Post uri.
/// </summary>
[JsonProperty("url")]
[JsonConverter(typeof(UrlParser))]
public Uri Url { get; private set; }
/// <summary>
/// Returns the parent <see cref="Subreddit"/> for this post
/// </summary>
/// <returns></returns>
public Task<Subreddit> GetSubredditAsync()
{
return Subreddit.GetByNameAsync(WebAgent, SubredditName);
}
/// <summary>
/// Comment on this post.
/// </summary>
/// <param name="message">Markdown text.</param>
/// <returns></returns>
public async Task<Comment> CommentAsync(string message)
{
var json = await WebAgent.Post(CommentUrl, new
{
text = message,
thing_id = FullName,
api_type = "json"
}).ConfigureAwait(false);
if (json["json"]["ratelimit"] != null)
throw new RateLimitException(TimeSpan.FromSeconds(json["json"]["ratelimit"].ValueOrDefault<double>()));
return new Comment(WebAgent, json["json"]["data"]["things"][0], this);
}
private async Task<JToken> SimpleActionToggleAsync(string endpoint, bool value, bool requiresModAction = false)
{
return await WebAgent.Post(endpoint, new
{
id = FullName,
state = value
}).ConfigureAwait(false);
}
/// <summary>
/// Hide this post.
/// </summary>
public Task HideAsync() => SimpleActionAsync(HideUrl);
/// <summary>
/// Unhide this post.
/// </summary>
public Task UnhideAsync() => SimpleActionAsync(UnhideUrl);
/// <summary>
/// Mark this post not safe for work.
/// </summary>
public Task MarkNSFWAsync() => SimpleActionAsync(MarkNSFWUrl);
/// <summary>
/// Mark this post as safe for work.
/// </summary>
public Task UnmarkNSFWAsync() => SimpleActionAsync(UnmarkNSFWUrl);
/// <summary>
/// Set contest mode state. Logged in user must be a moderator of parent subreddit.
/// </summary>
/// <param name="state"></param>
public Task ContestModeAsync(bool state) => SimpleActionAsync(ContestModeUrl);
/// <summary>
/// Set sticky state. Logged in user must be a moderator of parent subreddit.
/// </summary>
/// <param name="state"></param>
public Task StickyModeAsync(bool state) => SimpleActionToggleAsync(StickyModeUrl, state, true);
/// <summary>
/// Replaces the text in this post with the input text.
/// </summary>
/// <param name="newText">The text to replace the post's contents</param>
public async Task EditTextAsync(string newText)
{
if (!IsSelfPost)
throw new Exception("Submission to edit is not a self-post.");
var json = await WebAgent.Post(EditUserTextUrl, new
{
api_type = "json",
text = newText,
thing_id = FullName
}).ConfigureAwait(false);
if (json["json"].ToString().Contains("\"errors\": []"))
SelfText = newText;
else
throw new Exception("Error editing text.");
}
/// <summary>
/// Updates data retrieved for this post.
/// </summary>
public async Task UpdateAsync() => Helpers.PopulateObject(GetJsonData(await Helpers.GetTokenAsync(WebAgent,Url)), this);
/// <summary>
/// Sets your flair
/// </summary>
/// <param name="flairText">Text to set your flair</param>
/// <param name="flairClass">class of the flair</param>
public async Task SetFlairAsync(string flairText, string flairClass)
{
//TODO Unit test
await WebAgent.Post(SetFlairUrl, new
{
api_type = "json",
css_class = flairClass,
link = FullName,
text = flairText
}).ConfigureAwait(false);
LinkFlairText = flairText;
}
/// <summary>
/// Get a <see cref="List{T}"/> of comments.
/// </summary>
/// <param name="limit">Maximum number of comments to return</param>
/// <returns></returns>
public async Task<List<Comment>> GetCommentsAsync(int limit = 0)
{
var url = string.Format(GetCommentsUrl, Id);
if (limit > 0)
{
var query = "limit=" + limit;
url = string.Format("{0}?{1}", url, query);
}
var json = await WebAgent.Get(url).ConfigureAwait(false);
var postJson = json.Last()["data"]["children"];
var comments = new List<Comment>();
foreach (var comment in postJson)
{
Comment newComment = new Comment(WebAgent, comment, this);
if (newComment.Kind != "more")
comments.Add(newComment);
}
return comments;
}
/// <summary>
/// Returns a <see cref="List{T}"/> of <see cref="Thing"/> that contains <see cref="Comment"/> and <see cref="More"/>
/// </summary>
/// <param name="limit">Maximum number of comments to return. Returned list may be larger than this number though due to <see cref="More"/></param>
/// <returns></returns>
public async Task<List<Thing>> GetCommentsWithMoresAsync(int limit = 0)
{
var url = string.Format(GetCommentsUrl, Id);
if (limit > 0)
{
var query = "limit=" + limit;
url = string.Format("{0}?{1}", url, query);
}
var json = await WebAgent.Get(url).ConfigureAwait(false);
var postJson = json.Last()["data"]["children"];
var things = new List<Thing>();
foreach (var comment in postJson)
{
Comment newComment = new Comment(WebAgent, comment, this);
if (newComment.Kind != "more")
{
things.Add(newComment);
}
else
{
things.Add(new More(WebAgent, comment));
}
}
return things;
}
/// <summary>
/// Returns an <see cref="IAsyncEnumerable{T}"/> of <see cref="Comment"/> containing all comments in a post.
/// This will cause multiple web requests on larger comment sections.
/// </summary>
/// <param name="limitPerRequest">Maximum number of comments to retrieve at a time. 0 for Reddit maximum</param>
/// <returns></returns>
public IAsyncEnumerable<Comment> EnumerateCommentTreeAsync(int limitPerRequest = 0)
{
return new CommentsEnumarable(WebAgent, this, limitPerRequest);
}
}
}