Beispiel #1
0
#pragma warning restore

        /// <summary>
        /// Gets a video url from redgif
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private async Task <string> GetRedGifUrlFromWatchUrl(string url)
        {
            // Return if we have nothing.
            if (url.Equals(string.Empty))
            {
                return(string.Empty);
            }

            try
            {
                var lastSegment = new Uri(url).Segments.Last();

                // Make the call
                var result = await RedGifHelper.GetVideoInfoAsync(lastSegment);

                return(result?.DataInfo?.VideoInfo == null ? url : result.DataInfo.VideoInfo.StandardDefUrl);
            }
            catch (Exception e)
            {
                App.BaconMan.MessageMan.DebugDia("failed to get image from redgif", e);
                TelemetryManager.ReportUnexpectedEvent(this, "FailedRedGifApiCall", e);
            }

            return(string.Empty);
        }
Beispiel #2
0
        /// <summary>
        /// Fired when we should load the content.
        /// </summary>
        public void OnPrepareContent()
        {
            // Since this can be costly kick it off to a background thread so we don't do work
            // as we are animating.
            Task.Run(async() =>
            {
                // Get the video Uri
                var youTubeVideoInfo = await GetYouTubeVideoInfoAsync(_contentPanelBase.Source);
                var youtubeUrl       = GetYouTubeUrl(youTubeVideoInfo);

                // Back to the UI thread with pri
                await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
                {
                    if (string.IsNullOrWhiteSpace(youtubeUrl))
                    {
                        // If we failed fallback to the browser.
                        _contentPanelBase.FireOnFallbackToBrowser();
                        TelemetryManager.ReportUnexpectedEvent(this, "FailedToGetYoutubeVideoAfterSuccess");
                        return;
                    }

                    // Setup the video
                    _videoPlayer = new MediaElement {
                        AutoPlay = false, AreTransportControlsEnabled = true
                    };
                    _videoPlayer.CurrentStateChanged += VideoPlayerOnCurrentStateChanged;
                    _videoPlayer.Source = new Uri(youtubeUrl);
                    ui_contentRoot.Children.Add(_videoPlayer);
                });
            });
        }
Beispiel #3
0
        /// <summary>
        /// Fired when we should load the content.
        /// </summary>
        public void OnPrepareContent()
        {
            // Run our work on a background thread.
            Task.Run(() =>
            {
                // Get the image Url
                var imageUrl = ImageManager.GetImageUrl(_baseContentPanel.Source.Url);

                // Make sure we got it.
                if (string.IsNullOrWhiteSpace(imageUrl))
                {
                    // This is bad, we should be able to get the url.
                    TelemetryManager.ReportUnexpectedEvent(this, "BasicImageControlNoImageUrl");

                    // Jump back to the UI thread
                    _baseContentPanel.FireOnFallbackToBrowser();
                    return;
                }

                // Make sure we aren't destroyed.
                if (_baseContentPanel.IsDestroyed)
                {
                    return;
                }

                // Fire off a request for the image.
                var request = new ImageManager.ImageManagerRequest
                {
                    ImageId = _baseContentPanel.Source.Id,
                    Url     = imageUrl
                };
                request.OnRequestComplete += OnRequestComplete;
                App.BaconMan.ImageMan.QueueImageRequest(request);
            });
        }
Beispiel #4
0
        /// <summary>
        /// Called when the user is trying to comment on something.
        /// </summary>
        /// <returns>Returns the json returned or a null string if failed.</returns>
        public static async Task <string> SendRedditComment(BaconManager baconMan, string redditIdCommentingOn, string comment, bool isEdit = false)
        {
            string returnString = null;

            try
            {
                // Build the data to send
                var postData = new List <KeyValuePair <string, string> >
                {
                    new KeyValuePair <string, string>("thing_id", redditIdCommentingOn),
                    new KeyValuePair <string, string>("text", comment)
                };

                var apiString = isEdit ? "api/editusertext" : "api/comment";

                // Make the call
                returnString = await baconMan.NetworkMan.MakeRedditPostRequestAsString(apiString, postData);
            }
            catch (Exception e)
            {
                TelemetryManager.ReportUnexpectedEvent("MisHelper", "failed to send comment", e);
                baconMan.MessageMan.DebugDia("failed to send message", e);
            }
            return(returnString);
        }
Beispiel #5
0
        /// <summary>
        /// Creates a new webview, this should be called under lock!
        /// </summary>
        private void MakeWebView()
        {
            if (_webView != null)
            {
                return;
            }

            // Make the web-view
            _webView = new WebView(WebViewExecutionMode.SeparateThread);

            // Setup the listeners, we need all of these because some web pages don't trigger
            // some of them.
            _webView.FrameNavigationCompleted         += NavigationCompleted;
            _webView.NavigationFailed                 += NavigationFailed;
            _webView.DOMContentLoaded                 += DomContentLoaded;
            _webView.ContentLoading                   += ContentLoading;
            _webView.ContainsFullScreenElementChanged += ContainsFullScreenElementChanged;

            // Navigate
            try
            {
                _webView.Navigate(new Uri(_contentPanelBase.Source.Url, UriKind.Absolute));
            }
            catch (Exception e)
            {
                TelemetryManager.ReportUnexpectedEvent(this, "FailedToMakeUriInWebControl", e);
                _contentPanelBase.FireOnError(true, "This web page failed to load");
            }

            // Now add an event for navigating.
            _webView.NavigationStarting += NavigationStarting;

            // Insert this before the full screen button.
            ui_contentRoot.Children.Insert(0, _webView);
        }
