Skip to content

Commit

Permalink
Merge branch 'v0.6.1'
Browse files Browse the repository at this point in the history
# Conflicts:
#	app.py
#	setup.py
  • Loading branch information
Tusky committed Aug 13, 2018
2 parents 1719fa8 + cd105c9 commit 146258e
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 143 deletions.
4 changes: 2 additions & 2 deletions api/discord_presence.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ def connect(self):
else:
self._connected = True

def update_status(self, state: str, details: str, large_image: str):
def update_status(self, state: str, details: str, large_image: str, end: int = None):
"""
Updates the status of the Discord Rich Presence.
"""
if self._connected:
try:
self._client.update(state=state, details=details, large_image=large_image)
self._client.update(state=state, details=details, large_image=large_image, end=end)
except pypresence.exceptions.InvalidID as e:
self._connected = False
ErrorHandler(e.args[0])
18 changes: 12 additions & 6 deletions api/kodi.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
from json import JSONDecodeError

import requests
Expand All @@ -6,8 +7,8 @@


class Kodi:
current_time = [0, 0, 0]
total_time = [0, 0, 0]
remaining_time = None
end_time = None
title = None
year = None
playing = False
Expand All @@ -24,8 +25,8 @@ def set_default(self):
"""
Sets the default values, in case there is an error.
"""
self.current_time = [0, 0, 0]
self.total_time = [0, 0, 0]
self.remaining_time = None
self.end_time = None
self.title = None
self.year = None
self.playing = False
Expand Down Expand Up @@ -124,8 +125,13 @@ def update_stream_information(self):
if j['id'] == 'player':
current_time = j['result']['time']
total_time = j['result']['totaltime']
self.current_time = [current_time['hours'], current_time['minutes'], current_time['seconds']]
self.total_time = [total_time['hours'], total_time['minutes'], total_time['seconds']]
now = datetime.datetime.now()
self.end_time = int((now + datetime.timedelta(
hours=total_time['hours'] - current_time['hours'],
minutes=total_time['minutes'] - current_time['minutes'],
seconds=total_time['seconds'] - current_time['seconds']
)).timestamp())
self.remaining_time = datetime.timedelta(seconds=self.end_time - int(now.timestamp()))
self.playing = j['result']['speed'] == 1
elif j['id'] == 'video':
item = j['result']['item']
Expand Down
208 changes: 110 additions & 98 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,98 +1,110 @@
import subprocess
import time
from typing import TYPE_CHECKING

from api.discord_presence import DiscordPresence
from api.kodi import Kodi
from updater import Updater
from util.config import Configurations
from util.system_tray import SysTray
from util.web_interface import WebInterface

running = True
if TYPE_CHECKING:
pass


class App:
play_icon = '\u25B6'
pause_icon = '\u275A\u275A'
running = True
update_rate = 1

def __init__(self, configuration):
self._config = configuration

def stop(self):
"""
Stop the application from running.
"""
self.running = False

def get_kodi_connection(self):
"""
Returns a new Kodi connection with recent configurations.
:return: new Kodi instance
:rtype: Kodi
"""
return Kodi(self._config.kodi_ip, self._config.kodi_port, self._config.kodi_username,
self._config.kodi_password)

def update_discord(self, discord: DiscordPresence, play_info: dict):
"""
Updates the Discord Rich Presence display.
:param discord: Discord connection.
:type discord: DiscordPresence
:param play_info: Information about the movie/show.
:type play_info: dict
"""
if play_info.get('title') is not None:
discord.connect()
icon = '{icon}'.format(icon=self.play_icon if play_info['playing'] else self.pause_icon)
time_format = '{time[0]}:{time[1]:02d}:{time[2]:02d}'
formatted_time = time_format.format(time=play_info['current_time'])
formatted_total_time = time_format.format(time=play_info['total_time'])
discord.update_status(details='{title}'.format(**play_info), large_image=play_info['type'],
state='{icon} {time}/{total_time}'.format(icon=icon, time=formatted_time,
total_time=formatted_total_time))
else:
discord.disconnect()

def run(self):
"""
Main running thread.
"""
discord = DiscordPresence(self._config.client_id)
kodi = self.get_kodi_connection()
while self.running:
time.sleep(self.update_rate)
if config.new_settings:
kodi = self.get_kodi_connection()
config.new_settings = False
elif self.update_rate > 1:
kodi = self.get_kodi_connection() # refresh settings, since it was put on timeout
kodi_info = kodi.get_currently_playing_item()
if not kodi_info['failed_connection']:
self.update_rate = 1
self.update_discord(discord, kodi_info)
else:
self.update_rate = 30


if __name__ == '__main__':
updater = Updater()
if updater.is_there_an_update():
try:
subprocess.Popen(['KoDiscord-updater.exe'], creationflags=subprocess.CREATE_NEW_CONSOLE)
except FileNotFoundError:
pass
else:
config = Configurations()
kodiscord = App(config)
sys_tray = SysTray(kodiscord, config)
sys_tray.start()
web = WebInterface(config)
web.start()
kodiscord.run()
import json
import subprocess
import time
from typing import TYPE_CHECKING

from api.discord_presence import DiscordPresence
from api.kodi import Kodi
from updater import Updater
from util.config import Configurations
from util.system_tray import SysTray
from util.web_interface import WebInterface

running = True
if TYPE_CHECKING:
import datetime


class App:
play_icon = '\u25B6'
pause_icon = '\u275A\u275A'
running = True
update_rate = 1
last_state = '{}'

def __init__(self, configuration):
self._config = configuration

def stop(self):
"""
Stop the application from running.
"""
self.running = False

