Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Watched status is always taking precedence over Unwatched #1080

Open
2 tasks done
solid-pixel opened this issue Oct 1, 2022 · 23 comments
Open
2 tasks done

Watched status is always taking precedence over Unwatched #1080

solid-pixel opened this issue Oct 1, 2022 · 23 comments
Labels
enhancement New feature or request

Comments

@solid-pixel
Copy link

solid-pixel commented Oct 1, 2022

Confirmation

  • I have read the README.md on the project homepage
  • I have checked if identical issue already exists

The problem

Hello! I'm really sorry for opening two issues in a day 🙏

I'm not sure if this is the intended behavior, but I can't find a way to remove the watched status in Trakt when marking something as Unwatched in Plex.

Once you look at the steps to reproduce, you'll see how I essentially have no way of marking something as Unwatched, unless I do it on both Trakt and Plex before running the script.

The episode in question is tmdb:3010853:Episode:190:Family-Guy-s20e01

Config

cache:
  path: $PTS_CACHE_DIR/trakt_cache

excluded-libraries:
  - Private
  - Family Holidays
  - X0R

config:
  dotenv_override: true

plex:
  timeout: 30

logging:
  append: true
  console_time: false
  debug: true
  filename: plextraktsync.log

sync:
  plex_to_trakt:
    collection: true
    ratings: true
    watched_status: true
    watchlist: true
  trakt_to_plex:
    liked_lists: true
    ratings: true
    watched_status: true
    watchlist: true
    watchlist_as_playlist: false

watch:
  add_collection: false
  remove_collection: false
  scrobble_threshold: 80
  username_filter: true

xbmc-providers:
  movies: imdb
  shows: tvdb

# vim:ts=2:sw=2:et

Log

plextraktsync.log


Thanks!

Error trace / logs

attached as it was too long.

Expected behavior

Stuff on Trakt should be marked as Unwatched when it's marked as such in Plex, and/or vice-versa.

Steps to reproduce the behavior

Scenario 1 - Plex > Trakt

  1. Have something that's been watched already
  2. Mark it as Unwatched only in Plex
  3. Run plextraktsync.sh
  4. The script will pull the status from Trakt and mark the episode in Plex as Watched again, rather than marking it as Unwatched in Trakt.

Scenario 2 - Trakt > Plex

  1. Have something that's been watched already
  2. Mark it as Unwatched only in Trakt
  3. Run plextraktsync.sh
  4. The script will pull the status from Plex and mark the episode in Trakt as Watched again, rather than marking it as Unwatched in Trakt.

Inspect of problematic items

No response

Workarounds

No response

Install method

git clone

Version

0.21.5

Python Version

3.7.3

Operating System and Version

Debian 10

@simonc56
Copy link
Collaborator

simonc56 commented Oct 1, 2022

The origin status of a video is unwatched.
The natural human behavior is to watch videos, not to unwatch videos. And the script works accordingly.
When a watched status is different between Plex and Trakt, the watched status takes precedence because the user is supposed to watch videos.

Stuff on Trakt should be marked as Unwatched when it's marked as such in Plex, and/or vice-versa

So when you watch a Plex movie, you want the script to mark it as unwatched ? That makes no sense.

@solid-pixel
Copy link
Author

I really appreciate all you guys do to maintain this script, but I'm being as polite and thorough as possible, do I really deserve this kind of answer?

What's the "mark as unwatched" option even for then, if human beings are never supposed to unwatch something?

There are not-so-rare cases in which the user might want to unwatch something:

  • They fell asleep, the episodes kept running - they will now need to mark these as unwatched
  • They want to re-watch a series they've watched some time ago, and unwatch it all in order to keep track of the new watch status
  • Debugging/Testing purposes
  • I'm sure there's more or they wouldn't have built an option for that

If there's a technical limitation behind this, then you are free to be open about it. Technology is meant to help where humans fail, so I wouldn't use human behavior as an explanation for this.

So when you watch a Plex movie, you want the script to mark it as unwatched ? That makes no sense.

Please read my issue again because it's absolutely not what I said.
What I wanted is the other end to update accordingly whenever I mark either Plex or Trakt as Watched or Unwatched.

Thanks anyway

@simonc56
Copy link
Collaborator

simonc56 commented Oct 1, 2022

What I wanted is the other end to update accordingly whenever I mark either Plex or Trakt as Watched or Unwatched.

