feat(playout): migrate notify cli to click (#1519)

Fixes #1502

- replace notify option parser with click
- refactor call from liquidsoap to playout-notify

BREAKING CHANGE: the libretime-layout-notify log file in '/var/log/airtime/pypo-liquidsoap/notify.log' was removed and merged into the existing '/var/log/libretime/liquidsoap.log' log file.
This commit is contained in:
Jonas L 2022-01-17 10:51:32 +01:00 committed by GitHub
parent fe0b2c4a7a
commit 5364911922
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 130 additions and 230 deletions

View File

@ -1,7 +1,13 @@
def notify(m) def gateway(args)
command = "timeout --signal=KILL 45 libretime-playout-notify --media-id=#{m['schedule_table_id']} &" prefix = "timeout --signal=KILL 45"
command = "libretime-playout-notify #{args}"
suffix = "&"
log(command) log(command)
system(command) system("#{prefix} #{command} #{suffix}")
end
def notify(m)
gateway("media '#{m['schedule_table_id']}'")
end end
def notify_queue(m) def notify_queue(m)
@ -11,15 +17,13 @@ def notify_queue(m)
end end
def notify_stream(m) def notify_stream(m)
json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
#if a string has a single apostrophe in it, let's comment it out by ending the string before right before it
#escaping the apostrophe, and then starting a new string right after it. This is why we use 3 apostrophes.
json_str = string.replace(pattern="'",(fun (s) -> "'\''"), json_str)
command = "timeout --signal=KILL 45 libretime-playout-notify --webstream='#{json_str}' --media-id=#{!current_dyn_id} &"
if !current_dyn_id != "-1" then if !current_dyn_id != "-1" then
log(command) json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
system(command) #if a string has a single apostrophe in it, let's comment it out by ending the string before right before it
#escaping the apostrophe, and then starting a new string right after it. This is why we use 3 apostrophes.
json_str = string.replace(pattern="'",(fun (s) -> "'\''"), json_str)
gateway("webstream '#{!current_dyn_id}' '#{json_str}'")
end end
end end
@ -97,16 +101,12 @@ def output_to(output_type, type, bitrate, host, port, pass, mount_point, url, de
source = ref s source = ref s
def on_error(msg) def on_error(msg)
connected := "false" connected := "false"
command = "timeout --signal=KILL 45 libretime-playout-notify --error='#{msg}' --stream-id=#{stream} --time=#{!time} &" gateway("stream '#{stream}' '#{!time}' --error='#{msg}'")
system(command)
log(command)
5. 5.
end end
def on_connect() def on_connect()
connected := "true" connected := "true"
command = "timeout --signal=KILL 45 libretime-playout-notify --connect --stream-id=#{stream} --time=#{!time} &" gateway("stream '#{stream}' '#{!time}'")
system(command)
log(command)
end end
stereo = (channels == "stereo") stereo = (channels == "stereo")

View File

@ -217,9 +217,7 @@ def make_scheduled_play_unavailable()
end end
def update_source_status(sourcename, status) = def update_source_status(sourcename, status) =
command = "timeout --signal=KILL 45 libretime-playout-notify --source-name=#{sourcename} --source-status=#{status} &" gateway("live '#{sourcename}' '#{status}'")
system(command)
log(command)
end end
def live_dj_connect(header) = def live_dj_connect(header) =
@ -442,7 +440,4 @@ if s4_enable == true then
s4_connected, s4_description, s4_channels) s4_connected, s4_description, s4_channels)
end end
gateway("started")
command = "timeout --signal=KILL 45 libretime-playout-notify --liquidsoap-started &"
log(command)
system(command)

View File