Beispiel #6
0
        /// <summary>
        /// Attempts to delete a post.
        /// </summary>
        /// <param name="baconMan"></param>
        /// <param name="postId"></param>
        /// <returns></returns>
        public static async Task <bool> DeletePost(BaconManager baconMan, string postId)
        {
            try
            {
                // Build the data to send
                var postData = new List <KeyValuePair <string, string> >
                {
                    new KeyValuePair <string, string>("id", "t3_" + postId)
                };


                // Make the call
                var returnString = await baconMan.NetworkMan.MakeRedditPostRequestAsString("api/del", postData);

                if (returnString.Equals("{}"))
                {
                    return(true);
                }
            }
            catch (Exception e)
            {
                TelemetryManager.ReportUnexpectedEvent("MisHelper", "failed to delete post", e);
                baconMan.MessageMan.DebugDia("failed to delete post", e);
            }
            return(false);
        }
        /// <summary>
        /// Called when we should update the inbox and send any notifications.
        /// </summary>
        /// <param name="newNotifications"></param>
        /// <param name="currentMessages"></param>
        public async Task UpdateInboxMessages(List <Tuple <string, string, string> > newNotifications, List <Message> currentMessages)
        {
            // Make sure we are enabled and in a good state
            if (ShowInboxOnBand && await EnsureBandTileState())
            {
                try
                {
                    var pairedBand = await GetPairedBand();

                    if (pairedBand == null)
                    {
                        // We don't have a band.
                        return;
                    }

                    // Try to connect to the band.
                    using (var bandClient = await BandClientManager.Instance.ConnectAsync(pairedBand))
                    {
                        foreach (var newNote in newNotifications)
                        {
                            var title = newNote.Item1;
                            var body  = newNote.Item2;

                            // If the body is empty move the title to the body so it wraps
                            if (string.IsNullOrWhiteSpace(body))
                            {
                                body  = title;
                                title = "";
                            }

                            // If we have a title clip it to only two words. The title can't be very long and
                            // looks odd if it is clipped on the band.
                            var firstSpace = string.IsNullOrWhiteSpace(title) ? -1 : title.IndexOf(' ');
                            if (firstSpace != -1)
                            {
                                if (title != null)
                                {
                                    var secondSpace = title.IndexOf(' ', firstSpace + 1);
                                    if (secondSpace != -1)
                                    {
                                        title = title.Substring(0, secondSpace);
                                    }
                                }
                            }

                            // Send the message.
                            await bandClient.NotificationManager.SendMessageAsync(_bandTileGuid, title, body, DateTimeOffset.Now, Microsoft.Band.Notifications.MessageFlags.ShowDialog);
                        }
                    }
                }
                catch (Exception e)
                {
                    _baconMan.MessageMan.DebugDia("failed to update band message", e);
                    TelemetryManager.ReportUnexpectedEvent(this, "FailedToUpdateBandMessages", e);
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Updates the subreddit list
        /// </summary>
        /// <param name="newSubreddits"></param>
        private void UpdateSubredditList(List <Subreddit> newSubreddits)
        {
            try
            {
                var insertCount = 0;
                for (var newListCount = 0; newListCount < newSubreddits.Count; newListCount++)
                {
                    var newSubreddit = newSubreddits[newListCount];

                    // Set some UI properties.
                    newSubreddit.FavIconUri  = newSubreddit.IsFavorite ? "ms-appx:///Assets/MainPage/FavoriteIcon.png" : "ms-appx:///Assets/MainPage/NotFavoriteIcon.png";
                    newSubreddit.DisplayName = newSubreddit.DisplayName.ToLower();

                    // If the two are the same, just update them.
                    if (_subreddits.Count > insertCount && _subreddits[insertCount].Id.Equals(newSubreddit.Id))
                    {
                        // If they are the same just update it
                        _subreddits[insertCount].DisplayName = newSubreddit.DisplayName;
                        _subreddits[insertCount].FavIconUri  = newSubreddit.FavIconUri;
                        _subreddits[insertCount].IsFavorite  = newSubreddit.IsFavorite;
                        _subreddits[insertCount].Title       = newSubreddit.Title;
                    }
                    // (subreddit insert) If the next element in the new list is the same as the current element in the old list, insert.
                    else if (_subreddits.Count > insertCount && newSubreddits.Count > newListCount + 1 && newSubreddits[newListCount + 1].Id.Equals(_subreddits[insertCount].Id))
                    {
                        _subreddits.Insert(insertCount, newSubreddit);
                    }
                    // (subreddit remove) If the current element in the new list is the same as the next element in the old list.
                    else if (_subreddits.Count > insertCount + 1 && newSubreddits.Count > newListCount && newSubreddits[newListCount].Id.Equals(_subreddits[insertCount + 1].Id))
                    {
                        _subreddits.RemoveAt(insertCount);
                    }
                    // If the old list is still larger than the new list, replace
                    else if (_subreddits.Count > insertCount)
                    {
                        _subreddits[insertCount] = newSubreddit;
                    }
                    // Or just add.
                    else
                    {
                        _subreddits.Add(newSubreddit);
                    }
                    insertCount++;
                }

                // Remove any extra subreddits
                while (_subreddits.Count > newSubreddits.Count)
                {
                    _subreddits.RemoveAt(_subreddits.Count - 1);
                }
            }
            catch (Exception e)
            {
                TelemetryManager.ReportUnexpectedEvent(this, "UpdateSubredditListFailed", e);
                App.BaconMan.MessageMan.DebugDia("UpdateSubredditListFailed", e);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Fired when we should load the content.
        /// </summary>
        public async void OnPrepareContent()
        {
            // Defer so we give the UI time to work.
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
            {
                var headerText = "";
                var minorText  = "";

                if (_contentPanelBase.Source.IsSelf)
                {
                    headerText = "There's no content here!";
                    minorText  = "Scroll down to view the discussion.";
                }
                else
                {
                    _content = MiscellaneousHelper.TryToFindRedditContentInLink(_contentPanelBase.Source.Url);

                    switch (_content.Type)
                    {
                    case RedditContentType.Subreddit:
                        headerText = "This post links to a subreddit";
                        minorText  = $"Tap anywhere to view /r/{_content.Subreddit}";
                        break;

                    case RedditContentType.Comment:
                        headerText = "This post links to a comment thread";
                        minorText  = "Tap anywhere to view it";
                        break;

                    case RedditContentType.Post:
                        headerText = "This post links to a reddit post";
                        minorText  = $"Tap anywhere to view it";
                        break;

                    case RedditContentType.User:
                        headerText = "This post links to a reddit user page";
                        minorText  = $"Tap anywhere to view {_content.User}";
                        break;

                    case RedditContentType.Website:
                        // This shouldn't happen
                        App.BaconMan.MessageMan.DebugDia("Got website back when prepare on reddit content control");
                        TelemetryManager.ReportUnexpectedEvent(this, "GotWebsiteOnPrepareRedditContent");
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }

                ui_headerText.Text = headerText;
                ui_minorText.Text  = minorText;

                // Hide loading
                _contentPanelBase.FireOnLoading(false);
            });
        }
Beispiel #10
0
 /// <summary>
 /// Hide the loading text when the markdown is done.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void MarkdownBox_OnMarkdownReady(object sender, MarkdownReadyArgs e)
 {
     if (e.WasError)
     {
         _contentPanelBase.FireOnFallbackToBrowser();
         TelemetryManager.ReportUnexpectedEvent(this, "FailedToShowMarkdown", e.Exception);
     }
     else
     {
         // Hide loading
         _contentPanelBase.FireOnLoading(false);
     }
 }
Beispiel #11
0
        /// <summary>
        /// Saves, unsaves, hides, or unhides a reddit item.
        /// </summary>
        /// <returns>Returns null if it fails or the user doesn't exist.</returns>
        public static async Task <bool> SaveOrHideRedditItem(BaconManager baconMan, string redditId, bool?save, bool?hide)
        {
            if (!baconMan.UserMan.IsUserSignedIn)
            {
                baconMan.MessageMan.ShowSigninMessage(save.HasValue ? "save item" : "hide item");
                return(false);
            }

            var wasSuccess = false;

            try
            {
                // Make the data
                var data = new List <KeyValuePair <string, string> > {
                    new KeyValuePair <string, string>("id", redditId)
                };

                string url;
                if (save.HasValue)
                {
                    url = save.Value ? "/api/save" : "/api/unsave";
                }
                else if (hide.HasValue)
                {
                    url = hide.Value ? "/api/hide" : "/api/unhide";
                }
                else
                {
                    return(false);
                }

                // Make the call
                var jsonResponse = await baconMan.NetworkMan.MakeRedditPostRequestAsString(url, data);

                if (jsonResponse.Contains("{}"))
                {
                    wasSuccess = true;
                }
                else
                {
                    TelemetryManager.ReportUnexpectedEvent("MisHelper", "failed to save or hide item, unknown response");
                    baconMan.MessageMan.DebugDia("failed to save or hide item, unknown response");
                }
            }
            catch (Exception e)
            {
                TelemetryManager.ReportUnexpectedEvent("MisHelper", "failed to save or hide item", e);
                baconMan.MessageMan.DebugDia("failed to save or hide item", e);
            }
            return(wasSuccess);
        }
        /// <summary>
        /// Assuming there are images, this does the rotation of the lock screen images.
        /// </summary>
        /// <returns></returns>
        private async Task DoImageRotation(UpdateTypes type)
        {
            try
            {
                var wasSuccess = false;
                switch (type)
                {
                case UpdateTypes.LockScreen:
                    wasSuccess = await DoSingleImageRotation(UpdateTypes.LockScreen);

                    break;

                case UpdateTypes.Desktop:
                    wasSuccess = await DoSingleImageRotation(UpdateTypes.Desktop);

                    break;

                case UpdateTypes.Band:
                    wasSuccess = await DoSingleImageRotation(UpdateTypes.Band);

                    break;

                case UpdateTypes.All:
                    break;

                default:
                {
                    var firstSuccess = await DoSingleImageRotation(UpdateTypes.LockScreen);

                    var secondSuccess = await DoSingleImageRotation(UpdateTypes.Desktop);

                    var thirdSuccess = await DoSingleImageRotation(UpdateTypes.Band);

                    wasSuccess = firstSuccess && secondSuccess && thirdSuccess;
                    break;
                }
                }

                // If we successfully updated set the time.
                if (wasSuccess)
                {
                    LastImageUpdate = DateTime.Now;
                }
            }
            catch (Exception e)
            {
                _baconMan.MessageMan.DebugDia("Failed to set background image", e);
                TelemetryManager.ReportUnexpectedEvent(this, "Failed to set background image", e);
            }
        }
Beispiel #13
0
 /// <summary>
 /// Fires FireOnDestroyContnet on the UI thread.
 /// </summary>
 /// <param name="host"></param>
 /// <param name="panel"></param>
 private async Task FireOnDestroyContent(IContentPanelBase panelBase)
 {
     await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
     {
         try
         {
             panelBase.OnDestroyContent();
         }
         catch (Exception e)
         {
             App.BaconMan.MessageMan.DebugDia("FireOnRemovePanel failed", e);
             TelemetryManager.ReportUnexpectedEvent(this, "FireOnRemovePanelFailed", e);
         }
     });
 }
Beispiel #14
0
 /// <summary>
 /// Fires OnPanelUnloaded on the UI thread.
 /// </summary>
 /// <param name="host"></param>
 /// <param name="panel"></param>
 private async void FireOnPanelUnloaded(IContentPanelHost host)
 {
     await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
     {
         try
         {
             // Then tell the pane has been unloaded.
             host.OnPanelUnloaded();
         }
         catch (Exception e)
         {
             App.BaconMan.MessageMan.DebugDia("FireOnPanelUnloaded failed", e);
             TelemetryManager.ReportUnexpectedEvent(this, "FireOnPanelUnloadedFailed", e);
         }
     });
 }
Beispiel #15
0
        /// <summary>
        /// Called by the consumer when a massage should be changed
        /// </summary>
        public void ChangeMessageReadStatus(Message message, bool isRead, int messagePosition = 0)
        {
            // Using the post and suggested index, find the real post and index
            var collectionMessage = message;

            FindMessageInCurrentCollection(ref collectionMessage, ref messagePosition);

            if (collectionMessage == null || messagePosition == -1)
            {
                // We didn't find it.
                return;
            }

            // Update the status
            collectionMessage.IsNew = isRead;

            // Fire off that a update happened.
            FireCollectionUpdated(messagePosition, new List <Message> {
                collectionMessage
            }, false, false);

            // Start a task to make the vote
            Task.Run(async() =>
            {
                try
                {
                    // Build the data
                    var request  = collectionMessage.IsNew ? "/api/unread_message" : "/api/read_message";
                    var postData = new List <KeyValuePair <string, string> >();
                    postData.Add(new KeyValuePair <string, string>("id", collectionMessage.GetFullName()));

                    // Make the call
                    var str = await _mBaconMan.NetworkMan.MakeRedditPostRequestAsString(request, postData);

                    // Do some super simple validation
                    if (str != "{}")
                    {
                        throw new Exception("Failed to set message status! The response indicated a failure");
                    }
                }
                catch (Exception ex)
                {
                    _mBaconMan.MessageMan.DebugDia("failed to set message status!", ex);
                    TelemetryManager.ReportUnexpectedEvent(this, "failedToSetMessageRead", ex);
                }
            });
        }
Beispiel #16
0
        /// <summary>
        /// Callback when we get the image.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="response"></param>
        private async void OnRequestComplete(object sender, ImageManager.ImageManagerResponseEventArgs response)
        {
            // Remove the event
            var request = (ImageManager.ImageManagerRequest)sender;

            request.OnRequestComplete -= OnRequestComplete;

            // Jump back to the UI thread
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                if (!response.Success)
                {
                    TelemetryManager.ReportUnexpectedEvent(this, "BasicImageControlNoImageUrl");
                    _baseContentPanel.FireOnFallbackToBrowser();
                    return;
                }

                lock (this)
                {
                    if (_baseContentPanel.IsDestroyed)
                    {
                        // Get out of here if we should be destroyed.
                        return;
                    }

                    // Grab the source, we need this to make the image
                    _imageSourceStream = response.ImageStream;

                    // Add the image to the UI
                    _image = new Image();

                    // We don't want to wait on this.
#pragma warning disable CS4014
                    // Set the image.
                    ReloadImage(false);
#pragma warning restore CS4014

                    // Set the image into the UI.
                    ui_scrollViewer.Content = _image;

                    // Setup the save image tap
                    _image.RightTapped += ContentRoot_RightTapped;
                    _image.Holding     += ContentRoot_Holding;
                }
            });
        }
Beispiel #17
0
        public static Type GetControlType(ContentPanelSource source, object callingClass = null)
        {
            try
            {
                if (GifImageContentPanel.CanHandlePost(source))
                {
                    return(typeof(GifImageContentPanel));
                }
                if (RedditVideoContentPanel.CanHandlePost(source))
                {
                    return(typeof(RedditVideoContentPanel));
                }
                if (YoutubeContentPanel.CanHandlePost(source))
                {
                    return(typeof(YoutubeContentPanel));
                }
                if (BasicImageContentPanel.CanHandlePost(source))
                {
                    return(typeof(BasicImageContentPanel));
                }
                if (MarkdownContentPanel.CanHandlePost(source))
                {
                    return(typeof(MarkdownContentPanel));
                }
                if (RedditContentPanel.CanHandlePost(source))
                {
                    return(typeof(RedditContentPanel));
                }
                if (CommentSpoilerContentPanel.CanHandlePost(source))
                {
                    return(typeof(CommentSpoilerContentPanel));
                }
                if (WindowsAppContentPanel.CanHandlePost(source))
                {
                    return(typeof(WindowsAppContentPanel));
                }
            }
            catch (Exception e)
            {
                // If we fail here we will fall back to the web browser.
                App.BaconMan.MessageMan.DebugDia("Failed to query can handle post", e);
                TelemetryManager.ReportUnexpectedEvent(callingClass, "FailedToQueryCanHandlePost", e);
            }

            return(typeof(WebPageContentPanel));
        }
Beispiel #18
0
 /// <summary>
 /// Fires OnContentPreloading on the UI thread.
 /// </summary>
 /// <param name="host"></param>
 /// <param name="panel"></param>
 private async void FireOnContentPreloading(IContentPanelHost host)
 {
     // Do this on a high pri so the loading indicator will show up ASAP.
     await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
     {
         try
         {
             // Then tell the content has begun loading.
             host.OnContentPreloading();
         }
         catch (Exception e)
         {
             App.BaconMan.MessageMan.DebugDia("FireOnContentPreloading failed", e);
             TelemetryManager.ReportUnexpectedEvent(this, "FireOnContentPreloadingFailed", e);
         }
     });
 }
Beispiel #19
0
#pragma warning restore

        /// <summary>
        /// Uses GfyCat to convert a normal .gif into a video
        /// </summary>
        /// <param name="gifUrl"></param>
        /// <returns></returns>
        private async Task <string> ConvertGifUsingGfycat(string gifUrl)
        {
            // Return if we have nothing.
            if (gifUrl.Equals(string.Empty))
            {
                return(string.Empty);
            }

            try
            {
                var url = $"https://upload.gfycat.com/transcode?fetchUrl={gifUrl}";
                // Make the call
                var webResult = await NetworkManager.MakeGetRequest("https://upload.gfycat.com/transcode?fetchUrl=" + gifUrl);

                // Get the input stream and json reader.
                // NOTE!! We are really careful not to use a string here so we don't have to allocate a huge string.
                var inputStream = await webResult.ReadAsInputStreamAsync();

                using (var reader = new StreamReader(inputStream.AsStreamForRead()))
                    using (JsonReader jsonReader = new JsonTextReader(reader))
                    {
                        // Parse the Json as an object
                        var serializer = new JsonSerializer();
                        var gfyData    = await Task.Run(() => serializer.Deserialize <GfyCatConversionData>(jsonReader));

                        // Validate the response
                        var mp4Url = gfyData.Mp4Url;
                        if (string.IsNullOrWhiteSpace(mp4Url))
                        {
                            throw new Exception("Gfycat failed to convert");
                        }

                        // Return the url
                        return(mp4Url);
                    }
            }
            catch (Exception e)
            {
                App.BaconMan.MessageMan.DebugDia("failed to convert gif via gfycat", e);
                TelemetryManager.ReportUnexpectedEvent(this, "GfyCatConvertFailed", e);
            }

            return(string.Empty);
        }
Beispiel #20
0
        /// <summary>
        /// Gets a video url from gfycat
        /// </summary>
        /// <param name="apiUrl"></param>
        /// <returns></returns>
        private async Task <string> GetGfyCatGifUrl(string apiUrl)
        {
            // Return if we have nothing.
            if (apiUrl.Equals(string.Empty))
            {
                return(string.Empty);
            }

            try
            {
                // Make the call
                var webResult = await NetworkManager.MakeGetRequest(apiUrl);

                // Get the input stream and json reader.
                // NOTE!! We are really careful not to use a string here so we don't have to allocate a huge string.
                var inputStream = await webResult.ReadAsInputStreamAsync();

                using (var reader = new StreamReader(inputStream.AsStreamForRead()))
                    using (JsonReader jsonReader = new JsonTextReader(reader))
                    {
                        // Parse the Json as an object
                        var serializer = new JsonSerializer();
                        var gfyData    = await Task.Run(() => serializer.Deserialize <GfyCatDataContainer>(jsonReader));

                        // Validate the response
                        var mp4Url = gfyData.Item.Mp4Url;
                        if (string.IsNullOrWhiteSpace(mp4Url))
                        {
                            throw new Exception("Gfycat response failed to parse");
                        }

                        // Return the url
                        return(mp4Url);
                    }
            }
            catch (Exception e)
            {
                App.BaconMan.MessageMan.DebugDia("failed to get image from gfycat", e);
                TelemetryManager.ReportUnexpectedEvent(this, "FaileGfyCatApiCall", e);
            }

            return(string.Empty);
        }
Beispiel #21
0
        /// <summary>
        /// Gets a reddit user.
        /// </summary>
        /// <returns>Returns null if it fails or the user doesn't exist.</returns>
        public static async Task <User> GetRedditUser(BaconManager baconMan, string userName)
        {
            User foundUser = null;

            try
            {
                // Make the call
                var jsonResponse = await baconMan.NetworkMan.MakeRedditGetRequestAsString($"user/{userName}/about/.json");

                // Parse the new user
                foundUser = await ParseOutRedditDataElement <User>(baconMan, jsonResponse);
            }
            catch (Exception e)
            {
                TelemetryManager.ReportUnexpectedEvent("MisHelper", "failed to search for user", e);
                baconMan.MessageMan.DebugDia("failed to search for user", e);
            }
            return(foundUser);
        }
Beispiel #22
0
        /// <summary>
        /// Fires FireOnPanelStolen on the UI thread.
        /// </summary>
        /// <param name="host"></param>
        /// <param name="panel"></param>
        private async Task FireOnRemovePanel(IContentPanelHost host, IContentPanelBase panelBase)
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
            {
                try
                {
                    // Tell the panel the host is gone
                    panelBase.OnHostRemoved();

                    // And remove the panel.
                    host.OnRemovePanel(panelBase);
                }
                catch (Exception e)
                {
                    App.BaconMan.MessageMan.DebugDia("FireOnRemovePanel failed", e);
                    TelemetryManager.ReportUnexpectedEvent(this, "FireOnRemovePanelFailed", e);
                }
            });
        }
Beispiel #23
0
        /// <summary>
        /// Fires OnPanelAvailable on the UI thread.
        /// </summary>
        /// <param name="host"></param>
        /// <param name="panel"></param>
        private async void FireOnPanelAvailable(IContentPanelHost host, IContentPanelBase panelBase)
        {
            await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
            {
                try
                {
                    // First tell the post it has a host
                    panelBase.OnHostAdded(host);

                    // Then tell the host it has a panel.
                    host.OnPanelAvailable(panelBase);
                }
                catch (Exception e)
                {
                    App.BaconMan.MessageMan.DebugDia("FireOnPanelAvailable failed", e);
                    TelemetryManager.ReportUnexpectedEvent(this, "FireOnPanelAvailableFailed", e);
                }
            });
        }
