Skip to content

Instantly share code, notes, and snippets.

@vsoch
Last active February 15, 2024 05:20
Show Gist options
  • Star 44 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save vsoch/4898025919365bf23b6f to your computer and use it in GitHub Desktop.
Save vsoch/4898025919365bf23b6f to your computer and use it in GitHub Desktop.
Generate RSS feed for files in a directory folder. Put this file in a folder with files, modify the $allowed_ext variable to customize your extensions, and $feedName, $feedDesc, $feedURL, and $feedBaseURL. Then navigate to the folder on the web to see the xml feed. Done!
<?php
header('Content-type: text/xml');
/*
Runs from a directory containing files to provide an
RSS 2.0 feed that contains the list and modification times for all the
files.
*/
$feedName = "My Audio Feed";
$feedDesc = "Feed for the my audio files in some server folder";
$feedURL = "http://www.mysite.com/audio";
$feedBaseURL = "http://www.mysite.com/audio/"; // must end in trailing forward slash (/).
$allowed_ext = ".mp4,.MP4,.mp3,.MP3";
?><<?= '?'; ?>xml version="1.0"<?= '?'; ?>>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title><?=$feedName?></title>
<link><?=$feedURL?></link>
<description><?=$feedDesc?></description>
<atom:link href="http://gogglesoptional.com/bloopers" rel="self" type="application/rss+xml" />
<?php
$files = array();
$dir=opendir("./");
while(($file = readdir($dir)) !== false)
{
$path_info = pathinfo($file);
$ext = strtoupper($path_info['extension']);
if($file !== '.' && $file !== '..' && !is_dir($file) && strpos($allowed_ext, $ext)>0)
{
$files[]['name'] = $file;
$files[]['timestamp'] = filectime($file);
}
}
closedir($dir);
// natcasesort($files); - we will use dates and times to sort the list.
for($i=0; $i<count($files); $i++) {
if($files[$i] != "index.php") {
if (!empty($files[$i]['name'])) {
echo " <item>\n";
echo " <title>". $files[$i]['name'] ."</title>\n";
echo " <link>". $feedBaseURL . $files[$i]['name'] . "</link>\n";
echo " <guid>". $feedBaseURL . $files[$i]['name'] . "</guid>\n";
echo " <pubDate>". date(DATE_RSS, $files[$i]['timestamp']) ."</pubDate>\n";
// echo " <pubDate>". date("D M j G:i:s T Y", $files[$i]['timestamp']) ."</pubDate>\n";
// echo " <pubDate>" . $files[$i]['timestamp'] ."</pubDate>\n";
echo " </item>\n";
}
}
}
?>
</channel>
</rss>
@xeruf
Copy link

xeruf commented Jul 29, 2019

What is this atom:link in the head? Is it supposed to statically link to http://gogglesoptional.com/bloopers?

@vsoch
Copy link
Author

vsoch commented Jul 29, 2019

hey everyone sorry for the lack of response on my part, for some reason I only got notified for this after @Xerus2000 post. The feed was for podcast episodes from the bloppers folder for a podcast, and it looks like it's valid https://validator.w3.org/feed/check.cgi?url=http%3A%2F%2Fgogglesoptional.com%2Fbloopers%2F with a warning that it might not be perfect in all places. I can definitely imagine that, depending on your platform, you might have issues escaping characters.

@Xerus2000 the atom link is like a self link, I must have copied it from whatever template I was looking at the time. Here's the feed http://gogglesoptional.com/bloopers/

@Dleewee
Copy link

Dleewee commented Jan 6, 2020

I had to make two changes to the code to get it running. Line #1 and Line #23. Changed both FROM <? TO <?php

@vsoch
Copy link
Author

vsoch commented Jan 6, 2020

I just fixed these two lines - could you take a look @Dleewee?

@xeruf
Copy link

xeruf commented Jan 7, 2020

shouldn't the
<atom:link href=...
then contain the $feedURL as well?

@Dleewee
Copy link

Dleewee commented Jan 17, 2020

Yes the lines I mentioned look good. I noticed some other comments about it just printing a couple of lines of code on the screen and those changes should fix it for people with that issue.

I did also borrow some of the changes from davet2001 as I was having issues getting the pubdates to work correctly (kept showing up as Jan 01 1970) and using davet's changes did fix that.

