Skip to content

Commit

Permalink
[script.cabertoss] 1.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
bossanova808 committed Oct 30, 2024
1 parent 8aefd81 commit 20e6c8f
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 36 deletions.
17 changes: 11 additions & 6 deletions script.cabertoss/addon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.cabertoss" name="Caber Toss" version="1.0.0" provider-name="bossanova808">
<addon id="script.cabertoss" name="Caber Toss" version="1.0.1" provider-name="bossanova808">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.bossanova808" version="1.0.0"/>
Expand All @@ -14,16 +14,21 @@ A script to quickly toss your Kodi logs from your Kodi client machine to somewhe

When something unexpected or bad happens, just run this add-on to copy the latest Kodi logs to your chosen destination.

Even better, bind this to a remote button (use `Runscript(script.cabertoss)`) - so you can carry on with your relaxing and deal with the issue later (without having to wade through all the stuff you did after the issue happened!).
Even better, bind this to a remote button (use `Runscript(script.cabertoss)`) - so you can carry on with your relaxing at the time, and deal with the issue later (without having to wade through all the stuff you did after the issue happened!).
</description>
<platform>all</platform>
<license>GPL-3.0-only</license>
<website>https://github.com/bossanova808/script.cabertoss</website>
<source>https://github.com/bossanova808/script.cabertoss</source>
<forum />
<email />
<news>
v1.0.0 Initial release
<forum>https://forum.kodi.tv/showthread.php?tid=379304</forum>
<email>[email protected]</email>
<news>v1.0.1
- Improve compatibility with network shares
- Improve compatibility with Windows and *ELEC
- Add hostname to logs folder, helps if using with multiple systems
- Don't copy crashlogs older than three days
- Language improvements
- Add 'Working...' notification to make more responsive (copying larger log files can take a moment)
</news>
<assets>
<icon>resources/icon.png</icon>
Expand Down
10 changes: 9 additions & 1 deletion script.cabertoss/changelog.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
v1.0.1
- Improve compatibility with network shares
- Improve compatibility with Windows and *ELEC
- Add hostname to logs folder, helps if using with multiple systems
- Don't copy crashlogs older than three days
- Language improvements
- Add 'Working...' notification to make more responsive (copying larger log files can take a moment)

v1.0.0
Initial release
- Initial release


Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ msgstr "
msgctxt "#32029"
msgid "Something went wrong, (ironically) check your logs!"
msgstr "
msgctxt "#32030"
msgid "Working..."
msgstr "
64 changes: 38 additions & 26 deletions script.cabertoss/resources/lib/cabertoss.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
# -*- coding: utf-8 -*-
import os
from datetime import datetime
import re
from time import sleep
from datetime import datetime, timedelta
import socket

import xbmc
import xbmcvfs
from bossanova808.constants import *
from bossanova808.utilities import *
from bossanova808.logger import Logger
from bossanova808.notify import Notify
from resources.lib.store import Store


def clean_log(content):
"""
Remove username/password details from log file content
@param content:
@return:
"""
for pattern, repl in Store.replaces:
sanitised = re.sub(pattern, repl, content)
return sanitised
from resources.lib.clean import *


def gather_log_files():
Expand All @@ -36,37 +28,57 @@ def gather_log_files():
log_files.append(['oldlog', os.path.join(LOG_PATH, 'kodi.old.log')])

# Can we find a crashlog?
# @TODO - check support for CoreElec & add Android if possible...
# @TODO - add Android support if possible..?
crashlog_path = ''
items = []
filematch = None
if xbmc.getCondVisibility('system.platform.osx'):
Logger.info("System is OSX")
crashlog_path = os.path.join(os.path.expanduser('~'), 'Library/Logs/DiagnosticReports/')
filematch = 'Kodi'
elif xbmc.getCondVisibility('system.platform.ios'):
Logger.info("System is IOS")
crashlog_path = '/var/mobile/Library/Logs/CrashReporter/'
filematch = 'Kodi'
elif xbmc.getCondVisibility('system.platform.linux'):
Logger.info("System is Linux")
crashlog_path = os.path.expanduser('~') # not 100% accurate (crashlogs can be created in the dir kodi was started from as well)
filematch = 'kodi_crashlog'
elif xbmc.getCondVisibility('system.platform.windows'):
Logger.info("System is Windows")
crashlog_path = LOG_PATH
filematch = 'crashlog'
filematch = 'kodi_'
elif xbmc.getCondVisibility('system.platform.android'):
Logger.info("System is Android")
Logger.info(LANGUAGE(32023))

# If *ELEC, we can be more specific
if xbmc.getCondVisibility('System.HasAddon(service.coreelec.settings)') or xbmc.getCondVisibility('System.HasAddon(service.libreelec.settings)'):
Logger.info("System is *ELEC")
crashlog_path = LOG_PATH
filematch = 'kodi_crashlog_'

if crashlog_path and os.path.isdir(crashlog_path):
lastcrash = None
dirs, possible_crashlog_files = xbmcvfs.listdir(crashlog_path)
for item in possible_crashlog_files:
if filematch in item and os.path.isfile(os.path.join(crashlog_path, item)):
items.append(os.path.join(crashlog_path, item))
items.sort(key=lambda f: os.path.getmtime(f))
if not xbmc.getCondVisibility('system.platform.windows'):
lastcrash = [items[-1]]
else:
lastcrash = items[-2:]
item_with_path = os.path.join(crashlog_path, item)
if filematch in item and os.path.isfile(item_with_path):
if filematch in item:
# Don't bother with older crashlogs
three_days_ago = datetime.now() - timedelta(days=3)
if three_days_ago < datetime.fromtimestamp(os.path.getmtime(item_with_path)):
items.append(os.path.join(crashlog_path, item))

items.sort(key=lambda f: os.path.getmtime(f))
# Windows crashlogs are a dmp and stacktrace combo...
if xbmc.getCondVisibility('system.platform.windows'):
lastcrash = items[-2:]
else:
lastcrash = items[-1:]

if lastcrash:
# Logger.info(f"lastcrash {lastcrash}")
for crashfile in lastcrash:
log_files.append(['crashlog', crashfile])

Expand All @@ -88,7 +100,7 @@ def copy_log_files(log_files: []):
Notify.error(LANGUAGE(32025))
return

now_folder_name = 'Kodi_Logs_' + datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
now_folder_name = f"{socket.gethostname()}_Kodi_Logs_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}"
now_destination_path = os.path.join(Store.destination_path, now_folder_name)

try:
Expand All @@ -100,11 +112,11 @@ def copy_log_files(log_files: []):
with open(xbmcvfs.translatePath(file[1]), 'r', encoding='utf-8') as current:
content = current.read()
sanitised = clean_log(content)
with open(xbmcvfs.translatePath(os.path.join(now_destination_path,os.path.basename(file[1]))), 'w+', encoding='utf-8') as output:
with xbmcvfs.File(os.path.join(xbmcvfs.translatePath(now_destination_path),os.path.basename(file[1])), 'w') as output:
output.write(sanitised)
else:
Logger.info(f'Copying {file[0]} {file[1]}')
if not xbmcvfs.copy(file[1], os.path.join(now_destination_path,os.path.basename(file[1]))):
if not xbmcvfs.copy(file[1], os.path.join(now_destination_path, os.path.basename(file[1]))):
return False
return True

Expand All @@ -116,13 +128,13 @@ def copy_log_files(log_files: []):

# This is 'main'...
def run():

footprints()
Store.load_config_from_settings()

if not Store.destination_path:
Notify.error(LANGUAGE(32027))
else:
Notify.info(LANGUAGE(32030))
log_file_list = gather_log_files()
result = copy_log_files(log_file_list)
if result:
Expand Down
15 changes: 15 additions & 0 deletions script.cabertoss/resources/lib/clean.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import re


def clean_log(content):
"""
Remove username/password details from log file content
@param content:
@return:
"""
replaces = (('//.+?:.+?@', '//USER:PASSWORD@'), ('<user>.+?</user>', '<user>USER</user>'), ('<pass>.+?</pass>', '<pass>PASSWORD</pass>'),)

for pattern, repl in replaces:
sanitised = re.sub(pattern, repl, content)
return sanitised
5 changes: 3 additions & 2 deletions script.cabertoss/resources/lib/store.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from bossanova808.constants import *
from bossanova808.logger import Logger
from resources.lib.clean import *


class Store:
Expand All @@ -12,7 +13,6 @@ class Store:

# Static class variables, referred to elsewhere by Store.whatever
# https://docs.python.org/3/faq/programming.html#how-do-i-create-static-class-data-and-static-class-methods
replaces = (('//.+?:.+?@', '//USER:PASSWORD@'), ('<user>.+?</user>', '<user>USER</user>'), ('<pass>.+?</pass>', '<pass>PASSWORD</pass>'),)
destination_path = None

def __init__(self):
Expand All @@ -29,7 +29,8 @@ def load_config_from_settings():
"""
Logger.info("Loading configuration from settings")
Store.destination_path = ADDON.getSetting('log_path')
Logger.info(f'Logs will be tossed to: {Store.destination_path}')

Logger.info(f'Logs will be tossed to: {clean_log(Store.destination_path)}')



Expand Down
6 changes: 5 additions & 1 deletion script.cabertoss/resources/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
<level>0</level>
<default/>
<constraints>
<sources>
<source>files</source>
</sources>
<writable>true</writable>
<allowempty>true</allowempty>
</constraints>
<control type="button" format="path">
<heading>32026</heading>
<heading>32001</heading>
</control>
</setting>
</group>
Expand Down

0 comments on commit 20e6c8f

Please sign in to comment.