Advertisement
Guest User

add_recorded_program.py

a guest
Feb 1st, 2023
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.53 KB | None | 0 0
  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. '''
  5. Create a new recorded entry for the recordedid passed on the command line.
  6.  
  7. Use: add_recorded_program.py --help to get started.
  8.  
  9. Install as: add_recorded_program.py; chmod a+rx add_recorded_program.py
  10. '''
  11.  
  12. import argparse
  13. import json
  14. import logging
  15. import sys
  16.  
  17. try:
  18. from MythTV.services_api import (send as api, utilities as util)
  19. except ImportError:
  20. sys.exit("Missing python bindings?")
  21.  
  22.  
  23. # pylint: disable=consider-using-f-string
  24. def process_command_line():
  25. '''All command line processing is done here.'''
  26.  
  27. parser = argparse.ArgumentParser(description='Add Guide data',
  28. epilog='Default values are in ()s')
  29.  
  30. mandatory = parser.add_argument_group('required arguments')
  31.  
  32. parser.add_argument('--digest', type=str, metavar='<user:pass>',
  33. help='digest username:password')
  34.  
  35. parser.add_argument('--debug', action='store_true',
  36. help='turn on debug messages (%(default)s)')
  37.  
  38. parser.add_argument('--jdump', action='store_true',
  39. help='turn on json debug messages (%(default)s)')
  40.  
  41. mandatory.add_argument('--host', type=str, required=True,
  42. metavar='<hostname>', help='backend hostname')
  43.  
  44. mandatory.add_argument('--recordedid', type=int, required=True,
  45. metavar='<recid>',
  46. help='recorded id for the program of interest')
  47.  
  48. parser.add_argument('--port', type=int, default=6544, metavar='<port>',
  49. help='port number of the Services API (%(default)s)')
  50.  
  51. parser.add_argument('--quiet', action='store_true',
  52. help='suppress progress messages (%(default)s)')
  53.  
  54. parser.add_argument('--starttime', type=str, metavar='<start>',
  55. help='format: yyyy-mm-ddThh:mm:ssZ')
  56.  
  57. parser.add_argument('--title', type=str, metavar='<title>',
  58. help='Replacement title')
  59.  
  60. parser.add_argument('--version', action='version', version='%(prog)s 0.1')
  61.  
  62. parser.add_argument('--wrmi', action='store_true',
  63. help='allow data to be changed (%(default)s)')
  64.  
  65. return vars(parser.parse_args())
  66.  
  67.  
  68. def setup(backend, opts):
  69. '''
  70. Make sure the backend is up (GetHostName) and then set the backend's UTC
  71. offset for other methods to use.
  72. '''
  73.  
  74. try:
  75. backend.send(endpoint='Myth/GetHostName', opts=opts)
  76. int(util.get_utc_offset(backend=backend, opts=opts))
  77. except ValueError:
  78. sys.exit('\nExit, non integer response from get_utc_offset.')
  79. except RuntimeError as error:
  80. sys.exit('\nExit on fatal API error: "{}"'.format(error))
  81.  
  82.  
  83. def get_recorded_data(backend, args, opts):
  84. ''' Find existing recordedid entry. '''
  85.  
  86. endpoint = 'Dvr/GetRecorded'
  87. rest = 'RecordedId={}'.format(args['recordedid'])
  88.  
  89. try:
  90. resp_dict = backend.send(endpoint=endpoint, rest=rest, opts=opts)
  91. except RuntimeError as error:
  92. sys.exit('\nExit, GetRecorded: Fatal error; "{}"'.format(error))
  93.  
  94. if not resp_dict['Program']['Title']:
  95. sys.exit('\nExit, No recorded program matched RecordedId: {}.\n'
  96. .format(args['recordedid']))
  97.  
  98. if args['jdump']:
  99. print(json.dumps(resp_dict, sort_keys=True, indent=4,
  100. separators=(',', ': ')))
  101.  
  102. return resp_dict
  103.  
  104.  
  105. def update_recorded_data(recorded_data, args):
  106. ''' We're here to make any changes in the Recorded Data. '''
  107.  
  108. try:
  109. # On 33-Pre, port 6544, the following results in the chanid 0
  110. # error message, ChanId must be a string
  111. # recorded_data['Program']['Channel']['ChanId'] = \
  112. # int(recorded_data['Program']['Channel']['ChanId'])
  113. recorded_data['Program']['StartTime'] = args['starttime']
  114. recorded_data['Program']['Recording']['StartTs'] = args['starttime']
  115. if args['title']:
  116. recorded_data['Program']['Title'] = args['title']
  117. except KeyError:
  118. print('++++++++ KeyError THIS SHOULD PRINT A BETTER ERROR!!!')
  119. return False
  120.  
  121. return True
  122.  
  123.  
  124. def add_record_schedule(backend, recorded_data, args, opts):
  125. ''' Use the changed data to create a new recorded entry. '''
  126.  
  127. endpoint = 'Dvr/AddRecordedProgram'
  128.  
  129. params_not_sent = ('Cast', 'Artwork')
  130.  
  131. for param in params_not_sent:
  132. try:
  133. del recorded_data['Program'][param]
  134. except KeyError:
  135. pass
  136.  
  137. # This isn't honored by jsondata.
  138. opts['wrmi'] = args['wrmi']
  139.  
  140. if args['jdump']:
  141. print(json.dumps(recorded_data, sort_keys=True, indent=4,
  142. separators=(',', ': ')))
  143.  
  144. try:
  145. resp_dict = backend.send(endpoint=endpoint, jsondata=recorded_data,
  146. opts=opts)
  147. except RuntimeWarning as error:
  148. sys.exit('Exit, Unable to add rule: {}. Warning was: {}.'
  149. .format(recorded_data['Program']['Title'], error))
  150. except RuntimeError as error:
  151. sys.exit('\nExit, Fatal API Error response: {}\n'.format(error))
  152.  
  153. opts['wrmi'] = False
  154.  
  155. if isinstance(resp_dict, dict) and \
  156. isinstance(resp_dict['int'], (int, str)):
  157.  
  158. recording_rule = int(resp_dict['int'])
  159.  
  160. if recording_rule < 4294967295:
  161. vprint('\nAdded: "{}" (RecordId {}).'
  162. .format(recorded_data['Program']['Title'],
  163. recording_rule), args)
  164. else:
  165. recording_rule = -1
  166. vprint('Backend failed to add: "{}" (RecordId {}).'
  167. .format(recorded_data['Program']['Title'],
  168. recording_rule), args)
  169. else:
  170. vprint('Expected a "int: int" dictionary response, but got {}'
  171. .format(resp_dict), args)
  172.  
  173.  
  174. def vprint(message, args):
  175. '''
  176. Verbose Print: print recording rule information unless --quiet
  177. was used. Not fully implemented, as there are still lots of
  178. print()s here.
  179.  
  180. The intention is that if run out of some other program, this
  181. will can remain quiet. sys.exit()s will return 1 for failures.
  182. This may get expanded to put messages in a log...
  183. '''
  184.  
  185. if not args['quiet']:
  186. print(message)
  187.  
  188.  
  189. def main():
  190. '''
  191. The primary job of main is to get the arguments from the command line,
  192. setup logging (and possibly) handle the digest user/password then:
  193. '''
  194.  
  195. args = process_command_line()
  196.  
  197. opts = {}
  198.  
  199. logging.basicConfig(level=logging.DEBUG if args['debug'] else logging.INFO)
  200. logging.getLogger('requests.packages.urllib3').setLevel(logging.WARNING)
  201. logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING)
  202.  
  203. try:
  204. opts['user'], opts['pass'] = args['digest'].split(':', 1)
  205. except (AttributeError, ValueError):
  206. pass
  207.  
  208. backend = api.Send(host=args['host'], port=args['port'])
  209.  
  210. setup(backend, opts)
  211.  
  212. recorded_data = get_recorded_data(backend, args, opts)
  213.  
  214. if not recorded_data['Program']['Title']:
  215. sys.exit('\nExit, no recording for RecordedId: {}'.
  216. format(args['recordedid']))
  217.  
  218. if update_recorded_data(recorded_data, args):
  219. add_record_schedule(backend, recorded_data, args, opts)
  220. else:
  221. print('++++++++ update_recorded_data failed NEEDS TO BE A BETTER MSG')
  222.  
  223. if __name__ == '__main__':
  224. main()
  225.  
  226. # vim: set expandtab tabstop=4 shiftwidth=4 smartindent noai colorcolumn=80:
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement