Merge pull request #4893 from damoasda/robolectric-feed-parser2

Run AtomParserTest and RssParserTest with Robolectric
This commit is contained in:
ByteHamster 2021-01-24 12:20:09 +01:00 committed by GitHub
commit a36d66bf35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 198 additions and 388 deletions

View File

@ -1,40 +0,0 @@
package de.test.antennapod.handler;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
import de.test.antennapod.util.syndication.feedgenerator.AtomGenerator;
import org.junit.Test;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
/**
* Tests for Atom feeds in FeedHandler.
*/
@SmallTest
public class AtomParserTest extends FeedParserTestBase {
@Test
public void testAtomBasic() throws Exception {
Feed f1 = createTestFeed(10, true);
Feed f2 = runFeedTest(f1, new AtomGenerator(), "UTF-8", 0);
feedValid(f1, f2, Feed.TYPE_ATOM1);
}
@Test
public void testLogoWithWhitespace() throws Exception {
String logo = "https://example.com/image.png";
Feed f1 = createTestFeed(0, false);
f1.setImageUrl(null);
Feed f2 = runFeedTest(f1, new AtomGenerator() {
@Override
protected void writeAdditionalAttributes(XmlSerializer xml) throws IOException {
xml.startTag(null, "logo");
xml.text(" " + logo + "\n");
xml.endTag(null, "logo");
}
}, "UTF-8", 0);
assertEquals(logo, f2.getImageUrl());
}
}

View File

@ -1,154 +0,0 @@
package de.test.antennapod.handler;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.syndication.handler.FeedHandler;
import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException;
import de.test.antennapod.util.syndication.feedgenerator.FeedGenerator;
import org.junit.After;
import org.junit.Before;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Tests for FeedHandler.
*/
public abstract class FeedParserTestBase {
private static final String FEEDS_DIR = "testfeeds";
private File file = null;
private OutputStream outputStream = null;
@Before
public void setUp() throws Exception {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
File destDir = context.getExternalFilesDir(FEEDS_DIR);
assertNotNull(destDir);
file = new File(destDir, "feed.xml");
file.delete();
assertNotNull(file);
assertFalse(file.exists());
outputStream = new FileOutputStream(file);
}
@After
public void tearDown() throws Exception {
file.delete();
file = null;
outputStream.close();
outputStream = null;
}
protected Feed runFeedTest(Feed feed, FeedGenerator g, String encoding, long flags)
throws IOException, UnsupportedFeedtypeException, SAXException, ParserConfigurationException {
g.writeFeed(feed, outputStream, encoding, flags);
FeedHandler handler = new FeedHandler();
Feed parsedFeed = new Feed(feed.getDownload_url(), feed.getLastUpdate());
parsedFeed.setFile_url(file.getAbsolutePath());
parsedFeed.setDownloaded(true);
handler.parseFeed(parsedFeed);
return parsedFeed;
}
protected void feedValid(Feed feed, Feed parsedFeed, String feedType) {
assertEquals(feed.getTitle(), parsedFeed.getTitle());
if (feedType.equals(Feed.TYPE_ATOM1)) {
assertEquals(feed.getFeedIdentifier(), parsedFeed.getFeedIdentifier());
} else {
assertEquals(feed.getLanguage(), parsedFeed.getLanguage());
}
assertEquals(feed.getLink(), parsedFeed.getLink());
assertEquals(feed.getDescription(), parsedFeed.getDescription());
assertEquals(feed.getPaymentLink(), parsedFeed.getPaymentLink());
assertEquals(feed.getImageUrl(), parsedFeed.getImageUrl());
if (feed.getItems() != null) {
assertNotNull(parsedFeed.getItems());
assertEquals(feed.getItems().size(), parsedFeed.getItems().size());
for (int i = 0; i < feed.getItems().size(); i++) {
FeedItem item = feed.getItems().get(i);
FeedItem parsedItem = parsedFeed.getItems().get(i);
if (item.getItemIdentifier() != null) {
assertEquals(item.getItemIdentifier(), parsedItem.getItemIdentifier());
}
assertEquals(item.getTitle(), parsedItem.getTitle());
assertEquals(item.getDescription(), parsedItem.getDescription());
assertEquals(item.getContentEncoded(), parsedItem.getContentEncoded());
assertEquals(item.getLink(), parsedItem.getLink());
assertEquals(item.getPubDate().getTime(), parsedItem.getPubDate().getTime());
assertEquals(item.getPaymentLink(), parsedItem.getPaymentLink());
if (item.hasMedia()) {
assertTrue(parsedItem.hasMedia());
FeedMedia media = item.getMedia();
FeedMedia parsedMedia = parsedItem.getMedia();
assertEquals(media.getDownload_url(), parsedMedia.getDownload_url());
assertEquals(media.getSize(), parsedMedia.getSize());
assertEquals(media.getMime_type(), parsedMedia.getMime_type());
}
assertEquals(feed.getImageUrl(), item.getImageLocation());
if (item.getChapters() != null) {
assertNotNull(parsedItem.getChapters());
assertEquals(item.getChapters().size(), parsedItem.getChapters().size());
List<Chapter> chapters = item.getChapters();
List<Chapter> parsedChapters = parsedItem.getChapters();
for (int j = 0; j < chapters.size(); j++) {
Chapter chapter = chapters.get(j);
Chapter parsedChapter = parsedChapters.get(j);
assertEquals(chapter.getTitle(), parsedChapter.getTitle());
assertEquals(chapter.getLink(), parsedChapter.getLink());
}
}
}
}
}
protected Feed createTestFeed(int numItems, boolean withFeedMedia) {
Feed feed = new Feed(0, null, "title", "http://example.com", "This is the description",
"http://example.com/payment", "Daniel", "en", null, "http://example.com/feed",
"http://example.com/picture", file.getAbsolutePath(), "http://example.com/feed", true);
feed.setItems(new ArrayList<>());
for (int i = 0; i < numItems; i++) {
FeedItem item = new FeedItem(0, "item-" + i, "http://example.com/item-" + i,
"http://example.com/items/" + i, new Date(i * 60000), FeedItem.UNPLAYED, feed);
feed.getItems().add(item);
if (withFeedMedia) {
item.setMedia(new FeedMedia(0, item, 4711, 0, 1024 * 1024, "audio/mp3", null,
"http://example.com/media-" + i, false, null, 0, 0));
}
}
return feed;
}
}

View File

@ -1,63 +0,0 @@
package de.test.antennapod.handler;
import androidx.test.filters.SmallTest;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.syndication.namespace.NSMedia;
import de.test.antennapod.util.syndication.feedgenerator.Rss2Generator;
import org.junit.Test;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
/**
* Tests for RSS feeds in FeedHandler.
*/
@SmallTest
public class RssParserTest extends FeedParserTestBase {
@Test
public void testRss2Basic() throws Exception {
Feed f1 = createTestFeed(10, true);
Feed f2 = runFeedTest(f1, new Rss2Generator(), "UTF-8", Rss2Generator.FEATURE_WRITE_GUID);
feedValid(f1, f2, Feed.TYPE_RSS2);
}
@Test
public void testImageWithWhitespace() throws Exception {
String image = "https://example.com/image.png";
Feed f1 = createTestFeed(0, false);
f1.setImageUrl(null);
Feed f2 = runFeedTest(f1, new Rss2Generator() {
@Override
protected void writeAdditionalAttributes(XmlSerializer xml) throws IOException {
xml.startTag(null, "image");
xml.startTag(null, "url");
xml.text(" " + image + "\n");
xml.endTag(null, "url");
xml.endTag(null, "image");
}
}, "UTF-8", 0);
assertEquals(image, f2.getImageUrl());
}
@Test
public void testMediaContentMime() throws Exception {
Feed f1 = createTestFeed(0, false);
f1.setImageUrl(null);
Feed f2 = runFeedTest(f1, new Rss2Generator() {
@Override
protected void writeAdditionalAttributes(XmlSerializer xml) throws IOException {
xml.setPrefix(NSMedia.NSTAG, NSMedia.NSURI);
xml.startTag(null, "item");
xml.startTag(NSMedia.NSURI, "content");
xml.attribute(null, "url", "https://www.example.com/file.mp4");
xml.attribute(null, "medium", "video");
xml.endTag(NSMedia.NSURI, "content");
xml.endTag(null, "item");
}
}, "UTF-8", 0);
assertEquals(MediaType.VIDEO, f2.getItems().get(0).getMedia().getMediaType());
}
}

View File

