예제 #1
0
        public static string GetSectionKey(XmlDocument doc)
        {
            var key = "";

            LoggingHelpers.RecordGeneralEntry("Parsing XML Reply");
            using (XmlReader reader = new XmlNodeReader(doc))
            {
                while (reader.Read())
                {
                    if (reader.IsStartElement())
                    {
                        LoggingHelpers.RecordGeneralEntry("Checking for directories");

                        switch (reader.Name)
                        {
                        case "Directory":
                            if (reader.GetAttribute("title") == "Library Sections")
                            {
                                var localKey = reader.GetAttribute("key");
                                key = localKey;
                                LoggingHelpers.RecordGeneralEntry("Found " + key);
                            }

                            break;
                        }
                    }
                }

                return(key);
            }
        }
예제 #2
0
        public static int GetTableIndexFromDgv(DataGridView dgv, DataTable table = null)
        {
            //MessageBox.Show(@"Hello!");
            LoggingHelpers.RecordGeneralEntry($"Table-to-Grid match has been requested on '{dgv.Name}'");

            //if the table's null we can't do anything with it, because there's no data to work with.
            if (table == null)
            {
                //set the table object to the default table, log it, and keep going.
                table = ReturnCorrectTable();
                LoggingHelpers.RecordGeneralEntry(
                    "Table-to-Grid match was not given a table; defaulting to the standard table selector.");
            }

            var selRow = ((DataRowView)dgv.SelectedRows[0].DataBoundItem).Row
                         .ItemArray; //array of cell values from the selected row
            var val = 0;             //value to return back to the caller

            //go through every row in the TABLE
            foreach (DataRow r in table.Rows)
            {
                //get the index number of the row we're currently processing
                //NOTE: This is the index inside of the TABLE NOT THE GRID
                var i = table.Rows.IndexOf(r);

                //represents the total matches so far (how many cells in the current
                //TABLE row match the selected GRID row)
                var m = 0;

                //cycle through each cell value in the currently selected GRID row
                foreach (var o in selRow)
                {
                    //does the TABLE row contain the current cell value of the GRID row?
                    if (r.ItemArray.Contains(o))
                    {
                        m++; //increment the match counter
                    }
                    else
                    {
                        break; //if one wrong match is encountered, break immediately. This will drastically improve lookup speeds.
                    }
                }
                //ALL column values must match, so the match count will be equal to the cell length.
                if (m != selRow.Length)
                {
                    continue;
                }

                val = i; //set the return value to the current TABLE row index

                break;   //ONLY triggered if the match counter equals the selected row's cell count.
            }

            return(val);
        }
예제 #3
0
        public static void LaunchPvs(PlexObject stream)
        {
            if (stream != null)
            {
                try
                {
                    if (!Methods.StreamAdultContentCheck(stream))
                    {
                        return;
                    }

                    //downloads won't work properly if you're streaming at the same time
                    if (!Flags.IsDownloadRunning && !Flags.IsEngineRunning)
                    {
                        var frm = new UI.Forms.Player
                        {
                            StreamingContent = stream
                        };
                        LoggingHelpers.RecordGeneralEntry("Started streaming " + stream.StreamInformation.ContentTitle +
                                                          " (PVS)");
                        frm.ShowDialog();
                    }
                    else
                    {
                        UIMessages.Warning(
                            "You cannot stream \n" + stream.StreamInformation.ContentTitle +
                            "\n because a download is already running. Cancel the download before attempting to stream within PlexDL.",
                            @"Validation Error");
                        LoggingHelpers.RecordGeneralEntry(
                            "Tried to stream content via PVS, but a download is running.");
                    }
                }
                catch (Exception ex)
                {
                    UIMessages.Error("Error occurred whilst trying to launch VLC\n\n" + ex, @"Launch Error");
                    LoggingHelpers.RecordException(ex.Message, "VLCLaunchError");
                }
            }
            else
            {
                LoggingHelpers.RecordGeneralEntry("Tried to stream content via PVS, but one or more values were null.");
            }
        }
예제 #4
0
 public static void LaunchBrowser(PlexObject stream)
 {
     try
     {
         if (Methods.StreamAdultContentCheck(stream))
         {
             Process.Start(stream.StreamInformation.Links
                           .View); //normal MP4 stream (this won't trigger a browser download if it's a supported file)
             LoggingHelpers.RecordGeneralEntry("Started streaming " + stream.StreamInformation.ContentTitle +
                                               " (Browser)");
         }
     }
     catch (Exception ex)
     {
         UIMessages.Error("Error occurred whilst trying to launch the default browser\n\n" + ex,
                          @"Launch Error");
         LoggingHelpers.RecordException(ex.Message, "BrowserLaunchError");
     }
 }
예제 #5
0
        public static XmlMetadata GetContentMetadata(int index)
        {
            XmlMetadata obj;

            try
            {
                LoggingHelpers.RecordGeneralEntry("Getting movie metadata XML");

                var result = RowGet.GetDataRowContent(index);

                obj = XmlMetadataHelpers.GetMetadata(result);
            }
            catch (Exception ex)
            {
                LoggingHelpers.RecordException(ex.Message, "GetMovieMetadataError");
                obj = new XmlMetadata();
            }

            return(obj);
        }
예제 #6
0
        public static XmlMetadata GetTracksListXml(int index)
        {
            XmlMetadata obj;

            try
            {
                LoggingHelpers.RecordGeneralEntry("Getting track list XML");

                var result = RowGet.GetDataRowAlbums(index);

                obj = XmlMetadataHelpers.GetMetadata(result);
            }
            catch (Exception ex)
            {
                LoggingHelpers.RecordException(ex.Message, "GetTrackListError");
                obj = new XmlMetadata();
            }

            return(obj);
        }
예제 #7
0
        //another method to handle testing a connection
        //this one's here for logging purposes and such, and is used
        //solely by the Server Manager
        private static WebCheck TestConnection(Server svr)
        {
            var value = new WebCheck();

            try
            {
                var uri = ConnectionLink(svr);

                //UIMessages.Info(uri);

                var testUrl = WebCheck.TestUrl(uri);

                value = testUrl;
            }
            catch (Exception ex)
            {
                LoggingHelpers.RecordGeneralEntry($"Couldn't connect to \"{svr.address}:{svr.port}\"");
                LoggingHelpers.RecordException(ex.Message, "ConnectionTestError");
            }

            return(value);
        }
예제 #8
0
        public void ToFile(string fileName = "plex.account")
        {
            try
            {
                var xsSubmit    = new XmlSerializer(typeof(CachedPlexLogin));
                var xmlSettings = new XmlWriterSettings();
                var sww         = new StringWriter();
                xmlSettings.Indent             = true;
                xmlSettings.IndentChars        = "\t";
                xmlSettings.OmitXmlDeclaration = false;

                xsSubmit.Serialize(sww, this);

                File.WriteAllText(fileName, sww.ToString());

                LoggingHelpers.RecordGeneralEntry("Saved PlexLogin data to '" + fileName + "'");
            }
            catch (Exception ex)
            {
                LoggingHelpers.RecordException(ex.Message, "PlexLoginSaveError");
            }
        }
예제 #9
0
        public static XmlMetadata GetMetadata(DataRow result,
                                              string msgNoKey     = "Error occurred whilst getting the unique content key",
                                              string logNoKeyMsg  = "Error occurred whilst getting the unique content key",
                                              string logNoKeyType = "NoUnqKeyError", string column = "key")
        {
            var         obj   = new XmlMetadata();
            XmlDocument reply = null;

            var key = "";

            if (result[column] != null)
            {
                if (!Equals(result[column], string.Empty))
                {
                    key = result[column].ToString();
                }
            }

            if (string.IsNullOrEmpty(key))
            {
                UIMessages.Error(msgNoKey, @"Data Error");
                LoggingHelpers.RecordGeneralEntry("Unique key error");
                LoggingHelpers.RecordException(logNoKeyMsg, logNoKeyType);
            }
            else
            {
                var baseUri = Strings.GetBaseUri(false);
                key = key.TrimStart('/');
                var uri = baseUri + key + "/?X-Plex-Token=";

                LoggingHelpers.RecordGeneralEntry("Contacting the API");
                reply = XmlGet.GetXmlTransaction(uri);
            }

            obj.Xml    = reply;
            obj.ApiUri = $"/{key}";
            return(obj);
        }
