[Request] Add TVMaze metadata agent

scanner-agent-dev

#1

This was brought up once but the user had their specific issue resolved, so I thought I would start a new thread.

tvmaze.com is quickly becoming a huge community and it would be a great asset to Plex users to have them as an option for a metadata agent for TV shows. I have written a python interface to their api here so I am familiar with their api but I have no idea how to write a plugin metadata agent (or if that is even possible). Would the devs be open to writing this and/or can someone please point me to documentation on how to write my own? Thanks in advance!


#2

I've started to try to hack my way through creating a metadata agent, having some troubles.

  1. How do people typically debug? Currently I'm just redirecting the logging to a file so I can see what is going on. Is there a better way?
  2. When/how does an Agent.TV__Shows object's update method get called?

If anyone has any resources for me to learn about creating a metadata agent I'd love to see them! Looking at other agents isn't really showing me the whole picture (I'm decent with python but have no current understanding of how plex interacts with the agent).


#3

Still struggling with this, can anybody help me out?


#4

I add the same little bit of nonsense to the beginning of my log messages. Then I can easily filter log messages by that nonsense string and see just the log messages I'm interested in. But yeah, basically log messages are your only way to see what's going on in there.

For your question 2, do you want all of the times update gets called, or are you looking for one way to force it to get called for testing? If it's the latter, you can go into any show in a library that uses your agent, and select "Fix incorrect match." The agent won't care if you fix it by assigning it back to the same show, but it will run the update method on that show's episodes.


#5

Thanks for this, raindancing! You're definitely helping make the picture a little bit clearer, the only thing I'm really fuzzy on still is the relationship between the "search()" method and the "update()" method, and how episodes are handled between them. Is search() just for the show as a whole or does it also deal with episode information? I see in other agents people are passing an id with a score from search() to update(), what is going on there? I just wish there was some documentation :D :D


#6

@raindancing said:
you can go into any show in a library that uses your agent, and select "Fix incorrect match." The agent won't care if you fix it by assigning it back to the same show, but it will run the update method on that show's episodes.

This seems to invoke the search() method, not update(). It gets through this code just fine:

def search(self, results, media, lang):

    log.debug("Search with TVMazeAgent: " + media.show)
    log.debug('Searching tvmaze....')
    show = pytvmaze.get_show(show_name=media.show)
    if show:
        log.debug(show.name + ' ' + str(show.maze_id))
        results.Append(MetadataSearchResult(
            id = str(show.maze_id),
            score = 100
        ))
    log.debug('MAZE ID FOUND: ' + str(metadata.id))

But then I never see this in the logs:
```
def update(self, metadata, media, lang):
log.debug('Update() called.....')
log.debug(str(dir(metadata)))
log.debug('NAME: ' + str(metadata.name))
log.debug(media.show)

log.debug('MAZE ID FOUND: ' + str(metadata.id))
show = pytvmaze.get_show(show_name=metadata.name)
if show:
    metadata.name = show.name
    metadata.summary = show.summary

#7

It should invoke both— the search() method when it searches for a correct match, and then the update() after you select the match from the list.

Although now I realize that I could have been clearer— you need to select the match from the list, and not cancel out of the operation.


#8

I definitely am selecting the match. I guess I'll have to play with this more, thanks for your responses, I'll continue to hack at it and maybe post more questions down the line :)


#9

Well I can't seem to figure this out, I'm really bummed that there is no documentation around this.


#10

There is documentation.... look at framework document attached in second post there:
https://forums.plex.tv/discussion/201365/request-add-tvmaze-metadata-agent#latest

You can check my agent and modify it as you see fit. It can do movies and series in the same agent.

Log.Debug is case sensitive.
You used lowercase...
You must have errors in the agent logs. Look there


#11

Framework document? You posted a link to this thread.


#12

https://forums.plex.tv/discussion/28084/plex-plugin-development-walkthrough

https://web.archive.org/web/20140107030832/https://dev.plexapp.com/


#13

Awesome, thank you


#14

The docs have gotten me much further, helped me discover some things I was doing wrong. I still can't seem to get the update() method to run, it doesn't show up in the logs at all even when I try using "fix incorrect match" and select the result. Maybe someone can see something I'm doing wrong by looking at my code here? I am only filling in metadata.name and metadata.summary for now until I can get this working. Everything within the search method is working great, hope someone can see what I'm doing wrong!


#15

import pytvmaze ? where is this library declared ?
commented and put the same as my agent
Plex Media Server.log doesn't throw an error ? Of course it does:

Jan 31, 2016 22:34:51 [0xf0bffb70] WARN - Couldn't determine bundle identifier for plug-in at: /volume1/Plex/Library/Application Support/Plex Media Server/Plug-ins/TVMaze.bundle

had to create info.plist. now it creates an agent log:

2016-01-31 22:50:35,492 (-8eda940) : DEBUG (init:7) - Starting TVMaze Agent

You should have taken an existing agent and wiped all un-necessary...
That should now give a head start


#16

pytvmaze is an external library which I have residing in Contents/Libraries/Shared/ and it does not throw an error. As far as I can tell all you did was comment out that import and add some other imports but do nothing with them, so I'm not sure what to do with that. I really just need to figure out how/when the update() method is called and I should be able to hack through it from there. Can you help me out with that?

When doing "Fix Incorrect Match" on an episode the logs show this, and that's it. No update() method, nothing else. Also, please see my updated code, I did realize that I was trying to handle episodes in the wrong way and I now see that first I need to match the show, then can loop through media items within that show.

EDIT: attached is the entire bundle.


#17

Ok I've figured out my major hurdle for now! The lang parameter in search() was getting a string that isn't approved by the api. It was getting "English" instead of "en". Back to hacking, thanks so much for pointing me to the docs!


#18

Things are going very well, can someone please help me with one more quick problem though? I'm wondering how to get "Local Media Assets" as an option when using my agent. See attached image for example of what I mean from tvdb agent. I figured it was declared at the contributes_to or accepts_from attributes but it seems that is incorrect? Thanks


#19

Having another issue - If a show does not have a language it is given the designation (xx), however it seems that in this case Update() will not be called. Is there anything I can do about this? When I force an unknown show to "en" for example Update() is called and everything else works great, but I don't want to force shows to a potentially incorrect language..


#20

To be clear, here is the code I'm using to try to deal with it but Update() is not called in this scenario.

    def search(self, results, media, lang, manual):
        Log.Debug("Search with TVMazeAgent: " + media.show)
        Log.Debug('Searching tvmaze...')
        show = pytvmaze.get_show(show_name=media.show)
        if show:
            Log.Debug(media.show)
            Log.Debug(show.name + ' ' + str(show.maze_id))
            Log.Debug(media.season)
            Log.Debug(media.episode)

            if show.language:
                lang_code = Locale.Language.Match(show.language)
                Log.Debug('{lang} ({code})'.format(lang=show.language,
                                                   code=lang_code))
            else:
                lang_code = Locale.Language.Unknown
            results.Append(MetadataSearchResult(
                id = str(show.maze_id),
                name = show.name,
                year = int(show.premiered[:4]),
                lang = lang_code,
                score = 100
            ))
            Log.Debug('Result added...')

I do get my log of "Result added..." but Update() isn't called so the show in question gets no metadata.