@ -1,131 +0,0 @@
package de.test.antennapod.util.syndication.feedgenerator;
import android.util.Xml;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.OutputStream;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.util.DateUtils;
/**
* Creates Atom feeds. See FeedGenerator for more information.
*/
public class AtomGenerator implements FeedGenerator {
private static final String NS_ATOM = "http://www.w3.org/2005/Atom";
private static final long FEATURE_USE_RFC3339LOCAL = 1;
@Override
public void writeFeed(Feed feed, OutputStream outputStream, String encoding, long flags) throws IOException {
if (feed == null) throw new IllegalArgumentException("feed = null");
if (outputStream == null) throw new IllegalArgumentException("outputStream = null");
if (encoding == null) throw new IllegalArgumentException("encoding = null");
XmlSerializer xml = Xml.newSerializer();
xml.setOutput(outputStream, encoding);
xml.startDocument(encoding, null);
xml.startTag(null, "feed");
xml.attribute(null, "xmlns", NS_ATOM);
// Write Feed data
if (feed.getIdentifyingValue() != null) {
xml.startTag(null, "id");
xml.text(feed.getIdentifyingValue());
xml.endTag(null, "id");
}
if (feed.getTitle() != null) {
xml.startTag(null, "title");
xml.text(feed.getTitle());
xml.endTag(null, "title");
}
if (feed.getLink() != null) {
xml.startTag(null, "link");
xml.attribute(null, "rel", "alternate");
xml.attribute(null, "href", feed.getLink());
xml.endTag(null, "link");
}
if (feed.getDescription() != null) {
xml.startTag(null, "subtitle");
xml.text(feed.getDescription());
xml.endTag(null, "subtitle");
}
if (feed.getImageUrl() != null) {
xml.startTag(null, "logo");
xml.text(feed.getImageUrl());
xml.endTag(null, "logo");
}
if (feed.getPaymentLink() != null) {
GeneratorUtil.addPaymentLink(xml, feed.getPaymentLink(), false);
}
// Write FeedItem data
if (feed.getItems() != null) {
for (FeedItem item : feed.getItems()) {
xml.startTag(null, "entry");
if (item.getIdentifyingValue() != null) {
xml.startTag(null, "id");
xml.text(item.getIdentifyingValue());
xml.endTag(null, "id");
}
if (item.getTitle() != null) {
xml.startTag(null, "title");
xml.text(item.getTitle());
xml.endTag(null, "title");
}
if (item.getLink() != null) {
xml.startTag(null, "link");
xml.attribute(null, "rel", "alternate");
xml.attribute(null, "href", item.getLink());
xml.endTag(null, "link");
}
if (item.getPubDate() != null) {
xml.startTag(null, "published");
if ((flags & FEATURE_USE_RFC3339LOCAL) != 0) {
xml.text(DateUtils.formatRFC3339Local(item.getPubDate()));
} else {
xml.text(DateUtils.formatRFC3339UTC(item.getPubDate()));
}
xml.endTag(null, "published");
}
if (item.getDescription() != null) {
xml.startTag(null, "content");
xml.text(item.getDescription());
xml.endTag(null, "content");
}
if (item.getMedia() != null) {
FeedMedia media = item.getMedia();
xml.startTag(null, "link");
xml.attribute(null, "rel", "enclosure");
xml.attribute(null, "href", media.getDownload_url());
xml.attribute(null, "type", media.getMime_type());
xml.attribute(null, "length", String.valueOf(media.getSize()));
xml.endTag(null, "link");
}
if (item.getPaymentLink() != null) {
GeneratorUtil.addPaymentLink(xml, item.getPaymentLink(), false);
}
xml.endTag(null, "entry");
}
}
writeAdditionalAttributes(xml);
xml.endTag(null, "feed");
xml.endDocument();
}
protected void writeAdditionalAttributes(XmlSerializer xml) throws IOException {
}
}

View File

