Advertisement
Guest User

add_recorded_program.py

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