Full Code of clinton-hall/nzbToMedia for AI

master 1521c404cec7 cached
2142 files
13.6 MB
3.7M tokens
19992 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (14,635K chars total). Download the full file to get everything.
Repository: clinton-hall/nzbToMedia
Branch: master
Commit: 1521c404cec7
Files: 2142
Total size: 13.6 MB

Directory structure:
gitextract_1h9iq7tv/

├── .bumpversion.cfg
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── README.md
├── .gitignore
├── TorrentToMedia.py
├── _config.yml
├── autoProcessMedia.cfg.spec
├── azure-pipelines.yml
├── cleanup.py
├── core/
│   ├── __init__.py
│   ├── auto_process/
│   │   ├── __init__.py
│   │   ├── books.py
│   │   ├── comics.py
│   │   ├── common.py
│   │   ├── games.py
│   │   ├── managers/
│   │   │   ├── __init__.py
│   │   │   ├── pymedusa.py
│   │   │   └── sickbeard.py
│   │   ├── movies.py
│   │   ├── music.py
│   │   └── tv.py
│   ├── configuration.py
│   ├── databases.py
│   ├── extractor/
│   │   ├── __init__.py
│   │   └── bin/
│   │       ├── AMD64/
│   │       │   └── license.txt
│   │       ├── invisible.vbs
│   │       └── x86/
│   │           └── license.txt
│   ├── github_api.py
│   ├── logger.py
│   ├── main_db.py
│   ├── permissions.py
│   ├── plugins/
│   │   ├── __init__.py
│   │   ├── downloaders/
│   │   │   ├── __init__.py
│   │   │   ├── configuration.py
│   │   │   ├── nzb/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── configuration.py
│   │   │   │   └── utils.py
│   │   │   ├── torrent/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── configuration.py
│   │   │   │   ├── deluge.py
│   │   │   │   ├── qbittorrent.py
│   │   │   │   ├── synology.py
│   │   │   │   ├── transmission.py
│   │   │   │   ├── utils.py
│   │   │   │   └── utorrent.py
│   │   │   └── utils.py
│   │   ├── plex.py
│   │   └── subtitles.py
│   ├── processor/
│   │   ├── __init__.py
│   │   ├── manual.py
│   │   ├── nzb.py
│   │   ├── nzbget.py
│   │   └── sab.py
│   ├── scene_exceptions.py
│   ├── transcoder.py
│   ├── user_scripts.py
│   ├── utils/
│   │   ├── __init__.py
│   │   ├── common.py
│   │   ├── download_info.py
│   │   ├── encoding.py
│   │   ├── files.py
│   │   ├── identification.py
│   │   ├── links.py
│   │   ├── naming.py
│   │   ├── network.py
│   │   ├── parsers.py
│   │   ├── paths.py
│   │   ├── processes.py
│   │   └── shutil_custom.py
│   └── version_check.py
├── eol.py
├── getffmpeg.sh
├── libs/
│   ├── __init__.py
│   ├── __main__.py
│   ├── autoload.py
│   ├── common/
│   │   ├── __init__.py
│   │   ├── _version.py
│   │   ├── _yaml/
│   │   │   └── __init__.py
│   │   ├── appdirs.py
│   │   ├── babelfish/
│   │   │   ├── __init__.py
│   │   │   ├── converters/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── alpha2.py
│   │   │   │   ├── alpha3b.py
│   │   │   │   ├── alpha3t.py
│   │   │   │   ├── countryname.py
│   │   │   │   ├── name.py
│   │   │   │   ├── opensubtitles.py
│   │   │   │   ├── scope.py
│   │   │   │   └── type.py
│   │   │   ├── country.py
│   │   │   ├── data/
│   │   │   │   ├── iso-3166-1.txt
│   │   │   │   ├── iso-639-3.tab
│   │   │   │   ├── iso15924-utf8-20131012.txt
│   │   │   │   └── opensubtitles_languages.txt
│   │   │   ├── exceptions.py
│   │   │   ├── language.py
│   │   │   └── script.py
│   │   ├── beets/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── art.py
│   │   │   ├── autotag/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── hooks.py
│   │   │   │   ├── match.py
│   │   │   │   └── mb.py
│   │   │   ├── config_default.yaml
│   │   │   ├── dbcore/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── db.py
│   │   │   │   ├── query.py
│   │   │   │   ├── queryparse.py
│   │   │   │   └── types.py
│   │   │   ├── importer.py
│   │   │   ├── library.py
│   │   │   ├── logging.py
│   │   │   ├── mediafile.py
│   │   │   ├── plugins.py
│   │   │   ├── random.py
│   │   │   ├── ui/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── commands.py
│   │   │   │   └── completion_base.sh
│   │   │   ├── util/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── artresizer.py
│   │   │   │   ├── bluelet.py
│   │   │   │   ├── confit.py
│   │   │   │   ├── enumeration.py
│   │   │   │   ├── functemplate.py
│   │   │   │   ├── hidden.py
│   │   │   │   └── pipeline.py
│   │   │   └── vfs.py
│   │   ├── beetsplug/
│   │   │   ├── __init__.py
│   │   │   ├── absubmit.py
│   │   │   ├── acousticbrainz.py
│   │   │   ├── albumtypes.py
│   │   │   ├── aura.py
│   │   │   ├── badfiles.py
│   │   │   ├── bareasc.py
│   │   │   ├── beatport.py
│   │   │   ├── bench.py
│   │   │   ├── bpd/
│   │   │   │   ├── __init__.py
│   │   │   │   └── gstplayer.py
│   │   │   ├── bpm.py
│   │   │   ├── bpsync.py
│   │   │   ├── bucket.py
│   │   │   ├── chroma.py
│   │   │   ├── convert.py
│   │   │   ├── deezer.py
│   │   │   ├── discogs.py
│   │   │   ├── duplicates.py
│   │   │   ├── edit.py
│   │   │   ├── embedart.py
│   │   │   ├── embyupdate.py
│   │   │   ├── export.py
│   │   │   ├── fetchart.py
│   │   │   ├── filefilter.py
│   │   │   ├── fish.py
│   │   │   ├── freedesktop.py
│   │   │   ├── fromfilename.py
│   │   │   ├── ftintitle.py
│   │   │   ├── fuzzy.py
│   │   │   ├── gmusic.py
│   │   │   ├── hook.py
│   │   │   ├── ihate.py
│   │   │   ├── importadded.py
│   │   │   ├── importfeeds.py
│   │   │   ├── info.py
│   │   │   ├── inline.py
│   │   │   ├── ipfs.py
│   │   │   ├── keyfinder.py
│   │   │   ├── kodiupdate.py
│   │   │   ├── lastgenre/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── genres-tree.yaml
│   │   │   │   └── genres.txt
│   │   │   ├── lastimport.py
│   │   │   ├── loadext.py
│   │   │   ├── lyrics.py
│   │   │   ├── mbcollection.py
│   │   │   ├── mbsubmit.py
│   │   │   ├── mbsync.py
│   │   │   ├── metasync/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── amarok.py
│   │   │   │   └── itunes.py
│   │   │   ├── missing.py
│   │   │   ├── mpdstats.py
│   │   │   ├── mpdupdate.py
│   │   │   ├── parentwork.py
│   │   │   ├── permissions.py
│   │   │   ├── play.py
│   │   │   ├── playlist.py
│   │   │   ├── plexupdate.py
│   │   │   ├── random.py
│   │   │   ├── replaygain.py
│   │   │   ├── rewrite.py
│   │   │   ├── scrub.py
│   │   │   ├── smartplaylist.py
│   │   │   ├── sonosupdate.py
│   │   │   ├── spotify.py
│   │   │   ├── subsonicplaylist.py
│   │   │   ├── subsonicupdate.py
│   │   │   ├── the.py
│   │   │   ├── thumbnails.py
│   │   │   ├── types.py
│   │   │   ├── unimported.py
│   │   │   ├── web/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── static/
│   │   │   │   │   ├── backbone.js
│   │   │   │   │   ├── beets.css
│   │   │   │   │   ├── beets.js
│   │   │   │   │   ├── jquery.js
│   │   │   │   │   └── underscore.js
│   │   │   │   └── templates/
│   │   │   │       └── index.html
│   │   │   └── zero.py
│   │   ├── bs4/
│   │   │   ├── __init__.py
│   │   │   ├── builder/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _html5lib.py
│   │   │   │   ├── _htmlparser.py
│   │   │   │   └── _lxml.py
│   │   │   ├── dammit.py
│   │   │   ├── diagnose.py
│   │   │   ├── element.py
│   │   │   ├── formatter.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── test_builder.py
│   │   │       ├── test_builder_registry.py
│   │   │       ├── test_dammit.py
│   │   │       ├── test_docs.py
│   │   │       ├── test_element.py
│   │   │       ├── test_formatter.py
│   │   │       ├── test_html5lib.py
│   │   │       ├── test_htmlparser.py
│   │   │       ├── test_lxml.py
│   │   │       ├── test_navigablestring.py
│   │   │       ├── test_pageelement.py
│   │   │       ├── test_soup.py
│   │   │       ├── test_tag.py
│   │   │       └── test_tree.py
│   │   ├── certifi/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── cacert.pem
│   │   │   └── core.py
│   │   ├── chardet/
│   │   │   ├── __init__.py
│   │   │   ├── big5freq.py
│   │   │   ├── big5prober.py
│   │   │   ├── chardistribution.py
│   │   │   ├── charsetgroupprober.py
│   │   │   ├── charsetprober.py
│   │   │   ├── cli/
│   │   │   │   ├── __init__.py
│   │   │   │   └── chardetect.py
│   │   │   ├── codingstatemachine.py
│   │   │   ├── compat.py
│   │   │   ├── cp949prober.py
│   │   │   ├── enums.py
│   │   │   ├── escprober.py
│   │   │   ├── escsm.py
│   │   │   ├── eucjpprober.py
│   │   │   ├── euckrfreq.py
│   │   │   ├── euckrprober.py
│   │   │   ├── euctwfreq.py
│   │   │   ├── euctwprober.py
│   │   │   ├── gb2312freq.py
│   │   │   ├── gb2312prober.py
│   │   │   ├── hebrewprober.py
│   │   │   ├── jisfreq.py
│   │   │   ├── jpcntx.py
│   │   │   ├── langbulgarianmodel.py
│   │   │   ├── langgreekmodel.py
│   │   │   ├── langhebrewmodel.py
│   │   │   ├── langhungarianmodel.py
│   │   │   ├── langrussianmodel.py
│   │   │   ├── langthaimodel.py
│   │   │   ├── langturkishmodel.py
│   │   │   ├── latin1prober.py
│   │   │   ├── mbcharsetprober.py
│   │   │   ├── mbcsgroupprober.py
│   │   │   ├── mbcssm.py
│   │   │   ├── metadata/
│   │   │   │   ├── __init__.py
│   │   │   │   └── languages.py
│   │   │   ├── sbcharsetprober.py
│   │   │   ├── sbcsgroupprober.py
│   │   │   ├── sjisprober.py
│   │   │   ├── universaldetector.py
│   │   │   ├── utf8prober.py
│   │   │   └── version.py
│   │   ├── click/
│   │   │   ├── __init__.py
│   │   │   ├── _compat.py
│   │   │   ├── _termui_impl.py
│   │   │   ├── _textwrap.py
│   │   │   ├── _winconsole.py
│   │   │   ├── core.py
│   │   │   ├── decorators.py
│   │   │   ├── exceptions.py
│   │   │   ├── formatting.py
│   │   │   ├── globals.py
│   │   │   ├── parser.py
│   │   │   ├── py.typed
│   │   │   ├── shell_completion.py
│   │   │   ├── termui.py
│   │   │   ├── testing.py
│   │   │   ├── types.py
│   │   │   └── utils.py
│   │   ├── colorama/
│   │   │   ├── __init__.py
│   │   │   ├── ansi.py
│   │   │   ├── ansitowin32.py
│   │   │   ├── initialise.py
│   │   │   ├── tests/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── ansi_test.py
│   │   │   │   ├── ansitowin32_test.py
│   │   │   │   ├── initialise_test.py
│   │   │   │   ├── isatty_test.py
│   │   │   │   ├── utils.py
│   │   │   │   └── winterm_test.py
│   │   │   ├── win32.py
│   │   │   └── winterm.py
│   │   ├── configobj.py
│   │   ├── confuse/
│   │   │   ├── __init__.py
│   │   │   ├── core.py
│   │   │   ├── exceptions.py
│   │   │   ├── sources.py
│   │   │   ├── templates.py
│   │   │   ├── util.py
│   │   │   └── yaml_util.py
│   │   ├── dateutil/
│   │   │   ├── __init__.py
│   │   │   ├── _common.py
│   │   │   ├── _version.py
│   │   │   ├── easter.py
│   │   │   ├── parser/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _parser.py
│   │   │   │   └── isoparser.py
│   │   │   ├── relativedelta.py
│   │   │   ├── rrule.py
│   │   │   ├── tz/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _common.py
│   │   │   │   ├── _factories.py
│   │   │   │   ├── tz.py
│   │   │   │   └── win.py
│   │   │   ├── tzwin.py
│   │   │   ├── utils.py
│   │   │   └── zoneinfo/
│   │   │       ├── __init__.py
│   │   │       └── rebuild.py
│   │   ├── decorator.py
│   │   ├── dogpile/
│   │   │   ├── __init__.py
│   │   │   ├── cache/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── api.py
│   │   │   │   ├── backends/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── file.py
│   │   │   │   │   ├── memcached.py
│   │   │   │   │   ├── memory.py
│   │   │   │   │   ├── null.py
│   │   │   │   │   └── redis.py
│   │   │   │   ├── exception.py
│   │   │   │   ├── plugins/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   └── mako_cache.py
│   │   │   │   ├── proxy.py
│   │   │   │   ├── region.py
│   │   │   │   └── util.py
│   │   │   ├── core.py
│   │   │   ├── lock.py
│   │   │   └── util/
│   │   │       ├── __init__.py
│   │   │       ├── compat.py
│   │   │       ├── langhelpers.py
│   │   │       ├── nameregistry.py
│   │   │       └── readwrite_lock.py
│   │   ├── easy_install.py
│   │   ├── enzyme/
│   │   │   ├── __init__.py
│   │   │   ├── compat.py
│   │   │   ├── exceptions.py
│   │   │   ├── mkv.py
│   │   │   ├── parsers/
│   │   │   │   ├── __init__.py
│   │   │   │   └── ebml/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── core.py
│   │   │   │       ├── readers.py
│   │   │   │       └── specs/
│   │   │   │           └── matroska.xml
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── parsers/
│   │   │       │   └── ebml/
│   │   │       │       └── test1.mkv.yml
│   │   │       ├── test_mkv.py
│   │   │       └── test_parsers.py
│   │   ├── filetype/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── filetype.py
│   │   │   ├── helpers.py
│   │   │   ├── match.py
│   │   │   ├── types/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── application.py
│   │   │   │   ├── archive.py
│   │   │   │   ├── audio.py
│   │   │   │   ├── base.py
│   │   │   │   ├── document.py
│   │   │   │   ├── font.py
│   │   │   │   ├── image.py
│   │   │   │   ├── isobmff.py
│   │   │   │   └── video.py
│   │   │   └── utils.py
│   │   ├── guessit/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── __version__.py
│   │   │   ├── api.py
│   │   │   ├── backports.py
│   │   │   ├── config/
│   │   │   │   └── options.json
│   │   │   ├── jsonutils.py
│   │   │   ├── monkeypatch.py
│   │   │   ├── options.py
│   │   │   ├── reutils.py
│   │   │   ├── rules/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── common/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── comparators.py
│   │   │   │   │   ├── date.py
│   │   │   │   │   ├── expected.py
│   │   │   │   │   ├── formatters.py
│   │   │   │   │   ├── numeral.py
│   │   │   │   │   ├── pattern.py
│   │   │   │   │   ├── quantity.py
│   │   │   │   │   ├── validators.py
│   │   │   │   │   └── words.py
│   │   │   │   ├── markers/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── groups.py
│   │   │   │   │   └── path.py
│   │   │   │   ├── match_processors.py
│   │   │   │   ├── processors.py
│   │   │   │   └── properties/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── audio_codec.py
│   │   │   │       ├── bit_rate.py
│   │   │   │       ├── bonus.py
│   │   │   │       ├── cds.py
│   │   │   │       ├── container.py
│   │   │   │       ├── country.py
│   │   │   │       ├── crc.py
│   │   │   │       ├── date.py
│   │   │   │       ├── edition.py
│   │   │   │       ├── episode_title.py
│   │   │   │       ├── episodes.py
│   │   │   │       ├── film.py
│   │   │   │       ├── language.py
│   │   │   │       ├── mimetype.py
│   │   │   │       ├── other.py
│   │   │   │       ├── part.py
│   │   │   │       ├── release_group.py
│   │   │   │       ├── screen_size.py
│   │   │   │       ├── size.py
│   │   │   │       ├── source.py
│   │   │   │       ├── streaming_service.py
│   │   │   │       ├── title.py
│   │   │   │       ├── type.py
│   │   │   │       ├── video_codec.py
│   │   │   │       └── website.py
│   │   │   ├── test/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── config/
│   │   │   │   │   ├── dummy.txt
│   │   │   │   │   ├── test.json
│   │   │   │   │   ├── test.yaml
│   │   │   │   │   └── test.yml
│   │   │   │   ├── enable_disable_properties.yml
│   │   │   │   ├── episodes.yml
│   │   │   │   ├── movies.yml
│   │   │   │   ├── rules/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── audio_codec.yml
│   │   │   │   │   ├── bonus.yml
│   │   │   │   │   ├── cds.yml
│   │   │   │   │   ├── common_words.yml
│   │   │   │   │   ├── country.yml
│   │   │   │   │   ├── date.yml
│   │   │   │   │   ├── edition.yml
│   │   │   │   │   ├── episodes.yml
│   │   │   │   │   ├── film.yml
│   │   │   │   │   ├── language.yml
│   │   │   │   │   ├── other.yml
│   │   │   │   │   ├── part.yml
│   │   │   │   │   ├── processors.yml
│   │   │   │   │   ├── processors_test.py
│   │   │   │   │   ├── release_group.yml
│   │   │   │   │   ├── screen_size.yml
│   │   │   │   │   ├── size.yml
│   │   │   │   │   ├── source.yml
│   │   │   │   │   ├── title.yml
│   │   │   │   │   ├── video_codec.yml
│   │   │   │   │   └── website.yml
│   │   │   │   ├── streaming_services.yaml
│   │   │   │   ├── suggested.json
│   │   │   │   ├── test-input-file.txt
│   │   │   │   ├── test_api.py
│   │   │   │   ├── test_api_unicode_literals.py
│   │   │   │   ├── test_benchmark.py
│   │   │   │   ├── test_main.py
│   │   │   │   ├── test_options.py
│   │   │   │   ├── test_yml.py
│   │   │   │   └── various.yml
│   │   │   ├── tlds-alpha-by-domain.txt
│   │   │   └── yamlutils.py
│   │   ├── idna/
│   │   │   ├── __init__.py
│   │   │   ├── codec.py
│   │   │   ├── compat.py
│   │   │   ├── core.py
│   │   │   ├── idnadata.py
│   │   │   ├── intranges.py
│   │   │   ├── package_data.py
│   │   │   └── uts46data.py
│   │   ├── importlib_metadata/
│   │   │   ├── __init__.py
│   │   │   └── _compat.py
│   │   ├── importlib_resources/
│   │   │   ├── __init__.py
│   │   │   ├── _adapters.py
│   │   │   ├── _common.py
│   │   │   ├── _itertools.py
│   │   │   ├── abc.py
│   │   │   ├── compat/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── py38.py
│   │   │   │   └── py39.py
│   │   │   ├── future/
│   │   │   │   ├── __init__.py
│   │   │   │   └── adapters.py
│   │   │   ├── py.typed
│   │   │   ├── readers.py
│   │   │   ├── simple.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── _compat.py
│   │   │       ├── _path.py
│   │   │       ├── data01/
│   │   │       │   ├── __init__.py
│   │   │       │   ├── binary.file
│   │   │       │   ├── subdirectory/
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   └── binary.file
│   │   │       │   ├── utf-16.file
│   │   │       │   └── utf-8.file
│   │   │       ├── data02/
│   │   │       │   ├── __init__.py
│   │   │       │   ├── one/
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   └── resource1.txt
│   │   │       │   ├── subdirectory/
│   │   │       │   │   └── subsubdir/
│   │   │       │   │       └── resource.txt
│   │   │       │   └── two/
│   │   │       │       ├── __init__.py
│   │   │       │       └── resource2.txt
│   │   │       ├── namespacedata01/
│   │   │       │   ├── binary.file
│   │   │       │   ├── subdirectory/
│   │   │       │   │   └── binary.file
│   │   │       │   ├── utf-16.file
│   │   │       │   └── utf-8.file
│   │   │       ├── test_compatibilty_files.py
│   │   │       ├── test_contents.py
│   │   │       ├── test_custom.py
│   │   │       ├── test_files.py
│   │   │       ├── test_open.py
│   │   │       ├── test_path.py
│   │   │       ├── test_read.py
│   │   │       ├── test_reader.py
│   │   │       ├── test_resource.py
│   │   │       ├── util.py
│   │   │       └── zip.py
│   │   ├── jaraco/
│   │   │   ├── context.py
│   │   │   ├── functools/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── __init__.pyi
│   │   │   │   └── py.typed
│   │   │   └── text/
│   │   │       ├── Lorem ipsum.txt
│   │   │       ├── __init__.py
│   │   │       ├── layouts.py
│   │   │       ├── show-newlines.py
│   │   │       ├── strip-prefix.py
│   │   │       ├── to-dvorak.py
│   │   │       └── to-qwerty.py
│   │   ├── jellyfish/
│   │   │   ├── __init__.py
│   │   │   ├── __init__.pyi
│   │   │   ├── _jellyfish.py
│   │   │   ├── porter.py
│   │   │   ├── py.typed
│   │   │   └── test.py
│   │   ├── linktastic.py
│   │   ├── mediafile.py
│   │   ├── more_itertools/
│   │   │   ├── __init__.py
│   │   │   ├── more.py
│   │   │   ├── recipes.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── test_more.py
│   │   │       └── test_recipes.py
│   │   ├── munkres.py
│   │   ├── musicbrainzngs/
│   │   │   ├── __init__.py
│   │   │   ├── caa.py
│   │   │   ├── compat.py
│   │   │   ├── mbxml.py
│   │   │   ├── musicbrainz.py
│   │   │   └── util.py
│   │   ├── mutagen/
│   │   │   ├── __init__.py
│   │   │   ├── _constants.py
│   │   │   ├── _file.py
│   │   │   ├── _iff.py
│   │   │   ├── _riff.py
│   │   │   ├── _tags.py
│   │   │   ├── _tools/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _util.py
│   │   │   │   ├── mid3cp.py
│   │   │   │   ├── mid3iconv.py
│   │   │   │   ├── mid3v2.py
│   │   │   │   ├── moggsplit.py
│   │   │   │   ├── mutagen_inspect.py
│   │   │   │   └── mutagen_pony.py
│   │   │   ├── _util.py
│   │   │   ├── _vorbis.py
│   │   │   ├── aac.py
│   │   │   ├── ac3.py
│   │   │   ├── aiff.py
│   │   │   ├── apev2.py
│   │   │   ├── asf/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _attrs.py
│   │   │   │   ├── _objects.py
│   │   │   │   └── _util.py
│   │   │   ├── dsdiff.py
│   │   │   ├── dsf.py
│   │   │   ├── easyid3.py
│   │   │   ├── easymp4.py
│   │   │   ├── flac.py
│   │   │   ├── id3/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _file.py
│   │   │   │   ├── _frames.py
│   │   │   │   ├── _id3v1.py
│   │   │   │   ├── _specs.py
│   │   │   │   ├── _tags.py
│   │   │   │   └── _util.py
│   │   │   ├── m4a.py
│   │   │   ├── monkeysaudio.py
│   │   │   ├── mp3/
│   │   │   │   ├── __init__.py
│   │   │   │   └── _util.py
│   │   │   ├── mp4/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _as_entry.py
│   │   │   │   ├── _atom.py
│   │   │   │   └── _util.py
│   │   │   ├── musepack.py
│   │   │   ├── ogg.py
│   │   │   ├── oggflac.py
│   │   │   ├── oggopus.py
│   │   │   ├── oggspeex.py
│   │   │   ├── oggtheora.py
│   │   │   ├── oggvorbis.py
│   │   │   ├── optimfrog.py
│   │   │   ├── py.typed
│   │   │   ├── smf.py
│   │   │   ├── tak.py
│   │   │   ├── trueaudio.py
│   │   │   ├── wave.py
│   │   │   └── wavpack.py
│   │   ├── oauthlib/
│   │   │   ├── __init__.py
│   │   │   ├── common.py
│   │   │   ├── oauth1/
│   │   │   │   ├── __init__.py
│   │   │   │   └── rfc5849/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── endpoints/
│   │   │   │       │   ├── __init__.py
│   │   │   │       │   ├── access_token.py
│   │   │   │       │   ├── authorization.py
│   │   │   │       │   ├── base.py
│   │   │   │       │   ├── pre_configured.py
│   │   │   │       │   ├── request_token.py
│   │   │   │       │   ├── resource.py
│   │   │   │       │   └── signature_only.py
│   │   │   │       ├── errors.py
│   │   │   │       ├── parameters.py
│   │   │   │       ├── request_validator.py
│   │   │   │       ├── signature.py
│   │   │   │       └── utils.py
│   │   │   ├── oauth2/
│   │   │   │   ├── __init__.py
│   │   │   │   └── rfc6749/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── clients/
│   │   │   │       │   ├── __init__.py
│   │   │   │       │   ├── backend_application.py
│   │   │   │       │   ├── base.py
│   │   │   │       │   ├── legacy_application.py
│   │   │   │       │   ├── mobile_application.py
│   │   │   │       │   ├── service_application.py
│   │   │   │       │   └── web_application.py
│   │   │   │       ├── endpoints/
│   │   │   │       │   ├── __init__.py
│   │   │   │       │   ├── authorization.py
│   │   │   │       │   ├── base.py
│   │   │   │       │   ├── introspect.py
│   │   │   │       │   ├── metadata.py
│   │   │   │       │   ├── pre_configured.py
│   │   │   │       │   ├── resource.py
│   │   │   │       │   ├── revocation.py
│   │   │   │       │   └── token.py
│   │   │   │       ├── errors.py
│   │   │   │       ├── grant_types/
│   │   │   │       │   ├── __init__.py
│   │   │   │       │   ├── authorization_code.py
│   │   │   │       │   ├── base.py
│   │   │   │       │   ├── client_credentials.py
│   │   │   │       │   ├── implicit.py
│   │   │   │       │   ├── refresh_token.py
│   │   │   │       │   └── resource_owner_password_credentials.py
│   │   │   │       ├── parameters.py
│   │   │   │       ├── request_validator.py
│   │   │   │       ├── tokens.py
│   │   │   │       └── utils.py
│   │   │   ├── openid/
│   │   │   │   ├── __init__.py
│   │   │   │   └── connect/
│   │   │   │       ├── __init__.py
│   │   │   │       └── core/
│   │   │   │           ├── __init__.py
│   │   │   │           ├── endpoints/
│   │   │   │           │   ├── __init__.py
│   │   │   │           │   ├── pre_configured.py
│   │   │   │           │   └── userinfo.py
│   │   │   │           ├── exceptions.py
│   │   │   │           ├── grant_types/
│   │   │   │           │   ├── __init__.py
│   │   │   │           │   ├── authorization_code.py
│   │   │   │           │   ├── base.py
│   │   │   │           │   ├── dispatchers.py
│   │   │   │           │   ├── exceptions.py
│   │   │   │           │   ├── hybrid.py
│   │   │   │           │   └── implicit.py
│   │   │   │           ├── request_validator.py
│   │   │   │           └── tokens.py
│   │   │   ├── signals.py
│   │   │   └── uri_validate.py
│   │   ├── packaging/
│   │   │   ├── __init__.py
│   │   │   ├── _elffile.py
│   │   │   ├── _manylinux.py
│   │   │   ├── _musllinux.py
│   │   │   ├── _parser.py
│   │   │   ├── _structures.py
│   │   │   ├── _tokenizer.py
│   │   │   ├── markers.py
│   │   │   ├── metadata.py
│   │   │   ├── py.typed
│   │   │   ├── requirements.py
│   │   │   ├── specifiers.py
│   │   │   ├── tags.py
│   │   │   ├── utils.py
│   │   │   └── version.py
│   │   ├── pbr/
│   │   │   ├── __init__.py
│   │   │   ├── build.py
│   │   │   ├── builddoc.py
│   │   │   ├── cmd/
│   │   │   │   ├── __init__.py
│   │   │   │   └── main.py
│   │   │   ├── core.py
│   │   │   ├── extra_files.py
│   │   │   ├── find_package.py
│   │   │   ├── git.py
│   │   │   ├── hooks/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── backwards.py
│   │   │   │   ├── base.py
│   │   │   │   ├── commands.py
│   │   │   │   ├── files.py
│   │   │   │   └── metadata.py
│   │   │   ├── options.py
│   │   │   ├── packaging.py
│   │   │   ├── pbr_json.py
│   │   │   ├── sphinxext.py
│   │   │   ├── testr_command.py
│   │   │   ├── tests/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── base.py
│   │   │   │   ├── test_commands.py
│   │   │   │   ├── test_core.py
│   │   │   │   ├── test_files.py
│   │   │   │   ├── test_hooks.py
│   │   │   │   ├── test_integration.py
│   │   │   │   ├── test_packaging.py
│   │   │   │   ├── test_pbr_json.py
│   │   │   │   ├── test_setup.py
│   │   │   │   ├── test_util.py
│   │   │   │   ├── test_version.py
│   │   │   │   ├── test_wsgi.py
│   │   │   │   ├── testpackage/
│   │   │   │   │   ├── CHANGES.txt
│   │   │   │   │   ├── LICENSE.txt
│   │   │   │   │   ├── MANIFEST.in
│   │   │   │   │   ├── README.txt
│   │   │   │   │   ├── data_files/
│   │   │   │   │   │   ├── a.txt
│   │   │   │   │   │   ├── b.txt
│   │   │   │   │   │   └── c.rst
│   │   │   │   │   ├── doc/
│   │   │   │   │   │   └── source/
│   │   │   │   │   │       ├── conf.py
│   │   │   │   │   │       ├── index.rst
│   │   │   │   │   │       ├── installation.rst
│   │   │   │   │   │       └── usage.rst
│   │   │   │   │   ├── extra-file.txt
│   │   │   │   │   ├── git-extra-file.txt
│   │   │   │   │   ├── pbr_testpackage/
│   │   │   │   │   │   ├── __init__.py
│   │   │   │   │   │   ├── _setup_hooks.py
│   │   │   │   │   │   ├── cmd.py
│   │   │   │   │   │   ├── extra.py
│   │   │   │   │   │   ├── package_data/
│   │   │   │   │   │   │   ├── 1.txt
│   │   │   │   │   │   │   └── 2.txt
│   │   │   │   │   │   └── wsgi.py
│   │   │   │   │   ├── setup.py
│   │   │   │   │   ├── src/
│   │   │   │   │   │   └── testext.c
│   │   │   │   │   └── test-requirements.txt
│   │   │   │   └── util.py
│   │   │   ├── util.py
│   │   │   └── version.py
│   │   ├── pkg_resources/
│   │   │   ├── __init__.py
│   │   │   ├── _vendor/
│   │   │   │   ├── __init__.py
│   │   │   │   └── packaging/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── _structures.py
│   │   │   │       ├── markers.py
│   │   │   │       ├── requirements.py
│   │   │   │       ├── specifiers.py
│   │   │   │       ├── utils.py
│   │   │   │       └── version.py
│   │   │   └── extern/
│   │   │       └── __init__.py
│   │   ├── platformdirs/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── android.py
│   │   │   ├── api.py
│   │   │   ├── macos.py
│   │   │   ├── py.typed
│   │   │   ├── unix.py
│   │   │   ├── version.py
│   │   │   └── windows.py
│   │   ├── pysrt/
│   │   │   ├── __init__.py
│   │   │   ├── commands.py
│   │   │   ├── comparablemixin.py
│   │   │   ├── compat.py
│   │   │   ├── srtexc.py
│   │   │   ├── srtfile.py
│   │   │   ├── srtitem.py
│   │   │   ├── srttime.py
│   │   │   └── version.py
│   │   ├── pytz/
│   │   │   ├── __init__.py
│   │   │   ├── exceptions.py
│   │   │   ├── lazy.py
│   │   │   ├── reference.py
│   │   │   ├── tzfile.py
│   │   │   ├── tzinfo.py
│   │   │   └── zoneinfo/
│   │   │       ├── Africa/
│   │   │       │   ├── Abidjan
│   │   │       │   ├── Accra
│   │   │       │   ├── Addis_Ababa
│   │   │       │   ├── Algiers
│   │   │       │   ├── Asmara
│   │   │       │   ├── Asmera
│   │   │       │   ├── Bamako
│   │   │       │   ├── Bangui
│   │   │       │   ├── Banjul
│   │   │       │   ├── Bissau
│   │   │       │   ├── Blantyre
│   │   │       │   ├── Brazzaville
│   │   │       │   ├── Bujumbura
│   │   │       │   ├── Cairo
│   │   │       │   ├── Casablanca
│   │   │       │   ├── Ceuta
│   │   │       │   ├── Conakry
│   │   │       │   ├── Dakar
│   │   │       │   ├── Dar_es_Salaam
│   │   │       │   ├── Djibouti
│   │   │       │   ├── Douala
│   │   │       │   ├── El_Aaiun
│   │   │       │   ├── Freetown
│   │   │       │   ├── Gaborone
│   │   │       │   ├── Harare
│   │   │       │   ├── Johannesburg
│   │   │       │   ├── Juba
│   │   │       │   ├── Kampala
│   │   │       │   ├── Khartoum
│   │   │       │   ├── Kigali
│   │   │       │   ├── Kinshasa
│   │   │       │   ├── Lagos
│   │   │       │   ├── Libreville
│   │   │       │   ├── Lome
│   │   │       │   ├── Luanda
│   │   │       │   ├── Lubumbashi
│   │   │       │   ├── Lusaka
│   │   │       │   ├── Malabo
│   │   │       │   ├── Maputo
│   │   │       │   ├── Maseru
│   │   │       │   ├── Mbabane
│   │   │       │   ├── Mogadishu
│   │   │       │   ├── Monrovia
│   │   │       │   ├── Nairobi
│   │   │       │   ├── Ndjamena
│   │   │       │   ├── Niamey
│   │   │       │   ├── Nouakchott
│   │   │       │   ├── Ouagadougou
│   │   │       │   ├── Porto-Novo
│   │   │       │   ├── Sao_Tome
│   │   │       │   ├── Timbuktu
│   │   │       │   ├── Tripoli
│   │   │       │   ├── Tunis
│   │   │       │   └── Windhoek
│   │   │       ├── America/
│   │   │       │   ├── Adak
│   │   │       │   ├── Anchorage
│   │   │       │   ├── Anguilla
│   │   │       │   ├── Antigua
│   │   │       │   ├── Araguaina
│   │   │       │   ├── Argentina/
│   │   │       │   │   ├── Buenos_Aires
│   │   │       │   │   ├── Catamarca
│   │   │       │   │   ├── ComodRivadavia
│   │   │       │   │   ├── Cordoba
│   │   │       │   │   ├── Jujuy
│   │   │       │   │   ├── La_Rioja
│   │   │       │   │   ├── Mendoza
│   │   │       │   │   ├── Rio_Gallegos
│   │   │       │   │   ├── Salta
│   │   │       │   │   ├── San_Juan
│   │   │       │   │   ├── San_Luis
│   │   │       │   │   ├── Tucuman
│   │   │       │   │   └── Ushuaia
│   │   │       │   ├── Aruba
│   │   │       │   ├── Asuncion
│   │   │       │   ├── Atikokan
│   │   │       │   ├── Atka
│   │   │       │   ├── Bahia
│   │   │       │   ├── Bahia_Banderas
│   │   │       │   ├── Barbados
│   │   │       │   ├── Belem
│   │   │       │   ├── Belize
│   │   │       │   ├── Blanc-Sablon
│   │   │       │   ├── Boa_Vista
│   │   │       │   ├── Bogota
│   │   │       │   ├── Boise
│   │   │       │   ├── Buenos_Aires
│   │   │       │   ├── Cambridge_Bay
│   │   │       │   ├── Campo_Grande
│   │   │       │   ├── Cancun
│   │   │       │   ├── Caracas
│   │   │       │   ├── Catamarca
│   │   │       │   ├── Cayenne
│   │   │       │   ├── Cayman
│   │   │       │   ├── Chicago
│   │   │       │   ├── Chihuahua
│   │   │       │   ├── Coral_Harbour
│   │   │       │   ├── Cordoba
│   │   │       │   ├── Costa_Rica
│   │   │       │   ├── Creston
│   │   │       │   ├── Cuiaba
│   │   │       │   ├── Curacao
│   │   │       │   ├── Danmarkshavn
│   │   │       │   ├── Dawson
│   │   │       │   ├── Dawson_Creek
│   │   │       │   ├── Denver
│   │   │       │   ├── Detroit
│   │   │       │   ├── Dominica
│   │   │       │   ├── Edmonton
│   │   │       │   ├── Eirunepe
│   │   │       │   ├── El_Salvador
│   │   │       │   ├── Ensenada
│   │   │       │   ├── Fort_Nelson
│   │   │       │   ├── Fort_Wayne
│   │   │       │   ├── Fortaleza
│   │   │       │   ├── Glace_Bay
│   │   │       │   ├── Godthab
│   │   │       │   ├── Goose_Bay
│   │   │       │   ├── Grand_Turk
│   │   │       │   ├── Grenada
│   │   │       │   ├── Guadeloupe
│   │   │       │   ├── Guatemala
│   │   │       │   ├── Guayaquil
│   │   │       │   ├── Guyana
│   │   │       │   ├── Halifax
│   │   │       │   ├── Havana
│   │   │       │   ├── Hermosillo
│   │   │       │   ├── Indiana/
│   │   │       │   │   ├── Indianapolis
│   │   │       │   │   ├── Knox
│   │   │       │   │   ├── Marengo
│   │   │       │   │   ├── Petersburg
│   │   │       │   │   ├── Tell_City
│   │   │       │   │   ├── Vevay
│   │   │       │   │   ├── Vincennes
│   │   │       │   │   └── Winamac
│   │   │       │   ├── Indianapolis
│   │   │       │   ├── Inuvik
│   │   │       │   ├── Iqaluit
│   │   │       │   ├── Jamaica
│   │   │       │   ├── Jujuy
│   │   │       │   ├── Juneau
│   │   │       │   ├── Kentucky/
│   │   │       │   │   ├── Louisville
│   │   │       │   │   └── Monticello
│   │   │       │   ├── Knox_IN
│   │   │       │   ├── Kralendijk
│   │   │       │   ├── La_Paz
│   │   │       │   ├── Lima
│   │   │       │   ├── Los_Angeles
│   │   │       │   ├── Louisville
│   │   │       │   ├── Lower_Princes
│   │   │       │   ├── Maceio
│   │   │       │   ├── Managua
│   │   │       │   ├── Manaus
│   │   │       │   ├── Marigot
│   │   │       │   ├── Martinique
│   │   │       │   ├── Matamoros
│   │   │       │   ├── Mazatlan
│   │   │       │   ├── Mendoza
│   │   │       │   ├── Menominee
│   │   │       │   ├── Merida
│   │   │       │   ├── Metlakatla
│   │   │       │   ├── Mexico_City
│   │   │       │   ├── Miquelon
│   │   │       │   ├── Moncton
│   │   │       │   ├── Monterrey
│   │   │       │   ├── Montevideo
│   │   │       │   ├── Montreal
│   │   │       │   ├── Montserrat
│   │   │       │   ├── Nassau
│   │   │       │   ├── New_York
│   │   │       │   ├── Nipigon
│   │   │       │   ├── Nome
│   │   │       │   ├── Noronha
│   │   │       │   ├── North_Dakota/
│   │   │       │   │   ├── Beulah
│   │   │       │   │   ├── Center
│   │   │       │   │   └── New_Salem
│   │   │       │   ├── Nuuk
│   │   │       │   ├── Ojinaga
│   │   │       │   ├── Panama
│   │   │       │   ├── Pangnirtung
│   │   │       │   ├── Paramaribo
│   │   │       │   ├── Phoenix
│   │   │       │   ├── Port-au-Prince
│   │   │       │   ├── Port_of_Spain
│   │   │       │   ├── Porto_Acre
│   │   │       │   ├── Porto_Velho
│   │   │       │   ├── Puerto_Rico
│   │   │       │   ├── Punta_Arenas
│   │   │       │   ├── Rainy_River
│   │   │       │   ├── Rankin_Inlet
│   │   │       │   ├── Recife
│   │   │       │   ├── Regina
│   │   │       │   ├── Resolute
│   │   │       │   ├── Rio_Branco
│   │   │       │   ├── Rosario
│   │   │       │   ├── Santa_Isabel
│   │   │       │   ├── Santarem
│   │   │       │   ├── Santiago
│   │   │       │   ├── Santo_Domingo
│   │   │       │   ├── Sao_Paulo
│   │   │       │   ├── Scoresbysund
│   │   │       │   ├── Shiprock
│   │   │       │   ├── Sitka
│   │   │       │   ├── St_Barthelemy
│   │   │       │   ├── St_Johns
│   │   │       │   ├── St_Kitts
│   │   │       │   ├── St_Lucia
│   │   │       │   ├── St_Thomas
│   │   │       │   ├── St_Vincent
│   │   │       │   ├── Swift_Current
│   │   │       │   ├── Tegucigalpa
│   │   │       │   ├── Thule
│   │   │       │   ├── Thunder_Bay
│   │   │       │   ├── Tijuana
│   │   │       │   ├── Toronto
│   │   │       │   ├── Tortola
│   │   │       │   ├── Vancouver
│   │   │       │   ├── Virgin
│   │   │       │   ├── Whitehorse
│   │   │       │   ├── Winnipeg
│   │   │       │   ├── Yakutat
│   │   │       │   └── Yellowknife
│   │   │       ├── Antarctica/
│   │   │       │   ├── Casey
│   │   │       │   ├── Davis
│   │   │       │   ├── DumontDUrville
│   │   │       │   ├── Macquarie
│   │   │       │   ├── Mawson
│   │   │       │   ├── McMurdo
│   │   │       │   ├── Palmer
│   │   │       │   ├── Rothera
│   │   │       │   ├── South_Pole
│   │   │       │   ├── Syowa
│   │   │       │   ├── Troll
│   │   │       │   └── Vostok
│   │   │       ├── Arctic/
│   │   │       │   └── Longyearbyen
│   │   │       ├── Asia/
│   │   │       │   ├── Aden
│   │   │       │   ├── Almaty
│   │   │       │   ├── Amman
│   │   │       │   ├── Anadyr
│   │   │       │   ├── Aqtau
│   │   │       │   ├── Aqtobe
│   │   │       │   ├── Ashgabat
│   │   │       │   ├── Ashkhabad
│   │   │       │   ├── Atyrau
│   │   │       │   ├── Baghdad
│   │   │       │   ├── Bahrain
│   │   │       │   ├── Baku
│   │   │       │   ├── Bangkok
│   │   │       │   ├── Barnaul
│   │   │       │   ├── Beirut
│   │   │       │   ├── Bishkek
│   │   │       │   ├── Brunei
│   │   │       │   ├── Calcutta
│   │   │       │   ├── Chita
│   │   │       │   ├── Choibalsan
│   │   │       │   ├── Chongqing
│   │   │       │   ├── Chungking
│   │   │       │   ├── Colombo
│   │   │       │   ├── Dacca
│   │   │       │   ├── Damascus
│   │   │       │   ├── Dhaka
│   │   │       │   ├── Dili
│   │   │       │   ├── Dubai
│   │   │       │   ├── Dushanbe
│   │   │       │   ├── Famagusta
│   │   │       │   ├── Gaza
│   │   │       │   ├── Harbin
│   │   │       │   ├── Hebron
│   │   │       │   ├── Ho_Chi_Minh
│   │   │       │   ├── Hong_Kong
│   │   │       │   ├── Hovd
│   │   │       │   ├── Irkutsk
│   │   │       │   ├── Istanbul
│   │   │       │   ├── Jakarta
│   │   │       │   ├── Jayapura
│   │   │       │   ├── Jerusalem
│   │   │       │   ├── Kabul
│   │   │       │   ├── Kamchatka
│   │   │       │   ├── Karachi
│   │   │       │   ├── Kashgar
│   │   │       │   ├── Kathmandu
│   │   │       │   ├── Katmandu
│   │   │       │   ├── Khandyga
│   │   │       │   ├── Kolkata
│   │   │       │   ├── Krasnoyarsk
│   │   │       │   ├── Kuala_Lumpur
│   │   │       │   ├── Kuching
│   │   │       │   ├── Kuwait
│   │   │       │   ├── Macao
│   │   │       │   ├── Macau
│   │   │       │   ├── Magadan
│   │   │       │   ├── Makassar
│   │   │       │   ├── Manila
│   │   │       │   ├── Muscat
│   │   │       │   ├── Nicosia
│   │   │       │   ├── Novokuznetsk
│   │   │       │   ├── Novosibirsk
│   │   │       │   ├── Omsk
│   │   │       │   ├── Oral
│   │   │       │   ├── Phnom_Penh
│   │   │       │   ├── Pontianak
│   │   │       │   ├── Pyongyang
│   │   │       │   ├── Qatar
│   │   │       │   ├── Qostanay
│   │   │       │   ├── Qyzylorda
│   │   │       │   ├── Rangoon
│   │   │       │   ├── Riyadh
│   │   │       │   ├── Saigon
│   │   │       │   ├── Sakhalin
│   │   │       │   ├── Samarkand
│   │   │       │   ├── Seoul
│   │   │       │   ├── Shanghai
│   │   │       │   ├── Singapore
│   │   │       │   ├── Srednekolymsk
│   │   │       │   ├── Taipei
│   │   │       │   ├── Tashkent
│   │   │       │   ├── Tbilisi
│   │   │       │   ├── Tehran
│   │   │       │   ├── Tel_Aviv
│   │   │       │   ├── Thimbu
│   │   │       │   ├── Thimphu
│   │   │       │   ├── Tokyo
│   │   │       │   ├── Tomsk
│   │   │       │   ├── Ujung_Pandang
│   │   │       │   ├── Ulaanbaatar
│   │   │       │   ├── Ulan_Bator
│   │   │       │   ├── Urumqi
│   │   │       │   ├── Ust-Nera
│   │   │       │   ├── Vientiane
│   │   │       │   ├── Vladivostok
│   │   │       │   ├── Yakutsk
│   │   │       │   ├── Yangon
│   │   │       │   ├── Yekaterinburg
│   │   │       │   └── Yerevan
│   │   │       ├── Atlantic/
│   │   │       │   ├── Azores
│   │   │       │   ├── Bermuda
│   │   │       │   ├── Canary
│   │   │       │   ├── Cape_Verde
│   │   │       │   ├── Faeroe
│   │   │       │   ├── Faroe
│   │   │       │   ├── Jan_Mayen
│   │   │       │   ├── Madeira
│   │   │       │   ├── Reykjavik
│   │   │       │   ├── South_Georgia
│   │   │       │   ├── St_Helena
│   │   │       │   └── Stanley
│   │   │       ├── Australia/
│   │   │       │   ├── ACT
│   │   │       │   ├── Adelaide
│   │   │       │   ├── Brisbane
│   │   │       │   ├── Broken_Hill
│   │   │       │   ├── Canberra
│   │   │       │   ├── Currie
│   │   │       │   ├── Darwin
│   │   │       │   ├── Eucla
│   │   │       │   ├── Hobart
│   │   │       │   ├── LHI
│   │   │       │   ├── Lindeman
│   │   │       │   ├── Lord_Howe
│   │   │       │   ├── Melbourne
│   │   │       │   ├── NSW
│   │   │       │   ├── North
│   │   │       │   ├── Perth
│   │   │       │   ├── Queensland
│   │   │       │   ├── South
│   │   │       │   ├── Sydney
│   │   │       │   ├── Tasmania
│   │   │       │   ├── Victoria
│   │   │       │   ├── West
│   │   │       │   └── Yancowinna
│   │   │       ├── Brazil/
│   │   │       │   ├── Acre
│   │   │       │   ├── DeNoronha
│   │   │       │   ├── East
│   │   │       │   └── West
│   │   │       ├── CET
│   │   │       ├── CST6CDT
│   │   │       ├── Canada/
│   │   │       │   ├── Atlantic
│   │   │       │   ├── Central
│   │   │       │   ├── Eastern
│   │   │       │   ├── Mountain
│   │   │       │   ├── Newfoundland
│   │   │       │   ├── Pacific
│   │   │       │   ├── Saskatchewan
│   │   │       │   └── Yukon
│   │   │       ├── Chile/
│   │   │       │   ├── Continental
│   │   │       │   └── EasterIsland
│   │   │       ├── Cuba
│   │   │       ├── EET
│   │   │       ├── EST
│   │   │       ├── EST5EDT
│   │   │       ├── Egypt
│   │   │       ├── Eire
│   │   │       ├── Etc/
│   │   │       │   ├── GMT
│   │   │       │   ├── GMT+0
│   │   │       │   ├── GMT+1
│   │   │       │   ├── GMT+10
│   │   │       │   ├── GMT+11
│   │   │       │   ├── GMT+12
│   │   │       │   ├── GMT+2
│   │   │       │   ├── GMT+3
│   │   │       │   ├── GMT+4
│   │   │       │   ├── GMT+5
│   │   │       │   ├── GMT+6
│   │   │       │   ├── GMT+7
│   │   │       │   ├── GMT+8
│   │   │       │   ├── GMT+9
│   │   │       │   ├── GMT-0
│   │   │       │   ├── GMT-1
│   │   │       │   ├── GMT-10
│   │   │       │   ├── GMT-11
│   │   │       │   ├── GMT-12
│   │   │       │   ├── GMT-13
│   │   │       │   ├── GMT-14
│   │   │       │   ├── GMT-2
│   │   │       │   ├── GMT-3
│   │   │       │   ├── GMT-4
│   │   │       │   ├── GMT-5
│   │   │       │   ├── GMT-6
│   │   │       │   ├── GMT-7
│   │   │       │   ├── GMT-8
│   │   │       │   ├── GMT-9
│   │   │       │   ├── GMT0
│   │   │       │   ├── Greenwich
│   │   │       │   ├── UCT
│   │   │       │   ├── UTC
│   │   │       │   ├── Universal
│   │   │       │   └── Zulu
│   │   │       ├── Europe/
│   │   │       │   ├── Amsterdam
│   │   │       │   ├── Andorra
│   │   │       │   ├── Astrakhan
│   │   │       │   ├── Athens
│   │   │       │   ├── Belfast
│   │   │       │   ├── Belgrade
│   │   │       │   ├── Berlin
│   │   │       │   ├── Bratislava
│   │   │       │   ├── Brussels
│   │   │       │   ├── Bucharest
│   │   │       │   ├── Budapest
│   │   │       │   ├── Busingen
│   │   │       │   ├── Chisinau
│   │   │       │   ├── Copenhagen
│   │   │       │   ├── Dublin
│   │   │       │   ├── Gibraltar
│   │   │       │   ├── Guernsey
│   │   │       │   ├── Helsinki
│   │   │       │   ├── Isle_of_Man
│   │   │       │   ├── Istanbul
│   │   │       │   ├── Jersey
│   │   │       │   ├── Kaliningrad
│   │   │       │   ├── Kiev
│   │   │       │   ├── Kirov
│   │   │       │   ├── Kyiv
│   │   │       │   ├── Lisbon
│   │   │       │   ├── Ljubljana
│   │   │       │   ├── London
│   │   │       │   ├── Luxembourg
│   │   │       │   ├── Madrid
│   │   │       │   ├── Malta
│   │   │       │   ├── Mariehamn
│   │   │       │   ├── Minsk
│   │   │       │   ├── Monaco
│   │   │       │   ├── Moscow
│   │   │       │   ├── Nicosia
│   │   │       │   ├── Oslo
│   │   │       │   ├── Paris
│   │   │       │   ├── Podgorica
│   │   │       │   ├── Prague
│   │   │       │   ├── Riga
│   │   │       │   ├── Rome
│   │   │       │   ├── Samara
│   │   │       │   ├── San_Marino
│   │   │       │   ├── Sarajevo
│   │   │       │   ├── Saratov
│   │   │       │   ├── Simferopol
│   │   │       │   ├── Skopje
│   │   │       │   ├── Sofia
│   │   │       │   ├── Stockholm
│   │   │       │   ├── Tallinn
│   │   │       │   ├── Tirane
│   │   │       │   ├── Tiraspol
│   │   │       │   ├── Ulyanovsk
│   │   │       │   ├── Uzhgorod
│   │   │       │   ├── Vaduz
│   │   │       │   ├── Vatican
│   │   │       │   ├── Vienna
│   │   │       │   ├── Vilnius
│   │   │       │   ├── Volgograd
│   │   │       │   ├── Warsaw
│   │   │       │   ├── Zagreb
│   │   │       │   ├── Zaporozhye
│   │   │       │   └── Zurich
│   │   │       ├── Factory
│   │   │       ├── GB
│   │   │       ├── GB-Eire
│   │   │       ├── GMT
│   │   │       ├── GMT+0
│   │   │       ├── GMT-0
│   │   │       ├── GMT0
│   │   │       ├── Greenwich
│   │   │       ├── HST
│   │   │       ├── Hongkong
│   │   │       ├── Iceland
│   │   │       ├── Indian/
│   │   │       │   ├── Antananarivo
│   │   │       │   ├── Chagos
│   │   │       │   ├── Christmas
│   │   │       │   ├── Cocos
│   │   │       │   ├── Comoro
│   │   │       │   ├── Kerguelen
│   │   │       │   ├── Mahe
│   │   │       │   ├── Maldives
│   │   │       │   ├── Mauritius
│   │   │       │   ├── Mayotte
│   │   │       │   └── Reunion
│   │   │       ├── Iran
│   │   │       ├── Israel
│   │   │       ├── Jamaica
│   │   │       ├── Japan
│   │   │       ├── Kwajalein
│   │   │       ├── Libya
│   │   │       ├── MET
│   │   │       ├── MST
│   │   │       ├── MST7MDT
│   │   │       ├── Mexico/
│   │   │       │   ├── BajaNorte
│   │   │       │   ├── BajaSur
│   │   │       │   └── General
│   │   │       ├── NZ
│   │   │       ├── NZ-CHAT
│   │   │       ├── Navajo
│   │   │       ├── PRC
│   │   │       ├── PST8PDT
│   │   │       ├── Pacific/
│   │   │       │   ├── Apia
│   │   │       │   ├── Auckland
│   │   │       │   ├── Bougainville
│   │   │       │   ├── Chatham
│   │   │       │   ├── Chuuk
│   │   │       │   ├── Easter
│   │   │       │   ├── Efate
│   │   │       │   ├── Enderbury
│   │   │       │   ├── Fakaofo
│   │   │       │   ├── Fiji
│   │   │       │   ├── Funafuti
│   │   │       │   ├── Galapagos
│   │   │       │   ├── Gambier
│   │   │       │   ├── Guadalcanal
│   │   │       │   ├── Guam
│   │   │       │   ├── Honolulu
│   │   │       │   ├── Johnston
│   │   │       │   ├── Kanton
│   │   │       │   ├── Kiritimati
│   │   │       │   ├── Kosrae
│   │   │       │   ├── Kwajalein
│   │   │       │   ├── Majuro
│   │   │       │   ├── Marquesas
│   │   │       │   ├── Midway
│   │   │       │   ├── Nauru
│   │   │       │   ├── Niue
│   │   │       │   ├── Norfolk
│   │   │       │   ├── Noumea
│   │   │       │   ├── Pago_Pago
│   │   │       │   ├── Palau
│   │   │       │   ├── Pitcairn
│   │   │       │   ├── Pohnpei
│   │   │       │   ├── Ponape
│   │   │       │   ├── Port_Moresby
│   │   │       │   ├── Rarotonga
│   │   │       │   ├── Saipan
│   │   │       │   ├── Samoa
│   │   │       │   ├── Tahiti
│   │   │       │   ├── Tarawa
│   │   │       │   ├── Tongatapu
│   │   │       │   ├── Truk
│   │   │       │   ├── Wake
│   │   │       │   ├── Wallis
│   │   │       │   └── Yap
│   │   │       ├── Poland
│   │   │       ├── Portugal
│   │   │       ├── ROC
│   │   │       ├── ROK
│   │   │       ├── Singapore
│   │   │       ├── Turkey
│   │   │       ├── UCT
│   │   │       ├── US/
│   │   │       │   ├── Alaska
│   │   │       │   ├── Aleutian
│   │   │       │   ├── Arizona
│   │   │       │   ├── Central
│   │   │       │   ├── East-Indiana
│   │   │       │   ├── Eastern
│   │   │       │   ├── Hawaii
│   │   │       │   ├── Indiana-Starke
│   │   │       │   ├── Michigan
│   │   │       │   ├── Mountain
│   │   │       │   ├── Pacific
│   │   │       │   └── Samoa
│   │   │       ├── UTC
│   │   │       ├── Universal
│   │   │       ├── W-SU
│   │   │       ├── WET
│   │   │       ├── Zulu
│   │   │       ├── iso3166.tab
│   │   │       ├── leapseconds
│   │   │       ├── tzdata.zi
│   │   │       ├── zone.tab
│   │   │       └── zone1970.tab
│   │   ├── qbittorrent/
│   │   │   ├── __init__.py
│   │   │   └── client.py
│   │   ├── rarfile.py
│   │   ├── rebulk/
│   │   │   ├── __init__.py
│   │   │   ├── __version__.py
│   │   │   ├── builder.py
│   │   │   ├── chain.py
│   │   │   ├── debug.py
│   │   │   ├── formatters.py
│   │   │   ├── introspector.py
│   │   │   ├── loose.py
│   │   │   ├── match.py
│   │   │   ├── pattern.py
│   │   │   ├── processors.py
│   │   │   ├── rebulk.py
│   │   │   ├── remodule.py
│   │   │   ├── rules.py
│   │   │   ├── test/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── default_rules_module.py
│   │   │   │   ├── rebulk_rules_module.py
│   │   │   │   ├── rules_module.py
│   │   │   │   ├── test_chain.py
│   │   │   │   ├── test_debug.py
│   │   │   │   ├── test_introspector.py
│   │   │   │   ├── test_loose.py
│   │   │   │   ├── test_match.py
│   │   │   │   ├── test_pattern.py
│   │   │   │   ├── test_processors.py
│   │   │   │   ├── test_rebulk.py
│   │   │   │   ├── test_rules.py
│   │   │   │   ├── test_toposort.py
│   │   │   │   └── test_validators.py
│   │   │   ├── toposort.py
│   │   │   ├── utils.py
│   │   │   └── validators.py
│   │   ├── rencode/
│   │   │   ├── __init__.py
│   │   │   └── rencode_orig.py
│   │   ├── requests/
│   │   │   ├── __init__.py
│   │   │   ├── __version__.py
│   │   │   ├── _internal_utils.py
│   │   │   ├── adapters.py
│   │   │   ├── api.py
│   │   │   ├── auth.py
│   │   │   ├── certs.py
│   │   │   ├── compat.py
│   │   │   ├── cookies.py
│   │   │   ├── exceptions.py
│   │   │   ├── help.py
│   │   │   ├── hooks.py
│   │   │   ├── models.py
│   │   │   ├── packages.py
│   │   │   ├── sessions.py
│   │   │   ├── status_codes.py
│   │   │   ├── structures.py
│   │   │   └── utils.py
│   │   ├── requests_oauthlib/
│   │   │   ├── __init__.py
│   │   │   ├── compliance_fixes/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── douban.py
│   │   │   │   ├── ebay.py
│   │   │   │   ├── facebook.py
│   │   │   │   ├── fitbit.py
│   │   │   │   ├── instagram.py
│   │   │   │   ├── mailchimp.py
│   │   │   │   ├── plentymarkets.py
│   │   │   │   ├── slack.py
│   │   │   │   └── weibo.py
│   │   │   ├── oauth1_auth.py
│   │   │   ├── oauth1_session.py
│   │   │   ├── oauth2_auth.py
│   │   │   └── oauth2_session.py
│   │   ├── setuptools/
│   │   │   ├── __init__.py
│   │   │   ├── _imp.py
│   │   │   ├── _vendor/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── ordered_set.py
│   │   │   │   └── packaging/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── _structures.py
│   │   │   │       ├── markers.py
│   │   │   │       ├── requirements.py
│   │   │   │       ├── specifiers.py
│   │   │   │       ├── tags.py
│   │   │   │       ├── utils.py
│   │   │   │       └── version.py
│   │   │   ├── archive_util.py
│   │   │   ├── build_meta.py
│   │   │   ├── command/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── alias.py
│   │   │   │   ├── bdist_egg.py
│   │   │   │   ├── bdist_rpm.py
│   │   │   │   ├── build_clib.py
│   │   │   │   ├── build_ext.py
│   │   │   │   ├── build_py.py
│   │   │   │   ├── develop.py
│   │   │   │   ├── dist_info.py
│   │   │   │   ├── easy_install.py
│   │   │   │   ├── egg_info.py
│   │   │   │   ├── install.py
│   │   │   │   ├── install_egg_info.py
│   │   │   │   ├── install_lib.py
│   │   │   │   ├── install_scripts.py
│   │   │   │   ├── launcher manifest.xml
│   │   │   │   ├── register.py
│   │   │   │   ├── rotate.py
│   │   │   │   ├── saveopts.py
│   │   │   │   ├── sdist.py
│   │   │   │   ├── setopt.py
│   │   │   │   ├── test.py
│   │   │   │   ├── upload.py
│   │   │   │   └── upload_docs.py
│   │   │   ├── dep_util.py
│   │   │   ├── depends.py
│   │   │   ├── dist.py
│   │   │   ├── errors.py
│   │   │   ├── extension.py
│   │   │   ├── extern/
│   │   │   │   └── __init__.py
│   │   │   ├── glob.py
│   │   │   ├── installer.py
│   │   │   ├── launch.py
│   │   │   ├── monkey.py
│   │   │   ├── msvc.py
│   │   │   ├── namespaces.py
│   │   │   ├── package_index.py
│   │   │   ├── sandbox.py
│   │   │   ├── script (dev).tmpl
│   │   │   ├── script.tmpl
│   │   │   ├── unicode_utils.py
│   │   │   ├── version.py
│   │   │   ├── wheel.py
│   │   │   └── windows_support.py
│   │   ├── share/
│   │   │   └── man/
│   │   │       └── man1/
│   │   │           ├── mid3cp.1
│   │   │           ├── mid3iconv.1
│   │   │           ├── mid3v2.1
│   │   │           ├── moggsplit.1
│   │   │           ├── mutagen-inspect.1
│   │   │           └── mutagen-pony.1
│   │   ├── six.py
│   │   ├── soupsieve/
│   │   │   ├── __init__.py
│   │   │   ├── __meta__.py
│   │   │   ├── css_match.py
│   │   │   ├── css_parser.py
│   │   │   ├── css_types.py
│   │   │   ├── pretty.py
│   │   │   ├── py.typed
│   │   │   └── util.py
│   │   ├── stevedore/
│   │   │   ├── __init__.py
│   │   │   ├── dispatch.py
│   │   │   ├── driver.py
│   │   │   ├── enabled.py
│   │   │   ├── example/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── base.py
│   │   │   │   ├── load_as_driver.py
│   │   │   │   ├── load_as_extension.py
│   │   │   │   ├── setup.py
│   │   │   │   └── simple.py
│   │   │   ├── example2/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── fields.py
│   │   │   │   └── setup.py
│   │   │   ├── exception.py
│   │   │   ├── extension.py
│   │   │   ├── hook.py
│   │   │   ├── named.py
│   │   │   ├── sphinxext.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── extension_unimportable.py
│   │   │       ├── manager.py
│   │   │       ├── test_callback.py
│   │   │       ├── test_dispatch.py
│   │   │       ├── test_driver.py
│   │   │       ├── test_enabled.py
│   │   │       ├── test_example_fields.py
│   │   │       ├── test_example_simple.py
│   │   │       ├── test_extension.py
│   │   │       ├── test_hook.py
│   │   │       ├── test_named.py
│   │   │       ├── test_sphinxext.py
│   │   │       ├── test_test_manager.py
│   │   │       └── utils.py
│   │   ├── subliminal/
│   │   │   ├── __init__.py
│   │   │   ├── cache.py
│   │   │   ├── cli.py
│   │   │   ├── converters/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── addic7ed.py
│   │   │   │   ├── legendastv.py
│   │   │   │   ├── shooter.py
│   │   │   │   ├── thesubdb.py
│   │   │   │   └── tvsubtitles.py
│   │   │   ├── core.py
│   │   │   ├── exceptions.py
│   │   │   ├── extensions.py
│   │   │   ├── matches.py
│   │   │   ├── providers/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── addic7ed.py
│   │   │   │   ├── argenteam.py
│   │   │   │   ├── legendastv.py
│   │   │   │   ├── napiprojekt.py
│   │   │   │   ├── opensubtitles.py
│   │   │   │   ├── podnapisi.py
│   │   │   │   ├── shooter.py
│   │   │   │   ├── thesubdb.py
│   │   │   │   └── tvsubtitles.py
│   │   │   ├── refiners/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── hash.py
│   │   │   │   ├── metadata.py
│   │   │   │   ├── omdb.py
│   │   │   │   └── tvdb.py
│   │   │   ├── score.py
│   │   │   ├── subtitle.py
│   │   │   ├── utils.py
│   │   │   └── video.py
│   │   ├── transmissionrpc/
│   │   │   ├── __init__.py
│   │   │   ├── client.py
│   │   │   ├── constants.py
│   │   │   ├── error.py
│   │   │   ├── httphandler.py
│   │   │   ├── session.py
│   │   │   ├── torrent.py
│   │   │   └── utils.py
│   │   ├── typing_extensions.py
│   │   ├── unidecode/
│   │   │   ├── __init__.py
│   │   │   ├── __init__.pyi
│   │   │   ├── __main__.py
│   │   │   ├── py.typed
│   │   │   ├── util.py
│   │   │   ├── x000.py
│   │   │   ├── x001.py
│   │   │   ├── x002.py
│   │   │   ├── x003.py
│   │   │   ├── x004.py
│   │   │   ├── x005.py
│   │   │   ├── x006.py
│   │   │   ├── x007.py
│   │   │   ├── x009.py
│   │   │   ├── x00a.py
│   │   │   ├── x00b.py
│   │   │   ├── x00c.py
│   │   │   ├── x00d.py
│   │   │   ├── x00e.py
│   │   │   ├── x00f.py
│   │   │   ├── x010.py
│   │   │   ├── x011.py
│   │   │   ├── x012.py
│   │   │   ├── x013.py
│   │   │   ├── x014.py
│   │   │   ├── x015.py
│   │   │   ├── x016.py
│   │   │   ├── x017.py
│   │   │   ├── x018.py
│   │   │   ├── x01d.py
│   │   │   ├── x01e.py
│   │   │   ├── x01f.py
│   │   │   ├── x020.py
│   │   │   ├── x021.py
│   │   │   ├── x022.py
│   │   │   ├── x023.py
│   │   │   ├── x024.py
│   │   │   ├── x025.py
│   │   │   ├── x026.py
│   │   │   ├── x027.py
│   │   │   ├── x028.py
│   │   │   ├── x029.py
│   │   │   ├── x02a.py
│   │   │   ├── x02c.py
│   │   │   ├── x02e.py
│   │   │   ├── x02f.py
│   │   │   ├── x030.py
│   │   │   ├── x031.py
│   │   │   ├── x032.py
│   │   │   ├── x033.py
│   │   │   ├── x04d.py
│   │   │   ├── x04e.py
│   │   │   ├── x04f.py
│   │   │   ├── x050.py
│   │   │   ├── x051.py
│   │   │   ├── x052.py
│   │   │   ├── x053.py
│   │   │   ├── x054.py
│   │   │   ├── x055.py
│   │   │   ├── x056.py
│   │   │   ├── x057.py
│   │   │   ├── x058.py
│   │   │   ├── x059.py
│   │   │   ├── x05a.py
│   │   │   ├── x05b.py
│   │   │   ├── x05c.py
│   │   │   ├── x05d.py
│   │   │   ├── x05e.py
│   │   │   ├── x05f.py
│   │   │   ├── x060.py
│   │   │   ├── x061.py
│   │   │   ├── x062.py
│   │   │   ├── x063.py
│   │   │   ├── x064.py
│   │   │   ├── x065.py
│   │   │   ├── x066.py
│   │   │   ├── x067.py
│   │   │   ├── x068.py
│   │   │   ├── x069.py
│   │   │   ├── x06a.py
│   │   │   ├── x06b.py
│   │   │   ├── x06c.py
│   │   │   ├── x06d.py
│   │   │   ├── x06e.py
│   │   │   ├── x06f.py
│   │   │   ├── x070.py
│   │   │   ├── x071.py
│   │   │   ├── x072.py
│   │   │   ├── x073.py
│   │   │   ├── x074.py
│   │   │   ├── x075.py
│   │   │   ├── x076.py
│   │   │   ├── x077.py
│   │   │   ├── x078.py
│   │   │   ├── x079.py
│   │   │   ├── x07a.py
│   │   │   ├── x07b.py
│   │   │   ├── x07c.py
│   │   │   ├── x07d.py
│   │   │   ├── x07e.py
│   │   │   ├── x07f.py
│   │   │   ├── x080.py
│   │   │   ├── x081.py
│   │   │   ├── x082.py
│   │   │   ├── x083.py
│   │   │   ├── x084.py
│   │   │   ├── x085.py
│   │   │   ├── x086.py
│   │   │   ├── x087.py
│   │   │   ├── x088.py
│   │   │   ├── x089.py
│   │   │   ├── x08a.py
│   │   │   ├── x08b.py
│   │   │   ├── x08c.py
│   │   │   ├── x08d.py
│   │   │   ├── x08e.py
│   │   │   ├── x08f.py
│   │   │   ├── x090.py
│   │   │   ├── x091.py
│   │   │   ├── x092.py
│   │   │   ├── x093.py
│   │   │   ├── x094.py
│   │   │   ├── x095.py
│   │   │   ├── x096.py
│   │   │   ├── x097.py
│   │   │   ├── x098.py
│   │   │   ├── x099.py
│   │   │   ├── x09a.py
│   │   │   ├── x09b.py
│   │   │   ├── x09c.py
│   │   │   ├── x09d.py
│   │   │   ├── x09e.py
│   │   │   ├── x09f.py
│   │   │   ├── x0a0.py
│   │   │   ├── x0a1.py
│   │   │   ├── x0a2.py
│   │   │   ├── x0a3.py
│   │   │   ├── x0a4.py
│   │   │   ├── x0ac.py
│   │   │   ├── x0ad.py
│   │   │   ├── x0ae.py
│   │   │   ├── x0af.py
│   │   │   ├── x0b0.py
│   │   │   ├── x0b1.py
│   │   │   ├── x0b2.py
│   │   │   ├── x0b3.py
│   │   │   ├── x0b4.py
│   │   │   ├── x0b5.py
│   │   │   ├── x0b6.py
│   │   │   ├── x0b7.py
│   │   │   ├── x0b8.py
│   │   │   ├── x0b9.py
│   │   │   ├── x0ba.py
│   │   │   ├── x0bb.py
│   │   │   ├── x0bc.py
│   │   │   ├── x0bd.py
│   │   │   ├── x0be.py
│   │   │   ├── x0bf.py
│   │   │   ├── x0c0.py
│   │   │   ├── x0c1.py
│   │   │   ├── x0c2.py
│   │   │   ├── x0c3.py
│   │   │   ├── x0c4.py
│   │   │   ├── x0c5.py
│   │   │   ├── x0c6.py
│   │   │   ├── x0c7.py
│   │   │   ├── x0c8.py
│   │   │   ├── x0c9.py
│   │   │   ├── x0ca.py
│   │   │   ├── x0cb.py
│   │   │   ├── x0cc.py
│   │   │   ├── x0cd.py
│   │   │   ├── x0ce.py
│   │   │   ├── x0cf.py
│   │   │   ├── x0d0.py
│   │   │   ├── x0d1.py
│   │   │   ├── x0d2.py
│   │   │   ├── x0d3.py
│   │   │   ├── x0d4.py
│   │   │   ├── x0d5.py
│   │   │   ├── x0d6.py
│   │   │   ├── x0d7.py
│   │   │   ├── x0f9.py
│   │   │   ├── x0fa.py
│   │   │   ├── x0fb.py
│   │   │   ├── x0fc.py
│   │   │   ├── x0fd.py
│   │   │   ├── x0fe.py
│   │   │   ├── x0ff.py
│   │   │   ├── x1d4.py
│   │   │   ├── x1d5.py
│   │   │   ├── x1d6.py
│   │   │   ├── x1d7.py
│   │   │   ├── x1f1.py
│   │   │   └── x1f6.py
│   │   ├── urllib3/
│   │   │   ├── __init__.py
│   │   │   ├── _collections.py
│   │   │   ├── _version.py
│   │   │   ├── connection.py
│   │   │   ├── connectionpool.py
│   │   │   ├── contrib/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _appengine_environ.py
│   │   │   │   ├── _securetransport/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── bindings.py
│   │   │   │   │   └── low_level.py
│   │   │   │   ├── appengine.py
│   │   │   │   ├── ntlmpool.py
│   │   │   │   ├── pyopenssl.py
│   │   │   │   ├── securetransport.py
│   │   │   │   └── socks.py
│   │   │   ├── exceptions.py
│   │   │   ├── fields.py
│   │   │   ├── filepost.py
│   │   │   ├── packages/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── backports/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   └── makefile.py
│   │   │   │   └── six.py
│   │   │   ├── poolmanager.py
│   │   │   ├── request.py
│   │   │   ├── response.py
│   │   │   └── util/
│   │   │       ├── __init__.py
│   │   │       ├── connection.py
│   │   │       ├── proxy.py
│   │   │       ├── queue.py
│   │   │       ├── request.py
│   │   │       ├── response.py
│   │   │       ├── retry.py
│   │   │       ├── ssl_.py
│   │   │       ├── ssl_match_hostname.py
│   │   │       ├── ssltransport.py
│   │   │       ├── timeout.py
│   │   │       ├── url.py
│   │   │       └── wait.py
│   │   ├── validate.py
│   │   ├── xdg/
│   │   │   ├── BaseDirectory.py
│   │   │   ├── Config.py
│   │   │   ├── DesktopEntry.py
│   │   │   ├── Exceptions.py
│   │   │   ├── IconTheme.py
│   │   │   ├── IniFile.py
│   │   │   ├── Locale.py
│   │   │   ├── Menu.py
│   │   │   ├── MenuEditor.py
│   │   │   ├── Mime.py
│   │   │   ├── RecentFiles.py
│   │   │   ├── __init__.py
│   │   │   └── util.py
│   │   ├── yaml/
│   │   │   ├── __init__.py
│   │   │   ├── composer.py
│   │   │   ├── constructor.py
│   │   │   ├── cyaml.py
│   │   │   ├── dumper.py
│   │   │   ├── emitter.py
│   │   │   ├── error.py
│   │   │   ├── events.py
│   │   │   ├── loader.py
│   │   │   ├── nodes.py
│   │   │   ├── parser.py
│   │   │   ├── reader.py
│   │   │   ├── representer.py
│   │   │   ├── resolver.py
│   │   │   ├── scanner.py
│   │   │   ├── serializer.py
│   │   │   └── tokens.py
│   │   └── zipp.py
│   ├── custom/
│   │   ├── deluge_client/
│   │   │   ├── __init__.py
│   │   │   ├── client.py
│   │   │   ├── rencode.py
│   │   │   └── tests.py
│   │   ├── syno/
│   │   │   ├── __init__.py
│   │   │   ├── auth.py
│   │   │   └── downloadstation.py
│   │   └── utorrent/
│   │       ├── __init__.py
│   │       ├── client.py
│   │       └── upload.py
│   ├── py2/
│   │   ├── backports/
│   │   │   ├── __init__.py
│   │   │   └── functools_lru_cache.py
│   │   ├── bs4/
│   │   │   ├── __init__.py
│   │   │   ├── builder/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _html5lib.py
│   │   │   │   ├── _htmlparser.py
│   │   │   │   └── _lxml.py
│   │   │   ├── dammit.py
│   │   │   ├── diagnose.py
│   │   │   ├── element.py
│   │   │   ├── testing.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── test_builder_registry.py
│   │   │       ├── test_docs.py
│   │   │       ├── test_html5lib.py
│   │   │       ├── test_htmlparser.py
│   │   │       ├── test_lxml.py
│   │   │       ├── test_soup.py
│   │   │       └── test_tree.py
│   │   ├── concurrent/
│   │   │   ├── __init__.py
│   │   │   └── futures/
│   │   │       ├── __init__.py
│   │   │       ├── _base.py
│   │   │       ├── process.py
│   │   │       └── thread.py
│   │   ├── enum/
│   │   │   ├── LICENSE
│   │   │   ├── README
│   │   │   └── __init__.py
│   │   └── yaml/
│   │       ├── __init__.py
│   │       ├── composer.py
│   │       ├── constructor.py
│   │       ├── cyaml.py
│   │       ├── dumper.py
│   │       ├── emitter.py
│   │       ├── error.py
│   │       ├── events.py
│   │       ├── loader.py
│   │       ├── nodes.py
│   │       ├── parser.py
│   │       ├── reader.py
│   │       ├── representer.py
│   │       ├── resolver.py
│   │       ├── scanner.py
│   │       ├── serializer.py
│   │       └── tokens.py
│   ├── requirements-common.txt
│   ├── requirements-custom.txt
│   ├── requirements-py2.txt
│   ├── requirements-win.txt
│   ├── requirements.txt
│   ├── util.py
│   └── win/
│       ├── autocommand/
│       │   ├── __init__.py
│       │   ├── autoasync.py
│       │   ├── autocommand.py
│       │   ├── automain.py
│       │   ├── autoparse.py
│       │   └── errors.py
│       ├── bugs/
│       │   ├── environ-api-wierdness.py
│       │   ├── find_target_path.py
│       │   ├── multi_os_libc.py
│       │   ├── vista-symlink-islink-bug.py
│       │   └── wnetaddconnection2-error-on-64-bit.py
│       ├── importlib_resources/
│       │   ├── __init__.py
│       │   ├── _adapters.py
│       │   ├── _common.py
│       │   ├── _compat.py
│       │   ├── _itertools.py
│       │   ├── _legacy.py
│       │   ├── abc.py
│       │   ├── py.typed
│       │   ├── readers.py
│       │   ├── simple.py
│       │   └── tests/
│       │       ├── __init__.py
│       │       ├── _compat.py
│       │       ├── _path.py
│       │       ├── data01/
│       │       │   ├── __init__.py
│       │       │   ├── binary.file
│       │       │   ├── subdirectory/
│       │       │   │   ├── __init__.py
│       │       │   │   └── binary.file
│       │       │   ├── utf-16.file
│       │       │   └── utf-8.file
│       │       ├── data02/
│       │       │   ├── __init__.py
│       │       │   ├── one/
│       │       │   │   ├── __init__.py
│       │       │   │   └── resource1.txt
│       │       │   └── two/
│       │       │       ├── __init__.py
│       │       │       └── resource2.txt
│       │       ├── namespacedata01/
│       │       │   ├── binary.file
│       │       │   ├── utf-16.file
│       │       │   └── utf-8.file
│       │       ├── test_compatibilty_files.py
│       │       ├── test_contents.py
│       │       ├── test_files.py
│       │       ├── test_open.py
│       │       ├── test_path.py
│       │       ├── test_read.py
│       │       ├── test_reader.py
│       │       ├── test_resource.py
│       │       ├── update-zips.py
│       │       ├── util.py
│       │       ├── zipdata01/
│       │       │   └── __init__.py
│       │       └── zipdata02/
│       │           └── __init__.py
│       ├── incubator/
│       │   ├── replace-file.py
│       │   └── trace-symlink.py
│       ├── inflect/
│       │   ├── __init__.py
│       │   └── py.typed
│       ├── jaraco/
│       │   ├── classes/
│       │   │   ├── __init__.py
│       │   │   ├── ancestry.py
│       │   │   ├── meta.py
│       │   │   └── properties.py
│       │   ├── collections.py
│       │   ├── context.py
│       │   ├── functools.py
│       │   ├── structures/
│       │   │   ├── __init__.py
│       │   │   └── binary.py
│       │   ├── text/
│       │   │   ├── Lorem ipsum.txt
│       │   │   ├── __init__.py
│       │   │   ├── layouts.py
│       │   │   ├── show-newlines.py
│       │   │   ├── strip-prefix.py
│       │   │   ├── to-dvorak.py
│       │   │   └── to-qwerty.py
│       │   ├── ui/
│       │   │   ├── __init__.py
│       │   │   ├── cmdline.py
│       │   │   ├── editor.py
│       │   │   ├── input.py
│       │   │   ├── menu.py
│       │   │   └── progress.py
│       │   └── windows/
│       │       ├── __init__.py
│       │       ├── api/
│       │       │   ├── __init__.py
│       │       │   ├── clipboard.py
│       │       │   ├── credential.py
│       │       │   ├── environ.py
│       │       │   ├── errors.py
│       │       │   ├── event.py
│       │       │   ├── filesystem.py
│       │       │   ├── inet.py
│       │       │   ├── library.py
│       │       │   ├── memory.py
│       │       │   ├── message.py
│       │       │   ├── net.py
│       │       │   ├── power.py
│       │       │   ├── privilege.py
│       │       │   ├── process.py
│       │       │   ├── security.py
│       │       │   ├── shell.py
│       │       │   ├── system.py
│       │       │   └── user.py
│       │       ├── batch.py
│       │       ├── clipboard.py
│       │       ├── cred.py
│       │       ├── dpapi.py
│       │       ├── environ.py
│       │       ├── error.py
│       │       ├── eventlog.py
│       │       ├── filesystem/
│       │       │   ├── __init__.py
│       │       │   ├── backports.py
│       │       │   └── change.py
│       │       ├── inet.py
│       │       ├── lib.py
│       │       ├── memory.py
│       │       ├── mmap.py
│       │       ├── msie.py
│       │       ├── msvc.py
│       │       ├── net.py
│       │       ├── power.py
│       │       ├── privilege.py
│       │       ├── registry.py
│       │       ├── reparse.py
│       │       ├── security.py
│       │       ├── services.py
│       │       ├── shell.py
│       │       ├── timers.py
│       │       ├── timezone.py
│       │       ├── ui.py
│       │       ├── user.py
│       │       ├── util.py
│       │       ├── vpn.py
│       │       └── xmouse.py
│       ├── more_itertools/
│       │   ├── __init__.py
│       │   ├── __init__.pyi
│       │   ├── more.py
│       │   ├── more.pyi
│       │   ├── py.typed
│       │   ├── recipes.py
│       │   └── recipes.pyi
│       ├── path/
│       │   ├── __init__.py
│       │   ├── __init__.pyi
│       │   ├── classes.py
│       │   ├── classes.pyi
│       │   ├── masks.py
│       │   ├── masks.pyi
│       │   ├── matchers.py
│       │   ├── matchers.pyi
│       │   ├── py.typed
│       │   ├── py37compat.py
│       │   └── py37compat.pyi
│       ├── pydantic/
│       │   ├── __init__.py
│       │   ├── _hypothesis_plugin.py
│       │   ├── annotated_types.py
│       │   ├── class_validators.py
│       │   ├── color.py
│       │   ├── config.py
│       │   ├── dataclasses.py
│       │   ├── datetime_parse.py
│       │   ├── decorator.py
│       │   ├── env_settings.py
│       │   ├── error_wrappers.py
│       │   ├── errors.py
│       │   ├── fields.py
│       │   ├── generics.py
│       │   ├── json.py
│       │   ├── main.py
│       │   ├── mypy.py
│       │   ├── networks.py
│       │   ├── parse.py
│       │   ├── py.typed
│       │   ├── schema.py
│       │   ├── tools.py
│       │   ├── types.py
│       │   ├── typing.py
│       │   ├── utils.py
│       │   ├── validators.py
│       │   └── version.py
│       ├── scripts/
│       │   └── watch-changes.py
│       ├── typing_extensions.py
│       └── zipp/
│           ├── __init__.py
│           └── py310compat.py
├── license.txt
├── nzbToCouchPotato.py
├── nzbToGamez.py
├── nzbToHeadPhones.py
├── nzbToLazyLibrarian.py
├── nzbToLidarr.py
├── nzbToMedia.py
├── nzbToMylar.py
├── nzbToNzbDrone.py
├── nzbToRadarr.py
├── nzbToReadarr.py
├── nzbToSiCKRAGE.py
├── nzbToSickBeard.py
├── nzbToWatcher3.py
├── setup.py
├── tests/
│   ├── __init__.py
│   ├── test_initialize.py
│   └── test_transcoder.py
└── tox.ini

================================================
FILE CONTENTS
================================================

================================================
FILE: .bumpversion.cfg
================================================
[bumpversion]
current_version = 12.1.13
commit = True
tag = False

[bumpversion:file:setup.py]
search = version='{current_version}'
replace = version='{new_version}'

[bumpversion:file:core/__init__.py]
search = __version__ = '{current_version}'
replace = __version__ = '{new_version}'


================================================
FILE: .editorconfig
================================================
# see http://editorconfig.org
root = true

[*]
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4
charset = utf-8

[*.{bat,cmd,ps1}]
end_of_line = crlf


================================================
FILE: .gitattributes
================================================
# Set default behaviour, in case users don't have core.autocrlf set.
* text=auto

# Explicitly declare text files we want to always be normalized and converted 
# to native line endings on checkout.
*.txt text

# Declare files that will always have LF line endings on checkout.
*.sh text eol=lf
*.py text eol=lf
*.sample text eol=lf
*.md text eol=lf
*.conf text eol=lf

# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary


================================================
FILE: .github/CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
 advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
 address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
 professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at fock_wulf@hotmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq


================================================
FILE: .github/CONTRIBUTING.md
================================================
# Contributing

When contributing to this repository, please first check the issues list, current pull requests, and FAQ pages.

While it is prefered that all interactions be made through github, the author can be contacted directly at fock_wulf@hotmail.com

Please note we have a code of conduct, please follow it in all your interactions with the project.

## Pull Request Process

1. Please base all pull requests on the current nightly branch.
2. Include a description to explain what is achieved with a pull request.
3. Link any relevant issues that are closed or impacted by the pull request.
4. Please update the FAQ to reflect any new parameters, changed behaviour, or suggested configurations relevant to the changes.

================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**Technical Specs**
1. Running on (Windows, Linux, NAS Model etc) '....'
2. Python version '....'
3. Download Client (NZBget, SABnbzd, Transmission) '....'
4. Intended Media Management (SickChill, CouchPotoato, Radarr, Sonarr) '....'

**Expected behavior**
A clear and concise description of what you expected to happen.

**Log**
Please provide an extract, or full debug log that indicates the issue.


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

**Test Configuration**:

# Checklist:
- [ ] I have based this change on the nightly branch
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes


================================================
FILE: .github/README.md
================================================
nzbToMedia
==========

Provides an [efficient](https://github.com/clinton-hall/nzbToMedia/wiki/Efficient-on-demand-post-processing) way to handle postprocessing for [CouchPotatoServer](https://couchpota.to/ "CouchPotatoServer") and [SickBeard](http://sickbeard.com/ "SickBeard") (and its [forks](https://github.com/clinton-hall/nzbToMedia/wiki/Failed-Download-Handling-%28FDH%29#sick-beard-and-its-forks))
when using one of the popular NZB download clients like [SABnzbd](http://sabnzbd.org/ "SABnzbd") and [NZBGet](https://nzbget.com/ "NZBGet") on low performance systems like a NAS. 
This script is based on sabToSickBeard (written by Nic Wolfe and supplied with SickBeard), with the support for NZBGet being added by [thorli](https://github.com/thorli "thorli") and further contributions by [schumi2004](https://github.com/schumi2004 "schumi2004") and [hugbug](https://sourceforge.net/apps/phpbb/nzbget/memberlist.php?mode=viewprofile&u=67 "hugbug").
Torrent suport added by [jkaberg](https://github.com/jkaberg "jkaberg") and [berkona](https://github.com/berkona "berkona")
Corrupt video checking, auto SickBeard fork determination and a whole lot of code improvement was done by [echel0n](https://github.com/echel0n "echel0n")
Python3 compatibility, and much cleaner code base has been contributed by [Labrys of Knossos](https://github.com/labrys "Labrys of Knossos")


Introduction
------------
Originally this was modified from the SickBeard version to allow for ["on-demand" renaming](https://github.com/clinton-hall/nzbToMedia/wiki/Efficient-on-demand-post-processing) and not have My QNAP TS-412 NAS constantly scanning the download directory. 
Later, a few failed downloads prompted me to incorporate ["failed download" handling](https://github.com/clinton-hall/nzbToMedia/wiki/Failed-Download-Handling-%28FDH%29).
Failed download handling is now provided for SABnzbd, by CouchPotatoServer; however on arm processors (e.g. small NAS systems) this can be un-reliable.

Failed download handling for SickBeard is available by using Tolstyak's fork [SickBeard-failed](https://github.com/hugepants/Sick-Beard)).
To use this feature, in autoProcessTV.cfg set the parameter "fork=failed". Default is "fork=default" and will work with the standard version of SickBeard and just ignores failed downloads.
Development of Tolstyak's fork ended in 2013, but newer forks exist with significant feature updates such as [Mr-Orange TPB](https://github.com/coach0742/Sick-Beard) (discontinued), [SickRageTV](https://github.com/SiCKRAGETV/SickRage) and [SickRage](https://github.com/SickRage/SickRage) (active). See [SickBeard Forks](https://github.com/clinton-hall/nzbToMedia/wiki/Failed-Download-Handling-%28FDH%29#sick-beard-and-its-forks "SickBeard Forks") for a list of known forks.

Full support is provided for [SickChill](https://github.com/SickChill/SickChill), [SiCKRAGE](https://github.com/SiCKRAGE/SiCKRAGE), [Medusa](https://github.com/pymedusa/Medusa), and [SickGear](https://github.com/SickGear/SickGear).

Torrent support has been added with the assistance of jkaberg and berkona. Currently supports uTorrent, Transmission, Deluge and possibly more.
To enable Torrent extraction, on Windows, you need to install [7-zip](http://www.7-zip.org/ "7-zip") or on *nix you need to install the following packages/commands.
	
	"unrar", "unzip", "tar", "7zr"
	note: "7zr" is available from the p7zip package. Available on Optware.

In order to use the transcoding option, and corrupt video checking you will need to install ffmpeg (and ffprobe).
Installation instructions for this are available in the [wiki](https://github.com/clinton-hall/nzbToMedia/wiki/Transcoder "wiki")
	
Contribution
------------
We who have developed nzbToMedia believe in the openness of open-source, and as such we hope that any modifications will lead back to the [original repo](https://github.com/clinton-hall/nzbToMedia "orignal repo") via pull requests.

Founder: [clinton-hall](https://github.com/clinton-hall "clinton-hall")

Contributors: Can be viewed [here](https://github.com/clinton-hall/nzbToMedia/contributors "here")


Installation
------------

**See more detailed instructions in the [wiki](https://github.com/clinton-hall/nzbToMedia/wiki "wiki")** 

### Windows

Support of the compiled versions of this code has ceased. Compiling this expanding code is becoming very difficult and time-consuming. Installing Python and running from source is not too complex. Please follow the instructions on the Wiki link above.
Sorry for any inconvenience caused here.


### General

1. Install Python

1. Install `pywin32`

1. Clone or copy all files into a directory wherever you want to keep them (eg. /scripts/ in the home directory of your download client) 
   and change the permission accordingly so the download client can access these files.
	
  `git clone git://github.com/clinton-hall/nzbToMedia.git`

### Configuration

1. Please read the [wiki](https://github.com/clinton-hall/nzbToMedia/wiki "wiki") pages for configuration settings appropriate to your system.

2. Please add to the wiki pages to help assist others ;)

### Issues

1. Please report all issues, or potential enhancements using the [issues](https://github.com/clinton-hall/nzbToMedia/issues "issues") page on this repo.


================================================
FILE: .gitignore
================================================
*.cfg
!.bumpversion.cfg
*.cfg.old
*.py[cod]
*.log
*.pid
*.db
*.dbm
/userscripts/
/logs/
/.idea/
/venv/
*.dist-info
*.egg-info
/.vscode


================================================
FILE: TorrentToMedia.py
================================================
#!/usr/bin/env python
# coding=utf-8

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import datetime
import os
import sys

import eol
import cleanup
eol.check()
cleanup.clean(cleanup.FOLDER_STRUCTURE)

import core
from core import logger, main_db
from core.auto_process import comics, games, movies, music, tv, books
from core.auto_process.common import ProcessResult
from core.plugins.plex import plex_update
from core.user_scripts import external_script
from core.utils import char_replace, convert_to_ascii, replace_links

try:
    text_type = unicode
except NameError:
    text_type = str


def process_torrent(input_directory, input_name, input_category, input_hash, input_id, client_agent):
    status = 1  # 1 = failed | 0 = success
    root = 0
    found_file = 0

    if client_agent != 'manual' and not core.DOWNLOAD_INFO:
        logger.debug('Adding TORRENT download info for directory {0} to database'.format(input_directory))

        my_db = main_db.DBConnection()

        input_directory1 = input_directory
        input_name1 = input_name

        try:
            encoded, input_directory1 = char_replace(input_directory)
            encoded, input_name1 = char_replace(input_name)
        except Exception:
            pass

        control_value_dict = {'input_directory': text_type(input_directory1)}
        new_value_dict = {
            'input_name': text_type(input_name1),
            'input_hash': text_type(input_hash),
            'input_id': text_type(input_id),
            'client_agent': text_type(client_agent),
            'status': 0,
            'last_update': datetime.date.today().toordinal(),
        }
        my_db.upsert('downloads', new_value_dict, control_value_dict)

    logger.debug('Received Directory: {0} | Name: {1} | Category: {2}'.format(input_directory, input_name, input_category))

    # Confirm the category by parsing directory structure
    input_directory, input_name, input_category, root = core.category_search(input_directory, input_name, input_category,
                                                                             root, core.CATEGORIES)
    if input_category == '':
        input_category = 'UNCAT'

    usercat = input_category

    logger.debug('Determined Directory: {0} | Name: {1} | Category: {2}'.format
                 (input_directory, input_name, input_category))

    # auto-detect section
    section = core.CFG.findsection(input_category).isenabled()
    if section is None: #Check for user_scripts for 'ALL' and 'UNCAT'
        if usercat in core.CATEGORIES:
            section = core.CFG.findsection('ALL').isenabled()
            usercat = 'ALL'
        else:
            section = core.CFG.findsection('UNCAT').isenabled()
            usercat = 'UNCAT'
    if section is None: # We haven't found any categories to process.
        logger.error('Category:[{0}] is not defined or is not enabled. '
                     'Please rename it or ensure it is enabled for the appropriate section '
                     'in your autoProcessMedia.cfg and try again.'.format
                     (input_category))
        return [-1, '']

    if len(section) > 1:
        logger.error('Category:[{0}] is not unique, {1} are using it. '
                     'Please rename it or disable all other sections using the same category name '
                     'in your autoProcessMedia.cfg and try again.'.format
                     (usercat, section.keys()))
        return [-1, '']

    if section:
        section_name = section.keys()[0]
        logger.info('Auto-detected SECTION:{0}'.format(section_name))
    else:
        logger.error('Unable to locate a section with subsection:{0} '
                     'enabled in your autoProcessMedia.cfg, exiting!'.format
                     (input_category))
        return [-1, '']

    section = dict(section[section_name][usercat])  # Type cast to dict() to allow effective usage of .get()

    torrent_no_link = int(section.get('Torrent_NoLink', 0))
    keep_archive = int(section.get('keep_archive', 0))
    extract = int(section.get('extract', 0))
    extensions = section.get('user_script_mediaExtensions', '')
    unique_path = int(section.get('unique_path', 1))

    if client_agent != 'manual':
        core.pause_torrent(client_agent, input_hash, input_id, input_name)

    # In case input is not directory, make sure to create one.
    # This way Processing is isolated.
    if not os.path.isdir(os.path.join(input_directory, input_name)):
        basename = os.path.basename(input_directory)
        basename = core.sanitize_name(input_name) \
            if input_name == basename else os.path.splitext(core.sanitize_name(input_name))[0]
        output_destination = os.path.join(core.OUTPUT_DIRECTORY, input_category, basename)
    elif unique_path:
        output_destination = os.path.normpath(
            core.os.path.join(core.OUTPUT_DIRECTORY, input_category, core.sanitize_name(input_name).replace(' ', '.')))
    else:
        output_destination = os.path.normpath(
            core.os.path.join(core.OUTPUT_DIRECTORY, input_category))

    if output_destination in input_directory:
        output_destination = input_directory

    logger.info('Output directory set to: {0}'.format(output_destination))

    if core.SAFE_MODE and output_destination == core.TORRENT_DEFAULT_DIRECTORY:
        logger.error('The output directory:[{0}] is the Download Directory. '
                     'Edit outputDirectory in autoProcessMedia.cfg. Exiting'.format
                     (input_directory))
        return [-1, '']

    logger.debug('Scanning files in directory: {0}'.format(input_directory))

    if section_name in ['HeadPhones', 'Lidarr']:
        core.NOFLATTEN.extend(
            input_category)  # Make sure we preserve folder structure for HeadPhones.

    now = datetime.datetime.now()

    if extract == 1:
        input_files = core.list_media_files(input_directory, archives=False, other=True, otherext=extensions)
    else:
        input_files = core.list_media_files(input_directory, other=True, otherext=extensions)
    if len(input_files) == 0 and os.path.isfile(input_directory):
        input_files = [input_directory]
        logger.debug('Found 1 file to process: {0}'.format(input_directory))
    else:
        logger.debug('Found {0} files in {1}'.format(len(input_files), input_directory))
    for inputFile in input_files:
        file_path = os.path.dirname(inputFile)
        file_name, file_ext = os.path.splitext(os.path.basename(inputFile))
        full_file_name = os.path.basename(inputFile)

        target_file = core.os.path.join(output_destination, full_file_name)
        if input_category in core.NOFLATTEN:
            if not os.path.basename(file_path) in output_destination:
                target_file = core.os.path.join(
                    core.os.path.join(output_destination, os.path.basename(file_path)), full_file_name)
                logger.debug('Setting outputDestination to {0} to preserve folder structure'.format
                             (os.path.dirname(target_file)))
        if root == 1:
            if not found_file:
                logger.debug('Looking for {0} in: {1}'.format(input_name, inputFile))
            if any([core.sanitize_name(input_name) in core.sanitize_name(inputFile),
                    core.sanitize_name(file_name) in core.sanitize_name(input_name)]):
                found_file = True
                logger.debug('Found file {0} that matches Torrent Name {1}'.format
                             (full_file_name, input_name))
            else:
                continue

        if root == 2:
            mtime_lapse = now - datetime.datetime.fromtimestamp(os.path.getmtime(inputFile))
            ctime_lapse = now - datetime.datetime.fromtimestamp(os.path.getctime(inputFile))

            if not found_file:
                logger.debug('Looking for files with modified/created dates less than 5 minutes old.')
            if (mtime_lapse < datetime.timedelta(minutes=5)) or (ctime_lapse < datetime.timedelta(minutes=5)):
                found_file = True
                logger.debug('Found file {0} with date modified/created less than 5 minutes ago.'.format
                             (full_file_name))
            else:
                continue  # This file has not been recently moved or created, skip it

        if torrent_no_link == 0:
            try:
                core.copy_link(inputFile, target_file, core.USE_LINK)
                core.remove_read_only(target_file)
            except Exception:
                logger.error('Failed to link: {0} to {1}'.format(inputFile, target_file))

    input_name, output_destination = convert_to_ascii(input_name, output_destination)

    if extract == 1:
        logger.debug('Checking for archives to extract in directory: {0}'.format(input_directory))
        core.extract_files(input_directory, output_destination, keep_archive)

    if input_category not in core.NOFLATTEN:
        # don't flatten hp in case multi cd albums, and we need to copy this back later.
        core.flatten(output_destination)

    # Now check if video files exist in destination:
    if section_name in ['SickBeard', 'SiCKRAGE', 'NzbDrone', 'Sonarr', 'CouchPotato', 'Radarr', 'Watcher3']:
        num_videos = len(
            core.list_media_files(output_destination, media=True, audio=False, meta=False, archives=False))
        if num_videos > 0:
            logger.info('Found {0} media files in {1}'.format(num_videos, output_destination))
            status = 0
        elif extract != 1:
            logger.info('Found no media files in {0}. Sending to {1} to process'.format(output_destination, section_name))
            status = 0
        else:
            logger.warning('Found no media files in {0}'.format(output_destination))

    # Only these sections can handling failed downloads
    # so make sure everything else gets through without the check for failed
    if section_name not in ['CouchPotato', 'Radarr', 'SickBeard', 'SiCKRAGE', 'NzbDrone', 'Sonarr', 'Watcher3']:
        status = 0

    logger.info('Calling {0}:{1} to post-process:{2}'.format(section_name, usercat, input_name))

    if core.TORRENT_CHMOD_DIRECTORY:
        core.rchmod(output_destination, core.TORRENT_CHMOD_DIRECTORY)

    result = ProcessResult(
        message='',
        status_code=0,
    )
    if section_name == 'UserScript':
        result = external_script(output_destination, input_name, input_category, section)
    elif section_name in ['CouchPotato', 'Radarr', 'Watcher3']:
        result = movies.process(section_name, output_destination, input_name, status, client_agent, input_hash, input_category)
    elif section_name in ['SickBeard', 'SiCKRAGE', 'NzbDrone', 'Sonarr']:
        if input_hash:
            input_hash = input_hash.upper()
        result = tv.process(section_name, output_destination, input_name, status, client_agent, input_hash, input_category)
    elif section_name in ['HeadPhones', 'Lidarr']:
        result = music.process(section_name, output_destination, input_name, status, client_agent, input_category)
    elif section_name == 'Mylar':
        result = comics.process(section_name, output_destination, input_name, status, client_agent, input_category)
    elif section_name == 'Gamez':
        result = games.process(section_name, output_destination, input_name, status, client_agent, input_category)
    elif section_name == 'LazyLibrarian':
        result = books.process(section_name, output_destination, input_name, status, client_agent, input_category)

    plex_update(input_category)

    if result.status_code != 0:
        if not core.TORRENT_RESUME_ON_FAILURE:
            logger.error('A problem was reported in the autoProcess* script. '
                         'Torrent won\'t resume seeding (settings)')
        elif client_agent != 'manual':
            logger.error('A problem was reported in the autoProcess* script. '
                         'If torrent was paused we will resume seeding')
            core.resume_torrent(client_agent, input_hash, input_id, input_name)

    else:
        if client_agent != 'manual':
            # update download status in our DB
            core.update_download_info_status(input_name, 1)

            # remove torrent
            if core.USE_LINK == 'move-sym' and not core.DELETE_ORIGINAL == 1:
                logger.debug('Checking for sym-links to re-direct in: {0}'.format(input_directory))
                for dirpath, _, files in os.walk(input_directory):
                    for file in files:
                        logger.debug('Checking symlink: {0}'.format(os.path.join(dirpath, file)))
                        replace_links(os.path.join(dirpath, file))
            core.remove_torrent(client_agent, input_hash, input_id, input_name)

        if section_name != 'UserScript':
            # for user script, we assume this is cleaned by the script or option USER_SCRIPT_CLEAN
            # cleanup our processing folders of any misc unwanted files and empty directories
            core.clean_dir(output_destination, section_name, input_category)

    return result


def main(args):
    # Initialize the config
    core.initialize()

    # clientAgent for Torrents
    client_agent = core.TORRENT_CLIENT_AGENT

    logger.info('#########################################################')
    logger.info('## ..::[{0}]::.. ##'.format(os.path.basename(__file__)))
    logger.info('#########################################################')

    # debug command line options
    logger.debug('Options passed into TorrentToMedia: {0}'.format(args))

    # Post-Processing Result
    result = ProcessResult(
        message='',
        status_code=0,
    )

    try:
        input_directory, input_name, input_category, input_hash, input_id = core.parse_args(client_agent, args)
    except Exception:
        logger.error('There was a problem loading variables')
        return -1

    if input_directory and input_name and input_hash and input_id:
        result = process_torrent(input_directory, input_name, input_category, input_hash, input_id, client_agent)
    elif core.TORRENT_NO_MANUAL:
        logger.warning('Invalid number of arguments received from client, and no_manual set')
    else:
        # Perform Manual Post-Processing
        logger.warning('Invalid number of arguments received from client, Switching to manual run mode ...')

        for section, subsections in core.SECTIONS.items():
            for subsection in subsections:
                if not core.CFG[section][subsection].isenabled():
                    continue
                for dir_name in core.get_dirs(section, subsection, link='hard'):
                    logger.info('Starting manual run for {0}:{1} - Folder:{2}'.format
                                (section, subsection, dir_name))

                    logger.info('Checking database for download info for {0} ...'.format
                                (os.path.basename(dir_name)))
                    core.DOWNLOAD_INFO = core.get_download_info(os.path.basename(dir_name), 0)
                    if core.DOWNLOAD_INFO:
                        client_agent = text_type(core.DOWNLOAD_INFO[0]['client_agent']) or 'manual'
                        input_hash = text_type(core.DOWNLOAD_INFO[0]['input_hash']) or ''
                        input_id = text_type(core.DOWNLOAD_INFO[0]['input_id']) or ''
                        logger.info('Found download info for {0}, '
                                    'setting variables now ...'.format(os.path.basename(dir_name)))
                    else:
                        logger.info('Unable to locate download info for {0}, '
                                    'continuing to try and process this release ...'.format
                                    (os.path.basename(dir_name)))
                        client_agent = 'manual'
                        input_hash = ''
                        input_id = ''

                    if client_agent.lower() not in core.TORRENT_CLIENTS:
                        continue

                    input_name = os.path.basename(dir_name)

                    results = process_torrent(dir_name, input_name, subsection, input_hash or None, input_id or None,
                                              client_agent)
                    if results.status_code != 0:
                        logger.error('A problem was reported when trying to perform a manual run for {0}:{1}.'.format
                                     (section, subsection))
                        result = results

    if result.status_code == 0:
        logger.info('The {0} script completed successfully.'.format(args[0]))
    else:
        logger.error('A problem was reported in the {0} script.'.format(args[0]))
    del core.MYAPP
    return result.status_code


if __name__ == '__main__':
    exit(main(sys.argv))


================================================
FILE: _config.yml
================================================
theme: jekyll-theme-cayman

================================================
FILE: autoProcessMedia.cfg.spec
================================================
# nzbToMedia Configuration
# For more information, visit https://github.com/clinton-hall/nzbToMedia/wiki

[General]
    # Enable/Disable update notifications
    version_notify = 1
    # Enable/Disable automatic updates
    auto_update = 0
    # Set to the full path to the git executable
    git_path =
    # GitHUB user for repo
    git_user =
    # GitHUB branch for repo
    git_branch =
    # Enable/Disable forceful cleaning of leftover files following postprocess
    force_clean = 0
    # Enable/Disable logging debug messages to nzbtomedia.log
    log_debug = 0
    # Enable/Disable logging database messages to nzbtomedia.log
    log_db = 0
    # Enable/Disable logging environment variables to debug nzbtomedia.log (helpful to track down errors calling external tools.)
    log_env = 0
    # Enable/Disable logging git output to debug nzbtomedia.log (helpful to track down update failures.)
    log_git = 0
    # Set to the directory to search for executables if not in default system path
    sys_path =
    # Set to the directory where your ffmpeg/ffprobe executables are located
    ffmpeg_path =
    # Enable/Disable media file checking using ffprobe.
    check_media = 1
    # Required media audio language for media to be deemed valid. Leave blank to disregard media audio language check.
    require_lan = 
    # Enable/Disable a safety check to ensure we don't process all downloads in the default_downloadDirectories by mistake.
    safe_mode = 1
    # Turn this on to disable additional extraction attempts for failed downloads. Default = 0 will attempt to extract and verify if media is present.
    no_extract_failed = 0

[Posix]
    ### Process priority setting for External commands (Extractor and Transcoder) on Posix (Unix/Linux/OSX) systems.
    # Set the Niceness value for the nice command. These range from -20 (most favorable to the process) to 19 (least favorable to the process).
    # If entering an integer e.g 'niceness = 4', this is added to the nice command and passed as 'nice -n4' (Default).
    # If entering a comma separated list e.g. 'niceness = nice,4' this will be passed as 'nice 4' (Safer).
    niceness = nice,-n0
    # Set the ionice scheduling class. 0 for none, 1 for real time, 2 for best-effort, 3 for idle.
    ionice_class = 0
    # Set the ionice scheduling class data. This defines the class data, if the class accepts an argument. For real time and best-effort, 0-7 is valid data.
    ionice_classdata = 0

[Windows]
    ### Set specific settings for Windows systems
    # Set this to 1 to allow extraction (7zip) windows to be lunched visble (for debugging) otherwise 0 to have this run in background.
    show_extraction = 0

[CouchPotato]
    #### autoProcessing for Movies
    #### movie - category that gets called for post-processing with CPS
    [[movie]]
        enabled = 0
        apikey =
        host = localhost
        port = 5050
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        ssl = 0
        web_root =
        # api key for www.omdbapi.com (used as alternative to imdb)
        omdbapikey =
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        method = renamer
        delete_failed = 0
        wait_for = 2
        # Set this to suppress error if no status change after rename called
        no_status_check = 0
        extract = 1
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if Couchpotato is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =
        ##### Set the recursive directory permissions to the following (0 to disable)
        chmodDirectory = 0

[Radarr]
    #### autoProcessing for Movies
    #### raCategory - category that gets called for post-processing with Radarr
    [[movie]]
        enabled = 0
        apikey =
        host = localhost
        port = 7878
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        web_root =
        ssl = 0
        # api key for www.omdbapi.com (used as alternative to imdb)
        omdbapikey =
        delete_failed = 0
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        extract = 1
        nzbExtractionBy = Downloader
        wait_for = 6
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if NzbDrone is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =
        ##### Set to define import behavior Move or Copy
        importMode = Copy

[Watcher3]
    #### autoProcessing for Movies
    #### movie - category that gets called for post-processing with CPS
    [[movie]]
        enabled = 0
        apikey =
        host = localhost
        port = 9090
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        ssl = 0
        web_root =
        # api key for www.omdbapi.com (used as alternative to imdb)
        omdbapikey =
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        delete_failed = 0
        wait_for = 0
        extract = 1
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if Watcher3 is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =
        ##### Set the recursive directory permissions to the following (0 to disable)
        chmodDirectory = 0

[SickBeard]
    #### autoProcessing for TV Series
    #### tv - category that gets called for post-processing with SB
    [[tv]]
        enabled = 0
        host = localhost
        port = 8081
        apikey =
        username =
        password =
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        web_root =
        ssl = 0
        fork = auto
        delete_failed = 0
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        process_method =
        # force processing of already processed content when running a manual scan.
        force = 0
        # Additionally to force, handle the download as a priority downlaod.
        # The processed files will always replace existing qualities, also if this is a lower quality.
        is_priority = 0
        # tell SickRage/Medusa to delete all source files after processing.
        delete_on = 0
        # tell Medusa to ignore check for associated subtitle check when postponing release
        ignore_subs = 0
        extract = 1
        nzbExtractionBy = Downloader
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if SickBeard is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =
        ##### Set the recursive directory permissions to the following (0 to disable)
        chmodDirectory = 0
        ##### pyMedusa (fork=medusa-apiv2) uses async postprocessing. Wait a maximum of x minutes for a pp result
        wait_for = 10

[SiCKRAGE]
    #### autoProcessing for TV Series
    #### tv - category that gets called for post-processing with SR
    [[tv]]
        enabled = 0
        host = localhost
        port = 8081
        apikey =
        # api version 1 uses api keys
        # api version 2 uses SSO user/pass
        api_version = 2
        # SSO login requires API v2 to be set
        sso_username =
        sso_password =
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        web_root =
        ssl = 0
        delete_failed = 0
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        process_method =
        # force processing of already processed content when running a manual scan.
        force = 0
        # tell SickRage/Medusa to delete all source files after processing.
        delete_on = 0
        # tell Medusa to ignore check for associated subtitle check when postponing release
        ignore_subs = 0
        extract = 1
        nzbExtractionBy = Downloader
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if SickBeard is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =
        ##### Set the recursive directory permissions to the following (0 to disable)
        chmodDirectory = 0

[NzbDrone]
    #### Formerly known as NzbDrone this is now Sonarr
    #### autoProcessing for TV Series
    #### ndCategory - category that gets called for post-processing with NzbDrone/Sonarr
    [[tv]]
        enabled = 0
        apikey =
        host = localhost
        port = 8989
        username =
        password =
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        web_root =
        ssl = 0
        delete_failed = 0
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        extract = 1
        nzbExtractionBy = Downloader
        wait_for = 6
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if NzbDrone is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =
        ##### Set to define import behavior Move or Copy
        importMode = Copy

[HeadPhones]
    #### autoProcessing for Music
    #### music - category that gets called for post-processing with HP
    [[music]]
        enabled = 0
        apikey =
        host = localhost
        port = 8181
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        ssl = 0
        web_root =
        delete_failed = 0
        wait_for = 2
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        extract = 1
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if HeadPhones is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =

[Lidarr]
    #### autoProcessing for Music
    #### LiCategory - category that gets called for post-processing with Lidarr
    [[music]]
        enabled = 0
        apikey =
        host = localhost
        port = 8686
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        web_root =
        ssl = 0
        delete_failed = 0
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        extract = 1
        nzbExtractionBy = Downloader
        wait_for = 6
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if NzbDrone is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =

[Mylar]
    #### autoProcessing for Comics
    #### comics - category that gets called for post-processing with Mylar
    [[comics]]
        enabled = 0
        host = localhost
        port= 8090
        apikey=
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        web_root=
        ssl=0
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        extract = 1
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if Mylar is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =

[Gamez]
    #### autoProcessing for Games
    #### games - category that gets called for post-processing with Gamez
    [[games]]
        enabled = 0
        apikey =
        host = localhost
        port = 8085
        ######
        library = Set to path where you want the processed games to be moved to.
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        ssl = 0
        web_root =
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        extract = 1
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if Gamez is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =

[LazyLibrarian]
    #### autoProcessing for LazyLibrarian
    #### books - category that gets called for post-processing with LazyLibrarian
    [[books]]
        enabled = 0
        apikey =
        host = localhost
        port = 5299
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        ssl = 0
        web_root =
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        extract = 1
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid media files)
        delete_ignored = 0
        ##### Enable if LazyLibrarian is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =

[Readarr]
    #### autoProcessing for Books
    #### raCategory - category that gets called for post-processing with Readarr
    [[book]]
        enabled = 0
        apikey =
        host = localhost
        port = 8787
        ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
        web_root =
        ssl = 0
        delete_failed = 0
        # Enable/Disable linking for Torrents
        Torrent_NoLink = 0
        keep_archive = 1
        extract = 1
        nzbExtractionBy = Downloader
        # Minutes to wait after triggering the import before checking status
        wait_for = 6
        # Set this to minimum required size to consider a media file valid (in MB)
        minSize = 0
        # Enable/Disable deleting ignored files (samples and invalid files)
        delete_ignored = 0
        ##### Enable if Readarr is on a remote server for this category
        remote_path = 0
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =
        ##### Set to define import behaviour Move or Copy
        importMode = Copy

[Network]
    # Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
    # e.g. MountPoints = /volume1/Public/,E:\|/volume2/share/,\\NAS\
    mount_points =

[Nzb]
    ###### clientAgent - Supported clients: sabnzbd, nzbget
    clientAgent = sabnzbd
    ###### SabNZBD (You must edit this if you're using nzbToMedia.py with SabNZBD)
    sabnzbd_host = http://localhost
    sabnzbd_port = 8080
    sabnzbd_apikey =
    ###### Enter the default path to your default download directory (non-category downloads). this directory is protected by safe_mode.
    default_downloadDirectory =
    # enable this option to prevent nzbToMedia from running in manual mode and scanning an entire directory.
    no_manual = 0

[Torrent]
    ###### clientAgent - Supported clients: utorrent, transmission, deluge, rtorrent, vuze, qbittorrent, synods, other
    clientAgent = other
    ###### useLink - Set to hard for physical links, sym for symbolic links, move to move, move-sym to move and link back, and no to not use links (copy)
    useLink = hard
    ###### outputDirectory - Default output directory (categories will be appended as sub directory to outputDirectory)
    outputDirectory = /abs/path/to/complete/
    ###### Enter the default path to your default download directory (non-category downloads). this directory is protected by safe_mode.
    default_downloadDirectory =
    ###### Other categories/labels defined for your downloader. Does not include CouchPotato, SickBeard, HeadPhones, Mylar categories.
    categories = music_videos,pictures,software,manual
    ###### A list of categories that you don't want to be flattened (i.e preserve the directory structure when copying/linking.
    noFlatten = pictures,manual
    ###### uTorrent Hardlink solution (You must edit this if you're using TorrentToMedia.py with uTorrent)
    uTorrentWEBui = http://localhost:8090/gui/
    uTorrentUSR = your username
    uTorrentPWD = your password
    ###### Transmission (You must edit this if you're using TorrentToMedia.py with Transmission)
    TransmissionHost = localhost
    TransmissionPort = 9091
    TransmissionUSR = your username
    TransmissionPWD = your password
    #### Deluge (You must edit this if you're using TorrentToMedia.py with deluge. Note that the host/port is for the deluge daemon, not the webui)
    DelugeHost = localhost
    DelugePort = 58846
    DelugeUSR = your username
    DelugePWD = your password
    ###### qBittorrent (You must edit this if you're using TorrentToMedia.py with qBittorrent)
    qBittorrentHost = localhost
    qBittorrentPort = 8080
    qBittorrentUSR = your username
    qBittorrentPWD = your password
    ###### Synology Download Station (You must edit this if you're using TorrentToMedia.py with Synology DS)
    synoHost = localhost
    synoPort = 5000
    synoUSR = your username
    synoPWD = your password
    ###### ADVANCED USE - ONLY EDIT IF YOU KNOW WHAT YOU'RE DOING ######
    deleteOriginal = 0
    chmodDirectory = 0
    resume = 1
    resumeOnFailure = 1
    # enable this option to prevent TorrentToMedia from running in manual mode and scanning an entire directory.
    no_manual = 0

[Extensions]
    compressedExtensions = .zip,.rar,.7z,.gz,.bz,.tar,.arj,.1,.01,.001
    mediaExtensions = .mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg,.vob,.iso,.m4v,.ts
    audioExtensions = .mp3, .aac, .ogg, .ape, .m4a, .asf, .wma, .flac
    metaExtensions = .nfo,.sub,.srt,.jpg,.gif

[Plex]
    # Only enter these details if you want to update plex library after processing.
    # Do not enter these details if you send the plex notifications from Sickbeard/CouchPotato.
    plex_host = localhost
    plex_port = 32400
    plex_token =
    plex_ssl = 0
    # Enter Plex category to section mapping as Category,section and separate each pair with '|'
    # e.g. plex_sections = movie,3|tv,4
    plex_sections =

[Transcoder]
    # getsubs. enable to download subtitles.
    getSubs = 0
    # subLanguages. create a list of languages in the order you want them in your subtitles.
    subLanguages = eng,spa,fra
    # transcode. enable to use transcoder
    transcode = 0
    ###### duplicate =1 will create a new file. =0 will replace the original
    duplicate = 1
    # concat. joins cd1 cd2 etc into a single video.
    concat = 1
    # IgnoreExtensions is a comma-separated list of extensions that will not be transcoded.
    ignoreExtensions = .avi,.mkv,.mp4
    # outputFastStart. 1 will use -movflags + faststart. 0 will disable this from being used.
    outputFastStart = 0
    # outputQualityPercent. used as -q:a value. 0 will disable this from being used.
    outputQualityPercent = 0
    # outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable.
    outputVideoPath =
    # processOutput. 1 will send the outputVideoPath to SickBeard/CouchPotato. 0 will send original files.
    processOutput = 0
    # audioLanguage. set the 3 letter language code you want as your primary audio track.
    audioLanguage = eng
    # allAudioLanguages. 1 will keep all audio tracks (uses AudioCodec3) where available.
    allAudioLanguages = 0
    # allSubLanguages. 1 will keep all existing sub languages. 0 will discard those not in your list above.
    allSubLanguages = 0
    # embedSubs. 1 will embed external sub/srt subs into your video if this is supported.
    embedSubs = 1
    # burnInSubtitle. burns the default sub language into your video (needed for players that don't support subs)
    burnInSubtitle = 0
    # extractSubs. 1 will extract subs from the video file and save these as external srt files.
    extractSubs = 0
    # externalSubDir. set the directory where subs should be saved (if not the same directory as the video)
    externalSubDir =
    # hwAccel. 1 will set ffmpeg to enable hardware acceleration (this requires a recent ffmpeg)
    hwAccel = 0
    # generalOptions. Enter your additional ffmpeg options (these insert before the '-i' input files) here with commas to separate each option/value (i.e replace spaces with commas).
    generalOptions =
    # otherOptions. Enter your additional ffmpeg options (these insert after the '-i' input files and before the output file) here with commas to separate each option/value (i.e replace spaces with commas).
    otherOptions =
    # outputDefault. Loads default configs for the selected device. The remaining options below are ignored.
    # If you want to use your own profile, leave this blank and set the remaining options below.
    # outputDefault profiles allowed: iPad, iPad-1080p, iPad-720p, Apple-TV2, iPod, iPhone, PS3, xbox, Roku-1080p, Roku-720p, Roku-480p, mkv, mkv-bluray, mp4-scene-release
    outputDefault =
    #### Define custom settings below.
    outputVideoExtension = .mp4
    outputVideoCodec = libx264
    VideoCodecAllow =
    outputVideoPreset = medium
    outputVideoResolution = 1920:1080
    outputVideoFramerate = 24
    outputVideoBitrate = 800000
    outputVideoCRF = 19
    outputVideoLevel = 3.1
    outputAudioCodec = ac3
    AudioCodecAllow =
    outputAudioChannels = 6
    outputAudioBitrate = 640k
    outputAudioTrack2Codec = libfaac
    AudioCodec2Allow =
    outputAudioTrack2Channels = 2
    outputAudioTrack2Bitrate = 128000
    outputAudioOtherCodec = libmp3lame
    AudioOtherCodecAllow =
    outputAudioOtherChannels =
    outputAudioOtherBitrate = 128000
    outputSubtitleCodec =

[WakeOnLan]
    ###### set wake = 1 to send WOL broadcast to the mac and test the server (e.g. xbmc) the host and port specified.
    wake = 0
    host = 192.168.1.37
    port = 80
    mac = 00:01:2e:2D:64:e1

[UserScript]
    #Use user_script for uncategorized downloads
    #Set the categories to use external script.
    #Use "UNCAT" to process non-category downloads, and "ALL" for all defined categories.
    [[UNCAT]]
        #Enable/Disable this subsection category
        enabled = 0
        Torrent_NoLink = 0
        keep_archive = 1
        extract = 1
        #Enable if you are sending commands to a remote server for this category
        remote_path = 0
        #What extension do you want to process? Specify all the extension, or use "ALL" to process all files.
        user_script_mediaExtensions = .mkv,.avi,.divx,.xvid,.mov,.wmv,.mp4,.mpg,.mpeg
        #Specify the path to your custom script. Use "None" if you wish to link this category, but NOT run any external script.
        user_script_path = /nzbToMedia/userscripts/script.sh
        #Specify the argument(s) passed to script, comma separated in order.
        #for example FP,FN,DN, TN, TL for file path (absolute file name with path), file name, absolute directory name (with path), Torrent Name, Torrent Label/Category.
        #So the result is /media/test/script/script.sh FP FN DN TN TL. Add other arguments as needed eg -f, -r
        user_script_param = FN
        #Set user_script_runOnce = 0 to run for each file, or 1 to only run once (presumably on the entire directory).
        user_script_runOnce = 0
        #Specify the successcodes returned by the user script as a comma separated list. Linux default is 0
        user_script_successCodes = 0
        #Clean after? Note that delay function is used to prevent possible mistake :) Delay is intended as seconds
        user_script_clean = 1
        delay = 120
        #Unique path (directory) created for every download. set 0 to disable.
        unique_path = 1
        ##### Set to path where download client places completed downloads locally for this category
        watch_dir =

[ASCII]
    #Set convert =1 if you want to convert any "foreign" characters to ASCII (UTF8) before passing to SB/CP etc. Default is disabled (0).
    convert = 0

[Passwords]
    # enter the full path to a text file containing passwords to be used for extraction attempts.
    # In the passwords file, every password should be on a new line
    PassWordFile =

[Custom]
    # enter a list (comma separated) of Group Tags you want removed from filenames to help with subtitle matching.
    # e.g remove_group = [rarbag],-NZBgeek
    # be careful if your "group" is a common "real" word. Please report if you have any group replacements that would fall in this category.
    remove_group =


================================================
FILE: azure-pipelines.yml
================================================
# Python package
# Create and test a Python package on multiple Python versions.
# Add steps that analyze code, save the dist with the build record, publish to a PyPI-compatible index, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/python

trigger:
- master

jobs:

- job: 'Test'
  pool:
    vmImage: 'Ubuntu-latest'
  strategy:
    matrix:
      Python310:
        python.version: '3.10'
      Python311:
        python.version: '3.11'
      Python312:
        python.version: '3.12'
      Python313:
        python.version: '3.13'
      Python314:
        python.version: '3.14'
    maxParallel: 3

  steps:
  - script: |
      sudo apt-get update
      sudo apt-get install ffmpeg
    displayName: 'Install ffmpeg'
  
  - task: UsePythonVersion@0
    inputs:
      versionSpec: '$(python.version)'
      architecture: 'x64'

  - script: python -m pip install --upgrade pip
    displayName: 'Install dependencies'

  - script: |
      pip install pytest
      pytest tests --doctest-modules --junitxml=junit/test-results.xml
    displayName: 'pytest'

  - script: |
      rm -rf .git
      python cleanup.py
      python TorrentToMedia.py
      python nzbToMedia.py
    displayName: 'Test source install cleanup'

  - task: PublishTestResults@2
    inputs:
      testResultsFiles: '**/test-results.xml'
      testRunTitle: 'Python $(python.version)'
    condition: succeededOrFailed()

- job: 'Publish'
  dependsOn: 'Test'
  pool:
    vmImage: 'Ubuntu-latest'

  steps:
  - task: UsePythonVersion@0
    inputs:
      versionSpec: '3.x'
      architecture: 'x64'

  - script: |
      python -m pip install setuptools
      python setup.py sdist
    displayName: 'Build sdist'


================================================
FILE: cleanup.py
================================================
#!/usr/bin/env python

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import os
import subprocess
import sys
import shutil

sys.dont_write_bytecode = True

FOLDER_STRUCTURE = {
    'libs': [
        'common',
        'custom',
        'py2',
        'win',
    ],
    'core': [
        'auto_process',
        'extractor',
        'plugins',
        'processor',
        'utils',
    ],
}


class WorkingDirectory(object):
    """Context manager for changing current working directory."""

    def __init__(self, new, original=None):
        self.working_directory = new
        self.original_directory = os.getcwd() if original is None else original

    def __enter__(self):
        os.chdir(self.working_directory)
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        try:
            os.chdir(self.original_directory)
        except OSError as error:
            print(
                'Unable to return to {original_directory}: {error}\n'
                'Continuing in {working_directory}'.format(
                    original_directory=self.original_directory,
                    error=error,
                    working_directory=self.working_directory,
                ),
            )


def module_path(module=__file__, parent=False):
    """
    Detect path for a module.

    :param module: The module who's path is being detected.  Defaults to current module.
    :param parent: True to return the parent folder of the current module.
    :return: The absolute normalized path to the module or its parent.
    """
    try:
        path = module.__file__
    except AttributeError:
        path = module
    directory = os.path.dirname(path)
    if parent:
        directory = os.path.join(directory, os.pardir)
    absolute = os.path.abspath(directory)
    normalized = os.path.normpath(absolute)
    return normalized


def git_clean(remove_directories=False, force=False, dry_run=False, interactive=False, quiet=False, exclude=None,
              ignore_rules=False, clean_ignored=False, paths=None):
    """Execute git clean commands."""
    command = ['git', 'clean']
    if remove_directories:
        command.append('-d')
    if force:
        command.append('--force')
    if interactive:
        command.append('--interactive')
    if quiet:
        command.append('--quiet')
    if dry_run:
        command.append('--dry-run')
    if exclude:
        try:
            exclude = exclude.split(' ')
        except AttributeError:
            pass
        for exclusion in exclude:
            command.append('--exclude={pattern}'.format(pattern=exclusion))
    if ignore_rules:
        command.append('-x')
    if clean_ignored:
        command.append('-X')
    if paths:
        try:
            paths = paths.split(' ')
        except AttributeError:
            pass
        command.extend(paths)
    return subprocess.check_output(command)


def clean_bytecode():
    """Clean bytecode files."""
    try:
        result = git_clean(
            remove_directories=True,
            force=True,
            ignore_rules=True,
            exclude=[
                '*.*',  # exclude everything
                '!*.py[co]',  # except bytecode
                '!**/__pycache__/',  # and __pycache__ folders
            ],
        )
        print(result)
    except subprocess.CalledProcessError as error:
        sys.exit('Error Code: {}'.format(error.returncode))
    except (IOError, OSError) as error:
        sys.exit('Error: {}'.format(error))
    else:
        return result


def clean_folders(*paths):
    """Clean obsolete folders."""
    try:
        result = git_clean(
            remove_directories=True,
            force=True,
            ignore_rules=True,
            paths=paths,
        )
    except subprocess.CalledProcessError as error:
        sys.exit('Error Code: {}'.format(error.returncode))
    except (IOError, OSError) as error:
        sys.exit('Error: {}'.format(error))
    else:
        return result


def force_clean_folder(path, required):
    """
    Force clean a folder and exclude any required subfolders.

    :param path: Target folder to remove subfolders
    :param required: Keep only the required subfolders
    """
    root, dirs, files = next(os.walk(path))
    required = sorted(required)
    if required:
        print('Skipping required subfolders', required)
    remove = sorted(set(dirs).difference(required))
    missing = sorted(set(required).difference(dirs))
    for path in remove:
        pathname = os.path.join(root, path)
        print('Removing', pathname)
        shutil.rmtree(pathname)
    if missing:
        raise Exception('Required subfolders missing:', missing)


def clean(paths):
    """Clean up bytecode and obsolete folders."""
    def _report_error(msg):
        print('WARNING: Automatic cleanup could not be executed.')
        print('         If errors occur, manual cleanup may be required.')
        print('REASON : {}'.format(msg))

    with WorkingDirectory(module_path()) as cwd:
        if cwd.working_directory != cwd.original_directory:
            print('Changing to directory:', cwd.working_directory)

        print('\n-- Cleaning bytecode --')
        try:
            result = clean_bytecode()
        except SystemExit as error:
            _report_error(error)
        else:
            print(result or 'No bytecode to clean')

        if paths and os.path.exists('.git'):
            print('\n-- Cleaning folders: {} --'.format(list(paths)))
            try:
                result = clean_folders(*paths)
            except SystemExit as error:
                _report_error(error)
            else:
                print(result or 'No folders to clean\n')
        else:
            print('\nDirectory is not a git repository')
            try:
                items = paths.items()
            except AttributeError:
                _report_error('Failed to clean, no subfolder structure given')
            else:
                for folder, subfolders in items:
                    print('\nForce cleaning folder:', folder)
                    force_clean_folder(folder, subfolders)

        if cwd.working_directory != cwd.original_directory:
            print('Returning to directory: ', cwd.original_directory)

        print('\n-- Cleanup finished --\n')


if __name__ == '__main__':
    clean(FOLDER_STRUCTURE)


================================================
FILE: core/__init__.py
================================================
# coding=utf-8

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import itertools
import locale
import os
import platform
import re
import subprocess
import sys
import time

import eol
import libs.autoload
import libs.util

if not libs.autoload.completed:
    sys.exit('Could not load vendored libraries.')

try:
    import win32event
except ImportError:
    if sys.platform == 'win32':
        sys.exit('Please install pywin32')

APP_ROOT = libs.util.module_path(parent=True)
SOURCE_ROOT = libs.util.module_path()

# init preliminaries
SYS_ARGV = sys.argv[1:]
APP_FILENAME = sys.argv[0]
APP_NAME = os.path.basename(APP_FILENAME)
LOG_DIR = os.path.join(APP_ROOT, 'logs')
LOG_FILE = os.path.join(LOG_DIR, 'nzbtomedia.log')
PID_FILE = os.path.join(LOG_DIR, 'nzbtomedia.pid')
CONFIG_FILE = os.path.join(APP_ROOT, 'autoProcessMedia.cfg')
CONFIG_SPEC_FILE = os.path.join(APP_ROOT, 'autoProcessMedia.cfg.spec')
CONFIG_MOVIE_FILE = os.path.join(APP_ROOT, 'autoProcessMovie.cfg')
CONFIG_TV_FILE = os.path.join(APP_ROOT, 'autoProcessTv.cfg')
TEST_FILE = os.path.join(APP_ROOT, 'tests', 'test.mp4')
MYAPP = None

import six
from six.moves import reload_module

from core import logger, main_db, version_check, databases, transcoder
from core.configuration import config
from core.plugins.downloaders.configuration import (
    configure_nzbs,
    configure_torrents,
    configure_torrent_class,
)
from core.plugins.downloaders.utils import (
    pause_torrent,
    remove_torrent,
    resume_torrent,
)
from core.plugins.plex import configure_plex
from core.utils import (
    RunningProcess,
    category_search,
    clean_dir,
    copy_link,
    extract_files,
    flatten,
    get_dirs,
    get_download_info,
    list_media_files,
    make_dir,
    parse_args,
    rchmod,
    remove_dir,
    remove_read_only,
    restart,
    sanitize_name,
    update_download_info_status,
    wake_up,
)

__version__ = '12.1.13'

# Client Agents
NZB_CLIENTS = ['sabnzbd', 'nzbget', 'manual']
TORRENT_CLIENTS = ['transmission', 'deluge', 'utorrent', 'rtorrent', 'qbittorrent', 'other', 'manual']

# sickbeard fork/branch constants
FORK_DEFAULT = 'default'
FORK_FAILED = 'failed'
FORK_FAILED_TORRENT = 'failed-torrent'
FORK_SICKCHILL = 'SickChill'
FORK_SICKCHILL_API = 'SickChill-api'
FORK_SICKBEARD_API = 'SickBeard-api'
FORK_MEDUSA = 'Medusa'
FORK_MEDUSA_API = 'Medusa-api'
FORK_MEDUSA_APIV2 = 'Medusa-apiv2'
FORK_SICKGEAR = 'SickGear'
FORK_SICKGEAR_API = 'SickGear-api'
FORK_STHENO = 'Stheno'

FORKS = {
    FORK_DEFAULT: {'dir': None},
    FORK_FAILED: {'dirName': None, 'failed': None},
    FORK_FAILED_TORRENT: {'dir': None, 'failed': None, 'process_method': None},
    FORK_SICKCHILL: {'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'delete_on': None, 'force_next': None},
    FORK_SICKCHILL_API: {'path': None, 'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'force_replace': None, 'return_data': None, 'type': None, 'delete': None, 'force_next': None, 'is_priority': None, 'cmd': 'postprocess'},
    FORK_SICKBEARD_API: {'path': None, 'failed': None, 'process_method': None, 'force_replace': None, 'return_data': None, 'type': None, 'delete': None, 'force_next': None, 'cmd': 'postprocess'},
    FORK_MEDUSA: {'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'delete_on': None, 'ignore_subs': None},
    FORK_MEDUSA_API: {'path': None, 'failed': None, 'process_method': None, 'force_replace': None, 'return_data': None, 'type': None, 'delete_files': None, 'is_priority': None, 'cmd': 'postprocess'},
    FORK_MEDUSA_APIV2: {'proc_dir': None, 'resource': None, 'failed': None, 'process_method': None, 'force': None, 'type': None, 'delete_on': None, 'is_priority': None},
    FORK_SICKGEAR: {'dir': None, 'failed': None, 'process_method': None, 'force': None},
    FORK_SICKGEAR_API: {'path': None, 'process_method': None, 'force_replace': None, 'return_data': None, 'type': None, 'is_priority': None, 'failed': None, 'cmd': 'sg.postprocess'},
    FORK_STHENO: {'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'delete_on': None, 'ignore_subs': None},
}
ALL_FORKS = {k: None for k in set(list(itertools.chain.from_iterable([FORKS[x].keys() for x in FORKS.keys()])))}

# SiCKRAGE OAuth2
SICKRAGE_OAUTH_CLIENT_ID = 'nzbtomedia'
SICKRAGE_OAUTH_TOKEN_URL = 'https://auth.sickrage.ca/realms/sickrage/protocol/openid-connect/token'

# NZBGet Exit Codes
NZBGET_POSTPROCESS_PAR_CHECK = 92
NZBGET_POSTPROCESS_SUCCESS = 93
NZBGET_POSTPROCESS_ERROR = 94
NZBGET_POSTPROCESS_NONE = 95

CFG = None
LOG_DEBUG = None
LOG_DB = None
LOG_ENV = None
LOG_GIT = None
SYS_ENCODING = None
FAILED = False

AUTO_UPDATE = None
NZBTOMEDIA_VERSION = __version__
NEWEST_VERSION = None
NEWEST_VERSION_STRING = None
VERSION_NOTIFY = None
GIT_PATH = None
GIT_USER = None
GIT_BRANCH = None
GIT_REPO = None
FORCE_CLEAN = None
SAFE_MODE = None
NOEXTRACTFAILED = None

NZB_CLIENT_AGENT = None
SABNZBD_HOST = None
SABNZBD_PORT = None
SABNZBD_APIKEY = None
NZB_DEFAULT_DIRECTORY = None

TORRENT_CLIENT_AGENT = None
TORRENT_CLASS = None
USE_LINK = None
OUTPUT_DIRECTORY = None
NOFLATTEN = []
DELETE_ORIGINAL = None
TORRENT_CHMOD_DIRECTORY = None
TORRENT_DEFAULT_DIRECTORY = None
TORRENT_RESUME = None
TORRENT_RESUME_ON_FAILURE = None

REMOTE_PATHS = []

UTORRENT_WEB_UI = None
UTORRENT_USER = None
UTORRENT_PASSWORD = None

TRANSMISSION_HOST = None
TRANSMISSION_PORT = None
TRANSMISSION_USER = None
TRANSMISSION_PASSWORD = None

SYNO_HOST = None
SYNO_PORT = None
SYNO_USER = None
SYNO_PASSWORD = None

DELUGE_HOST = None
DELUGE_PORT = None
DELUGE_USER = None
DELUGE_PASSWORD = None

QBITTORRENT_HOST = None
QBITTORRENT_PORT = None
QBITTORRENT_USER = None
QBITTORRENT_PASSWORD = None

PLEX_SSL = None
PLEX_HOST = None
PLEX_PORT = None
PLEX_TOKEN = None
PLEX_SECTION = []

EXT_CONTAINER = []
COMPRESSED_CONTAINER = []
MEDIA_CONTAINER = []
AUDIO_CONTAINER = []
META_CONTAINER = []

SECTIONS = []
CATEGORIES = []
FORK_SET = []

MOUNTED = None
GETSUBS = False
TRANSCODE = None
CONCAT = None
FFMPEG_PATH = None
SYS_PATH = None
DUPLICATE = None
IGNOREEXTENSIONS = []
VEXTENSION = None
OUTPUTVIDEOPATH = None
PROCESSOUTPUT = False
GENERALOPTS = []
OTHEROPTS = []
ALANGUAGE = None
AINCLUDE = False
SLANGUAGES = []
SINCLUDE = False
SUBSDIR = None
ALLOWSUBS = False
SEXTRACT = False
SEMBED = False
BURN = False
DEFAULTS = None
VCODEC = None
VCODEC_ALLOW = []
VPRESET = None
VFRAMERATE = None
VBITRATE = None
VLEVEL = None
VCRF = None
VRESOLUTION = None
ACODEC = None
ACODEC_ALLOW = []
ACHANNELS = None
ABITRATE = None
ACODEC2 = None
ACODEC2_ALLOW = []
ACHANNELS2 = None
ABITRATE2 = None
ACODEC3 = None
ACODEC3_ALLOW = []
ACHANNELS3 = None
ABITRATE3 = None
SCODEC = None
OUTPUTFASTSTART = None
OUTPUTQUALITYPERCENT = None
FFMPEG = None
SEVENZIP = None
SHOWEXTRACT = 0
PAR2CMD = None
FFPROBE = None
CHECK_MEDIA = None
REQUIRE_LAN = None
NICENESS = []
HWACCEL = False

PASSWORDS_FILE = None
DOWNLOAD_INFO = None
GROUPS = None

USER_SCRIPT_MEDIAEXTENSIONS = None
USER_SCRIPT = None
USER_SCRIPT_PARAM = None
USER_SCRIPT_SUCCESSCODES = None
USER_SCRIPT_CLEAN = None
USER_DELAY = None
USER_SCRIPT_RUNONCE = None

__INITIALIZED__ = False


def configure_logging():
    global LOG_FILE
    global LOG_DIR

    if 'NTM_LOGFILE' in os.environ:
        LOG_FILE = os.environ['NTM_LOGFILE']
        LOG_DIR = os.path.split(LOG_FILE)[0]

    if not make_dir(LOG_DIR):
        print('No log folder, logging to screen only')


def configure_process():
    global MYAPP

    MYAPP = RunningProcess()
    while MYAPP.alreadyrunning():
        print('Waiting for existing session to end')
        time.sleep(30)


def configure_locale():
    global SYS_ENCODING

    try:
        locale.setlocale(locale.LC_ALL, '')
        SYS_ENCODING = locale.getpreferredencoding()
    except (locale.Error, IOError):
        pass

    # For OSes that are poorly configured I'll just randomly force UTF-8
    if not SYS_ENCODING or SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'):
        SYS_ENCODING = 'UTF-8'

    if six.PY2:
        if not hasattr(sys, 'setdefaultencoding'):
            reload_module(sys)

        try:
            # pylint: disable=E1101
            # On non-unicode builds this will raise an AttributeError, if encoding type is not valid it throws a LookupError
            sys.setdefaultencoding(SYS_ENCODING)
        except Exception:
            print('Sorry, you MUST add the nzbToMedia folder to the PYTHONPATH environment variable'
                  '\nor find another way to force Python to use {codec} for string encoding.'.format
                  (codec=SYS_ENCODING))
            if 'NZBOP_SCRIPTDIR' in os.environ:
                sys.exit(NZBGET_POSTPROCESS_ERROR)
            else:
                sys.exit(1)


def configure_migration():
    global CONFIG_FILE
    global CFG

    # run migrate to convert old cfg to new style cfg plus fix any cfg missing values/options.
    if not config.migrate():
        logger.error('Unable to migrate config file {0}, exiting ...'.format(CONFIG_FILE))
        if 'NZBOP_SCRIPTDIR' in os.environ:
            pass  # We will try and read config from Environment.
        else:
            sys.exit(-1)

    # run migrate to convert NzbGet data from old cfg style to new cfg style
    if 'NZBOP_SCRIPTDIR' in os.environ:
        CFG = config.addnzbget()

    else:  # load newly migrated config
        logger.info('Loading config from [{0}]'.format(CONFIG_FILE))
        CFG = config()


def configure_logging_part_2():
    global LOG_DB
    global LOG_DEBUG
    global LOG_ENV
    global LOG_GIT

    # Enable/Disable DEBUG Logging
    LOG_DB = int(CFG['General']['log_db'])
    LOG_DEBUG = int(CFG['General']['log_debug'])
    LOG_ENV = int(CFG['General']['log_env'])
    LOG_GIT = int(CFG['General']['log_git'])

    if LOG_ENV:
        for item in os.environ:
            logger.info('{0}: {1}'.format(item, os.environ[item]), 'ENVIRONMENT')


def configure_general():
    global VERSION_NOTIFY
    global GIT_REPO
    global GIT_PATH
    global GIT_USER
    global GIT_BRANCH
    global FORCE_CLEAN
    global FFMPEG_PATH
    global SYS_PATH
    global CHECK_MEDIA
    global REQUIRE_LAN
    global SAFE_MODE
    global NOEXTRACTFAILED

    # Set Version and GIT variables
    VERSION_NOTIFY = int(CFG['General']['version_notify'])
    GIT_REPO = 'nzbToMedia'
    GIT_PATH = CFG['General']['git_path']
    GIT_USER = CFG['General']['git_user'] or 'clinton-hall'
    GIT_BRANCH = CFG['General']['git_branch'] or 'master'
    FORCE_CLEAN = int(CFG['General']['force_clean'])
    FFMPEG_PATH = CFG['General']['ffmpeg_path']
    SYS_PATH = CFG['General']['sys_path']
    CHECK_MEDIA = int(CFG['General']['check_media'])
    REQUIRE_LAN = None if not CFG['General']['require_lan'] else CFG['General']['require_lan'].split(',')
    SAFE_MODE = int(CFG['General']['safe_mode'])
    NOEXTRACTFAILED = int(CFG['General']['no_extract_failed'])


def configure_updates():
    global AUTO_UPDATE
    global MYAPP

    AUTO_UPDATE = int(CFG['General']['auto_update'])
    version_checker = version_check.CheckVersion()

    # Check for updates via GitHUB
    if version_checker.check_for_new_version() and AUTO_UPDATE:
        logger.info('Auto-Updating nzbToMedia, Please wait ...')
        if version_checker.update():
            # restart nzbToMedia
            try:
                del MYAPP
            except Exception:
                pass
            restart()
        else:
            logger.error('Update failed, not restarting. Check your log for more information.')

    # Set Current Version
    logger.info('nzbToMedia Version:{version} Branch:{branch} ({system} {release})'.format
                (version=NZBTOMEDIA_VERSION, branch=GIT_BRANCH,
                 system=platform.system(), release=platform.release()))


def configure_wake_on_lan():
    if int(CFG['WakeOnLan']['wake']):
        wake_up()


def configure_groups():
    global GROUPS

    GROUPS = CFG['Custom']['remove_group']

    if isinstance(GROUPS, str):
        GROUPS = GROUPS.split(',')

    if GROUPS == ['']:
        GROUPS = None


def configure_remote_paths():
    global REMOTE_PATHS

    REMOTE_PATHS = CFG['Network']['mount_points'] or []

    if REMOTE_PATHS:
        if isinstance(REMOTE_PATHS, list):
            REMOTE_PATHS = ','.join(REMOTE_PATHS)  # fix in case this imported as list.

        REMOTE_PATHS = (
            # /volume1/Public/,E:\|/volume2/share/,\\NAS\
            tuple(item.split(','))
            for item in REMOTE_PATHS.split('|')
        )

        REMOTE_PATHS = [
            # strip trailing and leading whitespaces
            (local.strip(), remote.strip())
            for local, remote in REMOTE_PATHS
        ]


def configure_niceness():
    global NICENESS

    with open(os.devnull, 'w') as devnull:
        try:
            subprocess.Popen(['nice'], stdout=devnull, stderr=devnull).communicate()
            if len(CFG['Posix']['niceness'].split(',')) > 1: #Allow passing of absolute command, not just value.
                NICENESS.extend(CFG['Posix']['niceness'].split(','))
            else:
                NICENESS.extend(['nice', '-n{0}'.format(int(CFG['Posix']['niceness']))])
        except Exception:
            pass
        try:
            subprocess.Popen(['ionice'], stdout=devnull, stderr=devnull).communicate()
            try:
                NICENESS.extend(['ionice', '-c{0}'.format(int(CFG['Posix']['ionice_class']))])
            except Exception:
                pass
            try:
                if 'ionice' in NICENESS:
                    NICENESS.extend(['-n{0}'.format(int(CFG['Posix']['ionice_classdata']))])
                else:
                    NICENESS.extend(['ionice', '-n{0}'.format(int(CFG['Posix']['ionice_classdata']))])
            except Exception:
                pass
        except Exception:
            pass


def configure_containers():
    global COMPRESSED_CONTAINER
    global MEDIA_CONTAINER
    global AUDIO_CONTAINER
    global META_CONTAINER

    COMPRESSED_CONTAINER = [re.compile(r'.r\d{2}$', re.I),
                            re.compile(r'.part\d+.rar$', re.I),
                            re.compile('.rar$', re.I)]
    COMPRESSED_CONTAINER += [re.compile('{0}$'.format(ext), re.I) for ext in
                             CFG['Extensions']['compressedExtensions']]
    MEDIA_CONTAINER = CFG['Extensions']['mediaExtensions']
    AUDIO_CONTAINER = CFG['Extensions']['audioExtensions']
    META_CONTAINER = CFG['Extensions']['metaExtensions']  # .nfo,.sub,.srt

    if isinstance(COMPRESSED_CONTAINER, str):
        COMPRESSED_CONTAINER = COMPRESSED_CONTAINER.split(',')

    if isinstance(MEDIA_CONTAINER, str):
        MEDIA_CONTAINER = MEDIA_CONTAINER.split(',')

    if isinstance(AUDIO_CONTAINER, str):
        AUDIO_CONTAINER = AUDIO_CONTAINER.split(',')

    if isinstance(META_CONTAINER, str):
        META_CONTAINER = META_CONTAINER.split(',')


def configure_transcoder():
    global MOUNTED
    global GETSUBS
    global TRANSCODE
    global DUPLICATE
    global CONCAT
    global IGNOREEXTENSIONS
    global OUTPUTFASTSTART
    global GENERALOPTS
    global OTHEROPTS
    global OUTPUTQUALITYPERCENT
    global OUTPUTVIDEOPATH
    global PROCESSOUTPUT
    global ALANGUAGE
    global AINCLUDE
    global SLANGUAGES
    global SINCLUDE
    global SEXTRACT
    global SEMBED
    global SUBSDIR
    global VEXTENSION
    global VCODEC
    global VPRESET
    global VFRAMERATE
    global VBITRATE
    global VRESOLUTION
    global VCRF
    global VLEVEL
    global VCODEC_ALLOW
    global ACODEC
    global ACODEC_ALLOW
    global ACHANNELS
    global ABITRATE
    global ACODEC2
    global ACODEC2_ALLOW
    global ACHANNELS2
    global ABITRATE2
    global ACODEC3
    global ACODEC3_ALLOW
    global ACHANNELS3
    global ABITRATE3
    global SCODEC
    global BURN
    global HWACCEL
    global ALLOWSUBS
    global DEFAULTS

    MOUNTED = None
    GETSUBS = int(CFG['Transcoder']['getSubs'])
    TRANSCODE = int(CFG['Transcoder']['transcode'])
    DUPLICATE = int(CFG['Transcoder']['duplicate'])
    CONCAT = int(CFG['Transcoder']['concat'])
    IGNOREEXTENSIONS = (CFG['Transcoder']['ignoreExtensions'])
    if isinstance(IGNOREEXTENSIONS, str):
        IGNOREEXTENSIONS = IGNOREEXTENSIONS.split(',')
    OUTPUTFASTSTART = int(CFG['Transcoder']['outputFastStart'])
    GENERALOPTS = (CFG['Transcoder']['generalOptions'])
    if isinstance(GENERALOPTS, str):
        GENERALOPTS = GENERALOPTS.split(',')
    if GENERALOPTS == ['']:
        GENERALOPTS = []
    if '-fflags' not in GENERALOPTS:
        GENERALOPTS.append('-fflags')
    if '+genpts' not in GENERALOPTS:
        GENERALOPTS.append('+genpts')
    OTHEROPTS = (CFG['Transcoder']['otherOptions'])
    if isinstance(OTHEROPTS, str):
        OTHEROPTS = OTHEROPTS.split(',')
    if OTHEROPTS == ['']:
        OTHEROPTS = []
    try:
        OUTPUTQUALITYPERCENT = int(CFG['Transcoder']['outputQualityPercent'])
    except Exception:
        pass
    OUTPUTVIDEOPATH = CFG['Transcoder']['outputVideoPath']
    PROCESSOUTPUT = int(CFG['Transcoder']['processOutput'])
    ALANGUAGE = CFG['Transcoder']['audioLanguage']
    AINCLUDE = int(CFG['Transcoder']['allAudioLanguages'])
    SLANGUAGES = CFG['Transcoder']['subLanguages']
    if isinstance(SLANGUAGES, str):
        SLANGUAGES = SLANGUAGES.split(',')
    if SLANGUAGES == ['']:
        SLANGUAGES = []
    SINCLUDE = int(CFG['Transcoder']['allSubLanguages'])
    SEXTRACT = int(CFG['Transcoder']['extractSubs'])
    SEMBED = int(CFG['Transcoder']['embedSubs'])
    SUBSDIR = CFG['Transcoder']['externalSubDir']
    VEXTENSION = CFG['Transcoder']['outputVideoExtension'].strip()
    VCODEC = CFG['Transcoder']['outputVideoCodec'].strip()
    VCODEC_ALLOW = CFG['Transcoder']['VideoCodecAllow'].strip()
    if isinstance(VCODEC_ALLOW, str):
        VCODEC_ALLOW = VCODEC_ALLOW.split(',')
    if VCODEC_ALLOW == ['']:
        VCODEC_ALLOW = []
    VPRESET = CFG['Transcoder']['outputVideoPreset'].strip()
    try:
        VFRAMERATE = float(CFG['Transcoder']['outputVideoFramerate'].strip())
    except Exception:
        pass
    try:
        VCRF = int(CFG['Transcoder']['outputVideoCRF'].strip())
    except Exception:
        pass
    try:
        VLEVEL = CFG['Transcoder']['outputVideoLevel'].strip()
    except Exception:
        pass
    try:
        VBITRATE = int((CFG['Transcoder']['outputVideoBitrate'].strip()).replace('k', '000'))
    except Exception:
        pass
    VRESOLUTION = CFG['Transcoder']['outputVideoResolution']
    ACODEC = CFG['Transcoder']['outputAudioCodec'].strip()
    ACODEC_ALLOW = CFG['Transcoder']['AudioCodecAllow'].strip()
    if isinstance(ACODEC_ALLOW, str):
        ACODEC_ALLOW = ACODEC_ALLOW.split(',')
    if ACODEC_ALLOW == ['']:
        ACODEC_ALLOW = []
    try:
        ACHANNELS = int(CFG['Transcoder']['outputAudioChannels'].strip())
    except Exception:
        pass
    try:
        ABITRATE = int((CFG['Transcoder']['outputAudioBitrate'].strip()).replace('k', '000'))
    except Exception:
        pass
    ACODEC2 = CFG['Transcoder']['outputAudioTrack2Codec'].strip()
    ACODEC2_ALLOW = CFG['Transcoder']['AudioCodec2Allow'].strip()
    if isinstance(ACODEC2_ALLOW, str):
        ACODEC2_ALLOW = ACODEC2_ALLOW.split(',')
    if ACODEC2_ALLOW == ['']:
        ACODEC2_ALLOW = []
    try:
        ACHANNELS2 = int(CFG['Transcoder']['outputAudioTrack2Channels'].strip())
    except Exception:
        pass
    try:
        ABITRATE2 = int((CFG['Transcoder']['outputAudioTrack2Bitrate'].strip()).replace('k', '000'))
    except Exception:
        pass
    ACODEC3 = CFG['Transcoder']['outputAudioOtherCodec'].strip()
    ACODEC3_ALLOW = CFG['Transcoder']['AudioOtherCodecAllow'].strip()
    if isinstance(ACODEC3_ALLOW, str):
        ACODEC3_ALLOW = ACODEC3_ALLOW.split(',')
    if ACODEC3_ALLOW == ['']:
        ACODEC3_ALLOW = []
    try:
        ACHANNELS3 = int(CFG['Transcoder']['outputAudioOtherChannels'].strip())
    except Exception:
        pass
    try:
        ABITRATE3 = int((CFG['Transcoder']['outputAudioOtherBitrate'].strip()).replace('k', '000'))
    except Exception:
        pass
    SCODEC = CFG['Transcoder']['outputSubtitleCodec'].strip()
    BURN = int(CFG['Transcoder']['burnInSubtitle'].strip())
    DEFAULTS = CFG['Transcoder']['outputDefault'].strip()
    HWACCEL = int(CFG['Transcoder']['hwAccel'])

    allow_subs = ['.mkv', '.mp4', '.m4v', 'asf', 'wma', 'wmv']
    codec_alias = {
        'libx264': ['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'],
        'libmp3lame': ['libmp3lame', 'mp3'],
        'libfaac': ['libfaac', 'aac', 'faac'],
    }
    transcode_defaults = {
        'iPad': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': None, 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': None, 'ACHANNELS': 2,
            'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'iPad-1080p': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': '1920:1080', 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': None, 'ACHANNELS': 2,
            'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'iPad-720p': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': '1280:720', 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': None, 'ACHANNELS': 2,
            'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'Apple-TV': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': '1280:720', 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'ac3', 'ACODEC_ALLOW': ['ac3'], 'ABITRATE': None, 'ACHANNELS': 6,
            'ACODEC2': 'aac', 'ACODEC2_ALLOW': ['libfaac'], 'ABITRATE2': None, 'ACHANNELS2': 2,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'iPod': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': '1280:720', 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
            'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'iPhone': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': '460:320', 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
            'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'PS3': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': None, 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'ac3', 'ACODEC_ALLOW': ['ac3'], 'ABITRATE': None, 'ACHANNELS': 6,
            'ACODEC2': 'aac', 'ACODEC2_ALLOW': ['libfaac'], 'ABITRATE2': None, 'ACHANNELS2': 2,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'xbox': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': None, 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'ac3', 'ACODEC_ALLOW': ['ac3'], 'ABITRATE': None, 'ACHANNELS': 6,
            'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'Roku-480p': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': None, 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
            'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'Roku-720p': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': None, 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
            'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'Roku-1080p': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': None, 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 160000, 'ACHANNELS': 2,
            'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
        'mkv': {
            'VEXTENSION': '.mkv', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': None, 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4', 'mpeg2video'],
            'ACODEC': 'dts', 'ACODEC_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE': None, 'ACHANNELS': 8,
            'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
            'ACODEC3': 'ac3', 'ACODEC3_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE3': None, 'ACHANNELS3': 8,
            'SCODEC': 'mov_text'
        },
        'mkv-bluray': {
            'VEXTENSION': '.mkv', 'VCODEC': 'libx265', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': None, 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'hevc', 'h265', 'libx265', 'h.265', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4', 'mpeg2video'],
            'ACODEC': 'dts', 'ACODEC_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE': None, 'ACHANNELS': 8,
            'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
            'ACODEC3': 'ac3', 'ACODEC3_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE3': None, 'ACHANNELS3': 8,
            'SCODEC': 'mov_text',
        },
        'mp4-scene-release': {
            'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': 19, 'VLEVEL': '3.1',
            'VRESOLUTION': None, 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4', 'mpeg2video'],
            'ACODEC': 'dts', 'ACODEC_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE': None, 'ACHANNELS': 8,
            'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
            'ACODEC3': 'ac3', 'ACODEC3_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE3': None, 'ACHANNELS3': 8,
            'SCODEC': 'mov_text',
        },
        'MKV-SD': {
            'VEXTENSION': '.mkv', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': '1200k', 'VCRF': None, 'VLEVEL': None,
            'VRESOLUTION': '720: -1', 'VCODEC_ALLOW': ['libx264', 'h264', 'h.264', 'AVC', 'avc', 'mpeg4', 'msmpeg4', 'MPEG-4'],
            'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
            'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
            'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
            'SCODEC': 'mov_text',
        },
    }
    if DEFAULTS and DEFAULTS in transcode_defaults:
        VEXTENSION = transcode_defaults[DEFAULTS]['VEXTENSION']
        VCODEC = transcode_defaults[DEFAULTS]['VCODEC']
        VPRESET = transcode_defaults[DEFAULTS]['VPRESET']
        VFRAMERATE = transcode_defaults[DEFAULTS]['VFRAMERATE']
        VBITRATE = transcode_defaults[DEFAULTS]['VBITRATE']
        VRESOLUTION = transcode_defaults[DEFAULTS]['VRESOLUTION']
        VCRF = transcode_defaults[DEFAULTS]['VCRF']
        VLEVEL = transcode_defaults[DEFAULTS]['VLEVEL']
        VCODEC_ALLOW = transcode_defaults[DEFAULTS]['VCODEC_ALLOW']
        ACODEC = transcode_defaults[DEFAULTS]['ACODEC']
        ACODEC_ALLOW = transcode_defaults[DEFAULTS]['ACODEC_ALLOW']
        ACHANNELS = transcode_defaults[DEFAULTS]['ACHANNELS']
        ABITRATE = transcode_defaults[DEFAULTS]['ABITRATE']
        ACODEC2 = transcode_defaults[DEFAULTS]['ACODEC2']
        ACODEC2_ALLOW = transcode_defaults[DEFAULTS]['ACODEC2_ALLOW']
        ACHANNELS2 = transcode_defaults[DEFAULTS]['ACHANNELS2']
        ABITRATE2 = transcode_defaults[DEFAULTS]['ABITRATE2']
        ACODEC3 = transcode_defaults[DEFAULTS]['ACODEC3']
        ACODEC3_ALLOW = transcode_defaults[DEFAULTS]['ACODEC3_ALLOW']
        ACHANNELS3 = transcode_defaults[DEFAULTS]['ACHANNELS3']
        ABITRATE3 = transcode_defaults[DEFAULTS]['ABITRATE3']
        SCODEC = transcode_defaults[DEFAULTS]['SCODEC']
    transcode_defaults = {}  # clear memory
    if transcode_defaults in ['mp4-scene-release'] and not OUTPUTQUALITYPERCENT:
        OUTPUTQUALITYPERCENT = 100

    if VEXTENSION in allow_subs:
        ALLOWSUBS = 1
    if not VCODEC_ALLOW and VCODEC:
        VCODEC_ALLOW.extend([VCODEC])
    for codec in VCODEC_ALLOW:
        if codec in codec_alias:
            extra = [item for item in codec_alias[codec] if item not in VCODEC_ALLOW]
            VCODEC_ALLOW.extend(extra)
    if not ACODEC_ALLOW and ACODEC:
        ACODEC_ALLOW.extend([ACODEC])
    for codec in ACODEC_ALLOW:
        if codec in codec_alias:
            extra = [item for item in codec_alias[codec] if item not in ACODEC_ALLOW]
            ACODEC_ALLOW.extend(extra)
    if not ACODEC2_ALLOW and ACODEC2:
        ACODEC2_ALLOW.extend([ACODEC2])
    for codec in ACODEC2_ALLOW:
        if codec in codec_alias:
            extra = [item for item in codec_alias[codec] if item not in ACODEC2_ALLOW]
            ACODEC2_ALLOW.extend(extra)
    if not ACODEC3_ALLOW and ACODEC3:
        ACODEC3_ALLOW.extend([ACODEC3])
    for codec in ACODEC3_ALLOW:
        if codec in codec_alias:
            extra = [item for item in codec_alias[codec] if item not in ACODEC3_ALLOW]
            ACODEC3_ALLOW.extend(extra)


def configure_passwords_file():
    global PASSWORDS_FILE

    PASSWORDS_FILE = CFG['passwords']['PassWordFile']


def configure_sections(section):
    global SECTIONS
    global CATEGORIES
    # check for script-defied section and if None set to allow sections
    SECTIONS = CFG[
        tuple(x for x in CFG if CFG[x].sections and CFG[x].isenabled())
        if not section else (section,)
    ]
    for section, subsections in SECTIONS.items():
        CATEGORIES.extend([subsection for subsection in subsections if CFG[section][subsection].isenabled()])
    CATEGORIES = list(set(CATEGORIES))


def configure_utility_locations():
    global SHOWEXTRACT
    global SEVENZIP
    global FFMPEG
    global FFPROBE
    global PAR2CMD

    # Setup FFMPEG, FFPROBE and SEVENZIP locations
    if platform.system() == 'Windows':
        FFMPEG = os.path.join(FFMPEG_PATH, 'ffmpeg.exe')
        FFPROBE = os.path.join(FFMPEG_PATH, 'ffprobe.exe')
        SEVENZIP = os.path.join(APP_ROOT, 'core', 'extractor', 'bin', platform.machine(), '7z.exe')
        SHOWEXTRACT = int(str(CFG['Windows']['show_extraction']), 0)

        if not (os.path.isfile(FFMPEG)):  # problem
            FFMPEG = None
            logger.warning('Failed to locate ffmpeg.exe. Transcoding disabled!')
            logger.warning('Install ffmpeg with x264 support to enable this feature  ...')

        if not (os.path.isfile(FFPROBE)):
            FFPROBE = None
            if CHECK_MEDIA:
                logger.warning('Failed to locate ffprobe.exe. Video corruption detection disabled!')
                logger.warning('Install ffmpeg with x264 support to enable this feature  ...')

    else:
        if SYS_PATH:
            os.environ['PATH'] += ':' + SYS_PATH
        try:
            SEVENZIP = subprocess.Popen(['which', '7z'], stdout=subprocess.PIPE).communicate()[0].strip().decode()
        except Exception:
            pass
        if not SEVENZIP:
            try:
                SEVENZIP = subprocess.Popen(['which', '7zr'], stdout=subprocess.PIPE).communicate()[0].strip().decode()
            except Exception:
                pass
        if not SEVENZIP:
            try:
                SEVENZIP = subprocess.Popen(['which', '7za'], stdout=subprocess.PIPE).communicate()[0].strip().decode()
            except Exception:
                pass
        if not SEVENZIP:
            SEVENZIP = None
            logger.warning(
                'Failed to locate 7zip. Transcoding of disk images and extraction of .7z files will not be possible!')
        try:
            PAR2CMD = subprocess.Popen(['which', 'par2'], stdout=subprocess.PIPE).communicate()[0].strip().decode()
        except Exception:
            pass
        if not PAR2CMD:
            PAR2CMD = None
            logger.warning(
                'Failed to locate par2. Repair and rename using par files will not be possible!')
        if os.path.isfile(os.path.join(FFMPEG_PATH, 'ffmpeg')) or os.access(os.path.join(FFMPEG_PATH, 'ffmpeg'),
                                                                            os.X_OK):
            FFMPEG = os.path.join(FFMPEG_PATH, 'ffmpeg')
        elif os.path.isfile(os.path.join(FFMPEG_PATH, 'avconv')) or os.access(os.path.join(FFMPEG_PATH, 'avconv'),
                                                                              os.X_OK):
            FFMPEG = os.path.join(FFMPEG_PATH, 'avconv')
        else:
            try:
                FFMPEG = subprocess.Popen(['which', 'ffmpeg'], stdout=subprocess.PIPE).communicate()[0].strip().decode()
            except Exception:
                pass
            if not FFMPEG:
                try:
                    FFMPEG = subprocess.Popen(['which', 'avconv'], stdout=subprocess.PIPE).communicate()[0].strip().decode()
                except Exception:
                    pass
        if not FFMPEG:
            FFMPEG = None
            logger.warning('Failed to locate ffmpeg. Transcoding disabled!')
            logger.warning('Install ffmpeg with x264 support to enable this feature  ...')

        if os.path.isfile(os.path.join(FFMPEG_PATH, 'ffprobe')) or os.access(os.path.join(FFMPEG_PATH, 'ffprobe'),
                                                                             os.X_OK):
            FFPROBE = os.path.join(FFMPEG_PATH, 'ffprobe')
        elif os.path.isfile(os.path.join(FFMPEG_PATH, 'avprobe')) or os.access(os.path.join(FFMPEG_PATH, 'avprobe'),
                                                                               os.X_OK):
            FFPROBE = os.path.join(FFMPEG_PATH, 'avprobe')
        else:
            try:
                FFPROBE = subprocess.Popen(['which', 'ffprobe'], stdout=subprocess.PIPE).communicate()[0].strip().decode()
            except Exception:
                pass
            if not FFPROBE:
                try:
                    FFPROBE = subprocess.Popen(['which', 'avprobe'], stdout=subprocess.PIPE).communicate()[0].strip().decode()
                except Exception:
                    pass
        if not FFPROBE:
            FFPROBE = None
            if CHECK_MEDIA:
                logger.warning('Failed to locate ffprobe. Video corruption detection disabled!')
                logger.warning('Install ffmpeg with x264 support to enable this feature  ...')


def check_python():
    """Check End-of-Life status for Python version."""
    # Raise if end of life
    eol.check()

    # Warn if within grace period
    grace_period = 365  # days
    eol.warn_for_status(grace_period=-grace_period)

    # Log warning if within grace period
    days_left = eol.lifetime()
    if days_left > 0:
        logger.info(
            'Python v{major}.{minor} will reach end of life in {x} days.'.format(
                major=sys.version_info[0],
                minor=sys.version_info[1],
                x=days_left,
            ),
        )
    else:
        logger.info(
            'Python v{major}.{minor} reached end of life {x} days ago.'.format(
                major=sys.version_info[0],
                minor=sys.version_info[1],
                x=-days_left,
            ),
        )
    if days_left <= grace_period:
        logger.warning('Please upgrade to a more recent Python version.')


def initialize(section=None):
    global __INITIALIZED__

    if __INITIALIZED__:
        return False

    configure_logging()
    configure_process()
    configure_locale()

    # init logging
    logger.ntm_log_instance.init_logging()

    configure_migration()
    configure_logging_part_2()

    # check python version
    check_python()

    # initialize the main SB database
    main_db.upgrade_database(main_db.DBConnection(), databases.InitialSchema)

    configure_general()
    configure_updates()
    configure_wake_on_lan()
    configure_nzbs(CFG)
    configure_torrents(CFG)
    configure_remote_paths()
    configure_plex(CFG)
    configure_niceness()
    configure_containers()
    configure_transcoder()
    configure_passwords_file()
    configure_utility_locations()
    configure_sections(section)
    configure_torrent_class()
    configure_groups()

    __INITIALIZED__ = True

    # finished initializing
    return __INITIALIZED__


================================================
FILE: core/auto_process/__init__.py
================================================


================================================
FILE: core/auto_process/books.py
================================================
# coding=utf-8

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import requests

import core
from core import logger
from core.auto_process.common import ProcessResult
from core.utils import (
    convert_to_ascii,
    remote_dir,
    server_responding,
)


requests.packages.urllib3.disable_warnings()


def process(section, dir_name, input_name=None, status=0, client_agent='manual', input_category=None):
    status = int(status)

    cfg = dict(core.CFG[section][input_category])

    host = cfg['host']
    port = cfg['port']
    apikey = cfg['apikey']
    ssl = int(cfg.get('ssl', 0))
    web_root = cfg.get('web_root', '')
    protocol = 'https://' if ssl else 'http://'
    remote_path = int(cfg.get('remote_path', 0))
    import_mode = cfg.get('importMode', cfg.get('importmode', 'Copy'))

    if section.lower() == 'readarr':
        url = '{0}{1}:{2}{3}/api/v1/command'.format(protocol, host, port, web_root)
        if not server_responding(url):
            logger.error('Server did not respond. Exiting', section)
            return ProcessResult(
                message='{0}: Failed to post-process - {0} did not respond.'.format(section),
                status_code=1,
            )

        input_name, dir_name = convert_to_ascii(input_name, dir_name)

        payload = {
            "name": "DownloadedBooksScan",
            "path": remote_dir(dir_name) if remote_path else dir_name,
            "importMode": import_mode
        }
        headers = {"X-Api-Key": apikey}

        logger.debug('POST to {0} with payload: {1}'.format(url, payload), section)

        try:
            r = requests.post(url, json=payload, headers=headers, verify=False, timeout=(30, 300))
        except requests.ConnectionError:
            logger.error('Unable to connect to Readarr', section)
            return ProcessResult(
                message='{0}: Failed to post-process - Unable to connect'.format(section),
                status_code=1,
            )

        if r.status_code in (200, 201, 202):
            logger.postprocess('SUCCESS: Readarr import triggered for {0}'.format(dir_name), section)
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(section, input_name),
                status_code=0,
            )
        else:
            logger.error('FAILED: Readarr returned status {0}, body: {1}'.format(r.status_code, r.text), section)
            return ProcessResult(
                message='{0}: Failed to post-process - HTTP {1}'.format(section, r.status_code),
                status_code=1,
            )

    url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root)
    if not server_responding(url):
        logger.error('Server did not respond. Exiting', section)
        return ProcessResult(
            message='{0}: Failed to post-process - {0} did not respond.'.format(section),
            status_code=1,
        )

    input_name, dir_name = convert_to_ascii(input_name, dir_name)

    params = {
        'apikey': apikey,
        'cmd': 'forceProcess',
        'dir': remote_dir(dir_name) if remote_path else dir_name,
    }
    logger.debug('Opening URL: {0} with params: {1}'.format(url, params), section)

    try:
        r = requests.get(url, params=params, verify=False, timeout=(30, 300))
    except requests.ConnectionError:
        logger.error('Unable to open URL')
        return ProcessResult(
            message='{0}: Failed to post-process - Unable to connect to {1}'.format(section, section),
            status_code=1,
        )

    logger.postprocess('{0}'.format(r.text), section)

    if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
        logger.error('Server returned status {0}'.format(r.status_code), section)
        return ProcessResult(
            message='{0}: Failed to post-process - Server returned status {1}'.format(section, r.status_code),
            status_code=1,
        )
    elif r.text == 'OK':
        logger.postprocess('SUCCESS: ForceProcess for {0} has been started in LazyLibrarian'.format(dir_name), section)
        return ProcessResult(
            message='{0}: Successfully post-processed {1}'.format(section, input_name),
            status_code=0,
        )
    else:
        logger.error('FAILED: ForceProcess of {0} has Failed in LazyLibrarian'.format(dir_name), section)
        return ProcessResult(
            message='{0}: Failed to post-process - Returned log from {0} was not as expected.'.format(section),
            status_code=1,
        )


================================================
FILE: core/auto_process/comics.py
================================================
# coding=utf-8

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import os

import requests

import core
from core import logger
from core.auto_process.common import ProcessResult
from core.utils import convert_to_ascii, remote_dir, server_responding

requests.packages.urllib3.disable_warnings()


def process(section, dir_name, input_name=None, status=0, client_agent='manual', input_category=None):
    apc_version = '2.04'
    comicrn_version = '1.01'

    cfg = dict(core.CFG[section][input_category])

    host = cfg['host']
    port = cfg['port']
    apikey = cfg['apikey']
    ssl = int(cfg.get('ssl', 0))
    web_root = cfg.get('web_root', '')
    remote_path = int(cfg.get('remote_path'), 0)
    protocol = 'https://' if ssl else 'http://'

    url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root)
    if not server_responding(url):
        logger.error('Server did not respond. Exiting', section)
        return ProcessResult(
            message='{0}: Failed to post-process - {0} did not respond.'.format(section),
            status_code=1,
        )

    input_name, dir_name = convert_to_ascii(input_name, dir_name)
    clean_name, ext = os.path.splitext(input_name)
    if len(ext) == 4:  # we assume this was a standard extension.
        input_name = clean_name

    params = {
        'cmd': 'forceProcess',
        'apikey': apikey,
        'nzb_folder': remote_dir(dir_name) if remote_path else dir_name,
    }

    if input_name is not None:
        params['nzb_name'] = input_name
    params['failed'] = int(status)
    params['apc_version'] = apc_version
    params['comicrn_version'] = comicrn_version

    success = False

    logger.debug('Opening URL: {0}'.format(url), section)
    try:
        r = requests.post(url, params=params, stream=True, verify=False, timeout=(30, 300))
    except requests.ConnectionError:
        logger.error('Unable to open URL', section)
        return ProcessResult(
            message='{0}: Failed to post-process - Unable to connect to {0}'.format(section),
            status_code=1,
        )
    if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
        logger.error('Server returned status {0}'.format(r.status_code), section)
        return ProcessResult(
            message='{0}: Failed to post-process - Server returned status {1}'.format(section, r.status_code),
            status_code=1,
        )

    result = r.text
    if not type(result) == list:
        result = result.split('\n')
    for line in result:
        if line:
            logger.postprocess('{0}'.format(line), section)
        if 'Post Processing SUCCESSFUL' in line:
            success = True

    if success:
        logger.postprocess('SUCCESS: This issue has been processed successfully', section)
        return ProcessResult(
            message='{0}: Successfully post-processed {1}'.format(section, input_name),
            status_code=0,
        )
    else:
        logger.warning('The issue does not appear to have successfully processed. Please check your Logs', section)
        return ProcessResult(
            message='{0}: Failed to post-process - Returned log from {0} was not as expected.'.format(section),
            status_code=1,
        )


================================================
FILE: core/auto_process/common.py
================================================
from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import requests

from core import logger


class ProcessResult(object):
    def __init__(self, message, status_code):
        self.message = message
        self.status_code = status_code

    def __iter__(self):
        return self.status_code, self.message

    def __bool__(self):
        return not bool(self.status_code)

    def __str__(self):
        return 'Processing {0}: {1}'.format(
            'succeeded' if bool(self) else 'failed',
            self.message,
        )

    def __repr__(self):
        return '<ProcessResult {0}: {1}>'.format(
            self.status_code,
            self.message,
        )


def command_complete(url, params, headers, section):
    try:
        r = requests.get(url, params=params, headers=headers, stream=True, verify=False, timeout=(30, 60))
    except requests.ConnectionError:
        logger.error('Unable to open URL: {0}'.format(url), section)
        return None
    if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
        logger.error('Server returned status {0}'.format(r.status_code), section)
        return None
    else:
        try:
            return r.json()['status']
        except (ValueError, KeyError):
            # ValueError catches simplejson's JSONDecodeError and json's ValueError
            logger.error('{0} did not return expected json data.'.format(section), section)
            return None


def completed_download_handling(url2, headers, section='MAIN'):
    try:
        r = requests.get(url2, params={}, headers=headers, stream=True, verify=False, timeout=(30, 60))
    except requests.ConnectionError:
        logger.error('Unable to open URL: {0}'.format(url2), section)
        return False
    if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
        logger.error('Server returned status {0}'.format(r.status_code), section)
        return False
    else:
        try:
            return r.json().get('enableCompletedDownloadHandling', False)
        except ValueError:
            # ValueError catches simplejson's JSONDecodeError and json's ValueError
            return False


================================================
FILE: core/auto_process/games.py
================================================
# coding=utf-8

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import os
import shutil

import requests

import core
from core import logger
from core.auto_process.common import ProcessResult
from core.utils import convert_to_ascii, server_responding

requests.packages.urllib3.disable_warnings()


def process(section, dir_name, input_name=None, status=0, client_agent='manual', input_category=None):
    status = int(status)

    cfg = dict(core.CFG[section][input_category])

    host = cfg['host']
    port = cfg['port']
    apikey = cfg['apikey']
    library = cfg.get('library')
    ssl = int(cfg.get('ssl', 0))
    web_root = cfg.get('web_root', '')
    protocol = 'https://' if ssl else 'http://'

    url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root)
    if not server_responding(url):
        logger.error('Server did not respond. Exiting', section)
        return ProcessResult(
            message='{0}: Failed to post-process - {0} did not respond.'.format(section),
            status_code=1,
        )

    input_name, dir_name = convert_to_ascii(input_name, dir_name)

    fields = input_name.split('-')

    gamez_id = fields[0].replace('[', '').replace(']', '').replace(' ', '')

    download_status = 'Downloaded' if status == 0 else 'Wanted'

    params = {
        'api_key': apikey,
        'mode': 'UPDATEREQUESTEDSTATUS',
        'db_id': gamez_id,
        'status': download_status,
    }

    logger.debug('Opening URL: {0}'.format(url), section)

    try:
        r = requests.get(url, params=params, verify=False, timeout=(30, 300))
    except requests.ConnectionError:
        logger.error('Unable to open URL')
        return ProcessResult(
            message='{0}: Failed to post-process - Unable to connect to {1}'.format(section, section),
            status_code=1,
        )

    result = r.json()
    logger.postprocess('{0}'.format(result), section)
    if library:
        logger.postprocess('moving files to library: {0}'.format(library), section)
        try:
            shutil.move(dir_name, os.path.join(library, input_name))
        except Exception:
            logger.error('Unable to move {0} to {1}'.format(dir_name, os.path.join(library, input_name)), section)
            return ProcessResult(
                message='{0}: Failed to post-process - Unable to move files'.format(section),
                status_code=1,
            )
    else:
        logger.error('No library specified to move files to. Please edit your configuration.', section)
        return ProcessResult(
            message='{0}: Failed to post-process - No library defined in {0}'.format(section),
            status_code=1,
        )

    if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
        logger.error('Server returned status {0}'.format(r.status_code), section)
        return ProcessResult(
            message='{0}: Failed to post-process - Server returned status {1}'.format(section, r.status_code),
            status_code=1,
        )
    elif result['success']:
        logger.postprocess('SUCCESS: Status for {0} has been set to {1} in Gamez'.format(gamez_id, download_status), section)
        return ProcessResult(
            message='{0}: Successfully post-processed {1}'.format(section, input_name),
            status_code=0,
        )
    else:
        logger.error('FAILED: Status for {0} has NOT been updated in Gamez'.format(gamez_id), section)
        return ProcessResult(
            message='{0}: Failed to post-process - Returned log from {0} was not as expected.'.format(section),
            status_code=1,
        )


================================================
FILE: core/auto_process/managers/__init__.py
================================================


================================================
FILE: core/auto_process/managers/pymedusa.py
================================================
import time

from core import logger
from core.auto_process.common import ProcessResult
from core.auto_process.managers.sickbeard import SickBeard

import requests


class PyMedusa(SickBeard):
    """PyMedusa class."""

    def __init__(self, sb_init):
        super(PyMedusa, self).__init__(sb_init)

    def _create_url(self):
        return '{0}{1}:{2}{3}/home/postprocess/processEpisode'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root)


class PyMedusaApiV1(SickBeard):
    """PyMedusa apiv1 class."""

    def __init__(self, sb_init):
        super(PyMedusaApiV1, self).__init__(sb_init)

    def _create_url(self):
        return '{0}{1}:{2}{3}/api/{4}/'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root, self.sb_init.apikey)

    def api_call(self):
        self._process_fork_prarams()
        url = self._create_url()

        logger.debug('Opening URL: {0} with params: {1}'.format(url, self.sb_init.fork_params), self.sb_init.section)
        try:
            response = self.session.get(url, auth=(self.sb_init.username, self.sb_init.password), params=self.sb_init.fork_params, stream=True, verify=False, timeout=(30, 1800))
        except requests.ConnectionError:
            logger.error('Unable to open URL: {0}'.format(url), self.sb_init.section)
            return ProcessResult(
                message='{0}: Failed to post-process - Unable to connect to {0}'.format(self.sb_init.section),
                status_code=1,
            )

        if response.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
            logger.error('Server returned status {0}'.format(response.status_code), self.sb_init.section)
            return ProcessResult(
                message='{0}: Failed to post-process - Server returned status {1}'.format(self.sb_init.section, response.status_code),
                status_code=1,
            )

        if response.json()['result'] == 'success':
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(self.sb_init.section, self.input_name),
                status_code=0,
            )
        return ProcessResult(
            message='{0}: Failed to post-process - Returned log from {0} was not as expected.'.format(self.sb_init.section),
            status_code=1,  # We did not receive Success confirmation.
        )


class PyMedusaApiV2(SickBeard):
    """PyMedusa apiv2 class."""

    def __init__(self, sb_init):
        super(PyMedusaApiV2, self).__init__(sb_init)

        # Check for an apikey, as this is required with using fork = medusa-apiv2
        if not sb_init.apikey:
            raise Exception('For the section SickBeard `fork = medusa-apiv2` you also need to configure an `apikey`')

    def _create_url(self):
        return '{0}{1}:{2}{3}/api/v2/postprocess'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root)

    def _get_identifier_status(self, url):
        # Loop through requesting medusa for the status on the queueitem.
        try:
            response = self.session.get(url, verify=False, timeout=(30, 1800))
        except requests.ConnectionError:
            logger.error('Unable to get postprocess identifier status', self.sb_init.section)
            return False

        try:
            jdata = response.json()
        except ValueError:
            return False

        return jdata

    def api_call(self):
        self._process_fork_prarams()
        url = self._create_url()

        logger.debug('Opening URL: {0}'.format(url), self.sb_init.section)
        payload = self.sb_init.fork_params
        payload['resource'] = self.sb_init.fork_params['nzbName']
        del payload['nzbName']

        # Update the session with the x-api-key
        self.session.headers.update({
            'x-api-key': self.sb_init.apikey,
            'Content-type': 'application/json'
        })

        # Send postprocess request
        try:
            response = self.session.post(url, json=payload, verify=False, timeout=(30, 1800))
        except requests.ConnectionError:
            logger.error('Unable to send postprocess request', self.sb_init.section)
            return ProcessResult(
                message='{0}: Unable to send postprocess request to PyMedusa',
                status_code=1,
            )

        # Get UUID
        if response:
            try:
                jdata = response.json()
            except ValueError:
                logger.debug('No data returned from provider')
                return False

        if not jdata.get('status') or not jdata['status'] == 'success':
            return False

        queueitem_identifier = jdata['queueItem']['identifier']

        wait_for = int(self.sb_init.config.get('wait_for', 2))
        n = 0
        response = {}
        url = '{0}/{1}'.format(url, queueitem_identifier)
        while n < 12:  # set up wait_for minutes to see if command completes..
            time.sleep(5 * wait_for)
            response = self._get_identifier_status(url)
            if response and response.get('success'):
                break
            if 'error' in response:
                break
            n += 1

        # Log Medusa's PP logs here.
        if response.get('output'):
            for line in response['output']:
                logger.postprocess('{0}'.format(line), self.sb_init.section)

        # For now this will most likely always be True. But in the future we could return an exit state
        # for when the PP in medusa didn't yield an expected result.
        if response.get('success'):
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(self.sb_init.section, self.input_name),
                status_code=0,
            )
        return ProcessResult(
            message='{0}: Failed to post-process - Returned log from {0} was not as expected.'.format(self.sb_init.section),
            status_code=1,  # We did not receive Success confirmation.
        )


================================================
FILE: core/auto_process/managers/sickbeard.py
================================================
# coding=utf-8

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import copy

import core
from core import logger
from core.auto_process.common import (
    ProcessResult,
)
from core.utils import remote_dir

from oauthlib.oauth2 import LegacyApplicationClient

import requests

from requests_oauthlib import OAuth2Session

import six
from six import iteritems


class InitSickBeard(object):
    """Sickbeard init class.

    Used to determin which sickbeard fork object to initialize.
    """

    def __init__(self, cfg, section, input_category):
        # As a bonus let's also put the config on self.
        self.config = cfg
        self.section = section
        self.input_category = input_category

        self.host = cfg['host']
        self.port = cfg['port']
        self.ssl = int(cfg.get('ssl', 0))
        self.web_root = cfg.get('web_root', '')
        self.protocol = 'https://' if self.ssl else 'http://'
        self.username = cfg.get('username', '')
        self.password = cfg.get('password', '')
        self.apikey = cfg.get('apikey', '')
        self.api_version = int(cfg.get('api_version', 2))
        self.sso_username = cfg.get('sso_username', '')
        self.sso_password = cfg.get('sso_password', '')

        self.fork = ''
        self.fork_params = None
        self.fork_obj = None

        replace = {
            'medusa': 'Medusa',
            'medusa-api': 'Medusa-api',
            'sickbeard-api': 'SickBeard-api',
            'sickgear': 'SickGear',
            'sickchill': 'SickChill',
            'stheno': 'Stheno',
        }
        _val = cfg.get('fork', 'auto')
        f1 = replace.get(_val, _val)
        try:
            self.fork = f1, core.FORKS[f1]
        except KeyError:
            self.fork = 'auto'
            self.protocol = 'https://' if self.ssl else 'http://'

    def auto_fork(self):
        # auto-detect correct section
        # config settings
        if core.FORK_SET:  # keep using determined fork for multiple (manual) post-processing
            logger.info('{section}:{category} fork already set to {fork}'.format
                        (section=self.section, category=self.input_category, fork=core.FORK_SET[0]))
            return core.FORK_SET[0], core.FORK_SET[1]

        cfg = dict(core.CFG[self.section][self.input_category])

        replace = {
            'medusa': 'Medusa',
            'medusa-api': 'Medusa-api',
            'medusa-apiv1': 'Medusa-api',
            'medusa-apiv2': 'Medusa-apiv2',
            'sickbeard-api': 'SickBeard-api',
            'sickgear': 'SickGear',
            'sickchill': 'SickChill',
            'stheno': 'Stheno',
        }
        _val = cfg.get('fork', 'auto')
        f1 = replace.get(_val.lower(), _val)
        try:
            self.fork = f1, core.FORKS[f1]
        except KeyError:
            self.fork = 'auto'
        protocol = 'https://' if self.ssl else 'http://'

        if self.section == 'NzbDrone':
            logger.info('Attempting to verify {category} fork'.format
                        (category=self.input_category))
            url = '{protocol}{host}:{port}{root}/api/rootfolder'.format(
                protocol=protocol, host=self.host, port=self.port, root=self.web_root,
            )
            headers = {'X-Api-Key': self.apikey}
            try:
                r = requests.get(url, headers=headers, stream=True, verify=False)
            except requests.ConnectionError:
                logger.warning('Could not connect to {0}:{1} to verify fork!'.format(self.section, self.input_category))

            if not r.ok:
                logger.warning('Connection to {section}:{category} failed! '
                               'Check your configuration'.format
                               (section=self.section, category=self.input_category))

            self.fork = ['default', {}]

        elif self.section == 'SiCKRAGE':
            logger.info('Attempting to verify {category} fork'.format
                        (category=self.input_category))

            if self.api_version >= 2:
                url = '{protocol}{host}:{port}{root}/api/v{api_version}/ping'.format(
                    protocol=protocol, host=self.host, port=self.port, root=self.web_root, api_version=self.api_version
                )
                api_params = {}
            else:
                url = '{protocol}{host}:{port}{root}/api/v{api_version}/{apikey}/'.format(
                    protocol=protocol, host=self.host, port=self.port, root=self.web_root, api_version=self.api_version, apikey=self.apikey,
                )
                api_params = {'cmd': 'postprocess', 'help': '1'}

            try:
                if self.api_version >= 2 and self.sso_username and self.sso_password:
                    oauth = OAuth2Session(client=LegacyApplicationClient(client_id=core.SICKRAGE_OAUTH_CLIENT_ID))
                    oauth_token = oauth.fetch_token(client_id=core.SICKRAGE_OAUTH_CLIENT_ID,
                                                    token_url=core.SICKRAGE_OAUTH_TOKEN_URL,
                                                    username=self.sso_username,
                                                    password=self.sso_password)
                    r = requests.get(url, headers={'Authorization': 'Bearer ' + oauth_token['access_token']}, stream=True, verify=False)
                else:
                    r = requests.get(url, params=api_params, stream=True, verify=False)

                if not r.ok:
                    logger.warning('Connection to {section}:{category} failed! '
                                   'Check your configuration'.format(
                                       section=self.section, category=self.input_category
                                   ))
            except requests.ConnectionError:
                logger.warning('Could not connect to {0}:{1} to verify API version!'.format(self.section, self.input_category))

            params = {
                'path': None,
                'failed': None,
                'process_method': None,
                'force_replace': None,
                'return_data': None,
                'type': None,
                'delete': None,
                'force_next': None,
                'is_priority': None
            }

            self.fork = ['default', params]

        elif self.fork == 'auto':
            self.detect_fork()

        logger.info('{section}:{category} fork set to {fork}'.format
                    (section=self.section, category=self.input_category, fork=self.fork[0]))
        core.FORK_SET = self.fork
        self.fork, self.fork_params = self.fork[0], self.fork[1]
        # This will create the fork object, and attach to self.fork_obj.
        self._init_fork()
        return self.fork, self.fork_params

    @staticmethod
    def _api_check(r, params, rem_params):
        try:
            json_data = r.json()
        except ValueError:
            logger.error('Failed to get JSON data from response')
            logger.debug('Response received')
            raise

        try:
            json_data = json_data['data']
        except KeyError:
            logger.error('Failed to get data from JSON')
            logger.debug('Response received: {}'.format(json_data))
            raise
        else:
            if six.PY3:
                str_type = (str)
            else:
                str_type = (str, unicode)
            if isinstance(json_data, str_type):
                return rem_params, False
            json_data = json_data.get('data', json_data)

        try:
            optional_parameters = json_data['optionalParameters'].keys()
            # Find excess parameters
            excess_parameters = set(params).difference(optional_parameters)
            excess_parameters.remove('cmd')  # Don't remove cmd from api params
            logger.debug('Removing excess parameters: {}'.format(sorted(excess_parameters)))
            rem_params.extend(excess_parameters)
            return rem_params, True
        except:
            logger.error('Failed to identify optionalParameters')
            return rem_params, False

    def detect_fork(self):
        """Try to detect a specific fork."""
        detected = False
        params = core.ALL_FORKS
        rem_params = []
        logger.info('Attempting to auto-detect {category} fork'.format(category=self.input_category))
        # define the order to test. Default must be first since the default fork doesn't reject parameters.
        # then in order of most unique parameters.

        if self.apikey:
            url = '{protocol}{host}:{port}{root}/api/{apikey}/'.format(
                protocol=self.protocol, host=self.host, port=self.port, root=self.web_root, apikey=self.apikey,
            )
            api_params = {'cmd': 'sg.postprocess', 'help': '1'}
        else:
            url = '{protocol}{host}:{port}{root}/home/postprocess/'.format(
                protocol=self.protocol, host=self.host, port=self.port, root=self.web_root,
            )
            api_params = {}

        # attempting to auto-detect fork
        try:
            s = requests.Session()

            if not self.apikey and self.username and self.password:
                login = '{protocol}{host}:{port}{root}/login'.format(
                    protocol=self.protocol, host=self.host, port=self.port, root=self.web_root)
                login_params = {'username': self.username, 'password': self.password}
                r = s.get(login, verify=False, timeout=(30, 60))
                if r.status_code in [401, 403] and r.cookies.get('_xsrf'):
                    login_params['_xsrf'] = r.cookies.get('_xsrf')
                s.post(login, data=login_params, stream=True, verify=False)
            r = s.get(url, auth=(self.username, self.password), params=api_params, verify=False)
        except requests.ConnectionError:
            logger.info('Could not connect to {section}:{category} to perform auto-fork detection!'.format
                        (section=self.section, category=self.input_category))
            r = []

        if r and r.ok:
            if self.apikey:
                rem_params, found = self._api_check(r, params, rem_params)
                if found:
                    params['cmd'] = 'sg.postprocess'
                else:  # try different api set for non-SickGear forks.
                    api_params = {'cmd': 'help', 'subject': 'postprocess'}
                    try:
                        if not self.apikey and self.username and self.password:
                            r = s.get(url, auth=(self.username, self.password), params=api_params, verify=False)
                        else:
                            r = s.get(url, params=api_params, verify=False)
                    except requests.ConnectionError:
                        logger.info('Could not connect to {section}:{category} to perform auto-fork detection!'.format
                                    (section=self.section, category=self.input_category))
                    rem_params, found = self._api_check(r, params, rem_params)
                    params['cmd'] = 'postprocess'
            else:
                # Find excess parameters
                rem_params.extend(
                    param
                    for param in params
                    if 'name="{param}"'.format(param=param) not in r.text
                )

            # Remove excess params
            for param in rem_params:
                params.pop(param)

            for fork in sorted(iteritems(core.FORKS), reverse=False):
                if params == fork[1]:
                    detected = True
                    break

        if detected:
            self.fork = fork
            logger.info('{section}:{category} fork auto-detection successful ...'.format
                        (section=self.section, category=self.input_category))
        elif rem_params:
            logger.info('{section}:{category} fork auto-detection found custom params {params}'.format
                        (section=self.section, category=self.input_category, params=params))
            self.fork = ['custom', params]
        else:
            logger.info('{section}:{category} fork auto-detection failed'.format
                        (section=self.section, category=self.input_category))
            self.fork = list(core.FORKS.items())[list(core.FORKS.keys()).index(core.FORK_DEFAULT)]

    def _init_fork(self):
        # These need to be imported here, to prevent a circular import.
        from .pymedusa import PyMedusa, PyMedusaApiV1, PyMedusaApiV2

        mapped_forks = {
            'Medusa': PyMedusa,
            'Medusa-api': PyMedusaApiV1,
            'Medusa-apiv2': PyMedusaApiV2
        }
        logger.debug('Create object for fork {fork}'.format(fork=self.fork))
        if self.fork and mapped_forks.get(self.fork):
            # Create the fork object and pass self (SickBeardInit) to it for all the data, like Config.
            self.fork_obj = mapped_forks[self.fork](self)
        else:
            logger.debug('{section}:{category} Could not create a fork object for {fork}. Probaly class not added yet.'.format(
                section=self.section, category=self.input_category, fork=self.fork)
            )


class SickBeard(object):
    """Sickbeard base class."""

    def __init__(self, sb_init):
        """SB constructor."""
        self.sb_init = sb_init
        self.session = requests.Session()

        self.failed = None
        self.status = None
        self.input_name = None
        self.dir_name = None

        self.delete_failed = int(self.sb_init.config.get('delete_failed', 0))
        self.nzb_extraction_by = self.sb_init.config.get('nzbExtractionBy', 'Downloader')
        self.process_method = self.sb_init.config.get('process_method')
        self.remote_path = int(self.sb_init.config.get('remote_path', 0))
        self.wait_for = int(self.sb_init.config.get('wait_for', 2))
        self.force = int(self.sb_init.config.get('force', 0))
        self.delete_on = int(self.sb_init.config.get('delete_on', 0))
        self.ignore_subs = int(self.sb_init.config.get('ignore_subs', 0))
        self.is_priority = int(self.sb_init.config.get('is_priority', 0))

        # get importmode, default to 'Move' for consistency with legacy
        self.import_mode = self.sb_init.config.get('importMode', 'Move')

        # Keep track of result state
        self.success = False

    def initialize(self, dir_name, input_name=None, failed=False, client_agent='manual'):
        """We need to call this explicitely because we need some variables.

        We can't pass these directly through the constructor.
        """
        self.dir_name = dir_name
        self.input_name = input_name
        self.failed = failed
        self.status = int(self.failed)
        if self.status > 0 and core.NOEXTRACTFAILED:
            self.extract = 0
        else:
            self.extract = int(self.sb_init.config.get('extract', 0))
        if client_agent == core.TORRENT_CLIENT_AGENT and core.USE_LINK == 'move-sym':
            self.process_method = 'symlink'

    def _create_url(self):
        if self.sb_init.apikey:
            return '{0}{1}:{2}{3}/api/{4}/'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root, self.sb_init.apikey)
        return '{0}{1}:{2}{3}/home/postprocess/processEpisode'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root)

    def _process_fork_prarams(self):
        # configure SB params to pass
        fork_params = self.sb_init.fork_params
        fork_params['quiet'] = 1
        fork_params['proc_type'] = 'manual'
        if self.input_name is not None:
            fork_params['nzbName'] = self.input_name

        for param in copy.copy(fork_params):
            if param == 'failed':
                if self.failed > 1:
                    self.failed = 1
                fork_params[param] = self.failed
                if 'proc_type' in fork_params:
                    del fork_params['proc_type']
                if 'type' in fork_params:
                    del fork_params['type']

            if param == 'return_data':
                fork_params[param] = 0
                if 'quiet' in fork_params:
                    del fork_params['quiet']

            if param == 'type':
                if 'type' in fork_params:  # only set if we haven't already deleted for 'failed' above.
                    fork_params[param] = 'manual'
                if 'proc_type' in fork_params:
                    del fork_params['proc_type']

            if param in ['dir_name', 'dir', 'proc_dir', 'process_directory', 'path']:
                fork_params[param] = self.dir_name
                if self.remote_path:
                    fork_params[param] = remote_dir(self.dir_name)
                # SickChill allows multiple path types. Only retunr 'path'
                if param == 'proc_dir' and 'path' in fork_params:
                    del fork_params['proc_dir']

            if param == 'process_method':
                if self.process_method:
                    fork_params[param] = self.process_method
                else:
                    del fork_params[param]

            if param in ['force', 'force_replace']:
                if self.force:
                    fork_params[param] = self.force
                else:
                    del fork_params[param]

            if param in ['delete_on', 'delete']:
                if self.delete_on:
                    fork_params[param] = self.delete_on
                else:
                    del fork_params[param]

            if param == 'ignore_subs':
                if self.ignore_subs:
                    fork_params[param] = self.ignore_subs
                else:
                    del fork_params[param]

            if param == 'is_priority':
                if self.is_priority:
                    fork_params[param] = self.is_priority
                else:
                    del fork_params[param]

            if param == 'force_next':
                fork_params[param] = 1

        # delete any unused params so we don't pass them to SB by mistake
        [fork_params.pop(k) for k, v in list(fork_params.items()) if v is None]

    def api_call(self):
        """Perform a base sickbeard api call."""
        self._process_fork_prarams()
        url = self._create_url()

        logger.debug('Opening URL: {0} with params: {1}'.format(url, self.sb_init.fork_params), self.sb_init.section)
        try:
            if not self.sb_init.apikey and self.sb_init.username and self.sb_init.password:
                # If not using the api, we need to login using user/pass first.
                login = '{0}{1}:{2}{3}/login'.format(self.sb_init.protocol, self.sb_init.host, self.sb_init.port, self.sb_init.web_root)
                login_params = {'username': self.sb_init.username, 'password': self.sb_init.password}
                r = self.session.get(login, verify=False, timeout=(30, 60))
                if r.status_code in [401, 403] and r.cookies.get('_xsrf'):
                    login_params['_xsrf'] = r.cookies.get('_xsrf')
                self.session.post(login, data=login_params, stream=True, verify=False, timeout=(30, 60))
            response = self.session.get(url, auth=(self.sb_init.username, self.sb_init.password), params=self.sb_init.fork_params, stream=True, verify=False, timeout=(30, 1800))
        except requests.ConnectionError:
            logger.error('Unable to open URL: {0}'.format(url), self.sb_init.section)
            return ProcessResult(
                message='{0}: Failed to post-process - Unable to connect to {0}'.format(self.sb_init.section),
                status_code=1,
            )

        if response.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
            logger.error('Server returned status {0}'.format(response.status_code), self.sb_init.section)
            return ProcessResult(
                message='{0}: Failed to post-process - Server returned status {1}'.format(self.sb_init.section, response.status_code),
                status_code=1,
            )

        return self.process_response(response)

    def process_response(self, response):
        """Iterate over the lines returned, and log.

        :param response: Streamed Requests response object.
        This method will need to be overwritten in the forks, for alternative response handling.
        """
        for line in response.iter_lines():
            if line:
                line = line.decode('utf-8')
                logger.postprocess('{0}'.format(line), self.sb_init.section)
                # if 'Moving file from' in line:
                #     input_name = os.path.split(line)[1]
                # if 'added to the queue' in line:
                #     queued = True
                # For the refactoring i'm only considering vanilla sickbeard, as for the base class.
                if 'Processing succeeded' in line or 'Successfully processed' in line:
                    self.success = True

        if self.success:
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(self.sb_init.section, self.input_name),
                status_code=0,
            )
        return ProcessResult(
            message='{0}: Failed to post-process - Returned log from {0} was not as expected.'.format(self.sb_init.section),
            status_code=1,  # We did not receive Success confirmation.
        )


================================================
FILE: core/auto_process/movies.py
================================================
# coding=utf-8

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import json
import os
import time

import requests

import core
from core import logger, transcoder
from core.auto_process.common import (
    ProcessResult,
    command_complete,
    completed_download_handling,
)
from core.plugins.downloaders.nzb.utils import report_nzb
from core.plugins.subtitles import import_subs, rename_subs
from core.scene_exceptions import process_all_exceptions
from core.utils import (
    convert_to_ascii,
    find_download,
    find_imdbid,
    list_media_files,
    remote_dir,
    remove_dir,
    server_responding,
)

requests.packages.urllib3.disable_warnings()


def process(section, dir_name, input_name=None, status=0, client_agent='manual', download_id='', input_category=None, failure_link=None):

    cfg = dict(core.CFG[section][input_category])

    host = cfg['host']
    port = cfg['port']
    apikey = cfg['apikey']
    if section == 'CouchPotato':
        method = cfg['method']
    else:
        method = None
    # added importMode for Radarr config
    if section == 'Radarr':
        import_mode = cfg.get('importMode', 'Move')
    else:
        import_mode = None
    delete_failed = int(cfg['delete_failed'])
    wait_for = int(cfg['wait_for'])
    ssl = int(cfg.get('ssl', 0))
    web_root = cfg.get('web_root', '')
    remote_path = int(cfg.get('remote_path', 0))
    protocol = 'https://' if ssl else 'http://'
    omdbapikey = cfg.get('omdbapikey', '')
    no_status_check = int(cfg.get('no_status_check', 0))
    status = int(status)
    if status > 0 and core.NOEXTRACTFAILED:
        extract = 0
    else:
        extract = int(cfg.get('extract', 0))

    imdbid, dir_name = find_imdbid(dir_name, input_name, omdbapikey)
    if section == 'CouchPotato':
        base_url = '{0}{1}:{2}{3}/api/{4}/'.format(protocol, host, port, web_root, apikey)
    if section == 'Radarr':
        base_url = '{0}{1}:{2}{3}/api/v3/command'.format(protocol, host, port, web_root)
        url2 = '{0}{1}:{2}{3}/api/v3/config/downloadClient'.format(protocol, host, port, web_root)
        headers = {'X-Api-Key': apikey, 'Content-Type': 'application/json'}
    if section == 'Watcher3':
        base_url = '{0}{1}:{2}{3}/postprocessing'.format(protocol, host, port, web_root)
    if not apikey:
        logger.info('No CouchPotato or Radarr apikey entered. Performing transcoder functions only')
        release = None
    elif server_responding(base_url):
        if section == 'CouchPotato':
            release = get_release(base_url, imdbid, download_id)
        else:
            release = None
    else:
        logger.error('Server did not respond. Exiting', section)
        return ProcessResult(
            message='{0}: Failed to post-process - {0} did not respond.'.format(section),
            status_code=1,
        )

    # pull info from release found if available
    release_id = None
    media_id = None
    downloader = None
    release_status_old = None
    if release:
        try:
            release_id = list(release.keys())[0]
            media_id = release[release_id]['media_id']
            download_id = release[release_id]['download_info']['id']
            downloader = release[release_id]['download_info']['downloader']
            release_status_old = release[release_id]['status']
        except Exception:
            pass

    if not os.path.isdir(dir_name) and os.path.isfile(dir_name):  # If the input directory is a file, assume single file download and split dir/name.
        dir_name = os.path.split(os.path.normpath(dir_name))[0]

    specific_path = os.path.join(dir_name, str(input_name))
    clean_name = os.path.splitext(specific_path)
    if clean_name[1] == '.nzb':
        specific_path = clean_name[0]
    if os.path.isdir(specific_path):
        dir_name = specific_path

    process_all_exceptions(input_name, dir_name)
    input_name, dir_name = convert_to_ascii(input_name, dir_name)

    if not list_media_files(dir_name, media=True, audio=False, meta=False, archives=False) and list_media_files(dir_name, media=False, audio=False, meta=False, archives=True) and extract:
        logger.debug('Checking for archives to extract in directory: {0}'.format(dir_name))
        core.extract_files(dir_name)
        input_name, dir_name = convert_to_ascii(input_name, dir_name)

    good_files = 0
    valid_files = 0
    num_files = 0
    # Check video files for corruption
    for video in list_media_files(dir_name, media=True, audio=False, meta=False, archives=False):
        num_files += 1
        if transcoder.is_video_good(video, status):
            good_files += 1
            if not core.REQUIRE_LAN or transcoder.is_video_good(video, status, require_lan=core.REQUIRE_LAN):
                valid_files += 1
                import_subs(video)
                rename_subs(dir_name)
    if num_files and valid_files == num_files:
        if status:
            logger.info('Status shown as failed from Downloader, but {0} valid video files found. Setting as success.'.format(good_files), section)
            status = 0
    elif num_files and valid_files < num_files:
        logger.info('Status shown as success from Downloader, but corrupt video files found. Setting as failed.', section)
        status = 1
        if 'NZBOP_VERSION' in os.environ and os.environ['NZBOP_VERSION'][0:5] >= '14.0':
            print('[NZB] MARK=BAD')
        if good_files == num_files:
            logger.debug('Video marked as failed due to missing required language: {0}'.format(core.REQUIRE_LAN), section)
        else:
            logger.debug('Video marked as failed due to missing playable audio or video', section)
        if good_files < num_files and failure_link: # only report corrupt files
            failure_link += '&corrupt=true'
    elif client_agent == 'manual':
        logger.warning('No media files found in directory {0} to manually process.'.format(dir_name), section)
        return ProcessResult(
            message='',
            status_code=0,  # Success (as far as this script is concerned)
        )
    else:
        logger.warning('No media files found in directory {0}. Processing this as a failed download'.format(dir_name), section)
        status = 1
        if 'NZBOP_VERSION' in os.environ and os.environ['NZBOP_VERSION'][0:5] >= '14.0':
            print('[NZB] MARK=BAD')

    if status == 0:
        if core.TRANSCODE == 1:
            result, new_dir_name = transcoder.transcode_directory(dir_name)
            if result == 0:
                logger.debug('Transcoding succeeded for files in {0}'.format(dir_name), section)
                dir_name = new_dir_name

                chmod_directory = int(str(cfg.get('chmodDirectory', '0')), 8)
                logger.debug('Config setting \'chmodDirectory\' currently set to {0}'.format(oct(chmod_directory)), section)
                if chmod_directory:
                    logger.info('Attempting to set the octal permission of \'{0}\' on directory \'{1}\''.format(oct(chmod_directory), dir_name), section)
                    core.rchmod(dir_name, chmod_directory)
            else:
                logger.error('Transcoding failed for files in {0}'.format(dir_name), section)
                return ProcessResult(
                    message='{0}: Failed to post-process - Transcoding failed'.format(section),
                    status_code=1,
                )
        for video in list_media_files(dir_name, media=True, audio=False, meta=False, archives=False):
            if not release and '.cp(tt' not in video and imdbid:
                video_name, video_ext = os.path.splitext(video)
                video2 = '{0}.cp({1}){2}'.format(video_name, imdbid, video_ext)
                if not (client_agent in [core.TORRENT_CLIENT_AGENT, 'manual'] and core.USE_LINK == 'move-sym'):
                    logger.debug('Renaming: {0} to: {1}'.format(video, video2))
                    os.rename(video, video2)

        if not apikey:  # If only using Transcoder functions, exit here.
            logger.info('No CouchPotato or Radarr or Watcher3 apikey entered. Processing completed.')
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(section, input_name),
                status_code=0,
            )

        params = {
            'media_folder': remote_dir(dir_name) if remote_path else dir_name,
        }

        if download_id and release_id:
            params['downloader'] = downloader or client_agent
            params['download_id'] = download_id

        if section == 'CouchPotato':
            if method == 'manage':
                command = 'manage.update'
                params.clear()
            else:
                command = 'renamer.scan'

            url = '{0}{1}'.format(base_url, command)
            logger.debug('Opening URL: {0} with PARAMS: {1}'.format(url, params), section)
            logger.postprocess('Starting {0} scan for {1}'.format(method, input_name), section)

        if section == 'Radarr':
            payload = {'name': 'DownloadedMoviesScan', 'path': params['media_folder'], 'downloadClientId': download_id, 'importMode': import_mode}
            if not download_id:
                payload.pop('downloadClientId')
            logger.debug('Opening URL: {0} with PARAMS: {1}'.format(base_url, payload), section)
            logger.postprocess('Starting DownloadedMoviesScan scan for {0}'.format(input_name), section)

        if section == 'Watcher3':
            if input_name and os.path.isfile(os.path.join(dir_name, input_name)):
                params['media_folder'] = os.path.join(params['media_folder'], input_name)
            payload = {'apikey': apikey, 'path': params['media_folder'], 'guid': download_id, 'mode': 'complete'}
            if not download_id:
                payload.pop('guid')
            logger.debug('Opening URL: {0} with PARAMS: {1}'.format(base_url, payload), section)
            logger.postprocess('Starting postprocessing scan for {0}'.format(input_name), section)

        try:
            if section == 'CouchPotato':
                r = requests.get(url, params=params, verify=False, timeout=(30, 1800))
            elif section == 'Watcher3':
                r = requests.post(base_url, data=payload, verify=False, timeout=(30, 1800))
            else:
                r = requests.post(base_url, data=json.dumps(payload), headers=headers, stream=True, verify=False, timeout=(30, 1800))
        except requests.ConnectionError:
            logger.error('Unable to open URL', section)
            return ProcessResult(
                message='{0}: Failed to post-process - Unable to connect to {0}'.format(section),
                status_code=1,
            )

        result = r.json()
        if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
            logger.error('Server returned status {0}'.format(r.status_code), section)
            return ProcessResult(
                message='{0}: Failed to post-process - Server returned status {1}'.format(section, r.status_code),
                status_code=1,
            )
        elif section == 'CouchPotato' and result['success']:
            logger.postprocess('SUCCESS: Finished {0} scan for folder {1}'.format(method, dir_name), section)
            if method == 'manage':
                return ProcessResult(
                    message='{0}: Successfully post-processed {1}'.format(section, input_name),
                    status_code=0,
                )
        elif section == 'Radarr':
            try:
                if isinstance(result, list):
                    scan_id = int(result[0]['id'])
                else:
                    scan_id = int(result['id'])
                logger.debug('Scan started with id: {0}'.format(scan_id), section)
            except Exception as e:
                logger.warning('No scan id was returned due to: {0}'.format(e), section)
                scan_id = None
        elif section == 'Watcher3' and result['status'] == 'finished':
            logger.postprocess('Watcher3 updated status to {0}'.format(result['tasks']['update_movie_status']))
            if result['tasks']['update_movie_status'] == 'Finished':
                return ProcessResult(
                    message='{0}: Successfully post-processed {1}'.format(section, input_name),
                    status_code=status,
                )
            else:
                return ProcessResult(
                    message='{0}: Failed to post-process - changed status to {1}'.format(section, result['tasks']['update_movie_status']),
                    status_code=1,
                )
        else:
            logger.error('FAILED: {0} scan was unable to finish for folder {1}. exiting!'.format(method, dir_name),
                         section)
            return ProcessResult(
                message='{0}: Failed to post-process - Server did not return success'.format(section),
                status_code=1,
            )
    else:
        core.FAILED = True
        logger.postprocess('FAILED DOWNLOAD DETECTED FOR {0}'.format(input_name), section)
        if failure_link:
            report_nzb(failure_link, client_agent)

        if section == 'Radarr':
            logger.postprocess('SUCCESS: Sending failed download to {0} for CDH processing'.format(section), section)
            return ProcessResult(
                message='{0}: Sending failed download back to {0}'.format(section),
                status_code=1,  # Return as failed to flag this in the downloader.
            )  # Return failed flag, but log the event as successful.
        elif section == 'Watcher3':
            logger.postprocess('Sending failed download to {0} for CDH processing'.format(section), section)
            path = remote_dir(dir_name) if remote_path else dir_name
            if input_name and os.path.isfile(os.path.join(dir_name, input_name)):
                path = os.path.join(path, input_name)
            payload = {'apikey': apikey, 'path': path, 'guid': download_id, 'mode': 'failed'}
            r = requests.post(base_url, data=payload, verify=False, timeout=(30, 1800))
            result = r.json()
            logger.postprocess('Watcher3 response: {0}'.format(result))
            if result['status'] == 'finished':
                return ProcessResult(
                    message='{0}: Sending failed download back to {0}'.format(section),
                    status_code=1,  # Return as failed to flag this in the downloader.
                )  # Return failed flag, but log the event as successful.

        if delete_failed and os.path.isdir(dir_name) and not os.path.dirname(dir_name) == dir_name:
            logger.postprocess('Deleting failed files and folder {0}'.format(dir_name), section)
            remove_dir(dir_name)

        if not release_id and not media_id:
            logger.error('Could not find a downloaded movie in the database matching {0}, exiting!'.format(input_name),
                         section)
            return ProcessResult(
                message='{0}: Failed to post-process - Failed download not found in {0}'.format(section),
                status_code=1,
            )

        if release_id:
            logger.postprocess('Setting failed release {0} to ignored ...'.format(input_name), section)

            url = '{url}release.ignore'.format(url=base_url)
            params = {'id': release_id}

            logger.debug('Opening URL: {0} with PARAMS: {1}'.format(url, params), section)

            try:
                r = requests.get(url, params=params, verify=False, timeout=(30, 120))
            except requests.ConnectionError:
                logger.error('Unable to open URL {0}'.format(url), section)
                return ProcessResult(
                    message='{0}: Failed to post-process - Unable to connect to {0}'.format(section),
                    status_code=1,
                )

            result = r.json()
            if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
                logger.error('Server returned status {0}'.format(r.status_code), section)
                return ProcessResult(
                    status_code=1,
                    message='{0}: Failed to post-process - Server returned status {1}'.format(section, r.status_code),
                )
            elif result['success']:
                logger.postprocess('SUCCESS: {0} has been set to ignored ...'.format(input_name), section)
            else:
                logger.warning('FAILED: Unable to set {0} to ignored!'.format(input_name), section)
                return ProcessResult(
                    message='{0}: Failed to post-process - Unable to set {1} to ignored'.format(section, input_name),
                    status_code=1,
                )

        logger.postprocess('Trying to snatch the next highest ranked release.', section)

        url = '{0}movie.searcher.try_next'.format(base_url)
        logger.debug('Opening URL: {0}'.format(url), section)

        try:
            r = requests.get(url, params={'media_id': media_id}, verify=False, timeout=(30, 600))
        except requests.ConnectionError:
            logger.error('Unable to open URL {0}'.format(url), section)
            return ProcessResult(
                message='{0}: Failed to post-process - Unable to connect to {0}'.format(section),
                status_code=1,
            )

        result = r.json()
        if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
            logger.error('Server returned status {0}'.format(r.status_code), section)
            return ProcessResult(
                message='{0}: Failed to post-process - Server returned status {1}'.format(section, r.status_code),
                status_code=1,
            )
        elif result['success']:
            logger.postprocess('SUCCESS: Snatched the next highest release ...', section)
            return ProcessResult(
                message='{0}: Successfully snatched next highest release'.format(section),
                status_code=0,
            )
        else:
            logger.postprocess('SUCCESS: Unable to find a new release to snatch now. CP will keep searching!', section)
            return ProcessResult(
                status_code=0,
                message='{0}: No new release found now. {0} will keep searching'.format(section),
            )

    # Added a release that was not in the wanted list so confirm rename successful by finding this movie media.list.
    if not release:
        download_id = None  # we don't want to filter new releases based on this.

    if no_status_check:
        return ProcessResult(
            status_code=0,
            message='{0}: Successfully processed but no change in status confirmed'.format(section),
        ) 

    # we will now check to see if CPS has finished renaming before returning to TorrentToMedia and unpausing.
    timeout = time.time() + 60 * wait_for
    while time.time() < timeout:  # only wait 2 (default) minutes, then return.
        logger.postprocess('Checking for status change, please stand by ...', section)
        if section == 'CouchPotato':
            release = get_release(base_url, imdbid, download_id, release_id)
            scan_id = None
        else:
            release = None
        if release:
            try:
                release_id = list(release.keys())[0]
                release_status_new = release[release_id]['status']
                if release_status_old is None:  # we didn't have a release before, but now we do.
                    title = release[release_id]['title']
                    logger.postprocess('SUCCESS: Movie {0} has now been added to CouchPotato with release status of [{1}]'.format(
                        title, str(release_status_new).upper()), section)
                    return ProcessResult(
                        message='{0}: Successfully post-processed {1}'.format(section, input_name),
                        status_code=0,
                    )

                if release_status_new != release_status_old:
                    logger.postprocess('SUCCESS: Release {0} has now been marked with a status of [{1}]'.format(
                        release_id, str(release_status_new).upper()), section)
                    return ProcessResult(
                        message='{0}: Successfully post-processed {1}'.format(section, input_name),
                        status_code=0,
                    )
            except Exception:
                pass
        elif scan_id:
            url = '{0}/{1}'.format(base_url, scan_id)
            command_status = command_complete(url, params, headers, section)
            if command_status:
                logger.debug('The Scan command return status: {0}'.format(command_status), section)
                if command_status in ['completed']:
                    logger.debug('The Scan command has completed successfully. Renaming was successful.', section)
                    return ProcessResult(
                        message='{0}: Successfully post-processed {1}'.format(section, input_name),
                        status_code=0,
                    )
                elif command_status in ['failed']:
                    logger.debug('The Scan command has failed. Renaming was not successful.', section)
                    # return ProcessResult(
                    #     message='{0}: Failed to post-process {1}'.format(section, input_name),
                    #     status_code=1,
                    # )

        if not os.path.isdir(dir_name):
            logger.postprocess('SUCCESS: Input Directory [{0}] has been processed and removed'.format(
                dir_name), section)
            return ProcessResult(
                status_code=0,
                message='{0}: Successfully post-processed {1}'.format(section, input_name),
            )

        elif not list_media_files(dir_name, media=True, audio=False, meta=False, archives=True):
            logger.postprocess('SUCCESS: Input Directory [{0}] has no remaining media files. This has been fully processed.'.format(
                dir_name), section)
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(section, input_name),
                status_code=0,
            )

        # pause and let CouchPotatoServer/Radarr catch its breath
        time.sleep(10 * wait_for)

    # The status hasn't changed. we have waited wait_for minutes which is more than enough. uTorrent can resume seeding now.
    if section == 'Radarr' and completed_download_handling(url2, headers, section=section):
        logger.debug('The Scan command did not return status completed, but complete Download Handling is enabled. Passing back to {0}.'.format(section), section)
        return ProcessResult(
            message='{0}: Complete DownLoad Handling is enabled. Passing back to {0}'.format(section),
            status_code=status,
        )
    logger.warning(
        '{0} does not appear to have changed status after {1} minutes, Please check your logs.'.format(input_name, wait_for),
        section,
    )
   
    return ProcessResult(
        status_code=1,
        message='{0}: Failed to post-process - No change in status'.format(section),
    )


def get_release(base_url, imdb_id=None, download_id=None, release_id=None):
    results = {}
    params = {}

    # determine cmd and params to send to CouchPotato to get our results
    section = 'movies'
    cmd = 'media.list'
    if release_id or imdb_id:
        section = 'media'
        cmd = 'media.get'
        params['id'] = release_id or imdb_id

    if not (release_id or imdb_id or download_id):
        logger.debug('No information available to filter CP results')
        return results

    url = '{0}{1}'.format(base_url, cmd)
    logger.debug('Opening URL: {0} with PARAMS: {1}'.format(url, params))

    try:
        r = requests.get(url, params=params, verify=False, timeout=(30, 60))
    except requests.ConnectionError:
        logger.error('Unable to open URL {0}'.format(url))
        return results

    try:
        result = r.json()
    except ValueError:
        # ValueError catches simplejson's JSONDecodeError and json's ValueError
        logger.error('CouchPotato returned the following non-json data')
        for line in r.iter_lines():
            logger.error('{0}'.format(line))
        return results

    if not result['success']:
        if 'error' in result:
            logger.error('{0}'.format(result['error']))
        else:
            logger.error('no media found for id {0}'.format(params['id']))
        return results

    # Gather release info and return it back, no need to narrow results
    if release_id:
        try:
            cur_id = result[section]['_id']
            results[cur_id] = result[section]
            return results
        except Exception:
            pass

    # Gather release info and proceed with trying to narrow results to one release choice

    movies = result[section]
    if not isinstance(movies, list):
        movies = [movies]
    for movie in movies:
        if movie['status'] not in ['active', 'done']:
            continue
        releases = movie['releases']
        if not releases:
            continue
        for release in releases:
            try:
                if release['status'] not in ['snatched', 'downloaded', 'done']:
                    continue
                if download_id:
                    if download_id.lower() != release['download_info']['id'].lower():
                        continue

                cur_id = release['_id']
                results[cur_id] = release
                results[cur_id]['title'] = movie['title']
            except Exception:
                continue

    # Narrow results by removing old releases by comparing their last_edit field
    if len(results) > 1:
        rem_id = set()
        for id1, x1 in results.items():
            for x2 in results.values():
                try:
                    if x2['last_edit'] > x1['last_edit']:
                        rem_id.add(id1)
                except Exception:
                    continue
        for id in rem_id:
            results.pop(id)

    # Search downloads on clients for a match to try and narrow our results down to 1
    if len(results) > 1:
        rem_id = set()
        for cur_id, x in results.items():
            try:
                if not find_download(str(x['download_info']['downloader']).lower(), x['download_info']['id']):
                    rem_id.add(cur_id)
            except Exception:
                continue
        for id in rem_id:
            results.pop(id)

    return results


================================================
FILE: core/auto_process/music.py
================================================
# coding=utf-8

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import json
import os
import time

import requests

import core
from core import logger
from core.auto_process.common import command_complete, ProcessResult
from core.scene_exceptions import process_all_exceptions
from core.utils import convert_to_ascii, list_media_files, remote_dir, remove_dir, server_responding

requests.packages.urllib3.disable_warnings()


def process(section, dir_name, input_name=None, status=0, client_agent='manual', input_category=None):
    status = int(status)

    cfg = dict(core.CFG[section][input_category])

    host = cfg['host']
    port = cfg['port']
    apikey = cfg['apikey']
    wait_for = int(cfg['wait_for'])
    ssl = int(cfg.get('ssl', 0))
    delete_failed = int(cfg['delete_failed'])
    web_root = cfg.get('web_root', '')
    remote_path = int(cfg.get('remote_path', 0))
    protocol = 'https://' if ssl else 'http://'
    status = int(status)
    if status > 0 and core.NOEXTRACTFAILED:
        extract = 0
    else:
        extract = int(cfg.get('extract', 0))

    if section == 'Lidarr':
        url = '{0}{1}:{2}{3}/api/v1'.format(protocol, host, port, web_root)
    else:
        url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root)
    if not server_responding(url):
        logger.error('Server did not respond. Exiting', section)
        return ProcessResult(
            message='{0}: Failed to post-process - {0} did not respond.'.format(section),
            status_code=1,
        )

    if not os.path.isdir(dir_name) and os.path.isfile(dir_name):  # If the input directory is a file, assume single file download and split dir/name.
        dir_name = os.path.split(os.path.normpath(dir_name))[0]

    specific_path = os.path.join(dir_name, str(input_name))
    clean_name = os.path.splitext(specific_path)
    if clean_name[1] == '.nzb':
        specific_path = clean_name[0]
    if os.path.isdir(specific_path):
        dir_name = specific_path

    process_all_exceptions(input_name, dir_name)
    input_name, dir_name = convert_to_ascii(input_name, dir_name)

    if not list_media_files(dir_name, media=False, audio=True, meta=False, archives=False) and list_media_files(dir_name, media=False, audio=False, meta=False, archives=True) and extract:
        logger.debug('Checking for archives to extract in directory: {0}'.format(dir_name))
        core.extract_files(dir_name)
        input_name, dir_name = convert_to_ascii(input_name, dir_name)

    # if listMediaFiles(dir_name, media=False, audio=True, meta=False, archives=False) and status:
    #     logger.info('Status shown as failed from Downloader, but valid video files found. Setting as successful.', section)
    #     status = 0

    if status == 0 and section == 'HeadPhones':

        params = {
            'apikey': apikey,
            'cmd': 'forceProcess',
            'dir': remote_dir(dir_name) if remote_path else dir_name,
        }

        res = force_process(params, url, apikey, input_name, dir_name, section, wait_for)
        if res.status_code in [0, 1]:
            return res

        params = {
            'apikey': apikey,
            'cmd': 'forceProcess',
            'dir': os.path.split(remote_dir(dir_name))[0] if remote_path else os.path.split(dir_name)[0],
        }

        res = force_process(params, url, apikey, input_name, dir_name, section, wait_for)
        if res.status_code in [0, 1]:
            return res

        # The status hasn't changed. uTorrent can resume seeding now.
        logger.warning('The music album does not appear to have changed status after {0} minutes. Please check your Logs'.format(wait_for), section)
        return ProcessResult(
            message='{0}: Failed to post-process - No change in wanted status'.format(section),
            status_code=1,
        )

    elif status == 0 and section == 'Lidarr':
        url = '{0}{1}:{2}{3}/api/v1/command'.format(protocol, host, port, web_root)
        headers = {'X-Api-Key': apikey}
        if remote_path:
            logger.debug('remote_path: {0}'.format(remote_dir(dir_name)), section)
            data = {'name': 'Rename', 'path': remote_dir(dir_name)}
        else:
            logger.debug('path: {0}'.format(dir_name), section)
            data = {'name': 'Rename', 'path': dir_name}
        data = json.dumps(data)
        try:
            logger.debug('Opening URL: {0} with data: {1}'.format(url, data), section)
            r = requests.post(url, data=data, headers=headers, stream=True, verify=False, timeout=(30, 1800))
        except requests.ConnectionError:
            logger.error('Unable to open URL: {0}'.format(url), section)
            return ProcessResult(
                message='{0}: Failed to post-process - Unable to connect to {0}'.format(section),
                status_code=1,
            )

        try:
            res = r.json()
            scan_id = int(res['id'])
            logger.debug('Scan started with id: {0}'.format(scan_id), section)
        except Exception as e:
            logger.warning('No scan id was returned due to: {0}'.format(e), section)
            return ProcessResult(
                message='{0}: Failed to post-process - Unable to start scan'.format(section),
                status_code=1,
            )

        n = 0
        params = {}
        url = '{0}/{1}'.format(url, scan_id)
        while n < 6:  # set up wait_for minutes to see if command completes..
            time.sleep(10 * wait_for)
            command_status = command_complete(url, params, headers, section)
            if command_status and command_status in ['completed', 'failed']:
                break
            n += 1
        if command_status:
            logger.debug('The Scan command return status: {0}'.format(command_status), section)
        if not os.path.exists(dir_name):
            logger.debug('The directory {0} has been removed. Renaming was successful.'.format(dir_name), section)
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(section, input_name),
                status_code=0,
            )
        elif command_status and command_status in ['completed']:
            logger.debug('The Scan command has completed successfully. Renaming was successful.', section)
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(section, input_name),
                status_code=0,
            )
        elif command_status and command_status in ['failed']:
            logger.debug('The Scan command has failed. Renaming was not successful.', section)
            # return ProcessResult(
            #     message='{0}: Failed to post-process {1}'.format(section, input_name),
            #     status_code=1,
            # )
        else:
            logger.debug('The Scan command did not return status completed. Passing back to {0} to attempt complete download handling.'.format(section), section)
            return ProcessResult(
                message='{0}: Passing back to {0} to attempt Complete Download Handling'.format(section),
                status_code=status,
            )

    else:
        if section == 'Lidarr':
            logger.postprocess('FAILED: The download failed. Sending failed download to {0} for CDH processing'.format(section), section)
            return ProcessResult(
                message='{0}: Download Failed. Sending back to {0}'.format(section),
                status_code=1,  # Return as failed to flag this in the downloader.
            )
        else:
            logger.warning('FAILED DOWNLOAD DETECTED', section)
            if delete_failed and os.path.isdir(dir_name) and not os.path.dirname(dir_name) == dir_name:
                logger.postprocess('Deleting failed files and folder {0}'.format(dir_name), section)
                remove_dir(dir_name)
            return ProcessResult(
                message='{0}: Failed to post-process. {0} does not support failed downloads'.format(section),
                status_code=1,  # Return as failed to flag this in the downloader.
            )


def get_status(url, apikey, dir_name):
    logger.debug('Attempting to get current status for release:{0}'.format(os.path.basename(dir_name)))

    params = {
        'apikey': apikey,
        'cmd': 'getHistory',
    }

    logger.debug('Opening URL: {0} with PARAMS: {1}'.format(url, params))

    try:
        r = requests.get(url, params=params, verify=False, timeout=(30, 120))
    except requests.RequestException:
        logger.error('Unable to open URL')
        return None

    try:
        result = r.json()
    except ValueError:
        # ValueError catches simplejson's JSONDecodeError and json's ValueError
        return None

    for album in result:
        if os.path.basename(dir_name) == album['FolderName']:
            return album['Status'].lower()


def force_process(params, url, apikey, input_name, dir_name, section, wait_for):
    release_status = get_status(url, apikey, dir_name)
    if not release_status:
        logger.error('Could not find a status for {0}, is it in the wanted list ?'.format(input_name), section)

    logger.debug('Opening URL: {0} with PARAMS: {1}'.format(url, params), section)

    try:
        r = requests.get(url, params=params, verify=False, timeout=(30, 300))
    except requests.ConnectionError:
        logger.error('Unable to open URL {0}'.format(url), section)
        return ProcessResult(
            message='{0}: Failed to post-process - Unable to connect to {0}'.format(section),
            status_code=1,
        )

    logger.debug('Result: {0}'.format(r.text), section)

    if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
        logger.error('Server returned status {0}'.format(r.status_code), section)
        return ProcessResult(
            message='{0}: Failed to post-process - Server returned status {1}'.format(section, r.status_code),
            status_code=1,
        )
    elif r.text == 'OK':
        logger.postprocess('SUCCESS: Post-Processing started for {0} in folder {1} ...'.format(input_name, dir_name), section)
    else:
        logger.error('FAILED: Post-Processing has NOT started for {0} in folder {1}. exiting!'.format(input_name, dir_name), section)
        return ProcessResult(
            message='{0}: Failed to post-process - Returned log from {0} was not as expected.'.format(section),
            status_code=1,
        )

    # we will now wait for this album to be processed before returning to TorrentToMedia and unpausing.
    timeout = time.time() + 60 * wait_for
    while time.time() < timeout:
        current_status = get_status(url, apikey, dir_name)
        if current_status is not None and current_status != release_status:  # Something has changed. CPS must have processed this movie.
            logger.postprocess('SUCCESS: This release is now marked as status [{0}]'.format(current_status), section)
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(section, input_name),
                status_code=0,
            )
        if not os.path.isdir(dir_name):
            logger.postprocess('SUCCESS: The input directory {0} has been removed Processing must have finished.'.format(dir_name), section)
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(section, input_name),
                status_code=0,
            )
        time.sleep(10 * wait_for)
    # The status hasn't changed.
    return ProcessResult(
        message='no change',
        status_code=2,
    )


================================================
FILE: core/auto_process/tv.py
================================================
# coding=utf-8

from __future__ import (
    absolute_import,
    division,
    print_function,
    unicode_literals,
)

import copy
import errno
import json
import os
import time

import requests
from oauthlib.oauth2 import LegacyApplicationClient
from requests_oauthlib import OAuth2Session

import core
from core import logger, transcoder
from core.auto_process.common import (
    ProcessResult,
    command_complete,
    completed_download_handling,
)
from core.auto_process.managers.sickbeard import InitSickBeard
from core.plugins.downloaders.nzb.utils import report_nzb
from core.plugins.subtitles import import_subs, rename_subs
from core.scene_exceptions import process_all_exceptions
from core.utils import (
    convert_to_ascii,
    flatten,
    list_media_files,
    remote_dir,
    remove_dir,
    server_responding,
)


requests.packages.urllib3.disable_warnings()


def process(section, dir_name, input_name=None, failed=False, client_agent='manual', download_id=None, input_category=None, failure_link=None):
    cfg = dict(core.CFG[section][input_category])

    host = cfg['host']
    port = cfg['port']
    ssl = int(cfg.get('ssl', 0))
    web_root = cfg.get('web_root', '')
    protocol = 'https://' if ssl else 'http://'
    username = cfg.get('username', '')
    password = cfg.get('password', '')
    apikey = cfg.get('apikey', '')
    api_version = int(cfg.get('api_version', 2))
    sso_username = cfg.get('sso_username', '')
    sso_password = cfg.get('sso_password', '')

    # Refactor into an OO structure.
    # For now let's do botch the OO and the serialized code, until everything has been migrated.
    init_sickbeard = InitSickBeard(cfg, section, input_category)

    if server_responding('{0}{1}:{2}{3}'.format(protocol, host, port, web_root)):
        # auto-detect correct fork
        # During reactor we also return fork, fork_params. But these are also stored in the object.
        # Should be changed after refactor.
        fork, fork_params = init_sickbeard.auto_fork()
    elif not username and not apikey and not sso_username:
        logger.info('No SickBeard / SiCKRAGE username or Sonarr apikey entered. Performing transcoder functions only')
        fork, fork_params = 'None', {}
    else:
        logger.error('Server did not respond. Exiting', section)
        return ProcessResult(
            status_code=1,
            message='{0}: Failed to post-process - {0} did not respond.'.format(section),
        )

    delete_failed = int(cfg.get('delete_failed', 0))
    nzb_extraction_by = cfg.get('nzbExtractionBy', 'Downloader')
    process_method = cfg.get('process_method')
    if client_agent == core.TORRENT_CLIENT_AGENT and core.USE_LINK == 'move-sym':
        process_method = 'symlink'
    remote_path = int(cfg.get('remote_path', 0))
    wait_for = int(cfg.get('wait_for', 2))
    force = int(cfg.get('force', 0))
    delete_on = int(cfg.get('delete_on', 0))
    ignore_subs = int(cfg.get('ignore_subs', 0))
    status = int(failed)
    if status > 0 and core.NOEXTRACTFAILED:
        extract = 0
    else:
        extract = int(cfg.get('extract', 0))
    # get importmode, default to 'Move' for consistency with legacy
    import_mode = cfg.get('importMode', 'Move')

    if not os.path.isdir(dir_name) and os.path.isfile(dir_name):  # If the input directory is a file, assume single file download and split dir/name.
        dir_name = os.path.split(os.path.normpath(dir_name))[0]

    specific_path = os.path.join(dir_name, str(input_name))
    clean_name = os.path.splitext(specific_path)
    if clean_name[1] == '.nzb':
        specific_path = clean_name[0]
    if os.path.isdir(specific_path):
        dir_name = specific_path

    # Attempt to create the directory if it doesn't exist and ignore any
    # error stating that it already exists. This fixes a bug where SickRage
    # won't process the directory because it doesn't exist.
    if dir_name:
        try:
            os.makedirs(dir_name)  # Attempt to create the directory
        except OSError as e:
            # Re-raise the error if it wasn't about the directory not existing
            if e.errno != errno.EEXIST:
                raise

    if 'process_method' not in fork_params or (client_agent in ['nzbget', 'sabnzbd'] and nzb_extraction_by != 'Destination'):
        if input_name:
            process_all_exceptions(input_name, dir_name)
            input_name, dir_name = convert_to_ascii(input_name, dir_name)

        # Now check if tv files exist in destination.
        if not list_media_files(dir_name, media=True, audio=False, meta=False, archives=False):
            if list_media_files(dir_name, media=False, audio=False, meta=False, archives=True) and extract:
                logger.debug('Checking for archives to extract in directory: {0}'.format(dir_name))
                core.extract_files(dir_name)
                input_name, dir_name = convert_to_ascii(input_name, dir_name)

        if list_media_files(dir_name, media=True, audio=False, meta=False, archives=False):  # Check that a video exists. if not, assume failed.
            flatten(dir_name)

    # Check video files for corruption
    good_files = 0
    valid_files = 0
    num_files = 0
    for video in list_media_files(dir_name, media=True, audio=False, meta=False, archives=False):
        num_files += 1
        if transcoder.is_video_good(video, status):
            good_files += 1
            if not core.REQUIRE_LAN or transcoder.is_video_good(video, status, require_lan=core.REQUIRE_LAN):
                valid_files += 1
                import_subs(video)
                rename_subs(dir_name)
    if num_files > 0:
        if valid_files == num_files and not status == 0:
            logger.info('Found Valid Videos. Setting status Success')
            status = 0
            failed = 0
        if valid_files < num_files and status == 0:
            logger.info('Found corrupt videos. Setting status Failed')
            status = 1
            failed = 1
            if 'NZBOP_VERSION' in os.environ and os.environ['NZBOP_VERSION'][0:5] >= '14.0':
                print('[NZB] MARK=BAD')
            if good_files == num_files:
                logger.debug('Video marked as failed due to missing required language: {0}'.format(core.REQUIRE_LAN), section)
            else:
                logger.debug('Video marked as failed due to missing playable audio or video', section)
            if good_files < num_files and failure_link: # only report corrupt files
                failure_link += '&corrupt=true'
    elif client_agent == 'manual':
        logger.warning('No media files found in directory {0} to manually process.'.format(dir_name), section)
        return ProcessResult(
            message='',
            status_code=0,  # Success (as far as this script is concerned)
        )
    elif nzb_extraction_by == 'Destination':
        logger.info('Check for media files ignored because nzbExtractionBy is set to Destination.')
        if int(failed) == 0:
            logger.info('Setting Status Success.')
            status = 0
            failed = 0
        else:
            logger.info('Downloader reported an error during download or verification. Processing this as a failed download.')
            status = 1
            failed = 1
    else:
        logger.warning('No media files found in directory {0}. Processing this as a failed download'.format(dir_name), section)
        status = 1
        failed = 1
        if 'NZBOP_VERSION' in os.environ and os.environ['NZBOP_VERSION'][0:5] >= '14.0':
            print('[NZB] MARK=BAD')

    if status == 0 and core.TRANSCODE == 1:  # only transcode successful downloads
        result, new_dir_name = transcoder.transcode_directory(dir_name)
        if result == 0:
            logger.debug('SUCCESS: Transcoding succeeded for files in {0}'.format(dir_name), section)
            dir_name = new_dir_name

            chmod_directory = int(str(cfg.get('chmodDirectory', '0')), 8)
            logger.debug('Config setting \'chmodDirectory\' currently set to {0}'.format(oct(chmod_directory)), section)
            if chmod_directory:
                logger.info('Attempting to set the octal permission of \'{0}\' on directory \'{1}\''.format(oct(chmod_directory), dir_name), section)
                core.rchmod(dir_name, chmod_directory)
        else:
            logger.error('FAILED: Transcoding failed for files in {0}'.format(dir_name), section)
            return ProcessResult(
                message='{0}: Failed to post-process - Transcoding failed'.format(section),
                status_code=1,
            )

    # Part of the refactor
    if init_sickbeard.fork_obj:
        init_sickbeard.fork_obj.initialize(dir_name, input_name, failed, client_agent='manual')

    # configure SB params to pass
    # We don't want to remove params, for the Forks that have been refactored.
    # As we don't want to duplicate this part of the code.
    if not init_sickbeard.fork_obj:
        fork_params['quiet'] = 1
        fork_params['proc_type'] = 'manual'
        if input_name is not None:
            fork_params['nzbName'] = input_name

        for param in copy.copy(fork_params):
            if param == 'failed':
                if failed > 1:
                    failed = 1
                fork_params[param] = failed
                if 'proc_type' in fork_params:
                    del fork_params['proc_type']
                if 'type' in fork_params:
                    del fork_params['type']

            if param == 'return_data':
                fork_params[param] = 0
                if 'quiet' in fork_params:
                    del fork_params['quiet']

            if param == 'type':
                if 'type' in fork_params:  # only set if we haven't already deleted for 'failed' above.
                    fork_params[param] = 'manual'
                if 'proc_type' in fork_params:
                    del fork_params['proc_type']

            if param in ['dir_name', 'dir', 'proc_dir', 'process_directory', 'path']:
                fork_params[param] = dir_name
                if remote_path:
                    fork_params[param] = remote_dir(dir_name)

            if param == 'process_method':
                if process_method:
                    fork_params[param] = process_method
                else:
                    del fork_params[param]

            if param in ['force', 'force_replace']:
                if force:
                    fork_params[param] = force
                else:
                    del fork_params[param]

            if param in ['delete_on', 'delete']:
                if delete_on:
                    fork_params[param] = delete_on
                else:
                    del fork_params[param]

            if param == 'ignore_subs':
                if ignore_subs:
                    fork_params[param] = ignore_subs
                else:
                    del fork_params[param]

            if param == 'force_next':
                fork_params[param] = 1

        # delete any unused params so we don't pass them to SB by mistake
        [fork_params.pop(k) for k, v in list(fork_params.items()) if v is None]

    if status == 0:
        if section == 'NzbDrone' and not apikey:
            logger.info('No Sonarr apikey entered. Processing completed.')
            return ProcessResult(
                message='{0}: Successfully post-processed {1}'.format(section, input_name),
                status_code=0,
            )
        logger.postprocess('SUCCESS: The download succeeded, sending a post-process request', section)
    else:
        core.FAILED = True
        if failure_link:
            report_nzb(failure_link, client_agent)
        if 'failed' in fork_params:
            logger.postprocess('FAILED: The download failed. Sending \'failed\' process request to {0} branch'.format(fork), section)
        elif section == 'NzbDrone':
            logger.postprocess('FAILED: The download failed. Sending failed download to {0} for CDH processing'.format(fork), section)
            return ProcessResult(
                message='{0}: D
Download .txt
gitextract_1h9iq7tv/

├── .bumpversion.cfg
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── README.md
├── .gitignore
├── TorrentToMedia.py
├── _config.yml
├── autoProcessMedia.cfg.spec
├── azure-pipelines.yml
├── cleanup.py
├── core/
│   ├── __init__.py
│   ├── auto_process/
│   │   ├── __init__.py
│   │   ├── books.py
│   │   ├── comics.py
│   │   ├── common.py
│   │   ├── games.py
│   │   ├── managers/
│   │   │   ├── __init__.py
│   │   │   ├── pymedusa.py
│   │   │   └── sickbeard.py
│   │   ├── movies.py
│   │   ├── music.py
│   │   └── tv.py
│   ├── configuration.py
│   ├── databases.py
│   ├── extractor/
│   │   ├── __init__.py
│   │   └── bin/
│   │       ├── AMD64/
│   │       │   └── license.txt
│   │       ├── invisible.vbs
│   │       └── x86/
│   │           └── license.txt
│   ├── github_api.py
│   ├── logger.py
│   ├── main_db.py
│   ├── permissions.py
│   ├── plugins/
│   │   ├── __init__.py
│   │   ├── downloaders/
│   │   │   ├── __init__.py
│   │   │   ├── configuration.py
│   │   │   ├── nzb/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── configuration.py
│   │   │   │   └── utils.py
│   │   │   ├── torrent/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── configuration.py
│   │   │   │   ├── deluge.py
│   │   │   │   ├── qbittorrent.py
│   │   │   │   ├── synology.py
│   │   │   │   ├── transmission.py
│   │   │   │   ├── utils.py
│   │   │   │   └── utorrent.py
│   │   │   └── utils.py
│   │   ├── plex.py
│   │   └── subtitles.py
│   ├── processor/
│   │   ├── __init__.py
│   │   ├── manual.py
│   │   ├── nzb.py
│   │   ├── nzbget.py
│   │   └── sab.py
│   ├── scene_exceptions.py
│   ├── transcoder.py
│   ├── user_scripts.py
│   ├── utils/
│   │   ├── __init__.py
│   │   ├── common.py
│   │   ├── download_info.py
│   │   ├── encoding.py
│   │   ├── files.py
│   │   ├── identification.py
│   │   ├── links.py
│   │   ├── naming.py
│   │   ├── network.py
│   │   ├── parsers.py
│   │   ├── paths.py
│   │   ├── processes.py
│   │   └── shutil_custom.py
│   └── version_check.py
├── eol.py
├── getffmpeg.sh
├── libs/
│   ├── __init__.py
│   ├── __main__.py
│   ├── autoload.py
│   ├── common/
│   │   ├── __init__.py
│   │   ├── _version.py
│   │   ├── _yaml/
│   │   │   └── __init__.py
│   │   ├── appdirs.py
│   │   ├── babelfish/
│   │   │   ├── __init__.py
│   │   │   ├── converters/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── alpha2.py
│   │   │   │   ├── alpha3b.py
│   │   │   │   ├── alpha3t.py
│   │   │   │   ├── countryname.py
│   │   │   │   ├── name.py
│   │   │   │   ├── opensubtitles.py
│   │   │   │   ├── scope.py
│   │   │   │   └── type.py
│   │   │   ├── country.py
│   │   │   ├── data/
│   │   │   │   ├── iso-3166-1.txt
│   │   │   │   ├── iso-639-3.tab
│   │   │   │   ├── iso15924-utf8-20131012.txt
│   │   │   │   └── opensubtitles_languages.txt
│   │   │   ├── exceptions.py
│   │   │   ├── language.py
│   │   │   └── script.py
│   │   ├── beets/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── art.py
│   │   │   ├── autotag/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── hooks.py
│   │   │   │   ├── match.py
│   │   │   │   └── mb.py
│   │   │   ├── config_default.yaml
│   │   │   ├── dbcore/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── db.py
│   │   │   │   ├── query.py
│   │   │   │   ├── queryparse.py
│   │   │   │   └── types.py
│   │   │   ├── importer.py
│   │   │   ├── library.py
│   │   │   ├── logging.py
│   │   │   ├── mediafile.py
│   │   │   ├── plugins.py
│   │   │   ├── random.py
│   │   │   ├── ui/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── commands.py
│   │   │   │   └── completion_base.sh
│   │   │   ├── util/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── artresizer.py
│   │   │   │   ├── bluelet.py
│   │   │   │   ├── confit.py
│   │   │   │   ├── enumeration.py
│   │   │   │   ├── functemplate.py
│   │   │   │   ├── hidden.py
│   │   │   │   └── pipeline.py
│   │   │   └── vfs.py
│   │   ├── beetsplug/
│   │   │   ├── __init__.py
│   │   │   ├── absubmit.py
│   │   │   ├── acousticbrainz.py
│   │   │   ├── albumtypes.py
│   │   │   ├── aura.py
│   │   │   ├── badfiles.py
│   │   │   ├── bareasc.py
│   │   │   ├── beatport.py
│   │   │   ├── bench.py
│   │   │   ├── bpd/
│   │   │   │   ├── __init__.py
│   │   │   │   └── gstplayer.py
│   │   │   ├── bpm.py
│   │   │   ├── bpsync.py
│   │   │   ├── bucket.py
│   │   │   ├── chroma.py
│   │   │   ├── convert.py
│   │   │   ├── deezer.py
│   │   │   ├── discogs.py
│   │   │   ├── duplicates.py
│   │   │   ├── edit.py
│   │   │   ├── embedart.py
│   │   │   ├── embyupdate.py
│   │   │   ├── export.py
│   │   │   ├── fetchart.py
│   │   │   ├── filefilter.py
│   │   │   ├── fish.py
│   │   │   ├── freedesktop.py
│   │   │   ├── fromfilename.py
│   │   │   ├── ftintitle.py
│   │   │   ├── fuzzy.py
│   │   │   ├── gmusic.py
│   │   │   ├── hook.py
│   │   │   ├── ihate.py
│   │   │   ├── importadded.py
│   │   │   ├── importfeeds.py
│   │   │   ├── info.py
│   │   │   ├── inline.py
│   │   │   ├── ipfs.py
│   │   │   ├── keyfinder.py
│   │   │   ├── kodiupdate.py
│   │   │   ├── lastgenre/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── genres-tree.yaml
│   │   │   │   └── genres.txt
│   │   │   ├── lastimport.py
│   │   │   ├── loadext.py
│   │   │   ├── lyrics.py
│   │   │   ├── mbcollection.py
│   │   │   ├── mbsubmit.py
│   │   │   ├── mbsync.py
│   │   │   ├── metasync/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── amarok.py
│   │   │   │   └── itunes.py
│   │   │   ├── missing.py
│   │   │   ├── mpdstats.py
│   │   │   ├── mpdupdate.py
│   │   │   ├── parentwork.py
│   │   │   ├── permissions.py
│   │   │   ├── play.py
│   │   │   ├── playlist.py
│   │   │   ├── plexupdate.py
│   │   │   ├── random.py
│   │   │   ├── replaygain.py
│   │   │   ├── rewrite.py
│   │   │   ├── scrub.py
│   │   │   ├── smartplaylist.py
│   │   │   ├── sonosupdate.py
│   │   │   ├── spotify.py
│   │   │   ├── subsonicplaylist.py
│   │   │   ├── subsonicupdate.py
│   │   │   ├── the.py
│   │   │   ├── thumbnails.py
│   │   │   ├── types.py
│   │   │   ├── unimported.py
│   │   │   ├── web/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── static/
│   │   │   │   │   ├── backbone.js
│   │   │   │   │   ├── beets.css
│   │   │   │   │   ├── beets.js
│   │   │   │   │   ├── jquery.js
│   │   │   │   │   └── underscore.js
│   │   │   │   └── templates/
│   │   │   │       └── index.html
│   │   │   └── zero.py
│   │   ├── bs4/
│   │   │   ├── __init__.py
│   │   │   ├── builder/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _html5lib.py
│   │   │   │   ├── _htmlparser.py
│   │   │   │   └── _lxml.py
│   │   │   ├── dammit.py
│   │   │   ├── diagnose.py
│   │   │   ├── element.py
│   │   │   ├── formatter.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── test_builder.py
│   │   │       ├── test_builder_registry.py
│   │   │       ├── test_dammit.py
│   │   │       ├── test_docs.py
│   │   │       ├── test_element.py
│   │   │       ├── test_formatter.py
│   │   │       ├── test_html5lib.py
│   │   │       ├── test_htmlparser.py
│   │   │       ├── test_lxml.py
│   │   │       ├── test_navigablestring.py
│   │   │       ├── test_pageelement.py
│   │   │       ├── test_soup.py
│   │   │       ├── test_tag.py
│   │   │       └── test_tree.py
│   │   ├── certifi/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── cacert.pem
│   │   │   └── core.py
│   │   ├── chardet/
│   │   │   ├── __init__.py
│   │   │   ├── big5freq.py
│   │   │   ├── big5prober.py
│   │   │   ├── chardistribution.py
│   │   │   ├── charsetgroupprober.py
│   │   │   ├── charsetprober.py
│   │   │   ├── cli/
│   │   │   │   ├── __init__.py
│   │   │   │   └── chardetect.py
│   │   │   ├── codingstatemachine.py
│   │   │   ├── compat.py
│   │   │   ├── cp949prober.py
│   │   │   ├── enums.py
│   │   │   ├── escprober.py
│   │   │   ├── escsm.py
│   │   │   ├── eucjpprober.py
│   │   │   ├── euckrfreq.py
│   │   │   ├── euckrprober.py
│   │   │   ├── euctwfreq.py
│   │   │   ├── euctwprober.py
│   │   │   ├── gb2312freq.py
│   │   │   ├── gb2312prober.py
│   │   │   ├── hebrewprober.py
│   │   │   ├── jisfreq.py
│   │   │   ├── jpcntx.py
│   │   │   ├── langbulgarianmodel.py
│   │   │   ├── langgreekmodel.py
│   │   │   ├── langhebrewmodel.py
│   │   │   ├── langhungarianmodel.py
│   │   │   ├── langrussianmodel.py
│   │   │   ├── langthaimodel.py
│   │   │   ├── langturkishmodel.py
│   │   │   ├── latin1prober.py
│   │   │   ├── mbcharsetprober.py
│   │   │   ├── mbcsgroupprober.py
│   │   │   ├── mbcssm.py
│   │   │   ├── metadata/
│   │   │   │   ├── __init__.py
│   │   │   │   └── languages.py
│   │   │   ├── sbcharsetprober.py
│   │   │   ├── sbcsgroupprober.py
│   │   │   ├── sjisprober.py
│   │   │   ├── universaldetector.py
│   │   │   ├── utf8prober.py
│   │   │   └── version.py
│   │   ├── click/
│   │   │   ├── __init__.py
│   │   │   ├── _compat.py
│   │   │   ├── _termui_impl.py
│   │   │   ├── _textwrap.py
│   │   │   ├── _winconsole.py
│   │   │   ├── core.py
│   │   │   ├── decorators.py
│   │   │   ├── exceptions.py
│   │   │   ├── formatting.py
│   │   │   ├── globals.py
│   │   │   ├── parser.py
│   │   │   ├── py.typed
│   │   │   ├── shell_completion.py
│   │   │   ├── termui.py
│   │   │   ├── testing.py
│   │   │   ├── types.py
│   │   │   └── utils.py
│   │   ├── colorama/
│   │   │   ├── __init__.py
│   │   │   ├── ansi.py
│   │   │   ├── ansitowin32.py
│   │   │   ├── initialise.py
│   │   │   ├── tests/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── ansi_test.py
│   │   │   │   ├── ansitowin32_test.py
│   │   │   │   ├── initialise_test.py
│   │   │   │   ├── isatty_test.py
│   │   │   │   ├── utils.py
│   │   │   │   └── winterm_test.py
│   │   │   ├── win32.py
│   │   │   └── winterm.py
│   │   ├── configobj.py
│   │   ├── confuse/
│   │   │   ├── __init__.py
│   │   │   ├── core.py
│   │   │   ├── exceptions.py
│   │   │   ├── sources.py
│   │   │   ├── templates.py
│   │   │   ├── util.py
│   │   │   └── yaml_util.py
│   │   ├── dateutil/
│   │   │   ├── __init__.py
│   │   │   ├── _common.py
│   │   │   ├── _version.py
│   │   │   ├── easter.py
│   │   │   ├── parser/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _parser.py
│   │   │   │   └── isoparser.py
│   │   │   ├── relativedelta.py
│   │   │   ├── rrule.py
│   │   │   ├── tz/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _common.py
│   │   │   │   ├── _factories.py
│   │   │   │   ├── tz.py
│   │   │   │   └── win.py
│   │   │   ├── tzwin.py
│   │   │   ├── utils.py
│   │   │   └── zoneinfo/
│   │   │       ├── __init__.py
│   │   │       └── rebuild.py
│   │   ├── decorator.py
│   │   ├── dogpile/
│   │   │   ├── __init__.py
│   │   │   ├── cache/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── api.py
│   │   │   │   ├── backends/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── file.py
│   │   │   │   │   ├── memcached.py
│   │   │   │   │   ├── memory.py
│   │   │   │   │   ├── null.py
│   │   │   │   │   └── redis.py
│   │   │   │   ├── exception.py
│   │   │   │   ├── plugins/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   └── mako_cache.py
│   │   │   │   ├── proxy.py
│   │   │   │   ├── region.py
│   │   │   │   └── util.py
│   │   │   ├── core.py
│   │   │   ├── lock.py
│   │   │   └── util/
│   │   │       ├── __init__.py
│   │   │       ├── compat.py
│   │   │       ├── langhelpers.py
│   │   │       ├── nameregistry.py
│   │   │       └── readwrite_lock.py
│   │   ├── easy_install.py
│   │   ├── enzyme/
│   │   │   ├── __init__.py
│   │   │   ├── compat.py
│   │   │   ├── exceptions.py
│   │   │   ├── mkv.py
│   │   │   ├── parsers/
│   │   │   │   ├── __init__.py
│   │   │   │   └── ebml/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── core.py
│   │   │   │       ├── readers.py
│   │   │   │       └── specs/
│   │   │   │           └── matroska.xml
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── parsers/
│   │   │       │   └── ebml/
│   │   │       │       └── test1.mkv.yml
│   │   │       ├── test_mkv.py
│   │   │       └── test_parsers.py
│   │   ├── filetype/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── filetype.py
│   │   │   ├── helpers.py
│   │   │   ├── match.py
│   │   │   ├── types/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── application.py
│   │   │   │   ├── archive.py
│   │   │   │   ├── audio.py
│   │   │   │   ├── base.py
│   │   │   │   ├── document.py
│   │   │   │   ├── font.py
│   │   │   │   ├── image.py
│   │   │   │   ├── isobmff.py
│   │   │   │   └── video.py
│   │   │   └── utils.py
│   │   ├── guessit/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── __version__.py
│   │   │   ├── api.py
│   │   │   ├── backports.py
│   │   │   ├── config/
│   │   │   │   └── options.json
│   │   │   ├── jsonutils.py
│   │   │   ├── monkeypatch.py
│   │   │   ├── options.py
│   │   │   ├── reutils.py
│   │   │   ├── rules/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── common/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── comparators.py
│   │   │   │   │   ├── date.py
│   │   │   │   │   ├── expected.py
│   │   │   │   │   ├── formatters.py
│   │   │   │   │   ├── numeral.py
│   │   │   │   │   ├── pattern.py
│   │   │   │   │   ├── quantity.py
│   │   │   │   │   ├── validators.py
│   │   │   │   │   └── words.py
│   │   │   │   ├── markers/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── groups.py
│   │   │   │   │   └── path.py
│   │   │   │   ├── match_processors.py
│   │   │   │   ├── processors.py
│   │   │   │   └── properties/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── audio_codec.py
│   │   │   │       ├── bit_rate.py
│   │   │   │       ├── bonus.py
│   │   │   │       ├── cds.py
│   │   │   │       ├── container.py
│   │   │   │       ├── country.py
│   │   │   │       ├── crc.py
│   │   │   │       ├── date.py
│   │   │   │       ├── edition.py
│   │   │   │       ├── episode_title.py
│   │   │   │       ├── episodes.py
│   │   │   │       ├── film.py
│   │   │   │       ├── language.py
│   │   │   │       ├── mimetype.py
│   │   │   │       ├── other.py
│   │   │   │       ├── part.py
│   │   │   │       ├── release_group.py
│   │   │   │       ├── screen_size.py
│   │   │   │       ├── size.py
│   │   │   │       ├── source.py
│   │   │   │       ├── streaming_service.py
│   │   │   │       ├── title.py
│   │   │   │       ├── type.py
│   │   │   │       ├── video_codec.py
│   │   │   │       └── website.py
│   │   │   ├── test/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── config/
│   │   │   │   │   ├── dummy.txt
│   │   │   │   │   ├── test.json
│   │   │   │   │   ├── test.yaml
│   │   │   │   │   └── test.yml
│   │   │   │   ├── enable_disable_properties.yml
│   │   │   │   ├── episodes.yml
│   │   │   │   ├── movies.yml
│   │   │   │   ├── rules/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── audio_codec.yml
│   │   │   │   │   ├── bonus.yml
│   │   │   │   │   ├── cds.yml
│   │   │   │   │   ├── common_words.yml
│   │   │   │   │   ├── country.yml
│   │   │   │   │   ├── date.yml
│   │   │   │   │   ├── edition.yml
│   │   │   │   │   ├── episodes.yml
│   │   │   │   │   ├── film.yml
│   │   │   │   │   ├── language.yml
│   │   │   │   │   ├── other.yml
│   │   │   │   │   ├── part.yml
│   │   │   │   │   ├── processors.yml
│   │   │   │   │   ├── processors_test.py
│   │   │   │   │   ├── release_group.yml
│   │   │   │   │   ├── screen_size.yml
│   │   │   │   │   ├── size.yml
│   │   │   │   │   ├── source.yml
│   │   │   │   │   ├── title.yml
│   │   │   │   │   ├── video_codec.yml
│   │   │   │   │   └── website.yml
│   │   │   │   ├── streaming_services.yaml
│   │   │   │   ├── suggested.json
│   │   │   │   ├── test-input-file.txt
│   │   │   │   ├── test_api.py
│   │   │   │   ├── test_api_unicode_literals.py
│   │   │   │   ├── test_benchmark.py
│   │   │   │   ├── test_main.py
│   │   │   │   ├── test_options.py
│   │   │   │   ├── test_yml.py
│   │   │   │   └── various.yml
│   │   │   ├── tlds-alpha-by-domain.txt
│   │   │   └── yamlutils.py
│   │   ├── idna/
│   │   │   ├── __init__.py
│   │   │   ├── codec.py
│   │   │   ├── compat.py
│   │   │   ├── core.py
│   │   │   ├── idnadata.py
│   │   │   ├── intranges.py
│   │   │   ├── package_data.py
│   │   │   └── uts46data.py
│   │   ├── importlib_metadata/
│   │   │   ├── __init__.py
│   │   │   └── _compat.py
│   │   ├── importlib_resources/
│   │   │   ├── __init__.py
│   │   │   ├── _adapters.py
│   │   │   ├── _common.py
│   │   │   ├── _itertools.py
│   │   │   ├── abc.py
│   │   │   ├── compat/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── py38.py
│   │   │   │   └── py39.py
│   │   │   ├── future/
│   │   │   │   ├── __init__.py
│   │   │   │   └── adapters.py
│   │   │   ├── py.typed
│   │   │   ├── readers.py
│   │   │   ├── simple.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── _compat.py
│   │   │       ├── _path.py
│   │   │       ├── data01/
│   │   │       │   ├── __init__.py
│   │   │       │   ├── binary.file
│   │   │       │   ├── subdirectory/
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   └── binary.file
│   │   │       │   ├── utf-16.file
│   │   │       │   └── utf-8.file
│   │   │       ├── data02/
│   │   │       │   ├── __init__.py
│   │   │       │   ├── one/
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   └── resource1.txt
│   │   │       │   ├── subdirectory/
│   │   │       │   │   └── subsubdir/
│   │   │       │   │       └── resource.txt
│   │   │       │   └── two/
│   │   │       │       ├── __init__.py
│   │   │       │       └── resource2.txt
│   │   │       ├── namespacedata01/
│   │   │       │   ├── binary.file
│   │   │       │   ├── subdirectory/
│   │   │       │   │   └── binary.file
│   │   │       │   ├── utf-16.file
│   │   │       │   └── utf-8.file
│   │   │       ├── test_compatibilty_files.py
│   │   │       ├── test_contents.py
│   │   │       ├── test_custom.py
│   │   │       ├── test_files.py
│   │   │       ├── test_open.py
│   │   │       ├── test_path.py
│   │   │       ├── test_read.py
│   │   │       ├── test_reader.py
│   │   │       ├── test_resource.py
│   │   │       ├── util.py
│   │   │       └── zip.py
│   │   ├── jaraco/
│   │   │   ├── context.py
│   │   │   ├── functools/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── __init__.pyi
│   │   │   │   └── py.typed
│   │   │   └── text/
│   │   │       ├── Lorem ipsum.txt
│   │   │       ├── __init__.py
│   │   │       ├── layouts.py
│   │   │       ├── show-newlines.py
│   │   │       ├── strip-prefix.py
│   │   │       ├── to-dvorak.py
│   │   │       └── to-qwerty.py
│   │   ├── jellyfish/
│   │   │   ├── __init__.py
│   │   │   ├── __init__.pyi
│   │   │   ├── _jellyfish.py
│   │   │   ├── porter.py
│   │   │   ├── py.typed
│   │   │   └── test.py
│   │   ├── linktastic.py
│   │   ├── mediafile.py
│   │   ├── more_itertools/
│   │   │   ├── __init__.py
│   │   │   ├── more.py
│   │   │   ├── recipes.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── test_more.py
│   │   │       └── test_recipes.py
│   │   ├── munkres.py
│   │   ├── musicbrainzngs/
│   │   │   ├── __init__.py
│   │   │   ├── caa.py
│   │   │   ├── compat.py
│   │   │   ├── mbxml.py
│   │   │   ├── musicbrainz.py
│   │   │   └── util.py
│   │   ├── mutagen/
│   │   │   ├── __init__.py
│   │   │   ├── _constants.py
│   │   │   ├── _file.py
│   │   │   ├── _iff.py
│   │   │   ├── _riff.py
│   │   │   ├── _tags.py
│   │   │   ├── _tools/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _util.py
│   │   │   │   ├── mid3cp.py
│   │   │   │   ├── mid3iconv.py
│   │   │   │   ├── mid3v2.py
│   │   │   │   ├── moggsplit.py
│   │   │   │   ├── mutagen_inspect.py
│   │   │   │   └── mutagen_pony.py
│   │   │   ├── _util.py
│   │   │   ├── _vorbis.py
│   │   │   ├── aac.py
│   │   │   ├── ac3.py
│   │   │   ├── aiff.py
│   │   │   ├── apev2.py
│   │   │   ├── asf/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _attrs.py
│   │   │   │   ├── _objects.py
│   │   │   │   └── _util.py
│   │   │   ├── dsdiff.py
│   │   │   ├── dsf.py
│   │   │   ├── easyid3.py
│   │   │   ├── easymp4.py
│   │   │   ├── flac.py
│   │   │   ├── id3/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _file.py
│   │   │   │   ├── _frames.py
│   │   │   │   ├── _id3v1.py
│   │   │   │   ├── _specs.py
│   │   │   │   ├── _tags.py
│   │   │   │   └── _util.py
│   │   │   ├── m4a.py
│   │   │   ├── monkeysaudio.py
│   │   │   ├── mp3/
│   │   │   │   ├── __init__.py
│   │   │   │   └── _util.py
│   │   │   ├── mp4/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _as_entry.py
│   │   │   │   ├── _atom.py
│   │   │   │   └── _util.py
│   │   │   ├── musepack.py
│   │   │   ├── ogg.py
│   │   │   ├── oggflac.py
│   │   │   ├── oggopus.py
│   │   │   ├── oggspeex.py
│   │   │   ├── oggtheora.py
│   │   │   ├── oggvorbis.py
│   │   │   ├── optimfrog.py
│   │   │   ├── py.typed
│   │   │   ├── smf.py
│   │   │   ├── tak.py
│   │   │   ├── trueaudio.py
│   │   │   ├── wave.py
│   │   │   └── wavpack.py
│   │   ├── oauthlib/
│   │   │   ├── __init__.py
│   │   │   ├── common.py
│   │   │   ├── oauth1/
│   │   │   │   ├── __init__.py
│   │   │   │   └── rfc5849/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── endpoints/
│   │   │   │       │   ├── __init__.py
│   │   │   │       │   ├── access_token.py
│   │   │   │       │   ├── authorization.py
│   │   │   │       │   ├── base.py
│   │   │   │       │   ├── pre_configured.py
│   │   │   │       │   ├── request_token.py
│   │   │   │       │   ├── resource.py
│   │   │   │       │   └── signature_only.py
│   │   │   │       ├── errors.py
│   │   │   │       ├── parameters.py
│   │   │   │       ├── request_validator.py
│   │   │   │       ├── signature.py
│   │   │   │       └── utils.py
│   │   │   ├── oauth2/
│   │   │   │   ├── __init__.py
│   │   │   │   └── rfc6749/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── clients/
│   │   │   │       │   ├── __init__.py
│   │   │   │       │   ├── backend_application.py
│   │   │   │       │   ├── base.py
│   │   │   │       │   ├── legacy_application.py
│   │   │   │       │   ├── mobile_application.py
│   │   │   │       │   ├── service_application.py
│   │   │   │       │   └── web_application.py
│   │   │   │       ├── endpoints/
│   │   │   │       │   ├── __init__.py
│   │   │   │       │   ├── authorization.py
│   │   │   │       │   ├── base.py
│   │   │   │       │   ├── introspect.py
│   │   │   │       │   ├── metadata.py
│   │   │   │       │   ├── pre_configured.py
│   │   │   │       │   ├── resource.py
│   │   │   │       │   ├── revocation.py
│   │   │   │       │   └── token.py
│   │   │   │       ├── errors.py
│   │   │   │       ├── grant_types/
│   │   │   │       │   ├── __init__.py
│   │   │   │       │   ├── authorization_code.py
│   │   │   │       │   ├── base.py
│   │   │   │       │   ├── client_credentials.py
│   │   │   │       │   ├── implicit.py
│   │   │   │       │   ├── refresh_token.py
│   │   │   │       │   └── resource_owner_password_credentials.py
│   │   │   │       ├── parameters.py
│   │   │   │       ├── request_validator.py
│   │   │   │       ├── tokens.py
│   │   │   │       └── utils.py
│   │   │   ├── openid/
│   │   │   │   ├── __init__.py
│   │   │   │   └── connect/
│   │   │   │       ├── __init__.py
│   │   │   │       └── core/
│   │   │   │           ├── __init__.py
│   │   │   │           ├── endpoints/
│   │   │   │           │   ├── __init__.py
│   │   │   │           │   ├── pre_configured.py
│   │   │   │           │   └── userinfo.py
│   │   │   │           ├── exceptions.py
│   │   │   │           ├── grant_types/
│   │   │   │           │   ├── __init__.py
│   │   │   │           │   ├── authorization_code.py
│   │   │   │           │   ├── base.py
│   │   │   │           │   ├── dispatchers.py
│   │   │   │           │   ├── exceptions.py
│   │   │   │           │   ├── hybrid.py
│   │   │   │           │   └── implicit.py
│   │   │   │           ├── request_validator.py
│   │   │   │           └── tokens.py
│   │   │   ├── signals.py
│   │   │   └── uri_validate.py
│   │   ├── packaging/
│   │   │   ├── __init__.py
│   │   │   ├── _elffile.py
│   │   │   ├── _manylinux.py
│   │   │   ├── _musllinux.py
│   │   │   ├── _parser.py
│   │   │   ├── _structures.py
│   │   │   ├── _tokenizer.py
│   │   │   ├── markers.py
│   │   │   ├── metadata.py
│   │   │   ├── py.typed
│   │   │   ├── requirements.py
│   │   │   ├── specifiers.py
│   │   │   ├── tags.py
│   │   │   ├── utils.py
│   │   │   └── version.py
│   │   ├── pbr/
│   │   │   ├── __init__.py
│   │   │   ├── build.py
│   │   │   ├── builddoc.py
│   │   │   ├── cmd/
│   │   │   │   ├── __init__.py
│   │   │   │   └── main.py
│   │   │   ├── core.py
│   │   │   ├── extra_files.py
│   │   │   ├── find_package.py
│   │   │   ├── git.py
│   │   │   ├── hooks/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── backwards.py
│   │   │   │   ├── base.py
│   │   │   │   ├── commands.py
│   │   │   │   ├── files.py
│   │   │   │   └── metadata.py
│   │   │   ├── options.py
│   │   │   ├── packaging.py
│   │   │   ├── pbr_json.py
│   │   │   ├── sphinxext.py
│   │   │   ├── testr_command.py
│   │   │   ├── tests/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── base.py
│   │   │   │   ├── test_commands.py
│   │   │   │   ├── test_core.py
│   │   │   │   ├── test_files.py
│   │   │   │   ├── test_hooks.py
│   │   │   │   ├── test_integration.py
│   │   │   │   ├── test_packaging.py
│   │   │   │   ├── test_pbr_json.py
│   │   │   │   ├── test_setup.py
│   │   │   │   ├── test_util.py
│   │   │   │   ├── test_version.py
│   │   │   │   ├── test_wsgi.py
│   │   │   │   ├── testpackage/
│   │   │   │   │   ├── CHANGES.txt
│   │   │   │   │   ├── LICENSE.txt
│   │   │   │   │   ├── MANIFEST.in
│   │   │   │   │   ├── README.txt
│   │   │   │   │   ├── data_files/
│   │   │   │   │   │   ├── a.txt
│   │   │   │   │   │   ├── b.txt
│   │   │   │   │   │   └── c.rst
│   │   │   │   │   ├── doc/
│   │   │   │   │   │   └── source/
│   │   │   │   │   │       ├── conf.py
│   │   │   │   │   │       ├── index.rst
│   │   │   │   │   │       ├── installation.rst
│   │   │   │   │   │       └── usage.rst
│   │   │   │   │   ├── extra-file.txt
│   │   │   │   │   ├── git-extra-file.txt
│   │   │   │   │   ├── pbr_testpackage/
│   │   │   │   │   │   ├── __init__.py
│   │   │   │   │   │   ├── _setup_hooks.py
│   │   │   │   │   │   ├── cmd.py
│   │   │   │   │   │   ├── extra.py
│   │   │   │   │   │   ├── package_data/
│   │   │   │   │   │   │   ├── 1.txt
│   │   │   │   │   │   │   └── 2.txt
│   │   │   │   │   │   └── wsgi.py
│   │   │   │   │   ├── setup.py
│   │   │   │   │   ├── src/
│   │   │   │   │   │   └── testext.c
│   │   │   │   │   └── test-requirements.txt
│   │   │   │   └── util.py
│   │   │   ├── util.py
│   │   │   └── version.py
│   │   ├── pkg_resources/
│   │   │   ├── __init__.py
│   │   │   ├── _vendor/
│   │   │   │   ├── __init__.py
│   │   │   │   └── packaging/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── _structures.py
│   │   │   │       ├── markers.py
│   │   │   │       ├── requirements.py
│   │   │   │       ├── specifiers.py
│   │   │   │       ├── utils.py
│   │   │   │       └── version.py
│   │   │   └── extern/
│   │   │       └── __init__.py
│   │   ├── platformdirs/
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── android.py
│   │   │   ├── api.py
│   │   │   ├── macos.py
│   │   │   ├── py.typed
│   │   │   ├── unix.py
│   │   │   ├── version.py
│   │   │   └── windows.py
│   │   ├── pysrt/
│   │   │   ├── __init__.py
│   │   │   ├── commands.py
│   │   │   ├── comparablemixin.py
│   │   │   ├── compat.py
│   │   │   ├── srtexc.py
│   │   │   ├── srtfile.py
│   │   │   ├── srtitem.py
│   │   │   ├── srttime.py
│   │   │   └── version.py
│   │   ├── pytz/
│   │   │   ├── __init__.py
│   │   │   ├── exceptions.py
│   │   │   ├── lazy.py
│   │   │   ├── reference.py
│   │   │   ├── tzfile.py
│   │   │   ├── tzinfo.py
│   │   │   └── zoneinfo/
│   │   │       ├── Africa/
│   │   │       │   ├── Abidjan
│   │   │       │   ├── Accra
│   │   │       │   ├── Addis_Ababa
│   │   │       │   ├── Algiers
│   │   │       │   ├── Asmara
│   │   │       │   ├── Asmera
│   │   │       │   ├── Bamako
│   │   │       │   ├── Bangui
│   │   │       │   ├── Banjul
│   │   │       │   ├── Bissau
│   │   │       │   ├── Blantyre
│   │   │       │   ├── Brazzaville
│   │   │       │   ├── Bujumbura
│   │   │       │   ├── Cairo
│   │   │       │   ├── Casablanca
│   │   │       │   ├── Ceuta
│   │   │       │   ├── Conakry
│   │   │       │   ├── Dakar
│   │   │       │   ├── Dar_es_Salaam
│   │   │       │   ├── Djibouti
│   │   │       │   ├── Douala
│   │   │       │   ├── El_Aaiun
│   │   │       │   ├── Freetown
│   │   │       │   ├── Gaborone
│   │   │       │   ├── Harare
│   │   │       │   ├── Johannesburg
│   │   │       │   ├── Juba
│   │   │       │   ├── Kampala
│   │   │       │   ├── Khartoum
│   │   │       │   ├── Kigali
│   │   │       │   ├── Kinshasa
│   │   │       │   ├── Lagos
│   │   │       │   ├── Libreville
│   │   │       │   ├── Lome
│   │   │       │   ├── Luanda
│   │   │       │   ├── Lubumbashi
│   │   │       │   ├── Lusaka
│   │   │       │   ├── Malabo
│   │   │       │   ├── Maputo
│   │   │       │   ├── Maseru
│   │   │       │   ├── Mbabane
│   │   │       │   ├── Mogadishu
│   │   │       │   ├── Monrovia
│   │   │       │   ├── Nairobi
│   │   │       │   ├── Ndjamena
│   │   │       │   ├── Niamey
│   │   │       │   ├── Nouakchott
│   │   │       │   ├── Ouagadougou
│   │   │       │   ├── Porto-Novo
│   │   │       │   ├── Sao_Tome
│   │   │       │   ├── Timbuktu
│   │   │       │   ├── Tripoli
│   │   │       │   ├── Tunis
│   │   │       │   └── Windhoek
│   │   │       ├── America/
│   │   │       │   ├── Adak
│   │   │       │   ├── Anchorage
│   │   │       │   ├── Anguilla
│   │   │       │   ├── Antigua
│   │   │       │   ├── Araguaina
│   │   │       │   ├── Argentina/
│   │   │       │   │   ├── Buenos_Aires
│   │   │       │   │   ├── Catamarca
│   │   │       │   │   ├── ComodRivadavia
│   │   │       │   │   ├── Cordoba
│   │   │       │   │   ├── Jujuy
│   │   │       │   │   ├── La_Rioja
│   │   │       │   │   ├── Mendoza
│   │   │       │   │   ├── Rio_Gallegos
│   │   │       │   │   ├── Salta
│   │   │       │   │   ├── San_Juan
│   │   │       │   │   ├── San_Luis
│   │   │       │   │   ├── Tucuman
│   │   │       │   │   └── Ushuaia
│   │   │       │   ├── Aruba
│   │   │       │   ├── Asuncion
│   │   │       │   ├── Atikokan
│   │   │       │   ├── Atka
│   │   │       │   ├── Bahia
│   │   │       │   ├── Bahia_Banderas
│   │   │       │   ├── Barbados
│   │   │       │   ├── Belem
│   │   │       │   ├── Belize
│   │   │       │   ├── Blanc-Sablon
│   │   │       │   ├── Boa_Vista
│   │   │       │   ├── Bogota
│   │   │       │   ├── Boise
│   │   │       │   ├── Buenos_Aires
│   │   │       │   ├── Cambridge_Bay
│   │   │       │   ├── Campo_Grande
│   │   │       │   ├── Cancun
│   │   │       │   ├── Caracas
│   │   │       │   ├── Catamarca
│   │   │       │   ├── Cayenne
│   │   │       │   ├── Cayman
│   │   │       │   ├── Chicago
│   │   │       │   ├── Chihuahua
│   │   │       │   ├── Coral_Harbour
│   │   │       │   ├── Cordoba
│   │   │       │   ├── Costa_Rica
│   │   │       │   ├── Creston
│   │   │       │   ├── Cuiaba
│   │   │       │   ├── Curacao
│   │   │       │   ├── Danmarkshavn
│   │   │       │   ├── Dawson
│   │   │       │   ├── Dawson_Creek
│   │   │       │   ├── Denver
│   │   │       │   ├── Detroit
│   │   │       │   ├── Dominica
│   │   │       │   ├── Edmonton
│   │   │       │   ├── Eirunepe
│   │   │       │   ├── El_Salvador
│   │   │       │   ├── Ensenada
│   │   │       │   ├── Fort_Nelson
│   │   │       │   ├── Fort_Wayne
│   │   │       │   ├── Fortaleza
│   │   │       │   ├── Glace_Bay
│   │   │       │   ├── Godthab
│   │   │       │   ├── Goose_Bay
│   │   │       │   ├── Grand_Turk
│   │   │       │   ├── Grenada
│   │   │       │   ├── Guadeloupe
│   │   │       │   ├── Guatemala
│   │   │       │   ├── Guayaquil
│   │   │       │   ├── Guyana
│   │   │       │   ├── Halifax
│   │   │       │   ├── Havana
│   │   │       │   ├── Hermosillo
│   │   │       │   ├── Indiana/
│   │   │       │   │   ├── Indianapolis
│   │   │       │   │   ├── Knox
│   │   │       │   │   ├── Marengo
│   │   │       │   │   ├── Petersburg
│   │   │       │   │   ├── Tell_City
│   │   │       │   │   ├── Vevay
│   │   │       │   │   ├── Vincennes
│   │   │       │   │   └── Winamac
│   │   │       │   ├── Indianapolis
│   │   │       │   ├── Inuvik
│   │   │       │   ├── Iqaluit
│   │   │       │   ├── Jamaica
│   │   │       │   ├── Jujuy
│   │   │       │   ├── Juneau
│   │   │       │   ├── Kentucky/
│   │   │       │   │   ├── Louisville
│   │   │       │   │   └── Monticello
│   │   │       │   ├── Knox_IN
│   │   │       │   ├── Kralendijk
│   │   │       │   ├── La_Paz
│   │   │       │   ├── Lima
│   │   │       │   ├── Los_Angeles
│   │   │       │   ├── Louisville
│   │   │       │   ├── Lower_Princes
│   │   │       │   ├── Maceio
│   │   │       │   ├── Managua
│   │   │       │   ├── Manaus
│   │   │       │   ├── Marigot
│   │   │       │   ├── Martinique
│   │   │       │   ├── Matamoros
│   │   │       │   ├── Mazatlan
│   │   │       │   ├── Mendoza
│   │   │       │   ├── Menominee
│   │   │       │   ├── Merida
│   │   │       │   ├── Metlakatla
│   │   │       │   ├── Mexico_City
│   │   │       │   ├── Miquelon
│   │   │       │   ├── Moncton
│   │   │       │   ├── Monterrey
│   │   │       │   ├── Montevideo
│   │   │       │   ├── Montreal
│   │   │       │   ├── Montserrat
│   │   │       │   ├── Nassau
│   │   │       │   ├── New_York
│   │   │       │   ├── Nipigon
│   │   │       │   ├── Nome
│   │   │       │   ├── Noronha
│   │   │       │   ├── North_Dakota/
│   │   │       │   │   ├── Beulah
│   │   │       │   │   ├── Center
│   │   │       │   │   └── New_Salem
│   │   │       │   ├── Nuuk
│   │   │       │   ├── Ojinaga
│   │   │       │   ├── Panama
│   │   │       │   ├── Pangnirtung
│   │   │       │   ├── Paramaribo
│   │   │       │   ├── Phoenix
│   │   │       │   ├── Port-au-Prince
│   │   │       │   ├── Port_of_Spain
│   │   │       │   ├── Porto_Acre
│   │   │       │   ├── Porto_Velho
│   │   │       │   ├── Puerto_Rico
│   │   │       │   ├── Punta_Arenas
│   │   │       │   ├── Rainy_River
│   │   │       │   ├── Rankin_Inlet
│   │   │       │   ├── Recife
│   │   │       │   ├── Regina
│   │   │       │   ├── Resolute
│   │   │       │   ├── Rio_Branco
│   │   │       │   ├── Rosario
│   │   │       │   ├── Santa_Isabel
│   │   │       │   ├── Santarem
│   │   │       │   ├── Santiago
│   │   │       │   ├── Santo_Domingo
│   │   │       │   ├── Sao_Paulo
│   │   │       │   ├── Scoresbysund
│   │   │       │   ├── Shiprock
│   │   │       │   ├── Sitka
│   │   │       │   ├── St_Barthelemy
│   │   │       │   ├── St_Johns
│   │   │       │   ├── St_Kitts
│   │   │       │   ├── St_Lucia
│   │   │       │   ├── St_Thomas
│   │   │       │   ├── St_Vincent
│   │   │       │   ├── Swift_Current
│   │   │       │   ├── Tegucigalpa
│   │   │       │   ├── Thule
│   │   │       │   ├── Thunder_Bay
│   │   │       │   ├── Tijuana
│   │   │       │   ├── Toronto
│   │   │       │   ├── Tortola
│   │   │       │   ├── Vancouver
│   │   │       │   ├── Virgin
│   │   │       │   ├── Whitehorse
│   │   │       │   ├── Winnipeg
│   │   │       │   ├── Yakutat
│   │   │       │   └── Yellowknife
│   │   │       ├── Antarctica/
│   │   │       │   ├── Casey
│   │   │       │   ├── Davis
│   │   │       │   ├── DumontDUrville
│   │   │       │   ├── Macquarie
│   │   │       │   ├── Mawson
│   │   │       │   ├── McMurdo
│   │   │       │   ├── Palmer
│   │   │       │   ├── Rothera
│   │   │       │   ├── South_Pole
│   │   │       │   ├── Syowa
│   │   │       │   ├── Troll
│   │   │       │   └── Vostok
│   │   │       ├── Arctic/
│   │   │       │   └── Longyearbyen
│   │   │       ├── Asia/
│   │   │       │   ├── Aden
│   │   │       │   ├── Almaty
│   │   │       │   ├── Amman
│   │   │       │   ├── Anadyr
│   │   │       │   ├── Aqtau
│   │   │       │   ├── Aqtobe
│   │   │       │   ├── Ashgabat
│   │   │       │   ├── Ashkhabad
│   │   │       │   ├── Atyrau
│   │   │       │   ├── Baghdad
│   │   │       │   ├── Bahrain
│   │   │       │   ├── Baku
│   │   │       │   ├── Bangkok
│   │   │       │   ├── Barnaul
│   │   │       │   ├── Beirut
│   │   │       │   ├── Bishkek
│   │   │       │   ├── Brunei
│   │   │       │   ├── Calcutta
│   │   │       │   ├── Chita
│   │   │       │   ├── Choibalsan
│   │   │       │   ├── Chongqing
│   │   │       │   ├── Chungking
│   │   │       │   ├── Colombo
│   │   │       │   ├── Dacca
│   │   │       │   ├── Damascus
│   │   │       │   ├── Dhaka
│   │   │       │   ├── Dili
│   │   │       │   ├── Dubai
│   │   │       │   ├── Dushanbe
│   │   │       │   ├── Famagusta
│   │   │       │   ├── Gaza
│   │   │       │   ├── Harbin
│   │   │       │   ├── Hebron
│   │   │       │   ├── Ho_Chi_Minh
│   │   │       │   ├── Hong_Kong
│   │   │       │   ├── Hovd
│   │   │       │   ├── Irkutsk
│   │   │       │   ├── Istanbul
│   │   │       │   ├── Jakarta
│   │   │       │   ├── Jayapura
│   │   │       │   ├── Jerusalem
│   │   │       │   ├── Kabul
│   │   │       │   ├── Kamchatka
│   │   │       │   ├── Karachi
│   │   │       │   ├── Kashgar
│   │   │       │   ├── Kathmandu
│   │   │       │   ├── Katmandu
│   │   │       │   ├── Khandyga
│   │   │       │   ├── Kolkata
│   │   │       │   ├── Krasnoyarsk
│   │   │       │   ├── Kuala_Lumpur
│   │   │       │   ├── Kuching
│   │   │       │   ├── Kuwait
│   │   │       │   ├── Macao
│   │   │       │   ├── Macau
│   │   │       │   ├── Magadan
│   │   │       │   ├── Makassar
│   │   │       │   ├── Manila
│   │   │       │   ├── Muscat
│   │   │       │   ├── Nicosia
│   │   │       │   ├── Novokuznetsk
│   │   │       │   ├── Novosibirsk
│   │   │       │   ├── Omsk
│   │   │       │   ├── Oral
│   │   │       │   ├── Phnom_Penh
│   │   │       │   ├── Pontianak
│   │   │       │   ├── Pyongyang
│   │   │       │   ├── Qatar
│   │   │       │   ├── Qostanay
│   │   │       │   ├── Qyzylorda
│   │   │       │   ├── Rangoon
│   │   │       │   ├── Riyadh
│   │   │       │   ├── Saigon
│   │   │       │   ├── Sakhalin
│   │   │       │   ├── Samarkand
│   │   │       │   ├── Seoul
│   │   │       │   ├── Shanghai
│   │   │       │   ├── Singapore
│   │   │       │   ├── Srednekolymsk
│   │   │       │   ├── Taipei
│   │   │       │   ├── Tashkent
│   │   │       │   ├── Tbilisi
│   │   │       │   ├── Tehran
│   │   │       │   ├── Tel_Aviv
│   │   │       │   ├── Thimbu
│   │   │       │   ├── Thimphu
│   │   │       │   ├── Tokyo
│   │   │       │   ├── Tomsk
│   │   │       │   ├── Ujung_Pandang
│   │   │       │   ├── Ulaanbaatar
│   │   │       │   ├── Ulan_Bator
│   │   │       │   ├── Urumqi
│   │   │       │   ├── Ust-Nera
│   │   │       │   ├── Vientiane
│   │   │       │   ├── Vladivostok
│   │   │       │   ├── Yakutsk
│   │   │       │   ├── Yangon
│   │   │       │   ├── Yekaterinburg
│   │   │       │   └── Yerevan
│   │   │       ├── Atlantic/
│   │   │       │   ├── Azores
│   │   │       │   ├── Bermuda
│   │   │       │   ├── Canary
│   │   │       │   ├── Cape_Verde
│   │   │       │   ├── Faeroe
│   │   │       │   ├── Faroe
│   │   │       │   ├── Jan_Mayen
│   │   │       │   ├── Madeira
│   │   │       │   ├── Reykjavik
│   │   │       │   ├── South_Georgia
│   │   │       │   ├── St_Helena
│   │   │       │   └── Stanley
│   │   │       ├── Australia/
│   │   │       │   ├── ACT
│   │   │       │   ├── Adelaide
│   │   │       │   ├── Brisbane
│   │   │       │   ├── Broken_Hill
│   │   │       │   ├── Canberra
│   │   │       │   ├── Currie
│   │   │       │   ├── Darwin
│   │   │       │   ├── Eucla
│   │   │       │   ├── Hobart
│   │   │       │   ├── LHI
│   │   │       │   ├── Lindeman
│   │   │       │   ├── Lord_Howe
│   │   │       │   ├── Melbourne
│   │   │       │   ├── NSW
│   │   │       │   ├── North
│   │   │       │   ├── Perth
│   │   │       │   ├── Queensland
│   │   │       │   ├── South
│   │   │       │   ├── Sydney
│   │   │       │   ├── Tasmania
│   │   │       │   ├── Victoria
│   │   │       │   ├── West
│   │   │       │   └── Yancowinna
│   │   │       ├── Brazil/
│   │   │       │   ├── Acre
│   │   │       │   ├── DeNoronha
│   │   │       │   ├── East
│   │   │       │   └── West
│   │   │       ├── CET
│   │   │       ├── CST6CDT
│   │   │       ├── Canada/
│   │   │       │   ├── Atlantic
│   │   │       │   ├── Central
│   │   │       │   ├── Eastern
│   │   │       │   ├── Mountain
│   │   │       │   ├── Newfoundland
│   │   │       │   ├── Pacific
│   │   │       │   ├── Saskatchewan
│   │   │       │   └── Yukon
│   │   │       ├── Chile/
│   │   │       │   ├── Continental
│   │   │       │   └── EasterIsland
│   │   │       ├── Cuba
│   │   │       ├── EET
│   │   │       ├── EST
│   │   │       ├── EST5EDT
│   │   │       ├── Egypt
│   │   │       ├── Eire
│   │   │       ├── Etc/
│   │   │       │   ├── GMT
│   │   │       │   ├── GMT+0
│   │   │       │   ├── GMT+1
│   │   │       │   ├── GMT+10
│   │   │       │   ├── GMT+11
│   │   │       │   ├── GMT+12
│   │   │       │   ├── GMT+2
│   │   │       │   ├── GMT+3
│   │   │       │   ├── GMT+4
│   │   │       │   ├── GMT+5
│   │   │       │   ├── GMT+6
│   │   │       │   ├── GMT+7
│   │   │       │   ├── GMT+8
│   │   │       │   ├── GMT+9
│   │   │       │   ├── GMT-0
│   │   │       │   ├── GMT-1
│   │   │       │   ├── GMT-10
│   │   │       │   ├── GMT-11
│   │   │       │   ├── GMT-12
│   │   │       │   ├── GMT-13
│   │   │       │   ├── GMT-14
│   │   │       │   ├── GMT-2
│   │   │       │   ├── GMT-3
│   │   │       │   ├── GMT-4
│   │   │       │   ├── GMT-5
│   │   │       │   ├── GMT-6
│   │   │       │   ├── GMT-7
│   │   │       │   ├── GMT-8
│   │   │       │   ├── GMT-9
│   │   │       │   ├── GMT0
│   │   │       │   ├── Greenwich
│   │   │       │   ├── UCT
│   │   │       │   ├── UTC
│   │   │       │   ├── Universal
│   │   │       │   └── Zulu
│   │   │       ├── Europe/
│   │   │       │   ├── Amsterdam
│   │   │       │   ├── Andorra
│   │   │       │   ├── Astrakhan
│   │   │       │   ├── Athens
│   │   │       │   ├── Belfast
│   │   │       │   ├── Belgrade
│   │   │       │   ├── Berlin
│   │   │       │   ├── Bratislava
│   │   │       │   ├── Brussels
│   │   │       │   ├── Bucharest
│   │   │       │   ├── Budapest
│   │   │       │   ├── Busingen
│   │   │       │   ├── Chisinau
│   │   │       │   ├── Copenhagen
│   │   │       │   ├── Dublin
│   │   │       │   ├── Gibraltar
│   │   │       │   ├── Guernsey
│   │   │       │   ├── Helsinki
│   │   │       │   ├── Isle_of_Man
│   │   │       │   ├── Istanbul
│   │   │       │   ├── Jersey
│   │   │       │   ├── Kaliningrad
│   │   │       │   ├── Kiev
│   │   │       │   ├── Kirov
│   │   │       │   ├── Kyiv
│   │   │       │   ├── Lisbon
│   │   │       │   ├── Ljubljana
│   │   │       │   ├── London
│   │   │       │   ├── Luxembourg
│   │   │       │   ├── Madrid
│   │   │       │   ├── Malta
│   │   │       │   ├── Mariehamn
│   │   │       │   ├── Minsk
│   │   │       │   ├── Monaco
│   │   │       │   ├── Moscow
│   │   │       │   ├── Nicosia
│   │   │       │   ├── Oslo
│   │   │       │   ├── Paris
│   │   │       │   ├── Podgorica
│   │   │       │   ├── Prague
│   │   │       │   ├── Riga
│   │   │       │   ├── Rome
│   │   │       │   ├── Samara
│   │   │       │   ├── San_Marino
│   │   │       │   ├── Sarajevo
│   │   │       │   ├── Saratov
│   │   │       │   ├── Simferopol
│   │   │       │   ├── Skopje
│   │   │       │   ├── Sofia
│   │   │       │   ├── Stockholm
│   │   │       │   ├── Tallinn
│   │   │       │   ├── Tirane
│   │   │       │   ├── Tiraspol
│   │   │       │   ├── Ulyanovsk
│   │   │       │   ├── Uzhgorod
│   │   │       │   ├── Vaduz
│   │   │       │   ├── Vatican
│   │   │       │   ├── Vienna
│   │   │       │   ├── Vilnius
│   │   │       │   ├── Volgograd
│   │   │       │   ├── Warsaw
│   │   │       │   ├── Zagreb
│   │   │       │   ├── Zaporozhye
│   │   │       │   └── Zurich
│   │   │       ├── Factory
│   │   │       ├── GB
│   │   │       ├── GB-Eire
│   │   │       ├── GMT
│   │   │       ├── GMT+0
│   │   │       ├── GMT-0
│   │   │       ├── GMT0
│   │   │       ├── Greenwich
│   │   │       ├── HST
│   │   │       ├── Hongkong
│   │   │       ├── Iceland
│   │   │       ├── Indian/
│   │   │       │   ├── Antananarivo
│   │   │       │   ├── Chagos
│   │   │       │   ├── Christmas
│   │   │       │   ├── Cocos
│   │   │       │   ├── Comoro
│   │   │       │   ├── Kerguelen
│   │   │       │   ├── Mahe
│   │   │       │   ├── Maldives
│   │   │       │   ├── Mauritius
│   │   │       │   ├── Mayotte
│   │   │       │   └── Reunion
│   │   │       ├── Iran
│   │   │       ├── Israel
│   │   │       ├── Jamaica
│   │   │       ├── Japan
│   │   │       ├── Kwajalein
│   │   │       ├── Libya
│   │   │       ├── MET
│   │   │       ├── MST
│   │   │       ├── MST7MDT
│   │   │       ├── Mexico/
│   │   │       │   ├── BajaNorte
│   │   │       │   ├── BajaSur
│   │   │       │   └── General
│   │   │       ├── NZ
│   │   │       ├── NZ-CHAT
│   │   │       ├── Navajo
│   │   │       ├── PRC
│   │   │       ├── PST8PDT
│   │   │       ├── Pacific/
│   │   │       │   ├── Apia
│   │   │       │   ├── Auckland
│   │   │       │   ├── Bougainville
│   │   │       │   ├── Chatham
│   │   │       │   ├── Chuuk
│   │   │       │   ├── Easter
│   │   │       │   ├── Efate
│   │   │       │   ├── Enderbury
│   │   │       │   ├── Fakaofo
│   │   │       │   ├── Fiji
│   │   │       │   ├── Funafuti
│   │   │       │   ├── Galapagos
│   │   │       │   ├── Gambier
│   │   │       │   ├── Guadalcanal
│   │   │       │   ├── Guam
│   │   │       │   ├── Honolulu
│   │   │       │   ├── Johnston
│   │   │       │   ├── Kanton
│   │   │       │   ├── Kiritimati
│   │   │       │   ├── Kosrae
│   │   │       │   ├── Kwajalein
│   │   │       │   ├── Majuro
│   │   │       │   ├── Marquesas
│   │   │       │   ├── Midway
│   │   │       │   ├── Nauru
│   │   │       │   ├── Niue
│   │   │       │   ├── Norfolk
│   │   │       │   ├── Noumea
│   │   │       │   ├── Pago_Pago
│   │   │       │   ├── Palau
│   │   │       │   ├── Pitcairn
│   │   │       │   ├── Pohnpei
│   │   │       │   ├── Ponape
│   │   │       │   ├── Port_Moresby
│   │   │       │   ├── Rarotonga
│   │   │       │   ├── Saipan
│   │   │       │   ├── Samoa
│   │   │       │   ├── Tahiti
│   │   │       │   ├── Tarawa
│   │   │       │   ├── Tongatapu
│   │   │       │   ├── Truk
│   │   │       │   ├── Wake
│   │   │       │   ├── Wallis
│   │   │       │   └── Yap
│   │   │       ├── Poland
│   │   │       ├── Portugal
│   │   │       ├── ROC
│   │   │       ├── ROK
│   │   │       ├── Singapore
│   │   │       ├── Turkey
│   │   │       ├── UCT
│   │   │       ├── US/
│   │   │       │   ├── Alaska
│   │   │       │   ├── Aleutian
│   │   │       │   ├── Arizona
│   │   │       │   ├── Central
│   │   │       │   ├── East-Indiana
│   │   │       │   ├── Eastern
│   │   │       │   ├── Hawaii
│   │   │       │   ├── Indiana-Starke
│   │   │       │   ├── Michigan
│   │   │       │   ├── Mountain
│   │   │       │   ├── Pacific
│   │   │       │   └── Samoa
│   │   │       ├── UTC
│   │   │       ├── Universal
│   │   │       ├── W-SU
│   │   │       ├── WET
│   │   │       ├── Zulu
│   │   │       ├── iso3166.tab
│   │   │       ├── leapseconds
│   │   │       ├── tzdata.zi
│   │   │       ├── zone.tab
│   │   │       └── zone1970.tab
│   │   ├── qbittorrent/
│   │   │   ├── __init__.py
│   │   │   └── client.py
│   │   ├── rarfile.py
│   │   ├── rebulk/
│   │   │   ├── __init__.py
│   │   │   ├── __version__.py
│   │   │   ├── builder.py
│   │   │   ├── chain.py
│   │   │   ├── debug.py
│   │   │   ├── formatters.py
│   │   │   ├── introspector.py
│   │   │   ├── loose.py
│   │   │   ├── match.py
│   │   │   ├── pattern.py
│   │   │   ├── processors.py
│   │   │   ├── rebulk.py
│   │   │   ├── remodule.py
│   │   │   ├── rules.py
│   │   │   ├── test/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── default_rules_module.py
│   │   │   │   ├── rebulk_rules_module.py
│   │   │   │   ├── rules_module.py
│   │   │   │   ├── test_chain.py
│   │   │   │   ├── test_debug.py
│   │   │   │   ├── test_introspector.py
│   │   │   │   ├── test_loose.py
│   │   │   │   ├── test_match.py
│   │   │   │   ├── test_pattern.py
│   │   │   │   ├── test_processors.py
│   │   │   │   ├── test_rebulk.py
│   │   │   │   ├── test_rules.py
│   │   │   │   ├── test_toposort.py
│   │   │   │   └── test_validators.py
│   │   │   ├── toposort.py
│   │   │   ├── utils.py
│   │   │   └── validators.py
│   │   ├── rencode/
│   │   │   ├── __init__.py
│   │   │   └── rencode_orig.py
│   │   ├── requests/
│   │   │   ├── __init__.py
│   │   │   ├── __version__.py
│   │   │   ├── _internal_utils.py
│   │   │   ├── adapters.py
│   │   │   ├── api.py
│   │   │   ├── auth.py
│   │   │   ├── certs.py
│   │   │   ├── compat.py
│   │   │   ├── cookies.py
│   │   │   ├── exceptions.py
│   │   │   ├── help.py
│   │   │   ├── hooks.py
│   │   │   ├── models.py
│   │   │   ├── packages.py
│   │   │   ├── sessions.py
│   │   │   ├── status_codes.py
│   │   │   ├── structures.py
│   │   │   └── utils.py
│   │   ├── requests_oauthlib/
│   │   │   ├── __init__.py
│   │   │   ├── compliance_fixes/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── douban.py
│   │   │   │   ├── ebay.py
│   │   │   │   ├── facebook.py
│   │   │   │   ├── fitbit.py
│   │   │   │   ├── instagram.py
│   │   │   │   ├── mailchimp.py
│   │   │   │   ├── plentymarkets.py
│   │   │   │   ├── slack.py
│   │   │   │   └── weibo.py
│   │   │   ├── oauth1_auth.py
│   │   │   ├── oauth1_session.py
│   │   │   ├── oauth2_auth.py
│   │   │   └── oauth2_session.py
│   │   ├── setuptools/
│   │   │   ├── __init__.py
│   │   │   ├── _imp.py
│   │   │   ├── _vendor/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── ordered_set.py
│   │   │   │   └── packaging/
│   │   │   │       ├── __init__.py
│   │   │   │       ├── _structures.py
│   │   │   │       ├── markers.py
│   │   │   │       ├── requirements.py
│   │   │   │       ├── specifiers.py
│   │   │   │       ├── tags.py
│   │   │   │       ├── utils.py
│   │   │   │       └── version.py
│   │   │   ├── archive_util.py
│   │   │   ├── build_meta.py
│   │   │   ├── command/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── alias.py
│   │   │   │   ├── bdist_egg.py
│   │   │   │   ├── bdist_rpm.py
│   │   │   │   ├── build_clib.py
│   │   │   │   ├── build_ext.py
│   │   │   │   ├── build_py.py
│   │   │   │   ├── develop.py
│   │   │   │   ├── dist_info.py
│   │   │   │   ├── easy_install.py
│   │   │   │   ├── egg_info.py
│   │   │   │   ├── install.py
│   │   │   │   ├── install_egg_info.py
│   │   │   │   ├── install_lib.py
│   │   │   │   ├── install_scripts.py
│   │   │   │   ├── launcher manifest.xml
│   │   │   │   ├── register.py
│   │   │   │   ├── rotate.py
│   │   │   │   ├── saveopts.py
│   │   │   │   ├── sdist.py
│   │   │   │   ├── setopt.py
│   │   │   │   ├── test.py
│   │   │   │   ├── upload.py
│   │   │   │   └── upload_docs.py
│   │   │   ├── dep_util.py
│   │   │   ├── depends.py
│   │   │   ├── dist.py
│   │   │   ├── errors.py
│   │   │   ├── extension.py
│   │   │   ├── extern/
│   │   │   │   └── __init__.py
│   │   │   ├── glob.py
│   │   │   ├── installer.py
│   │   │   ├── launch.py
│   │   │   ├── monkey.py
│   │   │   ├── msvc.py
│   │   │   ├── namespaces.py
│   │   │   ├── package_index.py
│   │   │   ├── sandbox.py
│   │   │   ├── script (dev).tmpl
│   │   │   ├── script.tmpl
│   │   │   ├── unicode_utils.py
│   │   │   ├── version.py
│   │   │   ├── wheel.py
│   │   │   └── windows_support.py
│   │   ├── share/
│   │   │   └── man/
│   │   │       └── man1/
│   │   │           ├── mid3cp.1
│   │   │           ├── mid3iconv.1
│   │   │           ├── mid3v2.1
│   │   │           ├── moggsplit.1
│   │   │           ├── mutagen-inspect.1
│   │   │           └── mutagen-pony.1
│   │   ├── six.py
│   │   ├── soupsieve/
│   │   │   ├── __init__.py
│   │   │   ├── __meta__.py
│   │   │   ├── css_match.py
│   │   │   ├── css_parser.py
│   │   │   ├── css_types.py
│   │   │   ├── pretty.py
│   │   │   ├── py.typed
│   │   │   └── util.py
│   │   ├── stevedore/
│   │   │   ├── __init__.py
│   │   │   ├── dispatch.py
│   │   │   ├── driver.py
│   │   │   ├── enabled.py
│   │   │   ├── example/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── base.py
│   │   │   │   ├── load_as_driver.py
│   │   │   │   ├── load_as_extension.py
│   │   │   │   ├── setup.py
│   │   │   │   └── simple.py
│   │   │   ├── example2/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── fields.py
│   │   │   │   └── setup.py
│   │   │   ├── exception.py
│   │   │   ├── extension.py
│   │   │   ├── hook.py
│   │   │   ├── named.py
│   │   │   ├── sphinxext.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── extension_unimportable.py
│   │   │       ├── manager.py
│   │   │       ├── test_callback.py
│   │   │       ├── test_dispatch.py
│   │   │       ├── test_driver.py
│   │   │       ├── test_enabled.py
│   │   │       ├── test_example_fields.py
│   │   │       ├── test_example_simple.py
│   │   │       ├── test_extension.py
│   │   │       ├── test_hook.py
│   │   │       ├── test_named.py
│   │   │       ├── test_sphinxext.py
│   │   │       ├── test_test_manager.py
│   │   │       └── utils.py
│   │   ├── subliminal/
│   │   │   ├── __init__.py
│   │   │   ├── cache.py
│   │   │   ├── cli.py
│   │   │   ├── converters/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── addic7ed.py
│   │   │   │   ├── legendastv.py
│   │   │   │   ├── shooter.py
│   │   │   │   ├── thesubdb.py
│   │   │   │   └── tvsubtitles.py
│   │   │   ├── core.py
│   │   │   ├── exceptions.py
│   │   │   ├── extensions.py
│   │   │   ├── matches.py
│   │   │   ├── providers/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── addic7ed.py
│   │   │   │   ├── argenteam.py
│   │   │   │   ├── legendastv.py
│   │   │   │   ├── napiprojekt.py
│   │   │   │   ├── opensubtitles.py
│   │   │   │   ├── podnapisi.py
│   │   │   │   ├── shooter.py
│   │   │   │   ├── thesubdb.py
│   │   │   │   └── tvsubtitles.py
│   │   │   ├── refiners/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── hash.py
│   │   │   │   ├── metadata.py
│   │   │   │   ├── omdb.py
│   │   │   │   └── tvdb.py
│   │   │   ├── score.py
│   │   │   ├── subtitle.py
│   │   │   ├── utils.py
│   │   │   └── video.py
│   │   ├── transmissionrpc/
│   │   │   ├── __init__.py
│   │   │   ├── client.py
│   │   │   ├── constants.py
│   │   │   ├── error.py
│   │   │   ├── httphandler.py
│   │   │   ├── session.py
│   │   │   ├── torrent.py
│   │   │   └── utils.py
│   │   ├── typing_extensions.py
│   │   ├── unidecode/
│   │   │   ├── __init__.py
│   │   │   ├── __init__.pyi
│   │   │   ├── __main__.py
│   │   │   ├── py.typed
│   │   │   ├── util.py
│   │   │   ├── x000.py
│   │   │   ├── x001.py
│   │   │   ├── x002.py
│   │   │   ├── x003.py
│   │   │   ├── x004.py
│   │   │   ├── x005.py
│   │   │   ├── x006.py
│   │   │   ├── x007.py
│   │   │   ├── x009.py
│   │   │   ├── x00a.py
│   │   │   ├── x00b.py
│   │   │   ├── x00c.py
│   │   │   ├── x00d.py
│   │   │   ├── x00e.py
│   │   │   ├── x00f.py
│   │   │   ├── x010.py
│   │   │   ├── x011.py
│   │   │   ├── x012.py
│   │   │   ├── x013.py
│   │   │   ├── x014.py
│   │   │   ├── x015.py
│   │   │   ├── x016.py
│   │   │   ├── x017.py
│   │   │   ├── x018.py
│   │   │   ├── x01d.py
│   │   │   ├── x01e.py
│   │   │   ├── x01f.py
│   │   │   ├── x020.py
│   │   │   ├── x021.py
│   │   │   ├── x022.py
│   │   │   ├── x023.py
│   │   │   ├── x024.py
│   │   │   ├── x025.py
│   │   │   ├── x026.py
│   │   │   ├── x027.py
│   │   │   ├── x028.py
│   │   │   ├── x029.py
│   │   │   ├── x02a.py
│   │   │   ├── x02c.py
│   │   │   ├── x02e.py
│   │   │   ├── x02f.py
│   │   │   ├── x030.py
│   │   │   ├── x031.py
│   │   │   ├── x032.py
│   │   │   ├── x033.py
│   │   │   ├── x04d.py
│   │   │   ├── x04e.py
│   │   │   ├── x04f.py
│   │   │   ├── x050.py
│   │   │   ├── x051.py
│   │   │   ├── x052.py
│   │   │   ├── x053.py
│   │   │   ├── x054.py
│   │   │   ├── x055.py
│   │   │   ├── x056.py
│   │   │   ├── x057.py
│   │   │   ├── x058.py
│   │   │   ├── x059.py
│   │   │   ├── x05a.py
│   │   │   ├── x05b.py
│   │   │   ├── x05c.py
│   │   │   ├── x05d.py
│   │   │   ├── x05e.py
│   │   │   ├── x05f.py
│   │   │   ├── x060.py
│   │   │   ├── x061.py
│   │   │   ├── x062.py
│   │   │   ├── x063.py
│   │   │   ├── x064.py
│   │   │   ├── x065.py
│   │   │   ├── x066.py
│   │   │   ├── x067.py
│   │   │   ├── x068.py
│   │   │   ├── x069.py
│   │   │   ├── x06a.py
│   │   │   ├── x06b.py
│   │   │   ├── x06c.py
│   │   │   ├── x06d.py
│   │   │   ├── x06e.py
│   │   │   ├── x06f.py
│   │   │   ├── x070.py
│   │   │   ├── x071.py
│   │   │   ├── x072.py
│   │   │   ├── x073.py
│   │   │   ├── x074.py
│   │   │   ├── x075.py
│   │   │   ├── x076.py
│   │   │   ├── x077.py
│   │   │   ├── x078.py
│   │   │   ├── x079.py
│   │   │   ├── x07a.py
│   │   │   ├── x07b.py
│   │   │   ├── x07c.py
│   │   │   ├── x07d.py
│   │   │   ├── x07e.py
│   │   │   ├── x07f.py
│   │   │   ├── x080.py
│   │   │   ├── x081.py
│   │   │   ├── x082.py
│   │   │   ├── x083.py
│   │   │   ├── x084.py
│   │   │   ├── x085.py
│   │   │   ├── x086.py
│   │   │   ├── x087.py
│   │   │   ├── x088.py
│   │   │   ├── x089.py
│   │   │   ├── x08a.py
│   │   │   ├── x08b.py
│   │   │   ├── x08c.py
│   │   │   ├── x08d.py
│   │   │   ├── x08e.py
│   │   │   ├── x08f.py
│   │   │   ├── x090.py
│   │   │   ├── x091.py
│   │   │   ├── x092.py
│   │   │   ├── x093.py
│   │   │   ├── x094.py
│   │   │   ├── x095.py
│   │   │   ├── x096.py
│   │   │   ├── x097.py
│   │   │   ├── x098.py
│   │   │   ├── x099.py
│   │   │   ├── x09a.py
│   │   │   ├── x09b.py
│   │   │   ├── x09c.py
│   │   │   ├── x09d.py
│   │   │   ├── x09e.py
│   │   │   ├── x09f.py
│   │   │   ├── x0a0.py
│   │   │   ├── x0a1.py
│   │   │   ├── x0a2.py
│   │   │   ├── x0a3.py
│   │   │   ├── x0a4.py
│   │   │   ├── x0ac.py
│   │   │   ├── x0ad.py
│   │   │   ├── x0ae.py
│   │   │   ├── x0af.py
│   │   │   ├── x0b0.py
│   │   │   ├── x0b1.py
│   │   │   ├── x0b2.py
│   │   │   ├── x0b3.py
│   │   │   ├── x0b4.py
│   │   │   ├── x0b5.py
│   │   │   ├── x0b6.py
│   │   │   ├── x0b7.py
│   │   │   ├── x0b8.py
│   │   │   ├── x0b9.py
│   │   │   ├── x0ba.py
│   │   │   ├── x0bb.py
│   │   │   ├── x0bc.py
│   │   │   ├── x0bd.py
│   │   │   ├── x0be.py
│   │   │   ├── x0bf.py
│   │   │   ├── x0c0.py
│   │   │   ├── x0c1.py
│   │   │   ├── x0c2.py
│   │   │   ├── x0c3.py
│   │   │   ├── x0c4.py
│   │   │   ├── x0c5.py
│   │   │   ├── x0c6.py
│   │   │   ├── x0c7.py
│   │   │   ├── x0c8.py
│   │   │   ├── x0c9.py
│   │   │   ├── x0ca.py
│   │   │   ├── x0cb.py
│   │   │   ├── x0cc.py
│   │   │   ├── x0cd.py
│   │   │   ├── x0ce.py
│   │   │   ├── x0cf.py
│   │   │   ├── x0d0.py
│   │   │   ├── x0d1.py
│   │   │   ├── x0d2.py
│   │   │   ├── x0d3.py
│   │   │   ├── x0d4.py
│   │   │   ├── x0d5.py
│   │   │   ├── x0d6.py
│   │   │   ├── x0d7.py
│   │   │   ├── x0f9.py
│   │   │   ├── x0fa.py
│   │   │   ├── x0fb.py
│   │   │   ├── x0fc.py
│   │   │   ├── x0fd.py
│   │   │   ├── x0fe.py
│   │   │   ├── x0ff.py
│   │   │   ├── x1d4.py
│   │   │   ├── x1d5.py
│   │   │   ├── x1d6.py
│   │   │   ├── x1d7.py
│   │   │   ├── x1f1.py
│   │   │   └── x1f6.py
│   │   ├── urllib3/
│   │   │   ├── __init__.py
│   │   │   ├── _collections.py
│   │   │   ├── _version.py
│   │   │   ├── connection.py
│   │   │   ├── connectionpool.py
│   │   │   ├── contrib/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _appengine_environ.py
│   │   │   │   ├── _securetransport/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── bindings.py
│   │   │   │   │   └── low_level.py
│   │   │   │   ├── appengine.py
│   │   │   │   ├── ntlmpool.py
│   │   │   │   ├── pyopenssl.py
│   │   │   │   ├── securetransport.py
│   │   │   │   └── socks.py
│   │   │   ├── exceptions.py
│   │   │   ├── fields.py
│   │   │   ├── filepost.py
│   │   │   ├── packages/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── backports/
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   └── makefile.py
│   │   │   │   └── six.py
│   │   │   ├── poolmanager.py
│   │   │   ├── request.py
│   │   │   ├── response.py
│   │   │   └── util/
│   │   │       ├── __init__.py
│   │   │       ├── connection.py
│   │   │       ├── proxy.py
│   │   │       ├── queue.py
│   │   │       ├── request.py
│   │   │       ├── response.py
│   │   │       ├── retry.py
│   │   │       ├── ssl_.py
│   │   │       ├── ssl_match_hostname.py
│   │   │       ├── ssltransport.py
│   │   │       ├── timeout.py
│   │   │       ├── url.py
│   │   │       └── wait.py
│   │   ├── validate.py
│   │   ├── xdg/
│   │   │   ├── BaseDirectory.py
│   │   │   ├── Config.py
│   │   │   ├── DesktopEntry.py
│   │   │   ├── Exceptions.py
│   │   │   ├── IconTheme.py
│   │   │   ├── IniFile.py
│   │   │   ├── Locale.py
│   │   │   ├── Menu.py
│   │   │   ├── MenuEditor.py
│   │   │   ├── Mime.py
│   │   │   ├── RecentFiles.py
│   │   │   ├── __init__.py
│   │   │   └── util.py
│   │   ├── yaml/
│   │   │   ├── __init__.py
│   │   │   ├── composer.py
│   │   │   ├── constructor.py
│   │   │   ├── cyaml.py
│   │   │   ├── dumper.py
│   │   │   ├── emitter.py
│   │   │   ├── error.py
│   │   │   ├── events.py
│   │   │   ├── loader.py
│   │   │   ├── nodes.py
│   │   │   ├── parser.py
│   │   │   ├── reader.py
│   │   │   ├── representer.py
│   │   │   ├── resolver.py
│   │   │   ├── scanner.py
│   │   │   ├── serializer.py
│   │   │   └── tokens.py
│   │   └── zipp.py
│   ├── custom/
│   │   ├── deluge_client/
│   │   │   ├── __init__.py
│   │   │   ├── client.py
│   │   │   ├── rencode.py
│   │   │   └── tests.py
│   │   ├── syno/
│   │   │   ├── __init__.py
│   │   │   ├── auth.py
│   │   │   └── downloadstation.py
│   │   └── utorrent/
│   │       ├── __init__.py
│   │       ├── client.py
│   │       └── upload.py
│   ├── py2/
│   │   ├── backports/
│   │   │   ├── __init__.py
│   │   │   └── functools_lru_cache.py
│   │   ├── bs4/
│   │   │   ├── __init__.py
│   │   │   ├── builder/
│   │   │   │   ├── __init__.py
│   │   │   │   ├── _html5lib.py
│   │   │   │   ├── _htmlparser.py
│   │   │   │   └── _lxml.py
│   │   │   ├── dammit.py
│   │   │   ├── diagnose.py
│   │   │   ├── element.py
│   │   │   ├── testing.py
│   │   │   └── tests/
│   │   │       ├── __init__.py
│   │   │       ├── test_builder_registry.py
│   │   │       ├── test_docs.py
│   │   │       ├── test_html5lib.py
│   │   │       ├── test_htmlparser.py
│   │   │       ├── test_lxml.py
│   │   │       ├── test_soup.py
│   │   │       └── test_tree.py
│   │   ├── concurrent/
│   │   │   ├── __init__.py
│   │   │   └── futures/
│   │   │       ├── __init__.py
│   │   │       ├── _base.py
│   │   │       ├── process.py
│   │   │       └── thread.py
│   │   ├── enum/
│   │   │   ├── LICENSE
│   │   │   ├── README
│   │   │   └── __init__.py
│   │   └── yaml/
│   │       ├── __init__.py
│   │       ├── composer.py
│   │       ├── constructor.py
│   │       ├── cyaml.py
│   │       ├── dumper.py
│   │       ├── emitter.py
│   │       ├── error.py
│   │       ├── events.py
│   │       ├── loader.py
│   │       ├── nodes.py
│   │       ├── parser.py
│   │       ├── reader.py
│   │       ├── representer.py
│   │       ├── resolver.py
│   │       ├── scanner.py
│   │       ├── serializer.py
│   │       └── tokens.py
│   ├── requirements-common.txt
│   ├── requirements-custom.txt
│   ├── requirements-py2.txt
│   ├── requirements-win.txt
│   ├── requirements.txt
│   ├── util.py
│   └── win/
│       ├── autocommand/
│       │   ├── __init__.py
│       │   ├── autoasync.py
│       │   ├── autocommand.py
│       │   ├── automain.py
│       │   ├── autoparse.py
│       │   └── errors.py
│       ├── bugs/
│       │   ├── environ-api-wierdness.py
│       │   ├── find_target_path.py
│       │   ├── multi_os_libc.py
│       │   ├── vista-symlink-islink-bug.py
│       │   └── wnetaddconnection2-error-on-64-bit.py
│       ├── importlib_resources/
│       │   ├── __init__.py
│       │   ├── _adapters.py
│       │   ├── _common.py
│       │   ├── _compat.py
│       │   ├── _itertools.py
│       │   ├── _legacy.py
│       │   ├── abc.py
│       │   ├── py.typed
│       │   ├── readers.py
│       │   ├── simple.py
│       │   └── tests/
│       │       ├── __init__.py
│       │       ├── _compat.py
│       │       ├── _path.py
│       │       ├── data01/
│       │       │   ├── __init__.py
│       │       │   ├── binary.file
│       │       │   ├── subdirectory/
│       │       │   │   ├── __init__.py
│       │       │   │   └── binary.file
│       │       │   ├── utf-16.file
│       │       │   └── utf-8.file
│       │       ├── data02/
│       │       │   ├── __init__.py
│       │       │   ├── one/
│       │       │   │   ├── __init__.py
│       │       │   │   └── resource1.txt
│       │       │   └── two/
│       │       │       ├── __init__.py
│       │       │       └── resource2.txt
│       │       ├── namespacedata01/
│       │       │   ├── binary.file
│       │       │   ├── utf-16.file
│       │       │   └── utf-8.file
│       │       ├── test_compatibilty_files.py
│       │       ├── test_contents.py
│       │       ├── test_files.py
│       │       ├── test_open.py
│       │       ├── test_path.py
│       │       ├── test_read.py
│       │       ├── test_reader.py
│       │       ├── test_resource.py
│       │       ├── update-zips.py
│       │       ├── util.py
│       │       ├── zipdata01/
│       │       │   └── __init__.py
│       │       └── zipdata02/
│       │           └── __init__.py
│       ├── incubator/
│       │   ├── replace-file.py
│       │   └── trace-symlink.py
│       ├── inflect/
│       │   ├── __init__.py
│       │   └── py.typed
│       ├── jaraco/
│       │   ├── classes/
│       │   │   ├── __init__.py
│       │   │   ├── ancestry.py
│       │   │   ├── meta.py
│       │   │   └── properties.py
│       │   ├── collections.py
│       │   ├── context.py
│       │   ├── functools.py
│       │   ├── structures/
│       │   │   ├── __init__.py
│       │   │   └── binary.py
│       │   ├── text/
│       │   │   ├── Lorem ipsum.txt
│       │   │   ├── __init__.py
│       │   │   ├── layouts.py
│       │   │   ├── show-newlines.py
│       │   │   ├── strip-prefix.py
│       │   │   ├── to-dvorak.py
│       │   │   └── to-qwerty.py
│       │   ├── ui/
│       │   │   ├── __init__.py
│       │   │   ├── cmdline.py
│       │   │   ├── editor.py
│       │   │   ├── input.py
│       │   │   ├── menu.py
│       │   │   └── progress.py
│       │   └── windows/
│       │       ├── __init__.py
│       │       ├── api/
│       │       │   ├── __init__.py
│       │       │   ├── clipboard.py
│       │       │   ├── credential.py
│       │       │   ├── environ.py
│       │       │   ├── errors.py
│       │       │   ├── event.py
│       │       │   ├── filesystem.py
│       │       │   ├── inet.py
│       │       │   ├── library.py
│       │       │   ├── memory.py
│       │       │   ├── message.py
│       │       │   ├── net.py
│       │       │   ├── power.py
│       │       │   ├── privilege.py
│       │       │   ├── process.py
│       │       │   ├── security.py
│       │       │   ├── shell.py
│       │       │   ├── system.py
│       │       │   └── user.py
│       │       ├── batch.py
│       │       ├── clipboard.py
│       │       ├── cred.py
│       │       ├── dpapi.py
│       │       ├── environ.py
│       │       ├── error.py
│       │       ├── eventlog.py
│       │       ├── filesystem/
│       │       │   ├── __init__.py
│       │       │   ├── backports.py
│       │       │   └── change.py
│       │       ├── inet.py
│       │       ├── lib.py
│       │       ├── memory.py
│       │       ├── mmap.py
│       │       ├── msie.py
│       │       ├── msvc.py
│       │       ├── net.py
│       │       ├── power.py
│       │       ├── privilege.py
│       │       ├── registry.py
│       │       ├── reparse.py
│       │       ├── security.py
│       │       ├── services.py
│       │       ├── shell.py
│       │       ├── timers.py
│       │       ├── timezone.py
│       │       ├── ui.py
│       │       ├── user.py
│       │       ├── util.py
│       │       ├── vpn.py
│       │       └── xmouse.py
│       ├── more_itertools/
│       │   ├── __init__.py
│       │   ├── __init__.pyi
│       │   ├── more.py
│       │   ├── more.pyi
│       │   ├── py.typed
│       │   ├── recipes.py
│       │   └── recipes.pyi
│       ├── path/
│       │   ├── __init__.py
│       │   ├── __init__.pyi
│       │   ├── classes.py
│       │   ├── classes.pyi
│       │   ├── masks.py
│       │   ├── masks.pyi
│       │   ├── matchers.py
│       │   ├── matchers.pyi
│       │   ├── py.typed
│       │   ├── py37compat.py
│       │   └── py37compat.pyi
│       ├── pydantic/
│       │   ├── __init__.py
│       │   ├── _hypothesis_plugin.py
│       │   ├── annotated_types.py
│       │   ├── class_validators.py
│       │   ├── color.py
│       │   ├── config.py
│       │   ├── dataclasses.py
│       │   ├── datetime_parse.py
│       │   ├── decorator.py
│       │   ├── env_settings.py
│       │   ├── error_wrappers.py
│       │   ├── errors.py
│       │   ├── fields.py
│       │   ├── generics.py
│       │   ├── json.py
│       │   ├── main.py
│       │   ├── mypy.py
│       │   ├── networks.py
│       │   ├── parse.py
│       │   ├── py.typed
│       │   ├── schema.py
│       │   ├── tools.py
│       │   ├── types.py
│       │   ├── typing.py
│       │   ├── utils.py
│       │   ├── validators.py
│       │   └── version.py
│       ├── scripts/
│       │   └── watch-changes.py
│       ├── typing_extensions.py
│       └── zipp/
│           ├── __init__.py
│           └── py310compat.py
├── license.txt
├── nzbToCouchPotato.py
├── nzbToGamez.py
├── nzbToHeadPhones.py
├── nzbToLazyLibrarian.py
├── nzbToLidarr.py
├── nzbToMedia.py
├── nzbToMylar.py
├── nzbToNzbDrone.py
├── nzbToRadarr.py
├── nzbToReadarr.py
├── nzbToSiCKRAGE.py
├── nzbToSickBeard.py
├── nzbToWatcher3.py
├── setup.py
├── tests/
│   ├── __init__.py
│   ├── test_initialize.py
│   └── test_transcoder.py
└── tox.ini
Download .txt
Showing preview only (1,491K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (19992 symbols across 1012 files)

FILE: TorrentToMedia.py
  function process_torrent (line 34) | def process_torrent(input_directory, input_name, input_category, input_h...
  function main (line 292) | def main(args):

FILE: cleanup.py
  class WorkingDirectory (line 34) | class WorkingDirectory(object):
    method __init__ (line 37) | def __init__(self, new, original=None):
    method __enter__ (line 41) | def __enter__(self):
    method __exit__ (line 45) | def __exit__(self, exc_type, exc_val, exc_tb):
  function module_path (line 59) | def module_path(module=__file__, parent=False):
  function git_clean (line 79) | def git_clean(remove_directories=False, force=False, dry_run=False, inte...
  function clean_bytecode (line 113) | def clean_bytecode():
  function clean_folders (line 135) | def clean_folders(*paths):
  function force_clean_folder (line 152) | def force_clean_folder(path, required):
  function clean (line 173) | def clean(paths):

FILE: core/__init__.py
  function configure_logging (line 283) | def configure_logging():
  function configure_process (line 295) | def configure_process():
  function configure_locale (line 304) | def configure_locale():
  function configure_migration (line 335) | def configure_migration():
  function configure_logging_part_2 (line 356) | def configure_logging_part_2():
  function configure_general (line 373) | def configure_general():
  function configure_updates (line 402) | def configure_updates():
  function configure_wake_on_lan (line 428) | def configure_wake_on_lan():
  function configure_groups (line 433) | def configure_groups():
  function configure_remote_paths (line 445) | def configure_remote_paths():
  function configure_niceness (line 467) | def configure_niceness():
  function configure_containers (line 496) | def configure_containers():
  function configure_transcoder (line 524) | def configure_transcoder():
  function configure_passwords_file (line 866) | def configure_passwords_file():
  function configure_sections (line 872) | def configure_sections(section):
  function configure_utility_locations (line 885) | def configure_utility_locations():
  function check_python (line 983) | def check_python():
  function initialize (line 1014) | def initialize(section=None):

FILE: core/auto_process/books.py
  function process (line 25) | def process(section, dir_name, input_name=None, status=0, client_agent='...

FILE: core/auto_process/comics.py
  function process (line 22) | def process(section, dir_name, input_name=None, status=0, client_agent='...

FILE: core/auto_process/common.py
  class ProcessResult (line 13) | class ProcessResult(object):
    method __init__ (line 14) | def __init__(self, message, status_code):
    method __iter__ (line 18) | def __iter__(self):
    method __bool__ (line 21) | def __bool__(self):
    method __str__ (line 24) | def __str__(self):
    method __repr__ (line 30) | def __repr__(self):
  function command_complete (line 37) | def command_complete(url, params, headers, section):
  function completed_download_handling (line 55) | def completed_download_handling(url2, headers, section='MAIN'):

FILE: core/auto_process/games.py
  function process (line 23) | def process(section, dir_name, input_name=None, status=0, client_agent='...

FILE: core/auto_process/managers/pymedusa.py
  class PyMedusa (line 10) | class PyMedusa(SickBeard):
    method __init__ (line 13) | def __init__(self, sb_init):
    method _create_url (line 16) | def _create_url(self):
  class PyMedusaApiV1 (line 20) | class PyMedusaApiV1(SickBeard):
    method __init__ (line 23) | def __init__(self, sb_init):
    method _create_url (line 26) | def _create_url(self):
    method api_call (line 29) | def api_call(self):
  class PyMedusaApiV2 (line 61) | class PyMedusaApiV2(SickBeard):
    method __init__ (line 64) | def __init__(self, sb_init):
    method _create_url (line 71) | def _create_url(self):
    method _get_identifier_status (line 74) | def _get_identifier_status(self, url):
    method api_call (line 89) | def api_call(self):

FILE: core/auto_process/managers/sickbeard.py
  class InitSickBeard (line 29) | class InitSickBeard(object):
    method __init__ (line 35) | def __init__(self, cfg, section, input_category):
    method auto_fork (line 73) | def auto_fork(self):
    method _api_check (line 180) | def _api_check(r, params, rem_params):
    method detect_fork (line 215) | def detect_fork(self):
    method _init_fork (line 300) | def _init_fork(self):
  class SickBeard (line 319) | class SickBeard(object):
    method __init__ (line 322) | def __init__(self, sb_init):
    method initialize (line 348) | def initialize(self, dir_name, input_name=None, failed=False, client_a...
    method _create_url (line 364) | def _create_url(self):
    method _process_fork_prarams (line 369) | def _process_fork_prarams(self):
    method api_call (line 442) | def api_call(self):
    method process_response (line 474) | def process_response(self, response):

FILE: core/auto_process/movies.py
  function process (line 39) | def process(section, dir_name, input_name=None, status=0, client_agent='...
  function get_release (line 492) | def get_release(base_url, imdb_id=None, download_id=None, release_id=None):

FILE: core/auto_process/music.py
  function process (line 25) | def process(section, dir_name, input_name=None, status=0, client_agent='...
  function get_status (line 192) | def get_status(url, apikey, dir_name):
  function force_process (line 219) | def force_process(params, url, apikey, input_name, dir_name, section, wa...

FILE: core/auto_process/tv.py
  function process (line 44) | def process(section, dir_name, input_name=None, failed=False, client_age...

FILE: core/configuration.py
  class Section (line 22) | class Section(configobj.Section, object):
    method isenabled (line 23) | def isenabled(self):
    method findsection (line 50) | def findsection(self, key):
    method __getitem__ (line 71) | def __getitem__(self, key):
  class ConfigObj (line 98) | class ConfigObj(configobj.ConfigObj, Section):
    method __init__ (line 99) | def __init__(self, *args, **kw):
    method find_key (line 106) | def find_key(node, kv):
    method migrate (line 119) | def migrate():
    method addnzbget (line 287) | def addnzbget():

FILE: core/databases.py
  function backup_database (line 17) | def backup_database(version):
  class InitialSchema (line 30) | class InitialSchema(main_db.SchemaUpgrade):
    method test (line 31) | def test(self):
    method execute (line 38) | def execute(self):

FILE: core/extractor/__init__.py
  function extract (line 21) | def extract(file_path, output_destination):

FILE: core/github_api.py
  class GitHub (line 13) | class GitHub(object):
    method __init__ (line 16) | def __init__(self, github_repo_user, github_repo, branch='master'):
    method _access_api (line 22) | def _access_api(self, path, params=None):
    method commits (line 28) | def commits(self):
    method compare (line 43) | def compare(self, base, head, per_page=1):

FILE: core/logger.py
  class NTMRotatingLogHandler (line 39) | class NTMRotatingLogHandler(object):
    method __init__ (line 40) | def __init__(self, log_file, num_files, num_bytes):
    method close_log (line 53) | def close_log(self, handler=None):
    method init_logging (line 69) | def init_logging(self, console_logging=True):
    method _config_handler (line 121) | def _config_handler(self):
    method _log_file_name (line 136) | def _log_file_name(self, i):
    method _num_logs (line 147) | def _num_logs(self):
    method _rotate_logs (line 158) | def _rotate_logs(self):
    method log (line 188) | def log(self, to_log, log_level=MESSAGE, section='MAIN'):
    method log_error_and_exit (line 232) | def log_error_and_exit(self, error_msg):
  class DispatchingFormatter (line 243) | class DispatchingFormatter(object):
    method __init__ (line 244) | def __init__(self, formatters, default_formatter):
    method format (line 248) | def format(self, record):
  function log (line 256) | def log(to_log, log_level=MESSAGE, section='MAIN'):
  function info (line 260) | def info(to_log, section='MAIN'):
  function error (line 264) | def error(to_log, section='MAIN'):
  function warning (line 268) | def warning(to_log, section='MAIN'):
  function debug (line 272) | def debug(to_log, section='MAIN'):
  function postprocess (line 276) | def postprocess(to_log, section='POSTPROCESS'):
  function db (line 280) | def db(to_log, section='DB'):
  function log_error_and_exit (line 284) | def log_error_and_exit(error_msg):
  function close (line 288) | def close():

FILE: core/main_db.py
  class Row (line 23) | class Row(sqlite3.Row, object):
    method __getitem__ (line 31) | def __getitem__(self, item):
  function db_filename (line 49) | def db_filename(filename='nzbtomedia.db', suffix=None):
  class DBConnection (line 64) | class DBConnection(object):
    method __init__ (line 65) | def __init__(self, filename='nzbtomedia.db', suffix=None, row_type=None):
    method check_db_version (line 90) | def check_db_version(self):
    method fetch (line 103) | def fetch(self, query, args=None):
    method mass_action (line 140) | def mass_action(self, querylist, log_transaction=False):
    method action (line 180) | def action(self, query, args=None):
    method select (line 213) | def select(self, query, args=None):
    method upsert (line 222) | def upsert(self, table_name, value_dict, key_dict):
    method table_info (line 254) | def table_info(self, table_name):
  function sanity_check_database (line 263) | def sanity_check_database(connection, sanity_check):
  class DBSanityCheck (line 267) | class DBSanityCheck(object):
    method __init__ (line 268) | def __init__(self, connection):
    method check (line 271) | def check(self):
  function upgrade_database (line 279) | def upgrade_database(connection, schema):
  function pretty_name (line 288) | def pretty_name(class_name):
  function _process_upgrade (line 292) | def _process_upgrade(connection, upgrade_class):
  class SchemaUpgrade (line 316) | class SchemaUpgrade(object):
    method __init__ (line 317) | def __init__(self, connection):
    method has_table (line 320) | def has_table(self, table_name):
    method has_column (line 323) | def has_column(self, table_name, column):
    method add_column (line 326) | def add_column(self, table, column, data_type='NUMERIC', default=0):
    method check_db_version (line 330) | def check_db_version(self):
    method inc_db_version (line 337) | def inc_db_version(self):

FILE: core/permissions.py
  function mode (line 29) | def mode(path):
  function nt_ownership (line 41) | def nt_ownership(path):
  function posix_ownership (line 72) | def posix_ownership(path):

FILE: core/plugins/downloaders/nzb/configuration.py
  function configure_nzbs (line 11) | def configure_nzbs(config):
  function configure_sabnzbd (line 20) | def configure_sabnzbd(config):

FILE: core/plugins/downloaders/nzb/utils.py
  function get_nzoid (line 16) | def get_nzoid(input_name):
  function report_nzb (line 64) | def report_nzb(failure_link, client_agent):

FILE: core/plugins/downloaders/torrent/configuration.py
  function configure_torrents (line 12) | def configure_torrents(config):
  function configure_torrent_linking (line 32) | def configure_torrent_linking(config):
  function configure_flattening (line 36) | def configure_flattening(config):
  function configure_torrent_categories (line 42) | def configure_torrent_categories(config):
  function configure_torrent_resuming (line 48) | def configure_torrent_resuming(config):
  function configure_torrent_permissions (line 53) | def configure_torrent_permissions(config):
  function configure_torrent_deletion (line 57) | def configure_torrent_deletion(config):
  function configure_utorrent (line 61) | def configure_utorrent(config):
  function configure_transmission (line 67) | def configure_transmission(config):
  function configure_syno (line 74) | def configure_syno(config):
  function configure_deluge (line 81) | def configure_deluge(config):
  function configure_qbittorrent (line 88) | def configure_qbittorrent(config):
  function configure_torrent_class (line 95) | def configure_torrent_class():

FILE: core/plugins/downloaders/torrent/deluge.py
  function configure_client (line 14) | def configure_client():

FILE: core/plugins/downloaders/torrent/qbittorrent.py
  function configure_client (line 15) | def configure_client():

FILE: core/plugins/downloaders/torrent/synology.py
  function configure_client (line 14) | def configure_client():

FILE: core/plugins/downloaders/torrent/transmission.py
  function configure_client (line 14) | def configure_client():

FILE: core/plugins/downloaders/torrent/utils.py
  function create_torrent_class (line 28) | def create_torrent_class(client_agent):
  function pause_torrent (line 37) | def pause_torrent(client_agent, input_hash, input_id, input_name):
  function resume_torrent (line 55) | def resume_torrent(client_agent, input_hash, input_id, input_name):
  function remove_torrent (line 75) | def remove_torrent(client_agent, input_hash, input_id, input_name):

FILE: core/plugins/downloaders/torrent/utorrent.py
  function configure_client (line 14) | def configure_client():

FILE: core/plugins/plex.py
  function configure_plex (line 14) | def configure_plex(config):
  function plex_update (line 32) | def plex_update(category):

FILE: core/plugins/subtitles.py
  function import_subs (line 22) | def import_subs(filename):
  function rename_subs (line 51) | def rename_subs(path):

FILE: core/processor/manual.py
  function process (line 18) | def process():

FILE: core/processor/nzb.py
  function process (line 24) | def process(input_directory, input_name=None, status=0, client_agent='ma...

FILE: core/processor/nzbget.py
  function parse_download_id (line 9) | def parse_download_id():
  function parse_failure_link (line 27) | def parse_failure_link():
  function _parse_total_status (line 32) | def _parse_total_status():
  function _parse_par_status (line 41) | def _parse_par_status():
  function _parse_unpack_status (line 50) | def _parse_unpack_status():
  function _parse_health_status (line 57) | def _parse_health_status():
  function parse_status (line 74) | def parse_status():
  function check_version (line 85) | def check_version():
  function process (line 95) | def process():

FILE: core/processor/sab.py
  function process_script (line 10) | def process_script():
  function process (line 24) | def process(args):

FILE: core/scene_exceptions.py
  function process_all_exceptions (line 39) | def process_all_exceptions(name, dirname):
  function strip_groups (line 61) | def strip_groups(filename):
  function rename_file (line 75) | def rename_file(filename, newfile_path):
  function replace_filename (line 86) | def replace_filename(filename, dirname, name):
  function reverse_filename (line 103) | def reverse_filename(filename, dirname, name):
  function rename_script (line 129) | def rename_script(dirname):
  function par2 (line 157) | def par2(dirname):

FILE: core/transcoder.py
  function is_video_good (line 30) | def is_video_good(videofile, status, require_lan=None):
  function zip_out (line 86) | def zip_out(file, img, bitbucket):
  function get_video_details (line 99) | def get_video_details(videofile, img=None, bitbucket=None):
  function check_vid_file (line 147) | def check_vid_file(video_details, result):
  function build_commands (line 162) | def build_commands(file, new_dir, movie_name, bitbucket):
  function get_subs (line 572) | def get_subs(file):
  function extract_subs (line 584) | def extract_subs(file, newfile_path, bitbucket):
  function process_list (line 643) | def process_list(it, new_dir, bitbucket):
  function mount_iso (line 701) | def mount_iso(item, new_dir, bitbucket): #Currently only supports Linux ...
  function rip_iso (line 733) | def rip_iso(item, new_dir, bitbucket):
  function combine_vts (line 819) | def combine_vts(vts_path):
  function combine_mts (line 851) | def combine_mts(mts_path):
  function combine_cd (line 881) | def combine_cd(combine):
  function print_cmd (line 897) | def print_cmd(command):
  function transcode_directory (line 904) | def transcode_directory(dir_name):

FILE: core/user_scripts.py
  function external_script (line 23) | def external_script(output_destination, torrent_name, torrent_label, set...

FILE: core/utils/common.py
  function flatten (line 18) | def flatten(output_destination):
  function clean_dir (line 22) | def clean_dir(path, section, subsection):
  function process_dir (line 33) | def process_dir(path, link):
  function get_dirs (line 95) | def get_dirs(section, subsection, link='hard'):

FILE: core/utils/download_info.py
  function update_download_info_status (line 17) | def update_download_info_status(input_name, status):
  function get_download_info (line 25) | def get_download_info(input_name, status):

FILE: core/utils/encoding.py
  function char_replace (line 20) | def char_replace(name_in):
  function convert_to_ascii (line 95) | def convert_to_ascii(input_name, dir_name):

FILE: core/utils/files.py
  function move_file (line 25) | def move_file(mediafile, path, link):
  function is_min_size (line 81) | def is_min_size(input_name, min_size):
  function is_archive_file (line 98) | def is_archive_file(filename):
  function is_media_file (line 106) | def is_media_file(mediafile, media=True, audio=True, meta=True, archives...
  function list_media_files (line 128) | def list_media_files(path, min_size=0, delete_ignored=0, media=True, aud...
  function extract_files (line 175) | def extract_files(src, dst=None, keep_archive=None):
  function backup_versioned_file (line 212) | def backup_versioned_file(old_file, version):

FILE: core/utils/identification.py
  function find_imdbid (line 19) | def find_imdbid(dir_name, input_name, omdb_api_key):
  function category_search (line 98) | def category_search(input_directory, input_name, input_category, root, c...

FILE: core/utils/links.py
  function copy_link (line 26) | def copy_link(src, target_link, use_link):
  function replace_links (line 77) | def replace_links(link, max_depth=10):

FILE: core/utils/naming.py
  function sanitize_name (line 11) | def sanitize_name(name):
  function clean_file_name (line 33) | def clean_file_name(filename):
  function is_sample (line 50) | def is_sample(input_name):

FILE: core/utils/network.py
  function make_wake_on_lan_packet (line 18) | def make_wake_on_lan_packet(mac_address):
  function wake_on_lan (line 30) | def wake_on_lan(ethernet_address):
  function test_connection (line 43) | def test_connection(host, port):
  function wake_up (line 54) | def wake_up():
  function server_responding (line 78) | def server_responding(base_url):
  function find_download (line 90) | def find_download(client_agent, download_id):

FILE: core/utils/parsers.py
  function parse_other (line 14) | def parse_other(args):
  function parse_rtorrent (line 18) | def parse_rtorrent(args):
  function parse_utorrent (line 42) | def parse_utorrent(args):
  function parse_deluge (line 62) | def parse_deluge(args):
  function parse_transmission (line 75) | def parse_transmission(args):
  function parse_synods (line 85) | def parse_synods(args):
  function parse_vuze (line 115) | def parse_vuze(args):
  function parse_qbittorrent (line 150) | def parse_qbittorrent(args):
  function parse_args (line 184) | def parse_args(client_agent, args):

FILE: core/utils/paths.py
  function onerror (line 20) | def onerror(func, path, exc_info):
  function remove_dir (line 39) | def remove_dir(dir_name):
  function make_dir (line 47) | def make_dir(path):
  function remote_dir (line 56) | def remote_dir(path):
  function get_dir_size (line 74) | def get_dir_size(input_path):
  function remove_empty_folders (line 82) | def remove_empty_folders(path, remove_root=True):
  function remove_read_only (line 103) | def remove_read_only(filename):
  function flatten_dir (line 117) | def flatten_dir(destination, files):
  function clean_directory (line 136) | def clean_directory(path, files):
  function rchmod (line 160) | def rchmod(path, mod):

FILE: core/utils/processes.py
  class WindowsProcess (line 22) | class WindowsProcess(object):
    method __init__ (line 23) | def __init__(self):
    method alreadyrunning (line 31) | def alreadyrunning(self):
    method __del__ (line 40) | def __del__(self):
  class PosixProcess (line 45) | class PosixProcess(object):
    method __init__ (line 46) | def __init__(self):
    method alreadyrunning (line 50) | def alreadyrunning(self):
    method __del__ (line 91) | def __del__(self):
  function restart (line 105) | def restart():

FILE: core/utils/shutil_custom.py
  function monkey_patch (line 13) | def monkey_patch(length=512 * 1024):

FILE: core/version_check.py
  class CheckVersion (line 28) | class CheckVersion(object):
    method __init__ (line 31) | def __init__(self):
    method run (line 43) | def run(self):
    method find_install_type (line 46) | def find_install_type(self):
    method check_for_new_version (line 63) | def check_for_new_version(self, force=False):
    method update (line 84) | def update(self):
  class UpdateManager (line 91) | class UpdateManager(object):
    method get_github_repo_user (line 92) | def get_github_repo_user(self):
    method get_github_repo (line 95) | def get_github_repo(self):
    method get_github_branch (line 98) | def get_github_branch(self):
  class GitUpdateManager (line 102) | class GitUpdateManager(UpdateManager):
    method __init__ (line 103) | def __init__(self):
    method _git_error (line 114) | def _git_error(self):
    method _find_working_git (line 118) | def _find_working_git(self):
    method _run_git (line 169) | def _run_git(self, git_path, args):
    method _find_installed_version (line 215) | def _find_installed_version(self):
    method _find_git_branch (line 237) | def _find_git_branch(self):
    method _check_github_for_update (line 247) | def _check_github_for_update(self):
    method set_newest_text (line 300) | def set_newest_text(self):
    method need_update (line 310) | def need_update(self):
    method update (line 329) | def update(self):
  class SourceUpdateManager (line 344) | class SourceUpdateManager(UpdateManager):
    method __init__ (line 345) | def __init__(self):
    method _find_installed_version (line 354) | def _find_installed_version(self):
    method need_update (line 373) | def need_update(self):
    method _check_github_for_update (line 388) | def _check_github_for_update(self):
    method set_newest_text (line 431) | def set_newest_text(self):
    method update (line 444) | def update(self):

FILE: eol.py
  function date (line 17) | def date(string, fmt='%Y-%m-%d'):
  class Error (line 52) | class Error(Exception):
  class LifetimeError (line 56) | class LifetimeError(Error):
  class LifetimeWarning (line 60) | class LifetimeWarning(Warning):
  function lifetime (line 64) | def lifetime(version=None):
  function expiration (line 81) | def expiration(version=None, grace_period=0):
  function check (line 94) | def check(version=None, grace_period=0):
  function raise_for_status (line 113) | def raise_for_status(version=None, grace_period=0):
  function warn_for_status (line 136) | def warn_for_status(version=None, grace_period=0):
  function print_statuses (line 157) | def print_statuses(show_expired=False):

FILE: libs/__init__.py
  function add_libs (line 39) | def add_libs(name):
  function add_all_libs (line 48) | def add_all_libs():
  function is_finished (line 56) | def is_finished():

FILE: libs/common/appdirs.py
  function user_data_dir (line 45) | def user_data_dir(appname=None, appauthor=None, version=None, roaming=Fa...
  function site_data_dir (line 100) | def site_data_dir(appname=None, appauthor=None, version=None, multipath=...
  function user_config_dir (line 166) | def user_config_dir(appname=None, appauthor=None, version=None, roaming=...
  function site_config_dir (line 206) | def site_config_dir(appname=None, appauthor=None, version=None, multipat...
  function user_cache_dir (line 257) | def user_cache_dir(appname=None, appauthor=None, version=None, opinion=T...
  function user_state_dir (line 314) | def user_state_dir(appname=None, appauthor=None, version=None, roaming=F...
  function user_log_dir (line 356) | def user_log_dir(appname=None, appauthor=None, version=None, opinion=True):
  class AppDirs (line 407) | class AppDirs(object):
    method __init__ (line 409) | def __init__(self, appname=None, appauthor=None, version=None,
    method user_data_dir (line 418) | def user_data_dir(self):
    method site_data_dir (line 423) | def site_data_dir(self):
    method user_config_dir (line 428) | def user_config_dir(self):
    method site_config_dir (line 433) | def site_config_dir(self):
    method user_cache_dir (line 438) | def user_cache_dir(self):
    method user_state_dir (line 443) | def user_state_dir(self):
    method user_log_dir (line 448) | def user_log_dir(self):
  function _get_win_folder_from_registry (line 455) | def _get_win_folder_from_registry(csidl_name):
  function _get_win_folder_with_pywin32 (line 479) | def _get_win_folder_with_pywin32(csidl_name):
  function _get_win_folder_with_ctypes (line 506) | def _get_win_folder_with_ctypes(csidl_name):
  function _get_win_folder_with_jna (line 532) | def _get_win_folder_with_jna(csidl_name):

FILE: libs/common/babelfish/converters/__init__.py
  class CaseInsensitiveDict (line 16) | class CaseInsensitiveDict(MutableMapping):
    method __init__ (line 39) | def __init__(self, data=None, **kwargs):
    method __setitem__ (line 45) | def __setitem__(self, key, value):
    method __getitem__ (line 50) | def __getitem__(self, key):
    method __delitem__ (line 53) | def __delitem__(self, key):
    method __iter__ (line 56) | def __iter__(self):
    method __len__ (line 59) | def __len__(self):
    method lower_items (line 62) | def lower_items(self):
    method __eq__ (line 70) | def __eq__(self, other):
    method copy (line 79) | def copy(self):
    method __repr__ (line 82) | def __repr__(self):
  class LanguageConverter (line 86) | class LanguageConverter(object):
    method convert (line 95) | def convert(self, alpha3, country=None, script=None):
  class LanguageReverseConverter (line 112) | class LanguageReverseConverter(LanguageConverter):
    method reverse (line 117) | def reverse(self, code):
  class LanguageEquivalenceConverter (line 129) | class LanguageEquivalenceConverter(LanguageReverseConverter):
    method __init__ (line 147) | def __init__(self):
    method convert (line 160) | def convert(self, alpha3, country=None, script=None):
    method reverse (line 166) | def reverse(self, code):
  class CountryConverter (line 173) | class CountryConverter(object):
    method convert (line 182) | def convert(self, alpha2):
  class CountryReverseConverter (line 194) | class CountryReverseConverter(CountryConverter):
    method reverse (line 199) | def reverse(self, code):
  class ConverterManager (line 211) | class ConverterManager(object):
    method __init__ (line 232) | def __init__(self):
    method __getitem__ (line 239) | def __getitem__(self, name):
    method __setitem__ (line 260) | def __setitem__(self, name, converter):
    method __delitem__ (line 264) | def __delitem__(self, name):
    method __iter__ (line 268) | def __iter__(self):
    method register (line 272) | def register(self, entry_point):
    method unregister (line 283) | def unregister(self, entry_point):
    method __contains__ (line 291) | def __contains__(self, name):

FILE: libs/common/babelfish/converters/alpha2.py
  class Alpha2Converter (line 12) | class Alpha2Converter(LanguageEquivalenceConverter):

FILE: libs/common/babelfish/converters/alpha3b.py
  class Alpha3BConverter (line 12) | class Alpha3BConverter(LanguageEquivalenceConverter):

FILE: libs/common/babelfish/converters/alpha3t.py
  class Alpha3TConverter (line 12) | class Alpha3TConverter(LanguageEquivalenceConverter):

FILE: libs/common/babelfish/converters/countryname.py
  class CountryNameConverter (line 13) | class CountryNameConverter(CountryReverseConverter):
    method __init__ (line 14) | def __init__(self):
    method convert (line 23) | def convert(self, alpha2):
    method reverse (line 28) | def reverse(self, name):

FILE: libs/common/babelfish/converters/name.py
  class NameConverter (line 12) | class NameConverter(LanguageEquivalenceConverter):

FILE: libs/common/babelfish/converters/opensubtitles.py
  class OpenSubtitlesConverter (line 13) | class OpenSubtitlesConverter(LanguageReverseConverter):
    method __init__ (line 14) | def __init__(self):
    method convert (line 22) | def convert(self, alpha3, country=None, script=None):
    method reverse (line 28) | def reverse(self, opensubtitles):

FILE: libs/common/babelfish/converters/scope.py
  class ScopeConverter (line 13) | class ScopeConverter(LanguageConverter):
    method convert (line 20) | def convert(self, alpha3, country=None, script=None):

FILE: libs/common/babelfish/converters/type.py
  class LanguageTypeConverter (line 13) | class LanguageTypeConverter(LanguageConverter):
    method convert (line 20) | def convert(self, alpha3, country=None, script=None):

FILE: libs/common/babelfish/country.py
  class CountryConverterManager (line 30) | class CountryConverterManager(ConverterManager):
  class CountryMeta (line 38) | class CountryMeta(type):
    method __getattr__ (line 44) | def __getattr__(cls, name):
  class Country (line 50) | class Country(CountryMeta(str('CountryBase'), (object,), {})):
    method __init__ (line 58) | def __init__(self, country):
    method fromcode (line 66) | def fromcode(cls, code, converter):
    method __getstate__ (line 78) | def __getstate__(self):
    method __setstate__ (line 81) | def __setstate__(self, state):
    method __getattr__ (line 84) | def __getattr__(self, name):
    method __hash__ (line 90) | def __hash__(self):
    method __eq__ (line 93) | def __eq__(self, other):
    method __ne__ (line 100) | def __ne__(self, other):
    method __repr__ (line 103) | def __repr__(self):
    method __str__ (line 106) | def __str__(self):

FILE: libs/common/babelfish/exceptions.py
  class Error (line 10) | class Error(Exception):
  class LanguageError (line 15) | class LanguageError(Error, AttributeError):
  class LanguageConvertError (line 20) | class LanguageConvertError(LanguageError):
    method __init__ (line 30) | def __init__(self, alpha3, country=None, script=None):
    method __str__ (line 35) | def __str__(self):
  class LanguageReverseError (line 44) | class LanguageReverseError(LanguageError):
    method __init__ (line 50) | def __init__(self, code):
    method __str__ (line 53) | def __str__(self):
  class CountryError (line 57) | class CountryError(Error, AttributeError):
  class CountryConvertError (line 62) | class CountryConvertError(CountryError):
    method __init__ (line 68) | def __init__(self, alpha2):
    method __str__ (line 71) | def __str__(self):
  class CountryReverseError (line 75) | class CountryReverseError(CountryError):
    method __init__ (line 81) | def __init__(self, code):
    method __str__ (line 84) | def __str__(self):

FILE: libs/common/babelfish/language.py
  class LanguageConverterManager (line 33) | class LanguageConverterManager(ConverterManager):
  class LanguageMeta (line 47) | class LanguageMeta(type):
    method __getattr__ (line 53) | def __getattr__(cls, name):
  class Language (line 59) | class Language(LanguageMeta(str('LanguageBase'), (object,), {})):
    method __init__ (line 78) | def __init__(self, language, country=None, script=None, unknown=None):
    method fromcode (line 100) | def fromcode(cls, code, converter):
    method fromietf (line 113) | def fromietf(cls, ietf):
    method __getstate__ (line 139) | def __getstate__(self):
    method __setstate__ (line 142) | def __setstate__(self, state):
    method __getattr__ (line 145) | def __getattr__(self, name):
    method __hash__ (line 154) | def __hash__(self):
    method __eq__ (line 157) | def __eq__(self, other):
    method __ne__ (line 166) | def __ne__(self, other):
    method __bool__ (line 169) | def __bool__(self):
    method __repr__ (line 173) | def __repr__(self):
    method __str__ (line 176) | def __str__(self):

FILE: libs/common/babelfish/script.py
  class Script (line 33) | class Script(object):
    method __init__ (line 41) | def __init__(self, script):
    method name (line 49) | def name(self):
    method __getstate__ (line 53) | def __getstate__(self):
    method __setstate__ (line 56) | def __setstate__(self, state):
    method __hash__ (line 59) | def __hash__(self):
    method __eq__ (line 62) | def __eq__(self, other):
    method __ne__ (line 69) | def __ne__(self, other):
    method __repr__ (line 72) | def __repr__(self):
    method __str__ (line 75) | def __str__(self):

FILE: libs/common/beets/__init__.py
  class IncludeLazyConfig (line 23) | class IncludeLazyConfig(confuse.LazyConfig):
    method read (line 27) | def read(self, user=True, defaults=True):

FILE: libs/common/beets/art.py
  function mediafile_image (line 30) | def mediafile_image(image_path, maxwidth=None):
  function get_art (line 39) | def get_art(log, item):
  function embed_item (line 51) | def embed_item(log, item, imagepath, maxwidth=None, itempath=None,
  function embed_album (line 85) | def embed_album(log, album, maxwidth=None, quiet=False, compare_threshol...
  function resize_image (line 107) | def resize_image(log, imagepath, maxwidth, quality):
  function check_art_similarity (line 118) | def check_art_similarity(log, item, imagepath, compare_threshold):
  function extract (line 190) | def extract(log, outpath, item):
  function extract_first (line 212) | def extract_first(log, outpath, items):
  function clear (line 219) | def clear(log, lib, query):

FILE: libs/common/beets/autotag/__init__.py
  function apply_item_metadata (line 74) | def apply_item_metadata(item, track_info):
  function apply_metadata (line 98) | def apply_metadata(album_info, mapping):

FILE: libs/common/beets/autotag/hooks.py
  class AttrDict (line 39) | class AttrDict(dict):
    method __getattr__ (line 44) | def __getattr__(self, attr):
    method __setattr__ (line 50) | def __setattr__(self, key, value):
    method __hash__ (line 53) | def __hash__(self):
  class AlbumInfo (line 57) | class AlbumInfo(AttrDict):
    method __init__ (line 71) | def __init__(self, tracks, album=None, album_id=None, artist=None,
    method decode (line 121) | def decode(self, codec='utf-8'):
    method copy (line 138) | def copy(self):
  class TrackInfo (line 145) | class TrackInfo(AttrDict):
    method __init__ (line 157) | def __init__(self, title=None, track_id=None, release_track_id=None,
    method decode (line 196) | def decode(self, codec='utf-8'):
    method copy (line 206) | def copy(self):
  function _string_dist_basic (line 232) | def _string_dist_basic(str1, str2):
  function string_dist (line 249) | def string_dist(str1, str2):
  class LazyClassProperty (line 307) | class LazyClassProperty:
    method __init__ (line 313) | def __init__(self, getter):
    method __get__ (line 317) | def __get__(self, obj, owner):
  class Distance (line 325) | class Distance:
    method __init__ (line 331) | def __init__(self):
    method _weights (line 335) | def _weights(cls):  # noqa: N805
    method distance (line 347) | def distance(self):
    method max_distance (line 357) | def max_distance(self):
    method raw_distance (line 366) | def raw_distance(self):
    method items (line 374) | def items(self):
    method __hash__ (line 392) | def __hash__(self):
    method __eq__ (line 395) | def __eq__(self, other):
    method __lt__ (line 400) | def __lt__(self, other):
    method __float__ (line 403) | def __float__(self):
    method __sub__ (line 406) | def __sub__(self, other):
    method __rsub__ (line 409) | def __rsub__(self, other):
    method __str__ (line 412) | def __str__(self):
    method __getitem__ (line 417) | def __getitem__(self, key):
    method __iter__ (line 426) | def __iter__(self):
    method __len__ (line 429) | def __len__(self):
    method keys (line 432) | def keys(self):
    method update (line 435) | def update(self, dist):
    method _eq (line 447) | def _eq(self, value1, value2):
    method add (line 456) | def add(self, key, dist):
    method add_equality (line 468) | def add_equality(self, key, value, options):
    method add_expr (line 484) | def add_expr(self, key, expr):
    method add_number (line 493) | def add_number(self, key, number1, number2):
    method add_priority (line 506) | def add_priority(self, key, value, options):
    method add_ratio (line 524) | def add_ratio(self, key, number1, number2):
    method add_string (line 535) | def add_string(self, key, str1, str2):
  function album_for_mbid (line 553) | def album_for_mbid(release_id):
  function track_for_mbid (line 566) | def track_for_mbid(recording_id):
  function albums_for_id (line 579) | def albums_for_id(album_id):
  function tracks_for_id (line 590) | def tracks_for_id(track_id):
  function album_candidates (line 602) | def album_candidates(items, artist, album, va_likely, extra_tags):
  function item_candidates (line 634) | def item_candidates(item, artist, title):

FILE: libs/common/beets/autotag/match.py
  class Recommendation (line 44) | class Recommendation(OrderedEnum):
  function current_metadata (line 63) | def current_metadata(items):
  function assign_items (line 88) | def assign_items(items, tracks):
  function track_index_changed (line 117) | def track_index_changed(item, track_info):
  function track_distance (line 124) | def track_distance(item, track_info, incl_artist=False):
  function distance (line 160) | def distance(items, album_info, mapping):
  function match_by_id (line 266) | def match_by_id(items):
  function _recommendation (line 290) | def _recommendation(results):
  function _sort_candidates (line 341) | def _sort_candidates(candidates):
  function _add_candidate (line 346) | def _add_candidate(items, results, info):
  function tag_album (line 389) | def tag_album(items, search_artist=None, search_album=None,
  function tag_item (line 475) | def tag_item(item, search_artist=None, search_title=None,

FILE: libs/common/beets/autotag/mb.py
  class MusicBrainzAPIError (line 49) | class MusicBrainzAPIError(util.HumanReadableException):
    method __init__ (line 54) | def __init__(self, reason, verb, query, tb=None):
    method get_message (line 60) | def get_message(self):
  function track_url (line 85) | def track_url(trackid):
  function album_url (line 89) | def album_url(albumid):
  function configure (line 93) | def configure():
  function _preferred_alias (line 109) | def _preferred_alias(aliases):
  function _preferred_release_event (line 132) | def _preferred_release_event(release):
  function _flatten_artist_credit (line 150) | def _flatten_artist_credit(credit):
  function track_info (line 196) | def track_info(recording, index=None, medium=None, medium_index=None,
  function _set_date_str (line 278) | def _set_date_str(info, date_str, original=False):
  function album_info (line 298) | def album_info(release):
  function match_album (line 477) | def match_album(artist, album, tracks=None, extra_tags=None):
  function match_track (line 524) | def match_track(artist, title):
  function _parse_id (line 546) | def _parse_id(s):
  function album_for_id (line 556) | def album_for_id(releaseid):
  function track_for_id (line 578) | def track_for_id(releaseid):

FILE: libs/common/beets/dbcore/db.py
  class DBAccessError (line 34) | class DBAccessError(Exception):
  class FormattedMapping (line 43) | class FormattedMapping(Mapping):
    method __init__ (line 59) | def __init__(self, model, included_keys=ALL_KEYS, for_path=False):
    method __getitem__ (line 68) | def __getitem__(self, key):
    method __iter__ (line 74) | def __iter__(self):
    method __len__ (line 77) | def __len__(self):
    method get (line 80) | def get(self, key, default=None):
    method _get_formatted (line 85) | def _get_formatted(self, model, key):
  class LazyConvertDict (line 104) | class LazyConvertDict:
    method __init__ (line 108) | def __init__(self, model_cls):
    method init (line 115) | def init(self, data):
    method _convert (line 120) | def _convert(self, key, value):
    method __setitem__ (line 125) | def __setitem__(self, key, value):
    method __getitem__ (line 130) | def __getitem__(self, key):
    method __delitem__ (line 141) | def __delitem__(self, key):
    method keys (line 149) | def keys(self):
    method copy (line 154) | def copy(self):
    method update (line 164) | def update(self, values):
    method items (line 170) | def items(self):
    method get (line 177) | def get(self, key, default=None):
    method __contains__ (line 186) | def __contains__(self, key):
    method __iter__ (line 191) | def __iter__(self):
  class Model (line 200) | class Model:
    method _getters (line 270) | def _getters(cls):
    method _template_funcs (line 277) | def _template_funcs(self):
    method __init__ (line 286) | def __init__(self, db=None, **values):
    method _awaken (line 300) | def _awaken(cls, db=None, fixed_values={}, flex_values={}):
    method __repr__ (line 313) | def __repr__(self):
    method clear_dirty (line 319) | def clear_dirty(self):
    method _check_db (line 327) | def _check_db(self, need_id=True):
    method copy (line 339) | def copy(self):
    method _type (line 357) | def _type(cls, key):
    method _get (line 365) | def _get(self, key, default=None, raise_=False):
    method __getitem__ (line 386) | def __getitem__(self, key):
    method _setitem (line 392) | def _setitem(self, key, value):
    method __setitem__ (line 414) | def __setitem__(self, key, value):
    method __delitem__ (line 419) | def __delitem__(self, key):
    method keys (line 432) | def keys(self, computed=False):
    method all_keys (line 444) | def all_keys(cls):
    method update (line 452) | def update(self, values):
    method items (line 458) | def items(self):
    method __contains__ (line 465) | def __contains__(self, key):
    method __iter__ (line 470) | def __iter__(self):
    method __getattr__ (line 478) | def __getattr__(self, key):
    method __setattr__ (line 487) | def __setattr__(self, key, value):
    method __delattr__ (line 493) | def __delattr__(self, key):
    method store (line 501) | def store(self, fields=None):
    method load (line 551) | def load(self):
    method remove (line 568) | def remove(self):
    method add (line 582) | def add(self, db=None):
    method formatted (line 611) | def formatted(self, included_keys=_formatter.ALL_KEYS, for_path=False):
    method evaluate_template (line 617) | def evaluate_template(self, template, for_path=False):
    method _parse (line 631) | def _parse(cls, key, string):
    method set_parse (line 639) | def set_parse(self, key, string):
  class Results (line 647) | class Results:
    method __init__ (line 652) | def __init__(self, model_class, rows, db, flex_rows,
    method _get_objects (line 685) | def _get_objects(self):
    method __iter__ (line 720) | def __iter__(self):
    method _get_indexed_flex_attrs (line 733) | def _get_indexed_flex_attrs(self):
    method _make_model (line 745) | def _make_model(self, row, flex_values={}):
    method __len__ (line 756) | def __len__(self):
    method __nonzero__ (line 774) | def __nonzero__(self):
    method __bool__ (line 779) | def __bool__(self):
    method __getitem__ (line 784) | def __getitem__(self, n):
    method get (line 801) | def get(self):
  class Transaction (line 812) | class Transaction:
    method __init__ (line 822) | def __init__(self, db):
    method __enter__ (line 825) | def __enter__(self):
    method __exit__ (line 838) | def __exit__(self, exc_type, exc_value, traceback):
    method query (line 854) | def query(self, statement, subvals=()):
    method mutate (line 861) | def mutate(self, statement, subvals=()):
    method script (line 880) | def script(self, statements):
  class Database (line 887) | class Database:
    method __init__ (line 904) | def __init__(self, path, timeout=5.0):
    method _connection (line 933) | def _connection(self):
    method _create_connection (line 946) | def _create_connection(self):
    method _close (line 971) | def _close(self):
    method _tx_stack (line 980) | def _tx_stack(self):
    method transaction (line 989) | def transaction(self):
    method load_extension (line 995) | def load_extension(self, path):
    method _make_table (line 1009) | def _make_table(self, table, fields):
    method _make_attribute_table (line 1044) | def _make_attribute_table(self, flex_table):
    method _fetch (line 1062) | def _fetch(self, model_cls, query=None, sort=None):
    method _get (line 1102) | def _get(self, model_cls, id):

FILE: libs/common/beets/dbcore/query.py
  class ParsingError (line 26) | class ParsingError(ValueError):
  class InvalidQueryError (line 32) | class InvalidQueryError(ParsingError):
    method __init__ (line 38) | def __init__(self, query, explanation):
  class InvalidQueryArgumentValueError (line 45) | class InvalidQueryArgumentValueError(ParsingError):
    method __init__ (line 52) | def __init__(self, what, expected, detail=None):
  class Query (line 59) | class Query:
    method clause (line 63) | def clause(self):
    method match (line 72) | def match(self, item):
    method __repr__ (line 78) | def __repr__(self):
    method __eq__ (line 81) | def __eq__(self, other):
    method __hash__ (line 84) | def __hash__(self):
  class FieldQuery (line 88) | class FieldQuery(Query):
    method __init__ (line 96) | def __init__(self, field, pattern, fast=True):
    method col_clause (line 101) | def col_clause(self):
    method clause (line 104) | def clause(self):
    method value_match (line 112) | def value_match(cls, pattern, value):
    method match (line 118) | def match(self, item):
    method __repr__ (line 121) | def __repr__(self):
    method __eq__ (line 125) | def __eq__(self, other):
    method __hash__ (line 129) | def __hash__(self):
  class MatchQuery (line 133) | class MatchQuery(FieldQuery):
    method col_clause (line 136) | def col_clause(self):
    method value_match (line 140) | def value_match(cls, pattern, value):
  class NoneQuery (line 144) | class NoneQuery(FieldQuery):
    method __init__ (line 147) | def __init__(self, field, fast=True):
    method col_clause (line 150) | def col_clause(self):
    method match (line 153) | def match(self, item):
    method __repr__ (line 156) | def __repr__(self):
  class StringFieldQuery (line 160) | class StringFieldQuery(FieldQuery):
    method value_match (line 166) | def value_match(cls, pattern, value):
    method string_match (line 173) | def string_match(cls, pattern, value):
  class SubstringQuery (line 180) | class SubstringQuery(StringFieldQuery):
    method col_clause (line 183) | def col_clause(self):
    method string_match (line 194) | def string_match(cls, pattern, value):
  class RegexpQuery (line 198) | class RegexpQuery(StringFieldQuery):
    method __init__ (line 206) | def __init__(self, field, pattern, fast=True):
    method _normalize (line 218) | def _normalize(s):
    method string_match (line 225) | def string_match(cls, pattern, value):
  class BooleanQuery (line 229) | class BooleanQuery(MatchQuery):
    method __init__ (line 234) | def __init__(self, field, pattern, fast=True):
  class BytesQuery (line 241) | class BytesQuery(MatchQuery):
    method __init__ (line 248) | def __init__(self, field, pattern):
    method col_clause (line 262) | def col_clause(self):
  class NumericQuery (line 266) | class NumericQuery(FieldQuery):
    method _convert (line 275) | def _convert(self, s):
    method __init__ (line 292) | def __init__(self, field, pattern, fast=True):
    method match (line 307) | def match(self, item):
    method col_clause (line 323) | def col_clause(self):
  class CollectionQuery (line 338) | class CollectionQuery(Query):
    method __init__ (line 343) | def __init__(self, subqueries=()):
    method __len__ (line 348) | def __len__(self):
    method __getitem__ (line 351) | def __getitem__(self, key):
    method __iter__ (line 354) | def __iter__(self):
    method __contains__ (line 357) | def __contains__(self, item):
    method clause_with_joiner (line 360) | def clause_with_joiner(self, joiner):
    method __repr__ (line 376) | def __repr__(self):
    method __eq__ (line 379) | def __eq__(self, other):
    method __hash__ (line 383) | def __hash__(self):
  class AnyFieldQuery (line 390) | class AnyFieldQuery(CollectionQuery):
    method __init__ (line 396) | def __init__(self, pattern, fields, cls):
    method clause (line 406) | def clause(self):
    method match (line 409) | def match(self, item):
    method __repr__ (line 415) | def __repr__(self):
    method __eq__ (line 419) | def __eq__(self, other):
    method __hash__ (line 423) | def __hash__(self):
  class MutableCollectionQuery (line 427) | class MutableCollectionQuery(CollectionQuery):
    method __setitem__ (line 432) | def __setitem__(self, key, value):
    method __delitem__ (line 435) | def __delitem__(self, key):
  class AndQuery (line 439) | class AndQuery(MutableCollectionQuery):
    method clause (line 442) | def clause(self):
    method match (line 445) | def match(self, item):
  class OrQuery (line 449) | class OrQuery(MutableCollectionQuery):
    method clause (line 452) | def clause(self):
    method match (line 455) | def match(self, item):
  class NotQuery (line 459) | class NotQuery(Query):
    method __init__ (line 464) | def __init__(self, subquery):
    method clause (line 467) | def clause(self):
    method match (line 476) | def match(self, item):
    method __repr__ (line 479) | def __repr__(self):
    method __eq__ (line 482) | def __eq__(self, other):
    method __hash__ (line 486) | def __hash__(self):
  class TrueQuery (line 490) | class TrueQuery(Query):
    method clause (line 493) | def clause(self):
    method match (line 496) | def match(self, item):
  class FalseQuery (line 500) | class FalseQuery(Query):
    method clause (line 503) | def clause(self):
    method match (line 506) | def match(self, item):
  function _to_epoch_time (line 512) | def _to_epoch_time(date):
  function _parse_periods (line 525) | def _parse_periods(pattern):
  class Period (line 539) | class Period:
    method __init__ (line 559) | def __init__(self, date, precision):
    method parse (line 570) | def parse(cls, string):
    method open_right_endpoint (line 624) | def open_right_endpoint(self):
  class DateInterval (line 649) | class DateInterval:
    method __init__ (line 656) | def __init__(self, start, end):
    method from_periods (line 664) | def from_periods(cls, start, end):
    method contains (line 671) | def contains(self, date):
    method __str__ (line 678) | def __str__(self):
  class DateQuery (line 682) | class DateQuery(FieldQuery):
    method __init__ (line 692) | def __init__(self, field, pattern, fast=True):
    method match (line 697) | def match(self, item):
    method col_clause (line 706) | def col_clause(self):
  class DurationQuery (line 727) | class DurationQuery(NumericQuery):
    method _convert (line 736) | def _convert(self, s):
  class Sort (line 757) | class Sort:
    method order_clause (line 762) | def order_clause(self):
    method sort (line 768) | def sort(self, items):
    method is_slow (line 773) | def is_slow(self):
    method __hash__ (line 779) | def __hash__(self):
    method __eq__ (line 782) | def __eq__(self, other):
  class MultipleSort (line 786) | class MultipleSort(Sort):
    method __init__ (line 790) | def __init__(self, sorts=None):
    method add_sort (line 793) | def add_sort(self, sort):
    method _sql_sorts (line 796) | def _sql_sorts(self):
    method order_clause (line 813) | def order_clause(self):
    method is_slow (line 821) | def is_slow(self):
    method sort (line 827) | def sort(self, items):
    method __repr__ (line 843) | def __repr__(self):
    method __hash__ (line 846) | def __hash__(self):
    method __eq__ (line 849) | def __eq__(self, other):
  class FieldSort (line 854) | class FieldSort(Sort):
    method __init__ (line 859) | def __init__(self, field, ascending=True, case_insensitive=True):
    method sort (line 864) | def sort(self, objs):
    method __repr__ (line 877) | def __repr__(self):
    method __hash__ (line 884) | def __hash__(self):
    method __eq__ (line 887) | def __eq__(self, other):
  class FixedFieldSort (line 893) | class FixedFieldSort(FieldSort):
    method order_clause (line 897) | def order_clause(self):
  class SlowFieldSort (line 909) | class SlowFieldSort(FieldSort):
    method is_slow (line 914) | def is_slow(self):
  class NullSort (line 918) | class NullSort(Sort):
    method sort (line 921) | def sort(self, items):
    method __nonzero__ (line 924) | def __nonzero__(self):
    method __bool__ (line 927) | def __bool__(self):
    method __eq__ (line 930) | def __eq__(self, other):
    method __hash__ (line 933) | def __hash__(self):

FILE: libs/common/beets/dbcore/queryparse.py
  function parse_query_part (line 37) | def parse_query_part(part, query_classes={}, prefixes={},
  function construct_query_part (line 103) | def construct_query_part(model_cls, prefixes, query_part):
  function query_from_strings (line 161) | def query_from_strings(query_cls, model_cls, prefixes, query_parts):
  function construct_sort_part (line 174) | def construct_sort_part(model_cls, part, case_insensitive=True):
  function sort_from_strings (line 200) | def sort_from_strings(model_cls, sort_parts, case_insensitive=True):
  function parse_sorted_query (line 215) | def parse_sorted_query(model_cls, parts, prefixes={},

FILE: libs/common/beets/dbcore/types.py
  class Type (line 24) | class Type:
    method null (line 47) | def null(self):
    method format (line 52) | def format(self, value):
    method parse (line 66) | def parse(self, string):
    method normalize (line 75) | def normalize(self, value):
    method from_sql (line 87) | def from_sql(self, sql_value):
    method to_sql (line 108) | def to_sql(self, model_value):
  class Default (line 117) | class Default(Type):
  class Integer (line 121) | class Integer(Type):
    method normalize (line 128) | def normalize(self, value):
  class PaddedInt (line 137) | class PaddedInt(Integer):
    method __init__ (line 141) | def __init__(self, digits):
    method format (line 144) | def format(self, value):
  class NullPaddedInt (line 148) | class NullPaddedInt(PaddedInt):
  class ScaledInt (line 154) | class ScaledInt(Integer):
    method __init__ (line 158) | def __init__(self, unit, suffix=''):
    method format (line 162) | def format(self, value):
  class Id (line 166) | class Id(Integer):
    method __init__ (line 172) | def __init__(self, primary=True):
  class Float (line 177) | class Float(Type):
    method __init__ (line 185) | def __init__(self, digits=1):
    method format (line 188) | def format(self, value):
  class NullFloat (line 192) | class NullFloat(Float):
  class String (line 198) | class String(Type):
    method normalize (line 204) | def normalize(self, value):
  class Boolean (line 211) | class Boolean(Type):
    method format (line 218) | def format(self, value):
    method parse (line 221) | def parse(self, string):

FILE: libs/common/beets/importer.py
  class ImportAbort (line 58) | class ImportAbort(Exception):
  function _open_state (line 66) | def _open_state():
  function _save_state (line 80) | def _save_state(state):
  function progress_read (line 92) | def progress_read():
  function progress_write (line 98) | def progress_write():
  function progress_add (line 105) | def progress_add(toppath, *paths):
  function progress_element (line 122) | def progress_element(toppath, path):
  function has_progress (line 133) | def has_progress(toppath):
  function progress_reset (line 141) | def progress_reset(toppath):
  function history_add (line 151) | def history_add(paths):
  function history_get (line 164) | def history_get():
  class ImportSession (line 175) | class ImportSession:
    method __init__ (line 180) | def __init__(self, lib, loghandler, paths, query):
    method _setup_logging (line 197) | def _setup_logging(self, loghandler):
    method set_config (line 205) | def set_config(self, config):
    method tag_log (line 256) | def tag_log(self, status, paths):
    method log_choice (line 262) | def log_choice(self, task, duplicate=False):
    method should_resume (line 283) | def should_resume(self, path):
    method choose_match (line 286) | def choose_match(self, task):
    method resolve_duplicate (line 289) | def resolve_duplicate(self, task, found_duplicates):
    method choose_item (line 292) | def choose_item(self, task):
    method run (line 295) | def run(self):
    method already_imported (line 349) | def already_imported(self, toppath, paths):
    method history_dirs (line 363) | def history_dirs(self):
    method already_merged (line 368) | def already_merged(self, paths):
    method mark_merged (line 378) | def mark_merged(self, paths):
    method is_resuming (line 386) | def is_resuming(self, toppath):
    method ask_resume (line 393) | def ask_resume(self, toppath):
  class BaseImportTask (line 413) | class BaseImportTask:
    method __init__ (line 419) | def __init__(self, toppath, paths, items):
  class ImportTask (line 441) | class ImportTask(BaseImportTask):
    method __init__ (line 473) | def __init__(self, toppath, paths, items):
    method set_choice (line 485) | def set_choice(self, choice):
    method save_progress (line 499) | def save_progress(self):
    method save_history (line 506) | def save_history(self):
    method apply (line 515) | def apply(self):
    method skip (line 519) | def skip(self):
    method chosen_ident (line 524) | def chosen_ident(self):
    method imported_items (line 536) | def imported_items(self):
    method apply_metadata (line 549) | def apply_metadata(self):
    method duplicate_items (line 558) | def duplicate_items(self, lib):
    method remove_duplicates (line 564) | def remove_duplicates(self, lib):
    method set_fields (line 576) | def set_fields(self, lib):
    method finalize (line 595) | def finalize(self, session):
    method cleanup (line 614) | def cleanup(self, copy=False, delete=False, move=False):
    method _emit_imported (line 637) | def _emit_imported(self, lib):
    method handle_created (line 640) | def handle_created(self, session):
    method lookup_candidates (line 654) | def lookup_candidates(self):
    method find_duplicates (line 666) | def find_duplicates(self, lib):
    method align_album_level_fields (line 692) | def align_album_level_fields(self):
    method manipulate_files (line 728) | def manipulate_files(self, operation=None, write=False, session=None):
    method add (line 768) | def add(self, lib):
    method record_replaced (line 780) | def record_replaced(self, lib):
    method reimport_metadata (line 801) | def reimport_metadata(self, lib):
    method remove_replaced (line 843) | def remove_replaced(self, lib):
    method choose_match (line 856) | def choose_match(self, session):
    method reload (line 863) | def reload(self):
    method prune (line 872) | def prune(self, filename):
  class SingletonImportTask (line 885) | class SingletonImportTask(ImportTask):
    method __init__ (line 889) | def __init__(self, toppath, item):
    method chosen_ident (line 895) | def chosen_ident(self):
    method imported_items (line 902) | def imported_items(self):
    method apply_metadata (line 905) | def apply_metadata(self):
    method _emit_imported (line 908) | def _emit_imported(self, lib):
    method lookup_candidates (line 912) | def lookup_candidates(self):
    method find_duplicates (line 917) | def find_duplicates(self, lib):
    method add (line 936) | def add(self, lib):
    method infer_album_fields (line 943) | def infer_album_fields(self):
    method choose_match (line 946) | def choose_match(self, session):
    method reload (line 953) | def reload(self):
    method set_fields (line 956) | def set_fields(self, lib):
  class SentinelImportTask (line 973) | class SentinelImportTask(ImportTask):
    method __init__ (line 982) | def __init__(self, toppath, paths):
    method save_history (line 989) | def save_history(self):
    method save_progress (line 992) | def save_progress(self):
    method skip (line 1000) | def skip(self):
    method set_choice (line 1003) | def set_choice(self, choice):
    method cleanup (line 1006) | def cleanup(self, **kwargs):
    method _emit_imported (line 1009) | def _emit_imported(self, session):
  class ArchiveImportTask (line 1013) | class ArchiveImportTask(SentinelImportTask):
    method __init__ (line 1026) | def __init__(self, toppath):
    method is_archive (line 1031) | def is_archive(cls, path):
    method handlers (line 1044) | def handlers(cls):
    method cleanup (line 1073) | def cleanup(self, **kwargs):
    method extract (line 1081) | def extract(self):
  class ImportTaskFactory (line 1099) | class ImportTaskFactory:
    method __init__ (line 1104) | def __init__(self, toppath, session):
    method tasks (line 1117) | def tasks(self):
    method _create (line 1157) | def _create(self, task):
    method paths (line 1170) | def paths(self):
    method singleton (line 1190) | def singleton(self, path):
    method album (line 1205) | def album(self, paths, dirs=None):
    method sentinel (line 1231) | def sentinel(self, paths=None):
    method unarchive (line 1237) | def unarchive(self):
    method read_item (line 1266) | def read_item(self, path):
  function _freshen_items (line 1287) | def _freshen_items(items):
  function _extend_pipeline (line 1295) | def _extend_pipeline(tasks, *stages):
  function read_tasks (line 1308) | def read_tasks(session):
  function query_tasks (line 1332) | def query_tasks(session):
  function lookup_candidates (line 1358) | def lookup_candidates(session, task):
  function user_query (line 1380) | def user_query(session, task):
  function resolve_duplicates (line 1448) | def resolve_duplicates(session, task):
  function import_asis (line 1489) | def import_asis(session, task):
  function apply_choice (line 1503) | def apply_choice(session, task):
  function plugin_stage (line 1527) | def plugin_stage(session, func, task):
  function manipulate_files (line 1544) | def manipulate_files(session, task):
  function log_files (line 1577) | def log_files(session, task):
  function group_albums (line 1588) | def group_albums(session):
  function is_subdir_of_any_in_list (line 1619) | def is_subdir_of_any_in_list(path, dirs):
  function albums_in_dir (line 1627) | def albums_in_dir(path):

FILE: libs/common/beets/library.py
  class PathQuery (line 47) | class PathQuery(dbcore.FieldQuery):
    method __init__ (line 55) | def __init__(self, field, pattern, fast=True, case_sensitive=None):
    method is_path_query (line 81) | def is_path_query(cls, query_part):
    method match (line 98) | def match(self, item):
    method col_clause (line 102) | def col_clause(self):
  class DateType (line 118) | class DateType(types.Float):
    method format (line 123) | def format(self, value):
    method parse (line 127) | def parse(self, string):
  class PathType (line 142) | class PathType(types.Type):
    method __init__ (line 151) | def __init__(self, nullable=False):
    method null (line 158) | def null(self):
    method format (line 164) | def format(self, value):
    method parse (line 167) | def parse(self, string):
    method normalize (line 170) | def normalize(self, value):
    method from_sql (line 182) | def from_sql(self, sql_value):
    method to_sql (line 185) | def to_sql(self, value):
  class MusicalKey (line 191) | class MusicalKey(types.String):
    method parse (line 206) | def parse(self, key):
    method normalize (line 214) | def normalize(self, key):
  class DurationType (line 221) | class DurationType(types.Float):
    method format (line 225) | def format(self, value):
    method parse (line 231) | def parse(self, string):
  class SmartArtistSort (line 245) | class SmartArtistSort(dbcore.query.Sort):
    method __init__ (line 250) | def __init__(self, model_cls, ascending=True, case_insensitive=True):
    method order_clause (line 255) | def order_clause(self):
    method sort (line 263) | def sort(self, objs):
  class FileOperationError (line 284) | class FileOperationError(Exception):
    method __init__ (line 290) | def __init__(self, path, reason):
    method text (line 298) | def text(self):
  class ReadError (line 312) | class ReadError(FileOperationError):
    method __str__ (line 316) | def __str__(self):
  class WriteError (line 320) | class WriteError(FileOperationError):
    method __str__ (line 324) | def __str__(self):
  class LibModel (line 330) | class LibModel(dbcore.Model):
    method _template_funcs (line 338) | def _template_funcs(self):
    method store (line 343) | def store(self, fields=None):
    method remove (line 347) | def remove(self):
    method add (line 351) | def add(self, lib=None):
    method __format__ (line 355) | def __format__(self, spec):
    method __str__ (line 361) | def __str__(self):
    method __bytes__ (line 364) | def __bytes__(self):
  class FormattedItemMapping (line 368) | class FormattedItemMapping(dbcore.db.FormattedMapping):
    method __init__ (line 376) | def __init__(self, item, included_keys=ALL_KEYS, for_path=False):
    method all_keys (line 390) | def all_keys(self):
    method album_keys (line 394) | def album_keys(self):
    method album (line 408) | def album(self):
    method _get (line 411) | def _get(self, key):
    method __getitem__ (line 424) | def __getitem__(self, key):
    method __iter__ (line 443) | def __iter__(self):
    method __len__ (line 446) | def __len__(self):
  class Item (line 450) | class Item(LibModel):
    method _cached_album (line 569) | def _cached_album(self):
    method _cached_album (line 585) | def _cached_album(self, album):
    method _getters (line 589) | def _getters(cls):
    method from_path (line 596) | def from_path(cls, path):
    method __setitem__ (line 605) | def __setitem__(self, key, value):
    method __getitem__ (line 622) | def __getitem__(self, key):
    method __repr__ (line 633) | def __repr__(self):
    method keys (line 643) | def keys(self, computed=False, with_album=True):
    method get (line 654) | def get(self, key, default=None, with_album=True):
    method update (line 665) | def update(self, values):
    method clear (line 673) | def clear(self):
    method get_album (line 678) | def get_album(self):
    method read (line 689) | def read(self, read_path=None):
    method write (line 720) | def write(self, path=None, tags=None, id3v23=None):
    method try_write (line 771) | def try_write(self, *args, **kwargs):
    method try_sync (line 784) | def try_sync(self, write, move, with_album=True):
    method move_file (line 808) | def move_file(self, dest, operation=MoveOperation.MOVE):
    method current_mtime (line 850) | def current_mtime(self):
    method try_filesize (line 856) | def try_filesize(self):
    method remove (line 869) | def remove(self, delete=False, with_album=True):
    method move (line 892) | def move(self, operation=MoveOperation.MOVE, basedir=None,
    method destination (line 940) | def destination(self, fragment=False, basedir=None, platform=None,
  class Album (line 1018) | class Album(LibModel):
    method _getters (line 1122) | def _getters(cls):
    method items (line 1130) | def items(self):
    method remove (line 1136) | def remove(self, delete=False, with_items=True):
    method move_art (line 1159) | def move_art(self, operation=MoveOperation.MOVE):
    method move (line 1201) | def move(self, operation=MoveOperation.MOVE, basedir=None, store=True):
    method item_dir (line 1232) | def item_dir(self):
    method _albumtotal (line 1241) | def _albumtotal(self):
    method art_destination (line 1262) | def art_destination(self, image, item_dir=None):
    method set_art (line 1291) | def set_art(self, path, copy=True):
    method store (line 1322) | def store(self, fields=None):
    method try_sync (line 1342) | def try_sync(self, write, move):
  function parse_query_parts (line 1358) | def parse_query_parts(parts, model_cls):
  function parse_query_string (line 1394) | def parse_query_string(s, model_cls):
  function _sqlite_bytelower (line 1409) | def _sqlite_bytelower(bytestring):
  class Library (line 1421) | class Library(dbcore.Database):
    method __init__ (line 1426) | def __init__(self, path='library.blb',
    method _create_connection (line 1440) | def _create_connection(self):
    method add (line 1447) | def add(self, obj):
    method add_album (line 1455) | def add_album(self, items):
    method _fetch (line 1484) | def _fetch(self, model_cls, query, sort=None):
    method get_default_album_sort (line 1508) | def get_default_album_sort():
    method get_default_item_sort (line 1515) | def get_default_item_sort():
    method albums (line 1521) | def albums(self, query=None, sort=None):
    method items (line 1526) | def items(self, query=None, sort=None):
    method get_item (line 1533) | def get_item(self, id):
    method get_album (line 1539) | def get_album(self, item_or_id):
  function _int_arg (line 1555) | def _int_arg(s):
  class DefaultTemplateFunctions (line 1562) | class DefaultTemplateFunctions:
    method __init__ (line 1570) | def __init__(self, item=None, lib=None):
    method functions (line 1578) | def functions(self):
    method tmpl_lower (line 1589) | def tmpl_lower(s):
    method tmpl_upper (line 1594) | def tmpl_upper(s):
    method tmpl_title (line 1599) | def tmpl_title(s):
    method tmpl_left (line 1604) | def tmpl_left(s, chars):
    method tmpl_right (line 1609) | def tmpl_right(s, chars):
    method tmpl_if (line 1614) | def tmpl_if(condition, trueval, falseval=''):
    method tmpl_asciify (line 1632) | def tmpl_asciify(s):
    method tmpl_time (line 1638) | def tmpl_time(s, fmt):
    method tmpl_aunique (line 1644) | def tmpl_aunique(self, keys=None, disam=None, bracket=None):
    method tmpl_first (line 1737) | def tmpl_first(s, count=1, skip=0, sep='; ', join_str='; '):
    method tmpl_ifdef (line 1751) | def tmpl_ifdef(self, field, trueval='', falseval=''):

FILE: libs/common/beets/logging.py
  function logsafe (line 30) | def logsafe(val):
  class StrFormatLogger (line 69) | class StrFormatLogger(Logger):
    class _LogMessage (line 74) | class _LogMessage:
      method __init__ (line 75) | def __init__(self, msg, args, kwargs):
      method __str__ (line 80) | def __str__(self):
    method _log (line 85) | def _log(self, level, msg, args, exc_info=None, extra=None, **kwargs):
  class ThreadLocalLevelLogger (line 91) | class ThreadLocalLevelLogger(Logger):
    method __init__ (line 95) | def __init__(self, name, level=NOTSET):
    method level (line 101) | def level(self):
    method level (line 109) | def level(self, value):
    method set_global_level (line 112) | def set_global_level(self, level):
  class BeetsLogger (line 120) | class BeetsLogger(ThreadLocalLevelLogger, StrFormatLogger):
  function getLogger (line 128) | def getLogger(name=None):  # noqa

FILE: libs/common/beets/plugins.py
  class PluginConflictException (line 40) | class PluginConflictException(Exception):
  class PluginLogFilter (line 48) | class PluginLogFilter(logging.Filter):
    method __init__ (line 53) | def __init__(self, plugin):
    method filter (line 56) | def filter(self, record):
  class BeetsPlugin (line 68) | class BeetsPlugin:
    method __init__ (line 74) | def __init__(self, name=None):
    method commands (line 93) | def commands(self):
    method _set_stage_log_level (line 99) | def _set_stage_log_level(self, stages):
    method get_early_import_stages (line 105) | def get_early_import_stages(self):
    method get_import_stages (line 115) | def get_import_stages(self):
    method _set_log_level_and_params (line 125) | def _set_log_level_and_params(self, base_log_level, func):
    method queries (line 151) | def queries(self):
    method track_distance (line 156) | def track_distance(self, item, info):
    method album_distance (line 162) | def album_distance(self, items, album_info, mapping):
    method candidates (line 168) | def candidates(self, items, artist, album, va_likely, extra_tags=None):
    method item_candidates (line 174) | def item_candidates(self, item, artist, title):
    method album_for_id (line 180) | def album_for_id(self, album_id):
    method track_for_id (line 186) | def track_for_id(self, track_id):
    method add_media_field (line 192) | def add_media_field(self, name, descriptor):
    method register_listener (line 210) | def register_listener(self, event, func):
    method template_func (line 228) | def template_func(cls, name):
    method template_field (line 241) | def template_field(cls, name):
  function load_plugins (line 258) | def load_plugins(names=()):
  function find_plugins (line 292) | def find_plugins():
  function commands (line 314) | def commands():
  function queries (line 323) | def queries():
  function types (line 333) | def types(model_cls):
  function named_queries (line 350) | def named_queries(model_cls):
  function track_distance (line 360) | def track_distance(item, info):
  function album_distance (line 371) | def album_distance(items, album_info, mapping):
  function candidates (line 380) | def candidates(items, artist, album, va_likely, extra_tags=None):
  function item_candidates (line 388) | def item_candidates(item, artist, title):
  function album_for_id (line 395) | def album_for_id(album_id):
  function track_for_id (line 404) | def track_for_id(track_id):
  function template_funcs (line 413) | def template_funcs():
  function early_import_stages (line 424) | def early_import_stages():
  function import_stages (line 432) | def import_stages():
  function item_field_getters (line 442) | def item_field_getters():
  function album_field_getters (line 453) | def album_field_getters():
  function event_handlers (line 465) | def event_handlers():
  function send (line 477) | def send(event, **arguments):
  function feat_tokens (line 494) | def feat_tokens(for_artist=True):
  function sanitize_choices (line 508) | def sanitize_choices(choices, choices_all):
  function sanitize_pairs (line 526) | def sanitize_pairs(pairs, pairs_all):
  function notify_info_yielded (line 564) | def notify_info_yielded(event):
  function get_distance (line 580) | def get_distance(config, data_source, info):
  function apply_item_changes (line 590) | def apply_item_changes(lib, item, move, pretend, write):
  class MetadataSourcePlugin (line 620) | class MetadataSourcePlugin(metaclass=abc.ABCMeta):
    method __init__ (line 621) | def __init__(self):
    method id_regex (line 626) | def id_regex(self):
    method data_source (line 630) | def data_source(self):
    method search_url (line 634) | def search_url(self):
    method album_url (line 638) | def album_url(self):
    method track_url (line 642) | def track_url(self):
    method _search_api (line 646) | def _search_api(self, query_type, filters, keywords=''):
    method album_for_id (line 650) | def album_for_id(self, album_id):
    method track_for_id (line 654) | def track_for_id(self, track_id=None, track_data=None):
    method get_artist (line 658) | def get_artist(artists, id_key='id', name_key='name'):
    method _get_id (line 693) | def _get_id(self, url_type, id_):
    method candidates (line 713) | def candidates(self, items, artist, album, va_likely, extra_tags=None):
    method item_candidates (line 736) | def item_candidates(self, item, artist, title):
    method album_distance (line 754) | def album_distance(self, items, album_info, mapping):
    method track_distance (line 759) | def track_distance(self, item, track_info):

FILE: libs/common/beets/random.py
  function _length (line 23) | def _length(obj, album):
  function _equal_chance_permutation (line 32) | def _equal_chance_permutation(objs, field='albumartist', random_gen=None):
  function _take (line 61) | def _take(iter, num):
  function _take_time (line 74) | def _take_time(iter, secs, album):
  function random_objs (line 89) | def random_objs(objs, album, number=1, time=None, equal_chance=False,

FILE: libs/common/beets/ui/__init__.py
  class UserError (line 66) | class UserError(Exception):
  function _in_encoding (line 75) | def _in_encoding():
  function _out_encoding (line 81) | def _out_encoding():
  function _stream_encoding (line 87) | def _stream_encoding(stream, default='utf-8'):
  function decargs (line 108) | def decargs(arglist):
  function print_ (line 115) | def print_(*strings, **kwargs):
  function _bool_fallback (line 150) | def _bool_fallback(a, b):
  function should_write (line 161) | def should_write(write_opt=None):
  function should_move (line 168) | def should_move(move_opt=None):
  function input_ (line 187) | def input_(prompt=None):
  function input_options (line 207) | def input_options(options, require=False, prompt=None, fallback_prompt=N...
  function input_yn (line 367) | def input_yn(prompt, require=False):
  function input_select_objects (line 377) | def input_select_objects(prompt, objs, rep, prompt_all=None):
  function human_bytes (line 415) | def human_bytes(size):
  function human_seconds (line 427) | def human_seconds(interval):
  function human_seconds_short (line 454) | def human_seconds_short(interval):
  function _colorize (line 502) | def _colorize(color, text):
  function colorize (line 516) | def colorize(color_name, text):
  function _colordiff (line 537) | def _colordiff(a, b, highlight='text_highlight',
  function colordiff (line 589) | def colordiff(a, b, highlight='text_highlight'):
  function get_path_formats (line 599) | def get_path_formats(subview=None):
  function get_replacements (line 611) | def get_replacements():
  function term_width (line 628) | def term_width():
  function _field_diff (line 654) | def _field_diff(field, old, old_fmt, new, new_fmt):
  function show_model_changes (line 684) | def show_model_changes(new, old=None, fields=None, always=False):
  function show_path_changes (line 732) | def show_path_changes(path_changes):
  function _store_dict (line 779) | def _store_dict(option, opt_str, value, parser):
  class CommonOptionsParser (line 808) | class CommonOptionsParser(optparse.OptionParser):
    method __init__ (line 824) | def __init__(self, *args, **kwargs):
    method add_album_option (line 831) | def add_album_option(self, flags=('-a', '--album')):
    method _set_format (line 843) | def _set_format(self, option, opt_str, value, parser, target=None,
    method add_path_option (line 877) | def add_path_option(self, flags=('-p', '--path')):
    method add_format_option (line 894) | def add_format_option(self, flags=('-f', '--format'), target=None):
    method add_all_common_options (line 922) | def add_all_common_options(self):
  class Subcommand (line 938) | class Subcommand:
    method __init__ (line 943) | def __init__(self, name, parser=None, help='', aliases=(), hide=False):
    method print_help (line 957) | def print_help(self):
    method parse_args (line 960) | def parse_args(self, args):
    method root_parser (line 964) | def root_parser(self):
    method root_parser (line 968) | def root_parser(self, root_parser):
  class SubcommandsOptionParser (line 974) | class SubcommandsOptionParser(CommonOptionsParser):
    method __init__ (line 979) | def __init__(self, *args, **kwargs):
    method add_subcommand (line 999) | def add_subcommand(self, *cmds):
    method format_help (line 1007) | def format_help(self, formatter=None):
    method _subcommand_for_name (line 1059) | def _subcommand_for_name(self, name):
    method parse_global_options (line 1070) | def parse_global_options(self, args):
    method parse_subcommand (line 1083) | def parse_subcommand(self, args):
  function _load_plugins (line 1106) | def _load_plugins(options, config):
  function _setup (line 1135) | def _setup(options, lib=None):
  function _configure (line 1173) | def _configure(options):
  function _open_library (line 1210) | def _open_library(config):
  function _raw_main (line 1235) | def _raw_main(args, lib=None):
  function main (line 1280) | def main(args=None):

FILE: libs/common/beets/ui/commands.py
  function _do_query (line 56) | def _do_query(lib, query, album, also_items=True):
  function _print_keys (line 84) | def _print_keys(query):
  function fields_func (line 92) | def fields_func(lib, opts, args):
  class HelpCommand (line 124) | class HelpCommand(ui.Subcommand):
    method __init__ (line 126) | def __init__(self):
    method func (line 132) | def func(self, lib, opts, args):
  function disambig_string (line 150) | def disambig_string(info):
  function dist_string (line 182) | def dist_string(dist):
  function penalty_string (line 196) | def penalty_string(distance, limit=None):
  function show_change (line 212) | def show_change(cur_artist, cur_album, match):
  function show_item_change (line 401) | def show_item_change(item, match):
  function summarize_items (line 439) | def summarize_items(items, singleton):
  function _summary_judgment (line 480) | def _summary_judgment(rec):
  function choose_candidate (line 514) | def choose_candidate(candidates, singleton, rec, cur_artist=None,
  function manual_search (line 645) | def manual_search(session, task):
  function manual_id (line 663) | def manual_id(session, task):
  function abort_action (line 681) | def abort_action(session, task):
  class TerminalImportSession (line 687) | class TerminalImportSession(importer.ImportSession):
    method choose_match (line 691) | def choose_match(self, task):
    method choose_item (line 758) | def choose_item(self, task):
    method resolve_duplicate (line 797) | def resolve_duplicate(self, task, found_duplicates):
    method should_resume (line 840) | def should_resume(self, path):
    method _get_choices (line 845) | def _get_choices(self, task):
  function import_files (line 912) | def import_files(lib, paths, query):
  function import_func (line 949) | def import_func(lib, opts, args):
  function list_items (line 1076) | def list_items(lib, query, album, fmt=''):
  function list_func (line 1088) | def list_func(lib, opts, args):
  function update_items (line 1102) | def update_items(lib, query, album, move, pretend, fields):
  function update_func (line 1204) | def update_func(lib, opts, args):
  function remove_items (line 1242) | def remove_items(lib, query, album, delete, force):
  function remove_func (line 1298) | def remove_func(lib, opts, args):
  function show_stats (line 1320) | def show_stats(lib, query, exact):
  function stats_func (line 1367) | def stats_func(lib, opts, args):
  function show_version (line 1384) | def show_version(lib, opts, args):
  function modify_items (line 1404) | def modify_items(lib, mods, dels, query, write, move, album, confirm):
  function print_and_modify (line 1457) | def print_and_modify(obj, mods, dels):
  function modify_parse_args (line 1473) | def modify_parse_args(args):
  function modify_func (line 1492) | def modify_func(lib, opts, args):
  function move_items (line 1531) | def move_items(lib, dest, query, copy, album, pretend, confirm=False,
  function move_func (line 1593) | def move_func(lib, opts, args):
  function write_items (line 1634) | def write_items(lib, query, pretend, force):
  function write_func (line 1663) | def write_func(lib, opts, args):
  function config_func (line 1682) | def config_func(lib, opts, args):
  function config_edit (line 1717) | def config_edit():
  function print_completion (line 1759) | def print_completion(*args):
  function completion_script (line 1778) | def completion_script(commands):

FILE: libs/common/beets/util/__init__.py
  class HumanReadableException (line 41) | class HumanReadableException(Exception):
    method __init__ (line 56) | def __init__(self, reason, verb, tb=None):
    method _gerund (line 62) | def _gerund(self):
    method _reasonstr (line 71) | def _reasonstr(self):
    method get_message (line 82) | def get_message(self):
    method log (line 88) | def log(self, logger):
  class FilesystemError (line 97) | class FilesystemError(HumanReadableException):
    method __init__ (line 103) | def __init__(self, reason, verb, paths, tb=None):
    method get_message (line 107) | def get_message(self):
  class MoveOperation (line 128) | class MoveOperation(Enum):
  function normpath (line 139) | def normpath(path):
  function ancestry (line 148) | def ancestry(path):
  function sorted_walk (line 172) | def sorted_walk(path, ignore=(), ignore_hidden=False, logger=None):
  function path_as_posix (line 229) | def path_as_posix(path):
  function mkdirall (line 236) | def mkdirall(path):
  function fnmatch_all (line 249) | def fnmatch_all(names, patterns):
  function prune_dirs (line 264) | def prune_dirs(path, root=None, clutter=('.DS_Store', 'Thumbs.db')):
  function components (line 307) | def components(path):
  function arg_encoding (line 331) | def arg_encoding():
  function _fsencoding (line 343) | def _fsencoding():
  function bytestring_path (line 358) | def bytestring_path(path):
  function displayable_path (line 382) | def displayable_path(path, separator='; '):
  function syspath (line 401) | def syspath(path, prefix=True):
  function samefile (line 435) | def samefile(p1, p2):
  function remove (line 442) | def remove(path, soft=True):
  function copy (line 455) | def copy(path, dest, replace=False):
  function move (line 474) | def move(path, dest, replace=False):
  function link (line 515) | def link(path, dest, replace=False):
  function hardlink (line 540) | def hardlink(path, dest, replace=False):
  function reflink (line 564) | def reflink(path, dest, replace=False, fallback=False):
  function unique_path (line 593) | def unique_path(path):
  function sanitize_path (line 630) | def sanitize_path(path, replacements=None):
  function truncate_path (line 651) | def truncate_path(path, length=MAX_FILENAME_LENGTH):
  function _legalize_stage (line 668) | def _legalize_stage(path, replacements, length, extension, fragment):
  function legalize_path (line 692) | def legalize_path(path, replacements, length, extension, fragment):
  function py3_path (line 740) | def py3_path(path):
  function str2bool (line 756) | def str2bool(value):
  function as_string (line 761) | def as_string(value):
  function text_string (line 775) | def text_string(value, encoding='utf-8'):
  function plurality (line 788) | def plurality(objs):
  function cpu_count (line 799) | def cpu_count():
  function convert_command_args (line 830) | def convert_command_args(args):
  function command_output (line 847) | def command_output(cmd, shell=False):
  function max_filename_length (line 890) | def max_filename_length(path, limit=MAX_FILENAME_LENGTH):
  function open_anything (line 907) | def open_anything():
  function editor_command (line 921) | def editor_command():
  function interactive_open (line 934) | def interactive_open(targets, command):
  function _windows_long_path_name (line 956) | def _windows_long_path_name(short_path):
  function case_sensitive (line 980) | def case_sensitive(path):
  function raw_seconds_short (line 1013) | def raw_seconds_short(string):
  function asciify_path (line 1026) | def asciify_path(path, sep_replace):
  function par_map (line 1050) | def par_map(transform, items):
  function lazy_property (line 1065) | def lazy_property(func):
  function decode_commandline_path (line 1088) | def decode_commandline_path(path):

FILE: libs/common/beets/util/artresizer.py
  function resize_url (line 38) | def resize_url(url, maxwidth, quality=0):
  function temp_file_for (line 53) | def temp_file_for(path):
  function pil_resize (line 62) | def pil_resize(maxwidth, path_in, path_out=None, quality=0, max_filesize...
  function im_resize (line 120) | def im_resize(maxwidth, path_in, path_out=None, quality=0, max_filesize=0):
  function pil_getsize (line 167) | def pil_getsize(path_in):
  function im_getsize (line 178) | def im_getsize(path_in):
  function pil_deinterlace (line 204) | def pil_deinterlace(path_in, path_out=None):
  function im_deinterlace (line 216) | def im_deinterlace(path_in, path_out=None):
  function im_get_format (line 238) | def im_get_format(filepath):
  function pil_get_format (line 250) | def pil_get_format(filepath):
  function im_convert_format (line 267) | def im_convert_format(source, target, deinterlaced):
  function pil_convert_format (line 285) | def pil_convert_format(source, target, deinterlaced):
  class Shareable (line 304) | class Shareable(type):
    method __init__ (line 311) | def __init__(cls, name, bases, dict):
    method shared (line 316) | def shared(cls):
  class ArtResizer (line 322) | class ArtResizer(metaclass=Shareable):
    method __init__ (line 326) | def __init__(self):
    method resize (line 345) | def resize(
    method deinterlace (line 360) | def deinterlace(self, path_in, path_out=None):
    method proxy_url (line 367) | def proxy_url(self, maxwidth, url, quality=0):
    method local (line 378) | def local(self):
    method get_size (line 384) | def get_size(self, path_in):
    method get_format (line 394) | def get_format(self, path_in):
    method reformat (line 403) | def reformat(self, path_in, new_format, deinterlaced=True):
    method _can_compare (line 432) | def _can_compare(self):
    method _check_method (line 438) | def _check_method():
  function get_im_version (line 461) | def get_im_version():
  function get_pil_version (line 485) | def get_pil_version():

FILE: libs/common/beets/util/bluelet.py
  class Event (line 21) | class Event:
  class WaitableEvent (line 29) | class WaitableEvent(Event):
    method waitables (line 34) | def waitables(self):
    method fire (line 42) | def fire(self):
  class ValueEvent (line 49) | class ValueEvent(Event):
    method __init__ (line 51) | def __init__(self, value):
  class ExceptionEvent (line 55) | class ExceptionEvent(Event):
    method __init__ (line 57) | def __init__(self, exc_info):
  class SpawnEvent (line 61) | class SpawnEvent(Event):
    method __init__ (line 63) | def __init__(self, coro):
  class JoinEvent (line 67) | class JoinEvent(Event):
    method __init__ (line 71) | def __init__(self, child):
  class KillEvent (line 75) | class KillEvent(Event):
    method __init__ (line 77) | def __init__(self, child):
  class DelegationEvent (line 81) | class DelegationEvent(Event):
    method __init__ (line 86) | def __init__(self, coro):
  class ReturnEvent (line 90) | class ReturnEvent(Event):
    method __init__ (line 94) | def __init__(self, value):
  class SleepEvent (line 98) | class SleepEvent(WaitableEvent):
    method __init__ (line 101) | def __init__(self, duration):
    method time_left (line 104) | def time_left(self):
  class ReadEvent (line 108) | class ReadEvent(WaitableEvent):
    method __init__ (line 110) | def __init__(self, fd, bufsize):
    method waitables (line 114) | def waitables(self):
    method fire (line 117) | def fire(self):
  class WriteEvent (line 121) | class WriteEvent(WaitableEvent):
    method __init__ (line 123) | def __init__(self, fd, data):
    method waitable (line 127) | def waitable(self):
    method fire (line 130) | def fire(self):
  function _event_select (line 136) | def _event_select(events):
  class ThreadException (line 194) | class ThreadException(Exception):
    method __init__ (line 195) | def __init__(self, coro, exc_info):
    method reraise (line 199) | def reraise(self):
  class Delegated (line 206) | class Delegated(Event):
    method __init__ (line 210) | def __init__(self, child):
  function run (line 214) | def run(root_coro):
  class SocketClosedError (line 385) | class SocketClosedError(Exception):
  class Listener (line 389) | class Listener:
    method __init__ (line 392) | def __init__(self, host, port):
    method accept (line 403) | def accept(self):
    method close (line 412) | def close(self):
  class Connection (line 419) | class Connection:
    method __init__ (line 422) | def __init__(self, sock, addr):
    method close (line 428) | def close(self):
    method recv (line 433) | def recv(self, size):
    method send (line 446) | def send(self, data):
    method sendall (line 454) | def sendall(self, data):
    method readline (line 460) | def readline(self, terminator=b"\n", bufsize=1024):
  class AcceptEvent (line 481) | class AcceptEvent(WaitableEvent):
    method __init__ (line 485) | def __init__(self, listener):
    method waitables (line 488) | def waitables(self):
    method fire (line 491) | def fire(self):
  class ReceiveEvent (line 496) | class ReceiveEvent(WaitableEvent):
    method __init__ (line 500) | def __init__(self, conn, bufsize):
    method waitables (line 504) | def waitables(self):
    method fire (line 507) | def fire(self):
  class SendEvent (line 511) | class SendEvent(WaitableEvent):
    method __init__ (line 515) | def __init__(self, conn, data, sendall=False):
    method waitables (line 520) | def waitables(self):
    method fire (line 523) | def fire(self):
  function null (line 533) | def null():
  function spawn (line 539) | def spawn(coro):
  function call (line 548) | def call(coro):
  function end (line 558) | def end(value=None):
  function read (line 565) | def read(fd, bufsize=None):
  function write (line 583) | def write(fd, data):
  function connect (line 588) | def connect(host, port):
  function sleep (line 597) | def sleep(duration):
  function join (line 603) | def join(coro):
  function kill (line 610) | def kill(coro):
  function server (line 618) | def server(host, port, func):

FILE: libs/common/beets/util/enumeration.py
  class OrderedEnum (line 19) | class OrderedEnum(Enum):
    method __ge__ (line 23) | def __ge__(self, other):
    method __gt__ (line 28) | def __gt__(self, other):
    method __le__ (line 33) | def __le__(self, other):
    method __lt__ (line 38) | def __lt__(self, other):

FILE: libs/common/beets/util/functemplate.py
  class Environment (line 48) | class Environment:
    method __init__ (line 53) | def __init__(self, values, functions):
  function ex_lvalue (line 60) | def ex_lvalue(name):
  function ex_rvalue (line 65) | def ex_rvalue(name):
  function ex_literal (line 70) | def ex_literal(val):
  function ex_varassign (line 77) | def ex_varassign(name, expr):
  function ex_call (line 86) | def ex_call(func, args):
  function compile_func (line 102) | def compile_func(arg_names, statements, name='_the_func', debug=False):
  class Symbol (line 149) | class Symbol:
    method __init__ (line 152) | def __init__(self, ident, original):
    method __repr__ (line 156) | def __repr__(self):
    method evaluate (line 159) | def evaluate(self, env):
    method translate (line 170) | def translate(self):
  class Call (line 177) | class Call:
    method __init__ (line 180) | def __init__(self, ident, args, original):
    method __repr__ (line 185) | def __repr__(self):
    method evaluate (line 189) | def evaluate(self, env):
    method translate (line 205) | def translate(self):
  class Expression (line 236) | class Expression:
    method __init__ (line 241) | def __init__(self, parts):
    method __repr__ (line 244) | def __repr__(self):
    method evaluate (line 247) | def evaluate(self, env):
    method translate (line 259) | def translate(self):
  class ParseError (line 279) | class ParseError(Exception):
  class Parser (line 283) | class Parser:
    method __init__ (line 297) | def __init__(self, string, in_argument=False):
    method parse_expression (line 316) | def parse_expression(self):
    method parse_symbol (line 397) | def parse_symbol(self):
    method parse_call (line 441) | def parse_call(self):
    method parse_argument_list (line 480) | def parse_argument_list(self):
    method _parse_ident (line 509) | def _parse_ident(self):
  function _parse (line 519) | def _parse(template):
  function cached (line 533) | def cached(func):
  function template (line 545) | def template(fmt):
  class Template (line 550) | class Template:
    method __init__ (line 554) | def __init__(self, template):
    method __eq__ (line 559) | def __eq__(self, other):
    method interpret (line 562) | def interpret(self, values={}, functions={}):
    method substitute (line 570) | def substitute(self, values={}, functions={}):
    method translate (line 580) | def translate(self):

FILE: libs/common/beets/util/hidden.py
  function _is_hidden_osx (line 24) | def _is_hidden_osx(path):
  function _is_hidden_win (line 37) | def _is_hidden_win(path):
  function _is_hidden_dot (line 53) | def _is_hidden_dot(path):
  function is_hidden (line 61) | def is_hidden(path):

FILE: libs/common/beets/util/pipeline.py
  function _invalidate_queue (line 45) | def _invalidate_queue(q, val=None, sync=True):
  class CountedQueue (line 86) | class CountedQueue(queue.Queue):
    method __init__ (line 92) | def __init__(self, maxsize=0):
    method acquire (line 97) | def acquire(self):
    method release (line 106) | def release(self):
  class MultiMessage (line 136) | class MultiMessage:
    method __init__ (line 141) | def __init__(self, messages):
  function multiple (line 145) | def multiple(messages):
  function stage (line 152) | def stage(func):
  function mutator_stage (line 174) | def mutator_stage(func):
  function _allmsgs (line 197) | def _allmsgs(obj):
  class PipelineThread (line 210) | class PipelineThread(Thread):
    method __init__ (line 213) | def __init__(self, all_threads):
    method abort (line 220) | def abort(self):
    method abort_all (line 232) | def abort_all(self, exc_info):
  class FirstPipelineThread (line 240) | class FirstPipelineThread(PipelineThread):
    method __init__ (line 245) | def __init__(self, coro, out_queue, all_threads):
    method run (line 251) | def run(self):
  class MiddlePipelineThread (line 279) | class MiddlePipelineThread(PipelineThread):
    method __init__ (line 284) | def __init__(self, coro, in_queue, out_queue, all_threads):
    method run (line 291) | def run(self):
  class LastPipelineThread (line 328) | class LastPipelineThread(PipelineThread):
    method __init__ (line 333) | def __init__(self, coro, in_queue, all_threads):
    method run (line 338) | def run(self):
  class Pipeline (line 365) | class Pipeline:
    method __init__ (line 371) | def __init__(self, stages):
    method run_sequential (line 385) | def run_sequential(self):
    method run_parallel (line 392) | def run_parallel(self, queue_size=DEFAULT_QUEUE_SIZE):
    method pull (line 448) | def pull(self):
  function produce (line 480) | def produce():
  function work (line 486) | def work():
  function consume (line 493) | def consume():
  function exc_produce (line 512) | def exc_produce():
  function exc_work (line 518) | def exc_work():
  function exc_consume (line 527) | def exc_consume():

FILE: libs/common/beets/vfs.py
  function _insert (line 25) | def _insert(node, path, itemid):
  function libtree (line 39) | def libtree(lib):

FILE: libs/common/beetsplug/absubmit.py
  class ABSubmitError (line 37) | class ABSubmitError(Exception):
  function call (line 41) | def call(args):
  class AcousticBrainzSubmitPlugin (line 54) | class AcousticBrainzSubmitPlugin(plugins.BeetsPlugin):
    method __init__ (line 56) | def __init__(self):
    method commands (line 101) | def commands(self):
    method command (line 120) | def command(self, lib, opts, args):
    method analyze_submit (line 126) | def analyze_submit(self, item):
    method _get_analysis (line 131) | def _get_analysis(self, item):
    method _submit_data (line 179) | def _submit_data(self, item, data):

FILE: libs/common/beetsplug/acousticbrainz.py
  class AcousticPlugin (line 112) | class AcousticPlugin(plugins.BeetsPlugin):
    method __init__ (line 138) | def __init__(self):
    method commands (line 151) | def commands(self):
    method import_task_files (line 168) | def import_task_files(self, session, task):
    method _get_data (line 173) | def _get_data(self, mbid):
    method _fetch_info (line 196) | def _fetch_info(self, items, write, force):
    method _map_data_to_scheme (line 235) | def _map_data_to_scheme(self, data, scheme):
    method _data_to_scheme_child (line 298) | def _data_to_scheme_child(self, subdata, subscheme, composites):
  function _generate_urls (line 330) | def _generate_urls(mbid):

FILE: libs/common/beetsplug/albumtypes.py
  class AlbumTypesPlugin (line 23) | class AlbumTypesPlugin(BeetsPlugin):
    method __init__ (line 26) | def __init__(self):
    method _atypes (line 43) | def _atypes(self, item: Album):

FILE: libs/common/beetsplug/aura.py
  class AURADocument (line 121) | class AURADocument:
    method error (line 125) | def error(status, title, detail):
    method translate_filters (line 139) | def translate_filters(self):
    method translate_sorts (line 160) | def translate_sorts(self, sort_arg):
    method paginate (line 185) | def paginate(self, collection):
    method get_included (line 222) | def get_included(self, data, include_str):
    method all_resources (line 269) | def all_resources(self):
    method single_resource_document (line 300) | def single_resource_document(self, resource_object):
  class TrackDocument (line 317) | class TrackDocument(AURADocument):
    method get_collection (line 322) | def get_collection(self, query=None, sort=None):
    method get_attribute_converter (line 331) | def get_attribute_converter(self, beets_attr):
    method resource_object (line 352) | def resource_object(track):
    method single_resource (line 384) | def single_resource(self, track_id):
  class AlbumDocument (line 402) | class AlbumDocument(AURADocument):
    method get_collection (line 407) | def get_collection(self, query=None, sort=None):
    method get_attribute_converter (line 416) | def get_attribute_converter(self, beets_attr):
    method resource_object (line 433) | def resource_object(album):
    method single_resource (line 482) | def single_resource(self, album_id):
  class ArtistDocument (line 500) | class ArtistDocument(AURADocument):
    method get_collection (line 505) | def get_collection(self, query=None, sort=None):
    method get_attribute_converter (line 521) | def get_attribute_converter(self, beets_attr):
    method resource_object (line 538) | def resource_object(artist_id):
    method single_resource (line 581) | def single_resource(self, artist_id):
  function safe_filename (line 599) | def safe_filename(fn):
  class ImageDocument (line 617) | class ImageDocument(AURADocument):
    method get_image_path (line 621) | def get_image_path(image_id):
    method resource_object (line 663) | def resource_object(image_id):
    method single_resource (line 705) | def single_resource(self, image_id):
  function server_info (line 729) | def server_info():
  function all_tracks (line 738) | def all_tracks():
  function single_track (line 745) | def single_track(track_id):
  function audio_file (line 756) | def audio_file(track_id):
  function all_albums (line 822) | def all_albums():
  function single_album (line 829) | def single_album(album_id):
  function all_artists (line 844) | def all_artists():
  function single_artist (line 852) | def single_artist(artist_id):
  function single_image (line 869) | def single_image(image_id):
  function image_file (line 881) | def image_file(image_id):
  function create_app (line 903) | def create_app():
  class AURAPlugin (line 948) | class AURAPlugin(BeetsPlugin):
    method __init__ (line 951) | def __init__(self):
    method commands (line 955) | def commands(self):

FILE: libs/common/beetsplug/badfiles.py
  class CheckerCommandException (line 33) | class CheckerCommandException(Exception):
    method __init__ (line 43) | def __init__(self, cmd, oserror):
  class BadFiles (line 50) | class BadFiles(BeetsPlugin):
    method __init__ (line 51) | def __init__(self):
    method run_command (line 60) | def run_command(self, cmd):
    method check_mp3val (line 76) | def check_mp3val(self, path):
    method check_flac (line 83) | def check_flac(self, path):
    method check_custom (line 86) | def check_custom(self, command):
    method get_checker (line 93) | def get_checker(self, ext):
    method check_item (line 106) | def check_item(self, item):
    method on_import_task_start (line 159) | def on_import_task_start(self, task, session):
    method on_import_task_before_choice (line 173) | def on_import_task_before_choice(self, task, session):
    method command (line 195) | def command(self, lib, opts, args):
    method commands (line 206) | def commands(self):

FILE: libs/common/beetsplug/bareasc.py
  class BareascQuery (line 29) | class BareascQuery(StringFieldQuery):
    method string_match (line 32) | def string_match(cls, pattern, val):
  class BareascPlugin (line 46) | class BareascPlugin(BeetsPlugin):
    method __init__ (line 48) | def __init__(self):
    method queries (line 55) | def queries(self):
    method commands (line 60) | def commands(self):
    method unidecode_list (line 70) | def unidecode_list(self, lib, opts, args):

FILE: libs/common/beetsplug/beatport.py
  class BeatportAPIError (line 37) | class BeatportAPIError(Exception):
  class BeatportObject (line 41) | class BeatportObject:
    method __init__ (line 42) | def __init__(self, data):
  class BeatportClient (line 56) | class BeatportClient:
    method __init__ (line 59) | def __init__(self, c_key, c_secret, auth_key=None, auth_secret=None):
    method get_authorize_url (line 78) | def get_authorize_url(self):
    method get_access_token (line 98) | def get_access_token(self, auth_data):
    method search (line 114) | def search(self, query, release_type='release', details=True):
    method get_release (line 142) | def get_release(self, beatport_id):
    method get_release_tracks (line 156) | def get_release_tracks(self, beatport_id):
    method get_track (line 167) | def get_track(self, beatport_id):
    method _make_url (line 177) | def _make_url(self, endpoint):
    method _get (line 183) | def _get(self, endpoint, **kwargs):
  class BeatportRelease (line 201) | class BeatportRelease(BeatportObject):
    method __str__ (line 202) | def __str__(self):
    method __repr__ (line 213) | def __repr__(self):
    method __init__ (line 216) | def __init__(self, data):
  class BeatportTrack (line 230) | class BeatportTrack(BeatportObject):
    method __str__ (line 231) | def __str__(self):
    method __repr__ (line 236) | def __repr__(self):
    method __init__ (line 239) | def __init__(self, data):
  class BeatportPlugin (line 268) | class BeatportPlugin(BeetsPlugin):
    method __init__ (line 271) | def __init__(self):
    method setup (line 284) | def setup(self, session=None):
    method authenticate (line 301) | def authenticate(self, c_key, c_secret):
    method _tokenfile (line 328) | def _tokenfile(self):
    method album_distance (line 333) | def album_distance(self, items, album_info, mapping):
    method track_distance (line 343) | def track_distance(self, item, track_info):
    method candidates (line 353) | def candidates(self, items, artist, release, va_likely, extra_tags=None):
    method item_candidates (line 367) | def item_candidates(self, item, artist, title):
    method album_for_id (line 378) | def album_for_id(self, release_id):
    method track_for_id (line 392) | def track_for_id(self, track_id):
    method _get_releases (line 406) | def _get_releases(self, query):
    method _get_album_info (line 421) | def _get_album_info(self, release):
    method _get_track_info (line 441) | def _get_track_info(self, track):
    method _get_artist (line 457) | def _get_artist(self, artists):
    method _get_tracks (line 465) | def _get_tracks(self, query):

FILE: libs/common/beetsplug/bench.py
  function aunique_benchmark (line 31) | def aunique_benchmark(lib, prof):
  function match_benchmark (line 60) | def match_benchmark(lib, prof, query=None, album_id=None):
  class BenchmarkPlugin (line 85) | class BenchmarkPlugin(BeetsPlugin):
    method commands (line 88) | def commands(self):

FILE: libs/common/beetsplug/bpd/__init__.py
  class NoGstreamerError (line 86) | class NoGstreamerError(Exception):
  class BPDError (line 92) | class BPDError(Exception):
    method __init__ (line 96) | def __init__(self, code, message, cmd_name='', index=0):
    method response (line 104) | def response(self):
  function make_bpd_error (line 117) | def make_bpd_error(s_code, s_message):
  function cast_arg (line 136) | def cast_arg(t, val):
  class BPDClose (line 152) | class BPDClose(Exception):
  class BPDIdle (line 158) | class BPDIdle(Exception):
    method __init__ (line 162) | def __init__(self, subsystems):
  class BaseServer (line 170) | class BaseServer:
    method __init__ (line 183) | def __init__(self, host, port, password, ctrl_port, log, ctrl_host=None):
    method connect (line 218) | def connect(self, conn):
    method disconnect (line 223) | def disconnect(self, conn):
    method run (line 228) | def run(self):
    method dispatch_events (line 242) | def dispatch_events(self):
    method _ctrl_send (line 250) | def _ctrl_send(self, message):
    method _send_event (line 260) | def _send_event(self, event):
    method _item_info (line 265) | def _item_info(self, item):
    method _item_id (line 271) | def _item_id(self, item):
    method _id_to_index (line 276) | def _id_to_index(self, track_id):
    method _random_idx (line 287) | def _random_idx(self):
    method _succ_idx (line 299) | def _succ_idx(self):
    method _prev_idx (line 310) | def _prev_idx(self):
    method cmd_ping (line 321) | def cmd_ping(self, conn):
    method cmd_idle (line 325) | def cmd_idle(self, conn, *subsystems):
    method cmd_kill (line 333) | def cmd_kill(self, conn):
    method cmd_close (line 337) | def cmd_close(self, conn):
    method cmd_password (line 341) | def cmd_password(self, conn, password):
    method cmd_commands (line 349) | def cmd_commands(self, conn):
    method cmd_notcommands (line 362) | def cmd_notcommands(self, conn):
    method cmd_status (line 376) | def cmd_status(self, conn):
    method cmd_clearerror (line 422) | def cmd_clearerror(self, conn):
    method cmd_random (line 429) | def cmd_random(self, conn, state):
    method cmd_repeat (line 434) | def cmd_repeat(self, conn, state):
    method cmd_consume (line 439) | def cmd_consume(self, conn, state):
    method cmd_single (line 444) | def cmd_single(self, conn, state):
    method cmd_setvol (line 450) | def cmd_setvol(self, conn, vol):
    method cmd_volume (line 458) | def cmd_volume(self, conn, vol_delta):
    method cmd_crossfade (line 463) | def cmd_crossfade(self, conn, crossfade):
    method cmd_mixrampdb (line 472) | def cmd_mixrampdb(self, conn, db):
    method cmd_mixrampdelay (line 481) | def cmd_mixrampdelay(self, conn, delay):
    method cmd_replay_gain_mode (line 490) | def cmd_replay_gain_mode(self, conn, mode):
    method cmd_replay_gain_status (line 498) | def cmd_replay_gain_status(self, conn):
    method cmd_clear (line 502) | def cmd_clear(self, conn):
    method cmd_delete (line 509) | def cmd_delete(self, conn, index):
    method cmd_deleteid (line 525) | def cmd_deleteid(self, conn, track_id):
    method cmd_move (line 528) | def cmd_move(self, conn, idx_from, idx_to):
    method cmd_moveid (line 549) | def cmd_moveid(self, conn, idx_from, idx_to):
    method cmd_swap (line 553) | def cmd_swap(self, conn, i, j):
    method cmd_swapid (line 575) | def cmd_swapid(self, conn, i_id, j_id):
    method cmd_urlhandlers (line 580) | def cmd_urlhandlers(self, conn):
    method cmd_playlistinfo (line 584) | def cmd_playlistinfo(self, conn, index=None):
    method cmd_playlistid (line 600) | def cmd_playlistid(self, conn, track_id=None):
    method cmd_plchanges (line 606) | def cmd_plchanges(self, conn, version):
    method cmd_plchangesposid (line 615) | def cmd_plchangesposid(self, conn, version):
    method cmd_currentsong (line 624) | def cmd_currentsong(self, conn):
    method cmd_next (line 631) | def cmd_next(self, conn):
    method cmd_previous (line 653) | def cmd_previous(self, conn):
    method cmd_pause (line 666) | def cmd_pause(self, conn, state=None):
    method cmd_play (line 674) | def cmd_play(self, conn, index=-1):
    method cmd_playid (line 694) | def cmd_playid(self, conn, track_id=0):
    method cmd_stop (line 702) | def cmd_stop(self, conn):
    method cmd_seek (line 708) | def cmd_seek(self, conn, index, pos):
    method cmd_seekid (line 716) | def cmd_seekid(self, conn, track_id, pos):
    method cmd_crash_TypeError (line 722) | def cmd_crash_TypeError(self, conn):  # noqa: N802
  class Connection (line 731) | class Connection:
    method __init__ (line 734) | def __init__(self, server, sock):
    method debug (line 741) | def debug(self, message, kind=' '):
    method run (line 746) | def run(self):
    method send (line 749) | def send(self, lines):
    method handler (line 765) | def handler(cls, server):
  class MPDConnection (line 773) | class MPDConnection(Connection):
    method __init__ (line 776) | def __init__(self, server, sock):
    method do_command (line 784) | def do_command(self, command):
    method disconnect (line 796) | def disconnect(self):
    method notify (line 802) | def notify(self, event):
    method send_notifications (line 807) | def send_notifications(self, force_close_idle=False):
    method run (line 821) | def run(self):
  class ControlConnection (line 888) | class ControlConnection(Connection):
    method __init__ (line 891) | def __init__(self, server, sock):
    method debug (line 896) | def debug(self, message, kind=' '):
    method run (line 899) | def run(self):
    method ctrl_play_finished (line 923) | def ctrl_play_finished(self):
    method ctrl_profile (line 928) | def ctrl_profile(self):
    method ctrl_nickname (line 935) | def ctrl_nickname(self, oldlabel, newlabel):
  class Command (line 946) | class Command:
    method __init__ (line 953) | def __init__(self, s):
    method delegate (line 972) | def delegate(self, prefix, target, extra_args=0):
    method run (line 1002) | def run(self, conn):
  class CommandList (line 1047) | class CommandList(list):
    method __init__ (line 1053) | def __init__(self, sequence=None, verbose=False):
    method run (line 1062) | def run(self, conn):
  class Server (line 1082) | class Server(BaseServer):
    method __init__ (line 1087) | def __init__(self, library, host, port, password, ctrl_port, log):
    method run (line 1106) | def run(self):
    method play_finished (line 1110) | def play_finished(self):
    method _item_info (line 1118) | def _item_info(self, item):
    method _parse_range (line 1139) | def _parse_range(self, items, accept_single_number=False):
    method _item_id (line 1154) | def _item_id(self, item):
    method cmd_update (line 1159) | def cmd_update(self, conn, path='/'):
    method _resolve_path (line 1173) | def _resolve_path(self, path):
    method _path_join (line 1197) | def _path_join(self, p1, p2):
    method cmd_lsinfo (line 1202) | def cmd_lsinfo(self, conn, path="/"):
    method _listall (line 1219) | def _listall(self, basepath, node, info=False):
    method cmd_listall (line 1241) | def cmd_listall(self, conn, path="/"):
    method cmd_listallinfo (line 1245) | def cmd_listallinfo(self, conn, path="/"):
    method _all_items (line 1251) | def _all_items(self, node):
    method _add (line 1266) | def _add(self, path, send_id=False):
    method cmd_add (line 1277) | def cmd_add(self, conn, path):
    method cmd_addid (line 1283) | def cmd_addid(self, conn, path):
    method cmd_status (line 1289) | def cmd_status(self, conn):
    method cmd_stats (line 1315) | def cmd_stats(self, conn):
    method cmd_decoders (line 1335) | def cmd_decoders(self, conn):
    method cmd_tagtypes (line 1369) | def cmd_tagtypes(self, conn):
    method _tagtype_lookup (line 1376) | def _tagtype_lookup(self, tag):
    method _metadata_query (line 1388) | def _metadata_query(self, query_type, any_query_type, kv):
    method cmd_search (line 1413) | def cmd_search(self, conn, *kv):
    method cmd_find (line 1421) | def cmd_find(self, conn, *kv):
    method cmd_list (line 1429) | def cmd_list(self, conn, show_tag, *kv):
    method cmd_count (line 1461) | def cmd_count(self, conn, tag, value):
    method cmd_listplaylist (line 1477) | def cmd_listplaylist(self, conn, playlist):
    method cmd_listplaylistinfo (line 1480) | def cmd_listplaylistinfo(self, conn, playlist):
    method cmd_listplaylists (line 1483) | def cmd_listplaylists(self, conn):
    method cmd_load (line 1486) | def cmd_load(self, conn, playlist):
    method cmd_playlistadd (line 1489) | def cmd_playlistadd(self, conn, playlist, uri):
    method cmd_playlistclear (line 1492) | def cmd_playlistclear(self, conn, playlist):
    method cmd_playlistdelete (line 1495) | def cmd_playlistdelete(self, conn, playlist, index):
    method cmd_playlistmove (line 1498) | def cmd_playlistmove(self, conn, playlist, from_index, to_index):
    method cmd_rename (line 1501) | def cmd_rename(self, conn, playlist, new_name):
    method cmd_rm (line 1504) | def cmd_rm(self, conn, playlist):
    method cmd_save (line 1507) | def cmd_save(self, conn, playlist):
    method cmd_outputs (line 1513) | def cmd_outputs(self, conn):
    method cmd_enableoutput (line 1521) | def cmd_enableoutput(self, conn, output_id):
    method cmd_disableoutput (line 1526) | def cmd_disableoutput(self, conn, output_id):
    method cmd_play (line 1537) | def cmd_play(self, conn, index=-1):
    method cmd_pause (line 1549) | def cmd_pause(self, conn, state=None):
    method cmd_stop (line 1556) | def cmd_stop(self, conn):
    method cmd_seek (line 1560) | def cmd_seek(self, conn, index, pos):
    method cmd_setvol (line 1569) | def cmd_setvol(self, conn, vol):
  class BPDPlugin (line 1577) | class BPDPlugin(BeetsPlugin):
    method __init__ (line 1581) | def __init__(self):
    method start_bpd (line 1592) | def start_bpd(self, lib, host, port, password, volume, ctrl_port):
    method commands (line 1603) | def commands(self):

FILE: libs/common/beetsplug/bpd/gstplayer.py
  class QueryError (line 36) | class QueryError(Exception):
  class GstPlayer (line 40) | class GstPlayer:
    method __init__ (line 53) | def __init__(self, finished_callback=None):
    method _get_state (line 90) | def _get_state(self):
    method _handle_message (line 96) | def _handle_message(self, bus, message):
    method _set_volume (line 113) | def _set_volume(self, volume):
    method _get_volume (line 119) | def _get_volume(self):
    method play_file (line 125) | def play_file(self, path):
    method play (line 137) | def play(self):
    method pause (line 143) | def pause(self):
    method stop (line 147) | def stop(self):
    method run (line 153) | def run(self):
    method time (line 168) | def time(self):
    method seek (line 197) | def seek(self, position):
    method block (line 211) | def block(self):
    method get_decoders (line 216) | def get_decoders(self):
  function get_decoders (line 220) | def get_decoders():
  function play_simple (line 270) | def play_simple(paths):
  function play_complicated (line 281) | def play_complicated(paths):

FILE: libs/common/beetsplug/bpm.py
  function bpm (line 24) | def bpm(max_strokes):
  class BPMPlugin (line 48) | class BPMPlugin(BeetsPlugin):
    method __init__ (line 50) | def __init__(self):
    method commands (line 57) | def commands(self):
    method command (line 64) | def command(self, lib, opts, args):
    method get_bpm (line 69) | def get_bpm(self, items, write=False):

FILE: libs/common/beetsplug/bpsync.py
  class BPSyncPlugin (line 24) | class BPSyncPlugin(BeetsPlugin):
    method __init__ (line 25) | def __init__(self):
    method commands (line 30) | def commands(self):
    method func (line 64) | def func(self, lib, opts, args):
    method singletons (line 75) | def singletons(self, lib, query, move, pretend, write):
    method is_beatport_track (line 101) | def is_beatport_track(item):
    method get_album_tracks (line 107) | def get_album_tracks(self, album):
    method albums (line 130) | def albums(self, lib, query, move, pretend, write):

FILE: libs/common/beetsplug/bucket.py
  class BucketError (line 30) | class BucketError(Exception):
  function pairwise (line 34) | def pairwise(iterable):
  function span_from_str (line 41) | def span_from_str(span_str):
  function complete_year_spans (line 76) | def complete_year_spans(spans):
  function extend_year_spans (line 87) | def extend_year_spans(spans, spanlen, start=1900, end=2014):
  function build_year_spans (line 108) | def build_year_spans(year_spans_str):
  function str2fmt (line 119) | def str2fmt(s):
  function format_span (line 135) | def format_span(fmt, yearfrom, yearto, fromnchars, tonchars):
  function extract_modes (line 145) | def extract_modes(spans):
  function build_alpha_spans (line 155) | def build_alpha_spans(alpha_spans_str, alpha_regexs):
  class BucketPlugin (line 182) | class BucketPlugin(plugins.BeetsPlugin):
    method __init__ (line 183) | def __init__(self):
    method setup (line 195) | def setup(self):
    method find_bucket_year (line 210) | def find_bucket_year(self, year):
    method find_bucket_alpha (line 225) | def find_bucket_alpha(self, s):
    method _tmpl_bucket (line 234) | def _tmpl_bucket(self, text, field=None):

FILE: libs/common/beetsplug/chroma.py
  function prefix (line 51) | def prefix(it, count):
  function releases_key (line 60) | def releases_key(release, countries, original_year):
  function acoustid_match (line 84) | def acoustid_match(log, path):
  function _all_releases (line 147) | def _all_releases(items):
  class AcoustidPlugin (line 166) | class AcoustidPlugin(plugins.BeetsPlugin):
    method __init__ (line 167) | def __init__(self):
    method fingerprint_task (line 179) | def fingerprint_task(self, task, session):
    method track_distance (line 182) | def track_distance(self, item, info):
    method candidates (line 192) | def candidates(self, items, artist, album, va_likely, extra_tags=None):
    method item_candidates (line 202) | def item_candidates(self, item, artist, title):
    method commands (line 215) | def commands(self):
  function fingerprint_task (line 243) | def fingerprint_task(log, task, session):
  function apply_acoustid_metadata (line 252) | def apply_acoustid_metadata(task, session):
  function submit_items (line 265) | def submit_items(log, userkey, items, chunksize=64):
  function fingerprint_item (line 312) | def fingerprint_item(log, item, write=False):

FILE: libs/common/beetsplug/convert.py
  function replace_ext (line 46) | def replace_ext(path, ext):
  function get_format (line 55) | def get_format(fmt=None):
  function should_transcode (line 90) | def should_transcode(item, fmt):
  class ConvertPlugin (line 108) | class ConvertPlugin(BeetsPlugin):
    method __init__ (line 109) | def __init__(self):
    method commands (line 154) | def commands(self):
    method auto_convert (line 181) | def auto_convert(self, config, task):
    method encode (line 188) | def encode(self, command, source, dest, pretend=False):
    method convert_item (line 246) | def convert_item(self, dest_dir, keep_new, path_formats, fmt,
    method copy_album_art (line 357) | def copy_album_art(self, album, dest_dir, path_formats, pretend=False,
    method convert_func (line 433) | def convert_func(self, lib, opts, args):
    method convert_on_import (line 494) | def convert_on_import(self, lib, item):
    method _cleanup (line 529) | def _cleanup(self, task, session):

FILE: libs/common/beetsplug/deezer.py
  class DeezerPlugin (line 28) | class DeezerPlugin(MetadataSourcePlugin, BeetsPlugin):
    method __init__ (line 42) | def __init__(self):
    method album_for_id (line 45) | def album_for_id(self, album_id):
    method _get_track (line 114) | def _get_track(self, track_data):
    method track_for_id (line 138) | def track_for_id(self, track_id=None, track_data=None):
    method _construct_search_query (line 174) | def _construct_search_query(filters=None, keywords=''):
    method _search_api (line 195) | def _search_api(self, query_type, filters=None, keywords=''):

FILE: libs/common/beetsplug/discogs.py
  class DiscogsPlugin (line 48) | class DiscogsPlugin(BeetsPlugin):
    method __init__ (line 50) | def __init__(self):
    method setup (line 67) | def setup(self, session=None):
    method reset_auth (line 95) | def reset_auth(self):
    method _tokenfile (line 101) | def _tokenfile(self):
    method authenticate (line 106) | def authenticate(self, c_key, c_secret):
    method album_distance (line 135) | def album_distance(self, items, album_info, mapping):
    method track_distance (line 144) | def track_distance(self, item, track_info):
    method candidates (line 153) | def candidates(self, items, artist, album, va_likely, extra_tags=None):
    method extract_release_id_regex (line 178) | def extract_release_id_regex(album_id):
    method album_for_id (line 202) | def album_for_id(self, album_id):
    method get_albums (line 234) | def get_albums(self, query):
    method get_master_year (line 257) | def get_master_year(self, master_id):
    method get_album_info (line 280) | def get_album_info(self, result):
    method format (line 362) | def format(self, classification):
    method extract_release_id (line 369) | def extract_release_id(self, uri):
    method get_tracks (line 375) | def get_tracks(self, tracklist):
    method coalesce_tracks (line 471) | def coalesce_tracks(self, raw_tracklist):
    method get_track_info (line 552) | def get_track_info(self, track, index, divisions):
    method get_track_index (line 570) | def get_track_index(self, position):
    method get_track_length (line 599) | def get_track_length(self, duration):

FILE: libs/common/beetsplug/duplicates.py
  class DuplicatesPlugin (line 30) | class DuplicatesPlugin(BeetsPlugin):
    method __init__ (line 33) | def __init__(self):
    method commands (line 108) | def commands(self):
    method _process_item (line 175) | def _process_item(self, item, copy=False, move=False, delete=False,
    method _checksum (line 198) | def _checksum(self, item, prog):
    method _group_by (line 226) | def _group_by(self, objs, keys, strict):
    method _order (line 251) | def _order(self, objs, tiebreak=None):
    method _merge_items (line 279) | def _merge_items(self, objs):
    method _merge_albums (line 300) | def _merge_albums(self, objs):
    method _merge (line 321) | def _merge(self, objs):
    method _duplicates (line 332) | def _duplicates(self, objs, keys, full, strict, tiebreak, merge):

FILE: libs/common/beetsplug/edit.py
  class ParseError (line 37) | class ParseError(Exception):
  function edit (line 43) | def edit(filename, log):
  function dump (line 57) | def dump(arg):
  function load (line 67) | def load(s):
  function _safe_value (line 92) | def _safe_value(obj, key, value):
  function flatten (line 103) | def flatten(obj, fields):
  function apply_ (line 129) | def apply_(obj, data):
  class EditPlugin (line 147) | class EditPlugin(plugins.BeetsPlugin):
    method __init__ (line 149) | def __init__(self):
    method commands (line 164) | def commands(self):
    method _edit_command (line 184) | def _edit_command(self, lib, opts, args):
    method _get_fields (line 202) | def _get_fields(self, album, extra):
    method edit (line 220) | def edit(self, album, objs, fields):
    method edit_objects (line 235) | def edit_objects(self, objs, fields):
    method apply_data (line 310) | def apply_data(self, objs, old_data, new_data):
    method save_changes (line 338) | def save_changes(self, objs):
    method before_choose_candidate_listener (line 349) | def before_choose_candidate_listener(self, session, task):
    method importer_edit (line 360) | def importer_edit(self, session, task):
    method importer_edit_candidate (line 391) | def importer_edit_candidate(self, session, task):

FILE: libs/common/beetsplug/embedart.py
  function _confirm (line 28) | def _confirm(objs, album):
  class EmbedCoverArtPlugin (line 50) | class EmbedCoverArtPlugin(BeetsPlugin):
    method __init__ (line 53) | def __init__(self):
    method commands (line 76) | def commands(self):
    method process_album (line 182) | def process_album(self, album):
    method remove_artfile (line 192) | def remove_artfile(self, album):

FILE: libs/common/beetsplug/embyupdate.py
  function api_url (line 19) | def api_url(host, port, endpoint):
  function password_data (line 58) | def password_data(username, password):
  function create_headers (line 75) | def create_headers(user_id, token=None):
  function get_token (line 103) | def get_token(host, port, headers, auth_data):
  function get_user (line 123) | def get_user(host, port, username):
  class EmbyUpdate (line 142) | class EmbyUpdate(BeetsPlugin):
    method __init__ (line 143) | def __init__(self):
    method listen_for_db_change (line 156) | def listen_for_db_change(self, lib, model):
    method update (line 161) | def update(self, lib):

FILE: libs/common/beetsplug/export.py
  class ExportEncoder (line 32) | class ExportEncoder(json.JSONEncoder):
    method default (line 34) | def default(self, o):
  class ExportPlugin (line 40) | class ExportPlugin(BeetsPlugin):
    method __init__ (line 42) | def __init__(self):
    method commands (line 81) | def commands(self):
    method run (line 111) | def run(self, lib, opts, args):
  class ExportFormat (line 159) | class ExportFormat:
    method __init__ (line 161) | def __init__(self, file_path, file_mode='w', encoding='utf-8'):
    method factory (line 170) | def factory(cls, file_type, **kwargs):
    method export (line 180) | def export(self, data, **kwargs):
  class JsonFormat (line 184) | class JsonFormat(ExportFormat):
    method __init__ (line 186) | def __init__(self, file_path, file_mode='w', encoding='utf-8'):
    method export (line 189) | def export(self, data, **kwargs):
  class CSVFormat (line 194) | class CSVFormat(ExportFormat):
    method __init__ (line 196) | def __init__(self, file_path, file_mode='w', encoding='utf-8'):
    method export (line 199) | def export(self, data, **kwargs):
  class XMLFormat (line 206) | class XMLFormat(ExportFormat):
    method __init__ (line 208) | def __init__(self, file_path, file_mode='w', encoding='utf-8'):
    method export (line 211) | def export(self, data, **kwargs):

FILE: libs/common/beetsplug/fetchart.py
  class Candidate (line 44) | class Candidate:
    method __init__ (line 58) | def __init__(self, log, path=None, url=None, source='',
    method _validate (line 68) | def _validate(self, plugin):
    method validate (line 168) | def validate(self, plugin):
    method resize (line 172) | def resize(self, plugin):
  function _logged_get (line 194) | def _logged_get(log, *args, **kwargs):
  class RequestMixin (line 232) | class RequestMixin:
    method request (line 237) | def request(self, *args, **kwargs):
  class ArtSource (line 247) | class ArtSource(RequestMixin):
    method __init__ (line 250) | def __init__(self, log, config, match_by=None):
    method get (line 255) | def get(self, album, plugin, paths):
    method _candidate (line 258) | def _candidate(self, **kwargs):
    method fetch_image (line 261) | def fetch_image(self, candidate, plugin):
    method cleanup (line 264) | def cleanup(self, candidate):
  class LocalArtSource (line 268) | class LocalArtSource(ArtSource):
    method fetch_image (line 272) | def fetch_image(self, candidate, plugin):
  class RemoteArtSource (line 276) | class RemoteArtSource(ArtSource):
    method fetch_image (line 280) | def fetch_image(self, candidate, plugin):
    method cleanup (line 348) | def cleanup(self, candidate):
  class CoverArtArchive (line 356) | class CoverArtArchive(RemoteArtSource):
    method get (line 364) | def get(self, album, plugin, paths):
  class Amazon (line 416) | class Amazon(RemoteArtSource):
    method get (line 421) | def get(self, album, plugin, paths):
  class AlbumArtOrg (line 430) | class AlbumArtOrg(RemoteArtSource):
    method get (line 435) | def get(self, album, plugin, paths):
  class GoogleImages (line 457) | class GoogleImages(RemoteArtSource):
    method __init__ (line 461) | def __init__(self, *args, **kwargs):
    method get (line 466) | def get(self, album, plugin, paths):
  class FanartTV (line 504) | class FanartTV(RemoteArtSource):
    method __init__ (line 511) | def __init__(self, *args, **kwargs):
    method get (line 515) | def get(self, album, plugin, paths):
  class ITunesStore (line 567) | class ITunesStore(RemoteArtSource):
    method get (line 571) | def get(self, album, plugin, paths):
  class Wikipedia (line 637) | class Wikipedia(RemoteArtSource):
    method get (line 663) | def get(self, album, plugin, paths):
  class FileSystem (line 776) | class FileSystem(LocalArtSource):
    method filename_priority (line 780) | def filename_priority(filename, cover_names):
    method get (line 789) | def get(self, album, plugin, paths):
  class LastFM (line 837) | class LastFM(RemoteArtSource):
    method __init__ (line 851) | def __init__(self, *args, **kwargs):
    method get (line 855) | def get(self, album, plugin, paths):
  class FetchArtPlugin (line 917) | class FetchArtPlugin(plugins.BeetsPlugin, RequestMixin):
    method __init__ (line 921) | def __init__(self):
    method fetch_art (line 1025) | def fetch_art(self, session, task):
    method _set_art (line 1047) | def _set_art(self, album, candidate, delete=False):
    method assign_art (line 1058) | def assign_art(self, session, task):
    method commands (line 1069) | def commands(self):
    method art_for_album (line 1090) | def art_for_album(self, album, paths, local_only=False):
    method batch_fetch_art (line 1127) | def batch_fetch_art(self, lib, albums, force, quiet):

FILE: libs/common/beetsplug/filefilter.py
  class FileFilterPlugin (line 26) | class FileFilterPlugin(BeetsPlugin):
    method __init__ (line 27) | def __init__(self):
    method import_task_created_event (line 47) | def import_task_created_event(self, session, task):
    method file_filter (line 67) | def file_filter(self, full_path):

FILE: libs/common/beetsplug/fish.py
  class FishPlugin (line 68) | class FishPlugin(BeetsPlugin):
    method commands (line 70) | def commands(self):
    method run (line 86) | def run(self, lib, opts, args):
  function _escape (line 134) | def _escape(name):
  function get_cmds_list (line 141) | def get_cmds_list(cmds_names):
  function get_standard_fields (line 150) | def get_standard_fields(fields):
  function get_extravalues (line 160) | def get_extravalues(lib, extravalues):
  function get_set_of_values_for_field (line 174) | def get_set_of_values_for_field(lib, fields):
  function get_basic_beet_options (line 185) | def get_basic_beet_options():
  function get_subcommands (line 205) | def get_subcommands(cmd_name_and_help, nobasicfields, extravalues):
  function get_all_commands (line 235) | def get_all_commands(beetcmds):
  function clean_whitespace (line 272) | def clean_whitespace(word):
  function wrap (line 277) | def wrap(word):

FILE: libs/common/beetsplug/freedesktop.py
  class FreedesktopPlugin (line 23) | class FreedesktopPlugin(BeetsPlugin):
    method commands (line 24) | def commands(self):
    method deprecation_message (line 31) | def deprecation_message(self, lib, opts, args):

FILE: libs/common/beetsplug/fromfilename.py
  function equal (line 45) | def equal(seq):
  function equal_fields (line 51) | def equal_fields(matchdict, field):
  function all_matches (line 59) | def all_matches(names, pattern):
  function bad_title (line 78) | def bad_title(title):
  function apply_matches (line 88) | def apply_matches(d):
  class FromFilenamePlugin (line 131) | class FromFilenamePlugin(plugins.BeetsPlugin):
    method __init__ (line 132) | def __init__(self):
  function filename_task (line 137) | def filename_task(task, session):

FILE: libs/common/beetsplug/ftintitle.py
  function split_on_feat (line 25) | def split_on_feat(artist):
  function contains_feat (line 40) | def contains_feat(title):
  function find_feat_part (line 46) | def find_feat_part(artist, albumartist):
  class FtInTitlePlugin (line 74) | class FtInTitlePlugin(plugins.BeetsPlugin):
    method __init__ (line 75) | def __init__(self):
    method commands (line 96) | def commands(self):
    method imported (line 112) | def imported(self, session, task):
    method update_metadata (line 121) | def update_metadata(self, item, feat_part, drop_feat):
    method ft_in_title (line 143) | def ft_in_title(self, item, drop_feat):

FILE: libs/common/beetsplug/fuzzy.py
  class FuzzyQuery (line 25) | class FuzzyQuery(StringFieldQuery):
    method string_match (line 27) | def string_match(cls, pattern, val):
  class FuzzyPlugin (line 36) | class FuzzyPlugin(BeetsPlugin):
    method __init__ (line 37) | def __init__(self):
    method queries (line 44) | def queries(self):

FILE: libs/common/beetsplug/gmusic.py
  class Gmusic (line 19) | class Gmusic(BeetsPlugin):
    method __init__ (line 20) | def __init__(self):

FILE: libs/common/beetsplug/hook.py
  class CodingFormatter (line 25) | class CodingFormatter(string.Formatter):
    method __init__ (line 35) | def __init__(self, coding):
    method format (line 39) | def format(self, format_string, *args, **kwargs):
    method convert_field (line 53) | def convert_field(self, value, conversion):
  class HookPlugin (line 69) | class HookPlugin(BeetsPlugin):
    method __init__ (line 72) | def __init__(self):
    method create_and_register_hook (line 89) | def create_and_register_hook(self, event, command):

FILE: libs/common/beetsplug/ihate.py
  function summary (line 29) | def summary(task):
  class IHatePlugin (line 39) | class IHatePlugin(BeetsPlugin):
    method __init__ (line 40) | def __init__(self):
    method do_i_hate_this (line 50) | def do_i_hate_this(cls, task, action_patterns):
    method import_task_choice_event (line 64) | def import_task_choice_event(self, session, task):

FILE: libs/common/beetsplug/importadded.py
  class ImportAddedPlugin (line 14) | class ImportAddedPlugin(BeetsPlugin):
    method __init__ (line 15) | def __init__(self):
    method check_config (line 41) | def check_config(self, task, session):
    method reimported_item (line 44) | def reimported_item(self, item):
    method reimported_album (line 47) | def reimported_album(self, album):
    method record_if_inplace (line 50) | def record_if_inplace(self, task, session):
    method record_reimported (line 61) | def record_reimported(self, task, session):
    method write_file_mtime (line 67) | def write_file_mtime(self, path, mtime):
    method write_item_mtime (line 73) | def write_item_mtime(self, item, mtime):
    method record_import_mtime (line 81) | def record_import_mtime(self, item, source, destination):
    method update_album_times (line 90) | def update_album_times(self, lib, album):
    method update_item_times (line 110) | def update_item_times(self, lib, item):
    method update_after_write_time (line 124) | def update_after_write_time(self, item, path):

FILE: libs/common/beetsplug/importfeeds.py
  function _build_m3u_filename (line 31) | def _build_m3u_filename(basename):
  function _write_m3u (line 44) | def _write_m3u(m3u_path, items_paths):
  class ImportFeedsPlugin (line 53) | class ImportFeedsPlugin(BeetsPlugin):
    method __init__ (line 54) | def __init__(self):
    method get_feeds_dir (line 74) | def get_feeds_dir(self):
    method _record_items (line 80) | def _record_items(self, lib, basename, items):
    method album_imported (line 123) | def album_imported(self, lib, album):
    method item_imported (line 126) | def item_imported(self, lib, item):

FILE: libs/common/beetsplug/info.py
  function tag_data (line 28) | def tag_data(lib, args, album=False):
  function tag_fields (line 42) | def tag_fields():
  function tag_data_emitter (line 48) | def tag_data_emitter(path):
  function library_data (line 72) | def library_data(lib, args, album=False):
  function library_data_emitter (line 77) | def library_data_emitter(item):
  function update_summary (line 85) | def update_summary(summary, tags):
  function print_data (line 94) | def print_data(data, item=None, fmt=None):
  function print_data_keys (line 131) | def print_data_keys(data, item=None):
  class InfoPlugin (line 150) | class InfoPlugin(BeetsPlugin):
    method commands (line 152) | def commands(self):
    method run (line 179) | def run(self, lib, opts, args):

FILE: libs/common/beetsplug/inline.py
  class InlineError (line 27) | class InlineError(Exception):
    method __init__ (line 30) | def __init__(self, code, exc):
  function _compile_func (line 37) | def _compile_func(body):
  class InlinePlugin (line 51) | class InlinePlugin(BeetsPlugin):
    method __init__ (line 52) | def __init__(self):
    method compile_inline (line 76) | def compile_inline(self, python_code, album):

FILE: libs/common/beetsplug/ipfs.py
  class IPFSPlugin (line 27) | class IPFSPlugin(BeetsPlugin):
    method __init__ (line 29) | def __init__(self):
    method commands (line 39) | def commands(self):
    method auto_add (line 89) | def auto_add(self, session, task):
    method ipfs_play (line 94) | def ipfs_play(self, lib, opts, args):
    method ipfs_add (line 103) | def ipfs_add(self, album):
    method ipfs_get (line 149) | def ipfs_get(self, lib, query):
    method ipfs_get_from_hash (line 161) | def ipfs_get_from_hash(self, lib, _hash):
    method ipfs_publish (line 177) | def ipfs_publish(self, lib):
    method ipfs_import (line 193) | def ipfs_import(self, lib, args):
    method already_added (line 232) | def already_added(self, check, jlib):
    method ipfs_list (line 238) | def ipfs_list(self, lib, args):
    method query (line 249) | def query(self, lib, args):
    method get_remote_lib (line 254) | def get_remote_lib(self, lib):
    method ipfs_added_albums (line 262) | def ipfs_added_albums(self, rlib, tmpname):
    method create_new_album (line 274) | def create_new_album(self, album, tmplib):

FILE: libs/common/beetsplug/keyfinder.py
  class KeyFinderPlugin (line 27) | class KeyFinderPlugin(BeetsPlugin):
    method __init__ (line 29) | def __init__(self):
    method commands (line 40) | def commands(self):
    method command (line 46) | def command(self, lib, opts, args):
    method imported (line 49) | def imported(self, session, task):
    method find_key (line 52) | def find_key(self, items, write=False):

FILE: libs/common/beetsplug/kodiupdate.py
  function update_kodi (line 31) | def update_kodi(host, port, user, password):
  class KodiUpdate (line 52) | class KodiUpdate(BeetsPlugin):
    method __init__ (line 53) | def __init__(self):
    method listen_for_db_change (line 66) | def listen_for_db_change(self, lib, model):
    method update (line 70) | def update(self, lib):

FILE: libs/common/beetsplug/lastgenre/__init__.py
  function deduplicate (line 50) | def deduplicate(seq):
  function flatten_tree (line 59) | def flatten_tree(elem, path, branches):
  function find_parents (line 76) | def find_parents(candidate, branches):
  class LastGenrePlugin (line 95) | class LastGenrePlugin(plugins.BeetsPlugin):
    method __init__ (line 96) | def __init__(self):
    method setup (line 115) | def setup(self):
    method sources (line 157) | def sources(self):
    method _get_depth (line 169) | def _get_depth(self, tag):
    method _sort_by_depth (line 179) | def _sort_by_depth(self, tags):
    method _resolve_genres (line 188) | def _resolve_genres(self, tags):
    method _format_tag (line 230) | def _format_tag(self, tag):
    method fetch_genre (line 235) | def fetch_genre(self, lastfm_obj):
    method _is_allowed (line 242) | def _is_allowed(self, genre):
    method _last_lookup (line 254) | def _last_lookup(self, entity, method, *args):
    method fetch_album_genre (line 281) | def fetch_album_genre(self, obj):
    method fetch_album_artist_genre (line 288) | def fetch_album_artist_genre(self, obj):
    method fetch_artist_genre (line 295) | def fetch_artist_genre(self, item):
    method fetch_track_genre (line 302) | def fetch_track_genre(self, obj):
    method _get_genre (line 309) | def _get_genre(self, obj):
    method commands (line 375) | def commands(self):
    method imported (line 430) | def imported(self, session, task):
    method _tags_for (line 453) | def _tags_for(self, obj, min_weight=None):

FILE: libs/common/beetsplug/lastimport.py
  class LastImportPlugin (line 27) | class LastImportPlugin(plugins.BeetsPlugin):
    method __init__ (line 28) | def __init__(self):
    method commands (line 43) | def commands(self):
  class CustomUser (line 53) | class CustomUser(pylast.User):
    method __init__ (line 59) | def __init__(self, *args, **kwargs):
    method _get_things (line 62) | def _get_things(self, method, thing, thing_type, params=None,
    method get_top_tracks_by_page (line 87) | def get_top_tracks_by_page(self, period=pylast.PERIOD_OVERALL, limit=N...
  function import_lastfm (line 110) | def import_lastfm(lib, log):
  function fetch_tracks (line 160) | def fetch_tracks(user, page, limit):
  function process_tracks (line 187) | def process_tracks(lib, tracks, log):

FILE: libs/common/beetsplug/loadext.py
  class LoadExtPlugin (line 24) | class LoadExtPlugin(BeetsPlugin):
    method __init__ (line 25) | def __init__(self):
    method library_opened (line 35) | def library_opened(self, lib):

FILE: libs/common/beetsplug/lyrics.py
  class HTMLParseError (line 51) | class HTMLParseError(Exception):
  function unichar (line 116) | def unichar(i):
  function unescape (line 123) | def unescape(text):
  function extract_text_between (line 136) | def extract_text_between(html, start_marker, end_marker):
  function search_pairs (line 145) | def search_pairs(item):
  function slug (line 202) | def slug(text):
  function try_parse_html (line 221) | def try_parse_html(html, **kwargs):
  function try_parse_html (line 227) | def try_parse_html(html, **kwargs):
  class Backend (line 231) | class Backend:
    method __init__ (line 234) | def __init__(self, config, log):
    method _encode (line 238) | def _encode(s):
    method build_url (line 246) | def build_url(self, artist, title):
    method fetch_url (line 250) | def fetch_url(self, url):
    method fetch (line 273) | def fetch(self, artist, title):
  class MusiXmatch (line 277) | class MusiXmatch(Backend):
    method _encode (line 290) | def _encode(cls, s):
    method fetch (line 296) | def fetch(self, artist, title):
  class Genius (line 324) | class Genius(Backend):
    method __init__ (line 335) | def __init__(self, config, log):
    method fetch (line 343) | def fetch(self, artist, title):
    method _search (line 369) | def _search(self, artist, title):
    method _scrape_lyrics_from_html (line 390) | def _scrape_lyrics_from_html(self, html):
  class Tekstowo (line 430) | class Tekstowo(Backend):
    method fetch (line 437) | def fetch(self, artist, title):
    method parse_search_results (line 453) | def parse_search_results(self, html):
    method extract_lyrics (line 483) | def extract_lyrics(self, html):
  function remove_credits (line 498) | def remove_credits(text):
  function _scrape_strip_cruft (line 512) | def _scrape_strip_cruft(html, plain_text_out=False):
  function _scrape_merge_paragraphs (line 532) | def _scrape_merge_paragraphs(html):
  function scrape_lyrics_from_html (line 537) | def scrape_lyrics_from_html(html):
  class Google (line 562) | class Google(Backend):
    method __init__ (line 567) | def __init__(self, config, log):
    method is_lyrics (line 572) | def is_lyrics(self, text, artist=None):
    method slugify (line 601) | def slugify(self, text):
    method is_page_candidate (line 619) | def is_page_candidate(self, url_link, url_title, title, artist):
    method fetch (line 646) | def fetch(self, artist, title):
  class LyricsPlugin (line 687) | class LyricsPlugin(plugins.BeetsPlugin):
    method __init__ (line 696) | def __init__(self):
    method sanitize_bs_sources (line 757) | def sanitize_bs_sources(self, sources):
    method get_bing_access_token (line 770) | def get_bing_access_token(self):
    method commands (line 788) | def commands(self):
    method appendrest (line 843) | def appendrest(self, directory, item):
    method writerest (line 869) | def writerest(self, directory):
    method writerest_indexes (line 878) | def writerest_indexes(self, directory):
    method imported (line 900) | def imported(self, session, task):
    method fetch_item_lyrics (line 908) | def fetch_item_lyrics(self, lib, item, write, force):
    method get_lyrics (line 947) | def get_lyrics(self, artist, title):
    method append_translation (line 958) | def append_translation(self, text, to_lang):

FILE: libs/common/beetsplug/mbcollection.py
  function mb_call (line 29) | def mb_call(func, *args, **kwargs):
  function submit_albums (line 42) | def submit_albums(collection_id, release_ids):
  class MusicBrainzCollectionPlugin (line 54) | class MusicBrainzCollectionPlugin(BeetsPlugin):
    method __init__ (line 55) | def __init__(self):
    method _get_collection (line 70) | def _get_collection(self):
    method _get_albums_in_collection (line 91) | def _get_albums_in_collection(self, id):
    method commands (line 109) | def commands(self):
    method remove_missing (line 120) | def remove_missing(self, collection_id, lib_albums):
    method update_collection (line 131) | def update_collection(self, lib, opts, args):
    method imported (line 136) | def imported(self, session, task):
    method update_album_list (line 142) | def update_album_list(self, lib, album_list, remove_missing=False):

FILE: libs/common/beetsplug/mbsubmit.py
  class MBSubmitPlugin (line 31) | class MBSubmitPlugin(BeetsPlugin):
    method __init__ (line 32) | def __init__(self):
    method before_choose_candidate_event (line 51) | def before_choose_candidate_event(self, session, task):
    method print_tracks (line 55) | def print_tracks(self, session, task):

FILE: libs/common/beetsplug/mbsync.py
  class MBSyncPlugin (line 28) | class MBSyncPlugin(BeetsPlugin):
    method __init__ (line 29) | def __init__(self):
    method commands (line 32) | def commands(self):
    method func (line 52) | def func(self, lib, opts, args):
    method singletons (line 63) | def singletons(self, lib, query, move, pretend, write):
    method albums (line 93) | def albums(self, lib, query, move, pretend, write):

FILE: libs/common/beetsplug/metasync/__init__.py
  class MetaSource (line 36) | class MetaSource(metaclass=ABCMeta):
    method __init__ (line 37) | def __init__(self, config, log):
    method sync_from_source (line 43) | def sync_from_source(self, item):
  function load_meta_sources (line 47) | def load_meta_sources():
  function load_item_types (line 63) | def load_item_types():
  class MetaSyncPlugin (line 72) | class MetaSyncPlugin(BeetsPlugin):
    method __init__ (line 76) | def __init__(self):
    method commands (line 79) | def commands(self):
    method func (line 91) | def func(self, lib, opts, args):

FILE: libs/common/beetsplug/metasync/amarok.py
  function import_dbus (line 30) | def import_dbus():
  class Amarok (line 39) | class Amarok(MetaSource):
    method __init__ (line 56) | def __init__(self, config, log):
    method sync_from_source (line 65) | def sync_from_source(self, item):

FILE: libs/common/beetsplug/metasync/itunes.py
  function create_temporary_copy (line 36) | def create_temporary_copy(path):
  function _norm_itunes_path (line 46) | def _norm_itunes_path(path):
  class Itunes (line 61) | class Itunes(MetaSource):
    method __init__ (line 72) | def __init__(self, config, log):
    method sync_from_source (line 104) | def sync_from_source(self, item):

FILE: libs/common/beetsplug/missing.py
  function _missing_count (line 31) | def _missing_count(album):
  function _item (line 37) | def _item(track_info, album_info, album_id):
  class MissingPlugin (line 85) | class MissingPlugin(BeetsPlugin):
    method __init__ (line 93) | def __init__(self):
    method commands (line 118) | def commands(self):
    method _missing_tracks (line 129) | def _missing_tracks(self, lib, query):
    method _missing_albums (line 156) | def _missing_albums(self, lib, query):
    method _missing (line 213) | def _missing(self, album):

FILE: libs/common/beetsplug/mpdstats.py
  function is_url (line 36) | def is_url(path):
  class MPDClientWrapper (line 44) | class MPDClientWrapper:
    method __init__ (line 45) | def __init__(self, log):
    method connect (line 60) | def connect(self):
    method disconnect (line 84) | def disconnect(self):
    method get (line 90) | def get(self, command, retries=RETRIES):
    method currentsong (line 113) | def currentsong(self):
    method status (line 134) | def status(self):
    method events (line 139) | def events(self):
  class MPDStats (line 146) | class MPDStats:
    method __init__ (line 147) | def __init__(self, lib, log):
    method rating (line 158) | def rating(self, play_count, skip_count, rating, skipped):
    method get_item (line 170) | def get_item(self, path):
    method update_item (line 180) | def update_item(self, item, attribute, value=None, increment=None):
    method update_rating (line 201) | def update_rating(self, item, skipped):
    method handle_song_change (line 217) | def handle_song_change(self, song):
    method handle_played (line 239) | def handle_played(self, song):
    method handle_skipped (line 245) | def handle_skipped(self, song):
    method on_stop (line 251) | def on_stop(self, status):
    method on_pause (line 261) | def on_pause(self, status):
    method on_play (line 265) | def on_play(self, status):
    method run (line 309) | def run(self):
  class MPDStatsPlugin (line 327) | class MPDStatsPlugin(plugins.BeetsPlugin):
    method __init__ (line 336) | def __init__(self):
    method commands (line 349) | def commands(self):

FILE: libs/common/beetsplug/mpdupdate.py
  class BufferedSocket (line 33) | class BufferedSocket:
    method __init__ (line 35) | def __init__(self, host, port, sep=b'\n'):
    method readline (line 45) | def readline(self):
    method send (line 57) | def send(self, data):
    method close (line 60) | def close(self):
  class MPDUpdatePlugin (line 64) | class MPDUpdatePlugin(BeetsPlugin):
    method __init__ (line 65) | def __init__(self):
    method db_change (line 82) | def db_change(self, lib, model):
    method update (line 85) | def update(self, lib):
    method update_mpd (line 92) | def update_mpd(self, host='localhost', port=6600, password=None):

FILE: libs/common/beetsplug/parentwork.py
  function direct_parent_id (line 26) | def direct_parent_id(mb_workid, work_date=None):
  function work_parent_id (line 48) | def work_parent_id(mb_workid):
  function find_parentwork_info (line 60) | def find_parentwork_info(mb_workid):
  class ParentWorkPlugin (line 70) | class ParentWorkPlugin(BeetsPlugin):
    method __init__ (line 71) | def __init__(self):
    method commands (line 82) | def commands(self):
    method imported (line 107) | def imported(self, session, task):
    method get_info (line 116) | def get_info(self, item, work_info):
    method find_work (line 159) | def find_work(self, item, force):

FILE: libs/common/beetsplug/permissions.py
  function convert_perm (line 14) | def convert_perm(perm):
  function check_permissions (line 24) | def check_permissions(path, permission):
  function assert_permissions (line 31) | def assert_permissions(path, permission, log):
  function dirs_in_library (line 48) | def dirs_in_library(library, item):
  class Permissions (line 56) | class Permissions(BeetsPlugin):
    method __init__ (line 57) | def __init__(self):
    method fix (line 70) | def fix(self, lib, item=None, album=None):
    method fix_art (line 84) | def fix_art(self, album):
    method set_permissions (line 90) | def set_permissions(self, files=[], dirs=[]):

FILE: libs/common/beetsplug/play.py
  function play (line 34) | def play(command_str, selection, paths, open_args, log, item_type='track',
  class PlayPlugin (line 56) | class PlayPlugin(BeetsPlugin):
    method __init__ (line 58) | def __init__(self):
    method commands (line 73) | def commands(self):
    method _play_command (line 92) | def _play_command(self, lib, opts, args):
    method _command_str (line 139) | def _command_str(self, args=None):
    method _playlist_or_paths (line 155) | def _playlist_or_paths(self, paths):
    method _exceeds_threshold (line 163) | def _exceeds_threshold(self, selection, command_str, open_args,
    method _create_tmp_playlist (line 185) | def _create_tmp_playlist(self, paths_list):
    method before_choose_candidate_listener (line 199) | def before_choose_candidate_listener(self, session, task):
    method importer_play (line 204) | def importer_play(self, session, task):

FILE: libs/common/beetsplug/playlist.py
  class PlaylistQuery (line 22) | class PlaylistQuery(beets.dbcore.Query):
    method __init__ (line 25) | def __init__(self, pattern):
    method col_clause (line 68) | def col_clause(self):
    method match (line 75) | def match(self, item):
  class PlaylistPlugin (line 79) | class PlaylistPlugin(beets.plugins.BeetsPlugin):
    method __init__ (line 82) | def __init__(self):
    method item_moved (line 108) | def item_moved(self, item, source, destination):
    method item_removed (line 111) | def item_removed(self, item):
    method cli_exit (line 115) | def cli_exit(self, lib):
    method find_playlists (line 129) | def find_playlists(self):
    method update_playlist (line 142) | def update_playlist(self, filename, base_dir):

FILE: libs/common/beetsplug/plexupdate.py
  function get_music_section (line 18) | def get_music_section(host, port, token, library_name, secure,
  function update_plex (line 36) | def update_plex(host, port, token, library_name, secure,
  function append_token (line 58) | def append_token(url, token):
  function get_protocol (line 66) | def get_protocol(secure):
  class PlexUpdate (line 73) | class PlexUpdate(BeetsPlugin):
    method __init__ (line 74) | def __init__(self):
    method listen_for_db_change (line 89) | def listen_for_db_change(self, lib, model):
    method update (line 93) | def update(self, lib):

FILE: libs/common/beetsplug/random.py
  function random_func (line 23) | def random_func(lib, opts, args):
  class Random (line 55) | class Random(BeetsPlugin):
    method commands (line 56) | def commands(self):

FILE: libs/common/beetsplug/replaygain.py
  class ReplayGainError (line 36) | class ReplayGainError(Exception):
  class FatalReplayGainError (line 42) | class FatalReplayGainError(Exception):
  class FatalGstreamerPluginReplayGainError (line 47) | class FatalGstreamerPluginReplayGainError(FatalReplayGainError):
  function call (line 52) | def call(args, **kwargs):
  function after_version (line 69) | def after_version(version_a, version_b):
  function db_to_lufs (line 74) | def db_to_lufs(db):
  function lufs_to_db (line 83) | def lufs_to_db(db):
  class Peak (line 102) | class Peak(enum.Enum):
  class Backend (line 108) | class Backend:
    method __init__ (line 114) | def __init__(self, config, log):
    method compute_track_gain (line 120) | def compute_track_gain(self, items, target_level, peak):
    method compute_album_gain (line 126) | def compute_album_gain(self, items, target_level, peak):
  class FfmpegBackend (line 134) | class FfmpegBackend(Backend):
    method __init__ (line 140) | def __init__(self, config, log):
    method compute_track_gain (line 168) | def compute_track_gain(self, items, target_level, peak):
    method compute_album_gain (line 184) | def compute_album_gain(self, items, target_level, peak):
    method _construct_cmd (line 242) | def _construct_cmd(self, item, peak_method):
    method _analyse_item (line 259) | def _analyse_item(self, item, target_level, peak, count_blocks=True):
    method _find_line (line 340) | def _find_line(self, output, search, start_line=0, step_size=1):
    method _parse_float (line 354) | def _parse_float(self, line):
  class CommandBackend (line 381) | class CommandBackend(Backend):
    method __init__ (line 384) | def __init__(self, config, log):
    method compute_track_gain (line 415) | def compute_track_gain(self, items, target_level, peak):
    method compute_album_gain (line 423) | def compute_album_gain(self, items, target_level, peak):
    method format_supported (line 438) | def format_supported(self, item):
    method compute_gain (line 447) | def compute_gain(self, items, target_level, is_album):
    method parse_tool_output (line 484) | def parse_tool_output(self, text, num_lines):
  class GStreamerBackend (line 510) | class GStreamerBackend(Backend):
    method __init__ (line 511) | def __init__(self, config, log):
    method _import_gst (line 565) | def _import_gst(self):
    method compute (line 596) | def compute(self, files, target_level, album):
    method compute_track_gain (line 615) | def compute_track_gain(self, items, target_level, peak):
    method compute_album_gain (line 627) | def compute_album_gain(self, items, target_level, peak):
    method close (line 653) | def close(self):
    method _on_eos (line 656) | def _on_eos(self, bus, message):
    method _on_error (line 664) | def _on_error(self, bus, message):
    method _on_tag (line 674) | def _on_tag(self, bus, message):
    method _set_first_file (line 700) | def _set_first_file(self):
    method _set_file (line 710) | def _set_file(self):
    method _set_next_file (line 744) | def _set_next_file(self):
    method _on_pad_added (line 765) | def _on_pad_added(self, decbin, pad):
    method _on_pad_removed (line 770) | def _on_pad_removed(self, decbin, pad):
  class AudioToolsBackend (line 777) | class AudioToolsBackend(Backend):
    method __init__ (line 783) | def __init__(self, config, log):
    method _import_audiotools (line 787) | def _import_audiotools(self):
    method open_audio_file (line 803) | def open_audio_file(self, item):
    method init_replaygain (line 825) | def init_replaygain(self, audiofile, item):
    method compute_track_gain (line 843) | def compute_track_gain(self, items, target_level, peak):
    method _with_target_level (line 850) | def _with_target_level(self, gain, target_level):
    method _title_gain (line 857) | def _title_gain(self, rg, audiofile, target_level):
    method _compute_track_gain (line 875) | def _compute_track_gain(self, item, target_level):
    method compute_album_gain (line 893) | def compute_album_gain(self, items, target_level, peak):
  class ExceptionWatcher (line 930) | class ExceptionWatcher(Thread):
    method __init__ (line 935) | def __init__(self, queue, callback):
    method run (line 941) | def run(self):
    method join (line 952) | def join(self, timeout=None):
  class ReplayGainPlugin (line 959) | class ReplayGainPlugin(BeetsPlugin):
    method __init__ (line 975) | def __init__(self):
    method should_use_r128 (line 1034) | def should_use_r128(self, item):
    method track_requires_gain (line 1040) | def track_requires_gain(self, item):
    method album_requires_gain (line 1046) | def album_requires_gain(self, album):
    method store_track_gain (line 1059) | def store_track_gain(self, item, track_gain):
    method store_album_gain (line 1066) | def store_album_gain(self, item, album_gain):
    method store_track_r128_gain (line 1073) | def store_track_r128_gain(self, item, track_gain):
    method store_album_r128_gain (line 1080) | def store_album_r128_gain(self, item, album_gain):
    method tag_specific_values (line 1086) | def tag_specific_values(self, items):
    method handle_album (line 1105) | def handle_album(self, album, write, force=False):
    method handle_track (line 1174) | def handle_track(self, item, write, force=False):
    method _has_pool (line 1218) | def _has_pool(self):
    method open_pool (line 1226) | def open_pool(self, threads):
    method _apply (line 1241) | def _apply(self, func, args, kwds, callback):
    method terminate_pool (line 1263) | def terminate_pool(self):
    method _interrupt (line 1274) | def _interrupt(self, signal, frame):
    method close_pool (line 1283) | def close_pool(self):
    method import_begin (line 1291) | def import_begin(self, session):
    method import_end (line 1301) | def import_end(self, paths):
    method imported (line 1306) | def imported(self, session, task):
    method command_func (line 1315) | def command_func(self, lib, opts, args):
    method commands (line 1347) | def commands(self):

FILE: libs/common/beetsplug/rewrite.py
  function rewriter (line 27) | def rewriter(field, rules):
  class RewritePlugin (line 43) | class RewritePlugin(BeetsPlugin):
    method __init__ (line 44) | def __init__(self):

FILE: libs/common/beetsplug/scrub.py
  class ScrubPlugin (line 46) | class ScrubPlugin(BeetsPlugin):
    method __init__ (line 48) | def __init__(self):
    method commands (line 57) | def commands(self):
    method _mutagen_classes (line 75) | def _mutagen_classes():
    method _scrub (line 85) | def _scrub(self, path):
    method _scrub_item (line 112) | def _scrub_item(self, item, restore=True):
    method import_task_files (line 144) | def import_task_files(self, session, task):

FILE: libs/common/beetsplug/smartplaylist.py
  class SmartPlaylistPlugin (line 35) | class SmartPlaylistPlugin(BeetsPlugin):
    method __init__ (line 37) | def __init__(self):
    method commands (line 56) | def commands(self):
    method update_cmd (line 65) | def update_cmd(self, lib, opts, args):
    method build_queries (line 89) | def build_queries(self):
    method matches (line 152) | def matches(self, model, query, album_query):
    method db_change (line 159) | def db_change(self, lib, model):
    method update_playlists (line 173) | def update_playlists(self, lib):

FILE: libs/common/beetsplug/sonosupdate.py
  class SonosUpdate (line 23) | class SonosUpdate(BeetsPlugin):
    method __init__ (line 24) | def __init__(self):
    method listen_for_db_change (line 28) | def listen_for_db_change(self, lib, model):
    method update (line 32) | def update(self, lib):

FILE: libs/common/beetsplug/spotify.py
  class SpotifyPlugin (line 34) | class SpotifyPlugin(MetadataSourcePlugin, BeetsPlugin):
    method __init__ (line 52) | def __init__(self):
    method setup (line 76) | def setup(self):
    method _authenticate (line 86) | def _authenticate(self):
    method _handle_response (line 122) | def _handle_response(self, request_type, url, params=None):
    method album_for_id (line 157) | def album_for_id(self, album_id):
    method _get_track (line 225) | def _get_track(self, track_data):
    method track_for_id (line 248) | def track_for_id(self, track_id=None, track_data=None):
    method _construct_search_query (line 286) | def _construct_search_query(filters=None, keywords=''):
    method _search_api (line 307) | def _search_api(self, query_type, filters=None, keywords=''):
    method commands (line 347) | def commands(self):
    method _parse_opts (line 376) | def _parse_opts(self, opts):
    method _match_library_tracks (line 392) | def _match_library_tracks(self, library, keywords):
    method _output_match_results (line 501) | def _output_match_results(self, results):

FILE: libs/common/beetsplug/subsonicplaylist.py
  function filter_to_be_removed (line 32) | def filter_to_be_removed(items, keys):
  class SubsonicPlaylistPlugin (line 54) | class SubsonicPlaylistPlugin(BeetsPlugin):
    method __init__ (line 56) | def __init__(self):
    method update_tags (line 69) | def update_tags(self, playlist_dict, lib):
    method get_playlist (line 84) | def get_playlist(self, playlist_id):
    method commands (line 97) | def commands(self):
    method generate_token (line 142) | def generate_token(self):
    method send (line 147) | def send(self, endpoint, params=None):
    method get_playlists (line 163) | def get_playlists(self, ids):

FILE: libs/common/beetsplug/subsonicupdate.py
  class SubsonicUpdate (line 45) | class SubsonicUpdate(BeetsPlugin):
    method __init__ (line 46) | def __init__(self):
    method __create_token (line 59) | def __create_token():
    method __format_url (line 76) | def __format_url(endpoint):
    method start_scan (line 99) | def start_scan(self):

FILE: libs/common/beetsplug/the.py
  class ThePlugin (line 29) | class ThePlugin(BeetsPlugin):
    method __init__ (line 33) | def __init__(self):
    method unthe (line 64) | def unthe(self, text, pattern):
    method the_template_func (line 87) | def the_template_func(self, text):

FILE: libs/common/beetsplug/thumbnails.py
  class ThumbnailsPlugin (line 43) | class ThumbnailsPlugin(BeetsPlugin):
    method __init__ (line 44) | def __init__(self):
    method commands (line 56) | def commands(self):
    method process_query (line 71) | def process_query(self, lib, opts, args):
    method _check_local_ok (line 77) | def _check_local_ok(self):
    method process_album (line 110) | def process_album(self, album):
    method make_cover_thumbnail (line 137) | def make_cover_thumbnail(self, album, size, target_dir):
    method thumbnail_file_name (line 158) | def thumbnail_file_name(self, path):
    method add_tags (line 166) | def add_tags(self, album, image_path):
    method make_dolphin_cover_thumbnail (line 179) | def make_dolphin_cover_thumbnail(self, album):
  function write_metadata_im (line 191) | def write_metadata_im(file, metadata):
  function write_metadata_pil (line 200) | def write_metadata_pil(file, metadata):
  class URIGetter (line 211) | class URIGetter:
    method uri (line 215) | def uri(self, path):
  class PathlibURI (line 219) | class PathlibURI(URIGetter):
    method uri (line 223) | def uri(self, path):
  function copy_c_string (line 227) | def copy_c_string(c_string):
  class GioURI (line 238) | class GioURI(URIGetter):
    method __init__ (line 243) | def __init__(self):
    method get_library (line 257) | def get_library(self):
    method uri (line 266) | def uri(self, path):

FILE: libs/common/beetsplug/types.py
  class TypesPlugin (line 22) | class TypesPlugin(BeetsPlugin):
    method item_types (line 25) | def item_types(self):
    method album_types (line 29) | def album_types(self):
    method _types (line 32) | def _types(self):

FILE: libs/common/beetsplug/unimported.py
  class Unimported (line 29) | class Unimported(BeetsPlugin):
    method __init__ (line 31) | def __init__(self):
    method commands (line 39) | def commands(self):

FILE: libs/common/beetsplug/web/__init__.py
  function _rep (line 32) | def _rep(obj, expand=False):
  function json_generator (line 69) | def json_generator(items, root, expand=False):
  function is_expand (line 89) | def is_expand():
  function is_delete (line 95) | def is_delete():
  function get_method (line 103) | def get_method():
  function resource (line 108) | def resource(name, patchable=False):
  function resource_query (line 162) | def resource_query(name, patchable=False):
  function resource_list (line 211) | def resource_list(name):
  function _get_unique_table_field_values (line 226) | def _get_unique_table_field_values(model, field, sort_field):
  class IdListConverter (line 236) | class IdListConverter(BaseConverter):
    method to_python (line 240) | def to_python(self, value):
    method to_url (line 249) | def to_url(self, value):
  class QueryConverter (line 253) | class QueryConverter(PathConverter):
    method to_python (line 257) | def to_python(self, value):
    method to_url (line 263) | def to_url(self, value):
  class EverythingConverter (line 267) | class EverythingConverter(PathConverter):
  function before_request (line 280) | def before_request():
  function get_item (line 288) | def get_item(id):
  function all_items (line 295) | def all_items():
  function item_file (line 300) | def item_file(item_id):
  function item_query (line 335) | def item_query(queries):
  function item_at_path (line 340) | def item_at_path(path):
  function item_unique_field_values (line 350) | def item_unique_field_values(key):
  function get_album (line 364) | def get_album(id):
  function all_albums (line 371) | def all_albums():
  function album_query (line 377) | def album_query(queries):
  function album_art (line 382) | def album_art(album_id):
  function album_unique_field_values (line 391) | def album_unique_field_values(key):
  function all_artists (line 404) | def all_artists():
  function stats (line 414) | def stats():
  function home (line 427) | def home():
  class WebPlugin (line 433) | class WebPlugin(BeetsPlugin):
    method __init__ (line 434) | def __init__(self):
    method commands (line 446) | def commands(self):
  class ReverseProxied (line 493) | class ReverseProxied:
    method __init__ (line 512) | def __init__(self, app):
    method __call__ (line 515) | def __call__(self, environ, start_response):

FILE: libs/common/beetsplug/web/static/jquery.js
  function jQuerySub (line 871) | function jQuerySub( selector, context ) {
  function doScrollCheck (line 937) | function doScrollCheck() {
  function createFlags (line 964) | function createFlags( flags ) {
  function resolveFunc (line 1296) | function resolveFunc( i ) {
  function progressFunc (line 1304) | function progressFunc( i ) {
  function dataAttr (line 1931) | function dataAttr( elem, key, data ) {
  function isEmptyDataObject (line 1962) | function isEmptyDataObject( obj ) {
  function handleQueueMarkDefer (line 1980) | function handleQueueMarkDefer( elem, type, src ) {
  function resolve (line 2133) | function resolve() {
  function returnFalse (line 3465) | function returnFalse() {
  function returnTrue (line 3468) | function returnTrue() {
  function dirNodeCheck (line 5168) | function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
  function dirCheck (line 5201) | function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
  function isDisconnected (line 5474) | function isDisconnected( node ) {
  function winnow (line 5591) | function winnow( elements, qualifier, keep ) {
  function createSafeFragment (line 5628) | function createSafeFragment( document ) {
  function root (line 5992) | function root( elem, cur ) {
  function cloneCopyEvent (line 5999) | function cloneCopyEvent( src, dest ) {
  function cloneFixAttributes (line 6027) | function cloneFixAttributes( src, dest ) {
  function getAll (line 6163) | function getAll( elem ) {
  function fixDefaultChecked (line 6176) | function fixDefaultChecked( elem ) {
  function findInputs (line 6182) | function findInputs( elem ) {
  function shimCloneNode (line 6193) | function shimCloneNode( elem ) {
  function evalScript (line 6425) | function evalScript( i, elem ) {
  function getWH (line 6767) | function getWH( elem, name, extra ) {
  function addToPrefiltersOrTransports (line 6895) | function addToPrefiltersOrTransports( structure ) {
  function inspectPrefiltersOrTransports (line 6931) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
  function ajaxExtend (line 6973) | function ajaxExtend( target, src ) {
  function done (line 7315) | function done( status, nativeStatusText, responses, headers ) {
  function buildParams (line 7630) | function buildParams( prefix, obj, traditional, add ) {
  function ajaxHandleResponses (line 7680) | function ajaxHandleResponses( s, jqXHR, responses ) {
  function ajaxConvert (line 7745) | function ajaxConvert( s, response ) {
  function createStandardXHR (line 8011) | function createStandardXHR() {
  function createActiveXHR (line 8017) | function createActiveXHR() {
  function doAnimation (line 8349) | function doAnimation() {
  function stopQueue (line 8492) | function stopQueue( elem, data, index ) {
  function createFxNow (line 8534) | function createFxNow() {
  function clearFxNow (line 8539) | function clearFxNow() {
  function genFx (line 8544) | function genFx( type, num ) {
  function t (line 8659) | function t( gotoEnd ) {
  function defaultDisplay (line 8851) | function defaultDisplay( nodeName ) {
  function getWindow (line 9160) | function getWindow( elem ) {

FILE: libs/common/beetsplug/web/static/underscore.js
  function eq (line 670) | function eq(a, b, stack) {

FILE: libs/common/beetsplug/zero.py
  class ZeroPlugin (line 29) | class ZeroPlugin(BeetsPlugin):
    method __init__ (line 30) | def __init__(self):
    method commands (line 70) | def commands(self):
    method _set_pattern (line 84) | def _set_pattern(self, field):
    method import_task_choice_event (line 102) | def import_task_choice_event(self, session, task):
    method write_event (line 108) | def write_event(self, item, path, tags):
    method set_fields (line 112) | def set_fields(self, item, tags):
    method process_item (line 142) | def process_item(self, item):
  function _match_progs (line 151) | def _match_progs(value, progs):

FILE: libs/common/bs4/__init__.py
  class GuessedAtParserWarning (line 62) | class GuessedAtParserWarning(UserWarning):
  class MarkupResemblesLocatorWarning (line 67) | class MarkupResemblesLocatorWarning(UserWarning):
  class BeautifulSoup (line 74) | class BeautifulSoup(Tag):
    method __init__ (line 120) | def __init__(self, markup="", features=None, builder=None,
    method __copy__ (line 351) | def __copy__(self):
    method __getstate__ (line 364) | def __getstate__(self):
    method _decode_markup (line 372) | def _decode_markup(cls, markup):
    method _markup_is_url (line 385) | def _markup_is_url(cls, markup):
    method _markup_resembles_filename (line 414) | def _markup_resembles_filename(cls, markup):
    method _feed (line 444) | def _feed(self):
    method reset (line 457) | def reset(self):
    method new_tag (line 472) | def new_tag(self, name, namespace=None, nsprefix=None, attrs={},
    method string_container (line 495) | def string_container(self, base_class=None):
    method new_string (line 511) | def new_string(self, s, subclass=None):
    method insert_before (line 518) | def insert_before(self, *args):
    method insert_after (line 524) | def insert_after(self, *args):
    method popTag (line 530) | def popTag(self):
    method pushTag (line 544) | def pushTag(self, tag):
    method endData (line 558) | def endData(self, containerClass=None):
    method object_was_parsed (line 592) | def object_was_parsed(self, o, parent=None, most_recent_element=None):
    method _linkage_fixer (line 620) | def _linkage_fixer(self, el):
    method _popToTag (line 660) | def _popToTag(self, name, nsprefix=None, inclusivePop=True):
    method handle_starttag (line 694) | def handle_starttag(self, name, namespace, nsprefix, attrs, sourceline...
    method handle_endtag (line 735) | def handle_endtag(self, name, nsprefix=None):
    method handle_data (line 745) | def handle_data(self, data):
    method decode (line 749) | def decode(self, pretty_print=False,
  class BeautifulStoneSoup (line 784) | class BeautifulStoneSoup(BeautifulSoup):
    method __init__ (line 787) | def __init__(self, *args, **kwargs):
  class StopParsing (line 797) | class StopParsing(Exception):
  class FeatureNotFound (line 801) | class FeatureNotFound(ValueError):

FILE: libs/common/bs4/builder/__init__.py
  class XMLParsedAsHTMLWarning (line 35) | class XMLParsedAsHTMLWarning(UserWarning):
  class TreeBuilderRegistry (line 42) | class TreeBuilderRegistry(object):
    method __init__ (line 47) | def __init__(self):
    method register (line 51) | def register(self, treebuilder_class):
    method lookup (line 61) | def lookup(self, *features):
  class TreeBuilder (line 111) | class TreeBuilder(object):
    method __init__ (line 139) | def __init__(self, multi_valued_attributes=USE_DEFAULT,
    method initialize_soup (line 189) | def initialize_soup(self, soup):
    method reset (line 197) | def reset(self):
    method can_be_empty_element (line 205) | def can_be_empty_element(self, tag_name):
    method feed (line 228) | def feed(self, markup):
    method prepare_markup (line 239) | def prepare_markup(self, markup, user_specified_encoding=None,
    method test_fragment_to_document (line 267) | def test_fragment_to_document(self, fragment):
    method set_up_substitutions (line 283) | def set_up_substitutions(self, tag):
    method _replace_cdata_list_attribute_values (line 295) | def _replace_cdata_list_attribute_values(self, tag_name, attrs):
  class SAXTreeBuilder (line 333) | class SAXTreeBuilder(TreeBuilder):
    method feed (line 340) | def feed(self, markup):
    method close (line 343) | def close(self):
    method startElement (line 346) | def startElement(self, name, attrs):
    method endElement (line 351) | def endElement(self, name):
    method startElementNS (line 355) | def startElementNS(self, nsTuple, nodeName, attrs):
    method endElementNS (line 359) | def endElementNS(self, nsTuple, nodeName):
    method startPrefixMapping (line 364) | def startPrefixMapping(self, prefix, nodeValue):
    method endPrefixMapping (line 368) | def endPrefixMapping(self, prefix):
    method characters (line 373) | def characters(self, content):
    method startDocument (line 376) | def startDocument(self):
    method endDocument (line 379) | def endDocument(self):
  class HTMLTreeBuilder (line 383) | class HTMLTreeBuilder(TreeBuilder):
    method set_up_substitutions (line 453) | def set_up_substitutions(self, tag):
  class DetectsXMLParsedAsHTML (line 496) | class DetectsXMLParsedAsHTML(object):
    method warn_if_markup_looks_like_xml (line 517) | def warn_if_markup_looks_like_xml(cls, markup):
    method _warn (line 543) | def _warn(cls):
    method _initialize_xml_detector (line 549) | def _initialize_xml_detector(self):
    method _document_might_be_xml (line 554) | def _document_might_be_xml(self, processing_instruction):
    method _root_tag_encountered (line 569) | def _root_tag_encountered(self, name):
  function register_treebuilders_from (line 589) | def register_treebuilders_from(module):
  class ParserRejectedMarkup (line 601) | class ParserRejectedMarkup(Exception):
    method __init__ (line 605) | def __init__(self, message_or_exception):

FILE: libs/common/bs4/builder/_html5lib.py
  class HTML5TreeBuilder (line 42) | class HTML5TreeBuilder(HTMLTreeBuilder):
    method prepare_markup (line 64) | def prepare_markup(self, markup, user_specified_encoding,
    method feed (line 82) | def feed(self, markup):
    method create_treebuilder (line 110) | def create_treebuilder(self, namespaceHTMLElements):
    method test_fragment_to_document (line 117) | def test_fragment_to_document(self, fragment):
  class TreeBuilderForHtml5lib (line 122) | class TreeBuilderForHtml5lib(treebuilder_base.TreeBuilder):
    method __init__ (line 124) | def __init__(self, namespaceHTMLElements, soup=None,
    method documentClass (line 146) | def documentClass(self):
    method insertDoctype (line 150) | def insertDoctype(self, token):
    method elementClass (line 158) | def elementClass(self, name, namespace):
    method commentClass (line 171) | def commentClass(self, data):
    method fragmentClass (line 174) | def fragmentClass(self):
    method appendChild (line 182) | def appendChild(self, node):
    method getDocument (line 186) | def getDocument(self):
    method getFragment (line 189) | def getFragment(self):
    method testSerializer (line 192) | def testSerializer(self, element):
  class AttrList (line 242) | class AttrList(object):
    method __init__ (line 243) | def __init__(self, element):
    method __iter__ (line 246) | def __iter__(self):
    method __setitem__ (line 248) | def __setitem__(self, name, value):
    method items (line 260) | def items(self):
    method keys (line 262) | def keys(self):
    method __len__ (line 264) | def __len__(self):
    method __getitem__ (line 266) | def __getitem__(self, name):
    method __contains__ (line 268) | def __contains__(self, name):
  class Element (line 272) | class Element(treebuilder_base.Node):
    method __init__ (line 273) | def __init__(self, element, soup, namespace):
    method appendChild (line 279) | def appendChild(self, node):
    method getAttributes (line 333) | def getAttributes(self):
    method setAttributes (line 338) | def setAttributes(self, attributes):
    method insertText (line 360) | def insertText(self, data, insertBefore=None):
    method insertBefore (line 367) | def insertBefore(self, node, refNode):
    method removeChild (line 379) | def removeChild(self, node):
    method reparentChildren (line 382) | def reparentChildren(self, new_parent):
    method cloneNode (line 448) | def cloneNode(self):
    method hasContent (line 455) | def hasContent(self):
    method getNameTuple (line 458) | def getNameTuple(self):
  class TextNode (line 466) | class TextNode(Element):
    method __init__ (line 467) | def __init__(self, element, soup):
    method cloneNode (line 472) | def cloneNode(self):

FILE: libs/common/bs4/builder/_htmlparser.py
  class HTMLParseError (line 18) | class HTMLParseError(Exception):
  class BeautifulSoupHTMLParser (line 56) | class BeautifulSoupHTMLParser(HTMLParser, DetectsXMLParsedAsHTML):
    method __init__ (line 66) | def __init__(self, *args, **kwargs):
    method error (line 94) | def error(self, msg):
    method handle_startendtag (line 107) | def handle_startendtag(self, name, attrs):
    method handle_starttag (line 122) | def handle_starttag(self, name, attrs, handle_empty_element=True):
    method handle_endtag (line 177) | def handle_endtag(self, name, check_already_closed=True):
    method handle_data (line 195) | def handle_data(self, data):
    method handle_charref (line 199) | def handle_charref(self, name):
    method handle_entityref (line 238) | def handle_entityref(self, name):
    method handle_comment (line 257) | def handle_comment(self, data):
    method handle_decl (line 266) | def handle_decl(self, data):
    method unknown_decl (line 276) | def unknown_decl(self, data):
    method handle_pi (line 290) | def handle_pi(self, data):
  class HTMLParserTreeBuilder (line 301) | class HTMLParserTreeBuilder(HTMLTreeBuilder):
    method __init__ (line 314) | def __init__(self, parser_args=None, parser_kwargs=None, **kwargs):
    method prepare_markup (line 342) | def prepare_markup(self, markup, user_specified_encoding=None,
    method feed (line 391) | def feed(self, markup):
  function parse_starttag (line 437) | def parse_starttag(self, i):
  function set_cdata_mode (line 492) | def set_cdata_mode(self, elem):

FILE: libs/common/bs4/builder/_lxml.py
  function _invert (line 37) | def _invert(d):
  class LXMLTreeBuilderForXML (line 41) | class LXMLTreeBuilderForXML(TreeBuilder):
    method initialize_soup (line 68) | def initialize_soup(self, soup):
    method _register_namespaces (line 77) | def _register_namespaces(self, mapping):
    method default_parser (line 101) | def default_parser(self, encoding):
    method parser_for (line 113) | def parser_for(self, encoding):
    method __init__ (line 129) | def __init__(self, parser=None, empty_element_tags=None, **kwargs):
    method _getNsTag (line 141) | def _getNsTag(self, tag):
    method prepare_markup (line 149) | def prepare_markup(self, markup, user_specified_encoding=None,
    method feed (line 219) | def feed(self, markup):
    method close (line 240) | def close(self):
    method start (line 243) | def start(self, name, attrs, nsmap={}):
    method _prefix_for_namespace (line 306) | def _prefix_for_namespace(self, namespace):
    method end (line 315) | def end(self, name):
    method pi (line 337) | def pi(self, target, data):
    method data (line 343) | def data(self, content):
    method doctype (line 346) | def doctype(self, name, pubid, system):
    method comment (line 351) | def comment(self, content):
    method test_fragment_to_document (line 357) | def test_fragment_to_document(self, fragment):
  class LXMLTreeBuilder (line 362) | class LXMLTreeBuilder(HTMLTreeBuilder, LXMLTreeBuilderForXML):
    method default_parser (line 371) | def default_parser(self, encoding):
    method feed (line 374) | def feed(self, markup):
    method test_fragment_to_document (line 384) | def test_fragment_to_document(self, fragment):

FILE: libs/common/bs4/dammit.py
  function chardet_dammit (line 43) | def chardet_dammit(s):
  function chardet_dammit (line 48) | def chardet_dammit(s):
  class EntitySubstitution (line 67) | class EntitySubstitution(object):
    method _populate_class_variables (line 70) | def _populate_class_variables():
    method _substitute_html_entity (line 206) | def _substitute_html_entity(cls, matchobj):
    method _substitute_xml_entity (line 213) | def _substitute_xml_entity(cls, matchobj):
    method quoted_attribute_value (line 220) | def quoted_attribute_value(self, value):
    method substitute_xml (line 257) | def substitute_xml(cls, value, make_quoted_attribute=False):
    method substitute_xml_containing_entities (line 278) | def substitute_xml_containing_entities(
    method substitute_html (line 300) | def substitute_html(cls, s):
  class EncodingDetector (line 317) | class EncodingDetector:
    method __init__ (line 344) | def __init__(self, markup, known_definite_encodings=None,
    method _usable (line 391) | def _usable(self, encoding, tried):
    method encodings (line 408) | def encodings(self):
    method strip_byte_order_mark (line 452) | def strip_byte_order_mark(cls, data):
    method find_declared_encoding (line 482) | def find_declared_encoding(cls, markup, is_html=False, search_entire_d...
  class UnicodeDammit (line 522) | class UnicodeDammit:
    method __init__ (line 541) | def __init__(self, markup, known_definite_encodings=[],
    method _sub_ms_char (line 629) | def _sub_ms_char(self, match):
    method _convert_from (line 646) | def _convert_from(self, proposed, errors="strict"):
    method _to_unicode (line 677) | def _to_unicode(self, data, encoding, errors="strict"):
    method declared_html_encoding (line 685) | def declared_html_encoding(self):
    method find_codec (line 693) | def find_codec(self, charset):
    method _codec (line 709) | def _codec(self, charset):
    method detwingle (line 1030) | def detwingle(cls, in_bytes, main_encoding="utf8",

FILE: libs/common/bs4/diagnose.py
  function diagnose (line 22) | def diagnose(data):
  function lxml_trace (line 93) | def lxml_trace(data, html=True, **kwargs):
  class AnnouncingParser (line 115) | class AnnouncingParser(HTMLParser):
    method _p (line 123) | def _p(self, s):
    method handle_starttag (line 126) | def handle_starttag(self, name, attrs):
    method handle_endtag (line 129) | def handle_endtag(self, name):
    method handle_data (line 132) | def handle_data(self, data):
    method handle_charref (line 135) | def handle_charref(self, name):
    method handle_entityref (line 138) | def handle_entityref(self, name):
    method handle_comment (line 141) | def handle_comment(self, data):
    method handle_decl (line 144) | def handle_decl(self, data):
    method unknown_decl (line 147) | def unknown_decl(self, data):
    method handle_pi (line 150) | def handle_pi(self, data):
  function htmlparser_trace (line 153) | def htmlparser_trace(data):
  function rword (line 167) | def rword(length=5):
  function rsentence (line 178) | def rsentence(length=4):
  function rdoc (line 182) | def rdoc(num_elements=1000):
  function benchmark_parsers (line 200) | def benchmark_parsers(num_elements=100000):
  function profile (line 232) | def profile(num_elements=100000, parser="lxml"):

FILE: libs/common/bs4/element.py
  function _alias (line 33) | def _alias(attr):
  class NamespacedAttribute (line 74) | class NamespacedAttribute(str):
    method __new__ (line 79) | def __new__(cls, prefix, name=None, namespace=None):
  class AttributeValueWithCharsetSubstitution (line 97) | class AttributeValueWithCharsetSubstitution(str):
  class CharsetMetaAttributeValue (line 100) | class CharsetMetaAttributeValue(AttributeValueWithCharsetSubstitution):
    method __new__ (line 107) | def __new__(cls, original_value):
    method encode (line 112) | def encode(self, encoding):
  class ContentMetaAttributeValue (line 121) | class ContentMetaAttributeValue(AttributeValueWithCharsetSubstitution):
    method __new__ (line 132) | def __new__(cls, original_value):
    method encode (line 142) | def encode(self, encoding):
  class PageElement (line 150) | class PageElement(object):
    method setup (line 157) | def setup(self, parent=None, previous_element=None, next_element=None,
    method format_string (line 198) | def format_string(self, s, formatter):
    method formatter_for_name (line 211) | def formatter_for_name(self, formatter):
    method _is_xml (line 232) | def _is_xml(self):
    method _all_strings (line 258) | def _all_strings(self, strip=False, types=default):
    method stripped_strings (line 266) | def stripped_strings(self):
    method get_text (line 274) | def get_text(self, separator="", strip=False,
    method replace_with (line 298) | def replace_with(self, *args):
    method unwrap (line 321) | def unwrap(self):
    method wrap (line 339) | def wrap(self, wrap_inside):
    method extract (line 350) | def extract(self, _self_index=None):
    method _last_descendant (line 388) | def _last_descendant(self, is_initialized=True, accept_self=True):
    method insert (line 407) | def insert(self, position, new_child):
    method append (line 489) | def append(self, tag):
    method extend (line 496) | def extend(self, tags):
    method insert_before (line 509) | def insert_before(self, *args):
    method insert_after (line 531) | def insert_after(self, *args):
    method find_next (line 557) | def find_next(self, name=None, attrs={}, string=None, **kwargs):
    method find_all_next (line 574) | def find_all_next(self, name=None, attrs={}, string=None, limit=None,
    method find_next_sibling (line 593) | def find_next_sibling(self, name=None, attrs={}, string=None, **kwargs):
    method find_next_siblings (line 611) | def find_next_siblings(self, name=None, attrs={}, string=None, limit=N...
    method find_previous (line 632) | def find_previous(self, name=None, attrs={}, string=None, **kwargs):
    method find_all_previous (line 650) | def find_all_previous(self, name=None, attrs={}, string=None, limit=None,
    method find_previous_sibling (line 671) | def find_previous_sibling(self, name=None, attrs={}, string=None, **kw...
    method find_previous_siblings (line 689) | def find_previous_siblings(self, name=None, attrs={}, string=None,
    method find_parent (line 710) | def find_parent(self, name=None, attrs={}, **kwargs):
    method find_parents (line 733) | def find_parents(self, name=None, attrs={}, limit=None, **kwargs):
    method next (line 753) | def next(self):
    method previous (line 762) | def previous(self):
    method _find_one (line 772) | def _find_one(self, method, name, attrs, string, **kwargs):
    method _find_all (line 779) | def _find_all(self, name, attrs, string, limit, generator, **kwargs):
    method next_elements (line 837) | def next_elements(self):
    method next_siblings (line 848) | def next_siblings(self):
    method previous_elements (line 860) | def previous_elements(self):
    method previous_siblings (line 871) | def previous_siblings(self):
    method parents (line 883) | def parents(self):
    method decomposed (line 894) | def decomposed(self):
    method nextGenerator (line 903) | def nextGenerator(self):
    method nextSiblingGenerator (line 906) | def nextSiblingGenerator(self):
    method previousGenerator (line 909) | def previousGenerator(self):
    method previousSiblingGenerator (line 912) | def previousSiblingGenerator(self):
    method parentGenerator (line 915) | def parentGenerator(self):
  class NavigableString (line 919) | class NavigableString(str, PageElement):
    method __new__ (line 934) | def __new__(cls, value):
    method __copy__ (line 949) | def __copy__(self):
    method __getnewargs__ (line 955) | def __getnewargs__(self):
    method __getattr__ (line 958) | def __getattr__(self, attr):
    method output_ready (line 969) | def output_ready(self, formatter="minimal"):
    method name (line 978) | def name(self):
    method name (line 988) | def name(self, name):
    method _all_strings (line 992) | def _all_strings(self, strip=False, types=PageElement.default):
  class PreformattedString (line 1040) | class PreformattedString(NavigableString):
    method output_ready (line 1051) | def output_ready(self, formatter=None):
  class CData (line 1067) | class CData(PreformattedString):
  class ProcessingInstruction (line 1072) | class ProcessingInstruction(PreformattedString):
  class XMLProcessingInstruction (line 1078) | class XMLProcessingInstruction(ProcessingInstruction):
  class Comment (line 1083) | class Comment(PreformattedString):
  class Declaration (line 1089) | class Declaration(PreformattedString):
  class Doctype (line 1095) | class Doctype(PreformattedString):
    method for_name_and_ids (line 1098) | def for_name_and_ids(cls, name, pub_id, system_id):
  class Stylesheet (line 1124) | class Stylesheet(NavigableString):
  class Script (line 1133) | class Script(NavigableString):
  class TemplateString (line 1142) | class TemplateString(NavigableString):
  class RubyTextString (line 1151) | class RubyTextString(NavigableString):
  class RubyParenthesisString (line 1163) | class RubyParenthesisString(NavigableString):
  class Tag (line 1172) | class Tag(PageElement):
    method __init__ (line 1180) | def __init__(self, parser=None, builder=None, name=None, namespace=None,
    method __copy__ (line 1299) | def __copy__(self):
    method is_empty_element (line 1318) | def is_empty_element(self):
    method string (line 1336) | def string(self):
    method string (line 1357) | def string(self, string):
    method _all_strings (line 1363) | def _all_strings(self, strip=False, types=PageElement.default):
    method decompose (line 1401) | def decompose(self):
    method clear (line 1421) | def clear(self, decompose=False):
    method smooth (line 1438) | def smooth(self):
    method index (line 1476) | def index(self, element):
    method get (line 1489) | def get(self, key, default=None):
    method get_attribute_list (line 1495) | def get_attribute_list(self, key, default=None):
    method has_attr (line 1509) | def has_attr(self, key):
    method __hash__ (line 1513) | def __hash__(self):
    method __getitem__ (line 1516) | def __getitem__(self, key):
    method __iter__ (line 1521) | def __iter__(self):
    method __len__ (line 1525) | def __len__(self):
    method __contains__ (line 1529) | def __contains__(self, x):
    method __bool__ (line 1532) | def __bool__(self):
    method __setitem__ (line 1536) | def __setitem__(self, key, value):
    method __delitem__ (line 1541) | def __delitem__(self, key):
    method __call__ (line 1545) | def __call__(self, *args, **kwargs):
    method __getattr__ (line 1551) | def __getattr__(self, tag):
    method __eq__ (line 1570) | def __eq__(self, other):
    method __ne__ (line 1587) | def __ne__(self, other):
    method __repr__ (line 1592) | def __repr__(self, encoding="unicode-escape"):
    method __unicode__ (line 1603) | def __unicode__(self):
    method encode (line 1609) | def encode(self, encoding=DEFAULT_OUTPUT_ENCODING,
    method decode (line 1635) | def decode(self, indent_level=None,
    method _should_pretty_print (line 1736) | def _should_pretty_print(self, indent_level):
    method prettify (line 1750) | def pretti
Copy disabled (too large) Download .json
Condensed preview — 2142 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (15,071K chars).
[
  {
    "path": ".bumpversion.cfg",
    "chars": 286,
    "preview": "[bumpversion]\ncurrent_version = 12.1.13\ncommit = True\ntag = False\n\n[bumpversion:file:setup.py]\nsearch = version='{curren"
  },
  {
    "path": ".editorconfig",
    "chars": 215,
    "preview": "# see http://editorconfig.org\nroot = true\n\n[*]\nend_of_line = lf\ntrim_trailing_whitespace = true\ninsert_final_newline = t"
  },
  {
    "path": ".gitattributes",
    "chars": 555,
    "preview": "# Set default behaviour, in case users don't have core.autocrlf set.\n* text=auto\n\n# Explicitly declare text files we wan"
  },
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "chars": 3353,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 726,
    "preview": "# Contributing\n\nWhen contributing to this repository, please first check the issues list, current pull requests, and FAQ"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 579,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 1171,
    "preview": "# Description\n\nPlease include a summary of the change and which issue is fixed. Please also include relevant motivation "
  },
  {
    "path": ".github/README.md",
    "chars": 5280,
    "preview": "nzbToMedia\n==========\n\nProvides an [efficient](https://github.com/clinton-hall/nzbToMedia/wiki/Efficient-on-demand-post-"
  },
  {
    "path": ".gitignore",
    "chars": 135,
    "preview": "*.cfg\n!.bumpversion.cfg\n*.cfg.old\n*.py[cod]\n*.log\n*.pid\n*.db\n*.dbm\n/userscripts/\n/logs/\n/.idea/\n/venv/\n*.dist-info\n*.egg"
  },
  {
    "path": "TorrentToMedia.py",
    "chars": 16974,
    "preview": "#!/usr/bin/env python\n# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n  "
  },
  {
    "path": "_config.yml",
    "chars": 26,
    "preview": "theme: jekyll-theme-cayman"
  },
  {
    "path": "autoProcessMedia.cfg.spec",
    "chars": 26713,
    "preview": "# nzbToMedia Configuration\n# For more information, visit https://github.com/clinton-hall/nzbToMedia/wiki\n\n[General]\n    "
  },
  {
    "path": "azure-pipelines.yml",
    "chars": 1702,
    "preview": "# Python package\n# Create and test a Python package on multiple Python versions.\n# Add steps that analyze code, save the"
  },
  {
    "path": "cleanup.py",
    "chars": 6421,
    "preview": "#!/usr/bin/env python\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_liter"
  },
  {
    "path": "core/__init__.py",
    "chars": 39928,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/auto_process/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "core/auto_process/books.py",
    "chars": 4619,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/auto_process/comics.py",
    "chars": 3320,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/auto_process/common.py",
    "chars": 2268,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport requests"
  },
  {
    "path": "core/auto_process/games.py",
    "chars": 3693,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/auto_process/managers/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "core/auto_process/managers/pymedusa.py",
    "chars": 6117,
    "preview": "import time\n\nfrom core import logger\nfrom core.auto_process.common import ProcessResult\nfrom core.auto_process.managers."
  },
  {
    "path": "core/auto_process/managers/sickbeard.py",
    "chars": 21720,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/auto_process/movies.py",
    "chars": 26934,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/auto_process/music.py",
    "chars": 11744,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/auto_process/tv.py",
    "chars": 22269,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/configuration.py",
    "chars": 34261,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/databases.py",
    "chars": 3365,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/extractor/__init__.py",
    "chars": 8716,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/extractor/bin/AMD64/license.txt",
    "chars": 3900,
    "preview": "  7-Zip\n  ~~~~~\n  License for use and distribution\n  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n  7-Zip Copyright (C) 1999-2018 I"
  },
  {
    "path": "core/extractor/bin/invisible.vbs",
    "chars": 512,
    "preview": "set args = WScript.Arguments\nnum = args.Count\n\nif num < 2 then\n    WScript.Echo \"Usage: [CScript | WScript] invis.vbs aS"
  },
  {
    "path": "core/extractor/bin/x86/license.txt",
    "chars": 3900,
    "preview": "  7-Zip\n  ~~~~~\n  License for use and distribution\n  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n  7-Zip Copyright (C) 1999-2018 I"
  },
  {
    "path": "core/github_api.py",
    "chars": 2039,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/logger.py",
    "chars": 9225,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/main_db.py",
    "chars": 12265,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/permissions.py",
    "chars": 3034,
    "preview": "import os\nimport sys\nimport logging\n\nlog = logging.getLogger(__name__)\nlog.addHandler(logging.NullHandler())\n\nWINDOWS = "
  },
  {
    "path": "core/plugins/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "core/plugins/downloaders/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "core/plugins/downloaders/configuration.py",
    "chars": 186,
    "preview": "from core.plugins.downloaders.nzb.configuration import configure_nzbs\nfrom core.plugins.downloaders.torrent.configuratio"
  },
  {
    "path": "core/plugins/downloaders/nzb/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "core/plugins/downloaders/nzb/configuration.py",
    "chars": 633,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport core\n\n\nd"
  },
  {
    "path": "core/plugins/downloaders/nzb/utils.py",
    "chars": 2506,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport os\n\nimpo"
  },
  {
    "path": "core/plugins/downloaders/torrent/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "core/plugins/downloaders/torrent/configuration.py",
    "chars": 3491,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport core\nfro"
  },
  {
    "path": "core/plugins/downloaders/torrent/deluge.py",
    "chars": 636,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nfrom deluge_cli"
  },
  {
    "path": "core/plugins/downloaders/torrent/qbittorrent.py",
    "chars": 709,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\n\nfrom qbittorre"
  },
  {
    "path": "core/plugins/downloaders/torrent/synology.py",
    "chars": 611,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nfrom syno.downl"
  },
  {
    "path": "core/plugins/downloaders/torrent/transmission.py",
    "chars": 669,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nfrom transmissi"
  },
  {
    "path": "core/plugins/downloaders/torrent/utils.py",
    "chars": 3960,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport time\n\nim"
  },
  {
    "path": "core/plugins/downloaders/torrent/utorrent.py",
    "chars": 575,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nfrom utorrent.c"
  },
  {
    "path": "core/plugins/downloaders/utils.py",
    "chars": 114,
    "preview": "from core.plugins.downloaders.torrent.utils import (\n    pause_torrent,\n    remove_torrent,\n    resume_torrent,\n)\n"
  },
  {
    "path": "core/plugins/plex.py",
    "chars": 1599,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport requests"
  },
  {
    "path": "core/plugins/subtitles.py",
    "chars": 4361,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nfrom babelfish "
  },
  {
    "path": "core/processor/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "core/processor/manual.py",
    "chars": 2718,
    "preview": "import os\n\nimport core\nfrom core import logger\nfrom core.auto_process.common import ProcessResult\nfrom core.processor im"
  },
  {
    "path": "core/processor/nzb.py",
    "chars": 6400,
    "preview": "import datetime\n\nimport core\nfrom core import logger, main_db\nfrom core.auto_process import comics, games, movies, music"
  },
  {
    "path": "core/processor/nzbget.py",
    "chars": 3476,
    "preview": "import os\nimport sys\n\nimport core\nfrom core import logger\nfrom core.processor import nzb\n\n\ndef parse_download_id():\n    "
  },
  {
    "path": "core/processor/sab.py",
    "chars": 1475,
    "preview": "import os\n\nfrom core import logger\nfrom core.processor import nzb\n\n# Constants\nMINIMUM_ARGUMENTS = 8\n\n\ndef process_scrip"
  },
  {
    "path": "core/scene_exceptions.py",
    "chars": 7849,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/transcoder.py",
    "chars": 45462,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/user_scripts.py",
    "chars": 6244,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/utils/__init__.py",
    "chars": 1392,
    "preview": "# coding=utf-8\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n"
  },
  {
    "path": "core/utils/common.py",
    "chars": 3532,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport os.path\n"
  },
  {
    "path": "core/utils/download_info.py",
    "chars": 855,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport datetime"
  },
  {
    "path": "core/utils/encoding.py",
    "chars": 4829,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport os\n\nfrom"
  },
  {
    "path": "core/utils/files.py",
    "chars": 8823,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport os\nimpor"
  },
  {
    "path": "core/utils/identification.py",
    "chars": 8206,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport os\nimpor"
  },
  {
    "path": "core/utils/links.py",
    "chars": 3387,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport os\nimpor"
  },
  {
    "path": "core/utils/naming.py",
    "chars": 1382,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport re\n\n\ndef"
  },
  {
    "path": "core/utils/network.py",
    "chars": 4102,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport socket\ni"
  },
  {
    "path": "core/utils/parsers.py",
    "chars": 6289,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport os\n\nimpo"
  },
  {
    "path": "core/utils/paths.py",
    "chars": 4962,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nfrom functools "
  },
  {
    "path": "core/utils/processes.py",
    "chars": 3534,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport os\nimpor"
  },
  {
    "path": "core/utils/shutil_custom.py",
    "chars": 463,
    "preview": "from __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nfrom functools "
  },
  {
    "path": "core/version_check.py",
    "chars": 20383,
    "preview": "# coding=utf-8\n# Author: Nic Wolfe <nic@wolfeden.ca>\n# Modified by: echel0n\n\nfrom __future__ import (\n    absolute_impor"
  },
  {
    "path": "eol.py",
    "chars": 5663,
    "preview": "#!/usr/bin/env python\n\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_liter"
  },
  {
    "path": "getffmpeg.sh",
    "chars": 517,
    "preview": "#!/bin/sh\n\n# get ffmpeg/yasm/x264\ngit clone git://source.ffmpeg.org/ffmpeg.git FFmpeg\ngit clone git://github.com/yasm/ya"
  },
  {
    "path": "libs/__init__.py",
    "chars": 968,
    "preview": "\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport os\nimpo"
  },
  {
    "path": "libs/__main__.py",
    "chars": 633,
    "preview": "\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport shutil\n"
  },
  {
    "path": "libs/autoload.py",
    "chars": 176,
    "preview": "\nfrom __future__ import (\n    absolute_import,\n    division,\n    print_function,\n    unicode_literals,\n)\n\nimport libs\n\n_"
  },
  {
    "path": "libs/common/__init__.py",
    "chars": 1,
    "preview": "\n"
  },
  {
    "path": "libs/common/_version.py",
    "chars": 21,
    "preview": "__version__ = '5.0.6'"
  },
  {
    "path": "libs/common/_yaml/__init__.py",
    "chars": 1402,
    "preview": "# This is a stub package designed to roughly emulate the _yaml\n# extension module, which previously existed as a standal"
  },
  {
    "path": "libs/common/appdirs.py",
    "chars": 24719,
    "preview": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (c) 2005-2010 ActiveState Software Inc.\n# Copyright (c) 2013 E"
  },
  {
    "path": "libs/common/babelfish/__init__.py",
    "chars": 761,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/converters/__init__.py",
    "chars": 9366,
    "preview": "# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is governed by the 3-clause B"
  },
  {
    "path": "libs/common/babelfish/converters/alpha2.py",
    "chars": 556,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/converters/alpha3b.py",
    "chars": 559,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/converters/alpha3t.py",
    "chars": 559,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/converters/countryname.py",
    "chars": 1077,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/converters/name.py",
    "chars": 551,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/converters/opensubtitles.py",
    "chars": 1774,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/converters/scope.py",
    "chars": 847,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/converters/type.py",
    "chars": 898,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/country.py",
    "chars": 3242,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/data/iso-3166-1.txt",
    "chars": 3859,
    "preview": "Country Name;ISO 3166-1-alpha-2 code\nAFGHANISTAN;AF\nÅLAND ISLANDS;AX\nALBANIA;AL\nALGERIA;DZ\nAMERICAN SAMOA;AS\nANDORRA;AD\n"
  },
  {
    "path": "libs/common/babelfish/data/iso-639-3.tab",
    "chars": 176168,
    "preview": "Id\tPart2B\tPart2T\tPart1\tScope\tLanguage_Type\tRef_Name\tComment\naaa\t\t\t\tI\tL\tGhotuo\t\naab\t\t\t\tI\tL\tAlumu-Tesu\t\naac\t\t\t\tI\tL\tAri\t\naa"
  },
  {
    "path": "libs/common/babelfish/data/iso15924-utf8-20131012.txt",
    "chars": 9702,
    "preview": "#\n# ISO 15924 - Codes for the representation of names of scripts\n#             Codes pour la représentation des noms d’é"
  },
  {
    "path": "libs/common/babelfish/data/opensubtitles_languages.txt",
    "chars": 9578,
    "preview": "IdSubLanguage\tISO639\tLanguageName\tUploadEnabled\tWebEnabled\naar\taa\tAfar, afar\t0\t0\nabk\tab\tAbkhazian\t0\t0\nace\t\tAchinese\t0\t0\n"
  },
  {
    "path": "libs/common/babelfish/exceptions.py",
    "chars": 2332,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/language.py",
    "chars": 6874,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/babelfish/script.py",
    "chars": 2054,
    "preview": "# -*- coding: utf-8 -*-\n#\n# Copyright (c) 2013 the BabelFish authors. All rights reserved.\n# Use of this source code is "
  },
  {
    "path": "libs/common/beets/__init__.py",
    "chars": 1380,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/__main__.py",
    "chars": 825,
    "preview": "# This file is part of beets.\n# Copyright 2017, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/art.py",
    "chars": 7924,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/autotag/__init__.py",
    "chars": 6687,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/autotag/hooks.py",
    "chars": 21866,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/autotag/match.py",
    "chars": 19893,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/autotag/mb.py",
    "chars": 21532,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/config_default.yaml",
    "chars": 2997,
    "preview": "library: library.db\ndirectory: ~/Music\n\nimport:\n    write: yes\n    copy: yes\n    move: no\n    link: no\n    hardlink: no\n"
  },
  {
    "path": "libs/common/beets/dbcore/__init__.py",
    "chars": 1040,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/dbcore/db.py",
    "chars": 37013,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/dbcore/query.py",
    "chars": 28599,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/dbcore/queryparse.py",
    "chars": 9680,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/dbcore/types.py",
    "chars": 6513,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/importer.py",
    "chars": 61461,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/library.py",
    "chars": 59076,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/logging.py",
    "chars": 4161,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/mediafile.py",
    "chars": 963,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/plugins.py",
    "chars": 24973,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/random.py",
    "chars": 3676,
    "preview": "# This file is part of beets.\n# Copyright 2016, Philippe Mongeau.\n#\n# Permission is hereby granted, free of charge, to a"
  },
  {
    "path": "libs/common/beets/ui/__init__.py",
    "chars": 43849,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/ui/commands.py",
    "chars": 63045,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/ui/completion_base.sh",
    "chars": 4454,
    "preview": "# This file is part of beets.\n# Copyright (c) 2014, Thomas Scholtes.\n#\n# Permission is hereby granted, free of charge, t"
  },
  {
    "path": "libs/common/beets/util/__init__.py",
    "chars": 36926,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/util/artresizer.py",
    "chars": 15240,
    "preview": "# This file is part of beets.\n# Copyright 2016, Fabrice Laporte\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/util/bluelet.py",
    "chars": 19890,
    "preview": "\"\"\"Extremely simple pure-Python implementation of coroutine-style\nasynchronous socket I/O. Inspired by, but inferior to,"
  },
  {
    "path": "libs/common/beets/util/confit.py",
    "chars": 982,
    "preview": "# This file is part of beets.\n# Copyright 2016-2019, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, t"
  },
  {
    "path": "libs/common/beets/util/enumeration.py",
    "chars": 1370,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/util/functemplate.py",
    "chars": 20497,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/util/hidden.py",
    "chars": 2735,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/util/pipeline.py",
    "chars": 16317,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beets/vfs.py",
    "chars": 1750,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/__init__.py",
    "chars": 802,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/absubmit.py",
    "chars": 6915,
    "preview": "# This file is part of beets.\n# Copyright 2016, Pieter Mulder.\n#\n# Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "libs/common/beetsplug/acousticbrainz.py",
    "chars": 11826,
    "preview": "# This file is part of beets.\n# Copyright 2015-2016, Ohm Patel.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/albumtypes.py",
    "chars": 2309,
    "preview": "# This file is part of beets.\n# Copyright 2021, Edgars Supe.\n#\n# Permission is hereby granted, free of charge, to any pe"
  },
  {
    "path": "libs/common/beetsplug/aura.py",
    "chars": 33545,
    "preview": "# This file is part of beets.\n# Copyright 2020, Callum Brown.\n#\n# Permission is hereby granted, free of charge, to any p"
  },
  {
    "path": "libs/common/beetsplug/badfiles.py",
    "chars": 7394,
    "preview": "# This file is part of beets.\n# Copyright 2016, François-Xavier Thomas.\n#\n# Permission is hereby granted, free of charge"
  },
  {
    "path": "libs/common/beetsplug/bareasc.py",
    "chars": 2866,
    "preview": "# This file is part of beets.\n# Copyright 2016, Philippe Mongeau.\n# Copyright 2021, Graham R. Cobb.\n#\n# Permission is he"
  },
  {
    "path": "libs/common/beetsplug/beatport.py",
    "chars": 18530,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/bench.py",
    "chars": 4111,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/bpd/__init__.py",
    "chars": 57378,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/bpd/gstplayer.py",
    "chars": 9905,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/bpm.py",
    "chars": 2647,
    "preview": "# This file is part of beets.\n# Copyright 2016, aroquen\n#\n# Permission is hereby granted, free of charge, to any person "
  },
  {
    "path": "libs/common/beetsplug/bpsync.py",
    "chars": 6591,
    "preview": "# This file is part of beets.\n# Copyright 2019, Rahul Ahuja.\n#\n# Permission is hereby granted, free of charge, to any pe"
  },
  {
    "path": "libs/common/beetsplug/bucket.py",
    "chars": 8052,
    "preview": "# This file is part of beets.\n# Copyright 2016, Fabrice Laporte.\n#\n# Permission is hereby granted, free of charge, to an"
  },
  {
    "path": "libs/common/beetsplug/chroma.py",
    "chars": 11871,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/convert.py",
    "chars": 20593,
    "preview": "# This file is part of beets.\n# Copyright 2016, Jakob Schnitzer.\n#\n# Permission is hereby granted, free of charge, to an"
  },
  {
    "path": "libs/common/beetsplug/deezer.py",
    "chars": 8463,
    "preview": "# This file is part of beets.\n# Copyright 2019, Rahul Ahuja.\n#\n# Permission is hereby granted, free of charge, to any pe"
  },
  {
    "path": "libs/common/beetsplug/discogs.py",
    "chars": 25616,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/duplicates.py",
    "chars": 13282,
    "preview": "# This file is part of beets.\n# Copyright 2016, Pedro Silva.\n#\n# Permission is hereby granted, free of charge, to any pe"
  },
  {
    "path": "libs/common/beetsplug/edit.py",
    "chars": 13892,
    "preview": "# This file is part of beets.\n# Copyright 2016\n#\n# Permission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "libs/common/beetsplug/embedart.py",
    "chars": 7529,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/embyupdate.py",
    "chars": 5827,
    "preview": "\"\"\"Updates the Emby Library whenever the beets library is changed.\n\n    emby:\n        host: localhost\n        port: 8096"
  },
  {
    "path": "libs/common/beetsplug/export.py",
    "chars": 7737,
    "preview": "# This file is part of beets.\n#\n# Permission is hereby granted, free of charge, to any person obtaining\n# a copy of this"
  },
  {
    "path": "libs/common/beetsplug/fetchart.py",
    "chars": 44418,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/filefilter.py",
    "chars": 2919,
    "preview": "# This file is part of beets.\n# Copyright 2016, Malte Ried.\n#\n# Permission is hereby granted, free of charge, to any per"
  },
  {
    "path": "libs/common/beetsplug/fish.py",
    "chars": 10224,
    "preview": "# This file is part of beets.\n# Copyright 2015, winters jean-marie.\n# Copyright 2020, Justin Mayer <https://justinmayer."
  },
  {
    "path": "libs/common/beetsplug/freedesktop.py",
    "chars": 1374,
    "preview": "# This file is part of beets.\n# Copyright 2016, Matt Lichtenberg.\n#\n# Permission is hereby granted, free of charge, to a"
  },
  {
    "path": "libs/common/beetsplug/fromfilename.py",
    "chars": 5240,
    "preview": "# This file is part of beets.\n# Copyright 2016, Jan-Erik Dahlin\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/ftintitle.py",
    "chars": 6042,
    "preview": "# This file is part of beets.\n# Copyright 2016, Verrus, <github.com/Verrus/beets-plugin-featInTitle>\n#\n# Permission is h"
  },
  {
    "path": "libs/common/beetsplug/fuzzy.py",
    "chars": 1465,
    "preview": "# This file is part of beets.\n# Copyright 2016, Philippe Mongeau.\n#\n# Permission is hereby granted, free of charge, to a"
  },
  {
    "path": "libs/common/beetsplug/gmusic.py",
    "chars": 1026,
    "preview": "# This file is part of beets.\n#\n# Permission is hereby granted, free of charge, to any person obtaining\n# a copy of this"
  },
  {
    "path": "libs/common/beetsplug/hook.py",
    "chars": 4040,
    "preview": "# This file is part of beets.\n# Copyright 2015, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/ihate.py",
    "chars": 2877,
    "preview": "# This file is part of beets.\n# Copyright 2016, Blemjhoo Tezoulbr <baobab@heresiarch.info>.\n#\n# Permission is hereby gra"
  },
  {
    "path": "libs/common/beetsplug/importadded.py",
    "chars": 5587,
    "preview": "\"\"\"Populate an item's `added` and `mtime` fields by using the file\nmodification time (mtime) of the item's source file b"
  },
  {
    "path": "libs/common/beetsplug/importfeeds.py",
    "chars": 4392,
    "preview": "# This file is part of beets.\n# Copyright 2016, Fabrice Laporte.\n#\n# Permission is hereby granted, free of charge, to an"
  },
  {
    "path": "libs/common/beetsplug/info.py",
    "chars": 7083,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/inline.py",
    "chars": 4359,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/ipfs.py",
    "chars": 10386,
    "preview": "# This file is part of beets.\n#\n# Permission is hereby granted, free of charge, to any person obtaining\n# a copy of this"
  },
  {
    "path": "libs/common/beetsplug/keyfinder.py",
    "chars": 3453,
    "preview": "# This file is part of beets.\n# Copyright 2016, Thomas Scholtes.\n#\n# Permission is hereby granted, free of charge, to an"
  },
  {
    "path": "libs/common/beetsplug/kodiupdate.py",
    "chars": 3012,
    "preview": "# This file is part of beets.\n# Copyright 2017, Pauli Kettunen.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/lastgenre/__init__.py",
    "chars": 16849,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/lastgenre/genres-tree.yaml",
    "chars": 15670,
    "preview": "- african:\n    - african heavy metal\n    - african hip hop\n    - afrobeat\n    - apala\n    - benga\n    - bikutsi\n    - bo"
  },
  {
    "path": "libs/common/beetsplug/lastgenre/genres.txt",
    "chars": 17223,
    "preview": "2 tone\n2-step garage\n4-beat\n4x4 garage\n8-bit\nacapella\nacid\nacid breaks\nacid house\nacid jazz\nacid rock\nacoustic music\naco"
  },
  {
    "path": "libs/common/beetsplug/lastimport.py",
    "chars": 8459,
    "preview": "# This file is part of beets.\n# Copyright 2016, Rafael Bodill https://github.com/rafi\n#\n# Permission is hereby granted, "
  },
  {
    "path": "libs/common/beetsplug/loadext.py",
    "chars": 1496,
    "preview": "# This file is part of beets.\n# Copyright 2019, Jack Wilsdon <jack.wilsdon@gmail.com>\n#\n# Permission is hereby granted, "
  },
  {
    "path": "libs/common/beetsplug/lyrics.py",
    "chars": 34170,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/mbcollection.py",
    "chars": 6156,
    "preview": "# This file is part of beets.\n# Copyright (c) 2011, Jeffrey Aylesworth <mail@jeffrey.red>\n#\n# Permission is hereby grant"
  },
  {
    "path": "libs/common/beetsplug/mbsubmit.py",
    "chars": 2107,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson and Diego Moreda.\n#\n# Permission is hereby granted, free "
  },
  {
    "path": "libs/common/beetsplug/mbsync.py",
    "chars": 7421,
    "preview": "# This file is part of beets.\n# Copyright 2016, Jakob Schnitzer.\n#\n# Permission is hereby granted, free of charge, to an"
  },
  {
    "path": "libs/common/beetsplug/metasync/__init__.py",
    "chars": 4281,
    "preview": "# This file is part of beets.\n# Copyright 2016, Heinz Wiesinger.\n#\n# Permission is hereby granted, free of charge, to an"
  },
  {
    "path": "libs/common/beetsplug/metasync/amarok.py",
    "chars": 4017,
    "preview": "# This file is part of beets.\n# Copyright 2016, Heinz Wiesinger.\n#\n# Permission is hereby granted, free of charge, to an"
  },
  {
    "path": "libs/common/beetsplug/metasync/itunes.py",
    "chars": 4479,
    "preview": "# This file is part of beets.\n# Copyright 2016, Tom Jaspers.\n#\n# Permission is hereby granted, free of charge, to any pe"
  },
  {
    "path": "libs/common/beetsplug/missing.py",
    "chars": 7991,
    "preview": "# This file is part of beets.\n# Copyright 2016, Pedro Silva.\n# Copyright 2017, Quentin Young.\n#\n# Permission is hereby g"
  },
  {
    "path": "libs/common/beetsplug/mpdstats.py",
    "chars": 12277,
    "preview": "# This file is part of beets.\n# Copyright 2016, Peter Schnebel and Johann Klähn.\n#\n# Permission is hereby granted, free "
  },
  {
    "path": "libs/common/beetsplug/mpdupdate.py",
    "chars": 4121,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/parentwork.py",
    "chars": 7948,
    "preview": "# This file is part of beets.\n# Copyright 2017, Dorian Soergel.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/permissions.py",
    "chars": 4108,
    "preview": "\"\"\"Fixes file permissions after the file gets written on import. Put something\nlike the following in your config.yaml to"
  },
  {
    "path": "libs/common/beetsplug/play.py",
    "chars": 7677,
    "preview": "# This file is part of beets.\n# Copyright 2016, David Hamp-Gonsalves\n#\n# Permission is hereby granted, free of charge, t"
  },
  {
    "path": "libs/common/beetsplug/playlist.py",
    "chars": 6841,
    "preview": "# This file is part of beets.\n#\n# Permission is hereby granted, free of charge, to any person obtaining\n# a copy of this"
  },
  {
    "path": "libs/common/beetsplug/plexupdate.py",
    "chars": 3569,
    "preview": "\"\"\"Updates an Plex library whenever the beets library is changed.\n\nPlex Home users enter the Plex Token to enable updati"
  },
  {
    "path": "libs/common/beetsplug/random.py",
    "chars": 1957,
    "preview": "# This file is part of beets.\n# Copyright 2016, Philippe Mongeau.\n#\n# Permission is hereby granted, free of charge, to a"
  },
  {
    "path": "libs/common/beetsplug/replaygain.py",
    "chars": 49203,
    "preview": "# This file is part of beets.\n# Copyright 2016, Fabrice Laporte, Yevgeny Bezman, and Adrian Sampson.\n#\n# Permission is h"
  },
  {
    "path": "libs/common/beetsplug/rewrite.py",
    "chars": 2749,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/scrub.py",
    "chars": 5248,
    "preview": "# This file is part of beets.\n# Copyright 2016, Adrian Sampson.\n#\n# Permission is hereby granted, free of charge, to any"
  },
  {
    "path": "libs/common/beetsplug/smartplaylist.py",
    "chars": 8735,
    "preview": "# This file is part of beets.\n# Copyright 2016, Dang Mai <contact@dangmai.net>.\n#\n# Permission is hereby granted, free o"
  },
  {
    "path": "libs/common/beetsplug/sonosupdate.py",
    "chars": 1606,
    "preview": "# This file is part of beets.\n# Copyright 2018, Tobias Sauerwein.\n#\n# Permission is hereby granted, free of charge, to a"
  },
  {
    "path": "libs/common/beetsplug/spotify.py",
    "chars": 19323,
    "preview": "# This file is part of beets.\n# Copyright 2019, Rahul Ahuja.\n#\n# Permission is hereby granted, free of charge, to any pe"
  }
]

// ... and 1942 more files (download for full content)

About this extraction

This page contains the full source code of the clinton-hall/nzbToMedia GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 2142 files (13.6 MB), approximately 3.7M tokens, and a symbol index with 19992 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!