One other change I am using is switching from DATE_RFC822 over to using DATE_RSS which I saw as a recomendation on Stackoverflow. So my date line reads:
echo " <pubDate>". date(DATE_RSS, $item['timestamp']) ."</pubDate>\n";

BTW, big thanks to vsoch for writing this in the first place!! It was exactly what I was looking for and replaces some really janky workarounds I was using before :)

@vsoch
Copy link
Author

vsoch commented Jan 17, 2020

okay let's fix up that line too then - take a look and let me know if it's okay?

For those interested, I've stopped using this method for podcast feeds because static jekyll sites on GitHub pages are much easier, and for that you can just do something like this: https://github.com/USRSE/rse-stories/blob/master/pages/episodes.rss

@life-on-mars
Copy link

For me, extensions only work when added as uppercase characters and the first character and dots are always ignored. E.g.: "XMP3" finds both .mp3 and .MP3 extensions and "mp3" (because it's lowercase) or "MP3" (because the first letter is ignored) finds nothing.

@PeraDev7
Copy link

any news? I get a 500 ERROR

@Dleewee
Copy link

Dleewee commented Oct 19, 2020

It's been working great for me for about 10 months. I record a daily audio broadcast and then share it as an RSS feed picked up by a podcast app on my phone.

As error 500 is generic I would first build a php test file and make sure that works. Add this line into a file named test.php:

<?php phpinfo(); ?>

If that works, you should be able to get the RSS feed going. If not, it points to an issue with your web server, PHP, file permissions, etc, that needs to be resolved first.

@Dleewee
Copy link

Dleewee commented Oct 19, 2020

Here is the code I've been using for several months. Just update the lines starting with $feedName, $feedDesc, $feedURL, $feedBaseUR.

<?php
header('Content-type: text/xml');
/*
	Runs from a directory containing files to provide an
	RSS 2.0 feed that contains the list and modification times for all the
	files. Thanks to vsoch on GitHub!

*/
$feedName = "Feed name";
$feedDesc = "Feed description";
$feedURL = "https://url.com";
$feedBaseURL = "https://url.com/"; // must end in trailing forward slash (/).

$allowed_ext = ".mp4,.MP4,.mp3,.MP3";

?><<?= '?'; ?>xml version="1.0"<?= '?'; ?>>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><?=$feedName?></title>
		<link><?=$feedURL?></link>
		<description><?=$feedDesc?></description>
<?php
$items = array();
$sub = "";
$dir=opendir("./");

while(($file = readdir($dir)) !== false)
{

	$ext = strtoupper(pathinfo($sub.$file, PATHINFO_EXTENSION));
	if($file !== '.' && $file !== '..' && !is_dir($file) && strpos($allowed_ext, $ext)>0)  
	{
		$item['name'] = $sub.$file;
		$item['timestamp'] = filectime($sub.$file);
		$item['size'] = filesize($sub.$file);
		$items[] = $item;

	}
}
closedir($dir);
// natcasesort($files); - we will use dates and times to sort the list.

foreach($items as $item) {
	if($item['name'] != "index.php") {
          if (!empty($item['name'])) {
		echo "	<item>\n";
		echo "		<title>". $item['name'] ."</title>\n";
		echo "		<link>". $feedBaseURL . $item['name'] . "</link>\n";
		echo "		<guid>". $feedBaseURL . $item['name'] . "</guid>\n";
		echo "		<pubDate>". date(DATE_RSS, $item['timestamp']) ."</pubDate>\n";

		echo "    </item>\n";
	  }
	}
}
?>
	</channel>
</rss>

@KimberH
Copy link

KimberH commented Nov 30, 2020

Hi, does anyone know where I can find codes like these but for HTML files? Thank you

@vsoch
Copy link
Author

vsoch commented Nov 30, 2020

If you generally want to interact with a database (and without php) then your options are server side frameworks that could do the same. What quickly comes to mind are nodejs, Python frameworks like Django or Flask, Ruby on Rails, and maybe R shiny if you are doing data science. Go and Rust also have their own server -> frontend frameworks, but are a slightly steeper learning curve (at least compared to something like Python). You can also just use standard javascript with Ajax (or other derivatives that make this easy, React, etc.) that communicates with some external API.

@dewijones92
Copy link

@strukturart
Copy link

thank you for the snippet!

this is my version sorted by filename, i use it on my kaios phone + rss reader to listen to audiobooks

https://gist.github.com/strukturart/9a42a18c78fa44c6929bfdd3d46be0f4

@xenotropic
Copy link

Thank you. Would be helpful to either remove $ext = strtoupper($path_info['extension']); or add a comment by $allowed_ext that it should be uppercased (since it looks like it matters, because the defaults are both upper and lower). Took me a while to figure out why some files were not showing up, and was because I'd put the extension in $allowed_ext in lowercase.

@xenotropic
Copy link

Also if anybody wants to get this to work with AntennaPod (or probably other players) you'll need to add an enclosure tag, see spec here https://help.apple.com/itc/podcasts_connect/#/itcb54353390

@olentulen
Copy link

olentulen commented Mar 2, 2022

Wow, it actually worked. Thank you very much!

I couldn't get the script to work but adding enclosure line fixed everything. Thanks to @davet2001 !

echo " <enclosure url='". $feedBaseURL . $item['name']. "' length='" . $item['size'] . "' type='video/mp4' />\n";

Do anybody know how can I add an artwork to my feed?

@strukturart
Copy link

I think you could use the tag for that
http://web.ard.de/radiotatort/rss/podcast.xml

@olentulen
Copy link

Thank you for pointing me in right direction, @strukturart :)

I've found simplest solution here:
https://www.w3schools.com/xml/rss_tag_image.asp

@strukturart
Copy link

not tested but this might work if the cover image is always called cover.jpg: https://gist.github.com/strukturart/9a42a18c78fa44c6929bfdd3d46be0f4#file-rss-php-L23

@kzar
Copy link

kzar commented Aug 16, 2022

Sharing this here in case anyone's interested, I took some time recently to write a more comprehensive RSS feed script for audiobooks. It takes care to read the title, author, cover image and other metadata from the MP3/M4B files. I've written a blog post about it and how to get it running on a Synology NAS, and the script's at the bottom of the post. Hope that helps, and shout if you have any problems getting it running.

@mailinglists35
Copy link

mailinglists35 commented Aug 31, 2022

@kzar thanks!

I added this for my private feed hosted on traffic limited server, to not get listed by public podcast indexes:

after <channel>

  echo '  <itunes:block>yes</itunes:block>' . "\n";

if you also add this, it will be refused to be added in mobile podcast apps (ios podcasts, android google podcasts), and it will only work in third party apps:

echo '  <googleplay:block>yes</googleplay:block>' . "\n";

sources: http://support.megaphone.fm/en/articles/2700280-itunes-and-google-block-tags https://support.google.com/podcast-publishers/answer/9889544?hl=en https://discussions.apple.com/thread/4871937

@kzar
Copy link

kzar commented Sep 4, 2022

Oh great, glad you found it useful. Thanks for the hint about blocking the indexes, I just have my feed hosted in my local network so I haven't run into that problem! I've made a couple more improvements to the script now, so it handles M4B files as well and I have corrected a bug with the cover image logic.

@Tab-Top
Copy link

Tab-Top commented Oct 4, 2022

How can Limit number of items?
Example: Show last 10Feed (datatime)

@kzar
Copy link

kzar commented Oct 4, 2022

How can Limit number of items?
Example: Show last 10Feed (datatime)

Well, if you're using my script there's an array $book_details that contains all the book details, that's then passed to the outputRSS function (see the outputRSS($book_details); line). You could just use array_slice (or similar) to shorten that array before passing it through to outputRSS.

@strukturart
Copy link

does anyone know of an ompl editor written in php?

@hvdkooij
Copy link

I tried the script but I have some very odd thing.
The key thing is that the timestamp is always now() instead of the file timestamp.

And I don't seem to understand how the array is working. Adding something like $files[]['comment'] always returns an empty value.

Not much PHP work done the last few years so I need a reminder of somethings that might seem too silly to mention.

@dewijones92
Copy link

@olentulen
Copy link

Hello! After switching from Apache to Caddy web server, I can't get rss to work. Podcast app sees files, but it always gives an error when i try to downloader the file. Is it possible that I am missing some specific part of php engine?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment