]> kaliko git repositories - mpd-sima.git/commitdiff
Add blocklist commands, remove simadb_cli
authorkaliko <kaliko@azylum.org>
Sun, 9 May 2021 09:48:57 +0000 (11:48 +0200)
committerkaliko <kaliko@azylum.org>
Sun, 9 May 2021 09:53:24 +0000 (11:53 +0200)
Move all command to a subparser

data/man/simadb_cli.1 [deleted file]
data/man/simadb_cli.1.xml [deleted file]
setup.py
sima/launch.py
sima/lib/simadb.py
sima/utils/blcli.py [new file with mode: 0644]
sima/utils/startopt.py
simadb_cli [deleted file]

diff --git a/data/man/simadb_cli.1 b/data/man/simadb_cli.1
deleted file mode 100644 (file)
index cc893d8..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-'\" t
-.\"     Title: simadb_cli
-.\"    Author: kaliko <kaliko@azylum.org>
-.\" Generator: DocBook XSL Stylesheets v1.79.2 <http://docbook.sf.net/>
-.\"      Date: 04/19/2021
-.\"    Manual: mpd-sima 0.17.0 User Manual
-.\"    Source: mpd-sima
-.\"  Language: English
-.\"
-.TH "SIMADB_CLI" "1" "04/19/2021" "mpd-sima" "mpd-sima 0.17.0 User Manual"
-.\" -----------------------------------------------------------------
-.\" * Define some portability stuff
-.\" -----------------------------------------------------------------
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.\" http://bugs.debian.org/507673
-.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
-.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-.ie \n(.g .ds Aq \(aq
-.el       .ds Aq '
-.\" -----------------------------------------------------------------
-.\" * set default formatting
-.\" -----------------------------------------------------------------
-.\" disable hyphenation
-.nh
-.\" disable justification (adjust text to left margin only)
-.ad l
-.\" -----------------------------------------------------------------
-.\" * MAIN CONTENT STARTS HERE *
-.\" -----------------------------------------------------------------
-.SH "NAME"
-simadb_cli \- simadb_cli is a command line interface editor for the sima user DB\&.
-.SH "SYNOPSIS"
-.HP \w'\fBsimadb_cli\fR\ 'u
-\fBsimadb_cli\fR \fB\-\-remove_artist=\fR\fIartist\fR [\fB\-\-dbfile=\fR\fIdb_file\fR] [\fB\-\-reciprocal\fR]
-.HP \w'\fBsimadb_cli\fR\ 'u
-\fBsimadb_cli\fR \fB\-\-purge_hist\fR [\fB\-\-dbfile=\fR\fIdb_file\fR]
-.HP \w'\fBsimadb_cli\fR\ 'u
-\fBsimadb_cli\fR \fB\-\-view_all\fR [\fB\-\-dbfile=\fR\fIdb_file\fR]
-.HP \w'\fBsimadb_cli\fR\ 'u
-\fBsimadb_cli\fR {\fB\-\-bl_curr_trk\fR | \fB\-\-bl_curr_art\fR | \fB\-\-bl_curr_alb\fR | \fB\-\-bl_art=\fR\fIartist_name\fR} [\fB\-\-dbfile=\fR\fIdb_file\fR] [\fB\-\-host=\fR\fImpd_host\fR] [\fB\-\-port=\fR\fImpd_port\fR]
-.HP \w'\fBsimadb_cli\fR\ 'u
-\fBsimadb_cli\fR \fB\-\-remove_bl=\fR\fIrow_id\fR [\fB\-\-dbfile=\fR\fIdb_file\fR]
-.HP \w'\fBsimadb_cli\fR\ 'u
-\fBsimadb_cli\fR \fB\-\-view_bl\fR [\fB\-\-dbfile=\fR\fIdb_file\fR]
-.HP \w'\fBsimadb_cli\fR\ 'u
-\fBsimadb_cli\fR {{\fB\-h\fR\ |\ \fB\-\-help\fR} | \fB\-\-version\fR}
-.SH "DESCRIPTION"
-.PP
-This manual page documents briefly the
-\fBsimadb_cli\fR
-commands\&.
-.PP
-simadb_cli is a command line interface to get and edit users blacklist database used with MPD_sima\&. The default database file (see
-the section called \(lqFILES\(rq) can be overridden if you want\&.
-.SH "EXAMPLE"
-.SS "Black list edition"
-.PP
-\fIAdding to black list\&.\fR
-You can add a single track, an album or an artist to the black list\&. The element to black list is chosen from the currently playing track\&. Use
-\fB\-\-bl_curr_trk\fR
-to prevent simadb_cli to queue this track,
-\fB\-\-bl_curr_alb\fR
-or
-\fB\-\-bl_curr_art\fR
-respectively for the album and the artist\&.
-.PP
-Remember you need access to your MPD server to retrieve information to black list\&. Defaults are localhost:6600 or found in environment variables but you may set it up from command line:
-.PP
-\fBsimadb_cli \-\-bl_curr_art \-S mympd\&.example\&.org\fR
-.PP
-\fITo black list a specific artist\fR
-(not currently playing) you can use
-\fB\-\-bl_ar="Artist name to black list"\fR\&.
-.SH "OPTIONS"
-.PP
-The program follows the usual GNU command line syntax, with long options starting with two dashes ("\-")\&. A summary of options is included below\&.
-.PP
-\fB\-h\fR, \fB\-\-help\fR
-.RS 4
-Print help and exit\&.
-.RE
-.PP
-\fB\-\-version\fR
-.RS 4
-Print version and exit\&.
-.RE
-.PP
-\fB\-\-bl_art=\fR\fB\fIartist_name\fR\fR
-.RS 4
-Use to black list
-\fIartist_name\fR\&. simadb_cli is checking
-\fIartist_name\fR
-is actually in MPD music library (cf
-\fB\-S\fR
-and
-\fB\-P\fR
-options to set MPD host/address if necessary)\&.
-.sp
-If
-\fIartist_name\fR
-is not found the script print out a list of matching artists\&.
-.RE
-.PP
-\fB\-\-bl_curr_trk\fR | \fB\-\-bl_curr_art\fR | \fB\-\-bl_curr_alb\fR
-.RS 4
-Use to black list the currently playing track|artist|album\&. You need access to your MPD server, use
-\fB\-S\fR
-and
-\fB\-P\fR
-to set MPD host/address if necessary\&.
-.RE
-.PP
-\fB\-d \fR\fB\fIdb_file\fR\fR, \fB\-\-dbfile=\fR\fB\fIdb_file\fR\fR
-.RS 4
-Use the specific file
-\fIdb_file\fR
-as database\&.
-.br
-Default is too use
-\fBXDG_DATA_HOME\fR
-(see
-the section called \(lqFILES\(rq)\&.
-.RE
-.PP
-\fB\-\-purge_hist\fR
-.RS 4
-Purge history, you may supply an alternative DB file with \-\-dbfile option\&.
-.RE
-.PP
-\fB\-\-remove_bl=\fR\fB\fIrow_id\fR\fR
-.RS 4
-Use to remove a black list entry\&. To get the row_id to suppress use
-\fB\-\-view_bl\fR
-option\&.
-.RE
-.PP
-\fB\-\-view_bl\fR
-.RS 4
-Get all entries in the black list\&.
-.RE
-.PP
-\fB\-P \fR\fB\fImpd_port\fR\fR, \fB\-\-port=\fR\fB\fImpd_port\fR\fR
-.RS 4
-Use the specific port number
-\fImpd_port\fR
-on MPD server\&. This overrides
-\fBMPD_PORT\fR
-environment variable\&.
-.br
-Default is
-\fI6600\fR\&.
-.RE
-.PP
-\fB\-S \fR\fB\fImpd_host\fR\fR, \fB\-\-host=\fR\fB\fImpd_host\fR\fR
-.RS 4
-Use the specific host
-\fImpd_host\fR
-as MPD server\&.
-.br
-\fImpd_host\fR
-can be an
-IP
-or a fully qualified domain name as long as your system can resolve it\&. This overrides
-\fBMPD_HOST\fR
-environment variable\&.
-.br
-Default is
-\fIlocalhost\fR\&.
-.RE
-.SH "FILES"
-.PP
-${XDG_DATA_HOME}/mpd_sima/sima\&.db
-.RS 4
-SQLite DB file\&. Usually
-\fBXDG_DATA_HOME\fR
-is set to
-${HOME}/\&.local/share\&.
-.RE
-.SH "FEEDBACK/BUGS"
-.PP
-The maintainer would be more than happy to ear from you, don\*(Aqt hesitate to send feedback,
-\m[blue]\fB\%https://kaliko.me/contact/\fR\m[]\&.
-.PP
-XMPP
-users are welcome to join the dedicated chat room at
-\m[blue]\fBkaliko\&.me@conf\&.azylum\&.org\fR\m[]\&.
-.SH "SEE ALSO"
-.PP
-\fBmpc\fR(1),
-\fBmpd\fR(1)
-.PP
-/usr/share/doc/mpd\-sima/
-.SH "AUTHOR"
-.PP
-\fBkaliko\fR <\&kaliko@azylum\&.org\&>
-.RS 4
-Wrote this man page and is currently leading MPD_sima project\&.
-.RE
-.SH "COPYRIGHT"
-.br
-Copyright \(co 2009-2021 kaliko
-.br
-.PP
-This manual page was written for the Debian system (and may be used by others)\&.
-.PP
-Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 published by the Free Software Foundation\&.
-.PP
-On Debian systems, the complete text of the GNU General Public License can be found in
-/usr/share/common\-licenses/GPL\&.
-.sp
diff --git a/data/man/simadb_cli.1.xml b/data/man/simadb_cli.1.xml
deleted file mode 100644 (file)
index 6bab004..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<!--
-
-`xsltproc -''-nonet \
-          -''-param man.charmap.use.subset "0" \
-          -''-param make.year.ranges "1" \
-          -''-param make.single.year.ranges "1" \
-          /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl \
-          manpage.xml'
-
-A manual page <package>.<section> will be generated. You may view the
-manual page with: nroff -man <package>.<section> | less'. A typical entry
-in a Makefile or Makefile.am is:
-
-DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl
-XP     = xsltproc -''-nonet -''-param man.charmap.use.subset "0"
-
-manpage.1: manpage.xml
-        $(XP) $(DB2MAN) $<
-
-The xsltproc binary is found in the xsltproc package. The XSL files are in
-docbook-xsl. A description of the parameters you can use can be found in the
-docbook-xsl-doc-* packages. Please remember that if you create the nroff
-version in one of the debian/rules file targets (such as build), you will need
-to include xsltproc and docbook-xsl in your Build-Depends control field.
-Alternatively use the xmlto command/package. That will also automatically
-pull in xsltproc and docbook-xsl.
-
-Notes for using docbook2x: docbook2x-man does not automatically create the
-AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as
-<refsect1> ... </refsect1>.
-
-To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections
-read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be
-found in the docbook-xsl-doc-html package.
-
-Validation can be done using: `xmllint -''-noout -''-valid manpage.xml`
-
-General documentation about man-pages and man-page-formatting:
-man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
-
--->
-<!DOCTYPE refentry [
-
-  <!ENTITY dhsection   "1">
-  <!ENTITY dhpackage "mpd-sima">
-  <!ENTITY dhutils "simadb_cli">
-
-]>
-
-<refentry xmlns="http://docbook.org/ns/docbook"
-          xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0">
-  <xi:include href="info.xml" />
-  <refmeta>
-      <refentrytitle>&dhutils;</refentrytitle>
-      <manvolnum>&dhsection;</manvolnum>
-  </refmeta>
-    <refnamediv>
-        <refname>&dhutils;</refname>
-        <refpurpose>&dhutils; is a command line interface editor for the sima user DB.</refpurpose>
-    </refnamediv>
-    <refsynopsisdiv>
-        <cmdsynopsis><!-- EDIT (RM ARTIST) OPTIONS -->
-            <command>&dhutils;</command>
-            <arg choice="plain"><option>--remove_artist=</option><replaceable class="parameter">artist</replaceable></arg>
-            <arg choice="opt">
-                <option>--dbfile=</option><replaceable class="option">db_file</replaceable>
-            </arg>
-            <arg choice="opt">
-                <option>--reciprocal</option>
-            </arg>
-        </cmdsynopsis>
-        <cmdsynopsis><!-- EDIT (PURGE HIST) OPTIONS -->
-            <command>&dhutils;</command>
-            <arg choice="plain"><option>--purge_hist</option></arg>
-            <arg choice="opt">
-                <option>--dbfile=</option><replaceable class="option">db_file</replaceable>
-            </arg>
-        </cmdsynopsis>
-        <cmdsynopsis><!-- VIEW ALL ENTRIES OPTIONS -->
-            <command>&dhutils;</command>
-            <arg choice="plain"><option>--view_all</option></arg>
-            <arg choice="opt">
-                <option>--dbfile=</option><replaceable class="option">db_file</replaceable>
-            </arg>
-        </cmdsynopsis>
-        <cmdsynopsis><!-- EDIT (BLACK LIST) OPTIONS -->
-            <command>&dhutils;</command>
-            <group choice="req">
-                <arg choice="plain"><option>--bl_curr_trk</option></arg>
-                <arg choice="plain"><option>--bl_curr_art</option></arg>
-                <arg choice="plain"><option>--bl_curr_alb</option></arg>
-                <arg choice="plain"><option>--bl_art=</option><replaceable class="parameter">artist_name</replaceable></arg>
-            </group>
-            <arg choice="opt">
-                <arg choice="plain"><option>--dbfile=</option><replaceable class="parameter">db_file</replaceable></arg>
-            </arg>
-            <arg choice="opt">
-                <arg choice="plain"><option>--host=</option><replaceable class="option">mpd_host</replaceable></arg>
-            </arg>
-            <arg choice="opt">
-                <arg choice="plain"><option>--port=</option><replaceable class="option">mpd_port</replaceable></arg>
-            </arg>
-        </cmdsynopsis>
-        <cmdsynopsis><!-- EDIT (RM BL) OPTIONS -->
-            <command>&dhutils;</command>
-            <arg choice="plain"><option>--remove_bl=</option><replaceable class="parameter">row_id</replaceable></arg>
-            <arg choice="opt">
-                <option>--dbfile=</option><replaceable class="option">db_file</replaceable>
-            </arg>
-        </cmdsynopsis>
-        <cmdsynopsis><!-- VIEW BL OPTIONS -->
-            <command>&dhutils;</command>
-            <arg choice="plain"><option>--view_bl</option></arg>
-            <arg choice="opt">
-                <option>--dbfile=</option><replaceable class="option">db_file</replaceable>
-            </arg>
-        </cmdsynopsis>
-        <cmdsynopsis><!-- HELP/VERSION -->
-            <command>&dhutils;</command>
-            <!-- Normally the help and version options make the programs stop
-            right after outputting the requested information. -->
-            <group choice="req">
-                <arg choice="plain">
-                    <group choice="req">
-                        <arg choice="plain"><option>-h</option></arg>
-                        <arg choice="plain"><option>--help</option></arg>
-                    </group>
-                </arg>
-                <arg choice="plain"><option>--version</option></arg>
-            </group>
-        </cmdsynopsis>
-    </refsynopsisdiv>
-    <refsect1 id="description">
-        <title>DESCRIPTION</title>
-        <para>This manual page documents briefly the
-            <command>&dhutils;</command> commands.</para>
-        <para>simadb_cli is a command line interface to get and edit users
-            blacklist database used with MPD_sima. The default
-            database file (see <xref linkend="files"/>) can be overridden if
-            you want.</para>
-    </refsect1>
-    <refsect1 id="example">
-        <title>EXAMPLE</title>
-        <refsect2 id="blacklist">
-            <title>Black list edition</title>
-            <para><emphasis>Adding to black list.</emphasis> You can add a single
-                track, an album or an artist to the black list. The element to
-                black list is chosen from the currently playing track. Use
-                <option>--bl_curr_trk</option> to prevent &dhutils; to queue this
-                track, <option>--bl_curr_alb</option> or <option>--bl_curr_art</option> respectively for the album and the
-                artist.
-            </para>
-            <para>Remember you need access to your MPD server to retrieve
-                information to black list. Defaults are localhost:6600 or found in
-                environment variables but you may set it up from command
-                line:
-            </para>
-            <para><command>&dhutils; --bl_curr_art -S mympd.example.org</command></para>
-            <para>
-                <emphasis>To black list a specific artist</emphasis> (not
-                currently playing) you can use <option>--bl_ar="Artist name to black list"</option>.
-            </para>
-        </refsect2>
-    </refsect1>
-    <refsect1 id="options">
-        <title>OPTIONS</title>
-        <para>The program follows the usual GNU command line syntax,
-            with long options starting with two dashes ("-").  A summary of
-            options is included below.</para>
-        <variablelist>
-            <!-- Use the variablelist.term.separator and the
-            variablelist.term.break.after parameters to
-            control the term elements. -->
-            <varlistentry> <!-- help -->
-                <term><option>-h</option></term>
-                <term><option>--help</option></term>
-                <listitem>
-                    <para>Print help and exit.</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry> <!-- version -->
-                <term><option>--version</option></term>
-                <listitem>
-                    <para>Print version and exit.</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry> <!-- black list artist -->
-                <term><option>--bl_art=<replaceable class="parameter">artist_name</replaceable></option></term>
-                <listitem>
-                    <para>Use to black list <replaceable class="parameter">artist_name</replaceable>. &dhutils; is checking <replaceable class="parameter">artist_name</replaceable> is actually in MPD music library (cf <option>-S</option> and <option>-P</option> options to set MPD host/address if necessary).</para>
-                    <para>If <replaceable class="parameter">artist_name</replaceable> is not found the script print out a list of matching artists.</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry> <!-- black list -->
-                <term><option>--bl_curr_trk</option> | <option>--bl_curr_art</option> | <option>--bl_curr_alb</option></term>
-                <listitem>
-                    <para>Use to black list the currently playing track|artist|album. You need access to your MPD server, use <option>-S</option> and <option>-P</option> to set MPD host/address if necessary.</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry> <!-- dbfile -->
-                <term><option>-d <replaceable class="parameter">db_file</replaceable></option></term>
-                <term><option>--dbfile=<replaceable class="parameter">db_file</replaceable></option></term>
-                <listitem>
-                    <para>Use the specific file <replaceable>db_file</replaceable> as database.<sbr />Default is too use <envar>XDG_DATA_HOME</envar> (see <xref linkend="files"/>).</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry> <!-- purge history -->
-                <term><option>--purge_hist</option></term>
-                <listitem>
-                    <para>Purge history, you may supply an alternative DB file with --dbfile option.</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry> <!-- remove bl id -->
-                <term><option>--remove_bl=<replaceable class="parameter">row_id</replaceable></option></term>
-                <listitem>
-                    <para>Use to remove a black list entry. To get the row_id to suppress use <option>--view_bl</option> option.</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry> <!-- view bl -->
-                <term><option>--view_bl</option></term>
-                <listitem>
-                    <para>Get all entries in the black list.</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term><option>-P <replaceable class="parameter">mpd_port</replaceable></option></term>
-                <term><option>--port=<replaceable class="parameter">mpd_port</replaceable></option></term>
-                <listitem>
-                    <para>Use the specific port number <replaceable>mpd_port</replaceable> on MPD server. This overrides <envar>MPD_PORT</envar> environment variable.<sbr />Default is <emphasis>6600</emphasis>.</para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term><option>-S <replaceable class="parameter">mpd_host</replaceable></option></term>
-                <term><option>--host=<replaceable class="parameter">mpd_host</replaceable></option></term>
-                <listitem>
-                    <para>Use the specific host <replaceable>mpd_host</replaceable> as MPD server.<sbr /><replaceable>mpd_host</replaceable> can be an <acronym>IP</acronym> or a fully qualified domain name as long as your system can resolve it. This overrides <envar>MPD_HOST</envar> environment variable.<sbr />Default is <emphasis>localhost</emphasis>.</para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </refsect1>
-    <refsect1 id="files">
-        <title>FILES</title>
-        <variablelist>
-            <varlistentry>
-                <term><filename>${XDG_DATA_HOME}/mpd_sima/sima.db</filename></term>
-                <listitem>
-                    <para>SQLite DB file. Usually <envar>XDG_DATA_HOME</envar> is set to <filename>${HOME}/.local/share</filename>.</para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </refsect1>
-  <xi:include href="feedback.xml" />
-  <xi:include href="seealso.xml" />
-</refentry>
index 0630a789ea92fb229fd213e8dbc475896be92e2e..d46a831cf1b3e82bb071a5c53b00d71af9d3cd03 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -11,7 +11,7 @@ from sima.info import __version__ as VERSION, __author__ as AUTHOR
 from sima.info import __doc__ as DESCRIPTION, __email__ as EMAIL
 
 data_files = [
-    ('share/man/man1', ['data/man/mpd-sima.1', 'data/man/simadb_cli.1']),
+    ('share/man/man1', ['data/man/mpd-sima.1']),
     ('share/man/man5', ['data/man/mpd_sima.cfg.5']),
     ('share/doc/mpd-sima/examples/', glob.glob('doc/examples/*')),
     ('share/doc/mpd-sima/', [fi for fi in listdir('doc') if isfile(fi)]),
@@ -46,7 +46,6 @@ setup(name='MPD_sima',
       packages=find_packages(exclude=["tests"]),
       include_package_data=True,
       data_files=data_files,
-      scripts=['simadb_cli'],
       entry_points={
           'console_scripts': [
               'mpd-sima = sima.launch:main',
index 890f96bfd1641db6c1b6a3b1e357ffe7ea4c8571..1757d2bcee717d1780d272c8e24fed977ee0dedd 100644 (file)
@@ -39,6 +39,7 @@ from .lib.simadb import SimaDB
 from .utils.config import ConfMan
 from .utils.startopt import StartOpt
 from .utils.utils import exception_log, SigHup, MPDSimaException
+from .utils.blcli import BLCli
 # core plugins
 from .plugins.core.history import History
 from .plugins.core.mpdoptions import MpdOptions
@@ -86,7 +87,10 @@ def start(sopt, restart=False):
     logger = logging.getLogger('sima')
     logfile = config.get('log', 'logfile', fallback=None)
     verbosity = config.get('log', 'verbosity')
-    set_logger(verbosity, logfile)
+    if sopt.options.get('command'):  # disable file logging
+        set_logger(verbosity)
+    else:
+        set_logger(verbosity, logfile)
     logger.debug('Command line say: %s', sopt.options)
 
     # Create database if not present
@@ -104,6 +108,9 @@ def start(sopt, restart=False):
 
     if sopt.options.get('command'):
         cmd = sopt.options.get('command')
+        if cmd.startswith('bl-'):
+            BLCli(config, sopt.options)
+            sys.exit(0)
         if cmd == "generate-config":
             config.write(sys.stdout, space_around_delimiters=True)
             sys.exit(0)
@@ -185,7 +192,7 @@ def run(sopt, restart=False):
 def main():
     """Entry point"""
     nfo = dict({'version': info.__version__,
-                'prog': 'sima'})
+                'prog': 'mpd-sima'})
     # StartOpt gathers options from command line call (in StartOpt().options)
     sopt = StartOpt(nfo)
     run(sopt)
index 07794dc6d24f079ea6cc5b11e234e6e02e15f4b4..a66cbd0a53296974d193713f1be21a7b5dfc086b 100644 (file)
@@ -670,6 +670,24 @@ class SimaDB:
             connection.close()
         return bl
 
+    def view_bl(self):
+        connection = self.get_database_connection()
+        connection.row_factory = sqlite3.Row
+        rows = connection.execute("""SELECT artists.name AS artist,
+               artists.mbid AS musicbrainz_artist,
+               albums.name AS album,
+               albums.mbid AS musicbrainz_album,
+               tracks.title AS title,
+               tracks.mbid AS musicbrainz_title,
+               blocklist.id
+               FROM blocklist
+               LEFT OUTER JOIN artists ON blocklist.artist = artists.id
+               LEFT OUTER JOIN albums ON blocklist.album = albums.id
+               LEFT OUTER JOIN tracks ON blocklist.track = tracks.id""")
+        res = [dict(row) for row in rows.fetchall()]
+        connection.close()
+        return res
+
     def delete_bl(self, track=None, album=None, artist=None):
         if not (track or album or artist):
             return
diff --git a/sima/utils/blcli.py b/sima/utils/blcli.py
new file mode 100644 (file)
index 0000000..4522e06
--- /dev/null
@@ -0,0 +1,166 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2021 kaliko <kaliko@azylum.org>
+#
+#  This file is part of sima
+#
+#  sima is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  sima is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with sima.  If not, see <http://www.gnu.org/licenses/>.
+
+# standard library import
+import atexit
+import sys
+
+# local import
+from ..mpdclient import MPD, PlayerError, Artist, Album
+from ..lib.simadb import SimaDB
+
+
+class BLCli(MPD):
+
+    def __init__(self, conf, options):
+        super().__init__(conf)
+        self.options = options
+        self.sdb = SimaDB(db_path=conf.get('sima', 'db_file'))
+        atexit.register(self.disconnect)
+        cmd = options.get('command', None)
+        if not cmd or not cmd.startswith('bl-'):
+            return
+        try:
+            getattr(self, cmd.replace('-', '_'))()
+        except PlayerError as err:
+            self.log.error(err)
+            sys.exit(1)
+
+    def bl_view(self):
+        blocklist = self.sdb.view_bl()
+        for entry in ['artist', 'album', 'title']:
+            header = False
+            for bl in blocklist:
+                art = bl.get(entry, '')
+                mbid = bl.get(f'musicbrainz_{entry}', '')
+                if art or mbid:
+                    if not header:
+                        header = True
+                        self.log.info(f'{entry.capitalize()}'
+                                      '(id name musicbranzID):')
+                    self.log.info(f'{bl["id"]} "{art}"\t\t{mbid}')
+
+    def bl_add_artist(self):
+        artist = self.options.get('artist', None)
+        self.connect()
+        if not artist:  # artist not provided
+            self.log.debug('current track: %r', self.current)
+            if not self.current:
+                self.log.error('No current song, cannot proceed')
+                return
+            if not self.current.artist:
+                self.log.error('No artist for the current song: %r',
+                               self.current)
+                return
+            self.log.info('Using "%s" (from current track)', self.current.artist)
+            artist = self.current.Artist
+        else:  # artist provided
+            self.log.debug('Looking for %r', artist)
+            search = self.search_artist(Artist(name=artist))
+            if not search:
+                self.log.warning('Artist not found: "%s"', artist)
+                return
+            self.log.info('Found artist in library: %s', search)
+            artist = search
+        if self.sdb.get_bl_artist(artist, add=False):
+            self.log.info('Already in blocklist')
+            return
+        self.log.info('Add artist to blocklist "%s"', artist.name)
+        self.sdb.get_bl_artist(artist)
+
+    def bl_add_album(self):
+        album = self.options.get('album', None)
+        self.connect()
+        if not album:  # album not provided
+            self.log.debug('current track: %r', self.current)
+            if not self.current:
+                self.log.error('No current song, cannot proceed')
+                return
+            if not self.current.album:
+                self.log.error('No album for the current song: %r',
+                               self.current)
+                return
+            if not self.current.artist:
+                self.log.error('No artist for the current song: %r',
+                               self.current)
+                return
+            self.log.info('Using "%s" (from current track)', self.current.album)
+            album = Album(self.current.album, mbid=self.current.musicbrainz_albumid,
+                          artist=self.current.Artist)
+        else:  # album provided
+            self.log.debug('Looking for %r', album)
+            album = Album(album)
+            tracks = self.find(f'(album == "{album.name_sz}")',
+                               'window', (0, 1))
+            if not tracks:
+                self.log.warning('Album not found: "%s"', album)
+                return
+            track = tracks[0]
+            album = Album(name=track.album, mbid=track.musicbrainz_albumid)
+            artist = Artist(name=track.artist, mbid=track.musicbrainz_artistid)
+            self.log.info('Found album in library: %s (by "%s")',
+                          album, artist)
+        if self.sdb.get_bl_album(album, add=False):
+            self.log.info('Already in blocklist')
+            return
+        self.log.info('Add album to blocklist "%s"', album)
+        self.sdb.get_bl_album(album)
+
+    def bl_add_track(self):
+        track = self.options.get('track', None)
+        self.connect()
+        if not track:  # track not provided
+            self.log.debug('current track: %r', self.current)
+            if not self.current:
+                self.log.error('No current song, cannot proceed')
+                return
+            if not self.current.title:
+                self.log.error('No title for the current song: %r',
+                               self.current)
+                return
+            self.log.info('Using "%s" (from current track)', self.current.title)
+            track = self.current
+        else:  # track provided
+            self.log.debug('Looking for %r', track)
+            track_sz = track.replace("'", r"\'")
+            tracks = self.find(f'(title == "{track_sz}")')
+            if not tracks:
+                self.log.warning('Track not found: "%s"', track)
+                return
+            if len(tracks) > 1:
+                artists = {t.artist for t in tracks}
+                if len(artists) > 1:
+                    self.log.error('Found various artists for this title: %s',
+                                   artists)
+                    return
+            track = tracks[0]
+        if self.sdb.get_bl_track(track, add=False):
+            self.log.info('Already in blocklist')
+            return
+        self.log.info('Add track to blocklist "%s"', track)
+        self.sdb.get_bl_track(track)
+
+    def bl_delete(self):
+        blid = self.options.get('id', None)
+        blocklist = self.sdb.view_bl()
+        if blid not in [bl['id'] for bl in blocklist]:
+            self.log.error('Blocklist ID not found: %s', blid)
+        self.sdb._remove_blocklist_id(blid)
+
+# VIM MODLINE
+# vim: ai ts=4 sw=4 sts=4 expandtab fileencoding=utf8
index 80ccb9742e737a9e9a12bcab167b03e71e4a28ca..bf9fcf4120ce95d1e227036d7388c42fddbe5bb1 100644 (file)
@@ -21,7 +21,6 @@
 
 from argparse import ArgumentParser, RawDescriptionHelpFormatter, SUPPRESS
 
-
 from .utils import Wfile, Rfile, Wdir
 
 DESCRIPTION = """
@@ -29,8 +28,6 @@ MPD_sima automagicaly queue new tracks in MPD playlist.
 
 Command line options override their equivalent in configuration file.
 If a positional arguments is provided MPD_sima execute the command and returns.
-Commands available:
-{}
 """
 
 
@@ -40,12 +37,6 @@ def clean_dict(to_clean):
         if not to_clean.get(k):
             to_clean.pop(k)
 
-# COMMANDS LIST
-CMDS = {'config-test': 'Test configuration (MPD connection and Tags plugin only)',
-        'create-db': 'Create the database',
-        'generate-config': 'Generate a configuration file to stdout',
-        'purge-history': 'Remove play history'
-        }
 # OPTIONS LIST
 # pop out 'sw' value before creating Parser object.
 # PAY ATTENTION:
@@ -99,11 +90,30 @@ OPTS = [
         'dest': 'var_dir',
         'action': Wdir,
         'help': 'directory to store var content (ie. database, cache)'},
-    {
-        'sw': ['command'],
-        'nargs': '?',
-        'choices': CMDS.keys(),
-        'help': 'command to run (cf. description or unix manual for more)'},
+]
+# Commands
+CMDS = [
+        {'config-test': [{}], 'help': 'Test configuration (MPD connection and Tags plugin only)'},
+        {'create-db': [{}], 'help': 'Create the database'},
+        {'generate-config': [{}], 'help': 'Generate a configuration file to stdout'},
+        {'purge-history': [{}], 'help': 'Remove play history'},
+        {'bl-view': [{}], 'help': 'List blocklist IDs'},
+        {'bl-add-artist': [
+            {'name': 'artist', 'type': str, 'nargs': '?',
+             'help': 'If artist is provided use it else use currently playing value'}
+            ], 'help': 'Add artist to the blocklist'},
+        {'bl-add-album': [
+            {'name': 'album', 'type': str, 'nargs': '?',
+             'help': 'If album is provided use it else use currently playing value'}
+         ], 'help': 'Add album to the blocklist'},
+        {'bl-add-track': [
+            {'name': 'track', 'type': str, 'nargs': '?',
+             'help': 'If track is provided use it else use currently playing value'}
+         ], 'help': 'Add track to the blocklist'},
+        {'bl-delete': [
+            {'name': 'id', 'type': int, 'nargs': '?',
+             'help': 'blocklist ID to suppress (use bl-view list IDs)'}
+         ], 'help': 'Remove entries from the blocklist'},
 ]
 
 
@@ -121,8 +131,7 @@ class StartOpt:
         """
         Declare options in ArgumentParser object.
         """
-        cmds = '\n'.join([f'    * {k}: {v}' for k, v in CMDS.items()])
-        self.parser = ArgumentParser(description=DESCRIPTION.format(cmds),
+        self.parser = ArgumentParser(description=DESCRIPTION,
                                      prog=self.info.get('prog'),
                                      epilog='Happy Listening',
                                      formatter_class=RawDescriptionHelpFormatter,
@@ -133,6 +142,19 @@ class StartOpt:
         for opt in OPTS:
             opt_names = opt.pop('sw')
             self.parser.add_argument(*opt_names, **opt)
+        # Add sub commands
+        sp = self.parser.add_subparsers(
+                title=f'{self.info["prog"]} commands as positional arguments',
+                description=f"""Use them after optionnal arguments.\n"{self.info["prog"]} command -h" for more info.""",
+                metavar='', dest='command')
+        for cmd in CMDS:
+            helpmsg = cmd.pop('help')
+            cmd, args = cmd.popitem()
+            _ = sp.add_parser(cmd, description=helpmsg, help=helpmsg)
+            for arg in args:
+                name = arg.pop('name', None)
+                if name:
+                    _.add_argument(name, **arg)
 
     def main(self):
         """
diff --git a/simadb_cli b/simadb_cli
deleted file mode 100755 (executable)
index b720a0d..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2010-2015 Jack Kaliko <kaliko@azylum.org>
-#
-#  This file is part of MPD_sima
-#
-#  MPD_sima is free software: you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation, either version 3 of the License, or
-#  (at your option) any later version.
-#
-#  MPD_sima is distributed in the hope that it will be useful,
-#  but WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
-#
-#  You should have received a copy of the GNU General Public License
-#  along with MPD_sima.  If not, see <http://www.gnu.org/licenses/>.
-#
-#
-
-__version__ = '0.4.1'
-
-# IMPORT#
-from argparse import (ArgumentParser, SUPPRESS)
-from difflib import get_close_matches
-from locale import getpreferredencoding
-from os import (environ, chmod, makedirs)
-from os.path import (join, isdir, isfile, expanduser)
-from sys import (exit, stdout, stderr)
-
-from sima.lib.track import Track
-from sima.utils import utils
-from sima.lib import simadb
-from musicpd import MPDClient, MPDError
-
-
-DESCRIPTION = """
-simadb_cli helps you to edit entries in your own DB of similarity
-between artists."""
-DB_NAME = 'sima.db'
-
-# Options list
-# pop out 'sw' value before creating ArgumentParser object.
-OPTS = list([
-    {
-        'sw':['-d', '--dbfile'],
-        'type': str,
-        'dest':'dbfile',
-        'action': utils.Wfile,
-        'help': 'File to read/write database from/to'},
-    {
-        'sw': ['-S', '--host'],
-        'type': str,
-        'dest': 'mpdhost',
-        'default': None,
-        'help': 'MPD host, as IP or FQDN (default: localhost|MPD_HOST).'},
-    {
-        'sw': ['-P', '--port'],
-        'type': int,
-        'dest': 'mpdport',
-        'default': None,
-        'help': 'Port MPD in listening on (default: 6600|MPD_PORT).'},
-    {
-        'sw': ['--password'],
-        'type': str,
-        'dest': 'passwd',
-        'default': None,
-        'help': SUPPRESS},
-    {
-        'sw': ['--view_bl'],
-        'action': 'store_true',
-        'dest': 'view_bl',
-        'help': 'View black list.'},
-    {
-        'sw': ['--remove_bl'],
-        'type': int,
-        'help': 'Suppress a black list entry, by row id. Use --view_bl to get row id.'},
-    {
-        'sw': ['--bl_art'],
-        'type': str,
-        'metavar': 'ARTIST_NAME',
-        'help': 'Black list artist.'},
-    {
-        'sw': ['--bl_curr_art'],
-        'action': 'store_true',
-        'help': 'Black list currently playing artist.'},
-    {
-        'sw': ['--bl_curr_alb'],
-        'action': 'store_true',
-        'help': 'Black list currently playing album.'},
-    {
-        'sw': ['--bl_curr_trk'],
-        'action': 'store_true',
-        'help': 'Black list currently playing track.'},
-    {
-        'sw':['--purge_hist'],
-        'action': 'store_true',
-        'dest': 'do_purge_hist',
-        'help': 'Purge play history.'}])
-
-
-class SimaDB_CLI(object):
-    """Command line management.
-    """
-
-    def __init__(self):
-        self.dbfile = self._get_default_dbfile()
-        self.parser = None
-        self.options = dict({})
-        self.localencoding = 'UTF-8'
-        self._get_encoding()
-        self.main()
-
-    def _get_encoding(self):
-        """Get local encoding"""
-        localencoding = getpreferredencoding()
-        if localencoding:
-            self.localencoding = localencoding
-
-    def _get_mpd_env_var(self):
-        """
-        MPD host/port environement variables are used if command line does not
-        provide host|port|passwd.
-        """
-        host, port, passwd = utils.get_mpd_environ()
-        if self.options.passwd is None and passwd:
-            self.options.passwd = passwd
-        if self.options.mpdhost is None:
-            if host:
-                self.options.mpdhost = host
-            else:
-                self.options.mpdhost = 'localhost'
-        if self.options.mpdport is None:
-            if port:
-                self.options.mpdport = port
-            else:
-                self.options.mpdport = 6600
-
-    def _declare_opts(self):
-        """
-        Declare options in ArgumentParser object.
-        """
-        self.parser = ArgumentParser(description=DESCRIPTION,
-                                   usage='%(prog)s [-h|--help] [options]',
-                                   prog='simadb_cli',
-                                   epilog='Happy Listening',
-                                   )
-
-        self.parser.add_argument('--version', action='version',
-                version='%(prog)s {0}'.format(__version__))
-        # Add all options declare in OPTS
-        for opt in OPTS:
-            opt_names = opt.pop('sw')
-            self.parser.add_argument(*opt_names, **opt)
-
-    def _get_default_dbfile(self):
-        """
-        Use XDG directory standard if exists
-        else use "HOME/.local/share/mpd_sima/"
-        http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
-        """
-        homedir = expanduser('~')
-        dirname = 'mpd_sima'
-        if environ.get('XDG_DATA_HOME'):
-            data_dir = join(environ.get('XDG_DATA_HOME'), dirname)
-        else:
-            data_dir = join(homedir, '.local', 'share', dirname)
-        if not isdir(data_dir):
-            makedirs(data_dir)
-            chmod(data_dir, 0o700)
-        return join(data_dir, DB_NAME)
-
-    def _get_mpd_client(self):
-        """"""
-        host = self.options.mpdhost
-        port = self.options.mpdport
-        passwd = self.options.passwd
-        cli = MPDClient()
-        try:
-            cli.connect(host, port)
-            if passwd:
-                cli.password(passwd)
-        except MPDError as err:
-            mess = 'ERROR: fail to connect MPD on %s:%s %s' % (
-                    host, port, err)
-            print(mess, file=stderr)
-            exit(1)
-        return cli
-
-    def _create_db(self):
-        """Create database if necessary"""
-        if isfile(self.dbfile):
-            return
-        print('Creating database!')
-        open(self.dbfile, 'a').close()
-        simadb.SimaDB(db_path=self.dbfile).create_db()
-
-    def _get_art_from_db(self, art):
-        """Return (id, name, self...) from DB or None is not in DB"""
-        db = simadb.SimaDB(db_path=self.dbfile)
-        art_db = db.get_artist(art, add_not=True)
-        if not art_db:
-            print('ERROR: "%s" not in data base!' % art, file=stderr)
-            return None
-        return art_db
-
-    def bl_artist(self):
-        """Black list artist"""
-        mpd_cli = self._get_mpd_client()
-        artists_list = mpd_cli.list('artist')
-        # Unicode cli given artist name
-        cli_artist_to_bl = self.options.bl_art
-        if cli_artist_to_bl not in artists_list:
-            print('Artist not found in MPD library.')
-            match = get_close_matches(cli_artist_to_bl, artists_list, 50, 0.78)
-            if match:
-                print('You may be refering to %s' %
-                        '/'.join([m_a for m_a in match]))
-            return False
-        print('Black listing artist: %s' % cli_artist_to_bl)
-        db = simadb.SimaDB(db_path=self.dbfile)
-        db.get_bl_artist(cli_artist_to_bl)
-
-    def bl_current_artist(self):
-        """Black list current artist"""
-        mpd_cli = self._get_mpd_client()
-        artist = mpd_cli.currentsong().get('artist', '')
-        if not artist:
-            print('No artist found.')
-            return False
-        print('Black listing artist: %s' % artist)
-        db = simadb.SimaDB(db_path=self.dbfile)
-        db.get_bl_artist(artist)
-
-    def bl_current_album(self):
-        """Black list current artist"""
-        mpd_cli = self._get_mpd_client()
-        track = Track(**mpd_cli.currentsong())
-        if not track.album:
-            print('No album set for this track: %s' % track)
-            return False
-        print('Black listing album: {0}'.format(track.album))
-        db = simadb.SimaDB(db_path=self.dbfile)
-        db.get_bl_album(track)
-
-    def bl_current_track(self):
-        """Black list current artist"""
-        mpd_cli = self._get_mpd_client()
-        track = Track(**mpd_cli.currentsong())
-        print('Black listing track: %s' % track)
-        db = simadb.SimaDB(db_path=self.dbfile)
-        db.get_bl_track(track)
-
-    def purge_history(self):
-        """Purge all entries in history"""
-        db = simadb.SimaDB(db_path=self.dbfile)
-        print('Purging history...')
-        db.purge_history(duration=int(0))
-        print('done.')
-        print('Cleaning database...')
-        db.clean_database()
-        print('done.')
-
-    def view_bl(self):
-        """Print out black list."""
-        # TODO: enhance output formating
-        db = simadb.SimaDB(db_path=self.dbfile)
-        for bl_e in db.get_black_list():
-            print('\t# '.join([str(e) for e in bl_e]))
-
-    def remove_black_list_entry(self):
-        """"""
-        db = simadb.SimaDB(db_path=self.dbfile)
-        db._remove_bl(int(self.options.remove_bl))
-
-    def main(self):
-        """
-        Parse command line and run actions.
-        """
-        self._declare_opts()
-        self.options = self.parser.parse_args()
-        self._get_mpd_env_var()
-        if self.options.dbfile:
-            self.dbfile = self.options.dbfile
-            print('Using db file: %s' % self.dbfile)
-        if self.options.bl_art:
-            self.bl_artist()
-            return
-        if self.options.bl_curr_art:
-            self.bl_current_artist()
-            return
-        if self.options.bl_curr_alb:
-            self.bl_current_album()
-            return
-        if self.options.bl_curr_trk:
-            self.bl_current_track()
-            return
-        if self.options.view_bl:
-            self.view_bl()
-            return
-        if self.options.remove_bl:
-            self.remove_black_list_entry()
-            return
-        if self.options.do_purge_hist:
-            self.purge_history()
-        exit(0)
-
-
-# Script starts here
-if __name__ == '__main__':
-    try:
-        SimaDB_CLI()
-    except Exception as err:
-        print(err)
-        exit(1)
-
-# VIM MODLINE
-# vim: ai ts=4 sw=4 sts=4 expandtab