bebo-dot-dev / m3u-epg-editor

a python m3u / epg optimizer
120 stars 27 forks source link

Possibility to set or modify tvg-id #49

Closed arjunior26 closed 4 years ago

arjunior26 commented 4 years ago

As you know, service providers don't pay too much attention for giving us a m3u list with valid or complete datas.

Thereby, I think a new option to set/modify tvg-id value would be useful to improve linkage with epg. Following your latest changes, it would be easy to make it like this:

# set missing or wrong tvg_id
def set_tvg_id(tvg_id, tvg_name, array):
    for item in array:
        tvg_name_value = next(iter(item.keys()))
        tvg_id_value = next(iter(item.values()))

        if tvg_name.startswith(tvg_name_value):
            tvg_id = tvg_id_value
    return tvg_id

add this line to filter_m3u_entries()

m3u_entry.tvg_id = set_tvg_id(m3u_entry.tvg_id, m3u_entry.tvg_name, args.id_transforms)

and of course modify script to handle new argument...

Maybe the best way would be to modify your transform_string_value() function and add one source argument for search value. If search value is empty, just replace string_value with replacement_value like it's done actually.

Let you decide for the right way ;)

Thank you !

arjunior26 commented 4 years ago

I think my previous message needs some clarifications.

It's probably better to set/modify tvg_id depending of channel name (using tvg-name or name property) rather than make string transformation like it's done for groups or channels names. In this last case, empty tvg-ig couldn't be set with a correct value. This is why I add tvg_name argument in set_tvg_id()

bebo-dot-dev commented 4 years ago

Thank you, this all makes sense.

Before I make a start on this I thought I'd ask you if you think this change should only apply updates to the tvg-id attribute value in the m3u data. In other words do you think we're able to make an assumption that the data in the epg xml is semi-reasonable and this feature will exist to attempt to match edited m3u tvg-id values to the data in the epg xml?

arjunior26 commented 4 years ago

Yes the goal here is to change only tvg-id attribute in m3u data to attempt to match data in the epg xml. It usefull if for example we use epg xml which are not provided by the same service provider (values used for channel property in programme element are unfortunately not standardized)

bebo-dot-dev commented 4 years ago

Thank you for clarifying, I'll make a start on this change asap.

bebo-dot-dev commented 4 years ago

One new commit pushed to the master branch.

This is the introduction of the new optional -it / id_transforms argument, i.e.:

{"id_transforms": [
    {"FILM 4": "film4.uk tvg-id edited"}
]}

Please give that a try, hopefully it will work how you intend it to.

arjunior26 commented 4 years ago

Yeah, exactly like expected or almost :) Strange results occured here if for example, one or several tvg-id contain tvg-name value of channel.

Suppose we have this m3u file (add voluntary bad datas for illustration):

#EXTM3U
#EXTINF:-1 tvg-id="fr.FRANCE 2" tvg-name="FR2" group-title="TNTSAT",FR2
http://xxxxxx.xxxxx/yyyyyyy/zz
#EXTINF:-1 tvg-id="fr.france" tvg-name="FRANCE 2" group-title="TNTSAT",FRANCE 2
http://xxxxxx.xxxxx/yyyyyyy/zz
#EXTINF:-1 tvg-id="fr.FRANCE 2" tvg-name="FRANCE 3" group-title="TNTSAT",FRANCE 3
http://xxxxxx.xxxxx/yyyyyyy/zz

and define new id_transforms argument like this:

"id_transforms": [
    {"FRANCE 2": "france2.fr"}
],

We expect that only tvg-id of channel with tvg-name="FRANCE 2" would be modify but it's not the case. Give it a try please...

So finally, I modify your function like this and all is perfect:

def transform_string_value(string_value, compare_value, transforms):
    for transform_item in transforms:
        src_value = next(iter(transform_item.keys()))
        replacement_value = next(iter(transform_item.values()))
        if compare_value is not None:
            if compare_value.startswith(src_value):
                string_value = replacement_value
        elif src_value in string_value:
            string_value = string_value.replace(src_value, replacement_value)
    return string_value

I'm curious to know if you get same results...

bebo-dot-dev commented 4 years ago

Good catch, yes I see the same problem when testing with your sample m3u data and id_transform set. Your proposed fix works perfectly, it is pushed in now.

Thanks for that, very much appreciated.

arjunior26 commented 4 years ago

OK thank you for test and feedback. Do you have any explanation about not working "and" operator in this specific case ??

bebo-dot-dev commented 4 years ago

Yes, the explanation is that the original version https://github.com/jjssoftware/m3u-epg-editor/commit/5adb4570ec36be209abb2cf67cd34fc5dea3f88c#diff-60f6329374a8b305656a72e83f132bd7R571 was buggy:

When a compare_value was passed into the transform_string_value function and when the compare_value.startswith(src_value) condition did not match, that would cause the code to fall through to the elif src_value in string_value: check. In the case of your 3rd m3u data item this just happened to pass / match due to how the data looked. This resulted in the 3rd m3u data item getting it's tvg-id value unexpectedly and incorrectly transformed.

Very good bug spotting on your part, thank you :)

arjunior26 commented 4 years ago

You're welcome. It's clear now. Thank you for highlights ;)

bebo-dot-dev commented 4 years ago

Jolly good, closing.

bigkraig commented 4 years ago

@arjunior26 @jjssoftware Rather than a startswith would you be open to an == or less preferably, a regex?

What i'm finding here is that its not possible to transform tvg_name's that are not unique enough.

For example if you want to transform name but you also have name 2 and name 3s. All 3 would are transformed and 2 are randomly deduped.

bebo-dot-dev commented 4 years ago

Hi @bigkraig personally I'm open to any change in this area that will generally work. This feature was introduced based on rules supplied by @arjunior26 so I'll let them decide what is / is not valid.

arjunior26 commented 4 years ago

Hi @bigkraig @jjssoftware For sure, it would be preferable to use equals() in some cases and in others not :) Suppose we have channels names like "France2 SD", "France2 HD", "France2 Full HD" in our list, using startswith() will permit us to set change easily (only one definition in json file).

However, I think your suggestion is right as current script doesn't let you make changes as you need ! Using equals() will permit to use the script in all configurations ! 👍

bebo-dot-dev commented 4 years ago

Hi @bigkraig + @arjunior26 I've made the suggested change switching .startswith to == within the transform_string_value function since it appears that this change will work as it needs to for both of you.