def get_kodi_connection(self):
"""
Returns a new Kodi connection with recent configurations.
:return: new Kodi instance
:rtype: Kodi
"""
return Kodi(self._config.kodi_ip, self._config.kodi_port, self._config.kodi_username,
self._config.kodi_password)

def update_discord(self, discord: DiscordPresence, play_info: dict, remaining_time: 'datetime.timedelta' = None):
"""
Updates the Discord Rich Presence display.
:param remaining_time: The remaining time timedelta if paused.
:type remaining_time: datetime.timedelta
:param discord: Discord connection.
:type discord: DiscordPresence
:param play_info: Information about the movie/show.
:type play_info: dict
"""
if play_info.get('title') is not None:
discord.connect()
if play_info['playing']:
icon = self.play_icon
state = None
end = play_info['end_time']
else:
icon = self.pause_icon
state = '{time_remaining} left'.format(icon=icon, time_remaining=time.strftime('%H:%M:%S', time.gmtime(
remaining_time.seconds
)))
end = None
discord.update_status(details='{icon} {title}'.format(icon=icon, **play_info),
large_image=play_info['type'],
state=state, end=end)
else:
discord.disconnect()

def run(self):
"""
Main running thread.
"""
discord = DiscordPresence(self._config.client_id)
kodi = self.get_kodi_connection()
while self.running:
time.sleep(self.update_rate)
if config.new_settings:
kodi = self.get_kodi_connection()
config.new_settings = False
elif self.update_rate > 1:
kodi = self.get_kodi_connection() # refresh settings, since it was put on timeout
kodi_info = kodi.get_currently_playing_item()
if not kodi_info['failed_connection']:
remaining_time = kodi_info.pop('remaining_time')
kodi_info_json = json.dumps(kodi_info)
if self.last_state != kodi_info_json:
if json.loads(self.last_state).get('playing') != json.loads(kodi_info_json).get('playing'):
self.update_discord(discord, kodi_info, remaining_time)
self.last_state = kodi_info_json


if __name__ == '__main__':
updater = Updater()
if updater.is_there_an_update():
try:
subprocess.Popen(['KoDiscord-updater.exe'], creationflags=subprocess.CREATE_NEW_CONSOLE)
except FileNotFoundError:
pass
else:
config = Configurations()
kodiscord = App(config)
sys_tray = SysTray(kodiscord, config)
sys_tray.start()
web = WebInterface(config)
web.start()
kodiscord.run()
72 changes: 36 additions & 36 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
import os.path
from pathlib import Path

from cx_Freeze import setup, Executable

PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__))
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')

base = 'Win32GUI'

kodiscord = Executable('app.py', base=base, icon='kodi-icon.ico', targetName="KoDiscord.exe")
updater = Executable('updater.py', base=None, icon='kodi-icon.ico', targetName='KoDiscord-updater.exe')

executables = [kodiscord, updater]

packages = ['asyncio', 'idna', 'pypresence', 'requests', 'threading', 'typing', 'pystray', 'PIL', 'pkg_resources']
options = {
'build_exe': {
'packages': packages,
'include_files': ['kodi-icon.ico', 'LICENSE', 'config.json', 'web', 'version', 'updater.bat'],
'include_msvcr': True
},
}
version = Path('version').read_text().strip()

setup(
name="KoDiscord",
options=options,
version=version,
author='Richard Hajdu',
author_email='tuskone16@gmail.com',
url='https://github.com/Tusky/KoDiscord',
description='Sends your currently watched Movie or TV Show from Kodi to discord.',
executables=executables
)
import os.path
from pathlib import Path

from cx_Freeze import setup, Executable

PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__))
os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')

base = 'Win32GUI'

kodiscord = Executable('app.py', base=base, icon='kodi-icon.ico', targetName="KoDiscord.exe")
updater = Executable('updater.py', base=None, icon='kodi-icon.ico', targetName='KoDiscord-updater.exe')

executables = [kodiscord, updater]

packages = ['asyncio', 'idna', 'pypresence', 'requests', 'threading', 'typing', 'pystray', 'PIL', 'pkg_resources']
options = {
'build_exe': {
'packages': packages,
'include_files': ['kodi-icon.ico', 'LICENSE', 'web', 'version', 'updater.bat'],
'include_msvcr': True
},
}
version = Path('version').read_text().strip()

setup(
name="KoDiscord",
options=options,
version=version,
author='Richard Hajdu',
author_email='tuskone16@gmail.com',
url='https://github.com/Tusky/KoDiscord',
description='Sends your currently watched Movie or TV Show from Kodi to discord.',
executables=executables
)
3 changes: 3 additions & 0 deletions util/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from pathlib import Path

# Default settings to be used.
from util.system_tray import SysTray

DEFAULTS = {
"kodi_ip": "localhost",
"kodi_port": 8080,
Expand Down Expand Up @@ -48,6 +50,7 @@ def save_default_settings(self):
"""
Saves the default settings in case config.json file is missing.
"""
DEFAULTS['auto_start'] = Path(SysTray.get_shortcut_file()).exists()
self.save_settings(DEFAULTS)

def refresh_settings(self):
Expand Down
3 changes: 2 additions & 1 deletion util/system_tray.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ def reload_settings(self, *args):
"""
self._config.refresh_settings()

def get_shortcut_file(self):
@staticmethod
def get_shortcut_file():
return os.path.join("C:\\Users\\{username}\\AppData\\Roaming\\Microsoft"
"\\Windows\\Start Menu\\Programs\\Startup".format(username=os.getlogin()),
'KoDiscord.lnk')
Expand Down

0 comments on commit 146258e

Please sign in to comment.