Beispiel #24
0
        private void ReadingMode_Tapped(object sender, TappedRoutedEventArgs e)
        {
            // Show loading
            try
            {
                lock (_lockObject)
                {
                    ui_readingModeLoading.Visibility    = Visibility.Visible;
                    ui_readingModeLoading.IsActive      = true;
                    ui_readingModeIconHolder.Visibility = Visibility.Collapsed;
                    _webView.Navigate(new Uri($"http://www.readability.com/m?url={_contentPanelBase.Source.Url}", UriKind.Absolute));
                }
            }
            catch (Exception ex)
            {
                TelemetryManager.ReportUnexpectedEvent(this, "FailedToNavReadingMode", ex);
            }

            TelemetryManager.ReportEvent(this, "ReadingModeEnabled");
        }
Beispiel #25
0
 private void DataTransferManager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args)
 {
     if (_mShareComment != null)
     {
         var commentLink = "https://reddit.com" + _post.Permalink + _mShareComment.Id;
         // #todo use a markdown-less body text
         var shareBody = _mShareComment.Body.Length > 50 ? _mShareComment.Body.Substring(0, 50) + "..." : _mShareComment.Body;
         args.Request.Data.Properties.ApplicationName      = "Baconit";
         args.Request.Data.Properties.ContentSourceWebLink = new Uri(commentLink, UriKind.Absolute);
         args.Request.Data.Properties.Title       = "A Reddit Post Shared From Baconit";
         args.Request.Data.Properties.Description = shareBody;
         args.Request.Data.SetText($" \r\n\r\n{shareBody}\r\n\r\n{commentLink}");
         _mShareComment = null;
         TelemetryManager.ReportEvent(this, "CommentShared");
     }
     else
     {
         args.Request.FailWithDisplayText("Baconit doesn't have anything to share!");
         TelemetryManager.ReportUnexpectedEvent(this, "FailedToShareCommentHelperCommentNoShareComment");
     }
 }
Beispiel #26
0
        /// <summary>
        ///     Called when the user added a comment or edit an existing comment.
        /// </summary>
        /// <returns></returns>
        public bool CommentAddedOrEdited(string parentOrOrgionalId, string serverResponse, bool isEdit)
        {
            // Assume if we can find author we are successful. Not sure if that is safe or not... :)
            if (!string.IsNullOrWhiteSpace(serverResponse) && serverResponse.Contains("\"author\""))
            {
                // Do the next part in a try catch so if we fail we will still report success since the
                // message was sent to reddit.
                try
                {
                    // Parse the new comment
                    var newComment = MiscellaneousHelper.ParseOutRedditDataElement <Comment>(_baconMan, serverResponse)
                                     .Result;

                    if (isEdit)
                    {
                        UpdateComment(newComment);
                    }
                    else
                    {
                        // Inject the new comment
                        InjectComment(parentOrOrgionalId, newComment);
                    }
                }
                catch (Exception e)
                {
                    // We f****d up adding the comment to the UI.
                    _baconMan.MessageMan.DebugDia("Failed injecting comment", e);
                    TelemetryManager.ReportUnexpectedEvent(this, "AddCommentSuccessButAddUiFailed");
                }

                // If we get to adding to the UI return true because reddit has the comment.
                return(true);
            }

            // Reddit returned something wrong
            _baconMan.MessageMan.ShowMessageSimple("That's not right",
                                                   "Sorry we can't post your comment right now, reddit returned and unexpected message.");
            TelemetryManager.ReportUnexpectedEvent(this, "CommentPostReturnedUnexpectedMessage");
            return(false);
        }
