+++ /dev/null
-'\" 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
+++ /dev/null
-<?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>
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)]),
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',
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
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
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)
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)
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
--- /dev/null
+# -*- 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
from argparse import ArgumentParser, RawDescriptionHelpFormatter, SUPPRESS
-
from .utils import Wfile, Rfile, Wdir
DESCRIPTION = """
Command line options override their equivalent in configuration file.
If a positional arguments is provided MPD_sima execute the command and returns.
-Commands available:
-{}
"""
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:
'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'},
]
"""
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,
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):
"""
+++ /dev/null
-#!/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