Der Feed für die Gemeinde
Winnie | 13.07.2008
Das alte Studio steht nicht mehr, Kathrin Bauerfeind ist schon lange zur Old-Media-Konkurrenz gewechselt. Und mein alter Feed läuft nach dem Relaunch der Website auch nicht mehr – die Dateien gibt es jetzt nur noch gezippt.
Deswegen gibt es hier ein Update, das zumindest den Mac-Usern etwas weiterhilft. Zumindest unter Leopard. Alle anderen können das Skript mit mehr oder weniger Aufwand ans eigene System anpassen.
-
Lokalen Webserver mit PHP aktivieren
- Terminal öffnen
-
sudo pico /etc/apache2/httpd.conf
um die Config-Datei des lokalen Webservers zu bearbeiten. Dafür wird noch ein Admin-Passwort abgefragt.
- mit Ctrl + W nach ‘php’ suchen
- das Kommentarzeichen ’#’ am Anfang der Zeile entfernen
- mit Ctrl + X, und dann mit Y und dann Enter speichern
- in den Systemeinstellungen unter ‘Sharing’ den Punkt ‘Web-Sharing’ aktivieren
- die lokale Adresse (z.B. http://192.168.1.1/~username/) merken
- Das Podcastskript (feed.php herunterladen und in ~/Sites/podcastfeed/feed.php speichern. Der Ordner braucht Schreibrechte für den Webserver-User. In den ersten paar Zeilen müssen noch die richtigen Servernamen und so für deine Lieblings-Internet-Fernsehsendung eingetragen werden.
- Zusätzliche Klassen installieren
- SimplePie laden und unter ~/Sites/podcastfeed/class/simplepie.class.php speichern
- rss_writer.class.php laden und unter ~/Sites/podcastfeed/class/rss_writer.class.php speichern – die Klasse basiert auf der FeedCreator.class.php von Kai Blankenhorn
- In dem podcastfeed-Ordner müssen außerdem noch zwei Unterordner cache und files, jeweils mit vollen Schreib- und Leserechten angelegt werden.
- Podcast in iTunes abonnieren
- Unter ‘Erweitert | Podcast abonnieren’ die Feed-Adresse vom eigenen Rechner eintragen, z.B. http://192.168.1.1/~username/podcastfeed/feed.php
- iTunes wird jetzt beim ersten Aufruf noch keine Folgen finden, sie werden aber im Hintergrund heruntergeladen und auf dem eigenen Rechner ausgepackt.
- Beim nächsten Update von iTunes werden die ersten Folgen erscheinen, die schon heruntergeladen sind.
Das Skript behält immer die letzten 10 Folgen auf dem System.
Obacht: Das Aktivieren des lokalen Webservers ist evtl. nicht jedermanns Sache, andererseits – wer bis hierher durchgehalten hat, weiß hoffentlich, was er tut.
Wenns nicht läuft – Das Apache-Log könnt ihr mit der Konsole in /var/log/apache2/ einsehen.
Ich bin Winnie. Das war mein Podcastskript. Tschüß.
<? /* E X A M P L E ----------------------------------------------- $feed = new RSS(); $feed->title = "RSS Feed Title"; $feed->link = "http://website.com"; $feed->description = "Recent articles on your website."; $db->query($query); $result = $db->result; while($row = mysql_fetch_array($result, MYSQL_ASSOC)) { $item = new RSSItem(); $item->title = $title; $item->link = $link; $item->setPubDate($create_date); $item->description = "<![CDATA[ $html ]]>"; $feed->addItem($item); } echo $feed->serve(); ---------------------------------------------------------------- */ class RSS { var $title; var $link; var $description; var $language = "en-us"; var $pubDate; var $items; var $tags; var $encoding = "utf-8"; function RSS() { $this->items = array(); $this->tags = array(); } function addItem($item) { $this->items[] = $item; } function setPubDate($when) { if(strtotime($when) == false) $this->pubDate = date("D, d M Y H:i:s ", $when) . "GMT"; else $this->pubDate = date("D, d M Y H:i:s ", strtotime($when)) . "GMT"; } function getPubDate() { if(empty($this->pubDate)) return date("D, d M Y H:i:s ") . "GMT"; else return $this->pubDate; } function addTag($tag, $value) { $this->tags[$tag] = $value; } function out() { $out = $this->header(); $out .= "<channel>\n"; $out .= "<title>" . $this->title . "</title>\n"; $out .= "<link>" . $this->link . "</link>\n"; $out .= "<description>" . $this->description . "</description>\n"; $out .= "<language>" . $this->language . "</language>\n"; $out .= "<pubDate>" . $this->getPubDate() . "</pubDate>\n"; foreach($this->tags as $key => $val) $out .= "<$key>$val</$key>\n"; foreach($this->items as $item) $out .= $item->out(); $out .= "</channel>\n"; $out .= $this->footer(); $out = str_replace("&", "&", $out); return $out; } function serve($contentType = "application/xml") { $xml = $this->out(); header("Content-type: $contentType"); echo $xml; } function header() { $out = '<'.'?xml version="1.0" encoding="'.$this->encoding.'"?'.'>' . "\n"; $out .= '<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">' . "\n"; return $out; } function footer() { return '</rss>'; } } class RSSItem { var $title; var $link; var $description; var $pubDate; var $guid; var $tags; var $attachment; var $length; var $mimetype; function RSSItem() { $this->tags = array(); } function setPubDate($when) { if(strtotime($when) == false) $this->pubDate = date("D, d M Y H:i:s ", $when) . "GMT"; else $this->pubDate = date("D, d M Y H:i:s ", strtotime($when)) . "GMT"; } function getPubDate() { if(empty($this->pubDate)) return date("D, d M Y H:i:s ") . "GMT"; else return $this->pubDate; } function addTag($tag, $value) { $this->tags[$tag] = $value; } function out() { $out .= "<item>\n"; $out .= "<title>" . $this->title . "</title>\n"; $out .= "<link>" . $this->link . "</link>\n"; $out .= "<description>" . $this->description . "</description>\n"; $out .= "<pubDate>" . $this->getPubDate() . "</pubDate>\n"; if($this->attachment != "") $out .= "<enclosure url='{$this->attachment}' length='{$this->length}' type='{$this->mimetype}' />"; if(empty($this->guid)) $this->guid = $this->link; $out .= "<guid>" . $this->guid . "</guid>\n"; foreach($this->tags as $key => $val) $out .= "<$key>$val</$key\n>"; $out .= "</item>\n"; return $out; } function enclosure($url, $mimetype, $length) { $this->attachment = $url; $this->mimetype = $mimetype; $this->length = $length; } } ?>
<? require_once('class/simplepie.class.php'); require_once('class/rss_writer.class.php'); define("BLOG_RSS_URL", "http://www.PODCASTURL.de/rss.xml"); define("BLOG_VIDEO_URL", "http://PODCAST.SERVER-X.VIDEO.DOMAIN.de/"); define("BLOG_VIDEO_DOWNLOAD_EXTENSION", ".mov.zip"); define("BLOG_VIDEO_TYPE", "video/quicktime"); define("VIDEO_URL", "files/"); define("VIDEO_EXTENSION", ".mov"); define("ABSOLUTE_PATH", "/Users/username/Sites/podcastfeed/"); define("WEB_PATH", "http://192.168.1.1/~username/podcastfeed/"); // Parse it $feed = new SimplePie(BLOG_RSS_URL); // neue Dateien laden getFilesFromFeed($feed); // Feed erstellen showRssFromSystemFiles($feed, VIDEO_URL); // liefert den RSS-Feed mit Enclosures von den geladenen Dateien function showRssFromSystemFiles(&$uFeed, $uFolder) { $locFiles = getFileListFromSystem($uFolder); header('Content-type: text/xml'); $rss = new RSS(); $rss->encoding = ($uFeed->get_encoding()?$uFeed->get_encoding():'UTF-8'); $rss->title = $uFeed->get_title(); $rss->link = $uFeed->get_permalink(); $rss->description = $uFeed->get_description(); $rss->language = $uFeed->get_language(); if ($uFeed->data) { $items = $uFeed->get_items(); foreach($items as $thisItem) { $rssItem = new RSSItem(); $locEnclosureLink = getEnclosureLink($thisItem->get_categories()); // Datei aus Feed in System vorhanden, dann in Feed aufnehmen if (in_array($locEnclosureLink.VIDEO_EXTENSION, $locFiles)) { $rssItem->title = $thisItem->get_title(); $rssItem->link = $thisItem->get_link(); $rssItem->setPubDate($thisItem->get_date()); $rssItem->description = "<![CDATA[ ".$thisItem->get_description(true)." ]]>"; if (!is_null($locEnclosureLink)) { $rssItem->enclosure(WEB_PATH.$uFolder.$locEnclosureLink.VIDEO_EXTENSION, BLOG_VIDEO_TYPE, 12); } $rss->addItem($rssItem); } } } echo $rss->serve(); } // liefert den Original-RSS-Feed mit Enclosures function showRssFromOrginalFeed(&$uFeed) { header('Content-type: text/xml'); $rss = new RSS(); $rss->encoding = ($uFeed->get_encoding()?$uFeed->get_encoding():'UTF-8'); $rss->title = $uFeed->get_title(); $rss->link = $uFeed->get_permalink(); $rss->description = $uFeed->get_description(); $rss->language = $uFeed->get_language(); if ($uFeed->data) { $items = $uFeed->get_items(); foreach($items as $thisItem) { $rssItem = new RSSItem(); $rssItem->title = $thisItem->get_title(); $rssItem->link = $thisItem->get_link(); $rssItem->setPubDate($thisItem->get_date()); $rssItem->description = "<![CDATA[ ".$thisItem->get_description(true)." ]]>"; if (!is_null($locEnclosureLink = getEnclosureLink($thisItem->get_categories()))) { $rssItem->enclosure(BLOG_VIDEO_URL.$locEnclosureLink.BLOG_VIDEO_DOWNLOAD_EXTENSION, BLOG_VIDEO_TYPE, 12); } $rss->addItem($rssItem); } } echo $rss->serve(); } // liefert den Enclosure-Link zurück function getEnclosureLink(&$uEnclosure) { $locEnclosureLink = null; $locEnclosure = $uEnclosure; if (isset($locEnclosure[0])) { if (is_array($locEnclosure)) { for ($i=0; $i < count($locEnclosure); $i++) { //echo $i; $locItem = $locEnclosure[$i]; if (is_object($locItem)) { if (isset($locItem->term)) { if (strpos($locItem->term, date("Y")) !== false) { $locEnclosureLink = $locItem->term; } } } } } } return $locEnclosureLink; } // läd die Dateien aus dem Feed, die noch nicht im System liegen // bzw. wenn Datei nicht im Feed aber im System dann löschen function getFilesFromFeed(&$uFeed) { $locFilesInSystem = getFileListFromSystem(VIDEO_URL, true, VIDEO_EXTENSION); $locFilesInFeed = getFileListFromFeed($uFeed, BLOG_VIDEO_DOWNLOAD_EXTENSION, true); // welche Dateien sind im System aber nicht im Feed $locDiffSystemToFeed = array_diff($locFilesInSystem, $locFilesInFeed); // welche Dateien sind im Feed aber nicht im System $locDiffFeedToSystem = array_diff($locFilesInFeed, $locFilesInSystem); // Datei, die nicht im Feed sind vom System löschen foreach ($locDiffSystemToFeed as $item) { @unlink(VIDEO_URL.$item.VIDEO_EXTENSION); } $locExec = "#!/bin/bash\n"; // Datei, die nicht im System sind aus Feed holen foreach ($locDiffFeedToSystem as $item) { $submit_url = BLOG_VIDEO_URL.$item.BLOG_VIDEO_DOWNLOAD_EXTENSION; $save_path = VIDEO_URL.$item.BLOG_VIDEO_DOWNLOAD_EXTENSION; $locExec .= "/usr/bin/curl ".$submit_url." -o ".$save_path." -L\n"; // Datei laden $locExec .= "/usr/bin/unzip ".$save_path." *".VIDEO_EXTENSION." -d ".VIDEO_URL."\n"; // Datei entzippen $locExec .= "rm ".$save_path."\n\n"; // Zip löschen } // in eine Datei schreiben und Datei als Script ausführen if (count($locDiffFeedToSystem) > 0) { $handle = fopen (ABSOLUTE_PATH."loadFeedFiles.sh", "w"); fputs($handle, $locExec); fclose($handle); @chmod (ABSOLUTE_PATH."loadFeedFiles.sh", 0777); // Script ausführen exec("./loadFeedFiles.sh > /dev/null &"); } } // gibt alle Dateien aus dem Feed als Array zurück function getFileListFromFeed(&$uFeed, $uExtension="", $uBasename=false) { $files = array(); if ($uFeed->data) { $items = $uFeed->get_items(); foreach($items as $thisItem) { if (!is_null($locEnclosureLink = getEnclosureLink($thisItem->get_categories()))) { $files[] = $locEnclosureLink.(($uBasename)?"":$uExtension); } } } return $files; } // gibt alle Dateien aus dem Ordner als Array zurück function getFileListFromSystem($uFolder, $uBasename=false, $uExtension="") { $files = array(); if($dir = opendir($uFolder)) { while($file = readdir($dir)) { if (!is_dir($file) && $file != "." && $file != ".." && $file != ".DS_Store" & $file != "__MACOSX") { $files[] = (($uBasename)?basename($file, $uExtension):$file); } } closedir($dir); } return $files; } ?>
Kategorien: Blog | 4 Kommentare

03.12.2007 03:05
hi winnie,
supi! jetzt klappts! hab die parameter nur ein bisserl abgewandelt – weil ich mamp hab.
lg
gentschi
08.12.2007 12:21
Super dann kann ich ja mein eigenes Skript jetzt in den Urlaub schicken.
Leider sind aber in feed.php und der Anleitung noch einige Fehler drin:
• class-snoopy.php ist wohl FeedCreater.class.php
• Bei SimplePie sollte man dazu schreiben das simplepie.inc in simplepie.class.php umgenannt werden sollte.
• Bei den Rechten sollte man eher so vorgehen chmod o+w cache files ../podcastfeed (letzteres weil sonst das sh Skript nicht angelegt werden kann)
• die letzte Funktion (printR) ist wohl überflüßig, wenn man das Script per Copy and Paste oben kopiert gibt’s da leider nen Fehler wegen einem typografischen Anführgszeichen…
• in Zeile 117 prüft unlink nicht ob es die Datei wirklich gibt, hat hier zu Folge das ein Fehler biem Löschen von z.B. files/2007-12-06.mov.zip.mov auftritt. Die Quick’n'dirty Lösung unlink durch @unlink ersetzen.
So funktioniert das ganze dann auch bei mir.
09.12.2007 23:50
@Jens: Danke für die Hinweise – ich habe meinen Post dementsprechend angepaßt.
05.10.2009 20:31
hi winnie,
supi! jetzt klappts! hab die parameter nur ein bisserl abgewandelt – weil ich mamp hab.
lg
gentschi