def __init__(self, mid = None, clean=False, segments=False, episodes=False, filter=None, dryrun=False, include_self=False, processor = None, processor_description= None, filter_description = None): self.api = MediaBackend().command_line_client() self.description = "Doing for all" self.clean = clean self.segments = segments self.episodes = episodes self.filter = filter self.dryrun = dryrun self.include_self = include_self self.mid = mid self.logger = self.api.logger self.processor = processor self.processor_description = processor_description self.filter_description = filter_description
#!/usr/bin/env python3 """ This script checks wether a poms playlist contains multiple translations of the same source. If so, it will delete remove all but one. """ from npoapi import MediaBackend import time api = MediaBackend().command_line_client() api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') args = api.parse_args() group = args.mid[0] members = api.members(group, batch=200, log_progress=True) translations_for_mid = {} for member in members: update = member.firstChild mid = update.attributes["mid"].value relations = member.getElementsByTagName("relation") for relation in relations: relation_type = relation.attributes["type"].value if relation_type == "TRANSLATION_SOURCE": translation_source = relation.firstChild.nodeValue if not translation_source in translations_for_mid: translations_for_mid[translation_source] = [] translations_for_mid[translation_source].append(mid) #print(pprint.pformat(map)) for mid in translations_for_mid: sorted_mids = sorted(translations_for_mid[mid]) mids_to_delete = sorted_mids[1:]
class ForAllDescendants: def __init__(self, mid = None, clean=False, segments=False, episodes=False, filter=None, dryrun=False, include_self=False, processor = None, processor_description= None, filter_description = None): self.api = MediaBackend().command_line_client() self.description = "Doing for all" self.clean = clean self.segments = segments self.episodes = episodes self.filter = filter self.dryrun = dryrun self.include_self = include_self self.mid = mid self.logger = self.api.logger self.processor = processor self.processor_description = processor_description self.filter_description = filter_description def command_line(self): api = self.api api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') api.add_argument('-C', '--clean', action='store_true', default=False) api.add_argument('--dryrun', action='store_true', default=False) api.add_argument('--segments', action='store_true', default=False, help='') api.add_argument('--episodes', action='store_true', default=False, help='') api.add_argument('--include_self', action='store_true', default=False, help='') if self.processor is None: api.add_argument('process', type=str, nargs=1, help= """ python code to postprocess. E.g. member.genre.append('1.3.4') member.publishStop=parse("2018-12-31") """) if self.filter is None: api.add_argument('--filter', type=str, help=""" Filter. A piece of python code to filter. E.g. type(member) == npoapi.xml.mediaupdate.programUpdateType member.type == 'CLIP' 'kort!' in short_title.lower() """) def parse_args(self): args = self.api.parse_args() self.processor = ForAllDescendants.function_or_arg(self.processor, args, "process", self.logger) self.filter = ForAllDescendants.function_or_arg(self.filter, args, "filter", self.logger) self.processor_description = ForAllDescendants.function_description(self.processor_description, args, "process") self.filter_description = ForAllDescendants.function_description(self.filter_description, args, "filter") self.mid = args.mid[0] self.clean = args.clean or self.clean self.segments = args.segments or self.segments self.episodes = args.episodes or self.episodes self.dryrun = args.dryrun or self.dryrun self.include_self = args.include_self or self.include_self def do_one(self, member, idx): self.api.post(member) def process(self, member, idx): needs_post = self.processor(member, idx) if needs_post is None: needs_post = True self.logger.debug(" needs post %s", str(needs_post)) return needs_post def do_all(self): log = self.api.logger tempfilename = os.path.splitext(os.path.basename(sys.argv[0]))[0] cache = os.path.join(gettempdir(), tempfilename + "." + self.mid + ".p") members = [] if os.path.exists(cache) and not self.clean: log.info("Reusing from " + cache) members = pickle.load(open(cache, "rb")) else: if not self.clean: log.info("Not found " + cache) MU.descendants(self.api, self.mid, batch=200, target=members, segments=self.segments, episodes=self.episodes, log_progress=True) pickle.dump(members, open(cache, "wb")) log.info("Found " + str(len(members)) + " objects") count = 0 for idx, member in enumerate(MU.iterate_objects(members)): member_mid = member.mid # noinspection PyUnusedLocal main_title = MU.title(member, "MAIN") # noinspection PyUnusedLocal short_title = MU.title(member, "SHORT") member_type = MU.mediatype(member) string = "%s %s (%s)" % (member_type, member_mid, main_title) if self.filter: try : result = self.filter(member, idx) log.debug("%s Execed %s result %s", str(idx), self.filter_description, str(result)) if not result: log.info("%s Skipping %s because of filter %s", str(idx), string, self.filter_description) continue except Exception as e: log.warning("%s %s", str(member.mid), str(e)) continue needs_post = self.process(member, idx) if needs_post is None: needs_post = True log.debug(" needs post %s", str(needs_post)) if needs_post: if not self.dryrun: log.info("%s Execed %s for %s and posting", str(idx), self.processor_description, string) self.do_one(member, idx) else: log.info("%s Execed %s for %s (not posting because of dryrun parameter)", str(idx), self.processor_description, string) else: log.info("%s Skipping %s for %s", str(idx), self.processor_description, string) count += 1 if self.include_self: if not self.dryrun: log.info("%s %s", self.description, self.mid) object = self.api.get_object(self.mid) log.info("Found %s", str(object)) self.do_one(object, None) else: log.info("Dry run %s %s", self.description, self.mid) count += 1 log.info("Ready. %s %s object from POMS", self.description, str(count)) return count @staticmethod def function_or_arg(given_function, args, attr, log): if given_function is None: to_exec = getattr(args, attr) if type(to_exec) == list: to_exec = to_exec[0] if not to_exec is None: if os.path.exists(to_exec): log.info("%s is a file.", str(to_exec)) to_exec = open(to_exec).read() def exec_string(member, idx): return ForAllDescendants.exec_then_eval(to_exec, {}, locals()) given_function = exec_string else: given_function = None return given_function @staticmethod def function_description(given_function_description, args, attr): if given_function_description is None: if hasattr(args, attr): given_function_description = getattr(args, attr) else: given_function_description = "" return given_function_description def nope(self, *args): """""" @staticmethod def exec_then_eval(code, globals, locals): block = ast.parse(code, mode='exec') # assumes last node is an expression last = ast.Expression(block.body.pop().value) exec(compile(block, '<string>', mode='exec'), globals, locals) return eval(compile(last, '<string>', mode='eval'), globals, locals) def main(self): self.command_line() self.parse_args() self.do_all()
#!/usr/bin/env python3 """ """ """Script to add a location """ from npoapi import MediaBackend, MediaBackendUtil as MU api = MediaBackend().command_line_client() api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') api.add_argument('location', type=str, nargs=1, help='URL of the new "location"') args = api.parse_args() print(api.add_location(args.mid[0], MU.create_location(args.location[0])))
#!/usr/bin/env python3 """Script to add a image to all members of a group.""" from npoapi import MediaBackend, MediaBackendUtil as MU import npoapi.xml.mediaupdate from xml.dom import minidom api = MediaBackend().command_line_client() api.add_argument("mid", type=str, nargs=1, help="The mid of the object to handle") api.add_argument( "image", type=str, nargs="+", help="New image. If more than one is provided, they will be used alternately" ) api.add_argument("title", type=str, nargs="?", help="title for new images") api.add_argument("--only_if_none", action="store_true", default=False, help="Only if no images present yet") api.add_argument("--dry_run", action="store_true", default=False, help="Dry run") api.add_argument( "--filter", type=str, help=""" Filter. A piece of python code to filter. E.g. "memberType == npoapi.xml.mediaupdate.programUpdateType" or "member.type == 'PROMO'" """, ) api.add_argument("--to_object", action="store_true", default=False, help="Add to object itself too") api.add_argument("--to_object_only", action="store_true", default=False, help="Add to object itself only") api.add_argument("--max", type=int, nargs="?", help="Maximum number of objects to process") api.add_argument("--max_query", type=int, nargs="?", help="Maximum number of objects to find") api.add_argument("--segments", action="store_true", default=False, help="") MU.logger = api.logger args = api.parse_args()
#!/usr/bin/env python3 """Script to add a genre to all members of a group. Supported in poms >= 3.2 only""" from npoapi import MediaBackend from npoapi.xml import mediaupdate from npoapi.xml import poms api = MediaBackend().command_line_client() api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') api.add_argument('genre', type=str, nargs=1, help='new Genre') args = api.parse_args() genre_id = args.genre[0] bytes = api.get(args.mid[0], ignore_not_found=True) if bytes: object = poms.CreateFromDocument(bytes) if type(object) == mediaupdate.programUpdateType: object.genre.append(genre_id) api.post(object) members = api.members(args.mid[0], batch=200) for member in map(lambda m: poms.CreateFromDOM(m.getElementsByTagName("mediaUpdate")[0], mediaupdate.Namespace), members): member_mid = member.mid print("Adding genre " + genre_id + " to " + member_mid) member.genre.append(genre_id) api.post(member)
#!/usr/bin/env python3 """Script to do something for all descendants of a poms group""" import pickle import os from tempfile import gettempdir # some imports handy for the exec call import npoapi.xml.mediaupdate from dateutil.parser import parse from npoapi import MediaBackend, MediaBackendUtil as MU api = MediaBackend().command_line_client() api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') api.add_argument('process', type=str, nargs=1, help=""" python code to postprocess. E.g. member.genre.append('1.3.4') member.publishStop=parse("2018-12-31") """) api.add_argument('-C', '--clean', action='store_true', default=False) api.add_argument('--dryrun', action='store_true', default=False) api.add_argument('--filter', type=str, help=""" Filter. A piece of python code to filter. E.g. type(member) == npoapi.xml.mediaupdate.programUpdateType member.type == 'CLIP' 'kort!' in short_title.lower() """)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.client = MediaBackend().configured_login(config_dir=os.path.dirname(__file__)).env(ENV).debug()
#!/usr/bin/env python3 """ """ from npoapi import MediaBackend from npoapi.xml import mediaupdate poms = MediaBackend().command_line_client() poms.add_argument('mid', type=str, nargs=1, help='The mid of the object to get') poms.add_argument('duration', type=str, nargs=1, help='The duration to set') args = poms.parse_args() bytes = poms.get(args.mid[0]) update = mediaupdate.CreateFromDocument(bytes) duration = args.duration[0] update.duration = duration poms.post(update)
#!/usr/bin/env python3 """The generic tool npo_mediabackend will let you too must things. This is an example for how to make a more specific tool""" from npoapi import MediaBackend from npoapi.xml import mediaupdate, media import sys poms = MediaBackend().command_line_client() poms.add_argument('id', type=str, nargs=1, help='The mid or crid of the object to handle') poms.add_argument('type', type=str, nargs='?', help='The new type') poms.add_argument('avType', type=str, nargs='?', help='The new avtype') args = poms.parse_args() id = args.id[0] xml = poms.get(id, ignore_not_found=True) if xml: object = mediaupdate.CreateFromDocument(xml) if args.type: if type(object) is mediaupdate.programUpdateType: object.type = getattr(media.programTypeEnum, args.type) elif type(object) is mediaupdate.groupUpdateType: object.type = getattr(media.groupTypeEnum, args.type) if args.avType: object.avType = getattr(media.avTypeEnum, args.avType) poms.post(object) else: sys.stderr.write("The object %s is not found in poms")
class MediaBackendTest(unittest.TestCase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.client = MediaBackend().configured_login(config_dir=os.path.dirname(__file__)).env(ENV).debug() def test_xml_to_bytes_string(self): self.assertEquals("<a xmlns='urn:vpro:media:update:2009' />", self.client.xml_to_bytes("<a xmlns='urn:vpro:media:update:2009' />").decode("utf-8")) def test_xml_to_bytes_minidom(self): self.assertEquals('<a xmlns="urn:vpro:media:update:2009"/>', self.client.xml_to_bytes( minidom.parseString("<a xmlns='urn:vpro:media:update:2009' />").documentElement).decode( "utf-8")) def test_append_params(self): self.assertEquals("http://vpro.nl?a=a&x=y", self.client.append_params("http://vpro.nl", include_errors=False, a="a", x="y")) def test_set_duration(self): existing = poms.CreateFromDocument(self.client.get("WO_VPRO_1422026")) existing.duration = "PT30M" self.client.post(existing) def test_get_locations(self): bytes=self.client.get_locations("POMS_VPRO_1421796") locations=poms.CreateFromDocument(bytes) print(str(locations)) def test_get_segments(self): bytes = self.client.get("RBX_AT_2145721") existing = mediaupdate.CreateFromDocument(bytes) self.assertTrue(type(existing) == mediaupdate.segmentUpdateType) def test_get_images(self): mid="POMS_VPRO_1421796" media=poms.CreateFromDocument(self.client.get(mid)) print(len(media.images.image)) image=media.images.image[0] bytes = self.client.get_images("POMS_VPRO_1421796") images= poms.CreateFromDocument(bytes) image2=images.wildcardElements()[0] self.assertEquals(image.title, image2.title) self.assertEquals(image2.title, "sdf") print(image2.toxml()) def test_set_location(self): mid = "POMS_VPRO_1421796" self.client.set_location(mid, "http://www.vpro.nl/123", publishStop="2012-01-11T17:16:01.287Z") def test_set_location_by_id(self): mid = "POMS_VPRO_1421796" self.client.set_location(mid, 58758190, publishStop="2012-01-11T17:16:01.287Z") def test_set_location_by_id_as_string(self): mid = "POMS_VPRO_1421796" self.client.set_location(mid, "58758190", publishStop="2013-01-11T17:16:01.287Z") def test_set_location_by_urn(self): mid = "POMS_VPRO_1421796" self.client.set_location(mid, "urn:vpro:media:location:58758190", publishStop="2014-01-11T17:16:01.287Z") def test_create_location(self): mid = "POMS_VPRO_1421796" self.client.set_location(mid, "http://www.vpro.nl/" + str(round(time.time())) + ".mp3", publishStop="2012-01-11T17:16:01.287Z")
#!/usr/bin/env python3 """Script to add a image to all members of a group.""" from npoapi import MediaBackend, MediaBackendUtil as MU import npoapi.xml.mediaupdate from xml.dom import minidom api = MediaBackend().command_line_client() api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') api.add_argument('image', type=str, nargs='+', help='New image. If more than one is provided, they will be used alternately') api.add_argument('title', type=str, nargs='?', help='title for new images') api.add_argument('--only_if_none', action='store_true', default=False, help='Only if no images present yet') api.add_argument('--dry_run', action='store_true', default=False, help='Dry run') api.add_argument('--filter', type=str, help=""" Filter. A piece of python code to filter. E.g. "memberType == npoapi.xml.mediaupdate.programUpdateType" or "member.type == 'PROMO'" """) api.add_argument('--to_object', action='store_true', default=False, help='Add to object itself too') api.add_argument('--to_object_only', action='store_true', default=False, help='Add to object itself only') api.add_argument('--max', type=int, nargs='?', help='Maximum number of objects to process') api.add_argument('--max_query', type=int, nargs='?', help='Maximum number of objects to find') api.add_argument('--segments', action='store_true', default=False, help='') MU.logger = api.logger args = api.parse_args() mid = args.mid[0] images = args.image title = args.title mediaUpdate = api.get_object(mid, ignore_not_found=True) only_if_none = args.only_if_none filter = args.filter
#!/usr/bin/env python3 """Script to add a image to all members of a group.""" from npoapi import MediaBackend, MediaBackendUtil as MU from npoapi.xml import mediaupdate from npoapi.xml import poms api = MediaBackend().command_line_client() api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') api.add_argument('group', type=str, nargs=1, help='Group') args = api.parse_args() mid = args.mid[0] group = args.group[0] media = poms.CreateFromDocument(api.get(mid)) memberOf = mediaupdate.memberRefUpdateType(group) memberOf.highlighted = False media.memberOf.append(memberOf) api.post(media)
#!/usr/bin/env python3 from npoapi import MediaBackend from mediaupdate import MediaUpdate import pprint api = MediaBackend().command_line_client() api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') args = api.parse_args() mid = args.mid[0] print(pprint.pformat(MediaUpdate.CreateFromDOM(api.get(mid))))
#!/usr/bin/env python3 """Script to add a image to all members of a group.""" from npoapi import MediaBackend, MediaBackendUtil as MU from npoapi.xml import mediaupdate from npoapi.xml import poms api = MediaBackend().command_line_client() api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') api.add_argument('group', type=str, nargs=1, help='Group') api.add_argument('--use_get', action='store_true', default=False) api.add_argument('--position', type=int, default=None) args = api.parse_args() mid = args.mid[0] group = args.group[0] if args.use_get: media = poms.CreateFromDocument(api.get(mid)) memberOf = mediaupdate.memberRef(group) memberOf.highlighted = False memberOf.position = args.position media.memberOf.append(memberOf) api.post(media) else: api.add_member(mid, group, position=args.position)
#!/usr/bin/env python3 """ """ """Script to add a location """ from npoapi import MediaBackend, MediaBackendUtil as MU import requests import pickle import os.path import time api = MediaBackend().command_line_client() api.add_argument('mid', type=str, nargs=1, help='The mid of the object to handle') args = api.parse_args() filename = "/tmp/members.pkl" if os.path.isfile(filename): with open(filename, 'rb') as input: members = pickle.load(input) else: members = [] MU.descendants(api, args.mid[0], batch=200, target=members, log_progress=True) with open(filename, 'wb') as output: pickle.dump(members, output, pickle.HIGHEST_PROTOCOL) api.logger.info("Wrote %s", filename) count_new = 0 count_done = 0 count_404 = 0