mqtt prep 8

This commit is contained in:
Jokob-sk
2022-12-04 00:07:22 +11:00
parent 525f6c3bf1
commit 8ea3f077e5
7262 changed files with 111 additions and 81 deletions
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
+2 -2
View File
@@ -16,9 +16,9 @@ unknown devices. It also warns if a "always connected" devices disconnects.
[![Docker Pulls](https://img.shields.io/docker/pulls/jokobsk/pi.alert?label=Pulls&logo=docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/pi.alert) [![Docker Pulls](https://img.shields.io/docker/pulls/jokobsk/pi.alert?label=Pulls&logo=docker&color=0aa8d2&logoColor=fff)](https://hub.docker.com/r/jokobsk/pi.alert)
[![Docker Pushed](https://img.shields.io/badge/dynamic/json?color=0aa8d2&logoColor=fff&label=Pushed&query=last_updated&url=https%3A%2F%2Fhub.docker.com%2Fv2%2Frepositories%2Fjokobsk%2Fpi.alert%2F&logo=docker&link=http://left&link=https://hub.docker.com/repository/docker/jokobsk/pi.alert)](https://hub.docker.com/r/jokobsk/pi.alert) [![Docker Pushed](https://img.shields.io/badge/dynamic/json?color=0aa8d2&logoColor=fff&label=Pushed&query=last_updated&url=https%3A%2F%2Fhub.docker.com%2Fv2%2Frepositories%2Fjokobsk%2Fpi.alert%2F&logo=docker&link=http://left&link=https://hub.docker.com/repository/docker/jokobsk/pi.alert)](https://hub.docker.com/r/jokobsk/pi.alert)
🐳 Docker Image: [jokobsk/Pi.Alert](https://registry.hub.docker.com/r/jokobsk/pi.alert) <br/> 🐳 Docker hub: [jokobsk/Pi.Alert](https://registry.hub.docker.com/r/jokobsk/pi.alert) <br/>
📄 [Dockerfile](https://github.com/jokob-sk/Pi.Alert/blob/main/Dockerfile) <br/> 📄 [Dockerfile](https://github.com/jokob-sk/Pi.Alert/blob/main/Dockerfile) <br/>
📚 [Dockerfile instructions](https://github.com/jokob-sk/Pi.Alert/blob/main//dockerfiles/README.md) 📚 [Docker instructions](https://github.com/jokob-sk/Pi.Alert/blob/main//dockerfiles/README.md)
Dark mode (and much more) within this fork courtesy of [leiweibau](https://github.com/leiweibau/Pi.Alert) Dark mode (and much more) within this fork courtesy of [leiweibau](https://github.com/leiweibau/Pi.Alert)
Regular → Executable
View File
+89 -58
View File
@@ -151,8 +151,8 @@ except NameError:
#=============================================================================== #===============================================================================
# MAIN # MAIN
#=============================================================================== #===============================================================================
send_report_on_cycles = [1, "internet_IP", "update_vendors_silent"]
cycle = "" cycle = ""
check_report = [1, "internet_IP", "update_vendors_silent"]
network_scan_minutes = 5 network_scan_minutes = 5
mqtt_thread_up = False mqtt_thread_up = False
@@ -166,8 +166,9 @@ last_run = now_minus_24h
last_cleanup = now_minus_24h last_cleanup = now_minus_24h
last_update_vendors = time_now - timedelta(days = 7) last_update_vendors = time_now - timedelta(days = 7)
def main (): debug_once = False
def main ():
# Initialize global variables # Initialize global variables
global time_now, cycle, last_network_scan, last_internet_IP_scan, last_run, last_cleanup, last_update_vendors, network_scan_minutes, mqtt_thread_up global time_now, cycle, last_network_scan, last_internet_IP_scan, last_run, last_cleanup, last_update_vendors, network_scan_minutes, mqtt_thread_up
# second set of global variables # second set of global variables
@@ -183,9 +184,11 @@ def main ():
# last time any scan or maintennace was run # last time any scan or maintennace was run
last_run = time_now last_run = time_now
reporting = False
# Header # Header
print ('\nPi.Alert ' + VERSION +' ('+ VERSION_DATE +')') print ('\nLoop start')
print ('---------------------------------------------------------')\ print ('---------------------------------------------------------')
log_timestamp = time_now log_timestamp = time_now
@@ -204,8 +207,9 @@ def main ():
if last_internet_IP_scan + timedelta(minutes=3) < time_now: if last_internet_IP_scan + timedelta(minutes=3) < time_now:
cycle = 'internet_IP' cycle = 'internet_IP'
last_internet_IP_scan = time_now last_internet_IP_scan = time_now
check_internet_IP() reporting = check_internet_IP()
# Update vendors once a week
if last_update_vendors + timedelta(days = 7) < time_now: if last_update_vendors + timedelta(days = 7) < time_now:
last_update_vendors = time_now last_update_vendors = time_now
cycle = 'update_vendors' cycle = 'update_vendors'
@@ -216,13 +220,14 @@ def main ():
cycle = 1 # network scan cycle = 1 # network scan
scan_network() scan_network()
# clean up the DB once a day
if last_cleanup + timedelta(hours = 24) < time_now: if last_cleanup + timedelta(hours = 24) < time_now:
last_cleanup = time_now last_cleanup = time_now
cycle = 'cleanup' cycle = 'cleanup'
cleanup_database() cleanup_database()
# Reporting # Reporting
if cycle in send_report_on_cycles: if cycle in check_report:
email_reporting() email_reporting()
# Close SQL # Close SQL
@@ -231,10 +236,15 @@ def main ():
# Final menssage # Final menssage
if cycle != "": if cycle != "":
print ('\nFinished cycle: ', cycle, '\n') print ('\nFinished cycle: ', cycle, '\n')
cycle = ""
# Footer
print ('\nLoop end')
print ('---------------------------------------------------------')
else: else:
# do something # do something
cycle = "" cycle = ""
print ('\n20s passed') print ('\n Wait 20s')
#loop - recursion #loop - recursion
time.sleep(20) # wait for N seconds time.sleep(20) # wait for N seconds
@@ -244,6 +254,8 @@ def main ():
# INTERNET IP CHANGE # INTERNET IP CHANGE
#=============================================================================== #===============================================================================
def check_internet_IP (): def check_internet_IP ():
reporting = False
# Header # Header
print ('Check Internet IP') print ('Check Internet IP')
print (' Timestamp:', startTime ) print (' Timestamp:', startTime )
@@ -258,7 +270,7 @@ def check_internet_IP ():
if internet_IP == "" : if internet_IP == "" :
print (' Error retrieving Internet IP') print (' Error retrieving Internet IP')
print (' Exiting...\n') print (' Exiting...\n')
return 1 return False
print (' ', internet_IP) print (' ', internet_IP)
# Get previous stored IP # Get previous stored IP
@@ -272,6 +284,7 @@ def check_internet_IP ():
print (' Saving new IP') print (' Saving new IP')
save_new_internet_IP (internet_IP) save_new_internet_IP (internet_IP)
print (' IP updated') print (' IP updated')
reporting = True
else : else :
print (' No changes to perform') print (' No changes to perform')
closeDB() closeDB()
@@ -285,7 +298,7 @@ def check_internet_IP ():
if dns_IP == "" : if dns_IP == "" :
print (' Error retrieving Dynamic DNS IP') print (' Error retrieving Dynamic DNS IP')
print (' Exiting...\n') print (' Exiting...\n')
return 1 return False
print (' ', dns_IP) print (' ', dns_IP)
# Check DNS Change # Check DNS Change
@@ -293,11 +306,14 @@ def check_internet_IP ():
print (' Updating Dynamic DNS IP...') print (' Updating Dynamic DNS IP...')
message = set_dynamic_DNS_IP () message = set_dynamic_DNS_IP ()
print (' ', message) print (' ', message)
reporting = True
else : else :
print (' No changes to perform') print (' No changes to perform')
else : else :
print ('\n Skipping Dynamic DNS update...') print ('\n Skipping Dynamic DNS update...')
return reporting
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def get_internet_IP (): def get_internet_IP ():
@@ -440,6 +456,7 @@ def update_devices_MAC_vendors (pArg = ''):
# Update vendors DB (iab oui) # Update vendors DB (iab oui)
print ('\nUpdating vendors DB (iab & oui)...') print ('\nUpdating vendors DB (iab & oui)...')
# update_args = ['sh', PIALERT_BACK_PATH + '/update_vendors.sh', ' > ', LOG_PATH + '/update_vendors.log', '2>&1']
update_args = ['sh', PIALERT_BACK_PATH + '/update_vendors.sh', pArg] update_args = ['sh', PIALERT_BACK_PATH + '/update_vendors.sh', pArg]
try: try:
@@ -492,6 +509,11 @@ def update_devices_MAC_vendors (pArg = ''):
# Close DB # Close DB
closeDB() closeDB()
if len(recordsToUpdate) > 0:
return True
else:
return False
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def query_MAC_vendor (pMAC): def query_MAC_vendor (pMAC):
try : try :
@@ -528,6 +550,8 @@ def query_MAC_vendor (pMAC):
# SCAN NETWORK # SCAN NETWORK
#=============================================================================== #===============================================================================
def scan_network (): def scan_network ():
reporting = False
# Header # Header
print ('Scan Devices') print ('Scan Devices')
print (' ScanCycle:', cycle) print (' ScanCycle:', cycle)
@@ -540,7 +564,7 @@ def scan_network ():
print ('\n*************** ERROR ***************') print ('\n*************** ERROR ***************')
print ('ScanCycle %s not found' % cycle ) print ('ScanCycle %s not found' % cycle )
print (' Exiting...\n') print (' Exiting...\n')
return 1 return False
# ScanCycle data # ScanCycle data
cycle_interval = scanCycle_data['cic_EveryXmin'] cycle_interval = scanCycle_data['cic_EveryXmin']
@@ -551,18 +575,19 @@ def scan_network ():
print_log ('arp-scan starts...') print_log ('arp-scan starts...')
arpscan_devices = execute_arpscan () arpscan_devices = execute_arpscan ()
print_log ('arp-scan ends') print_log ('arp-scan ends')
# DEBUG - print number of rows updated # DEBUG - print number of rows updated
# print (arpscan_devices) # print ('aspr-scan result:', len(arpscan_devices))
# Pi-hole method # Pi-hole method
print (' Pi-hole Method...') print (' Pi-hole Method...')
openDB() openDB()
print_log ('Pi-hole copy starts...') print_log ('Pi-hole copy starts...')
copy_pihole_network() reporting = copy_pihole_network() or reporting
# DHCP Leases method # DHCP Leases method
print (' DHCP Leases Method...') print (' DHCP Leases Method...')
read_DHCP_leases () reporting = read_DHCP_leases () or reporting
# Load current scan data # Load current scan data
print ('\nProcessing scan results...') print ('\nProcessing scan results...')
@@ -612,6 +637,8 @@ def scan_network ():
sql_connection.commit() sql_connection.commit()
closeDB() closeDB()
return reporting
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def query_ScanCycle_Data (pOpenCloseDB = False): def query_ScanCycle_Data (pOpenCloseDB = False):
# Check if is necesary open DB # Check if is necesary open DB
@@ -722,23 +749,25 @@ def copy_pihole_network ():
AND hwaddr <> '00:00:00:00:00:00' """) AND hwaddr <> '00:00:00:00:00:00' """)
sql.execute ("""UPDATE PiHole_Network SET PH_Name = '(unknown)' sql.execute ("""UPDATE PiHole_Network SET PH_Name = '(unknown)'
WHERE PH_Name IS NULL OR PH_Name = '' """) WHERE PH_Name IS NULL OR PH_Name = '' """)
# DEBUG
# print (sql.rowcount)
# Close Pi-hole DB # Close Pi-hole DB
sql.execute ("DETACH PH") sql.execute ("DETACH PH")
return str(sql.rowcount) != "0"
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def read_DHCP_leases (): def read_DHCP_leases ():
reporting = False
# check DHCP Leases is active # check DHCP Leases is active
if not DHCP_ACTIVE : if not DHCP_ACTIVE :
return return False
# Read DHCP Leases # Read DHCP Leases
# Bugfix #1 - dhcp.leases: lines with different number of columns (5 col) # Bugfix #1 - dhcp.leases: lines with different number of columns (5 col)
data = [] data = []
with open(DHCP_LEASES, 'r') as f: with open(DHCP_LEASES, 'r') as f:
for line in f: for line in f:
reporting = True
row = line.rstrip().split() row = line.rstrip().split()
if len(row) == 5 : if len(row) == 5 :
data.append (row) data.append (row)
@@ -755,6 +784,7 @@ def read_DHCP_leases ():
""", data) """, data)
# DEBUG # DEBUG
# print (sql.rowcount) # print (sql.rowcount)
return reporting
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
def save_scanned_devices (p_arpscan_devices, p_cycle_interval): def save_scanned_devices (p_arpscan_devices, p_cycle_interval):
@@ -1399,7 +1429,7 @@ def email_reporting ():
global mail_text global mail_text
global mail_html global mail_html
# Reporting section # Reporting section
print ('\nReporting...') print ('\nCheck if something to report...')
openDB() openDB()
# prepare variables for JSON construction # prepare variables for JSON construction
@@ -1453,7 +1483,7 @@ def email_reporting ():
# mail_html = mail_html.replace ('<PIALERT_YEAR>', VERSION_YEAR ) # mail_html = mail_html.replace ('<PIALERT_YEAR>', VERSION_YEAR )
# Compose Internet Section # Compose Internet Section
print (' Formating report...')
mail_section_Internet = False mail_section_Internet = False
mail_text_Internet = '' mail_text_Internet = ''
mail_html_Internet = '' mail_html_Internet = ''
@@ -1599,6 +1629,8 @@ def email_reporting ():
# Send Mail # Send Mail
if mail_section_Internet == True or mail_section_new_devices == True \ if mail_section_Internet == True or mail_section_new_devices == True \
or mail_section_devices_down == True or mail_section_events == True : or mail_section_devices_down == True or mail_section_events == True :
print ('\nChanges detected, sending reports...')
if REPORT_MAIL : if REPORT_MAIL :
print (' Sending report by email...') print (' Sending report by email...')
send_email (mail_text, mail_html) send_email (mail_text, mail_html)
@@ -1874,65 +1906,63 @@ def create_generic_device(client):
deviceName = 'PiAlert' deviceName = 'PiAlert'
deviceId = 'pialert' deviceId = 'pialert'
device_sensor(client, deviceId, deviceName, 'sensor', 'online', 'wifi-check') create_sensor(client, deviceId, deviceName, 'sensor', 'online', 'wifi-check')
device_sensor(client, deviceId, deviceName, 'sensor', 'down', 'wifi-cancel') create_sensor(client, deviceId, deviceName, 'sensor', 'down', 'wifi-cancel')
device_sensor(client, deviceId, deviceName, 'sensor', 'all', 'wifi') create_sensor(client, deviceId, deviceName, 'sensor', 'all', 'wifi')
device_sensor(client, deviceId, deviceName, 'sensor', 'archived', 'wifi-lock') create_sensor(client, deviceId, deviceName, 'sensor', 'archived', 'wifi-lock')
device_sensor(client, deviceId, deviceName, 'sensor', 'new', 'wifi-plus') create_sensor(client, deviceId, deviceName, 'sensor', 'new', 'wifi-plus')
device_sensor(client, deviceId, deviceName, 'sensor', 'unknown', 'wifi-alert') create_sensor(client, deviceId, deviceName, 'sensor', 'unknown', 'wifi-alert')
# #------------------------------------------------------------------------------- # #-------------------------------------------------------------------------------
# def create_sensor(client, deviceId, deviceName, sensorType, sensorName, icon): def create_sensor(client, deviceId, deviceName, sensorType, sensorName, icon):
# global mqtt_sensors
# new_sensor_config = sensor_config(deviceId, deviceName, sensorType, sensorName, icon) new_sensor_config = sensor_config(deviceId, deviceName, sensorType, sensorName, icon)
# if new_sensor_config in mqtt_sensors # check if config already in list and if not, add it, otherwise skip
global mqtt_sensors
# mqtt_sensors is_unique = True
# #------------------------------------------------------------------------------- for sensor in mqtt_sensors:
# class sensor_config: if sensor.hash == new_sensor_config.hash:
# def __init__(self, deviceId, deviceName, sensorType, sensorName, icon): is_unique = False
# self.deviceId = deviceId break
# self.deviceName = deviceName
# self.sensorType = sensorType
# self.sensorName = sensorName
# self.icon = icon
# save if unique
if is_unique:
mqtt_sensors.append(new_sensor_config)
publish_sensor(client, new_sensor_config)
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
class device_sensor: class sensor_config:
def __init__(self, client, deviceId, deviceName, sensorType, sensorName, icon): def __init__(self, deviceId, deviceName, sensorType, sensorName, icon):
self.deviceId = deviceId self.deviceId = deviceId
self.deviceName = deviceName self.deviceName = deviceName
self.sensorType = sensorType self.sensorType = sensorType
self.sensorName = sensorName self.sensorName = sensorName
self.icon = icon self.icon = icon
self.hash = str(hash(str(deviceId) + str(deviceName)+ str(sensorType)+ str(sensorName)+ str(icon)))
global mqtt_sensors #-------------------------------------------------------------------------------
def publish_sensor(client, sensorConf):
if (self in mqtt_sensors) == False:
mqtt_sensors.append(self)
message = '{ \ message = '{ \
"name":"'+ deviceName +' '+sensorName+'", \ "name":"'+ sensorConf.deviceName +' '+sensorConf.sensorName+'", \
"state_topic":"system-sensors/'+sensorType+'/'+deviceId+'/state", \ "state_topic":"system-sensors/'+sensorConf.sensorType+'/'+sensorConf.deviceId+'/state", \
"value_template":"{{value_json.'+sensorName+'}}", \ "value_template":"{{value_json.'+sensorConf.sensorName+'}}", \
"unique_id":"'+deviceId+'_sensor_'+sensorName+'", \ "unique_id":"'+sensorConf.deviceId+'_sensor_'+sensorConf.sensorName+'", \
"device": \ "device": \
{ \ { \
"identifiers": ["'+deviceId+'_sensor"], \ "identifiers": ["'+sensorConf.deviceId+'_sensor"], \
"manufacturer": "PiAlert", \ "manufacturer": "PiAlert", \
"name":"'+deviceName+'" \ "name":"'+sensorConf.deviceName+'" \
}, \ }, \
"icon":"mdi:'+icon+'" \ "icon":"mdi:'+sensorConf.icon+'" \
}' }'
topic='homeassistant/'+sensorType+'/'+deviceId+'/'+sensorName+'/config' topic='homeassistant/'+sensorConf.sensorType+'/'+sensorConf.deviceId+'/'+sensorConf.sensorName+'/config'
publish_mqtt(client, topic, message) publish_mqtt(client, topic, message)
@@ -1977,6 +2007,7 @@ def mqtt_start():
for column in columns: for column in columns:
payload += '"'+column+'": ' + str(row[column]) +',' payload += '"'+column+'": ' + str(row[column]) +','
# Publish (warap into {} and remove last ',' from above)
publish_mqtt(client, "system-sensors/sensor/pialert/state", publish_mqtt(client, "system-sensors/sensor/pialert/state",
'{ \ '{ \
'+ payload[:-1] +'\ '+ payload[:-1] +'\
@@ -1995,11 +2026,11 @@ def mqtt_start():
deviceId = 'mac_' + device["dev_MAC"].replace(" ", "").replace(":", "_").lower() deviceId = 'mac_' + device["dev_MAC"].replace(" ", "").replace(":", "_").lower()
deviceNameDisplay = re.sub('[^a-zA-Z0-9-_\s]', '', device["dev_Name"]) deviceNameDisplay = re.sub('[^a-zA-Z0-9-_\s]', '', device["dev_Name"])
device_sensor(client, deviceId, deviceNameDisplay, 'sensor', 'last_ip', 'ip-network') create_sensor(client, deviceId, deviceNameDisplay, 'sensor', 'last_ip', 'ip-network')
device_sensor(client, deviceId, deviceNameDisplay, 'binary_sensor', 'is_present', 'wifi') create_sensor(client, deviceId, deviceNameDisplay, 'binary_sensor', 'is_present', 'wifi')
device_sensor(client, deviceId, deviceNameDisplay, 'sensor', 'mac_address', 'folder-key-network') create_sensor(client, deviceId, deviceNameDisplay, 'sensor', 'mac_address', 'folder-key-network')
device_sensor(client, deviceId, deviceNameDisplay, 'sensor', 'is_new', 'bell-alert-outline') create_sensor(client, deviceId, deviceNameDisplay, 'sensor', 'is_new', 'bell-alert-outline')
device_sensor(client, deviceId, deviceNameDisplay, 'sensor', 'vendor', 'cog') create_sensor(client, deviceId, deviceNameDisplay, 'sensor', 'vendor', 'cog')
# update device sensors in home assistant # update device sensors in home assistant
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
+1
View File
@@ -15,6 +15,7 @@ services:
# comment out below 2 lines, they are only for development purposes # comment out below 2 lines, they are only for development purposes
- ${DEV_LOCATION}/back/pialert.py:/home/pi/pialert/back/pialert.py - ${DEV_LOCATION}/back/pialert.py:/home/pi/pialert/back/pialert.py
- ${DEV_LOCATION}/front:/home/pi/pialert/front - ${DEV_LOCATION}/front:/home/pi/pialert/front
- ${DEV_LOCATION}/back/update_vendors.sh:/home/pi/pialert/back/update_vendors.sh
environment: environment:
- TZ=${TZ} - TZ=${TZ}
- PORT=${PORT} - PORT=${PORT}
Regular → Executable
View File
Regular → Executable
+2 -3
View File
@@ -6,10 +6,9 @@
# 🐳 A docker image for Pi.Alert # 🐳 A docker image for Pi.Alert
🥇 Pi.Alert credit goes to [pucherot/Pi.Alert](https://github.com/pucherot/Pi.Alert) <br/> 🐳 Docker hub: [jokobsk/Pi.Alert](https://registry.hub.docker.com/r/jokobsk/pi.alert) <br/>
🐳 Docker Image: [jokobsk/Pi.Alert](https://registry.hub.docker.com/r/jokobsk/pi.alert) <br/>
📄 [Dockerfile](https://github.com/jokob-sk/Pi.Alert/blob/main/Dockerfile) <br/> 📄 [Dockerfile](https://github.com/jokob-sk/Pi.Alert/blob/main/Dockerfile) <br/>
📚 [Dockerfile instructions](https://github.com/jokob-sk/Pi.Alert/blob/main//dockerfiles/README.md) 📚 [Docker instructions](https://github.com/jokob-sk/Pi.Alert/blob/main//dockerfiles/README.md)
Big thanks to <a href="https://github.com/Macleykun">@Macleykun</a> for help and tips&tricks for Dockerfile(s): Big thanks to <a href="https://github.com/Macleykun">@Macleykun</a> for help and tips&tricks for Dockerfile(s):
-1
View File
@@ -15,6 +15,5 @@ chown -R www-data:www-data /home/pi/pialert/db/pialert.db
/etc/init.d/php7.4-fpm start /etc/init.d/php7.4-fpm start
/etc/init.d/nginx start /etc/init.d/nginx start
#cron -f
python /home/pi/pialert/back/pialert.py > /home/pi/pialert/log/pialert.log 2>&1 python /home/pi/pialert/back/pialert.py > /home/pi/pialert/log/pialert.log 2>&1
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 253 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 244 KiB

After

Width:  |  Height:  |  Size: 244 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 258 KiB

After

Width:  |  Height:  |  Size: 258 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 200 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 198 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 290 KiB

After

Width:  |  Height:  |  Size: 290 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 250 KiB

After

Width:  |  Height:  |  Size: 250 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 551 KiB

After

Width:  |  Height:  |  Size: 551 KiB

Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 813 B

After

Width:  |  Height:  |  Size: 813 B

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Regular → Executable
View File
Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Regular → Executable
View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
Regular → Executable
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File

Some files were not shown because too many files have changed in this diff Show More