/BaconographyPortable/Model/Reddit/RedditService.cs
C# | 1192 lines | 995 code | 183 blank | 14 comment | 126 complexity | 04c9251ae744a8750eeb5f04111b5413 MD5 | raw file
- using BaconographyPortable.Properties;
- using BaconographyPortable.Services;
- using BaconographyPortable.ViewModel;
- using Microsoft.Practices.ServiceLocation;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Linq;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace BaconographyPortable.Model.Reddit
- {
- public class RedditService : IRedditService
- {
- protected ISettingsService _settingsService;
- protected ISimpleHttpService _simpleHttpService;
- protected IUserService _userService;
- protected INotificationService _notificationService;
- protected IBaconProvider _baconProvider;
-
- Dictionary<string, string> _linkToOpMap = new Dictionary<string, string>();
- Dictionary<string, HashSet<string>> _subredditToModMap = new Dictionary<string, HashSet<string>>();
-
- public virtual void Initialize(ISettingsService settingsService, ISimpleHttpService simpleHttpService, IUserService userService, INotificationService notificationService, IBaconProvider baconProvider)
- {
- _settingsService = settingsService;
- _simpleHttpService = simpleHttpService;
- _userService = userService;
- _notificationService = notificationService;
- _baconProvider = baconProvider;
- }
-
- public async Task<Account> GetMe()
- {
- var user = await _userService.GetUser();
- return await GetMe(user);
- }
-
- //this one is seperated out so we can use it interally on initial user login
- public async Task<Account> GetMe(User user)
- {
- bool needsRetry = false;
- try
- {
- var meString = await _simpleHttpService.SendGet(user.LoginCookie, "http://www.reddit.com/api/me.json");
- if (!string.IsNullOrWhiteSpace(meString) && meString != "{}")
- {
- var thing = JsonConvert.DeserializeObject<Thing>(meString);
- return (new TypedThing<Account>(thing)).Data;
- }
- else
- return null;
- }
- catch (WebException webException)
- {
- if (webException.Status == WebExceptionStatus.RequestCanceled)
- needsRetry = true;
- else
- {
- _notificationService.CreateErrorNotification(webException);
- return null;
- }
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return null;
- }
-
- if (needsRetry)
- {
- return await GetMe();
- }
- else
- return null;
- }
-
- public async Task<User> Login(string username, string password)
- {
- var loginUri = "https://ssl.reddit.com/api/login";
- var postContent = new Dictionary<string, string>
- {
- { "api_type", "json" },
- { "user", username },
- { "passwd", password }
- };
-
- var loginResult = await _simpleHttpService.SendPostForCookies(postContent, loginUri);
-
- var jsonResult = loginResult.Item1;
- var loginResultThing = JsonConvert.DeserializeObject<LoginJsonThing>(jsonResult);
- if (loginResultThing == null || loginResultThing.Json == null ||
- (loginResultThing.Json.Errors != null && loginResultThing.Json.Errors.Length != 0))
- {
- _notificationService.CreateNotification(string.Format("Failed to login as User:{0}", username));
- return null; //errors in the login process
- }
- else
- {
- var loginCookie = loginResult.Item2["reddit_session"];
- var user = new User { Authenticated = true, LoginCookie = loginCookie, Username = username, NeedsCaptcha = false };
-
- user.Me = await GetMe(user);
- return user;
- }
-
- }
-
- public async Task<Listing> Search(string query, int? limit, bool reddits, string restrictedToSubreddit)
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 100;
- var guardedLimit = Math.Min(maxLimit, limit ?? maxLimit);
-
- string targetUri = null;
-
- if (reddits)
- {
- targetUri = string.Format("http://www.reddit.com/subreddits/search.json?limit={0}&q={1}", guardedLimit, query);
- }
- else if (string.IsNullOrWhiteSpace(restrictedToSubreddit))
- {
- targetUri = string.Format("http://www.reddit.com/search.json?limit={0}&q={1}", guardedLimit, query);
- }
- else
- {
- targetUri = string.Format("http://www.reddit.com/r/{2}/search.json?limit={0}&q={1}&restrict_sr=on", guardedLimit, query, restrictedToSubreddit);
- }
-
- var comments = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- var newListing = JsonConvert.DeserializeObject<Listing>(comments);
- return MaybeFilterForNSFW(newListing);
- }
-
- public async Task<Thing> GetThingById(string id)
- {
- var targetUri = string.Format("http://www.reddit.com/by_id/{0}.json", id);
-
- try
- {
- var thingStr = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- if(thingStr.StartsWith("{\"kind\": \"Listing\""))
- {
- var listing = JsonConvert.DeserializeObject<Listing>(thingStr);
- return listing.Data.Children.First();
- }
- else
- return JsonConvert.DeserializeObject<Thing>(thingStr);
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return null;
- }
- }
-
- public async Task<HashSet<string>> GetSubscribedSubreddits()
- {
- var hashifyListing = new Func<Thing, string>((thing) =>
- {
- if (thing.Data is Subreddit)
- {
- return ((Subreddit)thing.Data).Name;
- }
- else
- return null;
- });
-
- return new HashSet<string>((await GetSubscribedSubredditListing())
- .Data.Children.Select(hashifyListing)
- .Where(str => str != null));
-
- }
-
- public virtual async Task<Listing> GetSubreddits(int? limit)
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 100;
- var guardedLimit = Math.Min(maxLimit, limit ?? maxLimit);
-
- var targetUri = string.Format("http://www.reddit.com/reddits/.json?limit={0}", guardedLimit);
-
- try
- {
- var comments = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- var newListing = JsonConvert.DeserializeObject<Listing>(comments);
-
- return MaybeFilterForNSFW(newListing);
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- }
-
- public async Task<TypedThing<Subreddit>> GetSubreddit(string name)
- {
- //no info for the front page
- if (name == "/")
- return new TypedThing<Subreddit>(new Thing { Kind = "t5", Data = new Subreddit { Headertitle = name } });
- else if (name == "all")
- return new TypedThing<Subreddit>(new Thing { Kind = "t5", Data = new Subreddit { Headertitle = "all", Url = "/r/all", Name = "all", DisplayName="all", Title="all", Id="t5_fakeid" } });
-
- string targetUri;
- if (!name.Contains("/m/"))
- {
- targetUri = string.Format("http://www.reddit.com/r/{0}/about.json", name);
- try
- {
- var comments = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- //error page
- if (comments.ToLower().StartsWith("<!doctype html>"))
- {
- return new TypedThing<Subreddit>(new Thing { Kind = "t5", Data = new Subreddit { Headertitle = name, Title = name, Url = string.Format("r/{0}", name), Created = DateTime.Now, CreatedUTC = DateTime.UtcNow, DisplayName = name, Description = "there doesnt seem to be anything here", Name = name, Over18 = false, PublicDescription = "there doesnt seem to be anything here", Subscribers = 0 } });
- }
- else
- {
- return new TypedThing<Subreddit>(JsonConvert.DeserializeObject<Thing>(comments));
- }
- }
- catch (Exception ex)
- {
- //_notificationService.CreateErrorNotification(ex);
- return new TypedThing<Subreddit>(new Thing { Kind = "t5", Data = new Subreddit { Headertitle = name, Title = name, Url = string.Format("r/{0}", name), Created = DateTime.Now, CreatedUTC = DateTime.UtcNow, DisplayName = name, Description = "there doesnt seem to be anything here", Name = name, Over18 = false, PublicDescription = "there doesnt seem to be anything here", Subscribers = 0 } });
- }
- }
- else
- {
- var currentUser = await _userService.GetUser();
- if (name.StartsWith("/"))
- name = name.TrimStart('/');
-
- if (name.StartsWith("me/"))
- {
- name = name.Replace("me/", "user/" + currentUser.Username + "/");
- }
-
- targetUri = string.Format("http://www.reddit.com/api/multi/{0}.json", name);
- try
- {
- var comments = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- //error page
- if (comments.ToLower().StartsWith("<!doctype html>"))
- {
- return new TypedThing<Subreddit>(new Thing { Kind = "t5", Data = new Subreddit { Headertitle = name, Title = name, Url = string.Format("r/{0}", name), Created = DateTime.Now, CreatedUTC = DateTime.UtcNow, DisplayName = name, Description = "there doesnt seem to be anything here", Name = name, Over18 = false, PublicDescription = "there doesnt seem to be anything here", Subscribers = 0 } });
- }
- else
- {
-
- var labeledMulti = new TypedThing<LabeledMulti>(JsonConvert.DeserializeObject<Thing>(comments));
- var multiPath = labeledMulti.Data.Path;
-
- if(!string.IsNullOrWhiteSpace(currentUser.Username))
- multiPath = multiPath.Replace("/user/" + currentUser.Username, "/me");
-
- return new TypedThing<Subreddit>(new Thing { Kind = "t5", Data = new Subreddit { DisplayName = labeledMulti.Data.Name, Title = labeledMulti.Data.Name, Url = multiPath, Headertitle = labeledMulti.Data.Name, Over18 = false } });
- }
- }
- catch (Exception ex)
- {
- //_notificationService.CreateErrorNotification(ex);
- return new TypedThing<Subreddit>(new Thing { Kind = "t5", Data = new Subreddit { Headertitle = name, Title = name, Url = string.Format("r/{0}", name), Created = DateTime.Now, CreatedUTC = DateTime.UtcNow, DisplayName = name, Description = "there doesnt seem to be anything here", Name = name, Over18 = false, PublicDescription = "there doesnt seem to be anything here", Subscribers = 0 } });
- }
- }
-
-
- }
-
- public async Task<Listing> GetPostsByUser(string username, int? limit)
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 100;
- var guardedLimit = Math.Min(maxLimit, limit ?? maxLimit);
-
- var targetUri = string.Format("http://www.reddit.com/user/{0}/.json?limit={1}", username, guardedLimit);
-
- try
- {
- var comments = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- var newListing = JsonConvert.DeserializeObject<Listing>(comments);
-
- return MaybeFilterForNSFW(newListing);
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- }
-
- public async Task<Listing> GetPostsBySubreddit(string subreddit, int? limit)
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 100;
- var guardedLimit = Math.Min(maxLimit, limit ?? maxLimit);
-
- if (subreddit == null)
- {
- //this isnt the front page, that would be "/"
- //return empty since there isnt anything here
- _notificationService.CreateNotification("There doesnt seem to be anything here");
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
-
- var targetUri = string.Format("http://www.reddit.com{0}.json?limit={1}", subreddit, guardedLimit);
- try
- {
- var links = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- var newListing = JsonConvert.DeserializeObject<Listing>(links);
- return MaybeInjectAdvertisements(MaybeFilterForNSFW(newListing));
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- }
-
- public async Task<Listing> GetMoreOnListing(IEnumerable<string> childrenIds, string contentId, string subreddit)
- {
- var targetUri = "http://www.reddit.com/api/morechildren.json";
-
- if (childrenIds.Count() == 0)
- return new Listing
- {
- Kind = "Listing",
- Data = new ListingData()
- };
-
- var arguments = new Dictionary<string, string>
- {
- {"children", string.Join(",", childrenIds) },
- {"link_id", contentId },
- {"pv_hex", ""},
- {"api_type", "json" }
- };
-
- if (subreddit != null)
- {
- arguments.Add("r", subreddit);
- }
-
- try
- {
- var result = await _simpleHttpService.SendPost(await GetCurrentLoginCookie(), arguments, targetUri);
- var newListing = new Listing
- {
- Kind = "Listing",
- Data = new ListingData { Children = JsonConvert.DeserializeObject<JsonThing>(result).Json.Data.Things }
- };
-
- return MaybeInjectAdvertisements(MaybeFilterForNSFW(newListing));
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
-
- return new Listing
- {
- Kind = "Listing",
- Data = new ListingData { Children = new List<Thing>() }
- };
- }
- }
-
- Tuple<DateTime, string, string, Listing> _lastCommentsOnPostRequest;
-
- public async Task<Thing> GetLinkByUrl(string url)
- {
- try
- {
- var originalUrl = url;
- if (originalUrl.Contains(".json"))
- {
- }
- else if (originalUrl.Contains("?"))
- {
- var queryPos = url.IndexOf("?");
- url = string.Format("{0}.json{1}", originalUrl.Remove(queryPos), originalUrl.Substring(queryPos));
- }
- else
- {
- url = originalUrl + ".json";
- }
-
- Listing listing = null;
- var comments = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), url);
- if (comments.StartsWith("["))
- {
- var listings = JsonConvert.DeserializeObject<Listing[]>(comments);
- listing = new Listing { Data = new ListingData { Children = new List<Thing>() } };
- foreach (var combinableListing in listings)
- {
- listing.Data.Children.AddRange(combinableListing.Data.Children);
- listing.Kind = combinableListing.Kind;
- listing.Data.After = combinableListing.Data.After;
- listing.Data.Before = combinableListing.Data.Before;
- }
- }
- else
- listing = JsonConvert.DeserializeObject<Listing>(comments);
-
- var requestedLinkInfo = listing.Data.Children.FirstOrDefault(thing => thing.Data is Link);
- if (requestedLinkInfo != null)
- {
-
- var result = MaybeFilterForNSFW(listing);
-
- ((Link)requestedLinkInfo.Data).Permalink = originalUrl;
- _lastCommentsOnPostRequest = Tuple.Create(DateTime.Now, ((Link)requestedLinkInfo.Data).Subreddit, ((Link)requestedLinkInfo.Data).Permalink, result);
- return requestedLinkInfo;
- }
- else
- return null;
- }
- catch(Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return null;
- }
- }
-
- public async Task<Listing> GetCommentsOnPost(string subreddit, string permalink, int? limit)
- {
- //comments are pretty slow to get, so cache it to within 5 minutes for the most recent request
- if (_lastCommentsOnPostRequest != null &&
- (DateTime.Now - _lastCommentsOnPostRequest.Item1).TotalMinutes < 5 &&
- _lastCommentsOnPostRequest.Item2 == subreddit &&
- _lastCommentsOnPostRequest.Item3 == permalink)
- return _lastCommentsOnPostRequest.Item4;
-
- try
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 500;
- var guardedLimit = Math.Min(maxLimit, limit ?? maxLimit);
-
- string targetUri = null;
-
- if (permalink.Contains("reddit.com"))
- {
- permalink = permalink.Substring(permalink.IndexOf("reddit.com") + "reddit.com".Length);
- }
-
- if (permalink.Contains(".json?"))
- {
- targetUri = "http://www.reddit.com" + permalink;
- }
- else if (permalink.Contains("?"))
- {
- var queryPos = permalink.IndexOf("?");
- targetUri = string.Format("http://www.reddit.com{0}.json{1}", permalink.Remove(queryPos), permalink.Substring(queryPos));
- }
- else
- {
- targetUri = limit == -1 ?
- string.Format("http://www.reddit.com{0}.json", permalink) :
- string.Format("http://www.reddit.com{0}.json?limit={1}", permalink, limit);
- }
-
- Listing listing = null;
- var comments = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- if (comments.StartsWith("["))
- {
- var listings = JsonConvert.DeserializeObject<Listing[]>(comments);
- listing = new Listing { Data = new ListingData { Children = new List<Thing>() } };
- foreach (var combinableListing in listings)
- {
- listing.Data.Children.AddRange(combinableListing.Data.Children);
- listing.Kind = combinableListing.Kind;
- listing.Data.After = combinableListing.Data.After;
- listing.Data.Before = combinableListing.Data.Before;
- }
- }
- else
- listing = JsonConvert.DeserializeObject<Listing>(comments);
-
- var result = MaybeFilterForNSFW(listing);
-
- var requestedLinkInfo = listing.Data.Children.FirstOrDefault(thing => thing.Data is Link);
- if (requestedLinkInfo != null)
- {
- if (!_linkToOpMap.ContainsKey(((Link)requestedLinkInfo.Data).Name))
- {
- _linkToOpMap.Add(((Link)requestedLinkInfo.Data).Name, ((Link)requestedLinkInfo.Data).Author);
- }
- }
-
- _lastCommentsOnPostRequest = Tuple.Create(DateTime.Now, subreddit, permalink, result);
-
- return result;
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- }
-
- public Task<Listing> GetMessages(int? limit)
- {
- return GetMail("messages", limit);
- }
-
- public void AddFlairInfo(string linkId, string opName)
- {
- if (!_linkToOpMap.ContainsKey(linkId))
- {
- _linkToOpMap.Add(linkId, opName);
- }
- }
-
- public async Task<Listing> GetAdditionalFromListing(string baseUrl, string after, int? limit)
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 500;
- var guardedLimit = Math.Min(maxLimit, limit ?? maxLimit);
-
- string targetUri = null;
- //if this base url already has arguments (like search) just append the count and the after
- if (baseUrl.Contains(".json?"))
- targetUri = string.Format("{0}&limit={1}&after={2}", baseUrl, guardedLimit, after);
- else
- targetUri = string.Format("{0}.json?limit={1}&after={2}", baseUrl, guardedLimit, after);
-
- try
- {
- var listing = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- var newListing = JsonConvert.DeserializeObject<Listing>(listing);
-
- return MaybeInjectAdvertisements(MaybeFilterForNSFW(newListing));
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- }
-
- public async Task<TypedThing<Account>> GetAccountInfo(string accountName)
- {
- var targetUri = string.Format("http://www.reddit.com/user/{0}/about.json", accountName);
-
- try
- {
- var account = await _simpleHttpService.UnAuthedGet(targetUri);
- return new TypedThing<Account>(JsonConvert.DeserializeObject<Thing>(account));
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return new TypedThing<Account>(new Thing { Kind = "t3", Data = new Account { Name = accountName } });
- }
- }
-
- private void ProcessJsonErrors(string response)
- {
- string realErrorString = "";
- try
- {
- if (response.Contains("errors"))
- {
- var jsonErrors = JsonConvert.DeserializeObject<JsonErrorsData>(response);
- if (jsonErrors.Errors != null && jsonErrors.Errors.Length > 0)
- {
- realErrorString = jsonErrors.Errors[0].ToString();
- }
- }
-
- }
- catch
- {
- }
- if (!string.IsNullOrWhiteSpace(realErrorString))
- throw new Exception(realErrorString);
- }
-
- public virtual async Task AddVote(string thingId, int direction)
- {
- var modhash = await GetCurrentModhash();
-
- var arguments = new Dictionary<string, string>
- {
- {"id", thingId},
- {"dir", direction.ToString()},
- {"uh", modhash}
- };
-
- ProcessJsonErrors(await _simpleHttpService.SendPost(await GetCurrentLoginCookie(), arguments, "http://www.reddit.com/api/vote"));
- }
-
- public virtual async Task AddSubredditSubscription(string subreddit, bool unsub)
- {
- var modhash = await GetCurrentModhash();
-
- var content = new Dictionary<string, string>
- {
- { "sr", subreddit},
- { "uh", modhash},
- { "action", unsub ? "unsub" : "sub"}
- };
-
- await _simpleHttpService.SendPost(await GetCurrentLoginCookie(), content, "http://www.reddit.com/api/subscribe");
- }
-
- public virtual Task AddSavedThing(string thingId)
- {
- return ThingAction("save", thingId);
- }
-
- public virtual Task AddReportOnThing(string thingId)
- {
- return ThingAction("report", thingId);
- }
-
- public virtual async Task AddPost(string kind, string url, string text, string subreddit, string title)
- {
- var modhash = await GetCurrentModhash();
-
- var arguments = new Dictionary<string, string>
- {
- {"api_type", "json"},
- {"kind", kind},
- {"url", url},
- {"text", text},
- {"title", title},
- {"sr", subreddit},
- {"renderstyle", "html" },
- {"uh", modhash}
- };
-
- ProcessJsonErrors(await this.SendPost(await GetCurrentLoginCookie(), arguments, "http://www.reddit.com/api/submit"));
- }
-
- public virtual async Task EditPost(string text, string name)
- {
- var modhash = await GetCurrentModhash();
-
- var arguments = new Dictionary<string, string>
- {
- {"api_type", "json"},
- {"text", text},
- {"thing_id", name},
- {"uh", modhash}
- };
-
- ProcessJsonErrors(await this.SendPost(await GetCurrentLoginCookie(), arguments, "http://www.reddit.com/api/editusertext"));
- }
-
- public async Task SubmitCaptcha(string captcha)
- {
- Captcha = captcha;
- List<PostData> data = PostQueue.ToList<PostData>();
- PostQueue.Clear();
- foreach (var post in data)
- {
- await this.SendPost(post.Cookie, post.UrlEncodedData, post.Uri, true);
- }
- }
-
- private class PostData
- {
- public string Cookie { get; set; }
- public Dictionary<string, string> UrlEncodedData { get; set; }
- public string Uri { get; set; }
- }
- private List<PostData> PostQueue = new List<PostData>();
-
- private string CaptchaIden { get; set; }
- private string Captcha { get; set; }
- private async Task<string> SendPost(string cookie, Dictionary<string, string> urlEncodedData, string uri, bool queuedMessage = false)
- {
- if (!urlEncodedData.ContainsKey("api_type"))
- urlEncodedData.Add("api_type", "json");
-
- if (!String.IsNullOrEmpty(CaptchaIden))
- {
- if (urlEncodedData.ContainsKey("iden"))
- urlEncodedData["iden"] = CaptchaIden;
- else
- urlEncodedData.Add("iden", CaptchaIden);
- }
-
- if (!String.IsNullOrEmpty(Captcha))
- {
- if (urlEncodedData.ContainsKey("captcha"))
- urlEncodedData["captcha"] = Captcha;
- else
- urlEncodedData.Add("captcha", Captcha);
- }
-
- string response = null;
-
- response = await _simpleHttpService.SendPost(cookie, urlEncodedData, uri);
-
- var jsonObject = JsonConvert.DeserializeObject(response) as JObject;
- JToken captcha = null;
- JToken errors = null;
- JObject first = null;
-
- if (jsonObject.First != null)
- first = (jsonObject.First as JProperty).Value as JObject;
-
- if (first != null)
- {
- first.TryGetValue("captcha", out captcha);
- first.TryGetValue("errors", out errors);
- if (captcha != null)
- CaptchaIden = captcha.Value<string>();
-
- if (captcha != null && errors != null)
- {
- var user = await _userService.GetUser();
- user.NeedsCaptcha = true;
-
- // If a user has told us to bug off this session, do as they say
- if (!_settingsService.PromptForCaptcha)
- return response;
-
- PostQueue.Add(new PostData { Cookie = cookie, Uri = uri, UrlEncodedData = urlEncodedData });
-
- CaptchaViewModel captchaVM = CaptchaViewModel.GetInstance(_baconProvider);
- captchaVM.ShowCaptcha(CaptchaIden);
- }
- }
-
- return response;
- }
-
- public virtual async Task ReadMessage(string id)
- {
- var modhash = await GetCurrentModhash();
-
- var arguments = new Dictionary<string, string>
- {
- {"id", id},
- {"uh", modhash}
- };
-
- ProcessJsonErrors(await this.SendPost(await GetCurrentLoginCookie(), arguments, "http://www.reddit.com/api/read_message"));
- }
-
- public virtual async Task AddMessage(string recipient, string subject, string message)
- {
- var modhash = await GetCurrentModhash();
-
- var arguments = new Dictionary<string, string>
- {
- {"id", "#compose-message"},
- {"to", recipient},
- {"text", message},
- {"subject", subject},
- {"thing-id", ""},
- {"renderstyle", "html"},
- {"uh", modhash}
- };
-
- ProcessJsonErrors(await this.SendPost(await GetCurrentLoginCookie(), arguments, "http://www.reddit.com/api/compose"));
- }
-
- public virtual async Task AddReply(string recipient, string subject, string message, string thing_id)
- {
- var modhash = await GetCurrentModhash();
-
- var arguments = new Dictionary<string, string>
- {
- {"id", "#compose-message"},
- {"to", recipient},
- {"text", message},
- {"subject", subject},
- {"thing-id", ""},
- {"renderstyle", "html"},
- {"uh", modhash}
- };
-
- ProcessJsonErrors(await this.SendPost(await GetCurrentLoginCookie(), arguments, "http://www.reddit.com/api/compose"));
- }
-
- public virtual async Task AddComment(string parentId, string content)
- {
- var modhash = await GetCurrentModhash();
-
- var arguments = new Dictionary<string, string>
- {
- {"thing_id", parentId},
- {"text", content.Replace("\r\n", "\n")},
- {"uh", modhash}
- };
-
- ProcessJsonErrors(await this.SendPost(await GetCurrentLoginCookie(), arguments, "http://www.reddit.com/api/comment"));
- }
-
- public virtual async Task EditComment(string thingId, string text)
- {
- var modhash = await GetCurrentModhash();
-
- var arguments = new Dictionary<string, string>
- {
- {"thing_id", thingId},
- {"text", text.Replace("\r\n", "\n")},
- {"uh", modhash}
- };
-
- ProcessJsonErrors(await this.SendPost(await GetCurrentLoginCookie(), arguments, "http://www.reddit.com/api/editusertext"));
- }
-
- private async Task<bool> UserIsGold()
- {
- var user = await _userService.GetUser();
- return user != null && user.Me != null && user.Me.IsGold;
- }
-
- private async Task<string> GetCurrentLoginCookie()
- {
- var currentUser = await _userService.GetUser();
- if (currentUser != null && !string.IsNullOrWhiteSpace(currentUser.LoginCookie))
- {
- return currentUser.LoginCookie;
- }
- else
- return string.Empty;
- }
-
- private async Task<string> GetCurrentModhash()
- {
- var currentUser = await _userService.GetUser();
- if (currentUser != null && !string.IsNullOrWhiteSpace(currentUser.LoginCookie) && currentUser.Me != null)
- {
- return currentUser.Me.ModHash;
- }
- else if (currentUser != null && !string.IsNullOrWhiteSpace(currentUser.LoginCookie))
- {
- currentUser.Me = await GetMe();
- return currentUser.Me.ModHash;
- }
- else
- return string.Empty;
- }
-
- private Listing MaybeFilterForNSFW(Listing source)
- {
- if (_settingsService.AllowOver18)
- {
- return source;
- }
- else
- return FilterForNSFW(source);
- }
-
- private Listing MaybeInjectAdvertisements(Listing source)
- {
- if (!_settingsService.AllowAdvertising)
- return source;
-
- int count = source.Data.Children.Count;
- for (int i = 9; i < count; i += 10)
- {
- var thing = new Thing { Data = new Advertisement(), Kind = "ad" };
- source.Data.Children.Insert(i, thing);
- }
- return source;
- }
-
- private Listing FilterForNSFW(Listing source)
- {
- source.Data.Children = source.Data.Children
- .Select(FilterForNSFW)
- .Where(thing => thing != null)
- .ToList();
-
- return source;
- }
-
- private Thing FilterForNSFW(Thing source)
- {
- if (source.Data is Link || source.Data is Subreddit)
- {
- if (((dynamic)source.Data).Over18)
- return null;
- }
-
- return source;
- }
-
-
- public AuthorFlairKind GetUsernameModifiers(string username, string linkid, string subreddit)
- {
- if (!string.IsNullOrEmpty(linkid))
- {
- string opName;
- if (_linkToOpMap.TryGetValue(linkid, out opName) && opName == username)
- {
- return AuthorFlairKind.OriginalPoster;
- }
- }
-
- if (!string.IsNullOrEmpty(subreddit))
- {
- HashSet<string> subredditMods;
- if (_subredditToModMap.TryGetValue(subreddit, out subredditMods) && subredditMods != null && subredditMods.Contains(username))
- {
- return AuthorFlairKind.Moderator;
- }
- }
-
- return AuthorFlairKind.None;
- }
-
- private async Task<Listing> GetUserMultis(Listing listing)
- {
- var targetUri = string.Format("http://www.reddit.com/api/multi/mine.json");
-
- try
- {
- var subreddits = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- if (subreddits == "[]")
- return listing;
- else
- {
- var currentUser = await _userService.GetUser();
- var userMultis = JsonConvert.DeserializeObject<Thing[]>(subreddits);
- foreach (var thing in userMultis)
- {
- var labeledMulti = new TypedThing<LabeledMulti>(thing);
- var multiPath = labeledMulti.Data.Path;
-
- multiPath = multiPath.Replace("/user/" + currentUser.Username, "/me");
-
- listing.Data.Children.Insert(0, (new Thing { Kind = "t5", Data = new Subreddit { DisplayName = labeledMulti.Data.Name, HeaderImage = "/Assets/multireddit.png", Title = labeledMulti.Data.Name, Url = multiPath, Headertitle = labeledMulti.Data.Name, Over18 = false } }));
- }
- }
- }
- //this api is most likely still in flux just silently fail if they break us down the line
- catch {}
- return listing;
- }
-
- public async Task<Listing> GetSubscribedSubredditListing()
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 100;
-
- var targetUri = string.Format("http://www.reddit.com/reddits/mine.json?limit={0}", maxLimit);
-
- try
- {
- var subreddits = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
-
- if (subreddits == "\"{}\"")
- return await GetDefaultSubreddits();
- else
- return await GetUserMultis(JsonConvert.DeserializeObject<Listing>(subreddits));
-
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- }
- //cant await in a catch block so do it after
- return await GetDefaultSubreddits();
- }
-
- public async Task<Listing> GetDefaultSubreddits()
- {
- return JsonConvert.DeserializeObject<Listing>(Resources.DefaultSubreddits1 + Resources.DefaultSubreddits2 + Resources.DefaultSubreddits3);
- }
-
-
- public async Task<bool> CheckLogin(string loginToken)
- {
- var meString = await _simpleHttpService.SendGet(loginToken, "http://www.reddit.com/api/me.json");
- return (!string.IsNullOrWhiteSpace(meString) && meString != "{}");
- }
-
- public async Task<Listing> GetSaved(int? limit)
- {
- return await GetUserInfoListing("saved", limit);
- }
-
- public async Task<Listing> GetLiked(int? limit)
- {
- return await GetUserInfoListing("liked", limit);
- }
-
- private async Task<Listing> GetUserInfoListing(string kind, int? limit)
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 100;
- var guardedLimit = Math.Min(maxLimit, limit ?? maxLimit);
-
- var targetUri = string.Format("http://www.reddit.com/user/{0}/{2}/.json?limit={1}", (await _userService.GetUser()).Username, guardedLimit, kind);
-
- try
- {
- var info = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- var newListing = JsonConvert.DeserializeObject<Listing>(info);
-
- return MaybeFilterForNSFW(newListing);
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- }
-
- public async Task<Listing> GetDisliked(int? limit)
- {
- return await GetUserInfoListing("disliked", limit);
- }
-
- public Task<Listing> GetSentMessages(int? limit)
- {
- return GetMail("sent", limit);
- }
-
- public async Task ThingAction(string action, string thingId)
- {
- var modhash = await GetCurrentModhash();
- var targetUri = "http://www.reddit.com/api/" + action;
-
- var content = new Dictionary<string, string>
- {
- { "id", thingId},
- { "uh", modhash}
- };
-
- ProcessJsonErrors(await _simpleHttpService.SendPost(await GetCurrentLoginCookie(), content, targetUri));
- }
-
- public Task UnSaveThing(string thingId)
- {
- return ThingAction("unsafe", thingId);
- }
-
- public async Task MarkVisited(IEnumerable<string> ids)
- {
- var user = await _userService.GetUser();
- if (user != null && user.Me != null && user.Me.IsGold)
- {
- var modhash = await GetCurrentModhash();
-
- var arguments = new Dictionary<string, string>
- {
- {"links", string.Join(",", ids)},
- { "uh", modhash}
- };
-
- ProcessJsonErrors(await this.SendPost(await GetCurrentLoginCookie(), arguments, "http://www.reddit.com/api/store_visits"));
- }
- }
-
-
- public async Task<Listing> GetModActions(string subreddit, int? limit)
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 100;
- var guardedLimit = Math.Min(maxLimit, limit ?? maxLimit);
-
- var targetUri = string.Format("http://www.reddit.com/r/{0}/about/log.json?limi={1}", subreddit, guardedLimit);
-
- try
- {
- var messages = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- if (messages == "\"{}\"")
- {
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- return JsonConvert.DeserializeObject<Listing>(messages);
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- }
-
- private async Task<Listing> GetMail(string kind, int? limit)
- {
- var maxLimit = (await UserIsGold()) ? 1500 : 100;
- var guardedLimit = Math.Min(maxLimit, limit ?? maxLimit);
-
- var targetUri = string.Format("http://www.reddit.com/message/{1}/.json?limit={0}", guardedLimit, kind);
-
- try
- {
- var messages = await _simpleHttpService.SendGet(await GetCurrentLoginCookie(), targetUri);
- if (messages == "\"{}\"")
- {
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- // Hacky hack mcHackerson
- messages = messages.Replace("\"kind\": \"t1\"", "\"kind\": \"t4.5\"");
- return JsonConvert.DeserializeObject<Listing>(messages);
- }
- catch (Exception ex)
- {
- _notificationService.CreateErrorNotification(ex);
- return new Listing { Kind = "Listing", Data = new ListingData { Children = new List<Thing>() } };
- }
- }
-
- public Task<Listing> GetModMail(int? limit)
- {
- return GetMail("moderator", limit);
- }
-
- public Task ApproveThing(string thingId)
- {
- return ThingAction("approve", thingId);
- }
-
- public async Task RemoveThing(string thingId, bool spam)
- {
- var modhash = await GetCurrentModhash();
- var targetUri = "http://www.reddit.com/api/remove";
-
- var content = new Dictionary<string, string>
- {
- { "id", thingId},
- { "uh", modhash},
- { "spam", spam ? "true" : "false"}
- };
-
- ProcessJsonErrors(await _simpleHttpService.SendPost(await GetCurrentLoginCookie(), content, targetUri));
- }
-
- public Task IgnoreReportsOnThing(string thingId)
- {
- return ThingAction("ignore_reports", thingId);
- }
-
- public async Task Friend(string name, string container, string note, string type)
- {
- var modhash = await GetCurrentModhash();
- var targetUri = "http://www.reddit.com/api/friend";
-
- var content = new Dictionary<string, string>
- {
- { "api_type", "json"},
- { "uh", modhash},
- { "container", container },
- { "name", name },
- { "note", note},
- { "type", type }
- };
-
- ProcessJsonErrors(await _simpleHttpService.SendPost(await GetCurrentLoginCookie(), content, targetUri));
- }
-
- public async Task Unfriend(string name, string container, string type)
- {
- var modhash = await GetCurrentModhash();
- var targetUri = "http://www.reddit.com/api/unfriend";
-
- var content = new Dictionary<string, string>
- {
- { "uh", modhash},
- { "container", container },
- { "name", name },
- { "type", type }
- };
-
- ProcessJsonErrors(await _simpleHttpService.SendPost(await GetCurrentLoginCookie(), content, targetUri));
- }
-
- public Task AddContributor(string name, string subreddit, string note)
- {
- return Friend(name, subreddit, note, "contributor");
- }
-
- public Task RemoveContributor(string subreddit, string name)
- {
- return Unfriend(name, subreddit, "contributor");
- }
-
- public Task AddModerator(string name, string subreddit, string note)
- {
- return Friend(name, subreddit, note, "moderator");
- }
-
- public Task RemoveModerator(string subreddit, string name)
- {
- return Unfriend(name, subreddit, "moderator");
- }
-
- public Task AddBan(string name, string subreddit, string note)
- {
- return Friend(name, subreddit, note, "banned");
- }
-
- public Task RemoveBan(string subreddit, string name)
- {
- return Unfriend(name, subreddit, "banned");
- }
- }
- }