1 # -*- coding: utf-8 -*-
3 # This file is part of my.gpodder.org.
5 # my.gpodder.org is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU Affero General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or (at your
8 # option) any later version.
10 # my.gpodder.org is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
13 # License for more details.
15 # You should have received a copy of the GNU Affero General Public License
16 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
19 """OPML importer and exporter (based on gPodder's "opml" module)
21 This module contains helper classes to import subscriptions from OPML files on
22 the web and to export a list of podcast objects to valid OPML 1.1 files.
27 import xml
.dom
.minidom
31 class Importer(object):
32 VALID_TYPES
= ('rss', 'link')
34 def __init__(self
, content
):
36 Parses the OPML feed from the given URL into a local data structure
37 containing podcast metadata.
40 doc
= xml
.dom
.minidom
.parseString(content
)
42 for outline
in doc
.getElementsByTagName('outline'):
43 if outline
.getAttribute('type') in self
.VALID_TYPES
and \
44 outline
.getAttribute('xmlUrl') or \
45 outline
.getAttribute('url'):
47 'url': outline
.getAttribute('xmlUrl') or \
48 outline
.getAttribute('url'),
49 'title': outline
.getAttribute('title') or \
50 outline
.getAttribute('text') or \
51 outline
.getAttribute('xmlUrl') or \
52 outline
.getAttribute('url'),
53 'description': outline
.getAttribute('text') or \
54 outline
.getAttribute('xmlUrl') or \
55 outline
.getAttribute('url'),
58 if channel
['description'] == channel
['title']:
59 channel
['description'] = channel
['url']
61 for attr
in ('url', 'title', 'description'):
62 channel
[attr
] = channel
[attr
].strip()
64 self
.items
.append(channel
)
67 class Exporter(object):
69 Helper class to export a list of channel objects to a local file in OPML
70 1.1 format. See www.opml.org for the OPML specification.
73 def __init__(self
, title
='my.gpodder.org Subscriptions'):
75 self
.created
= email
.Utils
.formatdate(localtime
=True)
77 def generate(self
, channels
):
79 Creates a XML document containing metadata for each channel object in
80 the "channels" parameter, which should be a list of channel objects.
82 Returns: An OPML document as string
84 doc
= xml
.dom
.minidom
.Document()
86 opml
= doc
.createElement('opml')
87 opml
.setAttribute('version', '2.0')
90 def create_node(name
, content
):
91 node
= doc
.createElement(name
)
92 node
.appendChild(doc
.createTextNode(content
))
95 head
= doc
.createElement('head')
96 head
.appendChild(create_node('title', self
.title
or ''))
97 head
.appendChild(create_node('dateCreated', self
.created
))
98 opml
.appendChild(head
)
100 def create_outline(channel
):
101 outline
= doc
.createElement('outline')
102 outline
.setAttribute('title', channel
.title
or '')
103 outline
.setAttribute('text', channel
.description
or '')
104 outline
.setAttribute('xmlUrl', channel
.url
)
105 outline
.setAttribute('type', 'rss')
108 body
= doc
.createElement('body')
109 for channel
in channels
:
110 body
.appendChild(create_outline(channel
))
111 opml
.appendChild(body
)
113 return doc
.toprettyxml(encoding
='utf-8', \