예제 #10
0
        //TV OBJECT BUILDER
        public static PlexTvShow GetTvObjectFromIndex(int index, bool waitWindow = true)
        {
            try
            {
                if (waitWindow)
                {
                    return((PlexTvShow)WaitWindow.WaitWindow.Show(GetTvObjectFromIndex_Callback, @"Getting metadata", index));
                }

                var obj = new PlexTvShow();
                LoggingHelpers.RecordGeneralEntry(@"Content Parse Started");
                LoggingHelpers.RecordGeneralEntry(@"Grabbing Titles");

                var metadata = XmlMetadataContent.GetEpisodeMetadata(index);

                LoggingHelpers.RecordGeneralEntry(@"Checking XML validity");
                if (Methods.PlexXmlValid(metadata.Xml))
                {
                    LoggingHelpers.RecordGeneralEntry(@"XML Valid");

                    var dlInfo = DownloadInfoGatherers.GetContentDownloadInfo(metadata.Xml);

                    if (dlInfo != null)
                    {
                        LoggingHelpers.RecordGeneralEntry(@"Assembling Object");

                        obj.ApiUri       = metadata.ApiUri;
                        obj.ContentGenre = XmlMetadataStrings.GetContentGenre(metadata.Xml);

                        var s = XmlMetadataIntegers.GetParentIndex(metadata.Xml);
                        var e = XmlMetadataIntegers.GetIndex(metadata.Xml);

                        obj.Season            = XmlMetadataStrings.GetParentTitle(metadata.Xml);
                        obj.EpisodesInSeason  = DataProvider.EpisodesProvider.GetRawTable().Rows.Count;
                        obj.EpisodeNumber     = e > 0 ? e : 1; //episode numbers start at 1, not 0; enforce this.
                        obj.SeasonNumber      = s > 0 ? s : 1; //season numbers start at 1, not 0; enforce this.
                        obj.TvShowName        = XmlMetadataStrings.GetGrandparentTitle(metadata.Xml);
                        obj.StreamResolution  = XmlMetadataObjects.GetContentResolution(metadata.Xml);
                        obj.Actors            = XmlMetadataObjects.GetActorsFromMetadata(metadata.Xml);
                        obj.StreamIndex       = index;
                        obj.Synopsis          = XmlMetadataStrings.GetContentSynopsis(metadata.Xml);
                        obj.StreamInformation = dlInfo;

                        //apply the raw metadata to the object (it won't get serialised)
                        obj.RawMetadata = metadata.Xml;

                        //This works, but it shouldn't - I feel like it shouldn't.

                        //Check if the season information is valid (must have a number).
                        //Sometimes, seasons don't get named correctly. For example, 'Specials' rather than 'Season 1'.
                        //This is one method of validation for a correctly named 'Season' of a show.
                        //In addition, if the verification method fails for a season number check, it returns -1 (season numbers start at 1+),
                        //so it makes sense to check for above zero season indices as well.
                        var valid    = obj.Season.ToLower().StartsWith(@"season") && s > 0;
                        var notation = valid ? obj.Notation : obj.Season; //apply default notation only if it's a valid season name, otherwise just use the name itself.
                        var fileName = $"{obj.TvShowName} - {notation} - {obj.StreamInformation.ContentTitle}.{dlInfo.Container}";

                        //override the filename generated above with the correct Plex formatting generated by the PlexTvShow object.
                        obj.StreamInformation.FileName = fileName.ToClean();
                    }
                    else
                    {
                        UIMessages.Error(
                            @"Failed to get contextual information; an unknown error occurred. Check the exception log for more information.",
                            @"Data Error");
                        LoggingHelpers.RecordException(
                            "DownloadInfo invalid. This may be an internal error; please report this issue on GitHub.",
                            "ContextDownloadInfoNull");
                        LoggingHelpers.RecordGeneralEntry(
                            "DownloadInfo is invalid (no stream contextual information)");
                    }
                }
                else
                {
                    LoggingHelpers.RecordGeneralEntry("XML Invalid");
                }

                LoggingHelpers.RecordGeneralEntry("Returned assembled TV object");
                return(obj);
            }
            catch (ThreadAbortException)
            {
                //literally nothing; this gets raised when a cancellation happens.
                return(null);
            }
            catch (Exception ex)
            {
                UIMessages.Error("Content metadata error:\n\n" + ex, @"Data Error");
                LoggingHelpers.RecordException(ex.Message, "TVObjectError");
                return(null);
            }
        }
