Exemple #1
0
    def commands(self):
        lastgenre_cmd = ui.Subcommand('lastgenre', help='fetch genres')

        def lastgenre_func(lib, config, opts, args):
            # The "write to files" option corresponds to the
            # import_write config value.
            write = ui.config_val(config, 'beets', 'import_write',
                                  commands.DEFAULT_IMPORT_WRITE, bool)
            for album in lib.albums(ui.decargs(args)):
                tags = []
                lastfm_obj = LASTFM.get_album(album.albumartist, album.album)
                if album.genre:
                    tags.append(album.genre)

                tags.extend(_tags_for(lastfm_obj))
                genre = _tags_to_genre(tags)

                if not genre and fallback_str != None:
                    genre = fallback_str
                    log.debug(u'no last.fm genre found: fallback to %s' %
                              genre)

                if genre is not None:
                    log.debug(u'adding last.fm album genre: %s' % genre)
                    album.genre = genre
                    if write:
                        for item in album.items():
                            item.write()

        lastgenre_cmd.func = lastgenre_func
        return [lastgenre_cmd]
Exemple #2
0
    def commands(self):
        def queries(lib, opts, args):
            success = self._parse_opts(opts)
            if success:
                results = self._match_library_tracks(lib, ui.decargs(args))
                self._output_match_results(results)

        spotify_cmd = ui.Subcommand('spotify',
                                    help=u'build a Spotify playlist')
        spotify_cmd.parser.add_option(
            u'-m',
            u'--mode',
            action='store',
            help=u'"open" to open Spotify with playlist, '
            u'"list" to print (default)',
        )
        spotify_cmd.parser.add_option(
            u'-f',
            u'--show-failures',
            action='store_true',
            dest='show_failures',
            help=u'list tracks that did not match a Spotify ID',
        )
        spotify_cmd.func = queries
        return [spotify_cmd]
Exemple #3
0
 def commands(self):
     cmd = ui.Subcommand('bpsync', help='update metadata from Beatport')
     cmd.parser.add_option(
         '-p',
         '--pretend',
         action='store_true',
         help='show all changes but do nothing',
     )
     cmd.parser.add_option(
         '-m',
         '--move',
         action='store_true',
         dest='move',
         help="move files in the library directory",
     )
     cmd.parser.add_option(
         '-M',
         '--nomove',
         action='store_false',
         dest='move',
         help="don't move files in library",
     )
     cmd.parser.add_option(
         '-W',
         '--nowrite',
         action='store_false',
         default=None,
         dest='write',
         help="don't write updated metadata to files",
     )
     cmd.parser.add_format_option()
     cmd.func = self.func
     return [cmd]
Exemple #4
0
    def commands(self):
        cmd = ui.Subcommand(
            'ftintitle',
            help=
            'puts featuring artists in the title instead of the artist field')

        def func(lib, config, opts, args):
            for track in lib.items():
                artistfield = track.__getattr__("artist")
                regxRes = re.split(
                    '\s[fF]t\.|\s[fF]eaturing|\s[fF]eat\.|\s[wW]ith',
                    artistfield)
                if len(regxRes) > 1:
                    titleField = track.__getattr__("title")
                    featInTitle = re.search('[fF]t\.|[fF]eaturing|[fF]eat\.',
                                            titleField)
                    if featInTitle == None:
                        print track.__getattr__("path")
                        track.__setattr__("artist", regxRes[0])
                        track.__setattr__(
                            "title", titleField + " (feat." + regxRes[1] + ")")
                        track.write()
                    else:
                        track.__setattr__("artist", regxRes[0])
                        track.write()
            print "A Manual 'beet update' run is recommended. "

        cmd.func = func

        return [cmd]
Exemple #5
0
 def commands(self):
     spl_update = ui.Subcommand(
         'splupdate',
         help=u'update the smart playlists. Playlist names may be '
         u'passed as arguments.')
     spl_update.func = self.update_cmd
     return [spl_update]
