AddRecordSchedule Perl example?

Post Reply
darknicht
Newcomer
Posts: 9
Joined: Thu Sep 28, 2017 10:50 pm
Canada

AddRecordSchedule Perl example?

Post by darknicht »

Can anyone supply a Perl LibXML example for using Dvr/AddRecordSchedule in v29? I am knocking together a small program to search the guide for movies that meet my search criteria and schedule them for recording when/if they show up. I've got everything working except POSTing the schedule back to AddRecordSchedule, and my Google-Fu is failing me on that one.

Looking at some python examples, I know I need to use GetRecordSchedule to create a generic rule for the show I wish to schedule and then modify it and POST it back to AddRecordSchedule. I have pulled the generic rule into a DOM and modified it to what I need, but I just can't figure out how to now POST that DOM back to AddRecordSchedule.

Code: Select all

# Get the default rule for the program
$url = "http://$backend:6544/Dvr/GetRecordSchedule?ChanId=$programChanId&StartTime=$programStartTime";
$domGetRecordSchedule = XML::LibXML->load_xml(location=>$url);
# Modify to create new FindOne rule
($recRuleType) = $domGetRecordSchedule->findnodes('/RecRule/Type');
  $recRuleType->removeChildNodes;
  $recRuleType->appendText($recType);
($recRuleRecGroup) = $domGetRecordSchedule->findnodes('/RecRule/RecGroup');
  $recRuleRecGroup->removeChildNodes;
  $recRuleRecGroup->appendText($recGroup);
($recRuleAutoExpire) = $domGetRecordSchedule->findnodes('/RecRule/');
  $recRuleAutoExpire->removeChildNodes;
  $recRuleAutoExpire->appendText($autoExpire);
From the above, you can see that I have the desired recording rule residing in the DOM named $domGetRecordSchedule and now need to POST that back to my backend. This is my first time using Perl LibXML for posting data, and can't seem to find any examples of how to do so. Any help would be appreciated.


Full disclosure: I'm a hardware hack, not a programmer. I can usually make whatever small programs I need work, but they are not always (ever?) pretty or efficient.
daraden
Senior
Posts: 175
Joined: Tue Feb 23, 2016 7:33 am
United States of America

Re: AddRecordSchedule Perl example?

Post by daraden »

Not a perl person, but did a quick google of "perl http post xml". looks like you need to use LWP::UserAgent and HTTP::Request to create an http post request.
User avatar
pvr4me
Senior
Posts: 763
Joined: Fri Feb 07, 2014 7:25 pm
Location: near Toronto, Canada
Contact:
Canada

Re: AddRecordSchedule Perl example?

Post by pvr4me »

I can't help with the Perl bindings...but are you sure you need them? Can you not create a custom recording schedule in Myth and let it set up the rules? Basics are covered in the User Manual:

https://www.mythtv.org/wiki/User_Manual ... tom_Record

Several examples are in the wiki:

https://www.mythtv.org/wiki/Custom_Recording

Craig
Formerly the MacPorts guy.
darknicht
Newcomer
Posts: 9
Joined: Thu Sep 28, 2017 10:50 pm
Canada

Re: AddRecordSchedule Perl example?

Post by darknicht »

daraden wrote:
Tue Oct 17, 2017 10:40 am
Not a perl person, but did a quick google of "perl http post xml". looks like you need to use LWP::UserAgent and HTTP::Request to create an http post request.
Yeah, I saw how to post via UserAgent, but I was hoping that there was a method to do so using LibXML since it can get from a URL. I'll likely have to resort to using UserAgent, but it would have been nice to be able to just post back the already built and formatted DOM rather than having to break out all the various nodes from it and pass them to the UserAgent call. Hopefully AddRecordSchedule only requires a handful of arguments passed to it and the majority are optional.
darknicht
Newcomer
Posts: 9
Joined: Thu Sep 28, 2017 10:50 pm
Canada

Re: AddRecordSchedule Perl example?

Post by darknicht »

pvr4me wrote:
Tue Oct 17, 2017 2:01 pm
I can't help with the Perl bindings...but are you sure you need them? Can you not create a custom recording schedule in Myth and let it set up the rules?

<snip>

Craig
I could create a custom rule every time I think of a show or movie that I might want to see if it ever makes it to one of the TV channels I subscribe to, but that would require me being in front of the mythtv system when I think of it. My method just requires me to jot the title in a note whenever I see/hear about it and then that note can get sucked into the mythtv system whenever the check is scheduled to run.

My general process flow is...
1) See/hear an ad for a new movie or show, and jot a note on my phone/tablet/laptop with the title
2) Notes get synchronized to my master list automatically whenever I am near my home network
3) Master list gets checked nightly by my scheduling script
4) Anything from my master list that has been seen in the MythTV programming guide gets scheduled to record

I have been using this process with 'tvwish' for several years now and it's been great for grabbing those movies that I see premiering in the theatre, but I'm going to wait to see it whenever it hits TV (in 3-24 months). The only reason I'm moving away from using tvwish is that it started throwing errors when I upgraded to myth v29 and I'd rather move to something using the recommended ServicesAPI and not the direct MySQL access that tvwish uses.
daraden
Senior
Posts: 175
Joined: Tue Feb 23, 2016 7:33 am
United States of America

Re: AddRecordSchedule Perl example?

Post by daraden »

darknicht wrote:
Tue Oct 17, 2017 7:33 pm

Yeah, I saw how to post via UserAgent, but I was hoping that there was a method to do so using LibXML since it can get from a URL. I'll likely have to resort to using UserAgent, but it would have been nice to be able to just post back the already built and formatted DOM rather than having to break out all the various nodes from it and pass them to the UserAgent call. Hopefully AddRecordSchedule only requires a handful of arguments passed to it and the majority are optional.
wouldn't it be possible to use one of the toString/serialize methods to pass the DOM instead using individual nodes?
User avatar
bill6502
Developer
Posts: 2307
Joined: Fri Feb 07, 2014 5:28 pm
United States of America

Re: AddRecordSchedule Perl example?

Post by bill6502 »

Hi,

Try looking here: https://www.mythtv.org/wiki/Perl_API_ex ... e_database

I to don't use Perl and the Writing to the database section is misleading because it's
really using the API as you want. The expire.pl example shows how a POST is done,
but I've never (with the Python equivalent) sent data in XML.
darknicht
Newcomer
Posts: 9
Joined: Thu Sep 28, 2017 10:50 pm
Canada

Re: AddRecordSchedule Perl example?

Post by darknicht »

daraden wrote:
Wed Oct 18, 2017 5:15 am
wouldn't it be possible to use one of the toString/serialize methods to pass the DOM instead using individual nodes?
That's what I was looking for an example of doing. I was hoping somebody had a slick example already cooked up that I could run with. I'm not really familiar with manipulating the DOM, so this is very much a learning experience for me.
darknicht
Newcomer
Posts: 9
Joined: Thu Sep 28, 2017 10:50 pm
Canada

Re: AddRecordSchedule Perl example?

Post by darknicht »

bill6502 wrote:
Wed Oct 18, 2017 1:46 pm
Try looking here: https://www.mythtv.org/wiki/Perl_API_ex ... e_database
That's pretty close to what I imagine I'll need to do. My last piece of the puzzle is to figure out if there's an easy way to parse through the DOM and pass all the key=>value pairs found. Otherwise, I'll just pull out the required data into my own structure and pass it that way. I should have a chance to play with it again this weekend.
User avatar
bill6502
Developer
Posts: 2307
Joined: Fri Feb 07, 2014 5:28 pm
United States of America

Re: AddRecordSchedule Perl example?

Post by bill6502 »

Here's a snippet from my Python version that may help you. As you can
see, not all parameters from the template are going to be sent back in the
Dvr/AddRecordSchedule endpoint. Also, you can see that Station in the
updated template comes from CallSign in the guide (EPG.)

Good luck.

Code: Select all

...                                                                                
def update_template(template, guide_data, args):                                
    '''                                                                         
    Put the guide information into the template for the new rule.               
    '''                                                                         
                                                                                
    try:                                                                        
        template['StartTime'] = guide_data['StartTime']                         
        template['EndTime'] = guide_data['EndTime']                             
        template['Title'] = guide_data['Title']                                 
        template['Type'] = 'Record {}'.format(args['type'])                     # Record All or Record One etc.
        template['Station'] = guide_data['Channel']['CallSign']                 
        template['ChanId'] = guide_data['Channel']['ChanId']                    
        template['SearchType'] = 'None'                                         
        template['Category'] = guide_data['Category']                           # The last four can be omitted...
        template['SeriesId'] = guide_data['SeriesId']                           
        template['FindTime'] = util.create_find_time(guide_data['StartTime'])   
        template['Description'] = 'Rule created by add_recording_rule.py'       
    except KeyError:                                                            
        return False                                                            
                                                                                
    return True                                                                 
                                                                                
                                                                                
