Add readme and colors.
This commit is contained in:
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Why?
|
||||
|
||||
Sometimes I run long scripts on a remote machine and I want to know when they finish. It's
|
||||
not urgent enough that I need a text or toot, but being able to pull up a simple page that
|
||||
shows what is done and not done makes it easy to check periodically.
|
||||
|
||||
# How?
|
||||
|
||||
This tiny Flask API runs on a server (Raspberry Pi, etc.). It has very basic authentication
|
||||
and waits for a curl (or similar) GET request with some small amount of data. The data are
|
||||
displayed on a simple web page.
|
||||
|
||||
The reason for a simple GET request is to make this as code-agnostic as possible. Drop a
|
||||
curl command into R or Python or Go or Ruby or whatever (I assume) and be able to watch
|
||||
whatever data you pass.
|
||||
|
||||
You can either run with the internal Flask development server or something like gunicorn.
|
||||
|
||||
# Other Use Cases?
|
||||
|
||||
I'm sure there are some.
|
||||
|
||||
# Security?
|
||||
|
||||
I'm sure this isn't very secure. It has basic data cleaning, string length limits, and
|
||||
username/password protection. There is no database--all data are kept in memory and will
|
||||
disappear when the server is stopped. Use at your own risk, don't reuse passwords, and
|
||||
obviously don't pass data that can't be shared openly online. The last part includes things
|
||||
like "front_door_unlocked"--use common sense.
|
6
app.py
6
app.py
@ -10,7 +10,8 @@ app = Flask(__name__)
|
||||
|
||||
statuses = [
|
||||
{
|
||||
'title': 'curl -u matt:python -i http://localhost:5000/log/api/v1.0/new?title="example_status_no_spaces"',
|
||||
'title': 'app_is_running',
|
||||
'color': "green",
|
||||
'timestamp': datetime.datetime.now().timestamp(),
|
||||
'timestamp_readable': datetime.datetime.now()
|
||||
}
|
||||
@ -38,6 +39,7 @@ def create_status():
|
||||
|
||||
status = {
|
||||
'title': safer_title,
|
||||
'color': request.args.get("color"),
|
||||
'timestamp': datetime.datetime.now().timestamp(),
|
||||
'timestamp_readable': datetime.datetime.now()
|
||||
}
|
||||
@ -57,7 +59,7 @@ def get_statuses_raw():
|
||||
@app.route('/', methods=['GET'])
|
||||
def get_statuses():
|
||||
long_agos = [humanfriendly.format_timespan(datetime.datetime.now().timestamp() - status['timestamp']) for status in statuses[::-1]]
|
||||
return render_template("list.html",
|
||||
return render_template("index.html",
|
||||
statuses = statuses[::-1],
|
||||
long_agos = long_agos)
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
.statuses tr td {
|
||||
border: 1px solid black;
|
||||
padding: 5px;
|
||||
}
|
39
templates/index.html
Normal file
39
templates/index.html
Normal file
@ -0,0 +1,39 @@
|
||||
<html>
|
||||
<head>
|
||||
<link href="/static/css/style.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="countdown"><span id="countdown_numbers"></span> seconds until refresh</div>
|
||||
<script>
|
||||
(function countdown(remaining) {
|
||||
if(remaining <= 0)
|
||||
location.reload(true);
|
||||
document.getElementById('countdown_numbers').innerHTML = remaining;
|
||||
setTimeout(function(){ countdown(remaining - 1); }, 1000);
|
||||
})(15); // n seconds
|
||||
</script>
|
||||
|
||||
<table class = "statuses">
|
||||
<tr><th>What Happened?</th><th>When Did It Happen?</th><th>How Long Has It Been?</th></tr>
|
||||
{% for status in statuses %}
|
||||
<tr>
|
||||
<td style="background-color: {{ status.color }}">{{ status.title }}</td><td>{{ status.timestamp_readable }}</td><td>{{ long_agos[loop.index0] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<h2>How does this work?</h2>
|
||||
|
||||
<p>Send a curl (or similar) request from any script or code and include your username and
|
||||
password (see app.py, @auth.get_password).</p>
|
||||
|
||||
<code>
|
||||
curl -u username:password -i "http://localhost:5000/new?title=a_status_without_spaces_goes_here"
|
||||
</code>
|
||||
|
||||
<p>The entire list of statuses is kept in memory and limited to 1000 (or whatever you set
|
||||
it to). If your service or server restarts, the list is wiped out.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,19 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<link href="/static/css/style.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class = "statuses">
|
||||
<tr><th>What Happened?</th><th>When Did It Happen?</th><th>How Long Has It Been?</th></tr>
|
||||
{% for status in statuses %}
|
||||
<tr>
|
||||
<td>{{ status.title }}</td><td>{{ status.timestamp_readable }}</td><td>{{ long_agos[loop.index0] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user