Skip to content

Commit

Permalink
Merge pull request #5 from Misterbabou/dev
Browse files Browse the repository at this point in the history
2.0.1  release
  • Loading branch information
Misterbabou authored Mar 23, 2024
2 parents 5943cbf + c7207d8 commit f11ef8c
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 62 deletions.
4 changes: 4 additions & 0 deletions app/templates/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
.card {
margin-bottom: 20px;
}
.card-body {
padding: 10px;
}
.card-footer {
text-align: right;
padding: 10px;
}
input[type=submit] {
background-color: #4CAF50;
Expand Down
62 changes: 53 additions & 9 deletions app/templates/wol_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
const name = document.getElementById('name').value;
const ipAddress = document.getElementById('ip_address').value;
const macAddress = document.getElementById('mac_address').value;
const testType = document.getElementById('test_type').value;

// Regular expressions to check the format of the IP and MAC address
const ipRegex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
Expand All @@ -24,6 +25,11 @@
}
return false;
}

if (testType !== 'icmp' && !isValidPort(testType)) {
alert('Please enter either "icmp" or a valid TCP port number.');
return false;
}

// Check if the name already exists
fetch(`/check_name_exists?name=${name}`)
Expand All @@ -37,10 +43,43 @@
});
}

function isValidPort(value) {
const portNumber = parseInt(value);
return !isNaN(portNumber) && portNumber >= 1 && portNumber <= 65535;
}

window.addEventListener('load', function() {
// Get all status indicator elements
const statusIndicators = document.querySelectorAll('.status-indicator');

// Loop through each status indicator element
statusIndicators.forEach(function(indicator) {
// Extract IP address and test type from the data attributes
const ip_address = indicator.getAttribute('data-ip-address');
const test_type = indicator.getAttribute('data-test-type');

// Make an HTTP GET request to fetch the initial status
fetch(`/check_status?ip_address=${ip_address}&test_type=${test_type}`)
.then(response => response.text())
.then(status => {
// Update the class of the element based on the returned status
if (status === 'awake') {
indicator.classList.remove('asleep');
indicator.classList.add('awake');
} else {
indicator.classList.remove('awake');
indicator.classList.add('asleep');
}
})
.catch(error => {
console.error('Error fetching initial status:', error);
});
});
});

function updateStatus(ip_address, element) {
function updateStatus(ip_address, test_type, element) {
// Make an HTTP GET request to the check_status endpoint
fetch(`/check_status?ip_address=${ip_address}`)
fetch(`/check_status?ip_address=${ip_address}&test_type=${test_type}`)
.then(response => response.text())
.then(status => {
// Update the class of the element based on the returned status
Expand All @@ -59,7 +98,8 @@
// Update the status of all computers
for (let element of document.getElementsByClassName('status-indicator')) {
const ip_address = element.getAttribute('data-ip-address');
updateStatus(ip_address, element);
const test_type = element.getAttribute('data-test-type');
updateStatus(ip_address, test_type, element);
}
{% if os.environ.get('REFRESH_PING') == '60' %}
}, 60000);
Expand All @@ -84,11 +124,6 @@
// continue with form submission
return true;
}

function clearSearchInput() {
document.querySelector('.search-input').value = '';
window.location.href = '/';
}
</script>

<header class="header" style="position: sticky; top: 0; z-index: 1; display: block; text-align: center; background-color: #333; color: #fff;">
Expand All @@ -108,9 +143,14 @@ <h1>GPT Wake On Lan</h1>
{% for computer in computers %}
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ computer.name }} <span class="status-indicator {% if is_computer_awake(computer.ip_address) %}awake{% else %}asleep{% endif %}" data-ip-address="{{ computer.ip_address }}"></span></h5>
<h5 class="card-title">{{ computer.name }} <span class="status-indicator {% if is_computer_awake(computer.ip_address, computer.test_type) %}awake{% else %}asleep{% endif %}" data-ip-address="{{ computer.ip_address }}" data-test-type="{{ computer.test_type }}"></span></h5>
<p class="card-info-right">IP: {{ computer.ip_address }}</p>
<p class="card-info-right">MAC: {{ computer.mac_address }}</p>
{% if computer.test_type == 'icmp' %}
<p class="card-info-right">Status Check: ICMP</p>
{% else %}
<p class="card-info-right">Status Check: TCP {{ computer.test_type }}</p>
{% endif %}
{% if computer.cron_schedule is defined %}
<p class="card-info-right" style="display: inline-block;">Cron: {{ computer.cron_schedule }}</p>
{% if os.environ.get('DISABLE_ADD_DEL') != '1' %}
Expand Down Expand Up @@ -166,6 +206,10 @@ <h5 class="card-title">{{ computer.name }} <span class="status-indicator {% if i
<label for="ip_address">IP address</label>
<input type="text" class="form-control" name="ip_address" id="ip_address" placeholder="192.168.0.1" required>
</div>
<div class="form-group">
<label for="test_type">Status Check</label>
<input type="text" class="form-control" name="test_type" id="test_type" placeholder="icmp or port number" required>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Add computer</button>
</div>
Expand Down
132 changes: 79 additions & 53 deletions app/wol.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,40 @@


def load_computers():
# Load the list of computers from the configuration file
computers = []
if not os.path.exists(computer_filename):
open(computer_filename, 'w').close() # create the file if it doesn't exist
with open(computer_filename) as f:
for line in f:
name, mac_address, ip_address = line.strip().split(',')
computers.append({'name': name, 'mac_address': mac_address, 'ip_address': ip_address})

# Load the cron schedule information for each computer
if not os.path.exists(cron_filename):
open(cron_filename, 'w').close() # create the file if it doesn't exist
with open(cron_filename) as f:
for line in f:
if not line.startswith('#'):
fields = line.strip().split()
schedule = ' '.join(fields[:5])
user = fields[5]
command = ' '.join(fields[6:])
mac_address = command.split()[-1]
computer = next((c for c in computers if c['mac_address'] == mac_address), None)
if computer:
computer['cron_schedule'] = schedule

return computers
# Load the list of computers from the configuration file
computers = []
if not os.path.exists(computer_filename):
open(computer_filename, 'w').close() # create the file if it doesn't exist
with open(computer_filename) as f:
for line in f:
fields = line.strip().split(',')
name = fields[0]
mac_address = fields[1]
ip_address = fields[2]
test_type = fields[3] if len(fields) >= 4 else 'icmp' # Default to 'icmp' if test_type is not specified
if not test_type.strip(): # Check if test_type is empty or whitespace
test_type = 'icmp'
line = f"{name},{mac_address},{ip_address},{test_type}\n" # Update the line with 'icmp'
with open(computer_filename, 'a') as f:
f.write(line) # Write the updated line to the file
computers.append({'name': name, 'mac_address': mac_address, 'ip_address': ip_address, 'test_type': test_type})

# Load the cron schedule information for each computer
if not os.path.exists(cron_filename):
open(cron_filename, 'w').close() # create the file if it doesn't exist
with open(cron_filename) as f:
for line in f:
if not line.startswith('#'):
fields = line.strip().split()
schedule = ' '.join(fields[:5])
user = fields[5]
command = ' '.join(fields[6:])
mac_address = command.split()[-1]
computer = next((c for c in computers if c['mac_address'] == mac_address), None)
if computer:
computer['cron_schedule'] = schedule

return computers

computers = load_computers()

Expand All @@ -50,23 +59,40 @@ def send_wol_packet(mac_address):
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.sendto(b'\xff' * 6 + packed_mac * 16, ('<broadcast>', 9))

def is_computer_awake(ip_address, timeout=ping_timeout):
def is_computer_awake(ip_address, port, timeout=ping_timeout):
if not port or port.lower() == 'icmp':
return is_computer_awake_icmp(ip_address)
else:
port_int = int(port)
return is_computer_awake_tcp(ip_address, port_int)