@ -0,0 +1,70 @@
package de.danoeh.antennapod.core.syndication.handler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.io.File;
import java.util.Date;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* Tests for Atom feeds in FeedHandler.
*/
@RunWith(RobolectricTestRunner.class)
public class AtomParserTest {
@Test
public void testAtomBasic() throws Exception {
File feedFile = FeedParserTestHelper.getFeedFile("feed-atom-testAtomBasic.xml");
Feed feed = FeedParserTestHelper.runFeedParser(feedFile);
assertEquals(Feed.TYPE_ATOM1, feed.getType());
assertEquals("title", feed.getTitle());
assertEquals("http://example.com/feed", feed.getFeedIdentifier());
assertEquals("http://example.com", feed.getLink());
assertEquals("This is the description", feed.getDescription());
assertEquals("http://example.com/payment", feed.getPaymentLink());
assertEquals("http://example.com/picture", feed.getImageUrl());
assertEquals(10, feed.getItems().size());
for (int i = 0; i < feed.getItems().size(); i++) {
FeedItem item = feed.getItems().get(i);
assertEquals("http://example.com/item-" + i, item.getItemIdentifier());
assertEquals("item-" + i, item.getTitle());
assertNull(item.getDescription());
assertNull(item.getContentEncoded());
assertEquals("http://example.com/items/" + i, item.getLink());
assertEquals(new Date(i * 60000), item.getPubDate());
assertNull(item.getPaymentLink());
assertEquals("http://example.com/picture", item.getImageLocation());
// media
assertTrue(item.hasMedia());
FeedMedia media = item.getMedia();
//noinspection ConstantConditions
assertEquals("http://example.com/media-" + i, media.getDownload_url());
assertEquals(1024 * 1024, media.getSize());
assertEquals("audio/mp3", media.getMime_type());
// chapters
assertNull(item.getChapters());
}
}
@Test
public void testLogoWithWhitespace() throws Exception {
File feedFile = FeedParserTestHelper.getFeedFile("feed-atom-testLogoWithWhitespace.xml");
Feed feed = FeedParserTestHelper.runFeedParser(feedFile);
assertEquals("title", feed.getTitle());
assertEquals("http://example.com/feed", feed.getFeedIdentifier());
assertEquals("http://example.com", feed.getLink());
assertEquals("This is the description", feed.getDescription());
assertEquals("http://example.com/payment", feed.getPaymentLink());
assertEquals("https://example.com/image.png", feed.getImageUrl());
assertEquals(0, feed.getItems().size());
}
}

View File

@ -0,0 +1,35 @@
package de.danoeh.antennapod.core.syndication.handler;
import androidx.annotation.NonNull;
import java.io.File;
import de.danoeh.antennapod.core.feed.Feed;
/**
* Tests for FeedHandler.
*/
public abstract class FeedParserTestHelper {
/**
* Returns the File object for a file in the resources folder.
*/
@NonNull
static File getFeedFile(@NonNull String fileName) {
//noinspection ConstantConditions
return new File(FeedParserTestHelper.class.getClassLoader().getResource(fileName).getFile());
}
/**
* Runs the feed parser on the given file.
*/
@NonNull
static Feed runFeedParser(@NonNull File feedFile) throws Exception {
FeedHandler handler = new FeedHandler();
Feed parsedFeed = new Feed("http://example.com/feed", null);
parsedFeed.setFile_url(feedFile.getAbsolutePath());
parsedFeed.setDownloaded(true);
handler.parseFeed(parsedFeed);
return parsedFeed;
}
}

View File