There is no "unwatched at 7:35 01/10/2022" in Plex or Trakt history.
History only keeps "watched" events.

Can you explain your expected workflow in detail ?

@solid-pixel
Copy link
Author

I'll try to be thorough, but let me know if you need more details please.

So, let's say I have an episode that's marked as Played on both Trakt and Plex.
Then, for some reason, I changed my mind, and I want this episode to be marked as Unplayed.

Use case A, marking as Unplayed from Plex.

I open Plex and mark it as Unplayed by clicking on this:

image

This is all good on the Plex side, until your script's cronjob starts.
Once the sync starts, Plex will mark this episode as Played again, because it's pulling this info from Trakt, where the episode was still marked as Played.

This makes it impossible to keep an episode as Unplayed, because the script will always end up changing it to Played.

So, what I'd expect here, is that when I mark it as Unplayed in Plex, either the sync or watch script mark it as Unplayed in Trakt too.

Use case B, marking as Unplayed from Trakt.

I open Trakt and mark it as Unplayed:
image

The episode is now marked as Unplayed in Trakt:

image

This is all good on Trakt, until your script's cronjob starts.
Once the sync starts, Trakt will mark this episode as Played again, because it's pulling this info from Plex, where the episode was still marked as Played.

This also makes it impossible to keep an episode as Unplayed, because the script will always end up changing it to Played.

So, what I'd expect here, is that when I mark it as Unplayed in Trakt, either the sync or watch script mark it as Unplayed in Plex too.


Basically, like you said earlier, every time the sync runs, the Played status always takes precedence, no matter what side I mark as Unplayed from. The only way to avoid this and let the Unplayed status stick when the script runs, is to log into both platforms, and mark it as Unplayed on both, which is a bit of a pain especially for my family members who know nothing about Trakt and this magic fuckery we nerds run behind it :P

Thank you!

@simonc56
Copy link
Collaborator

simonc56 commented Oct 1, 2022

I was asking the detailed workflow from the script point of view.

Plex

So, what I'd expect here, is that when I mark it as Unplayed in Plex, either the sync or watch script mark it as Unplayed in Trakt too.

The sync cannot read a unwatched event in Plex because, as I said, there is no such thing in Plex history. How can we know a Plex movie has been unwatched ?

For watch command, maybe the mark as unwatched event can be read, I don't know. Note that we had issue with reading manually set "Mark as watched" and had to remove this feature.

Trakt

So, what I'd expect here, is that when I mark it as Unplayed in Trakt, either the sync or watch script mark it as Unplayed in Plex too.

Like I said, there is no history of unwatched event in Trakt. How can we know a Trakt movie has been unwatched ?

@solid-pixel
Copy link
Author

Yeah, I didn't know there was no unwatched history in Trakt until you mentioned it. I've always used Jellyfin and Kodi and unless I'm mistaken, their Trakt plugins worked well in this regard. I've never checked if a manually triggered unwatched status updated from one end to the other, but at least they didn't overwrite my local unwatched status when the sync ran. This is mostly what made me assume it'd be possible.

Another thing that made me assume it'd be possible was the fact that watch seems to be able to track it, because as soon as I click Mark as Unplayed in Plex, it immediately triggers this in the terminal:

image

So, somehow, it does seem possible to know when something is being marked as Unwatched, at least on Plex's end?

@simonc56
Copy link
Collaborator

simonc56 commented Oct 1, 2022

An other solution would be to overwrite watched status with a one-way watched_status sync in config file.

But none of these can answer the first post request.

Also, you can edit the title to reflect what is asked in first post (scenario 2).

@solid-pixel solid-pixel changed the title Can't remove Watched status from Trakt Trakt's Unwatched status not syncing to Plex Oct 2, 2022
@solid-pixel
Copy link
Author

fair point, I've changed it, although the issue is not specific to Scenario 2, but to both. It's more like that "Watched status is always taking precedence over Unwatched" - let me know if you'd like me to change it :)

And yeah, I thought about your solution too before posting, but it would make it kinda hard to use Trakt as a main hub for different clients other than this Plex instance :(

@simonc56

This comment was marked as off-topic.

@solid-pixel solid-pixel changed the title Trakt's Unwatched status not syncing to Plex Watched status is always taking precedence over Unwatched Oct 2, 2022
@solid-pixel

This comment was marked as off-topic.

@simonc56

This comment was marked as off-topic.

@simonc56 simonc56 added the enhancement New feature or request label Oct 29, 2022
@thedinz
Copy link

thedinz commented Oct 31, 2022

Yes I have been dealing with this as well, I do not have much more to offer except I'd like to see this be possible. I am trying to mark things as unwatched in plex which works. Once PTS runs its marks it back to watched. It would be nice if somehow when PTS runs its see's that a more recent timestamp of "unwatched" for X and compares it's against trakt sees the older timestamp of "watched" and updates accordingly.

@pterisaur
Copy link

I'm having a similar issue — marking episodes as unwatched in both Plex and Trakt isn't working, as the script will eventually mark those episodes as watched again. It doesn't seem to happen right away — sometimes it's a week or so later — I'm wondering if this is due to the size of our library?

Anyway, is there a way to "officially" indicate something isn't watched, so this won't happen? Maybe it's pulling from somewhere other than the current Plex/Trakt status, like a cache?

@douginoz
Copy link

douginoz commented Feb 4, 2023

My use case is, what I'd think to be the most obvious need for this ability.
I want to re-watch a TV show I haven't watched in a while. To do so I need to mark the entire series as unwatched so that Plex correctly displays the next show to watch in the sequence. (Otherwise, Plex assumes that there are no more unwatched episodes).

So the only way to re-watch any TV show that you've watched before is to set it to unwatched. But PTS messes that up.

I would think that most people want to re-watch a show they've watched before, and thus need to reset it's watched status.

Resetting the watched status of a TV series has got to be a completely normal use case. PTS destroys this and the only workaround is to stop using it, or like the op said, go into trakt and set the status manually there, which negates using PTS.

I understand that there's no flag in plex to handle this easily but one way would be to provide a runtime option that forces the local plex server's watched status to override the trakt one.

@simonc56
Copy link
Collaborator

simonc56 commented Feb 4, 2023

Resetting the watched status of a TV series has got to be a completely normal use case. PTS destroys this and the only workaround is to stop using it, or like the op said, go into trakt and set the status manually there, which negates using PTS.

You need to use the Trakt VIP feature Reset show progress.
PTS reads and respects the progress reset of shows in Trakt.
Feature discussed here.

Plex episodes marked as unwatched after a reset :

def reset_show(self, show: Show, reset_date: datetime):
reset_count = 0
for ep in show.watched():
ep_seen_date = PlexLibraryItem(ep).seen_date.replace(tzinfo=None)
if ep_seen_date < reset_date:
self.mark_unwatched(ep)
reset_count += 1
else:
logger.debug(
f"{show.title} {ep.seasonEpisode} watched at {ep.lastViewedAt} after reset date {reset_date}")
logger.debug(f"{show.title}: {reset_count} Plex episode(s) marked as unwatched.")

@thedinz
Copy link

thedinz commented Feb 10, 2023

I found a very simple work around that doesn't delete any watched or require you go get VIP.

Simply add the show you want to rewatch to your plex watchlist, problem solved, from there just go to watchlist section of plex and it will be tracking your current watches of the show without messing with trakt

@JeremyKennedy
Copy link

JeremyKennedy commented Apr 24, 2023

I have several items that have mistakenly been marked as watched in Plex. This has been synced to Trakt. Now, I try to mark unwatched in Plex, but the watched status in Trakt gets synced back to Plex. I would love a one-way sync option, where if it is unwatched in Plex and watched in Trakt, it would be updated in Trakt (or vice-versa). I imagine adding this as an option this would solve this issue.

For now I suppose I have to mark as unwatched in both Plex and Trakt.

@glensc
Copy link
Collaborator

glensc commented Apr 25, 2023

the one-way sync is there. just turn off the "other" leg:

@KoenBoone
Copy link

KoenBoone commented Apr 28, 2023

I'm sure a lot of people are happy with one way sync, but there's also a lot of people and use cases where a real sync would be much better.
this, and some watchlist sync issues, could be solved if this great script, which I appreciate a lot, was changed a bit and kept a log or intermediary db of the status itself with timestamps.
On the first run, it adds the current timestamp if no timestamp is provided by either. On the second run, it can use the timestamp in its own log/db to determine what to do.

rough flow:

fields:
A. Media ID
B. Plex timestamp watched
C. seen on Plex sync?
D. Trakt timestamp watched
E. seen on Trakt sync?
F. result

Only on the first run one might find issues that need correcting.
You could ask the user on a first run, which of the two would be master in case of conflict and adjust the logic below accordingly. (only during first run!)

first run:
0. on every run start by setting the fields C and E as false, and F as null or '', and if the db is empty, this is the first run, keep a flag in memory for that: firstrun=true, otherwise firstrun=false

  1. Plex => Trakt => retrieve complete watchlist

  2. Compare list with own db

  3. if not found in own db, add, and put plex timestamp (if no timestamp is available, leave empty for now) in field B and set C to true.

  4. if found in own db, and it was unwatched for Plex, do the same as in 1. Leave timestamp empty for now if it is not provided.

  5. Trakt => Plex => retrieve complete watchlist

  6. compare list with own db

  7. if not found in own db, add, and put Trakt timestamp (if no timestamp is available, leave empty for now) in field D and set E to true.

  8. if found in own db, and it was unwatched on Trakt, do the same as in 7. Leave timestamp emtpy for now if it is not provided

  9. traverse through own db, create a single timestamp and put that in B if C is true and there is no timestamp yet, and in D if E is true and there is no timestamp yet.

  10. for each media check the status and do the following:
    10a. any media that has false for both C and E, we know must be set as unwatched in both.

    • if firstrun=false we set F as 'unwatched' and any filled in timestamp in B or D to null
    • on the first run, naturally the above will not occur as that media will simply not be there
      10b. any media that has both C and E as true, put the previously created timestamp in B and D, set F as 'watched'.
      10c. any media that has C or E as true, compare the timestamps.
    • In case of firstrun=true, set F as 'watched' (unless the user decided on who should be master on first run, then check C or E against that to decide to set 'watched or 'unwatched'. and fill in any emtpy timestamp with the previously created one.
    • on later runs, the latest timestamp wins, set F as 'watched' or 'unwatched' accordingly.
  11. for all the media where C is true and F is 'unwatched', update that media on Plex accordingly

  12. for all the media where E is true and F is 'unwatched', update that media on Trakt accordingly

  13. for all media where F is 'watched', update that media on Plex and Trakt accdordingly

  14. the user can see the results, described in F in the log or db if wanted.

Just a quick thought, but might need an overhaul of the existing code? :-)
Sadly, i'm no good in Python :-(

@glensc
Copy link
Collaborator

glensc commented Apr 29, 2023

So, having this done without local database is not possible.

Here's closed PR attempting to add local database read support (but different purpose):

maybe a good start.

sqlite is already independence due requests cache, so the local cache could be sqlite based, but still need some way to ensure database migrations, i.e how to ensure schema in database.

@glensc
Copy link
Collaborator

glensc commented Apr 29, 2023

So, having this done without local database is not possible.

Here's closed PR attempting to add local database read support (but different purpose):

maybe a good start.

sqlite is already in dependency due requests cache, so the local cache could be sqlite based, but still need some way to ensure database migrations, i.e how to ensure schema in database.

@KoenBoone
Copy link

So, having this done without local database is not possible.

Here's closed PR attempting to add local database read support (but different purpose):

maybe a good start.

sqlite is already independence due requests cache, so the local cache could be sqlite based, but still need some way to ensure database migrations, i.e how to ensure schema in database.

i think so, without receiving dates from both, you need a way to save/create your own and keep track of them.
My first choice would indeed be sqlite.
One might also find a speed improvement for large libraries, but I haven't looked enough at the api's for both to know if that would be the case.
I'm out for the day, but maybe i'll have a look at both and try to conjure something up as a test, it won't be in python because that's not my area, but it should atleast give me an idea of speed and if it is practical.

@JonnyWong16
Copy link
Contributor

JonnyWong16 commented Jul 22, 2023

As already discussed above, there is no way to determine is something got marked as "unwatched" on a Plex server because it wipes out all previous watch data. i.e. Marking something "unwatched" looks identical to "never watched", thus the sync from Trakt -> Plex happens.

However, you can infer the "mark unwatched" state using Plex's cloud watched status sync. The userState keeps the lastViewedAt date while resetting the viewCount to 0.

https://python-plexapi.readthedocs.io/en/stable/modules/myplex.html#plexapi.myplex.MyPlexAccount.userState

user_state = account.userState(item)

if user_state.viewCount == 0:
    if user_state.lastViewedAt is None:
        # item has never been watched
    else:
        # item was previously watched and marked as unwatched
elif user_state.viewCount > 0:
    # item is watched

Going the other way (marking unwatched on Trakt), I have no idea without keeping a local database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

9 participants