Skip to content

Commit

Permalink
[script.cabertoss] 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
bossanova808 committed Oct 10, 2024
1 parent a0dccdb commit dcba6a0
Show file tree
Hide file tree
Showing 10 changed files with 979 additions and 0 deletions.
674 changes: 674 additions & 0 deletions script.cabertoss/LICENSE.txt

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions script.cabertoss/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

Caber Toss for Kodi
===================================

_script.cabertoss_

[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/bossanova808)

A script to quickly toss your Kodi logs from your Kodi client machine to somewhere more handy, for easier review.

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!).








32 changes: 32 additions & 0 deletions script.cabertoss/addon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.cabertoss" name="Caber Toss" version="1.0.0" provider-name="bossanova808">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.bossanova808" version="1.0.0"/>
</requires>
<extension point="xbmc.python.script" library="default.py">
<provides>executable</provides>
</extension>
<extension point="xbmc.addon.metadata">
<summary lang="en_GB">Provides an easy way to save Kodi log files, at a particular moment, to a chosen destination.</summary>
<description lang="en_GB">
A script to quickly toss your Kodi logs from your Kodi client machine to somewhere more handy, for easier review.

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!).
</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
</news>
<assets>
<icon>resources/icon.png</icon>
</assets>
</extension>
</addon>
4 changes: 4 additions & 0 deletions script.cabertoss/changelog.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
v1.0.0
Initial release


8 changes: 8 additions & 0 deletions script.cabertoss/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-

from bossanova808 import exception_logger
from resources.lib import cabertoss

if __name__ == "__main__":
with exception_logger.log_exception():
cabertoss.run()
Binary file added script.cabertoss/resources/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Kodi Media Center language file
msgid ""
msgstr ""
"Project-Id-Version: XBMC-Addons\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2020-04-26 11:43+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: en\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"

msgctxt "#32000"
msgid "General"
msgstr ""

msgctxt "#32001"
msgid "Toss log files to..."
msgstr ""

msgctxt "#32023"
msgid "Windows crashlogs are not supported, sorry"
msgstr ""

msgctxt "#32024"
msgid "Android crashlogs are not supported, sorry"
msgstr "
msgctxt "#32025"
msgid "No log files found to copy ?!"
msgstr "
msgctxt "#32026"
msgid "Error copying logs"
msgstr "
msgctxt "#32027"
msgid "No destination path set in the addon settings!"
msgstr "
msgctxt "#32028"
msgid "Log files copied"
msgstr "
msgctxt "#32029"
msgid "Something went wrong, (ironically) check your logs!"
msgstr "
133 changes: 133 additions & 0 deletions script.cabertoss/resources/lib/cabertoss.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# -*- coding: utf-8 -*-
import os
from datetime import datetime
import re
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


def gather_log_files():
"""
Gather a list of the standard Kodi log files (Kodi.log, Kodi.old.log) and the latest crash log, if there is one.
@return: list of log files in form [type, path], where type is log, oldlog, or crashlog
"""

# Basic log files
log_files = [['log', os.path.join(LOG_PATH, 'kodi.log')]]
if os.path.exists(os.path.join(LOG_PATH, 'kodi.old.log')):
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...
crashlog_path = ''
items = []
filematch = None
if xbmc.getCondVisibility('system.platform.osx'):
crashlog_path = os.path.join(os.path.expanduser('~'), 'Library/Logs/DiagnosticReports/')
filematch = 'Kodi'
elif xbmc.getCondVisibility('system.platform.ios'):
crashlog_path = '/var/mobile/Library/Logs/CrashReporter/'
filematch = 'Kodi'
elif xbmc.getCondVisibility('system.platform.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'):
crashlog_path = LOG_PATH
filematch = 'crashlog'
elif xbmc.getCondVisibility('system.platform.android'):
Logger.info(LANGUAGE(32023))

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:]
if lastcrash:
for crashfile in lastcrash:
log_files.append(['crashlog', crashfile])

Logger.info("Found these log files to copy:")
Logger.info(log_files)

return log_files


def copy_log_files(log_files: []):
"""
Actually copy the log files to the path in the addon settings
@param log_files: [] list of log files to copy
@return: None
"""
if not log_files:
Logger.error(LANGUAGE(32025))
Notify.error(LANGUAGE(32025))
return

now_folder_name = 'Kodi_Logs_' + datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
now_destination_path = os.path.join(Store.destination_path, now_folder_name)

try:
Logger.info(f'Making destination folder: {now_destination_path}')
xbmcvfs.mkdir(now_destination_path)
for file in log_files:
if file[0] in ['log', 'oldlog']:
Logger.info(f'Copying sanitised {file[0]} {file[1]}')
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:
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]))):
return False
return True

except Exception as e:
Logger.error(LANGUAGE(32026) + f": {str(e)}")
Notify.error(LANGUAGE(32026) + f": {str(e)}")
return False


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

footprints()
Store.load_config_from_settings()

if not Store.destination_path:
Notify.error(LANGUAGE(32027))
else:
log_file_list = gather_log_files()
result = copy_log_files(log_file_list)
if result:
Notify.info(LANGUAGE(32028) + f": {len(log_file_list)}")
else:
Notify.info(LANGUAGE(32029))
# and, we're done...
footprints(startup=False)
37 changes: 37 additions & 0 deletions script.cabertoss/resources/lib/store.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from bossanova808.constants import *
from bossanova808.logger import Logger


class Store:
"""
Helper class to read in and store the addon settings, and to provide a centralised store
from resources.lib.store import Store
log(f'{Store.whatever}')
"""

# 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):
"""
Load in the addon settings and do basic initialisation stuff
"""
Store.load_config_from_settings()

@staticmethod
def load_config_from_settings():
"""
Load in the addon settings, at start or reload them if they have been changed
Log each setting as it is loaded
"""
Logger.info("Loading configuration from settings")
Store.destination_path = ADDON.getSetting('log_path')
Logger.info(f'Logs will be tossed to: {Store.destination_path}')





20 changes: 20 additions & 0 deletions script.cabertoss/resources/settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" ?>
<settings version="1">
<section id="script.cabertoss">
<category help="" id="cabertoss" label="32000">
<group id="1">
<setting id="log_path" type="path" label="32001" help="">
<level>0</level>
<default/>
<constraints>
<allowempty>true</allowempty>
</constraints>
<control type="button" format="path">
<heading>32026</heading>
</control>
</setting>
</group>
</category>
</section>
</settings>

0 comments on commit dcba6a0

Please sign in to comment.