예제 #11
0
        //MUSIC OBJECT BUILDER
        public static PlexMusic GetMusicObjectFromIndex(int index, bool waitWindow = true)
        {
            try
            {
                if (waitWindow)
                {
                    return((PlexMusic)WaitWindow.WaitWindow.Show(GetMusicObjectFromIndex_Callback, @"Getting metadata", index));
                }

                var obj = new PlexMusic();
                LoggingHelpers.RecordGeneralEntry(@"Content Parse Started");
                LoggingHelpers.RecordGeneralEntry(@"Grabbing Titles");
                var metadata = XmlMetadataContent.GetTrackMetadata(index);

                LoggingHelpers.RecordGeneralEntry(@"Checking XML validity");
                if (Methods.PlexXmlValid(metadata.Xml))
                {
                    LoggingHelpers.RecordGeneralEntry(@"XML Valid");

                    //UIMessages.Info(ObjectProvider.CurrentContentType.ToString());

                    var dlInfo = DownloadInfoGatherers.GetContentDownloadInfo(metadata.Xml);

                    if (dlInfo != null)
                    {
                        LoggingHelpers.RecordGeneralEntry(@"Assembling Object");

                        obj.ApiUri            = metadata.ApiUri;
                        obj.ContentGenre      = XmlMetadataStrings.GetContentGenre(metadata.Xml);
                        obj.StreamInformation = dlInfo;
                        obj.StreamResolution  = new Resolution();       //audio doesn't have video-type resolution
                        obj.Actors            = new List <PlexActor>(); //Plex audio does not contain the "<Role>" tag
                        obj.StreamIndex       = index;
                        obj.Album             = XmlMetadataStrings.GetParentTitle(metadata.Xml);
                        obj.Artist            = XmlMetadataStrings.GetGrandparentTitle(metadata.Xml);
                        obj.Synopsis          = "Auditory Content"; //Plex audio does not contain the "summary" attribute

                        //apply the raw metadata to the object (it won't get serialised)
                        obj.RawMetadata = metadata.Xml;
                    }
                    else
                    {
                        UIMessages.Error(
                            @"Failed to get contextual information; an unknown error occurred. Check the exception log for more information.",
                            @"Data Error");
                        LoggingHelpers.RecordException(
                            @"DownloadInfo invalid. This may be an internal error; please report this issue on GitHub.",
                            @"ContextDownloadInfoNull");
                        LoggingHelpers.RecordGeneralEntry("DownloadInfo is invalid (no stream contextual information)");
                    }
                }
                else
                {
                    LoggingHelpers.RecordGeneralEntry("XML Invalid");
                }

                LoggingHelpers.RecordGeneralEntry("Returned assembled Music object");
                return(obj);
            }
            catch (ThreadAbortException)
            {
                //literally nothing; this gets raised when a cancellation happens.
                return(null);
            }
            catch (Exception ex)
            {
                UIMessages.Error("Content metadata error:\n\n" + ex, @"Data Error");
                LoggingHelpers.RecordException(ex.Message, @"MusicObjectError");
                return(null);
            }
        }
