Jump to content

Using "Scheduled Tasks" inside a plugin.


Recommended Posts

Posted

I am using the TV C# platform code within the VirtualTV Example code created by Luke.  In the Emby "Scheduled Task" function, clicking "Refresh Guide" executes the "AddNewItemsToSchedule" function within this plugin.  The executed function is illustrated below.

 private void AddNewItemsToSchedule(TunerHostInfo tuner, string tunerChannelId, ChannelSchedule channelSchedule)
        

Within this function the plugin developer is supposed to add new EPG data to the existing data. I did this by adding the code below to refresh the EPG from the existing data.  The C# code is below.

channelSchedule = this.EnsureChannelSchedule(tuner, tunerChannelId);

 

My question is this, is the inclusion of the code above sufficient to update the EPG?  My second question is, can I somehow call the Javascript code in the plugin to request it to rebuild the EPG. I believe if the user has available the "Scheduled Task" function, then the user is using a browser, and therefore has the Javascript for the plugin loaded.

 

Please keep in mind that I am just a simple programmer trying to learn what I can.

Vic 

 

 

Posted

Why don't you send the EPG into the server from the javascript using a web route, ie create your own API endpoint, have the c# function build it and if you need the output in the html return it as an object.  You can always send that back again or store it and create a second endpoint to load it to the current EPG. That way the function is in your c# and available to the scheduled task to use directly as that function.

I hope this makes sense

Posted

@mickle026WOW that's a great idea. I am going to try it. Thanks so much.

Vic

Posted (edited)

This thread really should be moved to the Developer API section..

 

Here is a simple example to get you started, apologies if I made any mistakes, typed this quite quicklly but it should help clarify how this works if you are unsure

You can then see the webroute and the parametes in your swagger via the dashboard API link, you are just passing a json object too and fro...but you can encode and decode it how you like

to send in your EPG you would POST it, see how that works in swagger, by running a "Try it out", it'll show you the call required.

C#

    public partial class TEST_WEBROUTE : IService, IRequiresRequest
    {

        [Route("/TESTEWEBPOUTE/testroute", "GET", Summary = "")]
        public class MyWebRouteClassName : IReturn<object>
        {
            /// <summary>
            /// Whatever you are sending in , its just decoding json
            /// if you set ApiMemberName (you dont have to) it sets the vaule available to swagger input
            /// </summary>
            /// <value></value>
            
            /// Examples
            /// [ApiMember(Name = "CoverType", Description = "Output File Type ie (Poster,Backdrop,)", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
           	/// public string CoverType { get; set; }
           	/// [ApiMember(Name = "ImageType", Description = "Output Image Type ie (jpg,bmp,png)", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
            /// public string ImageType { get; set; }

            public string Text { get; set; }
        }
        
        
        // get method that accompanies the route for returning the object to the route/calling a function, same classname (MyWebRouteClassName)
        public string Get(MyWebRouteClassName result)
        {
        
         /// Call your function here
         /// the bool value from your call result returns into this "completed" bool
         
         bool completed = DoWheteverIWantFromMyWebInput();
         
        
        
        /// Serialise and return whatever you want to your browser via the Get Result to the Webroute object - example below.
        /// yopu can add more elements its just json
        
        return JsonSerializer.SerializeToString(new MyWebRouteClassName()
                {
                // using $ to subsitute back the True/False "Completed" value
                // in the javasript the response value Text is available via the dat.Text - That is the Json value from the container: "Text"
                    Text = $"Function Ended with {Completed}<br />"
                });
        }
        
        
        
        
        // Here is the function that would be available to your sheduled task
        public bool DoWheteverIWantFromMyWebInput(string ThePassedInputText)
        {
        
        // Do Whatever
        bool Completed = false
        
        // the building epg was successfull , set completed to true
        // the building epg was a failure , set completed to false
        
        
        
        
        	If{comlpeted}
        	{ 
        		return True
        	}
        	else 
        	{
        		return false
        	}
        }
    }
    
    
