Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ecc71972e2 | |||
|
|
b31d8f3fcc | ||
|
|
eaefe02988 | ||
|
|
a3b27e1dea | ||
|
|
32fd101e5a | ||
|
|
9abe918906 | ||
|
|
900084f493 | ||
|
|
f5d66e8c0b | ||
| 63841a2ba0 | |||
| 0d17739bbd | |||
| 94fd726873 | |||
| d4e2319045 | |||
| 0e0222d645 | |||
| 9f3ab3cb38 | |||
| d7dcf943f5 | |||
|
|
3bfdd126ba | ||
|
|
a36d735ec2 | ||
|
|
56b84fea08 | ||
|
|
e76ab4c74b | ||
|
|
4c7fdaf66a | ||
|
|
d493b02326 | ||
|
|
15e3c13609 | ||
|
|
cafdd3d094 | ||
|
|
024ff141f6 | ||
|
|
cedb173b63 | ||
|
|
feb4408f2b | ||
|
|
8b40ae1cab | ||
|
|
b5dbe40365 |
117
Feed.py
117
Feed.py
@@ -1,117 +0,0 @@
|
|||||||
import opml
|
|
||||||
import feedparser as fp
|
|
||||||
import database as db
|
|
||||||
|
|
||||||
|
|
||||||
def feedImport (userID):
|
|
||||||
outline = opml.parse("podcast_republic_podcasts.opml")
|
|
||||||
#get the number of shows from the OPML file
|
|
||||||
x = len(outline)
|
|
||||||
y=0
|
|
||||||
|
|
||||||
#loops through each podcast and parses out relevant information
|
|
||||||
while y < x:
|
|
||||||
title = outline[y].title
|
|
||||||
url = outline[y].xmlUrl
|
|
||||||
artwork = outline[y].pr_artwork
|
|
||||||
desc = outline[y].pr_desc
|
|
||||||
|
|
||||||
#checks to see if the podcast URL already exists for logged in user and skips it if it has already been imported.
|
|
||||||
query = db.sql.text("""select URL from Podcasts where URL = \"%s\" and userID = %i""" % (url, userID))
|
|
||||||
exists = db.con.execute(query).fetchone()
|
|
||||||
#if the show doesn't already exist for the logged in user it gets added
|
|
||||||
if exists is None or exists[0] != url:
|
|
||||||
query = db.sql.text("""insert into Podcasts (userID, title, URL, artworkURL) values(%i, \"%s\", \"%s\", \"%s\") """ % (userID, title, url, artwork))
|
|
||||||
db.con.execute(query)
|
|
||||||
print("%s added" % title)
|
|
||||||
else:
|
|
||||||
print("%s already exists" % title)
|
|
||||||
y=y+1
|
|
||||||
|
|
||||||
def updateFeeds(userID):
|
|
||||||
showCheck = []
|
|
||||||
#grabs podcast urls from logged in user
|
|
||||||
query = db.sql.text("""select URL, podcastID, title from Podcasts where userID = %i""" % userID)
|
|
||||||
shows = db.con.execute(query).fetchall()
|
|
||||||
|
|
||||||
#loops through the returned urls and parses each rss feed
|
|
||||||
y=0
|
|
||||||
for x in shows:
|
|
||||||
#Here we're grabbing all the show urls for each podcast and moving them into a separate array.
|
|
||||||
query = db.sql.text("""select link from Shows where userID = %i and podcastID = %i""" % (userID, shows[y][1]))
|
|
||||||
showGrab = db.con.execute(query).fetchall()
|
|
||||||
z=0
|
|
||||||
for each in showGrab:
|
|
||||||
showCheck.append(showGrab[z][0])
|
|
||||||
z=z+1
|
|
||||||
|
|
||||||
parsed = fp.parse(shows[y][0])
|
|
||||||
count = 0
|
|
||||||
for items in parsed['entries']:
|
|
||||||
url = parsed.entries[count].enclosures[0].get('href')
|
|
||||||
#after parsing out the show URL we check if it already exists by comparing it against the showCheck array containing all show URLs
|
|
||||||
if url not in showCheck:
|
|
||||||
query = db.sql.text("""insert into Shows (podcastID, userID, link) values (%i, %i, \"%s\")""" % (shows[y][1], userID, url))
|
|
||||||
db.con.execute(query)
|
|
||||||
print("%s has a new show" % shows[y][2])
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
count = count + 1
|
|
||||||
y=y+1
|
|
||||||
showCheck = [] #Clear out the array for the next podcast
|
|
||||||
|
|
||||||
|
|
||||||
def addFeed(userID):
|
|
||||||
newURL = input("Enter Feed URL: ")
|
|
||||||
count = 0
|
|
||||||
|
|
||||||
parsed = fp.parse(newURL)
|
|
||||||
|
|
||||||
title = parsed.feed.title
|
|
||||||
artwork = parsed.feed.image
|
|
||||||
|
|
||||||
# checks to see if the podcast URL already exists for logged in user and skips it if it has already been imported.
|
|
||||||
query = db.sql.text("""select URL from Podcasts where URL = \"%s\" and userID = %i""" % (newURL, userID))
|
|
||||||
exists = db.con.execute(query).fetchone()
|
|
||||||
# if the show doesn't already exist for the logged in user it gets added
|
|
||||||
if exists is None or exists[0] != newURL:
|
|
||||||
query = db.sql.text("""insert into Podcasts (userID, title, URL, artworkURL) values(%i, \"%s\", \"%s\", \"%s\") """ % (userID, title, newURL, artwork))
|
|
||||||
db.con.execute(query)
|
|
||||||
print("%s added" % title)
|
|
||||||
# Once the podcast is added we grab the podcastID so we can import the shows
|
|
||||||
query = db.sql.text("""select podcastID from Podcasts where userID = %i and URL = \"%s\"""" % (userID, newURL))
|
|
||||||
result = db.con.execute(query).fetchone()
|
|
||||||
podcastID = result[0]
|
|
||||||
|
|
||||||
# Import the new shows. No need to check if the show URLS already exist since it's new
|
|
||||||
for items in parsed['entries']:
|
|
||||||
itemURL = parsed.entries[count].enclosures[0].get('href')
|
|
||||||
query = db.sql.text("""insert into Shows (podcastID, userID, link) values (%i, %i, \"%s\")""" % (podcastID, userID, itemURL))
|
|
||||||
db.con.execute(query)
|
|
||||||
count = count + 1
|
|
||||||
else:
|
|
||||||
print("%s already exists" % title)
|
|
||||||
|
|
||||||
def deleteFeed(userID):
|
|
||||||
podcasts=[]
|
|
||||||
y=0
|
|
||||||
# grabs podcast urls from logged in user
|
|
||||||
query = db.sql.text("""select podcastID, title from Podcasts where userID = %i""" % userID)
|
|
||||||
results = db.con.execute(query).fetchall()
|
|
||||||
|
|
||||||
for each in results:
|
|
||||||
print("%i. %s" % (y+1, results[y][1]))
|
|
||||||
y=y+1
|
|
||||||
val = input("Delete which podcast? ")
|
|
||||||
|
|
||||||
deletedID = results[val-1][1]
|
|
||||||
print(deletedID)
|
|
||||||
|
|
||||||
query = db.sql.text("""delete * from Podcasts where podcastID = %i and userID = %i""" % (deletedID, userID))
|
|
||||||
db.con.execute(query)
|
|
||||||
|
|
||||||
query = db.sql.text("""delete * from Shows where podcastID = %i and userID = %i""" % (deletedID, userID))
|
|
||||||
db.con.execute(query)
|
|
||||||
|
|
||||||
print("%s has been deleted" % results[val][0])
|
|
||||||
|
|
||||||
4
captain-definition
Normal file
4
captain-definition
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"dockerfilePath": "./docker"
|
||||||
|
}
|
||||||
10
database.py
10
database.py
@@ -1,10 +0,0 @@
|
|||||||
import sqlalchemy as sql
|
|
||||||
|
|
||||||
db_URI = 'mysql+pymysql://pc:pc@192.168.86.198/Podcast'
|
|
||||||
# db_URI = 'mysql+pymysql://pc:pc@dandembinski.duckdns.org:80/Podcast'
|
|
||||||
|
|
||||||
engine = sql.create_engine(db_URI)
|
|
||||||
con = engine.connect()
|
|
||||||
|
|
||||||
metadata = sql.MetaData()
|
|
||||||
|
|
||||||
9
docker
Normal file
9
docker
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
FROM python:3
|
||||||
|
ADD main.py /
|
||||||
|
ADD requirements.txt /
|
||||||
|
|
||||||
|
|
||||||
|
RUN pip install -r ./requirements.txt
|
||||||
|
|
||||||
|
|
||||||
|
CMD ["python", "./main.py"]
|
||||||
27
helper.py
Normal file
27
helper.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import opml
|
||||||
|
import requests
|
||||||
|
|
||||||
|
API_URL = '''http://podcast-api.caprover.dandev.us'''
|
||||||
|
|
||||||
|
def feedImport ():
|
||||||
|
# outline = opml.parse("podcast_republic_podcasts.opml")
|
||||||
|
outline = opml.parse("test.opml")
|
||||||
|
#get the number of shows from the OPML file
|
||||||
|
x = len(outline)
|
||||||
|
y=0
|
||||||
|
|
||||||
|
#loops through each podcast and parses out relevant information
|
||||||
|
while y < x:
|
||||||
|
title = outline[y].title
|
||||||
|
url = outline[y].xmlUrl
|
||||||
|
artwork = outline[y].pr_artwork
|
||||||
|
desc = outline[y].pr_desc
|
||||||
|
|
||||||
|
#checks to see if the podcast URL already exists for logged in user and skips it if it has already been imported.
|
||||||
|
r = requests.post(API_URL+'/addFeed/', json={"userID" : 1, "newURL" : url.href})
|
||||||
|
print(r.text)
|
||||||
|
# print(url)
|
||||||
|
|
||||||
|
y=y+1
|
||||||
|
|
||||||
|
feedImport()
|
||||||
281
main.py
281
main.py
@@ -1,46 +1,259 @@
|
|||||||
import database as db
|
import feedparser as fp
|
||||||
import Feed
|
from flask import Flask, jsonify, request
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
|
||||||
userID = None
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://pc:pc@67.149.14.121:3306/Podcast'
|
||||||
|
|
||||||
|
db = SQLAlchemy(app)
|
||||||
|
|
||||||
|
#############
|
||||||
|
# ALTER TABLE shows AUTO_INCREMENT = 1;
|
||||||
|
# ALTER TABLE podcasts AUTO_INCREMENT = 1;
|
||||||
|
# ALTER TABLE users AUTO_INCREMENT = 1;
|
||||||
|
#############
|
||||||
|
|
||||||
|
|
||||||
|
class users(db.Model):
|
||||||
|
userID = db.Column(db.Integer, primary_key=True)
|
||||||
|
username = db.Column(db.Text, unique=True)
|
||||||
|
password = db.Column(db.Text)
|
||||||
|
name = db.Column(db.Text)
|
||||||
|
email = db.Column(db.Text)
|
||||||
|
# token = db.column(db.Text)
|
||||||
|
|
||||||
|
class shows(db.Model):
|
||||||
|
showID = db.Column(db.Integer, primary_key=True)
|
||||||
|
podcastID = db.Column(db.Integer)
|
||||||
|
userID = db.Column(db.Integer)
|
||||||
|
link = db.Column(db.Text)
|
||||||
|
started = db.Column(db.Boolean, default=0)
|
||||||
|
position = db.Column(db.Text, default=0)
|
||||||
|
|
||||||
|
|
||||||
|
class podcasts(db.Model):
|
||||||
|
podcastID = db.Column(db.Integer, primary_key=True)
|
||||||
|
userID = db.Column(db.Integer)
|
||||||
|
title = db.Column(db.Text)
|
||||||
|
URL = db.Column(db.Text)
|
||||||
|
artworkURL = db.Column(db.Text, default=None)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET'])
|
||||||
|
def index():
|
||||||
|
stuff = """<b> /login </b<br>Method: 'GET' JSON: 'username', 'password'<br>
|
||||||
|
<b>/updateFeeds</b><br>Method: 'PUT', JSON:: 'podcastID' <i>note leave podcastID blank to update all feeds</i><br><br>
|
||||||
|
<b>/addFeed</b>to Come</b><br><br>
|
||||||
|
<b>/listPoddcasts/<userID><b><br><br>
|
||||||
|
|
||||||
|
"""
|
||||||
|
return 'stuff'
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/login/', methods=['GET'])
|
||||||
def login():
|
def login():
|
||||||
|
|
||||||
username = 'Dan'
|
username = 'Dan'
|
||||||
password = 'password'
|
password = 'password'
|
||||||
|
|
||||||
|
data = request.get_json()
|
||||||
|
|
||||||
query = db.sql.text(""" select userID from Users where username = \'%s\'""" % username)
|
user = users.query.filter_by(username=data['username']).first()
|
||||||
result = db.con.execute(query).fetchone()
|
|
||||||
|
|
||||||
print(result[0])
|
if data['password'] != user.password:
|
||||||
|
return jsonify(message='Login Failed')
|
||||||
|
else:
|
||||||
|
return jsonify(message='User logged in', userID=user.userID)
|
||||||
|
|
||||||
return result[0]
|
@app.route('/updateFeeds/', methods={'PUT'})
|
||||||
|
def updateFeeds():
|
||||||
|
|
||||||
|
data = request.get_json()
|
||||||
|
showCheck = []
|
||||||
|
updatedShows = []
|
||||||
|
|
||||||
|
if data['podcastID'] is None or data['podcastID'] == '':
|
||||||
|
# grabs podcast urls from logged in user
|
||||||
|
pc = podcasts.query.filter_by(userID=data['userID']).all()
|
||||||
|
|
||||||
|
# loops through the returned urls and parses each rss feed
|
||||||
|
for show in pc:
|
||||||
|
parsed = fp.parse(show.URL)
|
||||||
|
query = shows.query.filter_by(userID=data['userID'], podcastID=show.podcastID).all()
|
||||||
|
for x in query:
|
||||||
|
showCheck.append(x.link)
|
||||||
|
count = 0
|
||||||
|
for items in parsed['entries']:
|
||||||
|
url = parsed.entries[count].enclosures[0].get('href')
|
||||||
|
# after parsing out the show URL we check if it already exists by comparing it against the showCheck array containing all show URLs
|
||||||
|
if url not in showCheck:
|
||||||
|
query = shows(podcastID=show.podcastID, userID=data['userID'], link=url)
|
||||||
|
db.session.add(query)
|
||||||
|
new_show = {}
|
||||||
|
new_show['title'] = show.title
|
||||||
|
updatedShows.append(new_show)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
count = count + 1
|
||||||
|
# Clear out the array for the next podcast
|
||||||
|
showCheck = []
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify(newShows=updatedShows)
|
||||||
|
else:
|
||||||
|
pc = podcasts.query.filter_by(userID=data['userID'], podcastID=data['podcastID']).first()
|
||||||
|
parsed = fp.parse(pc.URL)
|
||||||
|
|
||||||
|
query = shows.query.filter_by(userID=data['userID'], podcastID=data['podcastID']).all()
|
||||||
|
for x in query:
|
||||||
|
showCheck.append(x.link)
|
||||||
|
count = 0
|
||||||
|
for items in parsed['entries']:
|
||||||
|
url = parsed.entries[count].enclosures[0].get('href')
|
||||||
|
# after parsing out the show URL we check if it already exists by comparing it against the showCheck array containing all show URLs
|
||||||
|
if url not in showCheck:
|
||||||
|
query = shows(podcastID=pc.podcastID, userID=data['userID'], link=url)
|
||||||
|
db.session.add(query)
|
||||||
|
db.session.commit()
|
||||||
|
new_show = {}
|
||||||
|
new_show['title'] = pc.title
|
||||||
|
updatedShows.append(new_show)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
count = count + 1
|
||||||
|
|
||||||
|
return jsonify(singleShow=updatedShows)
|
||||||
|
|
||||||
|
|
||||||
while True:
|
@app.route('/addFeed/', methods=['POST'])
|
||||||
print("1. Login\n2. Upload\n3. Update feeds\n4. Add Feed\n9. Exit\n")
|
def addFeed():
|
||||||
val = input(">>>")
|
|
||||||
if val == "1":
|
count = 0
|
||||||
userID = login()
|
data = request.get_json()
|
||||||
elif val == "2":
|
parsed = fp.parse(data['newURL'])
|
||||||
if userID is None or userID == '':
|
|
||||||
print("Please login first")
|
title = str(parsed.feed.title)
|
||||||
else:
|
if not parsed.feed.title:
|
||||||
Feed.feedImport(userID)
|
artwork = str(parsed.feed.image)
|
||||||
elif val == "3":
|
else:
|
||||||
if userID is None or userID == '':
|
artwork = ''
|
||||||
print("Please login first")
|
|
||||||
else:
|
# checks to see if the podcast URL already exists for logged in user and skips it if it has already been imported.
|
||||||
Feed.updateFeeds(userID)
|
# if the show doesn't already exist for the logged in user it gets added
|
||||||
elif val == "4":
|
if not podcasts.query.filter_by(URL=data['newURL'], userID=data['userID']).first():
|
||||||
if userID is None or userID == '':
|
query = podcasts(userID=data['userID'], title=title, URL=data['newURL'], artworkURL=artwork)
|
||||||
print("Please login first")
|
db.session.add(query)
|
||||||
else:
|
db.session.commit()
|
||||||
Feed.addFeed(userID)
|
# Once the podcast is added we grab the podcastID so we can import the shows
|
||||||
elif val == "5":
|
result = podcasts.query.filter_by(URL=data['newURL'], userID=data['userID']).first()
|
||||||
if userID is None or userID == '':
|
# Import the new shows. No need to check if the show URLS already exist since it's new
|
||||||
print("Please login first")
|
for items in parsed['entries']:
|
||||||
else:
|
itemURL = parsed.entries[count].enclosures[0].get('href')
|
||||||
Feed.deleteFeed(userID)
|
query = shows(podcastID=result.podcastID, userID=data['userID'], link=itemURL)
|
||||||
elif val == "9":
|
db.session.add(query)
|
||||||
exit()
|
count = count + 1
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify(title=title, added=1)
|
||||||
|
else:
|
||||||
|
return jsonify(title=title, added=0)
|
||||||
|
|
||||||
|
# @app.route('/importFeed/', methods=['POST'])
|
||||||
|
# def importFeed():
|
||||||
|
#
|
||||||
|
# count = 0
|
||||||
|
# data = request.get_json()
|
||||||
|
# parsed = fp.parse(data['newURL'])
|
||||||
|
#
|
||||||
|
# title = str(parsed.feed.title)
|
||||||
|
# artwork = str(parsed.feed.image)
|
||||||
|
#
|
||||||
|
# # checks to see if the podcast URL already exists for logged in user and skips it if it has already been imported.
|
||||||
|
# # if the show doesn't already exist for the logged in user it gets added
|
||||||
|
# if not podcasts.query.filter_by(URL=data['newURL'], userID=data['userID']).first():
|
||||||
|
# query = podcasts(userID=data['userID'], title=title, URL=data['newURL'], artworkURL=artwork)
|
||||||
|
# db.session.add(query)
|
||||||
|
# db.session.commit()
|
||||||
|
# # Once the podcast is added we grab the podcastID so we can import the shows
|
||||||
|
# result = podcasts.query.filter_by(URL=data['newURL'], userID=data['userID']).first()
|
||||||
|
# # Import the new shows. No need to check if the show URLS already exist since it's new
|
||||||
|
# for items in parsed['entries']:
|
||||||
|
# itemURL = parsed.entries[count].enclosures[0].get('href')
|
||||||
|
# query = shows(podcastID=result.podcastID, userID=data['userID'], link=itemURL)
|
||||||
|
# db.session.add(query)
|
||||||
|
# count = count + 1
|
||||||
|
# db.session.commit()
|
||||||
|
# return jsonify(message='Podcast added')
|
||||||
|
# else:
|
||||||
|
# return jsonify(message='Podcast already exists')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/listPodcasts/<int:userID>/', methods=['GET'])
|
||||||
|
def listPodcasts(userID):
|
||||||
|
|
||||||
|
output = []
|
||||||
|
y = 0
|
||||||
|
# grabs podcast urls from logged in user
|
||||||
|
pc = podcasts.query.filter_by(userID=userID).all()
|
||||||
|
|
||||||
|
for each in pc:
|
||||||
|
result = {}
|
||||||
|
result['podcastID'] = each.podcastID
|
||||||
|
result['Title'] = each.title
|
||||||
|
output.append(result)
|
||||||
|
|
||||||
|
return jsonify(shows=output)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/register/', methods=['POST'])
|
||||||
|
def register():
|
||||||
|
|
||||||
|
data = request.get_json()
|
||||||
|
|
||||||
|
# checks to see if the username already exists
|
||||||
|
if not users.query.filter_by(username=data['username']).first():
|
||||||
|
new_user = users(username=data['username'], password=data['password'], name=data['name'], email=data['email'])
|
||||||
|
db.session.add(new_user)
|
||||||
|
db.session.commit()
|
||||||
|
# Returns the new userID
|
||||||
|
newID = users.query.filter_by(username=data['username']).first()
|
||||||
|
return jsonify(userid=newID.userID)
|
||||||
|
# if the username doesn't already exist it will be added
|
||||||
|
else:
|
||||||
|
return jsonify(message='Username already exists')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/updateStatus/<int:userID>/<int:podcastID>/<int:status>')
|
||||||
|
def updateStatus(userID, podcastID, status):
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/updateTime/<int:userID>/<int:podcastID>/<int:time>')
|
||||||
|
def updateTime(userID, podcastID,time):
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/deleteUser/<int:userID>/', methods=['DELETE'])
|
||||||
|
def deleteUser(userID):
|
||||||
|
|
||||||
|
users.query.filter_by(userID=userID).delete()
|
||||||
|
podcasts.query.filter_by(userID=userID).delete()
|
||||||
|
shows.query.filter_by(userID=userID).delete()
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return jsonify(message="User deleted")
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/removeFeed/')
|
||||||
|
def removeFeed():
|
||||||
|
|
||||||
|
data = request.get_json()
|
||||||
|
|
||||||
|
podcasts.query.filter_by(userID=data['userID'], podcastID=data['podcastID']).delete()
|
||||||
|
shows.query.filter_by(userID=data['userID'], podcastID=data['podcastID']).delete()
|
||||||
|
|
||||||
|
return jsonify(message='Show delete')
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host='0.0.0.0', debug=True)
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,12 @@
|
|||||||
|
Click==7.0
|
||||||
feedparser==5.2.1
|
feedparser==5.2.1
|
||||||
|
Flask==1.1.1
|
||||||
|
Flask-SQLAlchemy==2.4.1
|
||||||
|
itsdangerous==1.1.0
|
||||||
|
Jinja2==2.11.1
|
||||||
lxml==4.5.0
|
lxml==4.5.0
|
||||||
|
MarkupSafe==1.1.1
|
||||||
opml==0.5
|
opml==0.5
|
||||||
PyMySQL==0.9.3
|
PyMySQL==0.9.3
|
||||||
SQLAlchemy==1.3.13
|
SQLAlchemy==1.3.13
|
||||||
|
Werkzeug==1.0.0
|
||||||
|
|||||||
5
test.opml
Normal file
5
test.opml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8' standalone='no' ?><opml version="1.0"><head><title>Podcast Republic Subscribed Feeds</title></head><body>
|
||||||
|
|
||||||
|
<outline text="Mountain Radio Astronomy" title="Mountain Radio Astronomy" type="rss" xmlUrl="http://www.gb.nrao.edu/epo/mra.xml" pr_Id="153540555" pr_artwork="https://is4-ssl.mzstatic.com/image/thumb/Features/v4/5f/88/96/5f8896e9-9be5-529a-af14-cc807367568a/mza_1382744875394257421.png/60x60bb.jpg" pr_artwork_large="https://is4-ssl.mzstatic.com/image/thumb/Features/v4/5f/88/96/5f8896e9-9be5-529a-af14-cc807367568a/mza_1382744875394257421.png/600x600bb.jpg" pr_desc="Ever wonder about radio astronomy? Join us at the National Radio Astronomy Observatory in Green Bank, WV for fascinating interviews with astronomers who are using the largest fully steerable telescope in the world: The Robert C. Byrd Green Bank Telelscope. Each episode is about 20-30 minutes in length." pr_au="0" meidaType="0" PodSourceType="0" PodUniqueCriteria="0" playbackSpeed="1.0" />
|
||||||
|
|
||||||
|
</body></opml>
|
||||||
Reference in New Issue
Block a user