예제 #12
0
        //MOVIE OBJECT BUILDER
        public static PlexMovie GetMovieObjectFromIndex(int index, bool waitWindow = true)
        {
            try
            {
                if (waitWindow)
                {
                    return((PlexMovie)WaitWindow.WaitWindow.Show(GetMovieObjectFromIndex_Callback, @"Getting metadata", index));
                }

                var obj = new PlexMovie();
                LoggingHelpers.RecordGeneralEntry(@"Content Parse Started");
                LoggingHelpers.RecordGeneralEntry(@"Grabbing Titles");
                var metadata = XmlMetadataContent.GetContentMetadata(index);

                LoggingHelpers.RecordGeneralEntry(@"Checking XML validity");
                if (Methods.PlexXmlValid(metadata.Xml))
                {
                    LoggingHelpers.RecordGeneralEntry(@"XML Valid");

                    var dlInfo = DownloadInfoGatherers.GetContentDownloadInfo(metadata.Xml);

                    if (dlInfo != null)
                    {
                        LoggingHelpers.RecordGeneralEntry(@"Assembling Object");

                        obj.ApiUri            = metadata.ApiUri;
                        obj.ContentGenre      = XmlMetadataStrings.GetContentGenre(metadata.Xml);
                        obj.StreamInformation = dlInfo;
                        obj.StreamResolution  = XmlMetadataObjects.GetContentResolution(metadata.Xml);
                        obj.Actors            = XmlMetadataObjects.GetActorsFromMetadata(metadata.Xml);
                        obj.StreamIndex       = index;
                        obj.Synopsis          = XmlMetadataStrings.GetContentSynopsis(metadata.Xml);

                        //apply the raw metadata to the object (it won't get serialised)
                        obj.RawMetadata = metadata.Xml;
                    }
                    else
                    {
                        UIMessages.Error(
                            @"Failed to get contextual information; an unknown error occurred. Check the exception log for more information.",
                            @"Data Error");
                        LoggingHelpers.RecordException(
                            @"DownloadInfo invalid. This may be an internal error; please report this issue on GitHub.",
                            @"ContextDownloadInfoNull");
                        LoggingHelpers.RecordGeneralEntry("DownloadInfo is invalid (no stream contextual information)");
                    }
                }
                else
                {
                    LoggingHelpers.RecordGeneralEntry("XML Invalid");
                }

                LoggingHelpers.RecordGeneralEntry("Returned assembled Movie object");
                return(obj);
            }
            catch (ThreadAbortException)
            {
                //literally nothing; this gets raised when a cancellation happens.
                return(null);
            }
            catch (Exception ex)
            {
                UIMessages.Error("Content metadata error:\n\n" + ex, @"Data Error");
                LoggingHelpers.RecordException(ex.Message, @"MovieObjectError");
                return(null);
            }
        }
예제 #13
0
        public static void LaunchVlc(PlexObject stream)
        {
            try
            {
                if (!Methods.StreamAdultContentCheck(stream))
                {
                    return;
                }

                var p = new Process();
                var c = new StringVariableController();

                var vlc = ObjectProvider.Settings.Player.VlcMediaPlayerPath;
                var arg = ObjectProvider.Settings.Player.VlcMediaPlayerArgs;

                if (VlcInstalled())
                {
                    c.Input = arg;

                    c.Variables = c.BuildFromDlInfo(stream.StreamInformation);
                    arg         = c.YieldString();

                    p.StartInfo.FileName  = vlc;
                    p.StartInfo.Arguments = arg;
                    p.Start();
                    LoggingHelpers.RecordGeneralEntry("Started streaming " + stream.StreamInformation.ContentTitle +
                                                      " (VLC)");
                }
                else
                {
                    UIMessages.Error(@"PlexDL could not find VLC Media Player. Please locate VLC and then try again.");

                    var ofd = new OpenFileDialog
                    {
                        Filter      = @"VLC Executable|vlc.exe",
                        Title       = @"Locate VLC Media Player",
                        Multiselect = false
                    };

                    if (ofd.ShowDialog() != DialogResult.OK)
                    {
                        return;
                    }

                    var fileName = ofd.FileName;
                    var baseName = Path.GetFileName(fileName).ToLower();

                    if (baseName == "vlc.exe")
                    {
                        //apply the newly-located vlc.exe to global settings for persistence
                        ObjectProvider.Settings.Player.VlcMediaPlayerPath = fileName;

                        //finally, launch VLC itself.
                        LaunchVlc(stream);
                    }
                    else
                    {
                        UIMessages.Error(@"Invalid VLC Media Player executable name");
                    }
                }
            }
            catch (Exception ex)
            {
                UIMessages.Error("Error occurred whilst trying to launch VLC\n\n" + ex, @"Launch Error");
                LoggingHelpers.RecordException(ex.Message, "VLCLaunchError");
            }
        }
