M3U parser works, done some unit tests
This commit is contained in:
parent
fbec61ffa5
commit
2c8a181b1c
3 changed files with 134 additions and 45 deletions
|
|
@ -1,64 +1,39 @@
|
||||||
package com.mykola2312.mptv.parser;
|
package com.mykola2312.mptv.parser;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Scanner;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
import com.mykola2312.mptv.parser.M3UException.Type;
|
|
||||||
|
|
||||||
public class M3U {
|
public class M3U {
|
||||||
public class Item {
|
@NonNull
|
||||||
@NonNull
|
public String title;
|
||||||
public String title;
|
|
||||||
|
|
||||||
public String groupTitle;
|
public String groupTitle;
|
||||||
public String tvgLogo;
|
public String tvgLogo;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public String url;
|
public String url;
|
||||||
|
|
||||||
|
public M3U(String tags, String title) {
|
||||||
|
parseTags(tags);
|
||||||
|
this.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Item> items = new ArrayList<>();
|
private static final Pattern EXTINF_TAG = Pattern.compile("^(.*)=\"(.*)\"");
|
||||||
|
|
||||||
public M3U(ArrayList<Item> items) {
|
private void parseTags(String tags) {
|
||||||
this.items = items;
|
for (String tag : tags.split(" ")) {
|
||||||
}
|
Matcher matcher = EXTINF_TAG.matcher(tag);
|
||||||
|
if (matcher.find()) {
|
||||||
|
String name = matcher.group(1);
|
||||||
|
String value = matcher.group(2);
|
||||||
|
|
||||||
private static final Pattern HEADER = Pattern.compile("^#EXTM3U");
|
switch (name) {
|
||||||
private static final Pattern EXTINF = Pattern.compile("^(?:#EXTINF:-?\\d\\s*)(.*?),(.*)$");
|
case "group-title" -> groupTitle = value;
|
||||||
|
case "tvg-logo" -> tvgLogo = value;
|
||||||
public static M3U parse(String data) throws M3UException {
|
|
||||||
ArrayList<Item> items = new ArrayList<>();
|
|
||||||
|
|
||||||
// state
|
|
||||||
boolean headerLine = true;
|
|
||||||
|
|
||||||
try (Scanner scanner = new Scanner(data)) {
|
|
||||||
while (scanner.hasNextLine()) {
|
|
||||||
String line = scanner.nextLine();
|
|
||||||
|
|
||||||
if (headerLine) {
|
|
||||||
Matcher matcher = HEADER.matcher(line);
|
|
||||||
if (!matcher.find()) {
|
|
||||||
throw new M3UException(Type.NOT_AN_M3U);
|
|
||||||
}
|
|
||||||
|
|
||||||
headerLine = false;
|
|
||||||
} else {
|
|
||||||
Matcher matcher = EXTINF.matcher(line);
|
|
||||||
if (matcher.find()) {
|
|
||||||
String tags = matcher.group(1);
|
|
||||||
String title = matcher.group(2);
|
|
||||||
|
|
||||||
System.out.printf("tags: %s | title: %s\n", tags, title);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new M3U(items);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
66
src/main/java/com/mykola2312/mptv/parser/M3UParser.java
Normal file
66
src/main/java/com/mykola2312/mptv/parser/M3UParser.java
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.mykola2312.mptv.parser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import com.mykola2312.mptv.parser.M3UException.Type;
|
||||||
|
|
||||||
|
public class M3UParser {
|
||||||
|
private static final Pattern HEADER = Pattern.compile("^#EXTM3U");
|
||||||
|
private static final Pattern EXTINF = Pattern.compile("^(?:#EXTINF:-?\\d\\s*)(.*?),(.*)$");
|
||||||
|
|
||||||
|
private enum ParserState {
|
||||||
|
HEADER_LINE,
|
||||||
|
EXTINF_LINE,
|
||||||
|
URL_LINE
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<M3U> parse(String data) throws M3UException {
|
||||||
|
ArrayList<M3U> items = new ArrayList<>();
|
||||||
|
|
||||||
|
ParserState state = ParserState.HEADER_LINE;
|
||||||
|
M3U item = null;
|
||||||
|
|
||||||
|
try (Scanner scanner = new Scanner(data)) {
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
String line = scanner.nextLine();
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case HEADER_LINE -> {
|
||||||
|
Matcher matcher = HEADER.matcher(line);
|
||||||
|
if (!matcher.find()) {
|
||||||
|
throw new M3UException(Type.NOT_AN_M3U);
|
||||||
|
}
|
||||||
|
|
||||||
|
state = ParserState.EXTINF_LINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EXTINF_LINE -> {
|
||||||
|
Matcher matcher = EXTINF.matcher(line);
|
||||||
|
if (matcher.find()) {
|
||||||
|
String tags = matcher.group(1);
|
||||||
|
String title = matcher.group(2);
|
||||||
|
|
||||||
|
item = new M3U(tags, title);
|
||||||
|
|
||||||
|
state = ParserState.URL_LINE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case URL_LINE -> {
|
||||||
|
String url = line;
|
||||||
|
|
||||||
|
item.url = url;
|
||||||
|
items.add(item);
|
||||||
|
|
||||||
|
state = ParserState.EXTINF_LINE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/test/java/com/mykola2312/mptv/TestM3U.java
Normal file
48
src/test/java/com/mykola2312/mptv/TestM3U.java
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.mykola2312.mptv;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import com.mykola2312.mptv.parser.M3U;
|
||||||
|
import com.mykola2312.mptv.parser.M3UException;
|
||||||
|
import com.mykola2312.mptv.parser.M3UParser;
|
||||||
|
|
||||||
|
public class TestM3U {
|
||||||
|
private static final String M3U_GOOD = """
|
||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 group-title="test1" tvg-logo="https://example.com/logo.jpg",Test title 1
|
||||||
|
http://example.org/video1.m3u8
|
||||||
|
|
||||||
|
#EXTINF:-1 group-title="test2" ,Test title 2
|
||||||
|
http://example.org/video2.m3u8
|
||||||
|
""";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testM3uGood() {
|
||||||
|
ArrayList<M3U> items = M3UParser.parse(M3U_GOOD);
|
||||||
|
assertNotEquals(0, items.size());
|
||||||
|
|
||||||
|
M3U item = items.get(0);
|
||||||
|
assertEquals("Test title 1", item.title);
|
||||||
|
assertEquals("test1", item.groupTitle);
|
||||||
|
assertEquals("http://example.org/video1.m3u8", item.url);
|
||||||
|
assertEquals("https://example.com/logo.jpg", item.tvgLogo);
|
||||||
|
|
||||||
|
item = items.get(1);
|
||||||
|
assertEquals("Test title 2", item.title);
|
||||||
|
assertEquals("test2", item.groupTitle);
|
||||||
|
assertEquals("http://example.org/video2.m3u8", item.url);
|
||||||
|
assertNull(item.tvgLogo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testM3uBad() {
|
||||||
|
assertThrows(M3UException.class, () -> M3UParser.parse("some random gibberish data"));
|
||||||
|
|
||||||
|
ArrayList<M3U> items = M3UParser.parse("#EXTM3U");
|
||||||
|
assertEquals(0, items.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue