mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2025-11-01 23:28:06 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25b565d9ba | ||
|
|
7b4ed2429d | ||
|
|
4e0fb33580 | ||
|
|
4931e757b9 | ||
|
|
3e934e8f8c | ||
|
|
118814912f | ||
|
|
4013e34899 | ||
|
|
b58cf76445 |
10
README.md
10
README.md
@@ -16,7 +16,7 @@ Know when ...
|
||||
- Realestate listing changes
|
||||
|
||||
|
||||
Get monitoring now! super simple, one command!
|
||||
**Get monitoring now! super simple, one command!**
|
||||
|
||||
```
|
||||
$ docker run -d --restart always -p "127.0.0.1:5000:5000" -v datastore-volume:/datastore dgtlmoon/changedetection.io
|
||||
@@ -25,9 +25,15 @@ $ docker run -d --restart always -p "127.0.0.1:5000:5000" -v datastore-volume:/d
|
||||
Now visit http://127.0.0.1:5000 , You should now be able to access the UI.
|
||||
|
||||
|
||||
### Screenshots
|
||||
|
||||

|
||||
Application running.
|
||||
|
||||

|
||||
|
||||
Examining differences in content.
|
||||
|
||||

|
||||
|
||||
### Future plans
|
||||
|
||||
|
||||
@@ -187,18 +187,28 @@ def diff_history_page(uuid):
|
||||
dates = list(watch['history'].keys())
|
||||
dates = [int(i) for i in dates]
|
||||
dates.sort(reverse=True)
|
||||
dates = [str(i) for i in dates]
|
||||
|
||||
|
||||
left_file_contents = right_file_contents = ""
|
||||
l_file = watch['history'][str(dates[-1])]
|
||||
with open(l_file, 'r') as f:
|
||||
left_file_contents = f.read()
|
||||
|
||||
r_file = watch['history'][str(dates[-2])]
|
||||
previous_version = request.args.get('previous_version')
|
||||
try:
|
||||
r_file = watch['history'][str(previous_version)]
|
||||
except KeyError:
|
||||
# Not present, use a default value
|
||||
r_file = watch['history'][str(dates[-2])]
|
||||
|
||||
with open(r_file, 'r') as f:
|
||||
right_file_contents = f.read()
|
||||
|
||||
#print (dates, l_file, r_file)
|
||||
output = render_template("diff.html", watch_a=watch, messages=messages, left=left_file_contents,
|
||||
right=right_file_contents, extra_stylesheets=extra_stylesheets)
|
||||
right=right_file_contents, extra_stylesheets=extra_stylesheets, versions=dates[:-1],
|
||||
current_previous_version=str(previous_version), current_diff_url=watch['url'])
|
||||
return output
|
||||
|
||||
@app.route("/favicon.ico", methods=['GET'])
|
||||
@@ -206,6 +216,20 @@ def favicon():
|
||||
return send_from_directory("/app/static/images", filename="favicon.ico")
|
||||
|
||||
|
||||
# A few self sanity checks, mostly for developer/bug check
|
||||
@app.route("/self-check", methods=['GET'])
|
||||
def selfcheck():
|
||||
output = "All fine"
|
||||
# In earlier versions before a single threaded write of the JSON store, sometimes histories could get mixed.
|
||||
# Could also maybe affect people who manually fiddle with their JSON store?
|
||||
for uuid, watch in datastore.data['watching'].items():
|
||||
for timestamp, path in watch['history'].items():
|
||||
# Each history snapshot should include a full path, which contains the {uuid}
|
||||
if not uuid in path:
|
||||
output = "Something weird in {}, suspected incorrect snapshot path.".format(uuid)
|
||||
|
||||
|
||||
return output
|
||||
@app.route("/static/<string:group>/<string:filename>", methods=['GET'])
|
||||
def static_content(group, filename):
|
||||
try:
|
||||
@@ -275,7 +299,8 @@ def api_watch_checknow():
|
||||
datastore=datastore)
|
||||
running_update_threads[uuid].start()
|
||||
|
||||
return redirect(url_for('main_page'))
|
||||
tag = request.args.get('tag')
|
||||
return redirect(url_for('main_page', tag=tag))
|
||||
|
||||
|
||||
@app.route("/api/recheckall", methods=['GET'])
|
||||
@@ -303,7 +328,7 @@ def launch_checks():
|
||||
minutes = datastore.data['settings']['requests']['minutes_between_check']
|
||||
for uuid, watch in datastore.data['watching'].items():
|
||||
|
||||
|
||||
#@Todo https://pymotw.com/2/Queue/
|
||||
if watch['last_checked'] <= time.time() - (minutes * 60):
|
||||
running_update_threads[watch['uuid']] = fetch_site_status.perform_site_check(uuid=uuid,
|
||||
datastore=datastore)
|
||||
|
||||
@@ -32,12 +32,17 @@ ins {
|
||||
}
|
||||
|
||||
#settings {
|
||||
|
||||
|
||||
line-height: 2em;
|
||||
background: rgba(0,0,0,.05);
|
||||
padding: 1em;
|
||||
border-radius: 10px;
|
||||
margin-bottom: 1em;
|
||||
color: #fff;
|
||||
font-size: 80%;
|
||||
}
|
||||
#settings label {
|
||||
margin-left: 1em;
|
||||
display: inline-block;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.source {
|
||||
@@ -53,7 +58,7 @@ ins {
|
||||
}
|
||||
|
||||
#diff-ui {
|
||||
background: #fff;
|
||||
background: #fff;
|
||||
padding: 2em;
|
||||
margin: 1em;
|
||||
border-radius: 5px;
|
||||
|
||||
@@ -77,7 +77,7 @@ section.content {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.watch-table .title-col a[target="_blank"]::after {
|
||||
.watch-table .title-col a[target="_blank"]::after, .current-diff-url::after {
|
||||
content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAQElEQVR42qXKwQkAIAxDUUdxtO6/RBQkQZvSi8I/pL4BoGw/XPkh4XigPmsUgh0626AjRsgxHTkUThsG2T/sIlzdTsp52kSS1wAAAABJRU5ErkJggg==);
|
||||
margin: 0 3px 0 5px;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
<div class="header">
|
||||
<div class="home-menu pure-menu pure-menu-horizontal pure-menu-fixed">
|
||||
<a class="pure-menu-heading" href="/"><strong>Change</strong>Detection.io</a>
|
||||
{% if current_diff_url %}
|
||||
<a class=current-diff-url href="{{ current_diff_url }}">{{ current_diff_url }}</a>
|
||||
{% endif %}
|
||||
|
||||
<ul class="pure-menu-list">
|
||||
|
||||
|
||||
@@ -2,34 +2,58 @@
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div id="diff-ui">
|
||||
<div id="settings">
|
||||
<h1>Differences</h1>
|
||||
<form class="pure-form " action="" method="GET">
|
||||
<fieldset>
|
||||
|
||||
<label for="diffWords" class="pure-checkbox">
|
||||
<input type="radio" name="diff_type" id="diffWords" value="diffWords" /> Words</label>
|
||||
<label for="diffLines" class="pure-checkbox">
|
||||
<input type="radio" name="diff_type" id="diffLines" value="diffLines" checked=""/> Lines</label>
|
||||
|
||||
<label for="diffChars" class="pure-checkbox">
|
||||
<input type="radio" name="diff_type" id="diffChars" value="diffChars"/> Chars</label>
|
||||
|
||||
{% if versions|length >= 1 %}
|
||||
<label for="diff-version">Compare newest with</label>
|
||||
<select id="diff-version" name="previous_version">
|
||||
{% for version in versions %}
|
||||
<option value="{{version}}" {% if version== current_previous_version %} selected="" {% endif %}>
|
||||
{{version}}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button type="submit" class="pure-button pure-button-primary">Go</button>
|
||||
{% endif %}
|
||||
</fieldset>
|
||||
</form>
|
||||
<del>Removed text</del>
|
||||
<ins>Inserted Text</ins>
|
||||
|
||||
<div id="settings">
|
||||
<h3>Diff</h3>
|
||||
<label><input type="radio" name="diff_type" value="diffChars"> Chars</label>
|
||||
<label><input type="radio" name="diff_type" value="diffWords" > Words</label>
|
||||
<label><input type="radio" name="diff_type" value="diffLines" checked=""> Lines</label>
|
||||
</div>
|
||||
|
||||
<div id="diff-ui">
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<!-- just proof of concept copied straight from github.com/kpdecker/jsdiff -->
|
||||
<!-- just proof of concept copied straight from github.com/kpdecker/jsdiff -->
|
||||
<td id="a" style="display: none;">{{left}}</td>
|
||||
<td id="b" style="display: none;">{{right}}</td>
|
||||
<td>
|
||||
<pre id="result"></pre>
|
||||
<span id="result"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
Diff algorithm from the amazing <a href="https://github.com/kpdecker/jsdiff" >github.com/kpdecker/jsdiff</a>
|
||||
Diff algorithm from the amazing <a href="https://github.com/kpdecker/jsdiff">github.com/kpdecker/jsdiff</a>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="/static/js/diff.js"></script>
|
||||
<script defer="">
|
||||
|
||||
|
||||
var a = document.getElementById('a');
|
||||
var b = document.getElementById('b');
|
||||
var result = document.getElementById('result');
|
||||
@@ -63,6 +87,19 @@ function changed() {
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
|
||||
|
||||
/* Convert what is options from UTC time.time() to local browser time */
|
||||
var diffList=document.getElementById("diff-version");
|
||||
if (typeof(diffList) != 'undefined' && diffList != null) {
|
||||
for (var option of diffList.options) {
|
||||
//alert(option.value);
|
||||
var dateObject = new Date(option.value*1000);
|
||||
option.label=dateObject.toLocaleString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onDiffTypeChange(document.querySelector('#settings [name="diff_type"]:checked'));
|
||||
changed();
|
||||
};
|
||||
@@ -89,10 +126,11 @@ for (var i = 0; i < radio.length; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -55,7 +55,7 @@
|
||||
</td>
|
||||
<td>{{watch|format_last_checked_time}}</td>
|
||||
<td>{{watch.last_changed|format_timestamp_timeago}}</td>
|
||||
<td><a href="/api/checknow?uuid={{ watch.uuid}}" class="pure-button button-small pure-button-primary">Recheck</a>
|
||||
<td><a href="/api/checknow?uuid={{ watch.uuid}}{% if request.args.get('tag') %}&tag={{request.args.get('tag')}}{% endif %}" class="pure-button button-small pure-button-primary">Recheck</a>
|
||||
<a href="/edit?uuid={{ watch.uuid}}" class="pure-button button-small pure-button-primary">Edit</a>
|
||||
{% if watch.history|length >= 2 %}
|
||||
<a href="/diff/{{ watch.uuid}}" class="pure-button button-small pure-button-primary">Diff</a>
|
||||
|
||||
BIN
screenshot-diff.png
Normal file
BIN
screenshot-diff.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
Reference in New Issue
Block a user