parker1992 / iptv-proxy

Simple Flask proxy app for m3u files.
MIT License
9 stars 3 forks source link

Implement group filter #8

Open coach1988 opened 2 years ago

coach1988 commented 2 years ago

Allows users to filter out channels tagged with a group-title="\<groupname>" within the #EXTINF via a new configuration variable

parker1992 commented 2 years ago

Can’t this be done using an m3u editor, such as m3u4u.com?

I was considering making a separate m3u editor web app similar to that site that can be self-hosted alongside this.

My only concern adding the group filter is that if we add this, then this app that’s simply a proxy app is now also an m3u editor app, which seems a bit out of scope.

Let me know your thoughts.

coach1988 commented 2 years ago

Good point, i was thinking about it more as access restriction in terms of content controls, which would be kind of a proxy's thing (depending on whether you want to reroute, cache or filter with it), but i agree, in its core it's about the network aspect.

I just came here to tell you not to merge it, as it's acting funky for some reason for me when I'm passing the filters via the environment (via portainer) instead of reading it from a file. you don't happen to know a reason for that, right?

So in a nutshell: Depending on the point of view it could be within scope, but it could also be out of it just aswell;) I've just implemented it because i thought it would be useful (as I've wanted to do that for my personal use) and relatively quick and easy to do=)

(I would definitely prefer some kind of self-hosted web-ui to manage playlists though, but that's further down the road as it sounds and I won't be of much help I'm afraid)

EDIT: Oh, and why not that page? Because I don't like the idea of my credentials being there + I prefer to access the playlist myself via verified tunnels, I'm not sure how they would handle requests about whose playlists have been synced with specific hosts. Not paranoid, but if I can avoid blasting out credentials and instead self-host or get around the required service somehow, I'll try that first=)

parker1992 commented 2 years ago

I just came here to tell you not to merge it, as it's acting funky for some reason for me when I'm passing the filters via the environment (via portainer) instead of reading it from a file. you don't happen to know a reason for that, right?

I didn't pull down the branch yet so I'm not sure. I don't mind spending a few minutes to help you out there and you can run this as its own fork.

Let me think about this feature a bit more, because I'm still on the side that it shouldn't be here, but you also make a solid point about being skeptical about m3u4u.com.

parker1992 commented 2 years ago

I took a look and I replaced the regex replace from

content = re.sub(rf'(#EXTINF.*group-title=\".*{filter}.*\".*\n.*(\n|\Z))','', content, flags=0)

to:

content = re.sub(rf'(#EXTINF.*group-title=\".*{filter}.*\".*\n.*\n)', '', content, flags=re.M)

I'm not sure what the \Z does, or what the flags=0 represents.

Also when debugging in VS code, I had some issues with environment variables, so in case you're having the same issue, follow this:

https://stackoverflow.com/questions/62295889/how-to-set-environment-variables-in-vscode-when-running-flask-app

I think I also found a bug in this where your regex looks for {filter}.* which can cause for false matches. For example, if someone adds the filter "United", it will match "United States" because "United States" fits United.*. You should probably surround the filters in quotes within the regex so it only looks for exact matches.

coach1988 commented 2 years ago

I took a look and I replaced the regex replace from

content = re.sub(rf'(#EXTINF.*group-title=\".*{filter}.*\".*\n.*(\n|\Z))','', content, flags=0)

to:

content = re.sub(rf'(#EXTINF.*group-title=\".*{filter}.*\".*\n.*\n)', '', content, flags=re.M)

I'm not sure what the \Z does, or what the flags=0 represents.

The \Z is supposed to find the end of the string (as it won't work for the last entry in the list otherwise if my tests were correct due to the missing second newline) and the flags=0 means no flags, as the MULTILINE caused the matching lines to get replaced with empty lines instead of nothing, leading to cluttered output files (which would probably still work fine though or could have been easily filtered out in a final parsing pass via RegEx)

Also when debugging in VS code, I had some issues with environment variables, so in case you're having the same issue, follow this:

https://stackoverflow.com/questions/62295889/how-to-set-environment-variables-in-vscode-when-running-flask-app

No, it's unfortunately when running the container via a docker-compose stack (haven't tested it via docker run -e ...), so I would have to add those to the parents' container environment, leading to way more fuzz than necessary. I've helped myself by mounting a config.ini and using that instead of the environment variables, works perfectly fine.

I think I also found a bug in this where your regex looks for {filter}.* which can cause for false matches. For example, if someone adds the filter "United", it will match "United States" because "United States" fits United.*. You should probably surround the filters in quotes within the regex so it only looks for exact matches.

I've realized it later on, but kept it as a feature, as it allows to easily filter out whole families of groups (e.g. using UK| as a filter for UK| Sports, UK| Documentary, etc.) or keywords (ADULT or XXX) EDIT: Same applies to the preceding .*

coach1988 commented 2 years ago

Let me think about this feature a bit more, because I'm still on the side that it shouldn't be here, but you also make a solid point about being skeptical about m3u4u.com.

To me it looks as if you've got the following options: a) Probably what you originally had in mind: A small, simple service with a very targeted set of proxy functions, used alongside other services (local or remote, e.g. m3u4u) that handle access and channel management <-- Very much the Linux philosophy BTW, so i would support that decision of course, too=) b) You decide that the position in the network and for the clients is perfect to build the base for something like tvheadend, just focused on ITPV and without the remuxing/transcoding part, basically the one-stop iptv stream relay (to avoid the limits of the term "proxy"), especially as you were thinking about creating something like m3u4u anyways; For a solid start that would incorporate imho at least though:

That would basically cover the functions that are implemented now + the added required mulituser adjustments (if i understand the flask streaming part right, this should already scale well to several users, or at least that should be handled by flask).

parker1992 commented 2 years ago

Thanks for the detailed response.

Yeah that’s definitely how I envision the m3u editor.

I’ll probably make that one in Django as I’m pretty sure Django has built-in user management that I can take advantage of.

I’m not sure when I’ll start it, I’m thinking in a week or two, but I’ll let you know when I release something as that will also likely be in another repo.