Compare commits
85 Commits
d94086a3ef
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 504d237405 | |||
| 6696bcc4e7 | |||
| 32a1458218 | |||
| 4697086f86 | |||
| c4b9e5f360 | |||
| 0a9934b889 | |||
| 8ad1650079 | |||
| 6e50013a84 | |||
| dba9a7690d | |||
| 319d237e5d | |||
| af6515e55f | |||
| 1b83098fd0 | |||
| ec11a3d4c4 | |||
| 024b829562 | |||
| d918540252 | |||
| 9022704e5c | |||
| 4046d25aa7 | |||
| aac2ec7ce2 | |||
| a714814ad0 | |||
| 47555303e2 | |||
| 9c83537d65 | |||
| b7d47b130d | |||
| baa8c1392d | |||
| b18012713e | |||
| b714a6c4e6 | |||
| 7188ad7c75 | |||
| 68314ba7af | |||
| f1e591ab5b | |||
| ee5d1b2758 | |||
| 7f2d0ec2f6 | |||
| 2b22eaf0e9 | |||
| 19d646aa40 | |||
| acd57b90a8 | |||
| d63d9cdb78 | |||
| 2ca97cba47 | |||
| 5ee126d0ec | |||
| 0d69fcc296 | |||
| 46c99f1ae0 | |||
| 1801e6d054 | |||
| ae17970d8c | |||
| 30fef37d45 | |||
| 76e90450f8 | |||
| 845a1c8494 | |||
| 4104ee47c4 | |||
| 597900d7b6 | |||
| 942a3adaf6 | |||
| 96960c17a1 | |||
| 6f7fc56e32 | |||
| 1cfa2668b2 | |||
| f524ed4e6a | |||
| 245f524c38 | |||
| 76f857ca0a | |||
| 6aeea9dedb | |||
| dd6ca2d75b | |||
| d9796b0b87 | |||
| 9958763f6f | |||
| a71f3f3681 | |||
| 9f8a9eebfe | |||
| a1fc7a4b27 | |||
| 0e8b558747 | |||
| b6d60e7210 | |||
| bf31f647e7 | |||
| 121cc91ad1 | |||
| ac2b23c459 | |||
| 10675cffbc | |||
| 32dee47628 | |||
| c08f81bd03 | |||
| 5063d78198 | |||
| a12366867d | |||
| 614dea44b4 | |||
| 305b269093 | |||
| 612ee5c740 | |||
| 64c2269c0a | |||
| f3ac9a8c1b | |||
| db414a0b03 | |||
| 51e9b87a3f | |||
| 4444d976e6 | |||
| 4036a15999 | |||
| 3755a1fef5 | |||
| 323a62c29a | |||
| faac097a98 | |||
| 882dc94190 | |||
| 53d767a773 | |||
| e2e0fe6175 | |||
| 7a74ce6227 |
86
client/bs_shutdown.py
Normal file
86
client/bs_shutdown.py
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import urllib.request
|
||||||
|
import json
|
||||||
|
import socket
|
||||||
|
from datetime import datetime
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
|
||||||
|
DEFAULT_SHUTDOWN = "21:00"
|
||||||
|
|
||||||
|
LAST_VALUE = 0
|
||||||
|
|
||||||
|
machine_name = socket.gethostname()
|
||||||
|
url = "http://192.168.50.27:5000/lookup"
|
||||||
|
payload = {
|
||||||
|
"name": machine_name,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_data():
|
||||||
|
data = json.dumps(payload).encode("utf-8")
|
||||||
|
|
||||||
|
req = urllib.request.Request(
|
||||||
|
url,
|
||||||
|
headers={"Content-Type": "application/json"},
|
||||||
|
data=data,
|
||||||
|
method="POST"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(req, timeout=10) as response:
|
||||||
|
data = response.read()
|
||||||
|
json_data = json.loads(data)
|
||||||
|
print(json_data)
|
||||||
|
return json_data
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def to_seconds(t):
|
||||||
|
return t.hour * 3600 + t.minute * 60 + t.second
|
||||||
|
|
||||||
|
def set_shutdown(time, now):
|
||||||
|
global LAST_VALUE
|
||||||
|
|
||||||
|
if (time - now) < 0 or time == LAST_VALUE:
|
||||||
|
return
|
||||||
|
LAST_VALUE = time
|
||||||
|
print("[BS Shutdown] shutting down in " + str(time - now) + " seconds")
|
||||||
|
# subprocess.run(["shutdown", "/s", "/t", (time - now), " "])
|
||||||
|
|
||||||
|
|
||||||
|
def remove_shutdown():
|
||||||
|
print("[BS Shutdown] Removed shutdown")
|
||||||
|
# subprocess.run(["shutdown", "/a"])
|
||||||
|
|
||||||
|
def update():
|
||||||
|
global LAST_VALUE
|
||||||
|
|
||||||
|
data = get_data()
|
||||||
|
|
||||||
|
if data is not None and data["noshutdown"] == 1:
|
||||||
|
if (LAST_VALUE != 0):
|
||||||
|
remove_shutdown() # In case
|
||||||
|
LAST_VALUE = 0
|
||||||
|
return
|
||||||
|
|
||||||
|
if data is None:
|
||||||
|
time = to_seconds(datetime.strptime(DEFAULT_SHUTDOWN, "%H:%M").time())
|
||||||
|
else:
|
||||||
|
time = to_seconds(datetime.strptime(data["time"], "%H:%M").time())
|
||||||
|
now = to_seconds(datetime.now().time())
|
||||||
|
|
||||||
|
if (time - now) < 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
if (time == LAST_VALUE):
|
||||||
|
return
|
||||||
|
|
||||||
|
if (LAST_VALUE != 0):
|
||||||
|
remove_shutdown()
|
||||||
|
print("[BS Shutdown] New value")
|
||||||
|
LAST_VALUE = time
|
||||||
|
set_shutdown(time, now)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
while True:
|
||||||
|
update()
|
||||||
|
time.sleep(30)
|
||||||
@@ -1,14 +1,125 @@
|
|||||||
from flask import Flask, render_template, request, redirect
|
from flask import Flask, render_template, request, redirect, url_for, jsonify
|
||||||
|
import sqlite3
|
||||||
|
import re
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
items = ['dummy1', 'dummy2', 'a', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa']
|
pattern = re.compile(r"^(?:[01]\d|2[0-3]):[0-5]\d$") # Regex "XX:XX"
|
||||||
|
|
||||||
|
DB_PATH = "data.db"
|
||||||
|
|
||||||
|
conn = sqlite3.connect(DB_PATH)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS items (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
time TEXT,
|
||||||
|
noshutdown INTEGER DEFAULT 0
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
cursor.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS val (
|
||||||
|
default_time TEXT NOT NULL DEFAULT '21:00'
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM val")
|
||||||
|
count = cursor.fetchone()[0]
|
||||||
|
if count == 0:
|
||||||
|
cursor.execute("INSERT INTO val (default_time) VALUES (?)", ('21:00',))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def get_db_connection():
|
||||||
|
conn = sqlite3.connect(DB_PATH)
|
||||||
|
conn.row_factory = sqlite3.Row
|
||||||
|
return conn
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def mainpage():
|
def mainpage():
|
||||||
return render_template('index.html', title='BG Shutdown', items=items)
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("SELECT name, time, noshutdown FROM items ORDER BY name")
|
||||||
|
items = cursor.fetchall()
|
||||||
|
cursor.execute("SELECT default_time FROM val")
|
||||||
|
default_time_row = cursor.fetchone()
|
||||||
|
default_time = default_time_row[0] if default_time_row else '21:00'
|
||||||
|
conn.close()
|
||||||
|
return render_template('index.html', title='BS Shutdown', items=items, default_time=default_time)
|
||||||
|
|
||||||
@app.route('/submit', methods =['POST'])
|
@app.route('/submit', methods =['POST'])
|
||||||
def submit():
|
def submit():
|
||||||
value = request.form.get("query")
|
value = request.form.get("query")
|
||||||
items.append(query)
|
time_value = request.form.get("time")
|
||||||
print(value)
|
noshutdown = 1 if request.form.get("noshutdown") == "on" else 0
|
||||||
return redirect(url_for("mainpage"))
|
if not value:
|
||||||
|
return redirect(url_for("mainpage"))
|
||||||
|
if noshutdown == 0 and not time_value:
|
||||||
|
return redirect(url_for("mainpage"))
|
||||||
|
if noshutdown == 1:
|
||||||
|
time_value = 'None'
|
||||||
|
if time_value != 'None':
|
||||||
|
if bool(pattern.match(time_value)) is not True:
|
||||||
|
return redirect(url_for("mainpage"))
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('SELECT 1 FROM items WHERE name = ?', (value,))
|
||||||
|
item = cursor.fetchone()
|
||||||
|
if item:
|
||||||
|
cursor.execute("UPDATE items SET time = ?, noshutdown = ? WHERE name = ?", (time_value, noshutdown, value))
|
||||||
|
else:
|
||||||
|
cursor.execute("INSERT INTO items (name, time, noshutdown) VALUES (?, ?, ?)", (value, time_value, noshutdown))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return redirect(url_for("mainpage"))
|
||||||
|
|
||||||
|
@app.route("/submit-default", methods=["POST"])
|
||||||
|
def submit_default():
|
||||||
|
time_value = request.form.get("default-time")
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
if bool(pattern.match(time_value)) is not True:
|
||||||
|
return redirect(url_for("mainpage"))
|
||||||
|
cursor.execute("UPDATE val SET default_time = ?", (time_value,))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return redirect(url_for("mainpage"))
|
||||||
|
|
||||||
|
@app.route("/delete", methods=["POST"])
|
||||||
|
def delete():
|
||||||
|
value = request.form.get("item_name")
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('SELECT 1 FROM items WHERE name = ?', (value,))
|
||||||
|
item = cursor.fetchone()
|
||||||
|
if not item:
|
||||||
|
conn.close()
|
||||||
|
return redirect(url_for("mainpage"))
|
||||||
|
cursor.execute(
|
||||||
|
"DELETE FROM items WHERE name = ?",
|
||||||
|
(value,)
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return redirect(url_for("mainpage"))
|
||||||
|
|
||||||
|
@app.route("/lookup", methods=["POST"])
|
||||||
|
def lookup():
|
||||||
|
data = request.get_json()
|
||||||
|
if not data or "name" not in data:
|
||||||
|
return jsonify({"error": "Not found"}), 404
|
||||||
|
name = data["name"]
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute(
|
||||||
|
"SELECT name, time, noshutdown FROM items WHERE name = ?",
|
||||||
|
(name,)
|
||||||
|
)
|
||||||
|
item = cursor.fetchone()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if item:
|
||||||
|
return jsonify({"name": item["name"], "noshutdown": item["noshutdown"], "time": item["time"]}), 200
|
||||||
|
else:
|
||||||
|
return jsonify({"error": "Not found"}), 404
|
||||||
@@ -35,14 +35,17 @@
|
|||||||
<header>
|
<header>
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand" href="{{ url_for('mainpage') }}">BG Shutdown</a>
|
<a class="navbar-brand" href="{{ url_for('mainpage') }}">BS Shutdown</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
<ul class="navbar-nav ms-auto">
|
<ul class="navbar-nav ms-auto">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {% if title=='BG Shutdown' %}active{% endif %}" href="{{ url_for('mainpage') }}">Accueil</a>
|
<a class="nav-link {% if title=='BS Shutdown' %}active{% endif %}" href="{{ url_for('mainpage') }}">Accueil</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link {% if title=='BG Shutdown' %}active{% endif %}" href="{{ url_for('mainpage') }}">Groupes</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,7 +53,7 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="container my-5">
|
<main class="container my-5 flex-fill">
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,108 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
|
||||||
|
|
||||||
<div class="container py-4">
|
<div class="container py-4">
|
||||||
|
|
||||||
<!-- Formulaire -->
|
|
||||||
<div class="card bg-dark bg-opacity-75 p-3 mb-4">
|
<div class="card bg-dark bg-opacity-75 p-3 mb-4">
|
||||||
<form method="post" action="/submit" class="row g-2 align-items-center">
|
<div class="row g-2 align-items-center">
|
||||||
<div class="col">
|
|
||||||
<input
|
<div class="col-10">
|
||||||
type="text"
|
<form method="post" action="/submit" class="row g-2 align-items-center">
|
||||||
name="query"
|
<div class="col-md-2">
|
||||||
class="form-control bg-secondary-subtle text-white"
|
<input
|
||||||
placeholder="Enter text">
|
type="text"
|
||||||
</div>
|
name="query"
|
||||||
<div class="col-auto">
|
class="form-control bg-dark text-white"
|
||||||
<button type="submit" class="btn btn-secondary">
|
placeholder="Nom de la machine">
|
||||||
Submit
|
</div>
|
||||||
</button>
|
<div class="col-md-2">
|
||||||
</div>
|
<select name="time" class="form-select bg-dark text-white" id="time-select">
|
||||||
</form>
|
{% for hour in range(0, 24) %}
|
||||||
</div>
|
<option value="{{ '%02d:00'|format(hour) }}">{{ '%02d:00'|format(hour) }}</option>
|
||||||
|
<option value="{{ '%02d:30'|format(hour) }}">{{ '%02d:30'|format(hour) }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<div class="form-check text-white">
|
||||||
|
<input class="form-check-input" type="checkbox" name="noshutdown" id="noshutdown">
|
||||||
|
<label class="form-check-label" for="noshutdown">Whitelist shutdown</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-1">
|
||||||
|
<button type="submit" class="btn btn-sm btn-primary w-100">
|
||||||
|
<i class="bi bi-plus-lg"> Save</i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-auto gap-1 ms-auto">
|
||||||
|
<form method="post" action="/submit-default" class="d-flex align-items-center gap-1">
|
||||||
|
<select name="default-time" class="form-select bg-dark text-white flex-grow-1" id="default-time-select">
|
||||||
|
{% for hour in range(0, 24) %}
|
||||||
|
{% set h1 = '%02d:00'|format(hour) %}
|
||||||
|
{% set h2 = '%02d:30'|format(hour) %}
|
||||||
|
|
||||||
|
<option value="{{ h1 }}"
|
||||||
|
{% if h1 == default_time %}selected{% endif %}>
|
||||||
|
{{ h1 }}
|
||||||
|
</option>
|
||||||
|
|
||||||
|
<option value="{{ h2 }}"
|
||||||
|
{% if h2 == default_time %}selected{% endif %}>
|
||||||
|
{{ h2 }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<button type="submit" class="btn btn-sm btn-primary w-100">
|
||||||
|
<i class="bi bi-save"> Save</i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Tableau / Liste -->
|
|
||||||
<div class="card bg-dark bg-opacity-75 p-3">
|
<div class="card bg-dark bg-opacity-75 p-3">
|
||||||
<h5 class="text-white mb-3">Liste des éléments</h5>
|
<h5 class="text-white mb-3">Liste des éléments</h5>
|
||||||
|
<div class="row fw-bold text-white mb-2">
|
||||||
|
<div class="col-4">Nom</div>
|
||||||
|
<div class="col-3">Whitelist</div>
|
||||||
|
<div class="col-3">Time</div>
|
||||||
|
<div class="col-2 text-end">Actions</div>
|
||||||
|
</div>
|
||||||
<div class="table-items">
|
<div class="table-items">
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<div class="py-2">
|
<div class="row align-items-center py-2">
|
||||||
<a href="#" class="text-decoration-none text-white">{{ item }}</a>
|
<div class="col-4 text-white">
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-3">
|
||||||
|
{% if item.noshutdown == 1 %}
|
||||||
|
<span class="text-success">OUI</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-danger">NON</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-3 text-white">
|
||||||
|
{% if item.noshutdown == 0 %}
|
||||||
|
{{ item.time }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-2 text-end">
|
||||||
|
<form method="post" action="/delete" class="m-0">
|
||||||
|
<input type="hidden" name="item_name" value="{{ item.name }}">
|
||||||
|
<button type="submit" class="btn btn-sm btn-danger">
|
||||||
|
<i class="bi bi-x-lg"></i>Supprimer
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if not loop.last %}
|
{% if not loop.last %}
|
||||||
<hr class="border-secondary my-1">
|
<hr class="border-secondary my-1">
|
||||||
@@ -38,4 +113,15 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const tickCheckbox = document.getElementById('noshutdown'); // script pr desactiver la selection de l'heure si whitelist
|
||||||
|
const timeSelect = document.getElementById('time-select');
|
||||||
|
|
||||||
|
timeSelect.disabled = tickCheckbox.checked;
|
||||||
|
|
||||||
|
tickCheckbox.addEventListener('change', function() {
|
||||||
|
timeSelect.disabled = this.checked;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user