kopia lustrzana https://github.com/dgtlmoon/changedetection.io
Issue #7 - RSS feeds
rodzic
e3e36b3cef
commit
a82e9243a6
|
@ -23,6 +23,11 @@ import queue
|
||||||
|
|
||||||
from flask import Flask, render_template, request, send_file, send_from_directory, abort, redirect, url_for
|
from flask import Flask, render_template, request, send_file, send_from_directory, abort, redirect, url_for
|
||||||
|
|
||||||
|
from feedgen.feed import FeedGenerator
|
||||||
|
from flask import make_response
|
||||||
|
import datetime
|
||||||
|
import pytz
|
||||||
|
|
||||||
datastore = None
|
datastore = None
|
||||||
|
|
||||||
# Local
|
# Local
|
||||||
|
@ -112,14 +117,41 @@ def changedetection_app(config=None, datastore_o=None):
|
||||||
sorted_watches.sort(key=lambda x: x['last_changed'], reverse=True)
|
sorted_watches.sort(key=lambda x: x['last_changed'], reverse=True)
|
||||||
|
|
||||||
existing_tags = datastore.get_all_tags()
|
existing_tags = datastore.get_all_tags()
|
||||||
output = render_template("watch-overview.html",
|
rss = request.args.get('rss')
|
||||||
watches=sorted_watches,
|
|
||||||
messages=messages,
|
if rss:
|
||||||
tags=existing_tags,
|
fg = FeedGenerator()
|
||||||
active_tag=limit_tag)
|
fg.title('changedetection.io')
|
||||||
|
fg.description('Feed description')
|
||||||
|
fg.link(href='https://changedetection.io')
|
||||||
|
|
||||||
|
for watch in sorted_watches:
|
||||||
|
if watch['unviewed']:
|
||||||
|
fe = fg.add_entry()
|
||||||
|
fe.title(watch['url'])
|
||||||
|
fe.link(href=watch['url'])
|
||||||
|
fe.description(watch['url'])
|
||||||
|
fe.guid(watch['uuid'], permalink=False)
|
||||||
|
dt = datetime.datetime.fromtimestamp(int(watch['newest_history_key']))
|
||||||
|
dt = dt.replace(tzinfo=pytz.UTC)
|
||||||
|
fe.pubDate(dt)
|
||||||
|
|
||||||
|
response = make_response(fg.rss_str())
|
||||||
|
response.headers.set('Content-Type', 'application/rss+xml')
|
||||||
|
return response
|
||||||
|
|
||||||
|
else:
|
||||||
|
output = render_template("watch-overview.html",
|
||||||
|
watches=sorted_watches,
|
||||||
|
messages=messages,
|
||||||
|
tags=existing_tags,
|
||||||
|
active_tag=limit_tag,
|
||||||
|
has_unviewed=datastore.data['has_unviewed'])
|
||||||
|
|
||||||
|
# Show messages but once.
|
||||||
|
messages = []
|
||||||
|
|
||||||
|
|
||||||
# Show messages but once.
|
|
||||||
messages = []
|
|
||||||
return output
|
return output
|
||||||
|
|
||||||
@app.route("/scrub", methods=['GET', 'POST'])
|
@app.route("/scrub", methods=['GET', 'POST'])
|
||||||
|
@ -296,6 +328,17 @@ def changedetection_app(config=None, datastore_o=None):
|
||||||
messages = []
|
messages = []
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
# Clear all statuses, so we do not see the 'unviewed' class
|
||||||
|
@app.route("/api/mark-all-viewed", methods=['GET'])
|
||||||
|
def mark_all_viewed():
|
||||||
|
|
||||||
|
# Save the current newest history as the most recently viewed
|
||||||
|
for watch_uuid, watch in datastore.data['watching'].items():
|
||||||
|
datastore.set_last_viewed(watch_uuid, watch['newest_history_key'])
|
||||||
|
|
||||||
|
messages.append({'class': 'ok', 'message': "Cleared all statuses."})
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
@app.route("/diff/<string:uuid>", methods=['GET'])
|
@app.route("/diff/<string:uuid>", methods=['GET'])
|
||||||
def diff_history_page(uuid):
|
def diff_history_page(uuid):
|
||||||
global messages
|
global messages
|
||||||
|
|
|
@ -88,11 +88,16 @@ section.content {
|
||||||
margin: 0 3px 0 5px;
|
margin: 0 3px 0 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#check-all-button {
|
#post-list-buttons {
|
||||||
text-align:right;
|
text-align: right;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
#post-list-buttons li {
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#check-all-button a {
|
#post-list-buttons a {
|
||||||
border-top-left-radius: initial;
|
border-top-left-radius: initial;
|
||||||
border-top-right-radius: initial;
|
border-top-right-radius: initial;
|
||||||
border-bottom-left-radius: 5px;
|
border-bottom-left-radius: 5px;
|
||||||
|
|
|
@ -120,7 +120,7 @@ class ChangeDetectionStore:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def set_last_viewed(self, uuid, timestamp):
|
def set_last_viewed(self, uuid, timestamp):
|
||||||
self.data['watching'][uuid].update({'last_viewed': str(timestamp)})
|
self.data['watching'][uuid].update({'last_viewed': int(timestamp)})
|
||||||
self.needs_write = True
|
self.needs_write = True
|
||||||
|
|
||||||
def update_watch(self, uuid, update_obj):
|
def update_watch(self, uuid, update_obj):
|
||||||
|
@ -141,6 +141,20 @@ class ChangeDetectionStore:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def data(self):
|
def data(self):
|
||||||
|
|
||||||
|
has_unviewed = False
|
||||||
|
|
||||||
|
for uuid, v in self.__data['watching'].items():
|
||||||
|
self.__data['watching'][uuid]['newest_history_key'] = self.get_newest_history_key(uuid)
|
||||||
|
if int(v['newest_history_key']) <= int(v['last_viewed']):
|
||||||
|
self.__data['watching'][uuid]['viewed'] = True
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.__data['watching'][uuid]['viewed'] = False
|
||||||
|
has_unviewed = True
|
||||||
|
|
||||||
|
self.__data['has_unviewed'] = has_unviewed
|
||||||
|
|
||||||
return self.__data
|
return self.__data
|
||||||
|
|
||||||
def get_all_tags(self):
|
def get_all_tags(self):
|
||||||
|
|
|
@ -43,8 +43,7 @@
|
||||||
<tr id="{{ watch.uuid }}"
|
<tr id="{{ watch.uuid }}"
|
||||||
class="{{ loop.cycle('pure-table-odd', 'pure-table-even') }}
|
class="{{ loop.cycle('pure-table-odd', 'pure-table-even') }}
|
||||||
{% if watch.last_error is defined and watch.last_error != False %}error{% endif %}
|
{% if watch.last_error is defined and watch.last_error != False %}error{% endif %}
|
||||||
{% if watch.newest_history_key| int > watch.last_viewed| int %}unviewed{% endif %}
|
{% if watch.newest_history_key| int > watch.last_viewed| int %}unviewed{% endif %}">
|
||||||
">
|
|
||||||
<td>{{ loop.index }}</td>
|
<td>{{ loop.index }}</td>
|
||||||
<td class="title-col">{{watch.title if watch.title is not none else watch.url}}
|
<td class="title-col">{{watch.title if watch.title is not none else watch.url}}
|
||||||
<a class="external" target=_blank href="{{ watch.url }}"></a>
|
<a class="external" target=_blank href="{{ watch.url }}"></a>
|
||||||
|
@ -76,11 +75,17 @@
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div id="check-all-button">
|
<ul id="post-list-buttons">
|
||||||
|
{% if has_unviewed %}
|
||||||
<a href="/api/checknow{% if active_tag%}?tag={{active_tag}}{%endif%}" class="pure-button button-tag ">Recheck
|
<li>
|
||||||
|
<a href="/api/mark-all-viewed" class="pure-button button-tag ">Mark all viewed</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
<li>
|
||||||
|
<a href="/api/checknow{% if active_tag%}?tag={{active_tag}}{%endif%}" class="pure-button button-tag ">Recheck
|
||||||
all {% if active_tag%}in "{{active_tag}}"{%endif%}</a>
|
all {% if active_tag%}in "{{active_tag}}"{%endif%}</a>
|
||||||
</div>
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
Ładowanie…
Reference in New Issue