|
a/ForgeBlog/forgeblog/command/rssfeeds.py |
|
b/ForgeBlog/forgeblog/command/rssfeeds.py |
|
... |
|
... |
54 |
self.custom_tag_opened = False
|
54 |
self.custom_tag_opened = False
|
55 |
|
55 |
|
56 |
self.result_doc = u"%s</%s>" % (self.result_doc, tag)
|
56 |
self.result_doc = u"%s</%s>" % (self.result_doc, tag)
|
57 |
|
57 |
|
58 |
def handle_data(self, data):
|
58 |
def handle_data(self, data):
|
59 |
if len(data.split()) == 0:
|
|
|
60 |
self.result_doc = u"%s%s" % (self.result_doc, data)
|
|
|
61 |
return
|
|
|
62 |
|
|
|
63 |
res_data = ""
|
59 |
res_data = ''
|
|
|
60 |
|
64 |
for line in data.split('\n'):
|
61 |
for line in data.splitlines(True):
|
|
|
62 |
# pre-emptive special case
|
|
|
63 |
if not line or line.isspace():
|
|
|
64 |
# don't wrap all whitespace lines
|
|
|
65 |
res_data += line
|
|
|
66 |
continue
|
|
|
67 |
|
|
|
68 |
# open custom tag
|
65 |
if self.custom_tag_opened:
|
69 |
if not self.custom_tag_opened:
|
66 |
res_data = u"%s%s" % (res_data, self.CUSTTAG_CLOSE)
|
70 |
res_data += self.CUSTTAG_OPEN
|
|
|
71 |
self.custom_tag_opened = True
|
|
|
72 |
# else: cust tag might be open already from previous incomplete data block
|
|
|
73 |
|
|
|
74 |
# data
|
|
|
75 |
res_data += line.rstrip('\r\n') # strip EOL (add close tag before)
|
|
|
76 |
|
|
|
77 |
# close custom tag
|
|
|
78 |
if line.endswith(('\r','\n')):
|
|
|
79 |
res_data += self.CUSTTAG_CLOSE + '\n'
|
67 |
self.custom_tag_opened = False
|
80 |
self.custom_tag_opened = False
|
|
|
81 |
# else: no EOL could mean we're dealing with incomplete data block;
|
|
|
82 |
# leave it open for next handle_data, handle_starttag, or handle_endtag to clean up
|
68 |
|
83 |
|
69 |
if len(line.split()) > 0:
|
84 |
self.result_doc += res_data
|
70 |
res_data = u"%s\n%s%s" % (res_data, self.CUSTTAG_OPEN, line)
|
|
|
71 |
self.custom_tag_opened = True
|
|
|
72 |
else:
|
|
|
73 |
res_data = u"%s\n" % res_data
|
|
|
74 |
|
|
|
75 |
if data[-1:] == "\n" and self.custom_tag_opened:
|
|
|
76 |
res_data = u"%s%s" % (res_data, self.CUSTTAG_CLOSE)
|
|
|
77 |
self.custom_tag_opened = False
|
|
|
78 |
|
|
|
79 |
self.result_doc = u"%s%s" % (self.result_doc, res_data)
|
|
|
80 |
|
85 |
|
81 |
def handle_comment(self, data):
|
86 |
def handle_comment(self, data):
|
82 |
if self.custom_tag_opened:
|
87 |
if self.custom_tag_opened:
|
83 |
self.result_doc = u"%s%s" % (self.result_doc, self.CUSTTAG_CLOSE)
|
88 |
self.result_doc = u"%s%s" % (self.result_doc, self.CUSTTAG_CLOSE)
|
84 |
self.custom_tag_opened = False
|
89 |
self.custom_tag_opened = False
|
|
... |
|
... |
114 |
self.custom_tag_opened = False
|
119 |
self.custom_tag_opened = False
|
115 |
|
120 |
|
116 |
|
121 |
|
117 |
class RssFeedsCommand(base.BlogCommand):
|
122 |
class RssFeedsCommand(base.BlogCommand):
|
118 |
summary = 'Rss feed client'
|
123 |
summary = 'Rss feed client'
|
119 |
parser = base.Command.standard_parser(verbose=True)
|
124 |
parser = base.BlogCommand.standard_parser(verbose=True)
|
120 |
parser.add_option('-a', '--appid', dest='appid', default='',
|
125 |
parser.add_option('-a', '--appid', dest='appid', default='',
|
121 |
help='application id')
|
126 |
help='application id')
|
122 |
parser.add_option('-u', '--username', dest='username', default='root',
|
127 |
parser.add_option('-u', '--username', dest='username', default='root',
|
123 |
help='poster username')
|
128 |
help='poster username')
|
124 |
|
129 |
|
|
... |
|
... |
158 |
c.app = app
|
163 |
c.app = app
|
159 |
|
164 |
|
160 |
allura_base.log.info("Get feed: %s" % feed_url)
|
165 |
allura_base.log.info("Get feed: %s" % feed_url)
|
161 |
f = feedparser.parse(feed_url)
|
166 |
f = feedparser.parse(feed_url)
|
162 |
if f.bozo:
|
167 |
if f.bozo:
|
163 |
base.log.exception("%s: %s" % (feed_url, f.bozo_exception))
|
168 |
allura_base.log.exception("%s: %s" % (feed_url, f.bozo_exception))
|
164 |
return
|
169 |
return
|
165 |
for e in f.entries:
|
170 |
for e in f.entries:
|
166 |
title = e.title
|
171 |
title = e.title
|
167 |
if 'content' in e:
|
172 |
if 'content' in e:
|
168 |
content = u''
|
173 |
content = u''
|
169 |
for ct in e.content:
|
174 |
for ct in e.content:
|
170 |
if ct.type != 'text/html':
|
175 |
if ct.type != 'text/html':
|
171 |
content += '[plain]%s[/plain]' % ct.value
|
176 |
content += '[plain]%s[/plain]' % ct.value
|
172 |
else:
|
177 |
else:
|
173 |
if False:
|
|
|
174 |
# FIXME: disabled until https://sourceforge.net/p/allura/tickets/4345
|
|
|
175 |
# because the bad formatting from [plain] is worse than bad formatting from unintentional markdown syntax
|
|
|
176 |
parser = MDHTMLParser()
|
178 |
parser = MDHTMLParser()
|
177 |
parser.feed(ct.value)
|
179 |
parser.feed(ct.value)
|
178 |
parser.close() # must be before using the result_doc
|
180 |
parser.close() # must be before using the result_doc
|
179 |
markdown_content = html2text.html2text(parser.result_doc, baseurl=e.link)
|
181 |
markdown_content = html2text.html2text(parser.result_doc, baseurl=e.link)
|
180 |
else:
|
|
|
181 |
markdown_content = html2text.html2text(ct.value, baseurl=e.link)
|
|
|
182 |
|
182 |
|
183 |
content += markdown_content
|
183 |
content += markdown_content
|
184 |
else:
|
184 |
else:
|
185 |
content = '[plain]%s[/plain]' % getattr(e, 'summary',
|
185 |
content = '[plain]%s[/plain]' % getattr(e, 'summary',
|
186 |
getattr(e, 'subtitle',
|
186 |
getattr(e, 'subtitle',
|