Beispiel #27
0
        /// <summary>
        /// Update the posts in flip view. Staring at the index given and going until the list is empty.
        /// </summary>
        /// <param name="startingPos"></param>
        /// <param name="newPosts"></param>
        private async void UpdatePosts(int startingPos, IReadOnlyList <Post> newPosts)
        {
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>
            {
                var flipViewMenuVis = _host.CurrentScreenMode() == ScreenMode.Single ? Visibility.Visible : Visibility.Collapsed;

                // Grab the list lock
                lock (_postsLists)
                {
                    // If we are currently in a deferred scenario then we need to handle updates
                    // differently since the list won't match the list that is expected
                    if (_deferredPostList.Count != 0)
                    {
                        if (_postsLists.Count <= 0 || newPosts.Count <= 0 ||
                            !_postsLists[0].Context.Post.Id.Equals(newPosts[0].Id))
                        {
                            return;
                        }
                        // The current post is updated, so update it.
                        // We can't replace the time because flip view will freak out
                        // so just update whatever UI we need to update.
                        _postsLists[0].Context.Post.Likes               = newPosts[0].Likes;
                        _postsLists[0].Context.Post.SubTextLine1        = newPosts[0].SubTextLine1;
                        _postsLists[0].Context.Post.SubTextLine2PartOne = newPosts[0].SubTextLine2PartOne;
                        _postsLists[0].Context.Post.SubTextLine2PartTwo = newPosts[0].SubTextLine2PartTwo;
                        _postsLists[0].Context.Post.Domain              = newPosts[0].Domain;
                        _postsLists[0].Context.Post.Score               = newPosts[0].Score;

                        // We have done all we want to do, leave now.
                        return;
                    }

                    // If the list is currently empty we want to only load the first element and defer the rest of the
                    // elements. If the target post is -1 we load the first element, if not we load it only.
                    var deferLoadPosts  = _postsLists.Count == 0;
                    var deferTargetPost = _targetPost;
                    _targetPost         = null;
                    if (deferLoadPosts)
                    {
                        // If we are doing a defer make sure we have a target
                        if (string.IsNullOrWhiteSpace(deferTargetPost) && newPosts.Count > 0)
                        {
                            deferTargetPost = newPosts[0].Id;
                        }
                    }

                    // Now setup the post update
                    var insertIndex = startingPos;

                    // Set up the objects for the UI
                    foreach (var post in newPosts)
                    {
                        if (post == null)
                        {
                            continue;
                        }

                        // Check if we are adding or inserting.
                        var isReplace = insertIndex < _postsLists.Count;

                        if (isReplace)
                        {
                            if (_postsLists[insertIndex].Context.Post.Id.Equals(post.Id))
                            {
                                // We can't replace the time because flip view will freak out
                                // so just update whatever UI we need to update.
                                _postsLists[insertIndex].Context.Post.Likes               = post.Likes;
                                _postsLists[insertIndex].Context.Post.SubTextLine1        = post.SubTextLine1;
                                _postsLists[insertIndex].Context.Post.SubTextLine2PartOne = post.SubTextLine2PartOne;
                                _postsLists[insertIndex].Context.Post.SubTextLine2PartTwo = post.SubTextLine2PartTwo;
                                _postsLists[insertIndex].Context.Post.Domain              = post.Domain;
                                _postsLists[insertIndex].Context.Post.Score               = post.Score;
                            }
                            else
                            {
                                // Replace the entire post if it brand new
                                _postsLists[insertIndex].Context.Post = post;
                            }
                        }
                        else
                        {
                            // If we are deferring posts only add the target
                            if (deferLoadPosts)
                            {
                                if (post.Id.Equals(deferTargetPost))
                                {
                                    // Try catch is a work around for bug https://github.com/QuinnDamerell/Baconit/issues/53
                                    try
                                    {
                                        _postsLists.Add(new FlipViewPostItem(_host, _collector, post, _targetComment));
                                    }
                                    catch (Exception e)
                                    {
                                        TelemetryManager.ReportUnexpectedEvent(this, "UpdatePosts", e);
                                        App.BaconMan.MessageMan.DebugDia("Adding to postList failed! (deferLoadPosts)", e);
                                    }
                                }

                                // Add it to the deferred list, also add the deferred post so we know
                                // where it is in the list.
                                _deferredPostList.Add(post);
                            }
                            else
                            {
                                // Otherwise, just add it.
                                // Try catch is a work around for bug https://github.com/QuinnDamerell/Baconit/issues/53
                                try
                                {
                                    _postsLists.Add(new FlipViewPostItem(_host, _collector, post, _targetComment));
                                }
                                catch (Exception e)
                                {
                                    TelemetryManager.ReportUnexpectedEvent(this, "UpdatePosts", e);
                                    App.BaconMan.MessageMan.DebugDia("Adding to postList failed! (!deferLoadPosts)", e);
                                }
                            }
                        }

                        // Set the menu button
                        post.FlipViewMenuButton = flipViewMenuVis;

                        // Add one to the insert index
                        insertIndex++;
                    }

                    // If the item source hasn't been set yet do it now.
                    if (ui_flipView.ItemsSource == null)
                    {
                        ui_flipView.ItemsSource = _postsLists;
                    }
                }

                // Hide the loading overlay if it is visible
                HideFullScreenLoading();
            });
        }
Beispiel #28
0
        /// <summary>
        /// Fired when a user taps view context.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ViewContext_OnButtonTapped(object sender, EventArgs e)
        {
            // Get the message
            var message = (Message)((FrameworkElement)sender).DataContext;

            // We need to get all of the parts of this message we need to send to flip view
            // The comment replies only have the post id in the "context" so use that for both.
            string postId = null;

            try
            {
                var context        = message.Context;
                var contextIndex   = context.IndexOf('/');
                var slashSeenCount = 0;
                while (contextIndex != -1)
                {
                    slashSeenCount++;
                    // Iterate one past the /
                    contextIndex++;

                    if (slashSeenCount == 4)
                    {
                        // After 4 slashes we should have the post id

                        var nextSlash = context.IndexOf('/', contextIndex);
                        postId = context.Substring(contextIndex, nextSlash - contextIndex);
                        break;
                    }

                    contextIndex = context.IndexOf('/', contextIndex);
                }

                if (string.IsNullOrEmpty(postId))
                {
                    throw new Exception("post id was empty");
                }
            }
            catch (Exception ex)
            {
                App.BaconMan.MessageMan.DebugDia("failed to parse message context", ex);
                App.BaconMan.MessageMan.ShowMessageSimple("Oops", "Something is wrong and we can't show this context right now.");
                TelemetryManager.ReportUnexpectedEvent(this, "failedToParseMessageContextString", ex);
                return;
            }

            // Navigate flip view and force it to the post and comment.
            var args = new Dictionary <string, object>();

            args.Add(PanelManager.NavArgsSubredditName, message.Subreddit);
            args.Add(PanelManager.NavArgsForcePostId, postId);
            args.Add(PanelManager.NavArgsForceCommentId, message.Id);

            // Make sure the page Id is unique
            _mPanelHost.Navigate(typeof(FlipViewPanel), message.Subreddit + SortTypes.Hot + SortTimeTypes.Week + postId + message.Id, args);

            // Also if it is unread set it to read
            if (message.IsNew)
            {
                MarkAsRead_Tapped(sender, e);
            }
        }
Beispiel #29
0
        /// <summary>
        /// Submits a new reddit post
        /// </summary>
        public static async Task <SubmitNewPostResponse> SubmitNewPost(BaconManager baconMan, string title, string urlOrText, string subredditDisplayName, bool isSelfText, bool sendRepliesToInbox)
        {
            if (!baconMan.UserMan.IsUserSignedIn)
            {
                baconMan.MessageMan.ShowSigninMessage("submit a new post");
                return(new SubmitNewPostResponse {
                    Success = false
                });
            }

            try
            {
                // Make the data
                var data = new List <KeyValuePair <string, string> >
                {
                    new KeyValuePair <string, string>("kind", isSelfText ? "self" : "link"),
                    new KeyValuePair <string, string>("sr", subredditDisplayName),
                    new KeyValuePair <string, string>("sendreplies", sendRepliesToInbox ? "true" : "false")
                };
                data.Add(isSelfText
                    ? new KeyValuePair <string, string>("text", urlOrText)
                    : new KeyValuePair <string, string>("url", urlOrText));
                data.Add(new KeyValuePair <string, string>("title", title));

                // Make the call
                var jsonResponse = await baconMan.NetworkMan.MakeRedditPostRequestAsString("/api/submit/", data);

                // Try to see if we can find the word redirect and if we can find the subreddit url
                var responseLower = jsonResponse.ToLower();
                if (responseLower.Contains("redirect") && responseLower.Contains($"://www.reddit.com/r/{subredditDisplayName}/comments/"))
                {
                    // Success, try to parse out the new post link
                    var startOfLink = responseLower.IndexOf($"://www.reddit.com/r/{subredditDisplayName}/comments/");
                    if (startOfLink == -1)
                    {
                        return(new SubmitNewPostResponse {
                            Success = false
                        });
                    }

                    var endofLink = responseLower.IndexOf('"', startOfLink);
                    if (endofLink == -1)
                    {
                        return(new SubmitNewPostResponse {
                            Success = false
                        });
                    }

                    // Try to get the link
                    var link = "https" + jsonResponse.Substring(startOfLink, endofLink - startOfLink);

                    // Return
                    return(new SubmitNewPostResponse {
                        Success = true, NewPostLink = link
                    });
                }

                // We have a reddit error. Try to figure out what it is.
                for (var i = 0; i < Enum.GetNames(typeof(SubmitNewPostErrors)).Length; i++)
                {
                    var enumName = Enum.GetName(typeof(SubmitNewPostErrors), i).ToLower();;
                    if (!responseLower.Contains(enumName))
                    {
                        continue;
                    }
                    TelemetryManager.ReportUnexpectedEvent("MisHelper", "failed to submit post; error: " + enumName);
                    baconMan.MessageMan.DebugDia("failed to submit post; error: " + enumName);
                    return(new SubmitNewPostResponse {
                        Success = false, RedditError = (SubmitNewPostErrors)i
                    });
                }

                TelemetryManager.ReportUnexpectedEvent("MisHelper", "failed to submit post; unknown reddit error: ");
                baconMan.MessageMan.DebugDia("failed to submit post; unknown reddit error");
                return(new SubmitNewPostResponse {
                    Success = false, RedditError = SubmitNewPostErrors.Unknown
                });
            }
            catch (Exception e)
            {
                TelemetryManager.ReportUnexpectedEvent("MisHelper", "failed to submit post", e);
                baconMan.MessageMan.DebugDia("failed to submit post", e);
                return(new SubmitNewPostResponse {
                    Success = false
                });
            }
        }
Beispiel #30
0
        /// <summary>
        /// Attempts to parse out a reddit object from a generic reddit response
        /// json containing a data object. We can't do a generic DataObject here because
        /// the function handles data blocks that are in various depths in the json.
        /// </summary>
        /// <param name="baconMan"></param>
        /// <param name="originalJson"></param>
        /// <returns></returns>
        public static async Task <T> ParseOutRedditDataElement <T>(BaconManager baconMan, string originalJson)
        {
            // TODO make this async. If I try to Task.Run(()=> the parse the task returns but the
            // await never resumes... idk why.
            try
            {
                // Try to parse out the data object
                var dataPos = originalJson.IndexOf("\"data\":", StringComparison.Ordinal);
                if (dataPos == -1)
                {
                    return(default(T));
                }
                var dataStartPos = originalJson.IndexOf('{', dataPos + 7);
                if (dataStartPos == -1)
                {
                    return(default(T));
                }
                // There can be nested { } in the data we want
                // To do this optimally, we will just look for the close manually.
                var dataEndPos = dataStartPos + 1;
                var depth      = 0;
                var isInText   = false;
                while (dataEndPos < originalJson.Length)
                {
                    // If we find a " make sure we ignore everything.
                    if (originalJson[dataEndPos] == '"')
                    {
                        if (isInText)
                        {
                            // If we are in a text block look if it is an escape.
                            // If it isn't an escape, end the text block.
                            if (originalJson[dataEndPos - 1] != '\\')
                            {
                                isInText = false;
                            }
                        }
                        else
                        {
                            // We entered text.
                            isInText = true;
                        }
                    }

                    // If not in a text block, look for {}
                    if (!isInText)
                    {
                        // If we find an open +1 to depth
                        if (originalJson[dataEndPos] == '{')
                        {
                            depth++;
                        }
                        // If we find and end..
                        else if (originalJson[dataEndPos] == '}')
                        {
                            // If we have no depth we are done.
                            if (depth == 0)
                            {
                                break;
                            }
                            // Otherwise take one off.

                            depth--;
                        }
                    }

                    dataEndPos++;
                }

                // Make sure we didn't fail.
                if (depth != 0)
                {
                    return(default(T));
                }

                // Move past the last }
                dataEndPos++;

                var dataBlock = originalJson.Substring(dataStartPos, (dataEndPos - dataStartPos));
                return(JsonConvert.DeserializeObject <T>(dataBlock));
            }
            catch (Exception e)
            {
                TelemetryManager.ReportUnexpectedEvent("MisHelper", "failed to parse data element", e);
            }
            return(default(T));
        }