@ -0,0 +1,86 @@
package de.danoeh.antennapod.core.syndication.handler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.io.File;
import java.util.Date;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
/**
* Tests for RSS feeds in FeedHandler.
*/
@RunWith(RobolectricTestRunner.class)
public class RssParserTest {
@Test
public void testRss2Basic() throws Exception {
File feedFile = FeedParserTestHelper.getFeedFile("feed-rss-testRss2Basic.xml");
Feed feed = FeedParserTestHelper.runFeedParser(feedFile);
assertEquals(Feed.TYPE_RSS2, feed.getType());
assertEquals("title", feed.getTitle());
assertEquals("en", feed.getLanguage());
assertEquals("http://example.com", feed.getLink());
assertEquals("This is the description", feed.getDescription());
assertEquals("http://example.com/payment", feed.getPaymentLink());
assertEquals("http://example.com/picture", feed.getImageUrl());
assertEquals(10, feed.getItems().size());
for (int i = 0; i < feed.getItems().size(); i++) {
FeedItem item = feed.getItems().get(i);
assertEquals("http://example.com/item-" + i, item.getItemIdentifier());
assertEquals("item-" + i, item.getTitle());
assertNull(item.getDescription());
assertNull(item.getContentEncoded());
assertEquals("http://example.com/items/" + i, item.getLink());
assertEquals(new Date(i * 60000), item.getPubDate());
assertNull(item.getPaymentLink());
assertEquals("http://example.com/picture", item.getImageLocation());
// media
assertTrue(item.hasMedia());
FeedMedia media = item.getMedia();
//noinspection ConstantConditions
assertEquals("http://example.com/media-" + i, media.getDownload_url());
assertEquals(1024 * 1024, media.getSize());
assertEquals("audio/mp3", media.getMime_type());
// chapters
assertNull(item.getChapters());
}
}
@Test
public void testImageWithWhitespace() throws Exception {
File feedFile = FeedParserTestHelper.getFeedFile("feed-rss-testImageWithWhitespace.xml");
Feed feed = FeedParserTestHelper.runFeedParser(feedFile);
assertEquals("title", feed.getTitle());
assertEquals("http://example.com", feed.getLink());
assertEquals("This is the description", feed.getDescription());
assertEquals("http://example.com/payment", feed.getPaymentLink());
assertEquals("https://example.com/image.png", feed.getImageUrl());
assertEquals(0, feed.getItems().size());
}
@Test
public void testMediaContentMime() throws Exception {
File feedFile = FeedParserTestHelper.getFeedFile("feed-rss-testMediaContentMime.xml");
Feed feed = FeedParserTestHelper.runFeedParser(feedFile);
assertEquals("title", feed.getTitle());
assertEquals("http://example.com", feed.getLink());
assertEquals("This is the description", feed.getDescription());
assertEquals("http://example.com/payment", feed.getPaymentLink());
assertNull(feed.getImageUrl());
assertEquals(1, feed.getItems().size());
FeedItem feedItem = feed.getItems().get(0);
//noinspection ConstantConditions
assertEquals(MediaType.VIDEO, feedItem.getMedia().getMediaType());
assertEquals("https://www.example.com/file.mp4", feedItem.getMedia().getDownload_url());
}
}

View File

@ -0,0 +1 @@
<?xml version='1.0' encoding='UTF-8' ?><feed xmlns="http://www.w3.org/2005/Atom"><id>http://example.com/feed</id><title>title</title><link rel="alternate" href="http://example.com" /><subtitle>This is the description</subtitle><logo>http://example.com/picture</logo><link rel="payment" href="http://example.com/payment" type="text/html" /><entry><id>http://example.com/item-0</id><title>item-0</title><link rel="alternate" href="http://example.com/items/0" /><published>1970-01-01T00:00:00Z</published><link rel="enclosure" href="http://example.com/media-0" type="audio/mp3" length="1048576" /></entry><entry><id>http://example.com/item-1</id><title>item-1</title><link rel="alternate" href="http://example.com/items/1" /><published>1970-01-01T00:01:00Z</published><link rel="enclosure" href="http://example.com/media-1" type="audio/mp3" length="1048576" /></entry><entry><id>http://example.com/item-2</id><title>item-2</title><link rel="alternate" href="http://example.com/items/2" /><published>1970-01-01T00:02:00Z</published><link rel="enclosure" href="http://example.com/media-2" type="audio/mp3" length="1048576" /></entry><entry><id>http://example.com/item-3</id><title>item-3</title><link rel="alternate" href="http://example.com/items/3" /><published>1970-01-01T00:03:00Z</published><link rel="enclosure" href="http://example.com/media-3" type="audio/mp3" length="1048576" /></entry><entry><id>http://example.com/item-4</id><title>item-4</title><link rel="alternate" href="http://example.com/items/4" /><published>1970-01-01T00:04:00Z</published><link rel="enclosure" href="http://example.com/media-4" type="audio/mp3" length="1048576" /></entry><entry><id>http://example.com/item-5</id><title>item-5</title><link rel="alternate" href="http://example.com/items/5" /><published>1970-01-01T00:05:00Z</published><link rel="enclosure" href="http://example.com/media-5" type="audio/mp3" length="1048576" /></entry><entry><id>http://example.com/item-6</id><title>item-6</title><link rel="alternate" href="http://example.com/items/6" /><published>1970-01-01T00:06:00Z</published><link rel="enclosure" href="http://example.com/media-6" type="audio/mp3" length="1048576" /></entry><entry><id>http://example.com/item-7</id><title>item-7</title><link rel="alternate" href="http://example.com/items/7" /><published>1970-01-01T00:07:00Z</published><link rel="enclosure" href="http://example.com/media-7" type="audio/mp3" length="1048576" /></entry><entry><id>http://example.com/item-8</id><title>item-8</title><link rel="alternate" href="http://example.com/items/8" /><published>1970-01-01T00:08:00Z</published><link rel="enclosure" href="http://example.com/media-8" type="audio/mp3" length="1048576" /></entry><entry><id>http://example.com/item-9</id><title>item-9</title><link rel="alternate" href="http://example.com/items/9" /><published>1970-01-01T00:09:00Z</published><link rel="enclosure" href="http://example.com/media-9" type="audio/mp3" length="1048576" /></entry></feed>

View File

@ -0,0 +1,2 @@
<?xml version='1.0' encoding='UTF-8' ?><feed xmlns="http://www.w3.org/2005/Atom"><id>http://example.com/feed</id><title>title</title><link rel="alternate" href="http://example.com" /><subtitle>This is the description</subtitle><link rel="payment" href="http://example.com/payment" type="text/html" /><logo> https://example.com/image.png
</logo></feed>

View File

@ -0,0 +1,2 @@
<?xml version='1.0' encoding='UTF-8' ?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>title</title><description>This is the description</description><link>http://example.com</link><language>en</language><atom:link rel="payment" href="http://example.com/payment" type="text/html" /><image><url> https://example.com/image.png
</url></image></channel></rss>

View File

@ -0,0 +1 @@
<?xml version='1.0' encoding='UTF-8' ?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>title</title><description>This is the description</description><link>http://example.com</link><language>en</language><atom:link rel="payment" href="http://example.com/payment" type="text/html" /><item xmlns:media="http://search.yahoo.com/mrss/"><media:content url="https://www.example.com/file.mp4" medium="video" /></item></channel></rss>

View File

@ -0,0 +1 @@
<?xml version='1.0' encoding='UTF-8' ?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>title</title><description>This is the description</description><link>http://example.com</link><language>en</language><image><url>http://example.com/picture</url></image><atom:link rel="payment" href="http://example.com/payment" type="text/html" /><item><title>item-0</title><link>http://example.com/items/0</link><pubDate>01 Jan 70 01:00:00 +0100</pubDate><guid>http://example.com/item-0</guid><enclosure url="http://example.com/media-0" length="1048576" type="audio/mp3" /></item><item><title>item-1</title><link>http://example.com/items/1</link><pubDate>01 Jan 70 01:01:00 +0100</pubDate><guid>http://example.com/item-1</guid><enclosure url="http://example.com/media-1" length="1048576" type="audio/mp3" /></item><item><title>item-2</title><link>http://example.com/items/2</link><pubDate>01 Jan 70 01:02:00 +0100</pubDate><guid>http://example.com/item-2</guid><enclosure url="http://example.com/media-2" length="1048576" type="audio/mp3" /></item><item><title>item-3</title><link>http://example.com/items/3</link><pubDate>01 Jan 70 01:03:00 +0100</pubDate><guid>http://example.com/item-3</guid><enclosure url="http://example.com/media-3" length="1048576" type="audio/mp3" /></item><item><title>item-4</title><link>http://example.com/items/4</link><pubDate>01 Jan 70 01:04:00 +0100</pubDate><guid>http://example.com/item-4</guid><enclosure url="http://example.com/media-4" length="1048576" type="audio/mp3" /></item><item><title>item-5</title><link>http://example.com/items/5</link><pubDate>01 Jan 70 01:05:00 +0100</pubDate><guid>http://example.com/item-5</guid><enclosure url="http://example.com/media-5" length="1048576" type="audio/mp3" /></item><item><title>item-6</title><link>http://example.com/items/6</link><pubDate>01 Jan 70 01:06:00 +0100</pubDate><guid>http://example.com/item-6</guid><enclosure url="http://example.com/media-6" length="1048576" type="audio/mp3" /></item><item><title>item-7</title><link>http://example.com/items/7</link><pubDate>01 Jan 70 01:07:00 +0100</pubDate><guid>http://example.com/item-7</guid><enclosure url="http://example.com/media-7" length="1048576" type="audio/mp3" /></item><item><title>item-8</title><link>http://example.com/items/8</link><pubDate>01 Jan 70 01:08:00 +0100</pubDate><guid>http://example.com/item-8</guid><enclosure url="http://example.com/media-8" length="1048576" type="audio/mp3" /></item><item><title>item-9</title><link>http://example.com/items/9</link><pubDate>01 Jan 70 01:09:00 +0100</pubDate><guid>http://example.com/item-9</guid><enclosure url="http://example.com/media-9" length="1048576" type="audio/mp3" /></item></channel></rss>