Jump to content

Plugin Set Defaults - Seem to Duplicate


bakes82

Recommended Posts

bakes82

I have a plugin and I set some defaults in the CTOR.  This works fine, plugin page loads them and its wonderful, the issue seems to be on next reboot the values get duplicated?  How do I prevent that from happening?  On 2nd reboot I see in the plugin UI my values from first save, and then the defaults again.

public class PluginConfig : BasePluginConfiguration
{
    public Guid Guid = new Guid("BC6A2309-39AB-4696-ADE1-48BEADA23CFA"); // Also Needs Set In HTML File

    public PluginConfig()
    {
        TraktUser = new TraktUser();
        CustomTraktChannels = new List<TraktChannel>();
        PreConfiguredTraktChannels = new List<TraktChannel>();

        PreConfiguredTraktChannels = new List<TraktChannel>
        {
            new TraktChannel
            {
                Uri = "https://trakt.tv/users/mmounirou/lists/imdb-top-250-movies?sort=rank,asc",
                Enabled = true,
                ChannelName = "IMDB Top 250 Movies",
                Id = 1
            },
            new TraktChannel
            {
                Uri = "https://trakt.tv/users/justin/lists/imdb-top-rated-movies?sort=rank,asc",
                Enabled = true,
                ChannelName = "IMDB Top Rated Movies",
                Id = 2
            }
        };

        var blankCustoms = new List<TraktChannel>();

        for (var i = 0; i < 10; i++)
        {
            var number = i + 1;
            blankCustoms.Add(new TraktChannel
            {
                Uri = string.Empty,
                Enabled = false,
                ChannelName = "Channel " + number,
                Id = number
            });
        }

        CustomTraktChannels = blankCustoms;
    }

    public string PluginName => "TraktLists";
    public string PluginDesc => "Generate Channels from TraktLists";
    public string Pin { get; set; }
    public List<TraktChannel> CustomTraktChannels { get; set; }
    public List<TraktChannel> PreConfiguredTraktChannels { get; set; }
    public TraktUser TraktUser { get; set; }
}

public class TraktChannel
{
    public string Uri { get; set; }
    public string TraktListUserName => TraktHelpers.TraktListUriParse(Uri).Username;
    public string TraktListName => TraktHelpers.TraktListUriParse(Uri).ListName;
    public bool Enabled { get; set; }
    public string ChannelName { get; set; }
    public int Id { get; set; }
}

 

 

 

 

  • Like 1
Link to comment
Share on other sites

Do you mean, that you only want to load default channels, if custom channels haven't been configured?

I think that by having two separate lists, in your BasePluginConfiguration is the issue. There is one for defaults, and one for custom channels.

I would, perhaps consider,  having one "List<TraktChannel>" which would hold all channel data.

In my opinion, Don't use a constructor in the BasePluginConfiguration. Use the BasePluginConfiguration as a model object,  to serialize saved data from the configuration XML.

If you want to run code at the beginning of your plugin, or load defaults when the server starts, check out implementing "IServerEntryPoint" in a class, and use the "Run" function.

 

Question: It looks like the user has to enter Trakt credentials in the plugin configuration before the channel will work, is this correct?

Because the workflow changes.

Or, if the plugin is able to request channel data from Trakt without adding credentials, then the workflow changes again.

 

Let me know, it looks like you have a really good handle on plugin development, it's looking great so far! Nicely done!

 

Note: I'm not sure if the "GUID" variable in your "PluginConfig" class is the Plugin "Id", but you don't have to put the plugin GUID in the BasePluginConfiguration, that can be hardcoded in the "Plugin" class.pluginGUID.thumb.png.f29a3594ef093a8ee1c62c253f734831.png

 

Edited by chef
Link to comment
Share on other sites

bakes82

@chef

I just pushed the code to gihub:  I moved the CTOR stuff to the JS init section that seems to have prevented the duplicates in the config, but if you have a way to do it in CS thats better/cleaner for me I think. 

The code works now, you have to reboot after you do the config, but thats because I moved the coded to the JS instead of CS.  Also after each run the channel is duplicating the movies 😕   Though If I just do 1 list per plugin it doesnt.  If you want to issue a PR or something that points it in to a better direction would be great.  Im sure I missed something some place with how Emby does something, but Im just throwing darts and seeing where they hit.

https://github.com/bakes82/TraktLists

 

The idea is to have a set of 10 lists that the end user can customize, and then another section where I chose the lists, they can enable/change the name, but not the actual list.  But yeah you need to set the pin and the channel has to be enabled for it to "show up" if its not enabled then I hide the channel from the user.

 

image.thumb.png.2414e6ebaefbbcf12f54576de65b24db.png

 

image.thumb.png.e8ecdc944dc64f4549613bcedd59d8ca.png

 

  • Like 1
Link to comment
Share on other sites

Just now, bakes82 said:

@chef

I just pushed the code to gihub:  I moved the CTOR stuff to the JS init section that seems to have prevented the duplicates in the config, but if you have a way to do it in CS thats better/cleaner for me I think. 

The code works now, you have to reboot after you do the config, but thats because I moved the coded to the JS instead of CS.  Also after each run the channel is duplicating the movies 😕   Though If I just do 1 list per plugin it doesnt.  If you want to issue a PR or something that points it in to a better direction would be great.  Im sure I missed something some place with how Emby does something, but Im just throwing darts and seeing where they hit.

https://github.com/bakes82/TraktLists

 

The idea is to have a set of 10 lists that the end user can customize, and then another section where I chose the lists, they can enable/change the name, but not the actual list.  But yeah you need to set the pin and the channel has to be enabled for it to "show up" if its not enabled then I hide the channel from the user.

 

image.thumb.png.2414e6ebaefbbcf12f54576de65b24db.png

 

image.thumb.png.e8ecdc944dc64f4549613bcedd59d8ca.png

 

Excellent, I was going to propose adding the default code to the javascript, and checking if the configuration had any data, else load defaults. nicely done!

I'd love to read the code, so I'll check you the Git for sure! Really great to see this coming to fruition!

Link to comment
Share on other sites

8 hours ago, bakes82 said:

@chef Any ideas why it might be duplicating the movies?

@bakes82 I think I do know why. 

Do you have copies of the duplicated movies in your library?

Edited by chef
Link to comment
Share on other sites

bakes82
5 minutes ago, chef said:

I think I do know why. 

Do you have copies of the duplicated movies in your library?

When it runs first time 0 duplictes, then runs again it duplciates, runs again, duplicates.  I dont believe I have duplicates in my library its a small test and this is duplicating every movie, even if I do a check before hand in the code, maybe Im comparing IDs wrong, or I thought because there so many sched tasks and I dont understand how the process gets run to make the channels.  when the task says this:

 

public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
foreach (var t in TaskManager.ScheduledTasks)
{
if (t.Name == "Refresh Internet Channels")
{
await TaskManager.Execute(t, new TaskOptions());
}
}

}

Link to comment
Share on other sites

I'm about half way through reading the git.

 

When I created a channel for "Latest Release" (...pretty much just took anything released in the last 30 day and stuffed it into a channel...) I found that the channel was creating two instances of the movie in the emby db.

this caused duplicate versions of the same movie to appear in libraries.

that's why I wondered if you have versions of those movies in your library already. I thought that by creating the channel item, it was creating a new instance of the item in the data base... which would show a duplicate.

The code you've written is quite good, It might take me a moment to catch up :)

Link to comment
Share on other sites

really quickly, just to test a theory,

 

if you run the plugins scheduled tasks,

then run refresh internet channels (I think it does automatically in your code...),

then what happens if you run a library scan right after the channel refresh ends.

Do the duplicates disappear?

 

Link to comment
Share on other sites

bakes82

Ha I mean .net is my day job. Didn’t think it was anything special and was fairly hacky and quick lol.  A lot was copy paste.

Doesn’t look like a scan removes them.  I have a Netflix/appletv example but only 1x channel for each plugin and that doesn’t duplicate.  Those in the repo also and should be fairly close code. I’ve done some refactoring since though.

Link to comment
Share on other sites

Okay, cool.

Something is happening in the db. Im pretty sure, because I can see you even try calling .Distinct() in the list.

One way an item would duplicate would be if the ID changed. 

I'm gonna load the code into an ide. Just a minute. 

 

Link to comment
Share on other sites

bakes82

@chef Is there a way to exclude items from channels?  It looks like the GetItemList returns back items that are in channels also

The count of items being returned grows each sched task run.

image.png.9f5ca186f5f21940cbbf36ad942f3779.png

var mediaItems =
    libraryManager.GetItemList(
            new InternalItemsQuery
            {
                IncludeItemTypes = new[] {nameof(Movie)},
                IsVirtualItem = false,
                OrderBy = new[]
                {
                    new ValueTuple<string, SortOrder>(ItemSortBy.SeriesSortName, SortOrder.Ascending),
                    new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending)
                }
            })
        .ToList();

logger.Info($"Count of items in emby {mediaItems.Count}");
Link to comment
Share on other sites

Do you think that the Match Helper might be an issue?

            if (item.Name == movie.title && item.ProductionYear == movie.year)
            {
                return true;
            }

do we know that the provider data (movie.title) will equal the "item.Name" exactly, in order to get a true result?

 

 

Link to comment
Share on other sites

bakes82
13 minutes ago, chef said:

Do you think that the Match Helper might be an issue?


            if (item.Name == movie.title && item.ProductionYear == movie.year)
            {
                return true;
            }

do we know that the provider data (movie.title) will equal the "item.Name" exactly, in order to get a true result?

 

 

"Should" be matched by IMDB first ;)  based on what I see it looks like the data being return from the one 1 api call "grows" every call, like it sees the same movie from Library A, then It see it in "Channel B" channel B has a diff internal ID.

Link to comment
Share on other sites

bakes82

@chef Yeah Im correct, the GetItemList is returning back the same movie from "channels"  Explains why a couple movies didnt ever get dupes, they dont appear in another channel.

 

2020-11-15 18:05:50.503 Info ChannelP1: 10 Years - 891

2020-11-15 18:05:50.503 Info ChannelP1: 12 Angry Men - 2158
2020-11-15 18:05:50.503 Info ChannelP1: 12 Angry Men - 56970
2020-11-15 18:05:50.503 Info ChannelP1: 12 Rounds 2: Reloaded - 151
2020-11-15 18:05:50.503 Info ChannelP1: 12 Rounds 3: Lockdown - 1352
2020-11-15 18:05:50.504 Info ChannelP1: 12 Strong - 1556
2020-11-15 18:05:50.504 Info ChannelP1: 12 Years a Slave - 1241
2020-11-15 18:05:50.504 Info ChannelP1: 12 Years a Slave - 56971
2020-11-15 18:05:50.504 Info ChannelP1: 13 Hours: The Secret Soldiers of Benghazi - 1322
2020-11-15 18:05:50.505 Info ChannelP1: 13 Sins - 54
2020-11-15 18:05:50.505 Info ChannelP1: 1917 - 2128
2020-11-15 18:05:50.505 Info ChannelP1: 1922 - 2009
2020-11-15 18:05:50.505 Info ChannelP1: 2 Guns - 1262
2020-11-15 18:05:50.505 Info ChannelP1: 2015 MTV Video Music Awards - 2450
2020-11-15 18:05:50.505 Info ChannelP1: 2016 Billboard Music Awards (2016) - 1497
2020-11-15 18:05:50.506 Info ChannelP1: 2016 MTV Video Music Awards (2016) - 745

Link to comment
Share on other sites

bakes82

Looks like I needed this:
Every item I add to a channel, I have to ignore if in the other channels.

foreach (var movie in mediaItems.OfType<Movie>().OrderBy(x => x.Name))
{
    if (channels.Select(x => x.ParentId).Contains(movie.Parent.ParentId))
    {
        logger.Info($"Skipped Movie {movie.Name} from {movie.Parent.Name}");
        continue;
    }
  • Like 1
Link to comment
Share on other sites

bakes82

@chef what does this do in the sched task?  How I just have it run on its own cycle 

 

foreach (var t in TaskManager.ScheduledTasks)
  {
  if (t.Name == "Refresh Internet Channels")
  {
  await TaskManager.Execute(t, new TaskOptions());
  }
  }

 

Link to comment
Share on other sites

8 hours ago, bakes82 said:

@chef what does this do in the sched task?  How I just have it run on its own cycle 

 

foreach (var t in TaskManager.ScheduledTasks)
  {
  if (t.Name == "Refresh Internet Channels")
  {
  await TaskManager.Execute(t, new TaskOptions());
  }
  }

 

That looks like iterates the schedule tasks collection and  it runs refresh channel task.

 

Link to comment
Share on other sites

bakes82
11 hours ago, chef said:

That looks like iterates the schedule tasks collection and  it runs refresh channel task.

 

This is in your request channel code.... so for my tasks do I need it to refresh the channel code. I’m confused by this code lol.  Again you have magic code and copy pasted and it worked even though it makes no sense to me.

Link to comment
Share on other sites

bakes82

@cheffor the channel schedule tasks do I need the code?  I only want the task to run 1x a day, I’m confused as how the sched task actually triggers the channel to be updated. 

Link to comment
Share on other sites

12 hours ago, bakes82 said:

@cheffor the channel schedule tasks do I need the code?  I only want the task to run 1x a day, I’m confused as how the sched task actually triggers the channel to be updated. 

        public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
        {
            return new[]
            {
                
                new TaskTriggerInfo
                {
                    Type          = TaskTriggerInfo.TriggerInterval,
                    IntervalTicks = TimeSpan.FromHours(24).Ticks //Every 24 hours... probably from when server starts
                },
                new TaskTriggerInfo()
                {
                    SystemEvent = SystemEvent.WakeFromSleep,
                    Type        = TaskTriggerInfo.TriggerSystemEvent
                }
            };
        }

 

You'll have to run the "Refresh Internet Channels" task somewhere after your task is complete (I think I saw in your code that you handled that....).

 

Is this what you meant?

Edited by chef
Link to comment
Share on other sites

bakes82

Yeah, but in my sched task thats all it does from what I can tell.  Why do I need to call the refresh internet channels after? wont it keep constantly calling it for every sched task I have?  I have like 20 channels.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...