Exemple #6
0
    def commands(self):
        cmd = ui.Subcommand('web2', help='start a Web2 interface')
        cmd.parser.add_option('-d', '--debug', action='store_true',
                              default=False, help='debug mode')

        def func(lib, opts, args):
            args = ui.decargs(args)
            if args:
                self.config['host'] = args.pop(0)
            if args:
                self.config['port'] = int(args.pop(0))
            if args:
                self.config['server'] = args.pop(0)

            host = self.config['host'].get(str)
            port = self.config['port'].get(int)
            server = self.config['server'].get(str)

            username = self.config['username'].get(str)
            password = self.config['password'].get(str)

            app = make_app(lib, username, password)
            run(app, host=host, port=port, server=server, debug=opts.debug)

        cmd.func = func
        return [cmd]
Exemple #7
0
 def commands(self):
     cmd = ui.Subcommand('info', help=u'show file metadata')
     cmd.func = self.run
     cmd.parser.add_option(
         u'-l',
         u'--library',
         action='store_true',
         help=u'show library fields instead of tags',
     )
     cmd.parser.add_option(
         u'-s',
         u'--summarize',
         action='store_true',
         help=u'summarize the tags of all files',
     )
     cmd.parser.add_option(
         u'-i',
         u'--include-keys',
         default=[],
         action='append',
         dest='included_keys',
         help=u'comma separated list of keys to show',
     )
     cmd.parser.add_option(
         u'-k',
         u'--keys-only',
         action='store_true',
         help=u'show only the keys',
     )
     cmd.parser.add_format_option(target='item')
     return [cmd]
Exemple #8
0
 def commands(self):
     def update(lib, opts, args):
         update_playlists(lib)
     spl_update = ui.Subcommand('splupdate',
                                help='update the smart playlists')
     spl_update.func = update
     return [spl_update]
Exemple #9
0
    def commands(self):
        cmd = ui.Subcommand('mpdstats',
                            help='run a MPD client to gather play statistics')
        cmd.parser.add_option(
            '--host',
            dest='host',
            type='string',
            help='set the hostname of the server to connect to')
        cmd.parser.add_option(
            '--port',
            dest='port',
            type='int',
            help='set the port of the MPD server to connect to')
        cmd.parser.add_option(
            '--password',
            dest='password',
            type='string',
            help='set the password of the MPD server to connect to')

        def func(lib, opts, args):
            self.config.set_args(opts)
            Client(lib).run()

        cmd.func = func
        return [cmd]
Exemple #10
0
    def commands(self):
        # TODO: Add option to use albums

        cmd = ui.Subcommand('export', help=u'export data from beets')
        cmd.func = self.run
        cmd.parser.add_option(
            u'-l',
            u'--library',
            action='store_true',
            help=u'show library fields instead of tags',
        )
        cmd.parser.add_option(
            u'--append',
            action='store_true',
            default=False,
            help=u'if should append data to the file',
        )
        cmd.parser.add_option(
            u'-i',
            u'--include-keys',
            default=[],
            action='append',
            dest='included_keys',
            help=u'comma separated list of keys to show',
        )
        cmd.parser.add_option(
            u'-o',
            u'--output',
            help=u'path for the output file. If not given, will print the data'
        )
        return [cmd]
Exemple #11
0
    def commands(self):
        def queries(lib, opts, args):
            success = self._parse_opts(opts)
            if success:
                results = self._match_library_tracks(lib, ui.decargs(args))
                self._output_match_results(results)

        spotify_cmd = ui.Subcommand(
            'spotify', help=f'build a {self.data_source} playlist')
        spotify_cmd.parser.add_option(
            '-m',
            '--mode',
            action='store',
            help='"open" to open {} with playlist, '
            '"list" to print (default)'.format(self.data_source),
        )
        spotify_cmd.parser.add_option(
            '-f',
            '--show-failures',
            action='store_true',
            dest='show_failures',
            help='list tracks that did not match a {} ID'.format(
                self.data_source),
        )
        spotify_cmd.func = queries
        return [spotify_cmd]
Exemple #12
0
    def commands(self):
        """Return the "replaygain" ui subcommand.
        """
        def func(lib, opts, args):
            try:
                write = ui.should_write(opts.write)
                force = opts.force

                # Bypass self.open_pool() if called with  `--threads 0`
                if opts.threads != 0:
                    threads = opts.threads or self.config['threads'].get(int)
                    self.open_pool(threads)

                if opts.album:
                    albums = lib.albums(ui.decargs(args))
                    self._log.info(
                        "Analyzing {} albums ~ {} backend...".format(
                            len(albums), self.backend_name))
                    for album in albums:
                        self.handle_album(album, write, force)
                else:
                    items = lib.items(ui.decargs(args))
                    self._log.info(
                        "Analyzing {} tracks ~ {} backend...".format(
                            len(items), self.backend_name))
                    for item in items:
                        self.handle_track(item, write, force)

                self.close_pool()
            except (SystemExit, KeyboardInterrupt):
                # Silence interrupt exceptions
                pass

        cmd = ui.Subcommand('replaygain', help=u'analyze for ReplayGain')
        cmd.parser.add_album_option()
        cmd.parser.add_option("-t",
                              "--threads",
                              dest="threads",
                              type=int,
                              help=u'change the number of threads, \
            defaults to maximum available processors')
        cmd.parser.add_option("-f",
                              "--force",
                              dest="force",
                              action="store_true",
                              default=False,
                              help=u"analyze all files, including those that "
                              "already have ReplayGain metadata")
        cmd.parser.add_option("-w",
                              "--write",
                              default=None,
                              action="store_true",
                              help=u"write new metadata to files' tags")
        cmd.parser.add_option("-W",
                              "--nowrite",
                              dest="write",
                              action="store_false",
                              help=u"don't write metadata (opposite of -w)")
        cmd.func = func
        return [cmd]
Exemple #13
0
 def commands(self):
     recording_date_command = ui.Subcommand(
         'oldestdate',
         help="Retrieve the date of the oldest known recording or release of a track.",
         aliases=['olddate'])
     recording_date_command.func = self._command_func
     return [recording_date_command]
Exemple #14
0
    def commands(self):
        def func(lib, opts, args):
            self.config.set_args(opts)
            force_parent = self.config['force'].get(bool)
            write = ui.should_write()

            for item in lib.items(ui.decargs(args)):
                self.find_work(item, force_parent)
                item.store()
                if write:
                    item.try_write()

        command = ui.Subcommand(
            'parentwork', help=u'fetche parent works, composers and dates')

        command.parser.add_option(
            u'-f',
            u'--force',
            dest='force',
            action='store_true',
            default=None,
            help=u're-fetch when parent work is already present')

        command.func = func
        return [command]
Exemple #15
0
 def commands(self):
     """Return the "replaygain" ui subcommand.
     """
     cmd = ui.Subcommand('replaygain', help=u'analyze for ReplayGain')
     cmd.parser.add_album_option()
     cmd.parser.add_option("-t",
                           "--threads",
                           dest="threads",
                           type=int,
                           help=u'change the number of threads, \
         defaults to maximum available processors')
     cmd.parser.add_option("-f",
                           "--force",
                           dest="force",
                           action="store_true",
                           default=False,
                           help=u"analyze all files, including those that "
                           "already have ReplayGain metadata")
     cmd.parser.add_option("-w",
                           "--write",
                           default=None,
                           action="store_true",
                           help=u"write new metadata to files' tags")
     cmd.parser.add_option("-W",
                           "--nowrite",
                           dest="write",
                           action="store_false",
                           help=u"don't write metadata (opposite of -w)")
     cmd.func = self.command_func
     return [cmd]
Exemple #16
0
    def commands(self):
        cmd = ui.Subcommand(
            'mpdstats',
            help=u'run a MPD client to gather play statistics')
        cmd.parser.add_option(
            u'--host', dest='host', type='string',
            help=u'set the hostname of the server to connect to')
        cmd.parser.add_option(
            u'--port', dest='port', type='int',
            help=u'set the port of the MPD server to connect to')
        cmd.parser.add_option(
            u'--password', dest='password', type='string',
            help=u'set the password of the MPD server to connect to')

        def func(lib, opts, args):
            mpd_config.set_args(opts)

            # Overrides for MPD settings.
            if opts.host:
                mpd_config['host'] = opts.host.decode('utf-8')
            if opts.port:
                mpd_config['host'] = int(opts.port)
            if opts.password:
                mpd_config['password'] = opts.password.decode('utf-8')

            try:
                MPDStats(lib, self._log).run()
            except KeyboardInterrupt:
                pass

        cmd.func = func
        return [cmd]
Exemple #17
0
    def commands(self):
        def scrub_func(lib, config, opts, args):
            # This is a little bit hacky, but we set a global flag to
            # avoid autoscrubbing when we're also explicitly scrubbing.
            global scrubbing
            scrubbing = True

            # Walk through matching files and remove tags.
            for item in lib.items(ui.decargs(args)):
                log.info(u'scrubbing: %s' % util.displayable_path(item.path))
                mf = mediafile.MediaFile(item.path)
                _scrub(mf)
                mf.save()

                if opts.write:
                    log.debug(u'writing new tags after scrub')
                    item.write()

            scrubbing = False

        scrub_cmd = ui.Subcommand('scrub', help='clean audio tags')
        scrub_cmd.parser.add_option('-W',
                                    '--nowrite',
                                    dest='write',
                                    action='store_false',
                                    default=True,
                                    help='leave tags empty')
        scrub_cmd.func = scrub_func

        return [scrub_cmd]
Exemple #18
0
    def commands(self):
        cmd = ui.Subcommand('ipfs', help='interact with ipfs')
        cmd.parser.add_option('-a',
                              '--add',
                              dest='add',
                              action='store_true',
                              help='Add to ipfs')
        cmd.parser.add_option('-g',
                              '--get',
                              dest='get',
                              action='store_true',
                              help='Get from ipfs')
        cmd.parser.add_option('-p',
                              '--publish',
                              dest='publish',
                              action='store_true',
                              help='Publish local library to ipfs')
        cmd.parser.add_option('-i',
                              '--import',
                              dest='_import',
                              action='store_true',
                              help='Import remote library from ipfs')
        cmd.parser.add_option('-l',
                              '--list',
                              dest='_list',
                              action='store_true',
                              help='Query imported libraries')
        cmd.parser.add_option('-m',
                              '--play',
                              dest='play',
                              action='store_true',
                              help='Play music from remote libraries')

        def func(lib, opts, args):
            if opts.add:
                for album in lib.albums(ui.decargs(args)):
                    if len(album.items()) == 0:
                        self._log.info('{0} does not contain items, aborting',
                                       album)

                    self.ipfs_add(album)
                    album.store()

            if opts.get:
                self.ipfs_get(lib, ui.decargs(args))

            if opts.publish:
                self.ipfs_publish(lib)

            if opts._import:
                self.ipfs_import(lib, ui.decargs(args))

            if opts._list:
                self.ipfs_list(lib, ui.decargs(args))

            if opts.play:
                self.ipfs_play(lib, opts, ui.decargs(args))

        cmd.func = func
        return [cmd]
Exemple #19
0
    def commands(self):
        lastgenre_cmd = ui.Subcommand('lastgenre', help='fetch genres')
        lastgenre_cmd.parser.add_option(
            '-f', '--force', dest='force', action='store_true', default=False,
            help='re-download genre when already present'
        )
        lastgenre_cmd.parser.add_option(
            '-s', '--source', dest='source', type='string',
            help='genre source: artist, album, or track'
        )

        def lastgenre_func(lib, opts, args):
            write = ui.should_write()
            self.config.set_args(opts)

            for album in lib.albums(ui.decargs(args)):
                album.genre, src = self._get_genre(album)
                self._log.info(u'genre for album {0} ({1}): {0.genre}',
                               album, src)
                album.store()

                for item in album.items():
                    # If we're using track-level sources, also look up each
                    # track on the album.
                    if 'track' in self.sources:
                        item.genre, src = self._get_genre(item)
                        item.store()
                        self._log.info(u'genre for track {0} ({1}): {0.genre}',
                                       item, src)

                    if write:
                        item.try_write()

        lastgenre_cmd.func = lastgenre_func
        return [lastgenre_cmd]
Exemple #20
0
 def commands(self):
     cmd = ui.Subcommand(
         u'inconsistent-album-tracks',
         help=u'Identify albums whose tracks have inconsistent album fields.'
     )
     cmd.parser.add_option(
         '-i',
         '--include-fields',
         default=[],
         action='append',
         metavar='FIELD',
         dest='included_fields',
         help='comma separated list of fields to show',
     )
     cmd.parser.add_option(
         '-x',
         '--exclude-fields',
         default=[],
         action='append',
         metavar='FIELD',
         dest='ignored_fields',
         help='comma separated list of fields to exclude/ignore',
     )
     cmd.func = self.command
     return [cmd]
Exemple #21
0
    def commands(self):
        """Return the "replaygain" ui subcommand.
        """
        def func(lib, opts, args):
            write = ui.should_write(opts.write)
            force = opts.force

            if opts.album:
                for album in lib.albums(ui.decargs(args)):
                    self.handle_album(album, write, force)

            else:
                for item in lib.items(ui.decargs(args)):
                    self.handle_track(item, write, force)

        cmd = ui.Subcommand('replaygain', help=u'analyze for ReplayGain')
        cmd.parser.add_album_option()
        cmd.parser.add_option(
            "-f", "--force", dest="force", action="store_true", default=False,
            help=u"analyze all files, including those that "
            "already have ReplayGain metadata")
        cmd.parser.add_option(
            "-w", "--write", default=None, action="store_true",
            help=u"write new metadata to files' tags")
        cmd.parser.add_option(
            "-W", "--nowrite", dest="write", action="store_false",
            help=u"don't write metadata (opposite of -w)")
        cmd.func = func
        return [cmd]
Exemple #22
0
 def commands(self):
     cmd = ui.Subcommand(
         'absubmit',
         help=u'calculate and submit AcousticBrainz analysis'
     )
     cmd.func = self.command
     return [cmd]
Exemple #23
0
 def commands(self):
     cmd = ui.Subcommand('convert', help=u'convert to external location')
     cmd.parser.add_option('-p',
                           '--pretend',
                           action='store_true',
                           help=u'show actions but do nothing')
     cmd.parser.add_option('-t',
                           '--threads',
                           action='store',
                           type='int',
                           help=u'change the number of threads, \
                           defaults to maximum available processors')
     cmd.parser.add_option('-k',
                           '--keep-new',
                           action='store_true',
                           dest='keep_new',
                           help=u'keep only the converted \
                           and move the old files')
     cmd.parser.add_option('-d',
                           '--dest',
                           action='store',
                           help=u'set the destination directory')
     cmd.parser.add_option('-f',
                           '--format',
                           action='store',
                           dest='format',
                           help=u'set the target format of the tracks')
     cmd.parser.add_option('-y',
                           '--yes',
                           action='store_true',
                           dest='yes',
                           help=u'do not ask for confirmation')
     cmd.parser.add_album_option()
     cmd.func = self.convert_func
     return [cmd]
Exemple #24
0
    def commands(self):
        cmd = ui.Subcommand('web', help=u'start a Web interface')
        cmd.parser.add_option(u'-d', u'--debug', action='store_true',
                              default=False, help=u'debug mode')

        def func(lib, opts, args):
            args = ui.decargs(args)
            if args:
                self.config['host'] = args.pop(0)
            if args:
                self.config['port'] = int(args.pop(0))

            app.config['lib'] = lib
            # Enable CORS if required.
            if self.config['cors']:
                self._log.info(u'Enabling CORS with origin: {0}',
                               self.config['cors'])
                from flask.ext.cors import CORS
                app.config['CORS_ALLOW_HEADERS'] = "Content-Type"
                app.config['CORS_RESOURCES'] = {
                    r"/*": {"origins": self.config['cors'].get(str)}
                }
                CORS(app)
            # Start the web application.
            app.run(host=self.config['host'].get(unicode),
                    port=self.config['port'].get(int),
                    debug=opts.debug, threaded=True)
        cmd.func = func
        return [cmd]
Exemple #25
0
 def commands(self):
     cmd = ui.Subcommand('mbsync', help='update metadata from musicbrainz')
     cmd.parser.add_option('-p',
                           '--pretend',
                           action='store_true',
                           help='show all changes but do nothing')
     cmd.parser.add_option('-M',
                           '--nomove',
                           action='store_false',
                           default=True,
                           dest='move',
                           help="don't move files in library")
     cmd.parser.add_option('-W',
                           '--nowrite',
                           action='store_false',
                           default=config['import']['write'],
                           dest='write',
                           help="don't write updated metadata to files")
     cmd.parser.add_option('-f',
                           '--format',
                           action='store',
                           default='',
                           help='print with custom format')
     cmd.func = self.func
     return [cmd]
    def commands(self):
        for plugin in plugins.find_plugins():
            if plugin.name == 'spotify':
                self.spotify = plugin
                break
        else:
            raise ui.UserError('spotify plugin is required')

        def explicits(lib, opts, args):
            args = ui.decargs(args)
            items = lib.items(args)
            results = self.spotify._match_library_tracks(lib, args)
            if results:
                for item, track in zip(items, results):
                    if track['explicit']:
                        title = track['name']
                        album = track['album']['name']
                        artist = track['artists'][0]['name']
                        tracknum = track['track_number']
                        url = track['external_urls']['spotify']
                        plugins.send("spotify_explicit_track",
                                     lib=lib,
                                     track=track,
                                     item=item)
                        print('{} - {} - {} - {} - {}'.format(
                            album, tracknum, artist, title, url))

        explicit_cmd = ui.Subcommand('spotify-explicit', help=u'')
        explicit_cmd.parser.add_all_common_options()
        explicit_cmd.func = explicits
        return [explicit_cmd]
Exemple #27
0
    def commands(self):
        cmd = ui.Subcommand('lyrics', help='fetch song lyrics')
        cmd.parser.add_option('-p',
                              '--print',
                              dest='printlyr',
                              action='store_true',
                              default=False,
                              help='print lyrics to console')
        cmd.parser.add_option('-f',
                              '--force',
                              dest='force_refetch',
                              action='store_true',
                              default=False,
                              help='always re-download lyrics')

        def func(lib, opts, args):
            # The "write to files" option corresponds to the
            # import_write config value.
            write = config['import']['write'].get(bool)
            for item in lib.items(ui.decargs(args)):
                self.fetch_item_lyrics(lib, logging.INFO, item, write,
                                       opts.force_refetch)
                if opts.printlyr and item.lyrics:
                    ui.print_(item.lyrics)

        cmd.func = func
        return [cmd]
    def commands(self):
        cmd = ui.Subcommand(
            'structuredcomments',
            help=u'for when you need beets data outside of beets')

        cmd.parser.add_option(u'-d',
                              u'--dry-run',
                              dest="dry_run",
                              action="store_true",
                              default=False,
                              help=u'Print changes without writing to files')
        cmd.parser.add_option(
            u'-f',
            u'--force',
            dest="force",
            action="store_true",
            default=False,
            help=u'Rewrite tags to file even if they are the same')
        # XXX not sure how to ensure we come back to the next 100 if we do batch of 100, maybe a skip arg
        # cmd.parser.add_option(
        #     u'-b', u'--batch', dest="batch",
        #     action="store", default=None,
        #     help=u'Write comments in batches instead of all at once'
        # )
        cmd.func = self.command
        return [cmd]
Exemple #29
0
    def commands(self):
        cmd = ui.Subcommand('tempo', help='fetch song tempo (bpm)')
        cmd.parser.add_option('-p',
                              '--print',
                              dest='printlyr',
                              action='store_true',
                              default=False,
                              help='print tempo (bpm) to console')

        def func(lib, config, opts, args):
            # The "write to files" option corresponds to the
            # import_write config value.
            if not _echonest_apikey:
                raise ui.UserError('no EchoNest user API key provided')

            write = ui.config_val(config, 'beets', 'import_write',
                                  commands.DEFAULT_IMPORT_WRITE, bool)

            for item in lib.items(ui.decargs(args)):
                fetch_item_tempo(lib, logging.INFO, item, write)
                if opts.printlyr and item.bpm:
                    ui.print_(item.bpm)

        cmd.func = func
        return [cmd]
Exemple #30
0
    def commands(self):
        """
        Return the "userrating" ui subcommand.
        """

        cmd = ui.Subcommand('userrating', help=u'manage user ratings for tracks')
        cmd.func = lambda lib, opts, args: self.handle_tracks(lib.items(ui.decargs(args)), opts)
        cmd.parser.add_option(
            u'-u', u'--update', action='store',
            help=u'all files will be rated with given value',
        )
        cmd.parser.add_option(
            u'-i', u'--imported', action='store_true',
            help=u'all files will be rated if possible with known players value in file',
        )
        cmd.parser.add_option(
            u'-o', u'--overwrite', action='store_true',
            help=u'allow overwriting rated file (default is to skip already rated file)',
        )
        cmd.parser.add_option(
            u'-s',u'--sync', action='store',
            help=u'write rating for existing players rating (default is to not update any players rating but beets)',
        )
        cmd.parser.add_option(
            u'-a', u'--all', action='store_true',
            help=u'write rating for all known players (default is to not update any players rating but beets)',
        )
        return [cmd]