Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions script.logviewer/addon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon id="script.logviewer" name="Log Viewer for Kodi" provider-name="i96751414" version="2.1.7+matrix.1">
<addon id="script.logviewer" name="Log Viewer for Kodi" provider-name="i96751414" version="2.1.8+matrix.1">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
</requires>
Expand All @@ -15,8 +15,10 @@
<source>https://github.com/i96751414/script.logviewer</source>
<summary lang="en_GB">View Kodi logfile directly on Kodi</summary>
<summary lang="pt_PT">Veja o log do Kodi directamente no Kodi</summary>
<summary lang="sv_SE">Visa Kodi-loggfilen direkt i Kodi</summary>
<description lang="en_GB">Tools to easily check and analyse Kodi log file.</description>
<description lang="pt_PT">Ferramenta para verificar e ler facilmente o log do Kodi.</description>
<description lang="sv_SE">Verktyg för att enkelt kontrollera och analysera Kodi-loggfiler.</description>
<platform>all</platform>
<news>
- Make text window skin independent
Expand All @@ -29,4 +31,4 @@
<screenshot>resources/images/screenshot-3.jpg</screenshot>
</assets>
</extension>
</addon>
</addon>
103 changes: 103 additions & 0 deletions script.logviewer/resources/language/resource.language.sv_se/strings.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Kodi Media Center language file
# Addon Name: Log Viewer for Kodi
# Addon id: scripy.logviewer
# Addon Provider: i96751414
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-08-06 12:03+0100\n"
"PO-Revision-Date: 2025-10-01 11:47+0200\n"
"Last-Translator: Daniel Nylander <github@danielnylander.se>\n"
"Language-Team: sv\n"
"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.7\n"

msgctxt "#30000"
msgid "Log Viewer for Kodi"
msgstr "Loggvisare för Kodi"

msgctxt "#30001"
msgid "Show Log"
msgstr "Visa logg"

msgctxt "#30002"
msgid "Show old Log"
msgstr "Visa gammal logg"

msgctxt "#30003"
msgid "Invalid number of lines. Showing full log"
msgstr "Ogiltigt antal rader. Visar hela loggen"

msgctxt "#30004"
msgid "Failed to open:"
msgstr "Misslyckades med att öppna:"

msgctxt "#30005"
msgid "Invert Log (most recent first)"
msgstr "Invertera loggen (nyaste först)"

msgctxt "#30006"
msgid "All"
msgstr "Alla"

msgctxt "#30007"
msgid "100"
msgstr "100"

msgctxt "#30008"
msgid "50"
msgstr "50"

msgctxt "#30009"
msgid "20"
msgstr "20"

msgctxt "#30010"
msgid "Number of lines to show"
msgstr "Antal rader som ska visas"

msgctxt "#30011"
msgid "Settings"
msgstr "Inställningar"

msgctxt "#30012"
msgid "General"
msgstr "Allmänt"

msgctxt "#30013"
msgid "Use custom text box"
msgstr "Använd anpassad textruta"

msgctxt "#30014"
msgid "Show log when an error occurs"
msgstr "Visa logg när ett fel inträffar"

msgctxt "#30015"
msgid "Upload Log file"
msgstr "Skicka upp loggfil"

msgctxt "#30016"
msgid "Error"
msgstr "Fel"

msgctxt "#30017"
msgid "Unable to locate log file..."
msgstr "Det går inte att hitta loggfilen..."

msgctxt "#30018"
msgid "Parse exceptions only"
msgstr "Tolka endast undantag"

msgctxt "#30019"
msgid "Enable HTTP server"
msgstr "Aktivera HTTP-server"

msgctxt "#30020"
msgid "Port"
msgstr "Port"
34 changes: 20 additions & 14 deletions script.logviewer/resources/lib/httpserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def tail_handler(ctx):
ctx.send_response_and_end(500)
return

offset = int(ctx.request.get("offset", 0))
offset = int(ctx.query.get("offset", 0))
reader = LogReader(ctx.log_path)
reader.set_offset(offset)
content = encode(reader.tail())
Expand All @@ -58,7 +58,7 @@ def favicon_handler(ctx):
shutil.copyfileobj(f, ctx.wfile)


class ServerHandler(BaseHTTPRequestHandler):
class HTTPRequestHandler(BaseHTTPRequestHandler, object):
protocol_version = "HTTP/1.1"
log_path = log_location(False)

Expand All @@ -68,23 +68,29 @@ class ServerHandler(BaseHTTPRequestHandler):
"/favicon.ico": favicon_handler,
}