def is_computer_awake_icmp(ip_address, timeout=ping_timeout):
# Use the ping command with a timeout to check if the computer is awake
result = subprocess.run(['fping', '-t', str(timeout), '-c', '1', ip_address], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return result.returncode == 0

def is_computer_awake_tcp(ip_address, port, timeout=ping_timeout):
try:
with socket.create_connection((ip_address, port), timeout=timeout):
return True
except (socket.timeout, OSError):
return False

def search_computers(computers, query):
query = query.lower()
return [computer for computer in computers if query in computer['name'].lower() or query in computer['mac_address'].lower() or query in computer['ip_address'].lower()]

### APP
def initial_computer_status(ip_address, test_type):
return "asleep"

@app.route('/')
def wol_form():
query = request.args.get('query')
computers = load_computers()

if query:
computers = search_computers(computers, query)
return render_template('wol_form.html', computers=computers, is_computer_awake=is_computer_awake, os=os, query=query)
computers = search_computers(computers, query)
return render_template('wol_form.html', computers=computers, is_computer_awake=initial_computer_status, os=os, query=query)

@app.route('/delete_computer', methods=['POST'])
def delete_computer():
Expand All @@ -82,14 +108,15 @@ def delete_computer():
# Save the updated list of computers to the configuration file
with open(computer_filename, 'w') as f:
for computer in computers:
f.write('{},{},{}\n'.format(computer['name'], computer['mac_address'], computer['ip_address']))
f.write('{},{},{},{}\n'.format(computer['name'], computer['mac_address'], computer['ip_address'], computer['test_type']))
return redirect('/')

@app.route('/add_computer', methods=['POST'])
def add_computer():
name = request.form['name']
mac_address = request.form['mac_address']
ip_address = request.form['ip_address']
test_type = request.form['test_type']

# Check if the computer name already exists
if check_name_exist(name, computers):
Expand All @@ -100,11 +127,11 @@ def add_computer():
</script>
'''

computers.append({'name': name, 'mac_address': mac_address, 'ip_address': ip_address})
computers.append({'name': name, 'mac_address': mac_address, 'ip_address': ip_address, 'test_type': test_type})
# Save the updated list of computers to the configuration file
with open(computer_filename, 'w') as f:
for computer in computers:
f.write('{},{},{}\n'.format(computer['name'], computer['mac_address'], computer['ip_address']))
f.write('{},{},{},{}\n'.format(computer['name'], computer['mac_address'], computer['ip_address'], computer['test_type']))
return redirect(url_for('wol_form'))

@app.route('/add_cron', methods=['POST'])
Expand Down Expand Up @@ -153,10 +180,11 @@ def delete_cron_entry(request_mac_address):
@app.route('/check_status')
def check_status():
ip_address = request.args.get('ip_address')
if is_computer_awake(ip_address):
return 'awake'
test_type = request.args.get('test_type')
if is_computer_awake(ip_address,test_type):
return 'awake'
else:
return 'asleep'
return 'asleep'

@app.route('/check_name_exist')
def check_name_exist(name, computers):
Expand All @@ -165,26 +193,24 @@ def check_name_exist(name, computers):
return True
return False


@app.route('/wakeup', methods=['POST'])
def wol_send():
mac_address = request.form['mac_address']
computer = next(c for c in computers if c['mac_address'] == mac_address)
ip_address = computer['ip_address']
if is_computer_awake(ip_address):
return '''
<script>
alert('Computer is Already Awake');
window.history.back();
</script>
'''
else:
send_wol_packet(mac_address)
return '''
<script>
alert('Magic Packet Send !');
window.history.back();
</script>
mac_address = request.form['mac_address']
computer = next(c for c in computers if c['mac_address'] == mac_address)
ip_address = computer['ip_address']
test_type = computer['test_type']

if is_computer_awake(ip_address, test_type):
message = 'Computer is Already Awake'
else:
send_wol_packet(mac_address)
message = 'Magic Packet Sent !'

return f'''
<script>
alert('{message}');
window.history.back();
</script>
'''

if __name__ == '__main__':
Expand Down

0 comments on commit f11ef8c

Please sign in to comment.