forked from marklieberman/iptvtuner
/
M3UParser.cs
110 lines (98 loc) · 3.54 KB
/
M3UParser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using IPTVTuner.Model;
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace IPTVTuner
{
/**
* A streaming M3UEXT parser with filtering.
*/
partial class M3UParser
{
private readonly Regex idRegex;
private readonly Regex nameRegex;
private readonly Regex logoRegex;
private readonly Regex groupRegex;
public M3UParser()
{
// TODO Support custom attribute names in configuration.
idRegex = new Regex("tvg-id=\"([^\"]+)\"");
nameRegex = new Regex("tvg-name=\"([^\"]+)\"");
logoRegex = new Regex("tvg-logo=\"([^\"]+)\"");
groupRegex = new Regex("group-title=\"([^\"]+)\"");
}
/**
* Filter function to remove channels from the M3U.
*/
public Func<ProviderChannel, bool> Filter
{
get;
set;
}
/**
* Parse an M3U stream with a filter to remove unwanted entries.
*/
public async Task<ProviderChannels> Parse(StreamReader stream)
{
var currentEntry = new ProviderChannel();
var m3u = new ProviderChannels();
using (stream)
{
string line;
while ((line = await stream.ReadLineAsync()) != null)
{
if (line.StartsWith("#EXTM3U"))
{
// Ignore the header.
}
else
if (line.StartsWith("#EXTINF"))
{
// Populate the entry ID.
currentEntry.ID = extractAttribute(idRegex, line);
// Populate the entry name.
currentEntry.Name = extractAttribute(nameRegex, line);
if (logoRegex != null)
{
// Populate the entry logo.
currentEntry.Logo = extractAttribute(logoRegex, line);
}
if (groupRegex != null)
{
// Populate the entry group.
currentEntry.Group = extractAttribute(groupRegex, line);
}
}
else
if (line.StartsWith("#"))
{
// Ignore comments.
}
else
{
// Populate the entry URL.
currentEntry.URL = line;
// Filter entries from the list.
if ((Filter == null) || Filter.Invoke(currentEntry))
{
// Add the entry to the list.
m3u.Add(currentEntry);
}
// Moving to the next entry.
currentEntry = new ProviderChannel();
}
}
}
return m3u;
}
/**
* Extract an attribute value from the extended info.
*/
private string extractAttribute(Regex regex, string line)
{
var match = regex.Match(line);
return match.Success ? match.Groups[1].Value : null;
}
}
}