JAVASCRIPT   
    In the javascript call it like this
    
    
    
    page.querySelector('#buildepg').addEventListener('click', () => {
                        document.getElementById("buildepgdivtexttoupdate").innerHTML = "Running..";

                        BuilDEPG();

                    });
                    
                    
     
        function BuilDEPG() {

            ApiClient.getJSON(ApiClient.getUrl('/TESTEWEBPOUTE/testroute')).then(response => {
                var dat = response;
                document.getElementById("buildepgdivtexttoupdate").innerHTML = dat.Text;
            }).catch(e => {
                console.log(e);
            });
        }               
                    

Javascript POST, you probably know how to do this already
keep away from jQuery if you can, Luke has said all onlng he wants to drop jQuery and go completely Vanilla.
  I have not tried this method, you'll probably have to modify it to work with ApiClient.getUrl
  
https://www.freecodecamp.org/news/javascript-post-request-how-to-send-an-http-post-request-in-js/

fetch("https://jsonplaceholder.typicode.com/todos", {
  method: "POST",
  body: JSON.stringify({
    userId: 1,
    title: "Fix my bugs",
    completed: false
  }),
  headers: {
    "Content-type": "application/json; charset=UTF-8"
  }
})
  .then((response) => response.json())
  .then((json) => console.log(json));

 

Edited by mickle026
amended to clarify it a bit more
Posted

@mickle026I will study this code today. Thanks so much.

I don't know how to move this thread to the API section. @GrimReaperPerhaps you can help me.

Vic

GrimReaper
Posted
2 minutes ago, VicMoore said:

I don't know how to move this thread to the API section.

*Done*

  • Thanks 1
Posted

@GrimReaperYou are fantastic...   Thank you, Vic

  • Like 1
GrimReaper
Posted

Np, Vic, just shout if you need anything else.

Cheers

  • Thanks 1
Posted (edited)

@mickle026I have learned a great deal from your code.  Thanks so much for helping me.  

As I understand your code, the C# sets up an endpoint inside Emby that can be called by the JS code. Is there a way that the C# code can asynchronously send a message to the JS ?

Vic

Edited by VicMoore
Posted (edited)

Asynchronously, I'm not sure how to do that without signalR or a web socket listener, and I am not at that point yet.  I know the basics but not got them working, it would help me a great deal too.  Luke will know as he updates progress bars, but I never managed to get him to be more than vague on the subject.  I never tried to extract that form the media browser code on the wiki either.

I only know how to send back one reply to a JavaScript query as a response per request.  You can send in as many endpoint requests as you like so you can create multiple for different things.  So you can use an endpoint aggressively to do the progress bar etc..

I'm sure there's some guru about that knows more about this but I have asked the same question before and not got an answer.

Edited by mickle026
Posted

I have also tried web sockets several times with very little success. No one would answer my questions either.  

I appreciate your help. Keep me in mind when you need help with Javascript. 

Vic

Posted

There is a way it just needs to be written up and documented. 

Posted

@LukePerhaps we can help each other.

Vic

  • Thanks 1
Posted

@VicMoore

I have a question which relates to this thread and is Javascript (please excuse spelling, I have dyslexia - I try to correct as much as i can after i have written it)

Perharps it should be in a thread of its own, but its about communicting between the web ui and the c# backend.

I would like to nest a "do while" inside a promise while waiting for it to resolve.  I have written an example below to highlight what I would like it to do.

So for example, a real world example:

if I want my app to report progress periodically while the first promise is running but not had a response

ApiClient.getJSON(ApiClient.getUrl('/TESTEWEBPOUTE/testroute')).then(response => 
{ var dat = response; document.getElementById("buildepgdivtexttoupdate").innerHTML = dat.Text; }).catch(e => { console.log(e); });

how would I do something like this, I know this isnt correct but highlights what I would like to be able to achieve.

I know you cannot test if a promise is resolved, but you can test a value and set that value when the promise has resolved.