def create_rule(backend, postdata, args, opts):                  # postdata here is my updated template from above      
    '''                                                                         
    Send the changed data to the backend.                                       
    '''                                                                         
                                                                                
    endpoint = 'Dvr/AddRecordSchedule'                                          
                                                                                
    params_not_sent = ('AverageDelay', 'CallSign', 'Id', 'LastDeleted',         
                       'LastRecorded', 'NextRecording', 'ParentId')             
                                                                                
    for param in params_not_sent:                                               
        del postdata[param]
...
darknicht
Newcomer
Posts: 9
Joined: Thu Sep 28, 2017 10:50 pm
Canada

Re: AddRecordSchedule Perl example?

Post by darknicht »

bill6502 wrote:
Fri Oct 20, 2017 3:00 pm
Here's a snippet from my Python version that may help you.
<snip>
Thanks. That looks like it'll push me in the proper direction. At the very least it gives me an indication of which parameters are mandatory for the API call. I was figuring I'd have to do a code-dive or trial and error to figure out what information _must_ be passed. The entry for AddRecordSchedule on the wiki makes it sound like it requires everything gathered from GetRecordSchedule to be passed back to it. I'm glad that is not so, as it makes creating the rule much easier if I only need to pass the items that are different from the default rule.

I'll bang away at the code this weekend and see if I can make headway. Worst case scenario is I just re-write in python since there are pre-existing examples already written. (Thanks to you!)

Everyone's help has been appreciated.

<Edited for typo's>
User avatar
bill6502
Developer
Posts: 2307
Joined: Fri Feb 07, 2014 5:28 pm
United States of America

Re: AddRecordSchedule Perl example?

Post by bill6502 »

To be clear, return everything from the template, with the above exceptions.
At least modify the 'top 7', as shown. If you're going the Python route, this link
should get you much closer. Be sure to read the comments at the top for the
requirement. https://pastebin.com/ADNuuS0P

EDIT, used pastebin as attachement didn't work
darknicht
Newcomer
Posts: 9
Joined: Thu Sep 28, 2017 10:50 pm
Canada

Re: AddRecordSchedule Perl example?

Post by darknicht »

Thanks for the link. It looks like it has all the logic I'm missing. I should be able to use that to get something working for myself.
darknicht
Newcomer
Posts: 9
Joined: Thu Sep 28, 2017 10:50 pm
Canada

Re: AddRecordSchedule Perl example?

Post by darknicht »

Closing the loop on this question in case anyone else is looking for an example. Below is what I ended up using to create the new recording rule...

Code: Select all

use strict;
use warnings;
use XML::LibXML;
use LWP::UserAgent;

my $browser = LWP::UserAgent->new;
my $response = "";
my $backend = "myth_backend_hostname";
my $url = "";
my $programStartTime = "";
my $programChanId = "";
my $recPriority = 0;
my $recType = "Record One";
my $recGroup = "MyMovies";
my $recAutoExpire = "false";

# ...Omitting a whole bunch of logic code for finding the program StartTime and Channel ID for the program I wish to schedule...

# Get the default rule for the program
$url = "http://$backend:6544/Dvr/GetRecordSchedule?ChanId=$programChanId&StartTime=$programStartTime";
$domGetRecordSchedule = XML::LibXML->load_xml(location=>$url);

# Modify to create new FindOne rule (also converting DOM to HASH as I can pass that directly to useragent post)
foreach my $node ($domGetRecordSchedule->documentElement->childNodes) {
    $newRecRule{$node->nodeName} = $node->to_literal;
}
$newRecRule{'AutoExpire'} = $recAutoExpire;
$newRecRule{'RecGroup'} = $recGroup;
$newRecRule{'RecPriority'} = $recPriority;
$newRecRule{'Type'} = $recType;
$newRecRule{'Station'} = $newRecRule{'CallSign'};
delete $newRecRule{'AverageDelay'};
delete $newRecRule{'CallSign'};
delete $newRecRule{'Id'};
delete $newRecRule{'LastDeleted'};
delete $newRecRule{'LastRecorded'};
delete $newRecRule{'NextRecording'};
delete $newRecRule{'ParentId'};

# POST the new rule
$url = "http://$backend:6544/Dvr/AddRecordSchedule";
$response = $browser->post( $url, \%newRecRule );
if ($response->is_success) {
    print "......Movie: '$programTitle ($programAirdate)' - '$programId' recording rule created\n";
} else {
    print "ERROR: Failed to create recording rule\n";
    print $response->content;
    print "\nStartTime = ",$newRecRule{'StartTime'}, ", ChanId = ",$newRecRule{'ChanId'};
    print "\n";
}
Thanks again to everyone for the help figuring this out!
Post Reply