@ -1,7 +1,13 @@
def notify(m) def gateway(args)
command = "timeout --signal=KILL 45 libretime-playout-notify --media-id=#{m['schedule_table_id']} &" prefix = "timeout --signal=KILL 45"
command = "libretime-playout-notify #{args}"
suffix = "&"
log(command) log(command)
system(command) system("#{prefix} #{command} #{suffix}")
end
def notify(m)
gateway("media '#{m['schedule_table_id']}'")
end end
def notify_queue(m) def notify_queue(m)
@ -11,15 +17,12 @@ def notify_queue(m)
end end
def notify_stream(m) def notify_stream(m)
json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
#if a string has a single apostrophe in it, let's comment it out by ending the string before right before it
#escaping the apostrophe, and then starting a new string right after it. This is why we use 3 apostrophes.
json_str = string.replace(pattern="'",(fun (s) -> "'\''"), json_str)
command = "timeout --signal=KILL 45 libretime-playout-notify --webstream='#{json_str}' --media-id=#{!current_dyn_id} &"
if !current_dyn_id != "-1" then if !current_dyn_id != "-1" then
log(command) json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
system(command) #if a string has a single apostrophe in it, let's comment it out by ending the string before right before it
#escaping the apostrophe, and then starting a new string right after it. This is why we use 3 apostrophes.
json_str = string.replace(pattern="'",(fun (s) -> "'\''"), json_str)
gateway("webstream '#{!current_dyn_id}' '#{json_str}'")
end end
end end
@ -97,16 +100,12 @@ def output_to(output_type, type, bitrate, host, port, pass, mount_point, url, de
source = ref s source = ref s
def on_error(msg) def on_error(msg)
connected := "false" connected := "false"
command = "timeout --signal=KILL 45 libretime-playout-notify --error='#{msg}' --stream-id=#{stream} --time=#{!time} &" gateway("stream '#{stream}' '#{!time}' --error='#{msg}'")
system(command)
log(command)
5. 5.
end end
def on_connect() def on_connect()
connected := "true" connected := "true"
command = "timeout --signal=KILL 45 libretime-playout-notify --connect --stream-id=#{stream} --time=#{!time} &" gateway("stream '#{stream}' '#{!time}'")
system(command)
log(command)
end end
stereo = (channels == "stereo") stereo = (channels == "stereo")

View File

@ -217,9 +217,7 @@ def make_scheduled_play_unavailable()
end end
def update_source_status(sourcename, status) = def update_source_status(sourcename, status) =
command = "timeout --signal=KILL 45 libretime-playout-notify --source-name=#{sourcename} --source-status=#{status} &" gateway("live '#{sourcename}' '#{status}'")
system(command)
log(command)
end end
def live_dj_connect(header) = def live_dj_connect(header) =
@ -457,6 +455,4 @@ if s4_enable == true then
end end
command = "timeout --signal=KILL 45 libretime-playout-notify --liquidsoap-started &" gateway("started")
log(command)
system(command)

View File

@ -1,9 +1,13 @@
def notify(m) def gateway(args)
command = "timeout --signal=KILL 45 libretime-playout-notify --media-id=#{m['schedule_table_id']} &" command = "timeout --signal=KILL 45 libretime-playout-notify #{args} &"
log(command) log(command)
system(command) system(command)
end end
def notify(m)
gateway("media '#{m['schedule_table_id']}'")
end
def notify_queue(m) def notify_queue(m)
f = !dynamic_metadata_callback f = !dynamic_metadata_callback
ignore(f(m)) ignore(f(m))
@ -11,15 +15,13 @@ def notify_queue(m)
end end
def notify_stream(m) def notify_stream(m)
json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
#if a string has a single apostrophe in it, let's comment it out by ending the string before right before it
#escaping the apostrophe, and then starting a new string right after it. This is why we use 3 apostrophes.
json_str = string.replace(pattern="'",(fun (s) -> "'\''"), json_str)
command = "timeout --signal=KILL 45 libretime-playout-notify --webstream='#{json_str}' --media-id=#{!current_dyn_id} &"
if !current_dyn_id != "-1" then if !current_dyn_id != "-1" then
log(command) json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
system(command) #if a string has a single apostrophe in it, let's comment it out by ending the string before right before it
#escaping the apostrophe, and then starting a new string right after it. This is why we use 3 apostrophes.
json_str = string.replace(pattern="'",(fun (s) -> "'\''"), json_str)
gateway("webstream '#{!current_dyn_id}' '#{json_str}'")
end end
end end
@ -88,16 +90,12 @@ def output_to(output_type, type, bitrate, host, port, pass, mount_point, url, de
source = ref s source = ref s
def on_error(msg) def on_error(msg)
connected := "false" connected := "false"
command = "timeout --signal=KILL 45 libretime-playout-notify --error='#{msg}' --stream-id=#{stream} --time=#{!time} &" gateway("stream '#{stream}' '#{!time}' --error='#{msg}'")
system(command)
log(command)
5. 5.
end end
def on_connect() def on_connect()
connected := "true" connected := "true"
command = "timeout --signal=KILL 45 libretime-playout-notify --connect --stream-id=#{stream} --time=#{!time} &" gateway("stream '#{stream}' '#{!time}'")
system(command)
log(command)
end end
stereo = (channels == "stereo") stereo = (channels == "stereo")

View File

@ -220,9 +220,7 @@ def make_scheduled_play_unavailable()
end end
def update_source_status(sourcename, status) = def update_source_status(sourcename, status) =
command = "timeout --signal=KILL 45 libretime-playout-notify --source-name=#{sourcename} --source-status=#{status} &" gateway("live '#{sourcename}' '#{status}'")
system(command)
log(command)
end end
def live_dj_connect(header) = def live_dj_connect(header) =
@ -460,6 +458,4 @@ if s4_enable == true then
end end
command = "timeout --signal=KILL 45 libretime-playout-notify --liquidsoap-started &" gateway("started")
log(command)
system(command)

View File

@ -12,176 +12,92 @@ Main case:
media id from it, and then calls back to the API to tell about it about it. media id from it, and then calls back to the API to tell about it about it.
""" """
import json
import sys
import traceback
from optparse import OptionParser
from pathlib import Path from pathlib import Path
from typing import Optional
# additional modules (should be checked) import click
from configobj import ConfigObj from libretime_api_client.version1 import AirtimeApiClient
from libretime_shared.cli import cli_logging_options
# custom imports from libretime_shared.logging import level_from_name, setup_logger
# from util import *
from libretime_api_client import version1 as api_client
from libretime_shared.logging import INFO, setup_logger
from loguru import logger from loguru import logger
# TODO: Get log settings from cli/env variables
DEFAULT_LOG_LEVEL = INFO
DEFAULT_LOG_FILEPATH = Path("/var/log/libretime/playout-notify.log")
setup_logger(DEFAULT_LOG_LEVEL, DEFAULT_LOG_FILEPATH) def api_client():
return AirtimeApiClient(logger=logger)
# help screeen / info
usage = "%prog [options]" + " - notification gateway"
parser = OptionParser(usage=usage)
# Options
parser.add_option(
"-d",
"--data",
help="Pass JSON data from Liquidsoap into this script.",
metavar="data",
)
parser.add_option(
"-m",
"--media-id",
help="ID of the file that is currently playing.",
metavar="media_id",
)
parser.add_option(
"-e",
"--error",
action="store",
dest="error",
type="string",
help="Liquidsoap error msg.",
metavar="error_msg",
)
parser.add_option("-s", "--stream-id", help="ID stream", metavar="stream_id")
parser.add_option(
"-c",
"--connect",
help="Liquidsoap connected",
action="store_true",
metavar="connect",
)
parser.add_option(
"-t",
"--time",
help="Liquidsoap boot up time",
action="store",
dest="time",
metavar="time",
type="string",
)
parser.add_option(
"-x", "--source-name", help="source connection name", metavar="source_name"
)
parser.add_option(
"-y", "--source-status", help="source connection status", metavar="source_status"
)
parser.add_option(
"-w",
"--webstream",
help="JSON metadata associated with webstream",
metavar="json_data",
)
parser.add_option(
"-n",
"--liquidsoap-started",
help="notify liquidsoap started",
metavar="json_data",
action="store_true",
default=False,
)
# parse options @click.group()
(options, args) = parser.parse_args() @cli_logging_options
def cli(log_level: str, log_filepath: Optional[Path]):
# need to wait for Python 2.7 for this.. """
# logging.captureWarnings(True) A gateway between Liquidsoap and the API.
"""
# loading config file setup_logger(level_from_name(log_level), log_filepath)
try:
config = ConfigObj("/etc/airtime/airtime.conf")
except Exception as e:
logger.error("Error loading config file: %s", e)
sys.exit()
class Notify: @cli.command()
def __init__(self): @click.argument("media_id")
self.api_client = api_client.AirtimeApiClient(logger=logger) def media(media_id):
"""
Notify currently playing media.
def notify_liquidsoap_started(self): Replaces: notify --media-id=#{m['schedule_table_id']}
logger.debug("Notifying server that Liquidsoap has started") """
self.api_client.notify_liquidsoap_started() logger.info(f"Sending currently playing media id '{media_id}'")
api_client().notify_media_item_start_playing(media_id)
def notify_media_start_playing(self, media_id):
logger.debug("#################################################")
logger.debug("# Calling server to update about what's playing #")
logger.debug("#################################################")
response = self.api_client.notify_media_item_start_playing(media_id)
logger.debug("Response: " + json.dumps(response))
# @pram time: time that LS started
def notify_liquidsoap_status(self, msg, stream_id, time):
logger.info("#################################################")
logger.info("# Calling server to update liquidsoap status #")
logger.info("#################################################")
logger.info("msg = " + str(msg))
self.api_client.notify_liquidsoap_status(msg, stream_id, time)
def notify_source_status(self, source_name, status):
logger.debug("#################################################")
logger.debug("# Calling server to update source status #")
logger.debug("#################################################")
logger.debug("msg = " + str(source_name) + " : " + str(status))
response = self.api_client.notify_source_status(source_name, status)
logger.debug("Response: " + json.dumps(response))
def notify_webstream_data(self, data, media_id):
logger.debug("#################################################")
logger.debug("# Calling server to update webstream data #")
logger.debug("#################################################")
self.api_client.notify_webstream_data(data, media_id)
def run_with_options(self, options):
if options.error and options.stream_id:
self.notify_liquidsoap_status(
options.error, options.stream_id, options.time
)
elif options.connect and options.stream_id:
self.notify_liquidsoap_status("OK", options.stream_id, options.time)
elif options.source_name and options.source_status:
self.notify_source_status(options.source_name, options.source_status)
elif options.webstream:
self.notify_webstream_data(options.webstream, options.media_id)
elif options.media_id:
self.notify_media_start_playing(options.media_id)
elif options.liquidsoap_started:
self.notify_liquidsoap_started()
else:
logger.debug(
"Unrecognized option in options({}). Doing nothing".format(options)
)
def run(): @cli.command()
print() @click.argument("media_id")
print("#########################################") @click.argument("data")
print("# *** pypo *** #") def webstream(media_id, data):
print("# pypo notification gateway #") """
print("#########################################") Notify currently playing webstream.
# initialize Replaces: notify --webstream='#{json_str}' --media-id=#{!current_dyn_id}
try: """
n = Notify() logger.info(f"Sending currently playing webstream '{media_id}' data '{data}'")
n.run_with_options(options) api_client().notify_webstream_data(data, media_id)
except Exception as e:
print(traceback.format_exc())
@cli.command()
@click.argument("name")
@click.argument("status")
def live(name, status):
"""
Notify currently playing live input.
Replaces: notify --source-name=#{sourcename} --source-status=#{status}
"""
logger.info(f"Sending currently playing live source '{name}' status '{status}'")
api_client().notify_source_status(name, status)
@cli.command()
@click.argument("stream_id")
@click.argument("time")
@click.option("--error", help="Error message if any occurred.")
def stream(stream_id, time, error):
"""
Notify about output stream status.
Replaces: notify --error='#{msg}' --stream-id=#{stream} --time=#{!time}
Replaces: notify --connect --stream-id=#{stream} --time=#{!time}
"""
status = "OK"
if error is not None:
status = error
logger.info(f"Sending output stream '{stream_id}' status '{status}'")
api_client().notify_liquidsoap_status(status, stream_id, time)
@cli.command()
def started():
"""
Notify liquidsoap startup status.
Replaces: notify --liquidsoap-started
"""
logger.debug("Notifying server that Liquidsoap has started")
api_client().notify_liquidsoap_started()

View File

@ -29,7 +29,7 @@ setup(
"console_scripts": [ "console_scripts": [
"libretime-playout=libretime_playout.main:cli", "libretime-playout=libretime_playout.main:cli",
"libretime-liquidsoap=libretime_liquidsoap.main:cli", "libretime-liquidsoap=libretime_liquidsoap.main:cli",
"libretime-playout-notify=libretime_playout.notify.main:run", "libretime-playout-notify=libretime_playout.notify.main:cli",
] ]
}, },
python_requires=">=3.6", python_requires=">=3.6",