예제 #14
0
        public static StreamInfo GetContentDownloadInfo(XmlDocument xml)
        {
            try
            {
                if (!Methods.PlexXmlValid(xml))
                {
                    return(new StreamInfo());
                }

                var obj = new StreamInfo();

                LoggingHelpers.RecordGeneralEntry("Grabbing DownloadInfo object");
                var sections = new DataSet();
                sections.ReadXml(new XmlNodeReader(xml));

                var part = sections.Tables["Part"];

                DataRow dlRow;

                //UIMessages.Info(ObjectProvider.CurrentContentType.ToString());

                switch (ObjectProvider.CurrentContentType)
                {
                case ContentType.Movies:
                    dlRow = sections.Tables["Video"].Rows[0];
                    break;

                case ContentType.TvShows:
                    dlRow = sections.Tables["Video"].Rows[0];
                    break;

                case ContentType.Music:
                    dlRow = sections.Tables["Track"].Rows[0];
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (dlRow == null)
                {
                    return(new StreamInfo());
                }

                var title = dlRow["title"].ToString();
                if (title.Length > ObjectProvider.Settings.Generic.DefaultStringLength)
                {
                    title = title.Substring(0, ObjectProvider.Settings.Generic.DefaultStringLength);
                }

                var thumb            = dlRow["thumb"].ToString();
                var thumbnailFullUri = "";

                if (!string.IsNullOrEmpty(thumb))
                {
                    var baseUri = Strings.GetBaseUri(false).TrimEnd('/');
                    thumbnailFullUri = baseUri + thumb + "?X-Plex-Token=" + Strings.GetToken();
                }

                var partRow = part.Rows[0];

                var filePart  = "";
                var container = "";

                if (partRow["key"] != null)
                {
                    filePart = partRow["key"].ToString();
                }

                if (partRow["container"] != null)
                {
                    container = partRow["container"].ToString();
                }
                var byteLength = Convert.ToInt64(partRow["size"]);

                var contentDuration = Convert.ToInt32(partRow["duration"]);
                var fileName        = (title + "." + container).ToClean();

                //The PMS (Plex Media Server) will return the file as an octet-stream (download) if we set
                //the GET parameter 'download' to '1' and a normal MP4 stream if we set it to '0'.
                obj.Links.View =
                    Strings.GetBaseUri(false).TrimEnd('/') + filePart + "?download=0&X-Plex-Token=" +
                    Strings.GetToken();
                obj.Links.Download =
                    Strings.GetBaseUri(false).TrimEnd('/') + filePart + "?download=1&X-Plex-Token=" +
                    Strings.GetToken();
                obj.Container           = container;
                obj.ByteLength          = byteLength;
                obj.ContentDuration     = contentDuration;
                obj.FileName            = fileName;
                obj.ContentTitle        = title;
                obj.ContentThumbnailUri = thumbnailFullUri;

                return(obj);
            }
            catch (Exception ex)
            {
                LoggingHelpers.RecordException(ex.Message, "DownloadXmlError");
                UIMessages.Error(ex.ToString());
                return(null);
            }
        }