# noinspection PyPep8Naming
# noinspection PyPep8Naming, PyAttributeOutsideInit
def do_GET(self):
self._response_started = False
try:
# noinspection PyAttributeOutsideInit
self.url = urlparse.urlsplit(self.path)
self.request = dict(urlparse.parse_qsl(self.url.query))
if self.url.path in self.get_routes:
self.get_routes[self.url.path](self)
self.query = dict(urlparse.parse_qsl(self.url.query))

handler = self.get_routes.get(self.url.path)
if handler is None:
self.send_response_and_end(404)
else:
self.send_response(404)
self.end_headers()
except BrokenPipeError as e:
raise e
handler(self)
except Exception as e:
logging.error(e)
self.send_response(500)
self.end_headers()
if self._response_started:
raise e
else:
logging.error(e, exc_info=True)
self.send_response_and_end(500)

def send_response(self, *args, **kwargs):
# noinspection PyAttributeOutsideInit
self._response_started = True
super(HTTPRequestHandler, self).send_response(*args, **kwargs)

def send_response_and_end(self, code, message=None):
self.send_response(code, message=message)
Expand Down
42 changes: 23 additions & 19 deletions script.logviewer/resources/lib/logviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def log_location(old=False):
return str_to_unicode(log_path)


log_entry_regex = re.compile(r"(?:\d{4}-\d{2}-\d{2} )?\d{2}:\d{2}:\d{2}")
log_entry_regex = re.compile(r"^(?:\d{4}-\d{2}-\d{2} )?\d{2}:\d{2}:\d{2}")
log_error_regex = re.compile(r" (ERROR|error)(?: <[^>]*>)?: ")
log_warning_regex = re.compile(r" (WARNING|warning)(?: <[^>]*>)?: ")
log_exception_regex = re.compile(log_error_regex.pattern + "EXCEPTION ")
Expand All @@ -93,30 +93,40 @@ def set_styles(content):
return content


def parse_errors(content, set_style=False, exceptions_only=False):
if content == "":
return ""
def preserve_indentation(line):
stripped = line.lstrip(" ")
return (len(line) - len(stripped)) * "\u00a0" + stripped

parsed_content = []
found_error = False

def parse_errors(content, exceptions_only=False):
pattern = log_exception_regex if exceptions_only else log_error_regex
found_error = False

for line in content.splitlines():
if log_entry_regex.match(line):
if pattern.search(line):
found_error = True
parsed_content.append(line)
yield line
else:
found_error = False
elif found_error:
parsed_content.append(line)
yield line

parsed_content = "\n".join(parsed_content)

def process_content_lines(lines, set_style=False):
content = "\n".join(preserve_indentation(line) for line in lines)

if set_style:
parsed_content = set_styles(parsed_content)
content = set_styles(content)

return content

return parsed_content

def get_errors(content, set_style=False, exceptions_only=False):
if not content:
return ""

return process_content_lines(parse_errors(content, exceptions_only=exceptions_only), set_style=set_style)


def get_content(old=False, invert=False, line_number=0, set_style=False):
Expand All @@ -126,15 +136,9 @@ def get_content(old=False, invert=False, line_number=0, set_style=False):
path = log_location(old)
if path is None:
xbmcgui.Dialog().ok(translate(30016), translate(30017))
return

f = LogReader(path)
content = f.read(invert, line_number)
return None

if set_style:
content = set_styles(content)

return content
return process_content_lines(LogReader(path).read_lines(invert, line_number), set_style=set_style)


def window(title, content, default=True, timeout=1):
Expand Down
10 changes: 5 additions & 5 deletions script.logviewer/resources/lib/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import xbmcgui

from resources.lib import logviewer, utils
from resources.lib.httpserver import ThreadedHTTPServer, ServerHandler
from resources.lib.httpserver import ThreadedHTTPServer, HTTPRequestHandler
from resources.lib.logreader import LogReader


Expand Down Expand Up @@ -80,7 +80,7 @@ def __init__(self, port):
super(HTTPServerRunner, self).__init__()

def run(self):
self._server = server = ThreadedHTTPServer(("", self._port), ServerHandler)
self._server = server = ThreadedHTTPServer(("", self._port), HTTPRequestHandler)
logging.debug("Server started at port %d", self._port)
logging.debug("Local IP is %s", xbmc.getIPAddress())
server.serve_forever()
Expand Down Expand Up @@ -120,9 +120,9 @@ def run(self):

while not self._monitor.waitForAbort(1) and self._running:
content = reader.tail()
parsed_errors = logviewer.parse_errors(content, set_style=True, exceptions_only=exceptions)
if parsed_errors:
logviewer.window(utils.ADDON_NAME, parsed_errors, default=utils.is_default_window())
errors = logviewer.get_errors(content, set_style=True, exceptions_only=exceptions)
if errors:
logviewer.window(utils.ADDON_NAME, errors, default=utils.is_default_window())

def stop(self):
self._running = False
Expand Down
Loading