Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Add subcommand to install LaunchAgents wrapper for watch #890

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
20 changes: 20 additions & 0 deletions plextraktsync/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@ def subdl():
pass


@click.group()
def launchctl():
"""
Installs launchctl wrapper
"""
pass


@command()
@click.option(
"--pr",
Expand Down Expand Up @@ -286,12 +294,24 @@ def imdb_import():
pass


def launchctl_available():
import shutil

return shutil.which("launchctl") is not None


cli.add_command(bug_report)
cli.add_command(cache)
cli.add_command(clear_collections)
cli.add_command(imdb_import)
cli.add_command(info)
cli.add_command(inspect)
if launchctl_available():
cli.add_command(launchctl)
from .commands.launchctl import load, unload

launchctl.add_command(load)
launchctl.add_command(unload)
cli.add_command(login)
cli.add_command(plex_login)
if enable_self_update():
Expand Down
32 changes: 32 additions & 0 deletions plextraktsync/com.github.plextraktsync.watch.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.github.plextraktsync.watch</string>
<key>ProgramArguments</key>
<array>
<string>plextraktsync</string>
<string>watch</string>
</array>
<key>WorkingDirectory</key>
<string>/</string>
<key>LimitLoadToSessionType</key>
<string>Aqua</string>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I used aqua based on a old example. You are right that Background might be better.

Setting a nice level might be a good idea though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Send an example for nice level. perhaps using suggest code change feature:

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Bas-Man I can't see the suggestion on the web, but had a glimpse of it in the email. Did you delete it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@glensc the pending change request is on this pull request.

@Bas-Man please reply in the thread where the question was asked.

But, I don't see your changes, perhaps you forgot to publish review?

<key>RunAtLoad</key>
<true/>
<key>ExitTimeOut</key>
<integer>0</integer>
<key>ProcessType</key>
<string>Background</string>

<!--
Enable to see debug logs.
- https://stackoverflow.com/a/29926482/2314626
-->
<key>StandardErrorPath</key>
<string>/tmp/plextraktsync.err</string>
<key>StandardOutPath</key>
<string>/tmp/plextraktsync.out</string>
</dict>
</plist>
82 changes: 82 additions & 0 deletions plextraktsync/commands/launchctl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import click

from plextraktsync.decorators.cached_property import cached_property


class Plist:
plist_file = "com.github.plextraktsync.watch.plist"

def load(self, plist_path: str):
from os import system

system(f"launchctl load {plist_path}")

def unload(self, plist_path: str):
from os import system
from os.path import exists

# Skip if file does not exist.
if not exists(plist_path):
return
system(f"launchctl unload {plist_path}")

def create(self, plist_path: str):
from plextraktsync.util.packaging import program_path

with open(self.plist_default_path, encoding='utf-8') as f:
contents = "".join(f.readlines())

def encode(f):
return f'<string>{f}</string>'

program = "\n".join(map(encode, program_path().split(' ')))
contents = contents.replace('<string>plextraktsync</string>', program)
with open(plist_path, "w+") as fw:
fw.writelines(contents)

def remove(self, plist_path: str):
from os import unlink
from os.path import exists

# Skip if file does not exist.
if not exists(plist_path):
return
unlink(plist_path)

@cached_property
def plist_default_path(self):
from os.path import join

from plextraktsync.path import module_path

return join(module_path, self.plist_file)

@cached_property
def plist_path(self):
from os.path import expanduser

return expanduser(f'~/Library/LaunchAgents/{self.plist_file}')


@click.command()
def load():
"""
Load the service.
"""
p = Plist()
p.create(p.plist_path)
click.echo(f"Created: {p.plist_path}")
p.load(p.plist_path)
click.echo(f"Loaded: {p.plist_path}")


@click.command()
def unload():
"""
Unload the service.
"""
p = Plist()
p.unload(p.plist_path)
click.echo(f"Unloaded: {p.plist_path}")
p.remove(p.plist_path)
click.echo(f"Removed: {p.plist_path}")
1 change: 1 addition & 0 deletions plextraktsync/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def ensure_dir(directory):
config_dir = p.config_dir
log_dir = p.log_dir

module_path = p.module_path
default_config_file = p.default_config_file
config_file = p.config_file
config_yml = p.config_yml
Expand Down
11 changes: 11 additions & 0 deletions plextraktsync/util/packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ def pipx_installed(package: str):
return package


def program_path():
"""
Return path to currently executed script
"""
import sys

absdir = dirname(dirname(dirname(__file__)))

return f"env PYTHONPATH={absdir} {sys.executable} -m plextraktsync"


def program_name():
"""
Return current program name:
Expand Down