var resolvedvalue=false;
ApiClient.getJSON(ApiClient.getUrl('/TESTEWEBPOUTE/testroute')).then(

do {

// send in another promise.then(update div)
  var intervalID = window.setInterval(myCallback, 500);
  
}
while (resolvedvalue !== true).then(
response => { 
  var dat = response; 
  resolvedvalue = true;
  document.getElementById("buildepgdivtexttoupdate").innerHTML = dat.Text; 
}).catch(e => { console.log(e); });
  
function myCallback() 
{
  ApiClient.getJSON(ApiClient.getUrl('/TESTEWEBPOUTE/getmyprogress')).then(response => {
    var dat = response;
    document.getElementById("propgress").innerHTML = dat.Text;
            }).catch(e => {
                console.log(e);
            });
}

Does this make sense?

Basically trigger a timer to update a div whilst the first promise is running.  The time sends a secod promise to get the progress.

This is just an example that i could use to update tables etc whilst something is running.

Posted

@mickle026I am recovering from a virus. I will send you a code sample later today or in the morning.

Vic

Posted

@mickle026I have tried several possibilities and none have worked.  A hurricane is headed my way, and I may lose power. I have a few other ideas that I would like to try.

vic

Posted
Just now, VicMoore said:

@mickle026I have tried several possibilities and none have worked.  A hurricane is headed my way, and I may lose power. I have a few other ideas that I would like to try.

vic

Thanks for trying.  I'll await to see if you can brainstorm this out.

I thought about setting a timer on function start, running the web route query after starting a timer and stopping the timer on resolution of the promise.  Triggering the second route request from the timer.

This is not ideal, it'll add extra to emby logs, but should function as needed.

I would rather start at the first web route call and stop and resolve but it's near enough the same thing.

Posted
9 minutes ago, VicMoore said:

A hurricane is headed my way, and I may lose power.

Oh wow what is it call this time ?

Stay safe and be out of harms way.

Posted (edited)

I tried something similar. I set a timeOut, then fetched System/Info. While waiting for the promise to be satisfied, a while statement types "*" on the console. I think this did not work because the promise and the while statement are on separate threads. I will keep trying.

vic

test();

        function test() {
            
            let timerIndex = setTimeout(timerCallback, 5000);
            let timeOut = false;
            console.log("#");

            ApiClient.getJSON(ApiClient.getUrl('System/Info')).then(
                (result) => {
                    console.log("===== Result = ", result);
                    clearTimeout(timerIndex);
                    timeOut = true;
                    return;
                }).catch((msg) => {
                    console.log("=== Erroe Msg = ", msg);
                    clearTimeout(timerIndex);
                    timeOut = true;
                    return;
                });

            while (!timeOut) {
                console.log("*");
            }

            function timerCallback() {
                console.log("TimeOut");
                timeOut = true;
            }
        };
        console.log("Done");

Edited by VicMoore
Posted

This is a start of an example: https://github.com/MediaBrowser/Emby.AutoOrganize/blob/master/Emby.AutoOrganize/Configuration/autoorganizelog.js#L522-L554

That is listening for the messages client-side.

However do not fully copy the auto-organize example. It is doing one thing wrong on the server and sending out the messages to all admin clients, which is too much messaging. That needs to be restricted so that it's only sent to clients that are currently on that screen and have requested to listen to those events.

But you can use this as proof of concept to get started.

Posted

@LukeThanks so much. I will study the code today.

Vic

Posted
48 minutes ago, VicMoore said:

@LukeThanks so much. I will study the code today.

Vic

Don't forget the imports/defines at the top of the page 😉.

Posted

@mickle026I don't really understand the imports and defines.  I think I know what they do but I don't really understand them.

Vic

The hurricane just turned cat 4.  I am on the edge of the cone.  So far the electric has been holding up.

Posted

I believe they are similar to imports in c# and tell the JavaScript to load the libraries so that the keywords for those library functions work.

Without them you will have a keyword that is just a var...

I think this makes sense..

Posted

@mickle026That does make since. I am determined to understand the code.  

Vic

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...