# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['mining', 'scripts', 'scripts.mining', 'xklb']

package_data = \
{'': ['*']}

install_requires = \
['Markdown',
 'catt',
 'ffmpeg-python',
 'ftfy',
 'gallery-dl',
 'humanize',
 'ipython',
 'joblib',
 'mutagen',
 'natsort',
 'praw',
 'protobuf<4',
 'pysubs2',
 'python-mpv-jsonipc',
 'regex',
 'rich',
 'screeninfo',
 'sqlite-utils>=3.30',
 'subliminal',
 'tabulate',
 'tinytag',
 'yt-dlp']

extras_require = \
{'full': ['brotab', 'aiohttp', 'PyExifTool', 'textract', 'orjson', 'pandas']}

entry_points = \
{'console_scripts': ['lb = xklb.lb:library', 'library = xklb.lb:library']}

setup_kwargs = {
    'name': 'xklb',
    'version': '1.23.26',
    'description': 'xk library',
    'long_description': '# xk media library\n\nA wise philosopher once told me: "[the future is autotainment](https://www.youtube.com/watch?v=F9sZFrsjPp0)".\n\nManage large media libraries. Similar to Plex but more minimalist.\nPrimary usage is local filesystem but also supports some virtual constructs like\ntracking online video playlists (eg. YouTube subscriptions) or daily browser tabs.\n\nRequired: `ffmpeg`\n\nRecommended: `mpv`, `fish`, `firefox`\n\n## Install\n\nLinux recommended but [Windows setup instructions](./Windows.md) available.\n\n    pip install xklb\n\n## Examples\n\n<details><summary>List all subcommands</summary>\n\n    $ library\n    xk media library subcommands (v1.23.026)\n\n    local media:\n      lb fsadd                 Create a local media database; Add folders\n      lb fsupdate              Refresh database: add new files, mark deleted\n\n      lb listen                Listen to local and online media\n      lb watch                 Watch local and online media\n      lb read                  Read books\n      lb view                  View images\n\n      lb bigdirs               Discover folders which take much room\n      lb mv-list               Reach a target free space by moving data across mount points\n      lb dedupe                Deduplicate local db files\n\n      lb christen              Cleanse files by giving them a new name\n\n    online media:\n      lb tubeadd               Create a tube database; Add playlists\n      lb tubeupdate            Fetch new videos from saved playlists\n\n      lb redditadd             Create a reddit database; Add subreddits\n      lb redditupdate          Fetch new posts from saved subreddits\n\n    downloads:\n      lb download              Download media\n      lb redownload            Redownload missing media\n      lb block                 Prevent downloading specific URLs\n      lb merge-dbs             Merge multiple SQLITE files\n      lb merge-online-local    Merge local and online metadata\n\n    playback:\n      lb now                   Print what is currently playing\n      lb next                  Play next file\n      lb stop                  Stop all playback\n      lb pause                 Pause all playback\n\n    statistics:\n      lb playlists             List added playlists\n      lb dlstatus              Show download status\n      lb usage                 Print mount usage\n\n    browser tabs:\n      lb tabsadd               Create a tabs database; Add URLs\n      lb tabs                  Open your tabs for the day\n      lb surf                  Load browser tabs in a streaming way (stdin)\n\n    mining:\n      lb reddit-selftext       db selftext external links -> db media table\n      lb pushshift             Convert Pushshift jsonl.zstd -> reddit.db format (stdin)\n      lb nfb-films             NFB Director links -> film links (stdin)\n      lb nouns                 Unstructured text -> compound nouns (stdin)\n      lb hnadd                 Create a hackernews database (this takes a few days)\n    \n\n</details>\n\n### Watch online media on your PC\n\n    wget https://github.com/chapmanjacobd/library/raw/main/examples/mealtime.tw.db\n    library watch mealtime.tw.db\n\n### Listen to online media on a chromecast group\n\n    wget https://github.com/chapmanjacobd/library/raw/main/examples/music.tl.db\n    library listen music.tl.db -ct "House speakers"\n\n### Hook into HackerNews\n\n    wget https://github.com/chapmanjacobd/hn_mining/raw/main/hackernews_only_direct.tw.db\n    library watch hackernews_only_direct.tw.db --random --ignore-errors\n\n## Getting started with local media\n\n### 1. Extract Metadata\n\nFor thirty terabytes of video the initial scan takes about four hours to complete.\nAfter that, subsequent scans of the path (or any subpaths) are much quicker--only\nnew files will be read by `ffprobe`.\n\n    library fsadd tv.db ./video/folder/\n\n![termtosvg](./examples/extract.svg)\n\n### 2. Watch / Listen from local files\n\n    library watch tv.db                           # the default post-action is to do nothing\n    library watch tv.db --post-action delete      # delete file after playing\n    library listen finalists.db --post-action=ask # ask whether to delete after playing\n\nTo stop playing press Ctrl+C in either the terminal or mpv\n\n## Getting started with online media\n\n### 1. Download Metadata\n\nDownload playlist and channel metadata. Break free of the YouTube algo~\n\n    library tubeadd educational.db https://www.youtube.com/c/BranchEducation/videos\n\n[![termtosvg](./examples/tubeadd.svg "library tubeadd example")](https://asciinema.org/a/BzplqNj9sCERH3A80GVvwsTTT)\n\nAnd you can always add more later--even from different websites.\n\n    library tubeadd maker.db https://vimeo.com/terburg\n\nTo prevent mistakes the default configuration is to download metadata for only\nthe most recent 20,000 videos per playlist/channel.\n\n    library tubeadd maker.db --dl-config playlistend=1000\n\nBe aware that there are some YouTube Channels which have many items--for example\nthe TEDx channel has about 180,000 videos. Some channels even have upwards of\ntwo million videos. More than you could likely watch in one sitting--maybe even one lifetime.\nOn a high-speed connection (>500 Mbps), it can take up to five hours to download\nthe metadata for 180,000 videos.\n\n#### 1a. Get new videos for saved playlists\n\nTubeupdate will go through the list of added playlists and fetch metadata for\nany videos not previously seen.\n\n    library tubeupdate tube.db\n\n### 2. Watch / Listen from websites\n\n    library watch maker.db\n\nTo stop playing press Ctrl+C in either the terminal or mpv\n\n## Getting started with tabs: visit websites on a schedule\n\ntabs is a way to organize your visits to URLs that you want to visit every once in a while.\n\nIf you want to track _changes_ to websites over time there are better tools out there, like\n`huginn`, `urlwatch`, or `changedetection.io`.\n\nThe use-case of tabs are websites that you know are going to change: subreddits, games,\nor tools that you want to use for a few minutes daily, weekly, monthly, quarterly, or yearly.\n\n### 1. Add your websites\n\n    library tabsadd tabs.db --frequency monthly --category fun \\\n        https://old.reddit.com/r/Showerthoughts/top/?sort=top&t=month \\\n        https://old.reddit.com/r/RedditDayOf/top/?sort=top&t=month\n\n### 2. Add library tabs to cron\n\nlibrary tabs is meant to run **once per day**. Here is how you would configure it with `crontab`:\n\n    45 9 * * * DISPLAY=:0 library tabs /home/my/tabs.db\n\nOr with `systemd`:\n\n    tee ~/.config/systemd/user/tabs.service\n    [Unit]\n    Description=xklb daily browser tabs\n\n    [Service]\n    Type=simple\n    RemainAfterExit=no\n    Environment="DISPLAY=:0"\n    ExecStart="/usr/bin/fish" "-c" "lb tabs /home/xk/lb/tabs.db"\n\n    tee ~/.config/systemd/user/tabs.timer\n    [Unit]\n    Description=xklb daily browser tabs timer\n\n    [Timer]\n    Persistent=yes\n    OnCalendar=*-*-* 9:58\n\n    [Install]\n    WantedBy=timers.target\n\n    systemctl --user daemon-reload\n    systemctl --user enable --now tabs.service\n\nYou can also invoke tabs manually:\n\n    library tabs tabs.db -L 1  # open one tab\n\n## Usage\n\n    $ library watch -h\n    usage: library watch [database] [optional args]\n\n    Control playback:\n        To stop playback press Ctrl-C in either the terminal or mpv\n\n        Create global shortcuts in your desktop environment by sending commands to mpv_socket:\n        echo \'playlist-next force\' | socat - /tmp/mpv_socket\n\n    Override the default player (mpv):\n        library does a lot of things to try to automatically use your preferred media player\n        but if it doesn\'t guess right you can make it explicit:\n        library watch --player "vlc --vlc-opts"\n\n    Cast to chromecast groups:\n        library watch --cast --cast-to "Office pair"\n        library watch -ct "Office pair"  # equivalent\n        If you don\'t know the exact name of your chromecast group run `catt scan`\n\n    Play media in order (similarly named episodes):\n        library watch --play-in-order\n        There are multiple strictness levels of --play-in-order:\n        library watch -O   # slow, more complex algorithm\n        library watch -OO  # above, plus ignores most filters\n        library watch -OOO # above, plus ignores include/exclude filter during ordinal search\n\n    Play recent partially-watched videos (requires mpv history):\n        library watch --partial       # play newest first\n        library watch --partial old   # play oldest first\n        library watch -P o            # equivalent\n        library watch -P p            # sort by progress / duration\n        library watch -P s            # skip partially watched (only show unseen)\n\n        The default time used is "last-viewed" (ie. the most recent time you closed the video)\n        If you want to use the "first-viewed" time (ie. the very first time you opened the video)\n        library watch -P f            # use watch_later file creation time instead of modified time\n\n        You can combine most of these options, though some will be overridden by others.\n        library watch -P fo           # this means "show the oldest videos using the time I first opened them"\n\n    Print instead of play:\n        library watch --print --limit 10  # print the next 10 files\n        library watch -p -L 10  # print the next 10 files\n        library watch -p  # this will print _all_ the media. be cautious about `-p` on an unfiltered set\n\n        Printing modes\n        library watch -p    # print in a table\n        library watch -p p  # equivalent\n        library watch -p a  # print an aggregate report\n        library watch -p a  # print a bigdirs report (see lb bigdirs -h for more info)\n        library watch -p f  # print fields -- useful for piping paths to utilities like xargs or GNU Parallel\n\n        Check if you have downloaded something before\n        library watch -u duration -p -s \'title\'\n\n        Print an aggregate report of deleted media\n        library watch -w time_deleted!=0 -p=a\n        ╒═══════════╤══════════════╤═════════╤═════════╕\n        │ path      │ duration     │ size    │   count │\n        ╞═══════════╪══════════════╪═════════╪═════════╡\n        │ Aggregate │ 14 days, 23  │ 50.6 GB │   29058 │\n        │           │ hours and 42 │         │         │\n        │           │ minutes      │         │         │\n        ╘═══════════╧══════════════╧═════════╧═════════╛\n        Total duration: 14 days, 23 hours and 42 minutes\n\n        Print an aggregate report of media that has no duration information (likely corrupt or online media)\n        library watch -w \'duration is null\' -p=a\n\n        Print a list of filenames which have below 1280px resolution\n        library watch -w \'width<1280\' -p=f\n\n        Print media you have partially viewed with mpv\n        library watch -p=v\n\n        View how much time you have watched\n        library watch -w play_count\'>\'0 -p=a\n\n        See how much video you have\n        library watch video.db -p=a\n        ╒═══════════╤═════════╤═════════╤═════════╕\n        │ path      │   hours │ size    │   count │\n        ╞═══════════╪═════════╪═════════╪═════════╡\n        │ Aggregate │  145769 │ 37.6 TB │  439939 │\n        ╘═══════════╧═════════╧═════════╧═════════╛\n        Total duration: 16 years, 7 months, 19 days, 17 hours and 25 minutes\n\n        View all the columns\n        library watch -p -L 1 --cols \'*\'\n\n        Open ipython with all of your media\n        library watch -vv -p --cols \'*\'\n        ipdb> len(media)\n        462219\n\n    Set the play queue size:\n        By default the play queue is 120--long enough that you likely have not noticed\n        but short enough that the program is snappy.\n\n        If you want everything in your play queue you can use the aid of infinity.\n        Pick your poison (these all do effectively the same thing):\n        library watch -L inf\n        library watch -l inf\n        library watch --queue inf\n        library watch -L 99999999999999999999999\n\n        You may also want to restrict the play queue.\n        For example, when you only want 1000 random files:\n        library watch -u random -L 1000\n\n    Offset the play queue:\n        You can also offset the queue. For example if you want to skip one or ten media:\n        library watch --skip 10        # offset ten from the top of an ordered query\n\n    Repeat\n        library watch                  # listen to 120 random songs (DEFAULT_PLAY_QUEUE)\n        library watch --limit 5        # listen to FIVE songs\n        library watch -l inf -u random # listen to random songs indefinitely\n        library watch -s infinite      # listen to songs from the band infinite\n\n    Constrain media by search:\n        Audio files have many tags to readily search through so metadata like artist,\n        album, and even mood are included in search.\n        Video files have less consistent metadata and so only paths are included in search.\n        library watch --include happy  # only matches will be included\n        library watch -s happy         # equivalent\n        library watch --exclude sad    # matches will be excluded\n        library watch -E sad           # equivalent\n\n        Search only the path column\n        library watch -O -s \'path : mad max\'\n        library watch -O -s \'path : "mad max"\' # add "quotes" to be more strict\n\n        Double spaces are parsed as one space\n        library watch -s \'  ost\'        # will match OST and not ghost\n        library watch -s toy story      # will match \'/folder/toy/something/story.mp3\'\n        library watch -s \'toy  story\'   # will match more strictly \'/folder/toy story.mp3\'\n\n        You can search without -s but it must directly follow the database due to how argparse works\n        library watch my.db searching for something\n\n    Constrain media by arbitrary SQL expressions:\n        library watch --where audio_count = 2  # media which have two audio tracks\n        library watch -w "language = \'eng\'"    # media which have an English language tag\n                                                    (this could be audio _or_ subtitle)\n        library watch -w subtitle_count=0      # media that doesn\'t have subtitles\n\n    Constrain media to duration (in minutes):\n        library watch --duration 20\n        library watch -d 6  # 6 mins ±10 percent (ie. between 5 and 7 mins)\n        library watch -d-6  # less than 6 mins\n        library watch -d+6  # more than 6 mins\n\n        Duration can be specified multiple times:\n        library watch -d+5 -d-7  # should be similar to -d 6\n\n        If you want exact time use `where`\n        library watch --where \'duration=6*60\'\n\n    Constrain media to file size (in megabytes):\n        library watch --size 20\n        library watch -S 6  # 6 MB ±10 percent (ie. between 5 and 7 MB)\n        library watch -S-6  # less than 6 MB\n        library watch -S+6  # more than 6 MB\n\n    Constrain media by time_created / time_played / time_deleted / time_modified:\n        library watch --created-within \'3 days\'\n        library watch --created-before \'3 years\'\n\n    Constrain media by throughput:\n        Bitrate information is not explicitly saved.\n        You can use file size and duration as a proxy for throughput:\n        library watch -w \'size/duration<50000\'\n\n    Constrain media to portrait orientation video:\n        library watch --portrait\n        library watch -w \'width<height\' # equivalent\n\n    Constrain media to duration of videos which match any size constraints:\n        library watch --duration-from-size +700 -u \'duration desc, size desc\'\n\n    Constrain media to online-media or local-media:\n        Not to be confused with only local-media which is not "offline" (ie. one HDD disconnected)\n        library watch --online-media-only\n        library watch --online-media-only -i  # and ignore playback errors (ie. YouTube video deleted)\n        library watch --local-media-only\n\n    Specify media play order:\n        library watch --sort duration   # play shortest media first\n        library watch -u duration desc  # play longest media first\n        You can use multiple SQL ORDER BY expressions\n        library watch -u \'subtitle_count > 0 desc\' # play media that has at least one subtitle first\n\n    Post-actions -- choose what to do after playing:\n        library watch --post-action delete  # delete file after playing\n        library watch -k ask  # ask after each whether to keep or delete\n\n        library watch -k askkeep  # ask after each whether to move to a keep folder or delete\n        The default location of the keep folder is ./keep/ (relative to the played media file)\n        You can change this by explicitly setting an *absolute* `keep-dir` path:\n        library watch -k askkeep --keep-dir /home/my/music/keep/\n\n    Experimental options:\n        Duration to play (in seconds) while changing the channel\n        library watch --interdimensional-cable 40\n        library watch -4dtv 40\n\n        Playback multiple files at once\n        library watch --multiple-playback    # one per display; or two if only one display detected\n        library watch --multiple-playback 4  # play four media at once, divide by available screens\n        library watch -m 4 --screen-name eDP # play four media at once on specific screen\n        library watch -m 4 --loop --crop     # play four cropped videos on a loop\n        library watch -m 4 --hstack          # use hstack style\n\n\n## More examples\n\n### Organize via separate databases.\n\n    library fsadd --audio both.db ./audiobooks/ ./podcasts/\n    library fsadd --audio audiobooks.db ./audiobooks/\n    library fsadd --audio podcasts.db ./podcasts/ ./another/more/secret/podcasts_folder/\n\n### Find large folders to curate or candidates for freeing up space by moving to another mount point\n\n<details><summary>lb mv-list</summary>\n\nThe program takes a mount point and a xklb database file. If you don\'t have a database file you can create one like this:\n\n    $ lb fsadd --filesystem d.db ~/d/\n\nBut this should definitely also work with xklb audio and video databases:\n\n    $ lb mv-list /mnt/d/ video.db\n\nThe program will print a table with a sorted list of folders which are good candidates for moving. Candidates are determined by how many files are in the folder (so you don\'t spend hours waiting for folders with millions of tiny files to copy over). The default is 4 to 4000--but it can be adjusted via the --lower and --upper flags.\n\n    ...\n    ├──────────┼─────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────┤\n    │ 4.0 GB   │       7 │ /mnt/d/71_Mealtime_Videos/unsorted/Miguel_4K/                                                                 │\n    ├──────────┼─────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────┤\n    │ 5.7 GB   │      10 │ /mnt/d/71_Mealtime_Videos/unsorted/Bollywood_Premium/                                                         │\n    ├──────────┼─────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────┤\n    │ 2.3 GB   │       4 │ /mnt/d/71_Mealtime_Videos/chief_wiggum/                                                                       │\n    ╘══════════╧═════════╧═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╛\n    6702 other folders not shown\n\n    ██╗███╗░░██╗░██████╗████████╗██████╗░██╗░░░██╗░█████╗░████████╗██╗░█████╗░███╗░░██╗░██████╗\n    ██║████╗░██║██╔════╝╚══██╔══╝██╔══██╗██║░░░██║██╔══██╗╚══██╔══╝██║██╔══██╗████╗░██║██╔════╝\n    ██║██╔██╗██║╚█████╗░░░░██║░░░██████╔╝██║░░░██║██║░░╚═╝░░░██║░░░██║██║░░██║██╔██╗██║╚█████╗░\n    ██║██║╚████║░╚═══██╗░░░██║░░░██╔══██╗██║░░░██║██║░░██╗░░░██║░░░██║██║░░██║██║╚████║░╚═══██╗\n    ██║██║░╚███║██████╔╝░░░██║░░░██║░░██║╚██████╔╝╚█████╔╝░░░██║░░░██║╚█████╔╝██║░╚███║██████╔╝\n    ╚═╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░░╚════╝░░░░╚═╝░░░╚═╝░╚════╝░╚═╝░░╚══╝╚═════╝░\n\n    Type "done" when finished\n    Type "more" to see more files\n    Paste a folder (and press enter) to toggle selection\n    Type "*" to select all files in the most recently printed table\n\nThen it will give you a prompt:\n\n    Paste a path:\n\nWherein you can copy and paste paths you want to move from the table and the program will keep track for you.\n\n    Paste a path: /mnt/d/75_MovieQueue/720p/s11/\n    26 selected paths: 162.1 GB ; future free space: 486.9 GB\n\nYou can also press the up arrow or paste it again to remove it from the list:\n\n    Paste a path: /mnt/d/75_MovieQueue/720p/s11/\n    25 selected paths: 159.9 GB ; future free space: 484.7 GB\n\nAfter you are done selecting folders you can press ctrl-d and it will save the list to a tmp file:\n\n    Paste a path: done\n\n        Folder list saved to /tmp/tmpa7x_75l8. You may want to use the following command to move files to an EMPTY folder target:\n\n            rsync -a --info=progress2 --no-inc-recursive --remove-source-files --files-from=/tmp/tmpa7x_75l8 -r --relative -vv --dry-run / jim:/free/real/estate/\n\n</details>\n\n<details><summary>lb bigdirs</summary>\n\nAlso, if you are just looking for folders which are candidates for curation (ie. I need space but don\'t want to buy a hard drive). The bigdirs subcommand was written for that purpose:\n\n    $ lb bigdirs fs/d.db\n\nYou may filter by folder depth (similar to QDirStat or WizTree)\n\n    $ lb bigdirs --depth=3 audio.db\n\nThere is also an flag to prioritize folders which have many files which have been deleted (for example you delete songs you don\'t like--now you can see who wrote those songs and delete all their other songs...)\n\n    $ lb bigdirs --sort-by-deleted audio.db\n\n</details>\n\n\n### Scatter your data across disks with [mergerfs](https://github.com/trapexit/mergerfs)\n\n<details><summary>If you use mergerfs, you\'ll likely be interested in this</summary>\n\n    library scatter -h\n    usage: library scatter [--limit LIMIT] [--policy POLICY] [--sort SORT] --srcmounts SRCMOUNTS database relative_paths ...\n\n    Balance size\n\n        $ library scatter -m /mnt/d1:/mnt/d2:/mnt/d3:/mnt/d4/:/mnt/d5:/mnt/d6:/mnt/d7 ~/lb/fs/scatter.db subfolder/of/mergerfs/mnt\n        Current path distribution:\n        ╒═════════╤══════════════╤══════════════╤═══════════════╤════════════════╤═════════════════╤════════════════╕\n        │ mount   │   file_count │ total_size   │ median_size   │ time_created   │ time_modified   │ time_scanned   │\n        ╞═════════╪══════════════╪══════════════╪═══════════════╪════════════════╪═════════════════╪════════════════╡\n        │ /mnt/d1 │        12793 │ 169.5 GB     │ 4.5 MB        │ Jan 27         │ Jul 19 2022     │ Jan 31         │\n        ├─────────┼──────────────┼──────────────┼───────────────┼────────────────┼─────────────────┼────────────────┤\n        │ /mnt/d2 │        13226 │ 177.9 GB     │ 4.7 MB        │ Jan 27         │ Jul 19 2022     │ Jan 31         │\n        ├─────────┼──────────────┼──────────────┼───────────────┼────────────────┼─────────────────┼────────────────┤\n        │ /mnt/d3 │            1 │ 717.6 kB     │ 717.6 kB      │ Jan 31         │ Jul 18 2022     │ yesterday      │\n        ├─────────┼──────────────┼──────────────┼───────────────┼────────────────┼─────────────────┼────────────────┤\n        │ /mnt/d4 │           82 │ 1.5 GB       │ 12.5 MB       │ Jan 31         │ Apr 22 2022     │ yesterday      │\n        ╘═════════╧══════════════╧══════════════╧═══════════════╧════════════════╧═════════════════╧════════════════╛\n\n        Simulated path distribution:\n        5845 files should be moved\n        20257 files should not be moved\n        ╒═════════╤══════════════╤══════════════╤═══════════════╤════════════════╤═════════════════╤════════════════╕\n        │ mount   │   file_count │ total_size   │ median_size   │ time_created   │ time_modified   │ time_scanned   │\n        ╞═════════╪══════════════╪══════════════╪═══════════════╪════════════════╪═════════════════╪════════════════╡\n        │ /mnt/d1 │         9989 │ 46.0 GB      │ 2.4 MB        │ Jan 27         │ Jul 19 2022     │ Jan 31         │\n        ├─────────┼──────────────┼──────────────┼───────────────┼────────────────┼─────────────────┼────────────────┤\n        │ /mnt/d2 │        10185 │ 46.0 GB      │ 2.4 MB        │ Jan 27         │ Jul 19 2022     │ Jan 31         │\n        ├─────────┼──────────────┼──────────────┼───────────────┼────────────────┼─────────────────┼────────────────┤\n        │ /mnt/d3 │         1186 │ 53.6 GB      │ 30.8 MB       │ Jan 27         │ Apr 07 2022     │ Jan 31         │\n        ├─────────┼──────────────┼──────────────┼───────────────┼────────────────┼─────────────────┼────────────────┤\n        │ /mnt/d4 │         1216 │ 49.5 GB      │ 29.5 MB       │ Jan 27         │ Apr 07 2022     │ Jan 31         │\n        ├─────────┼──────────────┼──────────────┼───────────────┼────────────────┼─────────────────┼────────────────┤\n        │ /mnt/d5 │         1146 │ 53.0 GB      │ 30.9 MB       │ Jan 27         │ Apr 07 2022     │ Jan 31         │\n        ├─────────┼──────────────┼──────────────┼───────────────┼────────────────┼─────────────────┼────────────────┤\n        │ /mnt/d6 │         1198 │ 48.8 GB      │ 30.6 MB       │ Jan 27         │ Apr 07 2022     │ Jan 31         │\n        ├─────────┼──────────────┼──────────────┼───────────────┼────────────────┼─────────────────┼────────────────┤\n        │ /mnt/d7 │         1182 │ 52.0 GB      │ 30.9 MB       │ Jan 27         │ Apr 07 2022     │ Jan 31         │\n        ╘═════════╧══════════════╧══════════════╧═══════════════╧════════════════╧═════════════════╧════════════════╛\n        ### Move 1182 files to /mnt/d7 with this command: ###\n        rsync -aE --xattrs --info=progress2 --remove-source-files --files-from=/tmp/tmpmr1628ij / /mnt/d7\n        ### Move 1198 files to /mnt/d6 with this command: ###\n        rsync -aE --xattrs --info=progress2 --remove-source-files --files-from=/tmp/tmp9yd75f6j / /mnt/d6\n        ### Move 1146 files to /mnt/d5 with this command: ###\n        rsync -aE --xattrs --info=progress2 --remove-source-files --files-from=/tmp/tmpfrj141jj / /mnt/d5\n        ### Move 1185 files to /mnt/d3 with this command: ###\n        rsync -aE --xattrs --info=progress2 --remove-source-files --files-from=/tmp/tmpqh2euc8n / /mnt/d3\n        ### Move 1134 files to /mnt/d4 with this command: ###\n        rsync -aE --xattrs --info=progress2 --remove-source-files --files-from=/tmp/tmphzb0gj92 / /mnt/d4\n\n    Balance device inodes for specific subfolder\n\n        $ library scatter -m /mnt/d1:/mnt/d2 ~/lb/fs/scatter.db subfolder --group count --sort \'size desc\'\n\n    Scatter the most recent 100 files\n\n        $ library scatter -m /mnt/d1:/mnt/d2 -l 100 -s \'time_modified desc\' ~/lb/fs/scatter.db /\n\n    Scatter without mountpoints (limited functionality; only good for balancing fs inodes)\n\n        $ library scatter scatter.db /test/{0,1,2,3,4,5,6,7,8,9}\n\n\n    positional arguments:\n    database\n    relative_paths        Paths to scatter, relative to the root of your mergerfs mount; any path substring is valid\n\n    options:\n    -h, --help            show this help message and exit\n    --limit LIMIT, -L LIMIT, -l LIMIT, -queue LIMIT, --queue LIMIT\n    --policy POLICY, -p POLICY\n    --group GROUP, -g GROUP\n    --sort SORT, -s SORT  Sort files before moving\n    --usage, -u           Show disk usage\n    --verbose, -v\n    --srcmounts SRCMOUNTS, -m SRCMOUNTS\n                            /mnt/d1:/mnt/d2\n\n</details>\n\n### Pipe to [mnamer](https://github.com/jkwill87/mnamer)\n\n<details><summary>Rename poorly named files</summary>\n\n    pip install mnamer\n    mnamer --movie-directory ~/d/70_Now_Watching/ --episode-directory ~/d/70_Now_Watching/ \\\n        --no-overwrite -b (library watch -p fd -s \'path : McCloud\')\n    library fsadd ~/d/70_Now_Watching/\n\n</details>\n\n### Wake up to your own music (via termux)\n\n    30 9 * * * lb listen ./audio.db\n\n### Wake up to your own music _only when you are not home_ (computer on local-only IP)\n\n    30 9 * * * timeout 0.4 nc -z 192.168.1.12 22 || lb listen --random\n\n### Wake up to your own music on your Chromecast speaker group _only when you are home_\n\n    30 9 * * * ssh 192.168.1.12 lb listen --random --play-in-order --cast --cast-to "Bedroom pair"\n\n### Pipe to [lowcharts](https://github.com/juan-leon/lowcharts)\n\n<details><summary>$ lb watch -p f -col time_created | lowcharts timehist -w 80</summary>\n\n    Matches: 445183.\n    Each ∎ represents a count of 1896\n    [2022-04-13 03:16:05] [151689] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-04-19 07:59:37] [ 16093] ∎∎∎∎∎∎∎∎\n    [2022-04-25 12:43:09] [ 12019] ∎∎∎∎∎∎\n    [2022-05-01 17:26:41] [ 48817] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-05-07 22:10:14] [ 36259] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-05-14 02:53:46] [  3942] ∎∎\n    [2022-05-20 07:37:18] [  2371] ∎\n    [2022-05-26 12:20:50] [   517]\n    [2022-06-01 17:04:23] [  4845] ∎∎\n    [2022-06-07 21:47:55] [  2340] ∎\n    [2022-06-14 02:31:27] [   563]\n    [2022-06-20 07:14:59] [ 13836] ∎∎∎∎∎∎∎\n    [2022-06-26 11:58:32] [  1905] ∎\n    [2022-07-02 16:42:04] [  1269]\n    [2022-07-08 21:25:36] [  3062] ∎\n    [2022-07-15 02:09:08] [  9192] ∎∎∎∎\n    [2022-07-21 06:52:41] [ 11955] ∎∎∎∎∎∎\n    [2022-07-27 11:36:13] [ 50938] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-08-02 16:19:45] [ 70973] ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎\n    [2022-08-08 21:03:17] [  2598] ∎\n\nBTW, for some cols like time_deleted you\'ll need to specify a where clause so they aren\'t filtered out:\n\n    $ lb watch -p f -col time_deleted -w time_deleted\'>\'0 | lowcharts timehist -w 80\n\n![video width](https://user-images.githubusercontent.com/7908073/184737808-b96fbe65-a1d9-43c2-b6b4-4bdfab592190.png)\n\n![fps](https://user-images.githubusercontent.com/7908073/184738438-ee566a4b-2da0-4e6d-a4b3-9bfca036aa2a.png)\n\n</details>\n\n### Pipe to rsync\n\n<details><summary>Copy or move files to your phone via syncthing</summary>\n\nI use rsync to move files instead of copy-on-write duplication because I want deletions to stick.\n\n    function mrmusic\n        rsync -a --remove-source-files --files-from=(\n            library lt ~/lb/audio.db -s /mnt/d/80_Now_Listening/ -p f \\\n            --moved /mnt/d/80_Now_Listening/ /mnt/d/ | psub\n        ) /mnt/d/80_Now_Listening/ /mnt/d/\n\n        rsync -a --remove-source-files --files-from=(\n            library lt ~/lb/audio.db -w play_count=0 -u random -L 1200 -p f \\\n            --moved /mnt/d/ /mnt/d/80_Now_Listening/ | psub\n        ) /mnt/d/ /mnt/d/80_Now_Listening/\n    end\n\n</details>\n\n### Backfill\n\n<details><summary>Backfill reddit databases with pushshift data</summary>\n\n[https://github.com/chapmanjacobd/reddit_mining/](https://github.com/chapmanjacobd/reddit_mining/)\n\n```fish\nfor reddit_db in ~/lb/reddit/*.db\n    set subreddits (sqlite-utils $reddit_db \'select path from playlists\' --tsv --no-headers | grep old.reddit.com | sed \'s|https://old.reddit.com/r/\\(.*\\)/|\\1|\' | sed \'s|https://old.reddit.com/user/\\(.*\\)/|u_\\1|\' | tr -d "\\r")\n\n    ~/github/xk/reddit_mining/links/\n    for subreddit in $subreddits\n        if not test -e "$subreddit.csv"\n            echo "octosql -o csv \\"select path,score,\'https://old.reddit.com/r/$subreddit/\' as playlist_path from `../reddit_links.parquet` where lower(playlist_path) = \'$subreddit\' order by score desc \\" > $subreddit.csv"\n        end\n    end | parallel -j8\n\n    for subreddit in $subreddits\n        sqlite-utils upsert --pk path --alter --csv --detect-types $reddit_db media $subreddit.csv\n    end\n\n    library tubeadd --safe -i $reddit_db --playlist-db media\nend\n```\n\n</details>\n\n### Datasette\n\nExplore `library` databases in your browser\n\n    pip install datasette\n    datasette tv.db\n\n\n',
    'author': 'Jacob Chapman',
    'author_email': '7908073+chapmanjacobd@users.noreply.github.com',
    'maintainer': 'None',
    'maintainer_email': 'None',
    'url': 'https://github.com/chapmanjacobd/library/',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'extras_require': extras_require,
    'entry_points': entry_points,
    'python_requires': '>=3.8,<4.0',
}


setup(**setup_kwargs)
