Finish torrentlinkHandler
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
.idea/
|
||||
__pycache__
|
||||
*~
|
||||
testenv/tests/webpage/cgitestrun/cgi-bin
|
||||
testenv/tests/webpage/cgitestrun/testfeeds
|
||||
@@ -1,10 +1,11 @@
|
||||
__author__ = 'dev'
|
||||
|
||||
Config = {
|
||||
"FeedLinkTypes" : {"audio/mpeg","application/x-bittorrent"},
|
||||
"FeedLinkTypes" : {"audio/mpeg","application/x-bittorrent", "audio/opus"},
|
||||
"FeedTypes" : {"podcast","rss"},
|
||||
"FeedStorageFolder" : "testfeeds",
|
||||
"FeedStoragePrefix" : { "0" : "FeedType", "1" : "FeedName"},
|
||||
"ConfigFileSuffix" : "-config",
|
||||
"ConfigFileExtension" : ".json"
|
||||
"ConfigFileExtension" : ".json",
|
||||
"TorrentStorageFolder": "testtorrents",
|
||||
}
|
||||
28
src/feed/entry_handler.py
Normal file
28
src/feed/entry_handler.py
Normal file
@@ -0,0 +1,28 @@
|
||||
__author__ = 'dev'
|
||||
|
||||
from feed.feed import Feed
|
||||
import utilities.file_methods as fm
|
||||
from feed.feed_entry_enums import FeedEntryEnums
|
||||
|
||||
|
||||
class EntryHandler():
|
||||
|
||||
def __init__(self, feed):
|
||||
assert isinstance(feed, Feed)
|
||||
self._feed = feed
|
||||
|
||||
def handle_entries(self):
|
||||
for entry in self.detect_new_entries():
|
||||
self.handle_entry(entry)
|
||||
|
||||
def detect_new_entries(self):
|
||||
new_links = []
|
||||
for entry in fm.read_json_file(self._feed.feed_file_path)[FeedEntryEnums.KeyName.EntryKey]:
|
||||
status = entry.get(FeedEntryEnums.KeyName.EntryStatusKey)
|
||||
if status is None or status == FeedEntryEnums.Status.New:
|
||||
new_links.append(entry)
|
||||
|
||||
return new_links
|
||||
|
||||
def handle_entry(self, link):
|
||||
pass
|
||||
@@ -2,8 +2,10 @@ __author__ = 'dev'
|
||||
|
||||
from config.config import Config
|
||||
from utilities.podcastserializer import PodcastSerializer
|
||||
from utilities.serializer import Serializer
|
||||
import feedparser
|
||||
import os
|
||||
import glob
|
||||
import utilities.file_methods as fm
|
||||
|
||||
|
||||
@@ -22,6 +24,8 @@ class Feed:
|
||||
self.feed_file_path = None
|
||||
self.serializer = None
|
||||
self.feed_folder = None
|
||||
self.name = feed_name
|
||||
self.type = feed_type
|
||||
self.setup_feed(feed_name, feed_type, link_type, feed_url)
|
||||
|
||||
def load_feed(self):
|
||||
@@ -62,8 +66,9 @@ class Feed:
|
||||
:return: Serializer - the serializer of the feed
|
||||
"""
|
||||
return {
|
||||
"podcast": PodcastSerializer(self.feed_config["LinkType"])
|
||||
}.get(self.feed_config["FeedType"], PodcastSerializer(self.feed_config["LinkType"]))
|
||||
"podcast": PodcastSerializer(self.feed_config["LinkType"]),
|
||||
"rss": Serializer()
|
||||
}.get(self.feed_config["FeedType"], Serializer())
|
||||
|
||||
def setup_feed(self, feed_name, feed_type, link_type, feed_url):
|
||||
"""
|
||||
@@ -110,7 +115,7 @@ class Feed:
|
||||
|
||||
self.feed_folder_path = self.feed_folder
|
||||
if not os.path.exists(self.feed_folder_path):
|
||||
os.mkdir(self.feed_folder)
|
||||
os.mkdir(self.feed_folder_path)
|
||||
|
||||
return self.feed_folder_path
|
||||
|
||||
@@ -131,6 +136,9 @@ class Feed:
|
||||
assert (self.feed_config is not None)
|
||||
fm.write_json_file(self.create_feed_config_path(), self.feed_config)
|
||||
|
||||
def get_feed_items(self):
|
||||
return fm.read_json_file(self.feed_file_path)
|
||||
|
||||
@staticmethod
|
||||
def create_feed_config_file(feed_name, feed_type, link_type, feed_url):
|
||||
"""
|
||||
@@ -153,4 +161,51 @@ class Feed:
|
||||
"FeedUrl": feed_url,
|
||||
"LinkType": link_type
|
||||
}
|
||||
return feed_config
|
||||
return feed_config
|
||||
|
||||
@staticmethod
|
||||
def create_feed_from_feed_config(feed_config):
|
||||
assert feed_config is not None
|
||||
feed_name = feed_config["FeedName"]
|
||||
feed_type = feed_config["FeedType"]
|
||||
feed_url = feed_config["FeedUrl"]
|
||||
link_type = feed_config["LinkType"]
|
||||
return Feed(feed_name, feed_type, link_type, feed_url)
|
||||
|
||||
@staticmethod
|
||||
def create_feed_from_feed_config_path(feed_config_path):
|
||||
assert os.path.isfile(feed_config_path)
|
||||
feed_config = fm.read_json_file(feed_config_path)
|
||||
return Feed.create_feed_from_feed_config(feed_config)
|
||||
|
||||
@staticmethod
|
||||
def create_feed_from_feed_folder_path(feed_folder_path):
|
||||
assert os.path.isdir(feed_folder_path)
|
||||
feed_config_path = glob.glob(feed_folder_path + "/*" + Config["ConfigFileSuffix"] + Config["ConfigFileExtension"])[0]
|
||||
return Feed.create_feed_from_feed_config_path(feed_config_path)
|
||||
|
||||
@staticmethod
|
||||
def create_feeds_from_storage_folder():
|
||||
feed_list_items = []
|
||||
for file_path in glob.glob(Config["FeedStorageFolder"] + "/*" * (len(Config["FeedStoragePrefix"]) + 1) + Config["ConfigFileSuffix"] + Config["ConfigFileExtension"], recursive=True):
|
||||
try:
|
||||
feed = Feed.create_feed_from_feed_config_path(file_path)
|
||||
feed_list_items.append(feed)
|
||||
except:
|
||||
pass
|
||||
return feed_list_items
|
||||
|
||||
@staticmethod
|
||||
def FindItem(feed_items, item_key, search_pattern):
|
||||
assert feed_items is not None
|
||||
assert item_key is not None
|
||||
assert search_pattern is not None
|
||||
result = None
|
||||
for feed_item in feed_items:
|
||||
if item_key not in feed_item:
|
||||
continue
|
||||
if feed_item[item_key] == search_pattern:
|
||||
result = feed_item
|
||||
break
|
||||
|
||||
return result
|
||||
12
src/feed/feed_entry_enums.py
Normal file
12
src/feed/feed_entry_enums.py
Normal file
@@ -0,0 +1,12 @@
|
||||
__author__ = 'dev'
|
||||
|
||||
|
||||
class FeedEntryEnums:
|
||||
class Status:
|
||||
New = "New"
|
||||
Loading = "Loading"
|
||||
Loaded = "Loaded"
|
||||
|
||||
class KeyName:
|
||||
EntryKey = "entries"
|
||||
EntryStatusKey = "EntryStatus"
|
||||
110
src/feed/torrent_cli_entry_handler.py
Normal file
110
src/feed/torrent_cli_entry_handler.py
Normal file
@@ -0,0 +1,110 @@
|
||||
__author__ = 'dev'
|
||||
|
||||
from feed.entry_handler import EntryHandler
|
||||
import urllib
|
||||
import os
|
||||
import shutil
|
||||
from config.config import Config
|
||||
import utilities.file_methods as fm
|
||||
import subprocess
|
||||
|
||||
|
||||
class TorrentCliEntryHandler(EntryHandler):
|
||||
|
||||
Transmission_Settings = {
|
||||
"alt-speed-down": 50,
|
||||
"alt-speed-enabled": False,
|
||||
"alt-speed-time-begin": 540,
|
||||
"alt-speed-time-day": 127,
|
||||
"alt-speed-time-enabled": False,
|
||||
"alt-speed-time-end": 1020,
|
||||
"alt-speed-up": 50,
|
||||
"bind-address-ipv4": "0.0.0.0",
|
||||
"bind-address-ipv6": "::",
|
||||
"blocklist-enabled": False,
|
||||
"blocklist-url": "http://www.example.com/blocklist",
|
||||
"cache-size-mb": 4,
|
||||
"dht-enabled": True,
|
||||
"download-dir": "tmp",
|
||||
"download-queue-enabled": True,
|
||||
"download-queue-size": 5,
|
||||
"encryption": 2,
|
||||
"idle-seeding-limit": 30,
|
||||
"idle-seeding-limit-enabled": False,
|
||||
"incomplete-dir": "/home/dev/Downloads",
|
||||
"incomplete-dir-enabled": False,
|
||||
"lpd-enabled": False,
|
||||
"message-level": 2,
|
||||
"peer-congestion-algorithm": "",
|
||||
"peer-id-ttl-hours": 6,
|
||||
"peer-limit-global": 200,
|
||||
"peer-limit-per-torrent": 50,
|
||||
"peer-port": 51413,
|
||||
"peer-port-random-high": 65535,
|
||||
"peer-port-random-low": 49152,
|
||||
"peer-port-random-on-start": False,
|
||||
"peer-socket-tos": "default",
|
||||
"pex-enabled": True,
|
||||
"port-forwarding-enabled": True,
|
||||
"preallocation": 1,
|
||||
"prefetch-enabled": 1,
|
||||
"queue-stalled-enabled": True,
|
||||
"queue-stalled-minutes": 30,
|
||||
"ratio-limit": 2,
|
||||
"ratio-limit-enabled": False,
|
||||
"rename-partial-files": True,
|
||||
"rpc-authentication-required": False,
|
||||
"rpc-bind-address": "0.0.0.0",
|
||||
"rpc-enabled": False,
|
||||
"rpc-password": "{7788eba16f883ebbda75ba83697c6db606a86ad1aMLMCwny",
|
||||
"rpc-port": 9091,
|
||||
"rpc-url": "/transmission/",
|
||||
"rpc-username": "",
|
||||
"rpc-whitelist": "127.0.0.1",
|
||||
"rpc-whitelist-enabled": True,
|
||||
"scrape-paused-torrents-enabled": True,
|
||||
"script-torrent-done-enabled": True,
|
||||
"script-torrent-done-filename": "",
|
||||
"seed-queue-enabled": False,
|
||||
"seed-queue-size": 10,
|
||||
"speed-limit-down": 100,
|
||||
"speed-limit-down-enabled": False,
|
||||
"speed-limit-up": 100,
|
||||
"speed-limit-up-enabled": False,
|
||||
"start-added-torrents": True,
|
||||
"trash-original-torrent-files": True,
|
||||
"umask": 18,
|
||||
"upload-slots-per-torrent": 14,
|
||||
"utp-enabled": True
|
||||
}
|
||||
SettingFile = Config["TorrentStorageFolder"] + "/settings.json"
|
||||
|
||||
@staticmethod
|
||||
def download_torrent(torrent_url):
|
||||
torrent_folder = Config["TorrentStorageFolder"]
|
||||
if not os.path.exists(torrent_folder):
|
||||
TorrentCliEntryHandler.init_torrent_folder(torrent_folder)
|
||||
file_name = torrent_folder + "/" + os.path.basename(torrent_url)
|
||||
|
||||
if os.path.exists(torrent_url):
|
||||
shutil.copy2(torrent_url, file_name)
|
||||
|
||||
else:
|
||||
with urllib.request.urlopen(torrent_url) as response, open(file_name, 'wb') as out_file:
|
||||
data = response.read()
|
||||
out_file.write(data)
|
||||
|
||||
@staticmethod
|
||||
def init_torrent_folder(torrent_folder):
|
||||
if os.path.exists(torrent_folder):
|
||||
return
|
||||
os.mkdir(torrent_folder)
|
||||
TorrentCliEntryHandler.Transmission_Settings["incomplete-dir"] = torrent_folder + "/Downloads"
|
||||
TorrentCliEntryHandler.Transmission_Settings["download-dir"] = torrent_folder + "/tmp"
|
||||
fm.write_json_file(TorrentCliEntryHandler.SettingFile, TorrentCliEntryHandler.Transmission_Settings)
|
||||
|
||||
@staticmethod
|
||||
def start_torrent(torrent_url, torrent_folder, download_folder):
|
||||
#pass
|
||||
tc = subprocess.Popen("transmission-cli -er -g" + torrent_folder + " -w " + download_folder + " " + torrent_url, shell=True)
|
||||
return tc
|
||||
38
src/feed/torrent_daemon_entry_handler.py
Normal file
38
src/feed/torrent_daemon_entry_handler.py
Normal file
@@ -0,0 +1,38 @@
|
||||
__author__ = 'dev'
|
||||
|
||||
from feed.entry_handler import EntryHandler
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
class TorrentDaemonEntryHandler(EntryHandler):
|
||||
|
||||
@staticmethod
|
||||
def start_daemon():
|
||||
if not TorrentDaemonEntryHandler.is_running_daemon():
|
||||
tc = subprocess.call("transmission-daemon", shell=True)
|
||||
time.sleep(1)
|
||||
return tc
|
||||
else:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def stop_daemon():
|
||||
tc = subprocess.call("killall transmission-daemon", shell=True)
|
||||
time.sleep(1)
|
||||
return tc
|
||||
|
||||
@staticmethod
|
||||
def is_running_daemon():
|
||||
tc = subprocess.Popen("pgrep transmission-da", shell=True, stdout=subprocess.PIPE)
|
||||
tc.wait()
|
||||
t = tc.stdout.readline()
|
||||
|
||||
if t is b'':
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def add_torrent_to_daemon(url):
|
||||
tc = subprocess.call("transmission-remote --add " + url, shell=True)
|
||||
return tc
|
||||
0
src/ui/__init__.py
Normal file
0
src/ui/__init__.py
Normal file
0
src/ui/web/__init__.py
Normal file
0
src/ui/web/__init__.py
Normal file
0
src/ui/web/cgi/__init__.py
Normal file
0
src/ui/web/cgi/__init__.py
Normal file
21
src/ui/web/cgi/cgi_server.py
Normal file
21
src/ui/web/cgi/cgi_server.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import glob
|
||||
import stat
|
||||
from http.server import HTTPServer, CGIHTTPRequestHandler
|
||||
import ui.web.cgi.pages
|
||||
|
||||
def runServer(workingDir, serverAddress=('',8080)):
|
||||
|
||||
page_folder = os.path.join(workingDir, "cgi-bin/")
|
||||
if(not os.path.exists(page_folder)):
|
||||
srcpagefolder = str(sys.modules['ui.web.cgi.pages']).replace("<module 'ui.web.cgi.pages' from '", "").replace("/__init__.py'>","")
|
||||
shutil.copytree(srcpagefolder, page_folder)
|
||||
os.chdir(page_folder)
|
||||
for file in glob.glob('*.py'):
|
||||
os.chmod(file, stat.S_IXUSR | stat.S_IWUSR | stat.S_IRUSR)
|
||||
|
||||
os.chdir('..')
|
||||
server = HTTPServer(serverAddress, CGIHTTPRequestHandler)
|
||||
server.serve_forever()
|
||||
44
src/ui/web/cgi/pages/FeedOverview.py
Normal file
44
src/ui/web/cgi/pages/FeedOverview.py
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
# enable debugging
|
||||
import cgi
|
||||
import urllib
|
||||
from feed.feed import Feed
|
||||
|
||||
|
||||
def create_episode_list(episodes, feedFolder):
|
||||
result = []
|
||||
for episode in episodes:
|
||||
result.append('''<li><a href="FileLoader.py?{EpisodeUrl}" target="_blank">{EpisodeTitle}</a> <i>{EpisodeDate}</i>
|
||||
<p>{EpisodeSubTitle}</p></li>'''.format(EpisodeTitle=episode["title"], EpisodeSubTitle=episode["subtitle"], EpisodeDate=episode["pubdate"], EpisodeUrl=urllib.parse.urlencode({'EpisodeTitle': episode["title"], 'FeedFolder': feedFolder})))
|
||||
|
||||
return "\n".join(result)
|
||||
|
||||
arguments = cgi.FieldStorage()
|
||||
feedFolder =arguments["FeedFolder"].value
|
||||
feed = Feed.create_feed_from_feed_folder_path(feedFolder)
|
||||
feedObj = feed.get_feed_items()
|
||||
|
||||
page = '''Content-Type: text/html
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Feed: {FeedName} - {FeedTitle}</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Feed: {FeedName} - {FeedTitle}</h1>
|
||||
<h2>{FeedSubTitle}</h2>
|
||||
<p>{FeedSummary}</p>
|
||||
|
||||
<ul>
|
||||
{EpisodeList}
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>'''.format(FeedName=feed.name, FeedTitle=feedObj["title"], FeedSubTitle=feedObj["subtitle"], FeedSummary=feedObj["summary"], EpisodeList=create_episode_list(feedObj["episodes"], feed.feed_folder_path))
|
||||
|
||||
print(page)
|
||||
48
src/ui/web/cgi/pages/FileLoader.py
Normal file
48
src/ui/web/cgi/pages/FileLoader.py
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
# enable debugging
|
||||
import cgi
|
||||
import os
|
||||
import subprocess
|
||||
from feed.feed import Feed
|
||||
|
||||
arguments = cgi.FieldStorage()
|
||||
feedFolder = arguments["FeedFolder"].value
|
||||
feed = Feed.create_feed_from_feed_folder_path(feedFolder)
|
||||
feedObj = feed.get_feed_items()
|
||||
|
||||
feedName = feed.name
|
||||
episodeTitle = arguments["EpisodeTitle"].value
|
||||
episode = Feed.FindItem(feedObj["episodes"], "title", episodeTitle)
|
||||
originLink = episode["file_link"]
|
||||
filename, file_extension = os.path.splitext(originLink)
|
||||
mylinkPrefix = os.path.join(feedFolder, episodeTitle.replace(" ", "_"))
|
||||
mylink = mylinkPrefix + file_extension
|
||||
if not os.path.exists(mylink):
|
||||
subprocess.call(['curl -Lo "{Mylink}" "{OriginLink}" &'.format(Mylink=mylink, OriginLink=originLink)],
|
||||
shell=True
|
||||
)
|
||||
|
||||
|
||||
page = '''Content-Type: text/html
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>FileLoad</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>FileLoad</h1>
|
||||
|
||||
<h2>{FeedName}: {EpisodeTitle}</h2>
|
||||
|
||||
<ul>
|
||||
<li><audio src="../{MyLinkUrl}" controls preload="auto"></audio></li>
|
||||
<li>MyLink: <a href="../{MyLinkUrl}" target="_blank">{MyLinkUrl}</a></li>
|
||||
<li>OriginLink: <a href="{OriginEpisodeUrl}" target="_blank">{OriginEpisodeUrl}</a></li>
|
||||
</body>
|
||||
</html>'''.format(FeedName=feedName, EpisodeTitle=episodeTitle, OriginEpisodeUrl=originLink, MyLinkUrl=mylink)
|
||||
|
||||
print(page)
|
||||
0
src/ui/web/cgi/pages/__init__.py
Normal file
0
src/ui/web/cgi/pages/__init__.py
Normal file
70
src/ui/web/cgi/pages/index.py
Normal file
70
src/ui/web/cgi/pages/index.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
# enable debugging
|
||||
import urllib
|
||||
import os
|
||||
from datetime import datetime
|
||||
from feed.feed import Feed
|
||||
|
||||
def create_feed_list(feeds):
|
||||
result = []
|
||||
for feed in feeds:
|
||||
result.append('''<li><a href="FeedOverview.py?{FeedFolder}">{FeedType}:{FeedName}</a></li>
|
||||
'''.format(FeedName=feed.name, FeedType=feed.type, FeedFolder=urllib.parse.urlencode({'FeedFolder': feed.feed_folder_path})))
|
||||
|
||||
return "\n".join(result)
|
||||
|
||||
def create_episode_list(feeds):
|
||||
|
||||
result = []
|
||||
episodes = []
|
||||
for feed in feeds:
|
||||
feedObj = feed.get_feed_items()
|
||||
if not "episodes" in feedObj:
|
||||
continue
|
||||
feedEpisodes = feedObj["episodes"]
|
||||
for feedEpisode in feedEpisodes:
|
||||
feedEpisode["FeedFolder"] = feed.feed_folder_path
|
||||
feedEpisode["FeedName"] = feed.name
|
||||
episodes.extend(feedEpisodes)
|
||||
|
||||
for episode in sorted(episodes, key= lambda x: datetime.strptime(x["pubdate"], "%a, %d %b %Y %X %z"), reverse=True)[0:50]:
|
||||
result.append('''<li><a href="FeedOverview.py?{FeedFolder}"">{FeedName}:</a> <a href="FileLoader.py?{EpisodeUrl}" target="_blank">{EpisodeTitle}</a></li>
|
||||
'''.format(EpisodeTitle=episode["title"], EpisodeUrl=urllib.parse.urlencode({'EpisodeTitle': episode["title"], 'FeedFolder': episode["FeedFolder"]}), FeedName=episode["FeedName"], FeedFolder=urllib.parse.urlencode({'FeedFolder': episode["FeedFolder"]})))
|
||||
|
||||
return "\n".join(result)
|
||||
|
||||
feed_list_items = Feed.create_feeds_from_storage_folder()
|
||||
for feed in feed_list_items:
|
||||
if not os.path.exists(feed.feed_file_path):
|
||||
feed.load_new_feed()
|
||||
|
||||
page = '''Content-Type: text/html
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>FeedIndexSeite</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>FeedIndexSeite</h1>
|
||||
|
||||
<h2>FeedListe</h2>
|
||||
|
||||
<ul>
|
||||
{FeedListItems}
|
||||
</ul>
|
||||
|
||||
<h2>EpisodeListe (neuste 50)</h2>
|
||||
|
||||
<ul>
|
||||
{EpisodeListItems}
|
||||
</ul>
|
||||
|
||||
|
||||
</body>
|
||||
</html>'''.format(FeedListItems=create_feed_list(feed_list_items), EpisodeListItems= create_episode_list(feed_list_items))
|
||||
|
||||
print(page)
|
||||
5
src/utilities/podcast_keys.py
Normal file
5
src/utilities/podcast_keys.py
Normal file
@@ -0,0 +1,5 @@
|
||||
__author__ = 'dev'
|
||||
|
||||
class PodcastKeys:
|
||||
FileLink = "file_link"
|
||||
FileLength = "length"
|
||||
@@ -6,6 +6,7 @@ from config.config import Config
|
||||
RSS_Prefix = "<?xml version=\"1.0\"?><rss version=\"2.0\"><channel>"
|
||||
RSS_Suffix = "</channel></rss>"
|
||||
|
||||
|
||||
class PodcastSerializer(Serializer):
|
||||
|
||||
def __init__(self, episode_file_type):
|
||||
@@ -20,35 +21,35 @@ class PodcastSerializer(Serializer):
|
||||
"""
|
||||
assert isinstance(dict_object, dict)
|
||||
|
||||
episodeList = []
|
||||
episode_list = []
|
||||
|
||||
for episode in dict_object["entries"]:
|
||||
filelink = ""
|
||||
file_link = ""
|
||||
file_length = ""
|
||||
for links in episode["links"]:
|
||||
if links["type"] == self.episode_file_type and links["rel"] == "enclosure":
|
||||
filelink = links["href"]
|
||||
file_link = links["href"]
|
||||
file_length = links["length"]
|
||||
|
||||
if filelink == "":
|
||||
if file_link == "":
|
||||
continue
|
||||
|
||||
tempepisode = {
|
||||
temp_episode = {
|
||||
"title": episode["title"],
|
||||
"subtitle": episode["subtitle"],
|
||||
"filelink": filelink,
|
||||
"file_link": file_link,
|
||||
"pubdate": episode["published"],
|
||||
"length": file_length
|
||||
}
|
||||
episodeList.append(tempepisode)
|
||||
episode_list.append(temp_episode)
|
||||
|
||||
tempdict = {
|
||||
temp_dict = {
|
||||
"title": dict_object["feed"]["title"],
|
||||
"subtitle": dict_object["feed"]["subtitle"],
|
||||
"summary": dict_object["feed"]["summary"],
|
||||
"episodes": episodeList
|
||||
"episodes": episode_list
|
||||
}
|
||||
return tempdict
|
||||
return temp_dict
|
||||
|
||||
def serialize_rss(self, dict_object):
|
||||
assert isinstance(dict_object, dict)
|
||||
@@ -62,7 +63,7 @@ class PodcastSerializer(Serializer):
|
||||
episodes_list += "<title>" + episode["title"] + "</title>"
|
||||
episodes_list += "<description>" + episode["subtitle"] + "</description>"
|
||||
episodes_list += "<pubDate>" + episode["pubdate"] + "</pubDate>"
|
||||
episodes_list += "<enclosure url=\"" + episode["filelink"] + "\" type=\"" + self.episode_file_type + "\" length=\"" + episode["length"] + "\"/>"
|
||||
episodes_list += "<enclosure url=\"" + episode["file_link"] + "\" type=\"" + self.episode_file_type + "\" length=\"" + episode["length"] + "\"/>"
|
||||
episodes_list += "</item>"
|
||||
|
||||
return RSS_Prefix + rss_channel_info + episodes_list + RSS_Suffix
|
||||
|
||||
6
testenv/testfeeds/podcast/lnp/lnp-config.json
Normal file
6
testenv/testfeeds/podcast/lnp/lnp-config.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"LinkType": "audio/opus",
|
||||
"FeedUrl": "http://logbuch-netzpolitik.de/feed/opus",
|
||||
"FeedType": "podcast",
|
||||
"FeedName": "lnp"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"LinkType": "audio/mpeg",
|
||||
"FeedUrl": "http://www.medienkuh.de/feed/mp3-archiv/",
|
||||
"FeedType": "podcast",
|
||||
"FeedName": "medienkuh"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"LinkType": "application/x-bittorrent",
|
||||
"FeedUrl": "http://www.staatsbuergerkunde-podcast.de/feed/mp3-rss/",
|
||||
"LinkType": "audio/opus",
|
||||
"FeedUrl": "http://www.staatsbuergerkunde-podcast.de/feed/opus-rss/",
|
||||
"FeedType": "podcast",
|
||||
"FeedName": "sbk"
|
||||
}
|
||||
@@ -1,210 +1,364 @@
|
||||
{
|
||||
"title": "Staatsb\u00fcrgerkunde",
|
||||
"subtitle": "Vom Leben in der DDR",
|
||||
"episodes": [
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2832/s/feed/c/opus-rss/SBK071_Gesundheitssystem_2.opus",
|
||||
"pubdate": "Sat, 19 Mar 2016 05:00:48 +0000",
|
||||
"title": "SBK071 Gesundheitssystem (2)",
|
||||
"subtitle": "Von der Kunst, der Wissenschaft und dem Leben",
|
||||
"length": "46933446"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2792/s/feed/c/opus-rss/SBK070_Propaganda_1.opus",
|
||||
"pubdate": "Sat, 20 Feb 2016 05:00:48 +0000",
|
||||
"title": "SBK070 Propaganda (1)",
|
||||
"subtitle": "Von rosaroten Brillen, Durchhalteparolen und der Ohnmacht der Worte",
|
||||
"length": "29456554"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2744/s/feed/c/opus-rss/EXPB005_Stasigefaengnis_Martin_Fischer_Lev_Illya.opus",
|
||||
"pubdate": "Sun, 31 Jan 2016 17:00:01 +0000",
|
||||
"title": "SBK069 \u2013 EXPB005 Stasi-Gef\u00e4ngnis Hohensch\u00f6nhausen",
|
||||
"subtitle": "Crossover-Folge mit dem \"Exponiert-Museumspodcast aus Berlin\" (fast) aus der Gedenkst\u00e4tte Hohensch\u00f6nhausen",
|
||||
"length": "42192154"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2701/s/feed/c/opus-rss/EXPB001_DDR_Museum_Martin_Fischer.opus",
|
||||
"pubdate": "Sat, 23 Jan 2016 05:00:06 +0000",
|
||||
"title": "SBK068 \u2013 EXPB001 DDR Museum Berlin",
|
||||
"subtitle": "Crossover-Folge mit dem \"Exponiert-Museumspodcast aus Berlin\" aus dem DDR-Museum",
|
||||
"length": "79230230"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2654/s/feed/c/opus-rss/SBK067_Ost-West-Freundschaft.opus",
|
||||
"pubdate": "Sat, 02 Jan 2016 05:00:47 +0000",
|
||||
"title": "SBK067 Ost-West-Freundschaft",
|
||||
"subtitle": "Von langer Verbundenheit, Nachrichten zwischen den Zeilen und grenzenloser Freundschaft",
|
||||
"length": "39726116"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2626/s/feed/c/opus-rss/SBK066_Stasi-Gefaengnis.opus",
|
||||
"pubdate": "Sat, 12 Dec 2015 05:00:00 +0000",
|
||||
"title": "SBK066 Stasi-Gef\u00e4ngnis",
|
||||
"subtitle": "Von Endstationen, mutigen Entscheidungen und vom Optimismus",
|
||||
"length": "54527546"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2592/s/feed/c/opus-rss/SBK065_Sport_1.opus",
|
||||
"pubdate": "Sat, 21 Nov 2015 05:00:42 +0000",
|
||||
"title": "SBK065 Sport (1)",
|
||||
"subtitle": "Von Bewegungen, Vereinsgeschichten und Sportgesch\u00e4ften",
|
||||
"length": "47186012"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2551/s/feed/c/opus-rss/SBK064_Mauerweg.opus",
|
||||
"pubdate": "Sat, 31 Oct 2015 05:00:12 +0000",
|
||||
"title": "SBK064 Mauerweg",
|
||||
"subtitle": "Von Stadtgrenzen, Waldwegen und Todesstreifen",
|
||||
"length": "30067720"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2530/s/feed/c/opus-rss/SBK063_Treuhand.opus",
|
||||
"pubdate": "Sat, 26 Sep 2015 04:00:46 +0000",
|
||||
"title": "SBK063 Treuhand",
|
||||
"subtitle": "Vom Volkseigentum, Ausverk\u00e4ufen und Erfolgsgeschichten",
|
||||
"length": "44094572"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2491/s/feed/c/opus-rss/SBK062_West-Berlin.opus",
|
||||
"pubdate": "Sat, 05 Sep 2015 04:00:27 +0000",
|
||||
"title": "SBK062 West-Berlin",
|
||||
"subtitle": "Von halben St\u00e4dten, Grenzerfahrungen und neuen Identit\u00e4ten",
|
||||
"length": "37432925"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2471/s/feed/c/opus-rss/SBK061_LPG.opus",
|
||||
"pubdate": "Sat, 15 Aug 2015 04:00:13 +0000",
|
||||
"title": "SBK061 LPG",
|
||||
"subtitle": "Von Pflanzen und Tieren, Altem und Neuem sowie Pl\u00e4nen und Zielen",
|
||||
"length": "26013501"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2407/s/feed/c/opus-rss/SBK060_Seefahrt.opus",
|
||||
"pubdate": "Sat, 25 Jul 2015 04:00:46 +0000",
|
||||
"title": "SBK060 Seefahrt",
|
||||
"subtitle": "Vom Leben an der K\u00fcste, st\u00fcrmischen Zeiten und Reiseandenken",
|
||||
"length": "40925709"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2397/s/feed/c/opus-rss/SBK059_Formel_Easter.opus",
|
||||
"pubdate": "Sat, 04 Jul 2015 04:00:10 +0000",
|
||||
"title": "SBK059 Formel Easter",
|
||||
"subtitle": "Vom Rennzirkus, der Geschwindigkeit und neuen Gef\u00e4hrten",
|
||||
"length": "25833874"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2380/s/feed/c/opus-rss/SBK058_Parteiarbeit_2.opus",
|
||||
"pubdate": "Sat, 13 Jun 2015 04:00:15 +0000",
|
||||
"title": "SBK058 Parteiarbeit (2)",
|
||||
"subtitle": "Von Gewissensentscheidungen, Verantwortung und der dunklen Seite der Macht",
|
||||
"length": "25114699"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2360/s/feed/c/opus-rss/SBK057_Comic_Das_UPgrade.opus",
|
||||
"pubdate": "Sat, 23 May 2015 04:00:59 +0000",
|
||||
"title": "SBK057 Comic Das UPgrade",
|
||||
"subtitle": "Von Ideen in der Badewanne, neu entdeckten Berufen und der k\u00fcnstlerischen Freiheit",
|
||||
"length": "62374831"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2343/s/feed/c/opus-rss/SBK056_Fragestunde_2.opus",
|
||||
"pubdate": "Sat, 02 May 2015 04:00:45 +0000",
|
||||
"title": "SBK056 Fragestunde (2)",
|
||||
"subtitle": "Von liebsten Filmen, neuen Dimensionen und gro\u00dfen Gef\u00fchlen",
|
||||
"length": "26685701"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2326/s/feed/c/opus-rss/SBK055_Science_Fiction.opus",
|
||||
"pubdate": "Sat, 11 Apr 2015 04:00:15 +0000",
|
||||
"title": "SBK055 Science Fiction",
|
||||
"subtitle": "Von guter Literatur, einer besseren Zukunft und allerhand Fantasie",
|
||||
"length": "27427676"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2303/s/feed/c/opus-rss/SBK054_Kindheit_2.opus",
|
||||
"pubdate": "Sat, 21 Mar 2015 05:00:35 +0000",
|
||||
"title": "SBK054 Kindheit (2)",
|
||||
"subtitle": "Von kleinen Leuten, mittleren Katastrophen und gro\u00dfen Konflikten",
|
||||
"length": "34313344"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2284/s/feed/c/opus-rss/SBK053_Marken.opus",
|
||||
"pubdate": "Sat, 28 Feb 2015 05:00:18 +0000",
|
||||
"title": "SBK053 Marken",
|
||||
"subtitle": "Von Verhei\u00dfungen, Absatzm\u00e4rkten und Spitzenreitern",
|
||||
"length": "28897853"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2250/s/feed/c/opus-rss/SBK052_Geld.opus",
|
||||
"pubdate": "Sat, 07 Feb 2015 05:00:53 +0000",
|
||||
"title": "SBK052 Geld",
|
||||
"subtitle": "Von neuem Geld, alten Preisen und dem gro\u00dfen Bankrott",
|
||||
"length": "33310727"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2120/s/feed/c/opus-rss/SBK051_DDR-Sprech_2.opus",
|
||||
"pubdate": "Sat, 17 Jan 2015 05:00:57 +0000",
|
||||
"title": "SBK051 DDR-Sprech (2)",
|
||||
"subtitle": "Von der \u00dcberwachung, Demonstrationen und dem Unrechtsstaat",
|
||||
"length": "29930678"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2072/s/feed/c/opus-rss/SBK050_Kabarett.opus",
|
||||
"pubdate": "Sat, 27 Dec 2014 05:00:30 +0000",
|
||||
"title": "SBK050 Kabarett",
|
||||
"subtitle": "Von professionellen Laien, Katz-und-Maus-Spielen und einem Pakt mit dem Publikum",
|
||||
"length": "33121835"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/2023/s/feed/c/opus-rss/SBK049_Weihnachten_2014.opus",
|
||||
"pubdate": "Wed, 24 Dec 2014 05:00:39 +0000",
|
||||
"title": "SBK049 Weihnachten 2014",
|
||||
"subtitle": "Vom neuen Pl\u00e4nen, dem Warten aufs Christkind und dem Blick hinter die Kulissen",
|
||||
"length": "101436999"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1989/s/feed/c/opus-rss/SBK048_Parteiarbeit_1.opus",
|
||||
"pubdate": "Sat, 06 Dec 2014 05:00:12 +0000",
|
||||
"title": "SBK048 Parteiarbeit (1)",
|
||||
"subtitle": "Von der Qual der Wahl, der gro\u00dfen Politik und vielf\u00e4ltiger Basisarbeit",
|
||||
"length": "37546060"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1977/s/feed/c/opus-rss/SBK047_Wende_3.opus",
|
||||
"pubdate": "Sat, 15 Nov 2014 05:00:18 +0000",
|
||||
"title": "SBK047 Wende (3)",
|
||||
"subtitle": "Vom Neuanfang, dem Weggehen und dem Zur\u00fcckkommen",
|
||||
"length": "24493174"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1953/s/feed/c/opus-rss/SBK046_Wende_2.opus",
|
||||
"pubdate": "Sat, 25 Oct 2014 04:00:02 +0000",
|
||||
"title": "SBK046 Wende (2)",
|
||||
"subtitle": "Von Ungewissheiten, neuen M\u00f6glichkeiten und Jungunternehmertum",
|
||||
"length": "16778718"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1920/s/feed/c/opus-rss/SBK045_Wende_1.opus",
|
||||
"pubdate": "Sat, 04 Oct 2014 04:00:59 +0000",
|
||||
"title": "SBK045 Wende (1)",
|
||||
"subtitle": "Von Briefen aus der Freiheit, unruhigen Tagen und vielen Ver\u00e4nderungen",
|
||||
"length": "39378014"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1878/s/feed/c/opus-rss/SBK044_Kunst_und_Kultur_2.opus",
|
||||
"pubdate": "Sat, 13 Sep 2014 04:00:26 +0000",
|
||||
"title": "SBK044 Kunst und Kultur (2)",
|
||||
"subtitle": "Von kunstvollen Rouladennadeln, Kulturgruppen und Zauberpr\u00fcfungen",
|
||||
"length": "35983020"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1837/s/feed/c/opus-rss/SBK043_Kunst_und_Kultur_1.opus",
|
||||
"pubdate": "Sat, 23 Aug 2014 04:00:26 +0000",
|
||||
"title": "SBK043 Kunst und Kultur (1)",
|
||||
"subtitle": "Von Kulturbanausen, Heimatdichtern und Weltstars",
|
||||
"length": "39283526"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1821/s/feed/c/opus-rss/SBK042_Behinderung.opus",
|
||||
"pubdate": "Sat, 02 Aug 2014 04:00:44 +0000",
|
||||
"title": "SBK042 Behinderung",
|
||||
"subtitle": "Von vertrauten Umgebungen, dem eigenen Leben und der Zugeh\u00f6rigkeit",
|
||||
"length": "28567248"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1758/s/feed/c/opus-rss/SBK041_Kindheit_1.opus",
|
||||
"pubdate": "Sat, 12 Jul 2014 04:00:34 +0000",
|
||||
"title": "SBK041 Kindheit (1)",
|
||||
"subtitle": "Vom Tischtennis, einem zu eng gewordenen Land und unbeschwerten Zeiten",
|
||||
"length": "31303160"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1703/s/feed/c/opus-rss/SBK040_DDR-Sprech.opus",
|
||||
"pubdate": "Sat, 21 Jun 2014 04:00:01 +0000",
|
||||
"title": "SBK040 DDR-Sprech",
|
||||
"subtitle": "Von der vierten Gewalt, Sprachregelungen und \u00dcbersetzungsfehlern",
|
||||
"length": "68565845"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1672/s/feed/c/opus-rss/SBK039_Stasi-Aufarbeitung.opus",
|
||||
"pubdate": "Sat, 31 May 2014 04:00:11 +0000",
|
||||
"title": "SBK039 Stasi-Aufarbeitung",
|
||||
"subtitle": "Vom Widerstand, Ungeheuerlichem und historischen Aufgaben",
|
||||
"length": "52883022"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1636/s/feed/c/opus-rss/SBK038_Freie_Rede_1.opus",
|
||||
"pubdate": "Sat, 10 May 2014 04:00:21 +0000",
|
||||
"title": "SBK038 Freie Rede (1)",
|
||||
"subtitle": "Vom Funken, Erholen, Bezahlen und Spielen",
|
||||
"length": "29374441"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1597/s/feed/c/opus-rss/SBK037_Fragestunde_1.opus",
|
||||
"pubdate": "Sat, 19 Apr 2014 04:00:00 +0000",
|
||||
"title": "SBK037 Fragestunde (Teil 1)",
|
||||
"subtitle": "Von Wertstoffen, der Wertsch\u00f6pfung und der Wertsch\u00e4tzung",
|
||||
"length": "39547682"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1575/s/feed/c/opus-rss/SBK036_Sowjetunion.opus",
|
||||
"pubdate": "Sat, 29 Mar 2014 05:00:34 +0000",
|
||||
"title": "SBK036 Sowjetunion",
|
||||
"subtitle": "Von kleinen und gro\u00dfen Br\u00fcdern, Weltsprachen und der Freundschaft",
|
||||
"length": "29205429"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1544/s/feed/c/opus-rss/SBK035_Studium.opus",
|
||||
"pubdate": "Sat, 08 Mar 2014 05:00:17 +0000",
|
||||
"title": "SBK035 Studium",
|
||||
"subtitle": "Von Stipendien, Studienpl\u00e4nen und der richtigen Einstellung",
|
||||
"length": "44695072"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1523/s/feed/c/opus-rss/SBK034_Kleiner_Grenzverkehr.opus",
|
||||
"pubdate": "Sat, 15 Feb 2014 05:00:58 +0000",
|
||||
"title": "SBK034 Kleiner Grenzverkehr",
|
||||
"subtitle": "Von Einreisen, Eintrittspreisen und Einbahnstra\u00dfen",
|
||||
"length": "24502044"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1441/s/feed/c/opus-rss/SBK033_Jugendweihe.opus",
|
||||
"pubdate": "Sat, 25 Jan 2014 05:00:59 +0000",
|
||||
"title": "SBK033 Jugendweihe",
|
||||
"subtitle": "Von Jugendstunden, dem Erwachsenwerden und Lippenbekenntnissen",
|
||||
"length": "27922157"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1392/s/feed/c/opus-rss/SBK032_Die_Mauer_Yadegar_Asisi.opus",
|
||||
"pubdate": "Sat, 04 Jan 2014 05:00:38 +0000",
|
||||
"title": "SBK032 Die Mauer \u2013 Yadegar Asisi",
|
||||
"subtitle": "Von \u00dcberg\u00e4ngen, Blickwechseln und der Normalit\u00e4t",
|
||||
"length": "42565599"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1368/s/feed/c/opus-rss/SBK031_Volkspolizei.opus",
|
||||
"pubdate": "Sat, 14 Dec 2013 05:00:29 +0000",
|
||||
"title": "SBK031 Volkspolizei",
|
||||
"subtitle": "Von Freunden und Helfern, Handlungsspielr\u00e4umen und vom Vertrauen",
|
||||
"length": "47258288"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1345/s/feed/c/opus-rss/SBK030_Weissensee.opus",
|
||||
"pubdate": "Sat, 23 Nov 2013 05:00:56 +0000",
|
||||
"title": "SBK030 Wei\u00dfensee",
|
||||
"subtitle": "Von gro\u00dfartigen Schauspielleistungen, der Suche nach Authentizit\u00e4t und dem Blick auf die Anderen",
|
||||
"length": "32795611"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1333/s/feed/c/opus-rss/SBK029_Post_und_Telefon.opus",
|
||||
"pubdate": "Sat, 02 Nov 2013 05:00:53 +0000",
|
||||
"title": "SBK029 Post und Telefon",
|
||||
"subtitle": "Von Warensendungen, Briefgeheimnissen und Knacken in der Leitung",
|
||||
"length": "22079662"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1278/s/feed/c/opus-rss/SBK028_Arbeit.opus",
|
||||
"pubdate": "Sat, 12 Oct 2013 04:00:44 +0000",
|
||||
"length": "32992167",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK028_Arbeit.mp3.torrent",
|
||||
"title": "SBK028 Arbeit",
|
||||
"subtitle": "Von Kollektivleistungen, Planstellen und dem Lohn der Arbeit",
|
||||
"title": "SBK028 Arbeit"
|
||||
"length": "33538103"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1242/s/feed/c/opus-rss/SBK027_Lehrerberuf.opus",
|
||||
"pubdate": "Sat, 21 Sep 2013 04:00:24 +0000",
|
||||
"length": "30136877",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK027_Lehrerberuf.mp3.torrent",
|
||||
"title": "SBK027 Lehrerberuf",
|
||||
"subtitle": "Vom Traumberuf, Experimenten und Schulpolitik",
|
||||
"title": "SBK027 Lehrerberuf"
|
||||
"length": "30175103"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/1181/s/feed/c/opus-rss/SBK026_Lebensmittel.opus",
|
||||
"pubdate": "Sat, 31 Aug 2013 04:00:56 +0000",
|
||||
"length": "26770243",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK026_Lebensmittel.mp3.torrent",
|
||||
"title": "SBK026 Lebensmittel",
|
||||
"subtitle": "Vom Konsum, geheimem Rotwein und Tieren ohne Lenden",
|
||||
"title": "SBK026 Lebensmittel"
|
||||
"length": "27058374"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/891/s/feed/c/opus-rss/SBK025_Wohnen.opus",
|
||||
"pubdate": "Sat, 10 Aug 2013 04:00:17 +0000",
|
||||
"length": "38635646",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK025_Wohnen.mp3.torrent",
|
||||
"title": "SBK025 Wohnen",
|
||||
"subtitle": "Von sch\u00f6nen Plattenbauten, viel Kohle und ganz viel Eigenleistung",
|
||||
"title": "SBK025 Wohnen"
|
||||
"length": "39040168"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/647/s/feed/c/opus-rss/SBK024_Kirchenmusik.opus",
|
||||
"pubdate": "Mon, 15 Jul 2013 17:00:13 +0000",
|
||||
"length": "38199474",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK024_Kirchenmusik.mp3.torrent",
|
||||
"title": "SBK024 Kirchenmusik",
|
||||
"subtitle": "Von gezogenen Registern, ungew\u00f6hnlichen Berufswegen und gro\u00dfer Musik",
|
||||
"title": "SBK024 Kirchenmusik"
|
||||
"length": "38576751"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/422/s/feed/c/opus-rss/SBK023_Feier_und_Gedenktage.opus",
|
||||
"pubdate": "Sat, 29 Jun 2013 04:00:35 +0000",
|
||||
"length": "32919850",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK023_Feier_und_Gedenktage.mp3.torrent",
|
||||
"title": "SBK023 Feier- und Gedenktage",
|
||||
"subtitle": "Von Halbtags-Demonstranten, Papiertauben und Tagedieben",
|
||||
"title": "SBK023 Feier- und Gedenktage"
|
||||
"length": "33277058"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/262/s/feed/c/opus-rss/SBK022_Station.opus",
|
||||
"pubdate": "Sat, 08 Jun 2013 04:00:10 +0000",
|
||||
"length": "37727485",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK022_Station.mp3.torrent",
|
||||
"title": "SBK022 Station",
|
||||
"subtitle": "Vom Forscherdrang, Wechselblinkern und n\u00e4chtlichen Bastelrunden",
|
||||
"title": "SBK022 Station"
|
||||
"length": "37743772"
|
||||
},
|
||||
{
|
||||
"file_link": "http://www.staatsbuergerkunde-podcast.de/podlove/file/157/s/feed/c/opus-rss/SBK021_Wahlen.opus",
|
||||
"pubdate": "Sun, 19 May 2013 09:03:45 +0000",
|
||||
"length": "26309869",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK021_Wahlen.mp3.torrent",
|
||||
"title": "SBK021 Wahlen",
|
||||
"subtitle": "Wir sprechen \u00fcber Blockparteien, gefaltete Zettel und Wahlbeobachtungen in beide Richtungen.",
|
||||
"title": "SBK021 Wahlen"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 27 Apr 2013 04:00:58 +0000",
|
||||
"length": "28570821",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK020_Gesundheitssystem.mp3.torrent",
|
||||
"subtitle": "Gesundheit \u2013 ist das Thema unserer heutigen Folge. Wie war es, wenn man in der DDR krank war und zum Arzt, zur \u00c4rztin oder gar ins Krankenhaus musste? Wie war man krankenversichert und warum sind Polikliniken auch heute noch modern?",
|
||||
"title": "SBK020 Gesundheitssystem"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 06 Apr 2013 04:00:26 +0000",
|
||||
"length": "35877572",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK019_NVA.mp3.torrent",
|
||||
"subtitle": "Wir sprechen \u00fcber den Grundwehrdienst meines Vaters in der Nationalen Volksarmee und welche Erfahrungen er und wir in dieser Zeit gemacht haben.",
|
||||
"title": "SBK019 NVA"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 16 Mar 2013 05:00:20 +0000",
|
||||
"length": "34306613",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK018_Ausreise_Teil_2.mp3.torrent",
|
||||
"subtitle": "Die Ausreise ist genehmigt \u2013 wie ging es nun weiter? Wir sprechen in dieser Folge \u00fcber die Zeit bis zum Ausreisetag, unsere Ankunft in der BRD und die ersten Schritte in diesem f\u00fcr uns neuen Land.",
|
||||
"title": "SBK018 Ausreise (Teil 2)"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 23 Feb 2013 05:00:50 +0000",
|
||||
"length": "43723255",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK017_Ausreise_Teil_1.mp3.torrent",
|
||||
"subtitle": "Meine Eltern haben 1987 einen Ausreiseantrag gestellt. Warum sie diesen Schritt gewagt haben, welche Konsequenzen er mit sich brachte und was w\u00e4hrend der zweij\u00e4hrigen Wartezeit bis zur Ausreisegenehmigung alles geschah, dar\u00fcber sprechen wir in dieser Folge.",
|
||||
"title": "SBK017 Ausreise (Teil 1)"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 02 Feb 2013 05:00:54 +0000",
|
||||
"length": "49337236",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK016_Geschlechterrollen.mp3.torrent",
|
||||
"subtitle": "Ost, West, Mann, Frau: Mit Katrin R\u00f6nicke spreche ich \u00fcber die unterschiedlichen Geschlechterbilder in der DDR und der BRD und wie es war, als M\u00e4dchen oder Junge in den beiden Deutschlands aufzuwachsen.",
|
||||
"title": "SBK016 Geschlechterrollen"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 12 Jan 2013 05:00:07 +0000",
|
||||
"length": "45256236",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK015_Deutsche_Reichsbahn.mp3.torrent",
|
||||
"subtitle": "Alle einsteigen und Vorsicht bei der Abfahrt! Mit Ingo Ebel spreche ich in dieser Episode \u00fcber die Deutsche Reichsbahn.",
|
||||
"title": "SBK015 Deutsche Reichsbahn"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 22 Dec 2012 05:00:49 +0000",
|
||||
"length": "28653301",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK014_Weihnachten.mp3.torrent",
|
||||
"subtitle": "In der letzten Sendung f\u00fcr 2012 sprechen wir \u00fcber das Weihnachtsfest in der DDR.",
|
||||
"title": "SBK014 Weihnachten"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 01 Dec 2012 05:00:41 +0000",
|
||||
"length": "29335939",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK013_Computer.mp3.torrent",
|
||||
"subtitle": "Die Anf\u00e4nge des digitalen Zeitalters in der DDR besch\u00e4ftigen meinen Papa und mich in dieser Episode.",
|
||||
"title": "SBK013 Computer"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 10 Nov 2012 05:00:56 +0000",
|
||||
"length": "47995194",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK012_Kino.mp3.torrent",
|
||||
"subtitle": "In Spielfilml\u00e4nge pr\u00e4sentiert sich die aktuelle Episode. Mit Eric vom Kinocast spreche ich \u00fcber das Kino in der DDR.",
|
||||
"title": "SBK012 Kino"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 20 Oct 2012 04:00:25 +0000",
|
||||
"length": "34995346",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK011_Radio_und_Fernsehfunk.mp3.torrent",
|
||||
"subtitle": "Die Massenmedien Radio und Fernsehen besch\u00e4ftigen uns im dritten Teil unserer Medienreihe. Darin sprechen wir \u00fcber den Rundfunk in der DDR.",
|
||||
"title": "SBK011 Radio und Fernsehfunk"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 29 Sep 2012 04:00:53 +0000",
|
||||
"length": "18982902",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK010_Buecher.mp3.torrent",
|
||||
"subtitle": "In dieser Ausgabe \u2013 dem zweiten Teil unserer Medienreihe \u2013 sprechen wir \u00fcber B\u00fccher in der DDR.",
|
||||
"title": "SBK010 B\u00fccher"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 08 Sep 2012 04:00:18 +0000",
|
||||
"length": "19821953",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK009_Zeitungen_und_Zeitschriften.mp3.torrent",
|
||||
"subtitle": "In dieser und den n\u00e4chsten beiden Episoden sprechen wir \u00fcber verschiedene DDR-Medien, von der gedruckten Zeitung \u00fcber B\u00fccher bis hin zum Rundfunk. Im ersten Teil schauen wir uns das Presseangebot etwas genauer an.",
|
||||
"title": "SBK009 Zeitungen und Zeitschriften"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 18 Aug 2012 04:00:57 +0000",
|
||||
"length": "16969503",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK008_Comic_MOSAIK.mp3.torrent",
|
||||
"subtitle": "Comics in der DDR? Klar, auch die gab es! Und deren ber\u00fchmtester Vertreter ist das MOSAIK. Ich spreche mit dem k\u00fcnstlerischen Leiter des MOSAIK, J\u00f6rg Reuter, \u00fcber seine Zeit als Comicmacher in der DDR \u2013 und heute.",
|
||||
"title": "SBK008 Comic MOSAIK"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 28 Jul 2012 04:00:08 +0000",
|
||||
"length": "22724557",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK007_Verkehrsmittel.mp3.torrent",
|
||||
"subtitle": "Wie kam man als DDR-B\u00fcrger von A nach B? Zu Fu\u00df, mit Bus und Bahn oder gar mit dem eigenen Auto? Womit man in der DDR alles unterwegs war, dar\u00fcber sprechen wir in der heutigen Episode.",
|
||||
"title": "SBK007 Verkehrsmittel"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 07 Jul 2012 04:00:10 +0000",
|
||||
"length": "24172798",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK006_Urlaub.mp3.torrent",
|
||||
"subtitle": "Sommer, Sonne, Strand und Meer: Auch in der DDR zog es die Menschen im Urlaub in die Ferne. In unserer Urlaubsfolge sprechen wir in gewohnter Besetzung \u00fcber Ferienspiele, wichtige Anmeldelisten und FDGB-Heime.",
|
||||
"title": "SBK006 Urlaub"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 16 Jun 2012 04:00:58 +0000",
|
||||
"length": "25494334",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK005_Spielekopien.mp3.torrent",
|
||||
"subtitle": "Die Brettspiele Monopoly, Sagaland oder Scotland Yard gab es in der DDR nicht zu kaufen. Und sie wurden dennoch gespielt, weil kreative Bastler sie einfach nachgemacht haben. Das Projekt \"Nachgemacht\" rettet solche Spielekopien vor dem Vergessen.",
|
||||
"title": "SBK005 Spielekopien"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 26 May 2012 04:00:55 +0000",
|
||||
"length": "16925540",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK004_Kleidung_und_Mode.mp3.torrent",
|
||||
"subtitle": "Diese Folge ist komplett durchgestylt: Wir sprechen \u00fcber Kleidung und Mode in der DDR.",
|
||||
"title": "SBK004 Kleidung und Mode"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 05 May 2012 04:00:25 +0000",
|
||||
"length": "31037098",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK003_Schulsystem_Teil_2.mp3.torrent",
|
||||
"subtitle": "Nahtlos schlie\u00dfen wir an die letzte Folge an und sprechen \u00fcber den Oberstufenunterricht im DDR-Schulsystem.",
|
||||
"title": "SBK003 Schulsystem (Teil 2)"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sat, 14 Apr 2012 05:40:35 +0000",
|
||||
"length": "46541265",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK002_Schulsystem_Teil_1.mp3.torrent",
|
||||
"subtitle": "Auf dem Stundenplan steht heute das Schulsystem in der DDR. Aufgrund der vielen Aspekte, die dieses Themenfeld in sich birgt, ist diese Ausgabe der erste Teil einer Doppelfolge.",
|
||||
"title": "SBK002 Schulsystem (Teil 1)"
|
||||
},
|
||||
{
|
||||
"pubdate": "Fri, 23 Mar 2012 14:55:26 +0000",
|
||||
"length": "30616053",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK001_Stabue.mp3.torrent",
|
||||
"subtitle": "Die erste Folge nimmt sich das Schulfach vor, das dem Podcast seinen Namen gegeben hat: Staatsb\u00fcrgerkunde oder kurz \"Stab\u00fc\" genannt. Welchem Zweck diente dieses Fach? Welche Inhalte sollten im Unterricht vermittelt werden? Und wie gingen Lehrer und Sch\u00fcler mit offensichtlichen Widerspr\u00fcchen zwischen Fach und Realit\u00e4t um?",
|
||||
"title": "SBK001 Stab\u00fc"
|
||||
},
|
||||
{
|
||||
"pubdate": "Sun, 04 Mar 2012 07:46:19 +0000",
|
||||
"length": "2123022",
|
||||
"filelink": "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK000_Nullnummer.mp3.torrent",
|
||||
"subtitle": "Los geht's: Die Nullnummer ist da! Darin erkl\u00e4re ich, was ich mit \"Staatsb\u00fcrgerkunde\" vorhabe, wann die erste regul\u00e4re Folge zu h\u00f6ren sein wird um worum es darin geht.",
|
||||
"title": "SBK000 Nullnummer"
|
||||
"length": "26689242"
|
||||
}
|
||||
],
|
||||
"summary": "Ein Podcast \u00fcber das Leben in der DDR. Im Gespr\u00e4ch mit G\u00e4sten schaut Martin Fischer in jeder Folge zur\u00fcck auf die Lebensaspekte eines B\u00fcrgers der ehemaligen Deutschen Demokratischen Republik. Vom Schulsystem, dem kulturellen Leben bis hin zu den politischen Repressionen reicht das Themenspektrum. Der Podcast erscheint ungef\u00e4hr alle drei Wochen.",
|
||||
"subtitle": "Vom Leben in der DDR",
|
||||
"title": "Staatsb\u00fcrgerkunde"
|
||||
"summary": "Ein Podcast \u00fcber das Leben in der DDR. Im Gespr\u00e4ch mit G\u00e4sten schaut Martin Fischer in jeder Folge zur\u00fcck auf die Lebensaspekte eines B\u00fcrgers der ehemaligen Deutschen Demokratischen Republik. Vom Schulsystem, dem kulturellen Leben bis hin zu den politischen Repressionen reicht das Themenspektrum. Der Podcast erscheint ungef\u00e4hr alle drei Wochen."
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
6
testenv/testfeeds/rss/example/example-config.json
Normal file
6
testenv/testfeeds/rss/example/example-config.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"FeedType": "rss",
|
||||
"FeedName": "example",
|
||||
"FeedUrl": "testfeeds/rss/feed.xml",
|
||||
"LinkType": "application/x-bittorrent"
|
||||
}
|
||||
211
testenv/testfeeds/rss/example/example.json
Normal file
211
testenv/testfeeds/rss/example/example.json
Normal file
@@ -0,0 +1,211 @@
|
||||
{
|
||||
"encoding": "utf-8",
|
||||
"version": "rss20",
|
||||
"namespaces": {},
|
||||
"bozo": 0,
|
||||
"entries": [
|
||||
{
|
||||
"title": "Star City",
|
||||
"title_detail": {
|
||||
"value": "Star City",
|
||||
"base": "",
|
||||
"type": "text/plain",
|
||||
"language": null
|
||||
},
|
||||
"published": "Tue, 03 Jun 2003 09:39:21 GMT",
|
||||
"summary": "How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's <a href=\"http://howe.iki.rssi.ru/GCTC/gctc_e.htm\">Star City</a>.",
|
||||
"links": [
|
||||
{
|
||||
"rel": "alternate",
|
||||
"href": "http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp",
|
||||
"type": "text/html"
|
||||
}
|
||||
],
|
||||
"summary_detail": {
|
||||
"value": "How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's <a href=\"http://howe.iki.rssi.ru/GCTC/gctc_e.htm\">Star City</a>.",
|
||||
"base": "",
|
||||
"type": "text/html",
|
||||
"language": null
|
||||
},
|
||||
"id": "http://liftoff.msfc.nasa.gov/2003/06/03.html#item573",
|
||||
"link": "http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp",
|
||||
"published_parsed": [
|
||||
2003,
|
||||
6,
|
||||
3,
|
||||
9,
|
||||
39,
|
||||
21,
|
||||
1,
|
||||
154,
|
||||
0
|
||||
],
|
||||
"guidislink": false
|
||||
},
|
||||
{
|
||||
"guidislink": true,
|
||||
"published": "Fri, 30 May 2003 11:06:42 GMT",
|
||||
"published_parsed": [
|
||||
2003,
|
||||
5,
|
||||
30,
|
||||
11,
|
||||
6,
|
||||
42,
|
||||
4,
|
||||
150,
|
||||
0
|
||||
],
|
||||
"summary": "Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a <a href=\"http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm\">partial eclipse of the Sun</a> on Saturday, May 31st.",
|
||||
"summary_detail": {
|
||||
"value": "Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a <a href=\"http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm\">partial eclipse of the Sun</a> on Saturday, May 31st.",
|
||||
"base": "",
|
||||
"type": "text/html",
|
||||
"language": null
|
||||
},
|
||||
"id": "http://liftoff.msfc.nasa.gov/2003/05/30.html#item572",
|
||||
"link": "http://liftoff.msfc.nasa.gov/2003/05/30.html#item572"
|
||||
},
|
||||
{
|
||||
"title": "The Engine That Does More",
|
||||
"title_detail": {
|
||||
"value": "The Engine That Does More",
|
||||
"base": "",
|
||||
"type": "text/plain",
|
||||
"language": null
|
||||
},
|
||||
"published": "Tue, 27 May 2003 08:37:32 GMT",
|
||||
"summary": "Before man travels to Mars, NASA hopes to design new engines that will let us fly through the Solar System more quickly. The proposed VASIMR engine would do that.",
|
||||
"links": [
|
||||
{
|
||||
"rel": "alternate",
|
||||
"href": "http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp",
|
||||
"type": "text/html"
|
||||
}
|
||||
],
|
||||
"summary_detail": {
|
||||
"value": "Before man travels to Mars, NASA hopes to design new engines that will let us fly through the Solar System more quickly. The proposed VASIMR engine would do that.",
|
||||
"base": "",
|
||||
"type": "text/html",
|
||||
"language": null
|
||||
},
|
||||
"id": "http://liftoff.msfc.nasa.gov/2003/05/27.html#item571",
|
||||
"link": "http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp",
|
||||
"published_parsed": [
|
||||
2003,
|
||||
5,
|
||||
27,
|
||||
8,
|
||||
37,
|
||||
32,
|
||||
1,
|
||||
147,
|
||||
0
|
||||
],
|
||||
"guidislink": false
|
||||
},
|
||||
{
|
||||
"title": "Astronauts' Dirty Laundry",
|
||||
"title_detail": {
|
||||
"value": "Astronauts' Dirty Laundry",
|
||||
"base": "",
|
||||
"type": "text/plain",
|
||||
"language": null
|
||||
},
|
||||
"published": "Tue, 20 May 2003 08:56:02 GMT",
|
||||
"summary": "Compared to earlier spacecraft, the International Space Station has many luxuries, but laundry facilities are not one of them. Instead, astronauts have other options.",
|
||||
"links": [
|
||||
{
|
||||
"rel": "alternate",
|
||||
"href": "http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp",
|
||||
"type": "text/html"
|
||||
}
|
||||
],
|
||||
"summary_detail": {
|
||||
"value": "Compared to earlier spacecraft, the International Space Station has many luxuries, but laundry facilities are not one of them. Instead, astronauts have other options.",
|
||||
"base": "",
|
||||
"type": "text/html",
|
||||
"language": null
|
||||
},
|
||||
"id": "http://liftoff.msfc.nasa.gov/2003/05/20.html#item570",
|
||||
"link": "http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp",
|
||||
"published_parsed": [
|
||||
2003,
|
||||
5,
|
||||
20,
|
||||
8,
|
||||
56,
|
||||
2,
|
||||
1,
|
||||
140,
|
||||
0
|
||||
],
|
||||
"guidislink": false
|
||||
}
|
||||
],
|
||||
"feed": {
|
||||
"title": "Liftoff News",
|
||||
"authors": [
|
||||
{}
|
||||
],
|
||||
"title_detail": {
|
||||
"value": "Liftoff News",
|
||||
"base": "",
|
||||
"type": "text/plain",
|
||||
"language": null
|
||||
},
|
||||
"published": "Tue, 10 Jun 2003 04:00:00 GMT",
|
||||
"generator_detail": {
|
||||
"name": "Weblog Editor 2.0"
|
||||
},
|
||||
"subtitle_detail": {
|
||||
"value": "Liftoff to Space Exploration.",
|
||||
"base": "",
|
||||
"type": "text/html",
|
||||
"language": null
|
||||
},
|
||||
"link": "http://liftoff.msfc.nasa.gov/",
|
||||
"language": "en-us",
|
||||
"publisher_detail": {
|
||||
"email": "webmaster@example.com"
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"rel": "alternate",
|
||||
"href": "http://liftoff.msfc.nasa.gov/",
|
||||
"type": "text/html"
|
||||
}
|
||||
],
|
||||
"docs": "http://blogs.law.harvard.edu/tech/rss",
|
||||
"subtitle": "Liftoff to Space Exploration.",
|
||||
"author_detail": {
|
||||
"email": "editor@example.com"
|
||||
},
|
||||
"publisher": "webmaster@example.com",
|
||||
"updated_parsed": [
|
||||
2003,
|
||||
6,
|
||||
10,
|
||||
9,
|
||||
41,
|
||||
1,
|
||||
1,
|
||||
161,
|
||||
0
|
||||
],
|
||||
"published_parsed": [
|
||||
2003,
|
||||
6,
|
||||
10,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
161,
|
||||
0
|
||||
],
|
||||
"updated": "Tue, 10 Jun 2003 09:41:01 GMT",
|
||||
"author": "editor@example.com",
|
||||
"generator": "Weblog Editor 2.0"
|
||||
}
|
||||
}
|
||||
33
testenv/tests/feed/test_entry_handler.py
Normal file
33
testenv/tests/feed/test_entry_handler.py
Normal file
@@ -0,0 +1,33 @@
|
||||
__author__ = 'dev'
|
||||
|
||||
import unittest
|
||||
from feed.entry_handler import EntryHandler
|
||||
from feed.feed import Feed
|
||||
import utilities.file_methods as fm
|
||||
|
||||
|
||||
class TestEntryHandler(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.__feed = Feed("example", "rss", "application/x-bittorrent", "testfeeds/rss/example/feed.xml")
|
||||
self.__lh = EntryHandler(self.__feed)
|
||||
|
||||
def test__init_wrong_feed_object(self):
|
||||
self.assertRaises(AssertionError, EntryHandler, None)
|
||||
self.assertRaises(AssertionError, EntryHandler, self.__lh)
|
||||
|
||||
def test_handle_entries(self):
|
||||
self.__lh.handle_entries()
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_handle_entry(self):
|
||||
self.__lh.handle_entry("www.example.com")
|
||||
self.assertTrue(True)
|
||||
|
||||
def test_detect_new_entries(self):
|
||||
feed_obj = fm.read_json_file(self.__feed.feed_file_path)
|
||||
self.assertListEqual(self.__lh.detect_new_entries(), feed_obj["entries"])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
53
testenv/tests/feed/test_torrent_cli_entry_handler.py
Normal file
53
testenv/tests/feed/test_torrent_cli_entry_handler.py
Normal file
@@ -0,0 +1,53 @@
|
||||
__author__ = 'dev'
|
||||
|
||||
import unittest
|
||||
from feed.torrent_cli_entry_handler import TorrentCliEntryHandler
|
||||
from feed.feed import Feed
|
||||
import urllib
|
||||
import os
|
||||
from config.config import Config
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
|
||||
class TestTorrentCliEntryHandler(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.__feed = Feed("sbk", "podcast", "application/x-bittorrent", "testfeeds/podcast/sbk/sbk.xml")
|
||||
self.__test_torrent = "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK028_Arbeit.mp3.torrent"
|
||||
self.__test_torrent2 = "testfeeds/podcast/SBK028_Arbeit.mp3.torrent"
|
||||
self.__test_torrent3 = "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK028_Arbeit.mp3.torren"
|
||||
self.__test_torrent4 = "testfeeds/podcast/SBK028_Arbeit.mp3.trrent"
|
||||
self.__torrent_file = "/home/dev/projects/feedcrawler/testenv/testtorrents/SBK028_Arbeit.mp3.torrent"
|
||||
self.__torrent_folder = Config["TorrentStorageFolder"]
|
||||
self.__tceh = TorrentCliEntryHandler(self.__feed)
|
||||
|
||||
def tearDown(self):
|
||||
if os.path.exists(self.__torrent_file):
|
||||
os.remove(self.__torrent_file)
|
||||
if os.path.exists(self.__torrent_folder):
|
||||
shutil.rmtree(self.__torrent_folder)
|
||||
|
||||
def test_download_torrent(self):
|
||||
self.__tceh.download_torrent(self.__test_torrent)
|
||||
self.assertTrue(os.path.exists(self.__torrent_file))
|
||||
os.remove(self.__torrent_file)
|
||||
self.__tceh.download_torrent(self.__test_torrent2)
|
||||
self.assertTrue(os.path.exists(self.__torrent_file))
|
||||
|
||||
def test_download_torrent_wrong_url(self):
|
||||
self.assertRaises(urllib.error.HTTPError, self.__tceh.download_torrent,self.__test_torrent3)
|
||||
self.assertRaises(ValueError, self.__tceh.download_torrent, self.__test_torrent4)
|
||||
|
||||
def test_init_torrent_folder(self):
|
||||
self.__tceh.init_torrent_folder(self.__torrent_folder)
|
||||
self.assertTrue(os.path.exists(self.__torrent_folder))
|
||||
self.assertTrue(os.path.exists(TorrentCliEntryHandler.SettingFile))
|
||||
|
||||
def test_start_torrent(self):
|
||||
tc = self.__tceh.start_torrent("/home/dev/projects/feedcrawler/testenv/testfeeds/podcast/SBK028_Arbeit.mp3.torrent", "testtorrents/", "testtorrents/")
|
||||
self.assertTrue(isinstance(tc, subprocess.Popen))
|
||||
tc.terminate()
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
38
testenv/tests/feed/test_torrent_deamon.py
Normal file
38
testenv/tests/feed/test_torrent_deamon.py
Normal file
@@ -0,0 +1,38 @@
|
||||
__author__ = 'dev'
|
||||
|
||||
import unittest
|
||||
from feed.feed import Feed
|
||||
from feed.torrent_daemon_entry_handler import TorrentDaemonEntryHandler
|
||||
|
||||
class TestTorrentDaemonEntryHandler(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.__feed = Feed("sbk", "podcast", "application/x-bittorrent", "testfeeds/podcast/sbk/sbk.xml")
|
||||
self.__test_torrent = "http://bitlove.org/nitramred/staatsbuergerkunde-mp3/SBK028_Arbeit.mp3.torrent"
|
||||
self.__tdeh = TorrentDaemonEntryHandler(self.__feed)
|
||||
self.__tdeh.start_daemon()
|
||||
|
||||
def tearDown(self):
|
||||
self.__tdeh.stop_daemon()
|
||||
|
||||
def test_start_daemon(self):
|
||||
self.assertTrue(self.__tdeh.is_running_daemon())
|
||||
|
||||
def test_stop_daemon(self):
|
||||
self.__tdeh.stop_daemon()
|
||||
self.assertFalse(self.__tdeh.is_running_daemon())
|
||||
|
||||
def test_is_running_daemon(self):
|
||||
self.assertTrue(self.__tdeh.is_running_daemon())
|
||||
self.__tdeh.stop_daemon()
|
||||
self.assertFalse(self.__tdeh.is_running_daemon())
|
||||
|
||||
def test_start_torrent(self):
|
||||
self.assertTrue(False)
|
||||
|
||||
def test_add_torrent_to_daemon(self):
|
||||
self.__tdeh.add_torrent_to_daemon(self.__test_torrent)
|
||||
self.assertTrue(True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -10,7 +10,7 @@ import utilities.file_methods as fm
|
||||
class TestFeed(unittest.TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.testFeed = Feed("sbk", "podcast", "application/x-bittorrent", "testfeeds/podcast/sbk/sbk.xml")
|
||||
self.testFeed = Feed("sbk", "podcast", "audio/opus", "testfeeds/podcast/sbk/sbk.xml")
|
||||
|
||||
def test_load_new_feed(self):
|
||||
fm.check_and_remove_file("testfeeds/podcast/sbk/sbk.json")
|
||||
@@ -103,6 +103,45 @@ class TestFeed(unittest.TestCase):
|
||||
self.assertRaises(AssertionError, Feed.create_feed_config_file, "sbk", "podcast",
|
||||
"audiomg", None)
|
||||
|
||||
def test_create_feed_from_feed_config(self):
|
||||
newFeed = Feed.create_feed_from_feed_config(self.testFeed.feed_config)
|
||||
self.assertEqual(self.testFeed.config_path, newFeed.config_path)
|
||||
self.assertEqual(self.testFeed.feed_file_path, newFeed.feed_file_path)
|
||||
self.assertEqual(self.testFeed.feed_folder, newFeed.feed_folder)
|
||||
self.assertEqual(self.testFeed.feed_folder_path, newFeed.feed_folder_path)
|
||||
|
||||
def test_create_feed_from_feed_config_error(self):
|
||||
self.assertRaises(AssertionError, Feed.create_feed_from_feed_config, None)
|
||||
|
||||
def test_create_feed_from_feed_config_path(self):
|
||||
newFeed = Feed.create_feed_from_feed_config_path(self.testFeed.config_path)
|
||||
self.assertEqual(self.testFeed.config_path, newFeed.config_path)
|
||||
self.assertEqual(self.testFeed.feed_file_path, newFeed.feed_file_path)
|
||||
self.assertEqual(self.testFeed.feed_folder, newFeed.feed_folder)
|
||||
self.assertEqual(self.testFeed.feed_folder_path, newFeed.feed_folder_path)
|
||||
|
||||
def test_create_feed_from_feed_config_path_error(self):
|
||||
self.assertRaises(TypeError, Feed.create_feed_from_feed_config_path, None)
|
||||
self.assertRaises(AssertionError, Feed.create_feed_from_feed_config_path, "/root")
|
||||
self.assertRaises(AssertionError, Feed.create_feed_from_feed_config_path, ".")
|
||||
self.assertRaises(AssertionError, Feed.create_feed_from_feed_config_path, "bla.json")
|
||||
|
||||
def test_create_feed_from_feed_folder_path(self):
|
||||
newFeed = Feed.create_feed_from_feed_folder_path(self.testFeed.feed_folder_path)
|
||||
self.assertEqual(self.testFeed.config_path, newFeed.config_path)
|
||||
self.assertEqual(self.testFeed.feed_file_path, newFeed.feed_file_path)
|
||||
self.assertEqual(self.testFeed.feed_folder, newFeed.feed_folder)
|
||||
self.assertEqual(self.testFeed.feed_folder_path, newFeed.feed_folder_path)
|
||||
|
||||
def test_create_feed_from_feed_folder_path_error(self):
|
||||
self.assertRaises(TypeError, Feed.create_feed_from_feed_folder_path, None)
|
||||
self.assertRaises(IndexError, Feed.create_feed_from_feed_folder_path, "/root")
|
||||
self.assertRaises(IndexError, Feed.create_feed_from_feed_folder_path, ".")
|
||||
self.assertRaises(AssertionError, Feed.create_feed_from_feed_folder_path, "bla.json")
|
||||
|
||||
def test_create_feeds_from_storage_folder(self):
|
||||
feeds = Feed.create_feeds_from_storage_folder()
|
||||
self.assertEqual(2, len(feeds))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -15,7 +15,7 @@ class TestFileMethod(unittest.TestCase):
|
||||
self.__text_file_content = "this is a test"
|
||||
self.__json_object_file_content = {"1": "4711", "123": "0815"}
|
||||
self.__json_string_file_content = "{\"1\": \"4711\", \"123\": \"0815\"}"
|
||||
self.__feed_file_path = "testfeeds/rss/feed.xml"
|
||||
self.__feed_file_path = "testfeeds/rss/example/feed.xml"
|
||||
self.__feed_json_file_path = "testfeed.json"
|
||||
self.__empty_string = ""
|
||||
self.__wrong_dict = "{1}"
|
||||
@@ -97,5 +97,6 @@ class TestFileMethod(unittest.TestCase):
|
||||
self.assertRaises(AssertionError, fm.write_feed_json_file, self.__feed_json_file_path, None, None)
|
||||
fm.check_and_remove_file(self.__feed_json_file_path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
0
testenv/tests/webpage/cgitestrun/dummy
Normal file
0
testenv/tests/webpage/cgitestrun/dummy
Normal file
20
testenv/tests/webpage/webserver.py
Normal file
20
testenv/tests/webpage/webserver.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import unittest
|
||||
import os
|
||||
import shutil
|
||||
import ui.web.cgi.cgi_server as cgis
|
||||
|
||||
class WebServerTest(unittest.TestCase):
|
||||
|
||||
def test_runServer(self):
|
||||
|
||||
if os.path.exists("./tests/webpage/cgitestrun"):
|
||||
shutil.rmtree("./tests/webpage/cgitestrun")
|
||||
|
||||
os.mkdir("./tests/webpage/cgitestrun")
|
||||
shutil.copytree("testfeeds/","./tests/webpage/cgitestrun/testfeeds/")
|
||||
cgis.runServer("./tests/webpage/cgitestrun")
|
||||
self.assertEqual(True, False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user