Marked video as watched

I am a new fan of Plex but i only use Plex when i am watching movies and series on my xbox. Most of the time however i still use VLC on my PC.

This means that OnDeck and unwatched status is never accurate and i am now planing on fixing this.

 

I had this idea that when i start start a movie (ex mkv file) on my computer a script will first run, check if that movie exists on my Plex server and if so, mark it as watch. Then it will start the movie with VLC. This will make sure that when i watch a movie on my PC with VLC it will be marked as watched on Plex. So when i run plex on my xbox the status will always be accurate. 

 

1. User double clicks on a video (ex .mkv file)

2. custom script run

2a check if video exists in Plex by file path or name

2b if movie exists mark video as watched, else just ignore

3 start vlc with the video as input

 

My problem however is that i am unable to find the API calls i need to make to fetch all movies on plex (2a) and how the then mark that movie as watched (2b)

 

Appreciate any kind of hints or tips to help me solve my problem.

For a start, there's AFAIK no API calls for the search.....

So you'll have to first get a list of the sections, and then grap the contents from the desired one.

Then search the output, and after that, toggle the watch status

All in all.....A huge task, for not wanting to use a Plex player on your laptop....So......Why not use that instead?

/T

I have no problems doing that, it should not take a long time to fix aslong as i find some kind of documentation for each api call i need to make.

Let's start slowly here:

To get the sections, you'll have to send a get to your PMS, looking like:

http://PMS:32400/library/sections

From the respond, grap the key from the relevant section

Then send a get looking like:

http://PMS:32400/library/sections/key/all

This should give you a list of all movies from that section

So in there, locate the key from the media you want

When you got that up running, then return here

https://support.plex.tv/hc/en-us/articles/201638786-Plex-Media-Server-URL-Commands

/T

And forgot....To mark a media as watched, send a get with the following url:

http://PMS:32400/:/scrobble?key=MEDIAKEY&identifier=com.plexapp.plugins.library

Script is done. 

Thanks for your help with the API. Had some problems finding out what key to use. With chrome and developer tools i could see the id that the plex web app used and figured out i were going to use ratingKey.

param($videoPath)
 
$plexBaseUrl = "http://192.168.1.75:32400"
$vlc = "C:\Program Files (x86)\VideoLAN\VLC\vlc.exe"
 
#Fetching video from NAS, so need to convert network path to local server path.
$serverPath = $videoPath.Replace("\\DS415", "/volume1")
$serverPath = $serverPath.Replace("\", "/")
 
$plexGetSessionsUrl = "$plexBaseUrl/library/sections"
 
function Mark-VideoAsWatched($videoPath)
{
    $plexGetSessionsUrl = "$plexBaseUrl/library/sections"
    $responce = Invoke-WebRequest -Uri $plexGetSessionsUrl
    $sessions = [xml] $responce.Content
    $keys = $sessions.MediaContainer.Directory | select -ExpandProperty key
    
    foreach($item in $keys)
    {
        $plexGetVideosInSectionUrl = "$plexBaseUrl/library/sections/$item/all"
        $responce = Invoke-WebRequest -Uri $plexGetVideosInSectionUrl
        $vidoesInSession = [xml] $responce.Content
        $vidoes = $vidoesInSession.MediaContainer.Video
 
        foreach($video in $vidoes)
        {
            if($video.Media.Part.File -eq $videoPath)
            {
                $key = $video.ratingKey
                $plexMarkAsWatchedUrl = "$plexBaseUrl/:/scrobble?key=$key&identifier=com.plexapp.plugins.library"
                $responce = Invoke-WebRequest -Uri $plexMarkAsWatchedUrl
                return;
            }
        }
    }
}
 
Mark-VideoAsWatched $serverPath
. $vlc $videoPath
 
I were not able to open a movie with a PowerShell script file so i wrapped it in a C# console.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace MarkedMovieAsWatchAndRunVLC
{
    class Program
    {
        static void Main(string[] args)
        {
            string scriptFile = @"\\DS415\Work\Privat\Scripts\MarkedMovieAsWatchAndRunVLC.ps1";
            string arguments = string.Format("-windowstyle hidden -ExecutionPolicy Bypass -File {0} \"{1}\"", scriptFile, args[0]);
 
            Process proc = new Process();
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            proc.StartInfo.FileName = "PowerShell.exe";
            proc.StartInfo.Arguments = arguments;
            proc.StartInfo.RedirectStandardError = false;
            proc.StartInfo.RedirectStandardOutput = false;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.Start();
        }
    }
}
 
It is working, but it is opening up new windows of VLC and not reusing the existing one. This needs to be fixed.

Nice work

My script only works on movies. When i want to get episodes $plexBaseUrl/library/sections/$item/all only lists the name of the tv serie.

I guess i need to fetch all episodes for a specific serie and maybe for each season, but my problem is i am unsure what API to call.

Would appropriate more hints :)

when you get the section list, there's a type with it as well, indicating if it's a TV-Show section or not

Then when grapping the section/all, you list the names of the shows...

Then use this call:

http://PMS:32400/library/metadata//children

When looking at the result from that, you'll get a list of directories, one for each season, and they each have a new ratingkey

And calling that, would list the episodes from that season

/T

Found that i could use

/allLeaves instead of /all that command will drill down and get all information

Updated the script and also made sure i run VLC before i update status since it could take some seconds to update.

param($videoPath)
 
$plexBaseUrl = "http://192.168.1.75:32400"
$vlc = "C:\Program Files (x86)\VideoLAN\VLC\vlc.exe"
 
#Fetching video from NAS, so need to convert network path to local server path.
$serverPath = $videoPath.Replace("\\DS415", "/volume1")
$serverPath = $serverPath.Replace("\", "/")
 
function Mark-VideoAsWatched($videoPath)
{
    $plexGetSessionsUrl = "$plexBaseUrl/library/sections"
    $responce = Invoke-WebRequest -Uri $plexGetSessionsUrl
    $sessions = [xml] $responce.Content
    $keys = $sessions.MediaContainer.Directory | select -ExpandProperty key
    
    foreach($item in $keys)
    {
        $plexGetVideosInSectionUrl = "$plexBaseUrl/library/sections/$item/allLeaves"
        $responce = Invoke-WebRequest -Uri $plexGetVideosInSectionUrl
        $vidoesInSession = [xml] $responce.Content
        $vidoes = $vidoesInSession.MediaContainer.Video
 
        #if($videos -eq $null)
        #    $videos = 
 
        foreach($video in $vidoes)
        {
            if($video.Media.Part.File -eq $videoPath)
            {
                $key = $video.ratingKey
                $plexMarkAsWatchedUrl = "$plexBaseUrl/:/scrobble?key=$key&identifier=com.plexapp.plugins.library"
                $responce = Invoke-WebRequest -Uri $plexMarkAsWatchedUrl
                return;
            }
        }
    }
}
 
. $vlc $videoPath
Mark-VideoAsWatched $serverPath

Found that i could use

/allLeaves instead of /all that command will drill down and get all information

Wow.....That's something I didn't knew  :rolleyes:

/Tommy

And adding here....Take care with a huge sized TV-Section....might drain the PMS, if going with /allLeaves

/T

Nice work.  I am going to see if I can somehow incorporate this into one of my scripts.  Once I figure out what all this means.   :blink:  :blink:  :blink:

Nice work.  I am going to see if I can somehow incorporate this into one of my scripts.  Once I figure out what all this means.   :blink:  :blink:  :blink:

Feel free to ask questions if you want me to explain something.

Thanks, I figured out your script.  I do not understand the C# part, but that's not important.  I liked your idea but I decided to go another way.  I chose to use the SQLite command line tool and look into the database instead of calling the xml file.  Only takes a split second to get a result.  Using the XML seems like it could take some time if you have a lot of media.

Thanks, I figured out your script.  I do not understand the C# part, but that's not important.  I liked your idea but I decided to go another way.  I chose to use the SQLite command line tool and look into the database instead of calling the xml file.  Only takes a split second to get a result.  Using the XML seems like it could take some time if you have a lot of media.

True, but ....

Accessing the database is something that should not be taken lightly, and besides that, and as already stated, sadly not every platform allows a direct access to the database, and accessing it over the LAN/WAN is NOT recommended with SQLite

/T

Definitely agree, messing with the database is not for beginners.  I have more experience with databases than with other coding (except for MortScript) so I actually feel safer dealing with SQL than anything else.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.