commit
ec3f34804f
@ -0,0 +1,3 @@
|
|||||||
|
__pycache__
|
||||||
|
.idea
|
||||||
|
*.pyc
|
@ -0,0 +1,73 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import json
|
||||||
|
import eventlet
|
||||||
|
import eventlet.wsgi
|
||||||
|
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import getopt
|
||||||
|
import sys
|
||||||
|
import datetime
|
||||||
|
from flask import Flask, render_template, request, send_file, send_from_directory, safe_join, abort
|
||||||
|
|
||||||
|
# Local
|
||||||
|
import store
|
||||||
|
from nocache import nocache
|
||||||
|
|
||||||
|
datastore = store.ChangeDetectionStore()
|
||||||
|
|
||||||
|
app = Flask(__name__, static_url_path='/static')
|
||||||
|
app.config['STATIC_RESOURCES'] = "/app/static"
|
||||||
|
|
||||||
|
# app.config['SECRET_KEY'] = 'secret!'
|
||||||
|
|
||||||
|
# Disables caching of the templates
|
||||||
|
app.config['TEMPLATES_AUTO_RELOAD'] = True
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/", methods=['GET'])
|
||||||
|
@nocache
|
||||||
|
def main_page():
|
||||||
|
return render_template("watch-overview.html", watches=datastore.data['watching'])
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/static/<string:group>/<string:filename>", methods=['GET'])
|
||||||
|
@nocache
|
||||||
|
def static_content(group, filename):
|
||||||
|
try:
|
||||||
|
return send_from_directory("/app/static/{}".format(group), filename=filename)
|
||||||
|
except FileNotFoundError:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
ssl_mode = False
|
||||||
|
port = 5000
|
||||||
|
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(argv, "sp:")
|
||||||
|
except getopt.GetoptError:
|
||||||
|
print('backend.py -s SSL enable -p [port]')
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt == '-s':
|
||||||
|
ssl_mode = True
|
||||||
|
|
||||||
|
if opt == '-p':
|
||||||
|
port = arg
|
||||||
|
|
||||||
|
# @todo finalise SSL config, but this should get you in the right direction if you need it.
|
||||||
|
if ssl_mode:
|
||||||
|
eventlet.wsgi.server(eventlet.wrap_ssl(eventlet.listen(('', port)),
|
||||||
|
certfile='cert.pem',
|
||||||
|
keyfile='privkey.pem',
|
||||||
|
server_side=True), app)
|
||||||
|
|
||||||
|
else:
|
||||||
|
eventlet.wsgi.server(eventlet.listen(('', port)), app)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main(sys.argv[1:])
|
@ -0,0 +1,7 @@
|
|||||||
|
FROM python:3.8-buster
|
||||||
|
RUN mkdir -p /app/dev
|
||||||
|
COPY sleep.py /
|
||||||
|
CMD [ "python", "/sleep.py" ]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
docker stop tss-node
|
||||||
|
docker rm tss-node
|
||||||
|
docker build -t tss-node .
|
||||||
|
|
@ -0,0 +1,18 @@
|
|||||||
|
aiohttp==1.3.1
|
||||||
|
async-timeout==1.1.0
|
||||||
|
chardet==2.3.0
|
||||||
|
multidict==2.1.4
|
||||||
|
python-engineio
|
||||||
|
python_socketio==1.8.4
|
||||||
|
six==1.10.0
|
||||||
|
yarl==0.9.2
|
||||||
|
eventlet==0.19.0
|
||||||
|
flask
|
||||||
|
|
||||||
|
# Actual connecting to services
|
||||||
|
pytz
|
||||||
|
phpserialize==1.3.0
|
||||||
|
redis>=2.6.2
|
||||||
|
pymysql==0.8
|
||||||
|
bleach==1.5.0
|
||||||
|
html5lib==0.9999999 # via bleach
|
@ -0,0 +1,9 @@
|
|||||||
|
import time
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# Wait for 5 seconds
|
||||||
|
print('To stderr.', file=sys.stderr)
|
||||||
|
|
||||||
|
time.sleep(2)
|
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
from flask import make_response
|
||||||
|
from functools import wraps, update_wrapper
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def nocache(view):
|
||||||
|
@wraps(view)
|
||||||
|
def no_cache(*args, **kwargs):
|
||||||
|
response = make_response(view(*args, **kwargs))
|
||||||
|
response.headers['hmm'] = datetime.now()
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
return update_wrapper(no_cache, view)
|
@ -0,0 +1,24 @@
|
|||||||
|
aiohttp
|
||||||
|
async-timeout
|
||||||
|
chardet==2.3.0
|
||||||
|
multidict
|
||||||
|
python-engineio
|
||||||
|
six==1.10.0
|
||||||
|
yarl
|
||||||
|
flask
|
||||||
|
gevent-websocket
|
||||||
|
eventlet
|
||||||
|
requests
|
||||||
|
|
||||||
|
# Actual connecting to services
|
||||||
|
pytz
|
||||||
|
phpserialize==1.3.0
|
||||||
|
redis>=2.6.2
|
||||||
|
pymysql==0.8
|
||||||
|
bleach==3.2.1
|
||||||
|
html5lib==0.9999999 # via bleach
|
||||||
|
|
||||||
|
flask_socketio~=5.0
|
||||||
|
|
||||||
|
# @notes
|
||||||
|
# - Dont install socketio, it interferes with flask_socketio
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* -- BASE STYLES --
|
||||||
|
* Most of these are inherited from Base, but I want to change a few.
|
||||||
|
*/
|
||||||
|
body {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #1b98f8;
|
||||||
|
}
|
||||||
|
a.github-link {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.content {
|
||||||
|
padding-top: 3em;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
import json
|
||||||
|
import uuid
|
||||||
|
# Is there an existing library to ensure some data store (JSON etc) is in sync with CRUD methods?
|
||||||
|
# Open a github issue if you know something :)
|
||||||
|
|
||||||
|
class ChangeDetectionStore:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
try:
|
||||||
|
with open('/datastore/url-watches.json') as json_file:
|
||||||
|
self.data = json.load(json_file)
|
||||||
|
for p in self.data['watching']:
|
||||||
|
print('url: ' + p['url'])
|
||||||
|
print('')
|
||||||
|
|
||||||
|
# First time ran, doesnt exist.
|
||||||
|
except (FileNotFoundError, json.decoder.JSONDecodeError):
|
||||||
|
print ("Resetting JSON store")
|
||||||
|
|
||||||
|
self.data = {}
|
||||||
|
self.data['watching'] = []
|
||||||
|
self.data['watching'].append({
|
||||||
|
'url': 'https://changedetection.io',
|
||||||
|
'tag': 'general',
|
||||||
|
'uuid': str(uuid.uuid4())
|
||||||
|
})
|
||||||
|
|
||||||
|
with open('/datastore/url-watches.json', 'w') as json_file:
|
||||||
|
json.dump(self.data, json_file)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def sync_to_json(self):
|
||||||
|
with open('/datastore/url-watches.json', 'w') as json_file:
|
||||||
|
json.dump(self.data, json_file)
|
||||||
|
|
||||||
|
# body of the constructor
|
@ -0,0 +1,45 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="description" content="A layout example that shows off a responsive email layout.">
|
||||||
|
<title>Email – Layout Examples – Pure</title>
|
||||||
|
<link rel="stylesheet" href="/static/css/pure-min.css">
|
||||||
|
<link rel="stylesheet" href="/static/css/styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="header">
|
||||||
|
<div class="home-menu pure-menu pure-menu-horizontal pure-menu-fixed">
|
||||||
|
<a class="pure-menu-heading" href="">ChangeDetection</a>
|
||||||
|
|
||||||
|
<ul class="pure-menu-list">
|
||||||
|
<li class="pure-menu-item pure-menu-selected"><a class="github-link " href="https://github.com/"
|
||||||
|
data-hotkey="g d" aria-label="Homepage "
|
||||||
|
data-ga-click="Header, go to dashboard, icon:logo">
|
||||||
|
<svg class="octicon octicon-mark-github v-align-middle" height="32" viewBox="0 0 16 16" version="1.1"
|
||||||
|
width="32" aria-hidden="true">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
|
||||||
|
</svg>
|
||||||
|
</a></li>
|
||||||
|
<li class="pure-menu-item"><a href="#" class="pure-menu-link">Tour</a></li>
|
||||||
|
<li class="pure-menu-item"><a href="#" class="pure-menu-link">Sign Up</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section class="content">
|
||||||
|
<header>
|
||||||
|
{% block header %}{% endblock %}
|
||||||
|
</header>
|
||||||
|
<!--
|
||||||
|
{% for message in get_flashed_messages() %}
|
||||||
|
<div class="flash">{{ message }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
-->
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,42 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="box">
|
||||||
|
|
||||||
|
<form class="pure-form">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Add new change detection watch</legend>
|
||||||
|
<input type="url" placeholder="https://..." />
|
||||||
|
<input type="text" placeholder="tag" size="10" />
|
||||||
|
<button type="submit" class="pure-button pure-button-primary">Save</button>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<table class="pure-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>URL</th>
|
||||||
|
<th>Last Checked</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>op</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
|
||||||
|
{% for watch in watches %}
|
||||||
|
<tr class="pure-table-odd">
|
||||||
|
<td>1</td>
|
||||||
|
<td>{{ watch.url }}</td>
|
||||||
|
<td>2021/2/2 14:00:00</td>
|
||||||
|
<td>No Change</td>
|
||||||
|
<td><button type="submit" class="pure-button pure-button-primary">Recheck</button> <button type="submit" class="pure-button pure-button-primary">Delete</button></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,2 @@
|
|||||||
|
Empty dir, please keep, this is used to store your data!
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
{"watching": [{"url": "https://changedetection.io", "tag": "general", "uuid": "3ba44e22-af8b-4dfd-8227-f9be55bd5788"}]}
|
@ -0,0 +1,18 @@
|
|||||||
|
version: "2"
|
||||||
|
services:
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build: ./backend/dev-docker
|
||||||
|
container_name: changedection-backend
|
||||||
|
volumes:
|
||||||
|
- ./backend:/app
|
||||||
|
- ./datastore:/datastore
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:5000:5000"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- changenet
|
||||||
|
|
||||||
|
networks:
|
||||||
|
changenet:
|
Loading…
Reference in new issue