pkkid / python-plexapi

Python bindings for the Plex API.
BSD 3-Clause "New" or "Revised" License
1.14k stars 198 forks source link

Support agents/plugins #140

Open Hellowlol opened 7 years ago

Hellowlol commented 7 years ago

Should we support editing the settings for agents/plugins. It very close to the rest of the settings, in addition it can have a values where the index of the values is what should be set.

blacktwin commented 4 years ago

Additional support for agents and library settings has been added in PR #436

An example for making library setting changes in the PR.

Suika commented 4 years ago

TL;DR: Extend fixMatch(auto=True) with optional agent=

I've tried testing the unmatch_match branch and stumbled uppon a problem possibly resulting from a bad agent. The library has the default agent of "NotYoutube", but contains "Youtube" videos. If a vide does not match the "NotYoutube", I can manually go and set it to "Youtube" via Auto Matchn in the webui.

Yet, when performing plex.fetchItem(XYZ).matches(agent='youtube', auto=True) it returns nothing, which is probably a problem resulting from bad/not properly written agent. Is it possible to extend the fixMatch() with optional agent= if the auto=True is set?

Since the matches() looks like the "Search Options" in "Fix Match" of the WebUI. And the fixMatch(auto=True) seems to default to the first agent in the list, which is the default agent. Whereas the WebUI allows to define an Agent in "Auto Match".

Also thanks for the (un)match feature.

blacktwin commented 4 years ago

Why are you using auto and providing an agent? What are your results with just using the agent?

Suika commented 4 years ago

I've looked at the fixMatch() function and see that it does a matches()[0] which defaults to the Library agent.

Let me demonstrate it quickly. For example, I have a Movie Library with XYZ Agent where a Youtube video was dropped in and I actually want to keep it there, but I want it to fetch the right metadata for it with the Youtube Agent. So, via the web I would go Library > Video > Fix Match > Auto Match > Youtube and it would find the youtube metadata and match the video. Because the XYZ Agent, by default, can't properly process/find the ID on the remote service, it slaps a generic broken match on the said video. Example below. When I try to request the same file with the right agent, it returns nothing.

>>> c= plex.fetchItem(993922)
>>> c.matches()
[<SearchResult:Doom-Behind-the-Musi:99>] # This is the "Default" XYZ Agent returning broken match due to a few reasons
>>> c.matches()[0].guid
'com.plexapp.agents.XYZ://f0ypVbPA?lang=xn'
>>> c.matches(agent='com.plexapp.agents.youtube') # The actual agent that would match the video
[]

If I perfrom the same requests on the API with curl 'https://XYZ.plex.direct:32400/library/metadata/993922/matches?agent=com.plexapp.agents.youtube&manual=0&X-Plex-Token=XYZ' I get:

<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer size="1" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1587038219">
<SearchResult guid="com.plexapp.agents.youtube://ua-f0ypVbPA?lang=xn" name="Doom Behind the Music Part 1 Ua F0ypvbpa" score="99" lifespanEnded="0">
</SearchResult>
</MediaContainer>

From here I can manually splice the whole thing and do the guid=com.plexapp.agents.youtube://ua-f0ypVbPA?lang=xn -X OPTIONS, -X PUT, etc. And it will work and match the Video.

So I guess matches() is not doing something or is not getting something from the api.

blacktwin commented 4 years ago

What happens when you use com.plexapp.agents.youtube://ua-f0ypVbP as your agent?

Suika commented 4 years ago

com.plexapp.agents.youtube://ua-f0ypVbP is not possible, because the 993922/matches?agent=com.plexapp.agents.youtube returns com.plexapp.agents.youtube://ua-f0ypVbPA?lang=xn. lang=xn comes from lang part of the MetadataSearchResult in the Agent. IIRC xn it means, no language.

But I did try what you wanted via the HTTP API and, the first matches call returned com.plexapp.agents.youtube://ua-f0ypVbPA?lang=xn, I changed it to com.plexapp.agents.youtube://ua-f0ypVbPA and sent the data via OPTIONS and PUT to plex. Plex "matched" the video with a non-existent entry, resulting in the entry only having the title Doom Behind the Music Part 1 Ua F0ypvbpa, that was extracted from the filename, and a few other file metadata that plex gathers by default. But there was no director, no time, no tags, nothing.

So you HAVE to use what the /matches?agent=com.plexapp.agents.youtube returns, for plex to fill the metadata.

Suika commented 4 years ago

Ah, found the problem. It's the year and title parameters being set and sent in https://github.com/pkkid/python-plexapi/blob/37b4c8729d0afe30cbdf8cff7ddd7b2e433af87e/plexapi/base.py#L510-L530 Both values are set to None.

>>> params={}
>>> params['title'] = "abc"
>>> params['year'] = 2020
>>> from urllib.parse import urlencode
>>> urlencode(params)
'year=2020&title=abc'
>>> params['year'] = None
>>> urlencode(params)
'year=None&title=abc'

curl 'https://XYZ.plex.direct:32400/library/metadata/993958/matches?agent=com.plexapp.agents.youtube&X-Plex-Token=XYZ&title=None'

<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer size="0" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1587038219">
</MediaContainer>
blacktwin commented 4 years ago

Can you provide a link to this agent or is it in webtools UAS? I'd like to test with it.

Suika commented 4 years ago

See comment above.

brb. gonna remove a few parts from the file and see if it works.

Suika commented 4 years ago

Yup, changing https://github.com/pkkid/python-plexapi/blob/37b4c8729d0afe30cbdf8cff7ddd7b2e433af87e/plexapi/base.py#L511-L519 to

            if title:
                params['title'] = title

            if year:
                params['year'] = year

made the whole thing work.

c.matches(agent='youtube')
[<SearchResult:Doom-Behind-the-Musi:99>]

So, maybe only set these if the user wants to use them for search? Because looking at the reqests that are generated by the webui, using "Auto Match", it does not send anything besides the agent=. And only when the user uses the Search Options, does it add the title, language and year.

So yeah, I would not set the year, title and language arguments at all for the matches() call.

PS: off to sleep

blacktwin commented 4 years ago

What does c.matches(agent='youtube',title='',year='') return?

Suika commented 4 years ago
>>> plex.fetchItem(994161).matches(agent='youtube',title='',year='')
[]

Since "" != None, the values are set to ""

>>> params={}
>>> params['title'] = ""
>>> params['year'] = 2020
>>> from urllib.parse import urlencode
>>> urlencode(params)
'year=2020&title='
>>> if params['title'] is None: print("yes")
...
>>> params['title'] = None
>>> urlencode(params)
'year=2020&title=None'

The inclusion of title and year in the query, breaks the auto match feature.

blacktwin commented 4 years ago

Can you provide a link to this agent or is it in webtools UAS? I'd like to test with it.

Suika commented 4 years ago

¯\(ツ)YouTube-Agent.bundle.zip In Agent settings the pattern should be something like -(?P<id>.{11})\. if video is downloaded with the default youtube-dl config.

blacktwin commented 4 years ago

@Suika Please try this PR.

I think this should get you what you want.

match = item.matches(year='', agent='youtube')
item.fixMatch(searchResult=match[0])
# or
item.fixMatch(agent='youtube', auto=True)
Suika commented 4 years ago
>>> plex.fetchItem(998322).matches(agent='youtube')
[]
>>> plex.fetchItem(998322).matches(year='', agent='youtube')
[]

Yeah, no. Doesn't work. Can't work because you missed my https://github.com/pkkid/python-plexapi/issues/140#issuecomment-619045231 by a mile.

The damn query keys are still being set. It's the inclusion of these keys that causes the problem. This https://github.com/pkkid/python-plexapi/issues/140#issuecomment-618744058 is all that is needed to make it work.

Hellowlol commented 4 years ago

@Suika send a PR that includes a test 👍

blacktwin commented 4 years ago

I didn't miss your comment, it just wasn't the correct way to go. I've left comments in both your PR and mine highlighting why.

Suika commented 4 years ago

Yeah, got it. Since it's the way plex is building the query and I missed that the value is not populated on "". You are right. ¯\(ツ)/¯ as long as it works the way the ui does it, all good. Thanks.

blacktwin commented 4 years ago

PR #507 and issue #450 kinda touch on related areas of this issue. Agent support has be added to a degree (see mentioned PRs) and plugin support has been drop by Plex.

Not sure how to move forward with this issue.

Has agent support been satisfied?

Should plugin support be abandoned? If not, where/what should the focus be?

JonnyWong16 commented 2 years ago

This can be closed?

With Plex no longer supporting plugins, I don't see any benefit of having this in PlexAPI.