Browse Source

Start of "bootyd" experiment.

experimental/bootyd
treyzania 5 years ago
parent
commit
10de202d15
16 changed files with 204 additions and 90 deletions
  1. 3
    0
      .gitignore
  2. 19
    0
      Cargo.lock
  3. 6
    0
      Cargo.toml
  4. 15
    45
      README.md
  5. 16
    0
      bootyd/Cargo.toml
  6. 3
    0
      bootyd/cli.rs
  7. 7
    0
      bootyd/daemon.rs
  8. 10
    0
      core/Cargo.toml
  9. 78
    0
      core/ident.rs
  10. 7
    0
      core/lib.rs
  11. 11
    0
      identity/filebot/Cargo.toml
  12. 9
    0
      identity/filebot/lib.rs
  13. 11
    0
      identity/parley/Cargo.toml
  14. 9
    0
      identity/parley/lib.rs
  15. 0
    5
      localconfig-plunder
  16. 0
    40
      plunder.sh

+ 3
- 0
.gitignore View File

@@ -1 +1,4 @@
/target/
fakeplex/
*~
\#*\#

+ 19
- 0
Cargo.lock View File

@@ -0,0 +1,19 @@
[[package]]
name = "booty-core"
version = "0.1.0"

[[package]]
name = "booty-id-filebot"
version = "0.1.0"
dependencies = [
"booty-core 0.1.0",
]

[[package]]
name = "bootyd"
version = "0.1.0"
dependencies = [
"booty-core 0.1.0",
"booty-id-filebot 0.1.0",
]


+ 6
- 0
Cargo.toml View File

@@ -0,0 +1,6 @@
[workspace]
members = [
"bootyd",
"core",
"identity/filebot"
]

+ 15
- 45
README.md View File

@@ -1,57 +1,27 @@
# Bootybot

This is a script for doing things with Plex that make it easier to do other
things. I'm not going to say what things those are, but we all know.
The new verion of Bootybot is a daemon for managing all of your tasks on the
high seas.

## Dependencies
**Note:** This is highly experimental and very early in development.

* Filebot
## Components

* `unrar`
### Server

* Python 3
The `bootyd` program runs as a system service or in a container and should have
access to all of the files you expect it to be running on. You can talk to it
over a unix socket.

## Configuration
### CLI

The default config location is `~/.config/bootybot.conf`. Below is an example.
The `bootyctl` program is how you primarily interact with the running `bootyd`
server to trigger content ingests and perform other administration tasks.

```json
{
"outdir": "/mnt/xvol1/plexdata",
"extractdir": "/tmp/bootybot_extract",
"simpleaction": "copy",
"overrides": [
{
"name": "The Simpsons",
"pattern": "The\\.Simpsons\\..*"
}
]
}
```
### Identity Engines

The `outdir` property has the `{plex}` formatter from Filebot appended to it,
so you should not have to worry about handling different media classes (TV,
Movies, etc.).
These are things for actually identifying content.

The `extractdir` is where we extract data from RAR archives into. It usually
ends up being emptied after we finish processing, as we move data out of here
after extraction.
* `filebot` - Traditional and more versatile, but not libre

The `simpleaction` property is passed to Filebot when processing simple,
non-archived media files. I use `copy` because of how I want to handle dealing
with data *after* it's been loaded into Plex, but you might want to use `move`,
`hardlink`, or `keeplink` depending on what you're situation is like.

The `overrides` section is used to enforce that TV shows have their names
properly auto-detected, as occasionally Filebot trips up and misses it. If none
of the entries match the file then we just hope that Filebot figures it out on
its own. Note that the regexes must match the *entire* filename. So it's a
good idea to put a `.*` at the end to make sure it matches every file format
and from any "distributor".

## Usage

Once you've configured it, you can just run `booty.py` in the directory of the
"media" you're trying to prepare.

You can set the `BOOTYCFG` envvar to override the config location.
* `parley` - Bootybot's native identification engine; faster, libre, but highly experimental

+ 16
- 0
bootyd/Cargo.toml View File

@@ -0,0 +1,16 @@
[package]
name = "bootyd"
version = "0.1.0"
authors = ["treyzania <treyzania@gmail.com>"]

[[bin]]
name = "bootyd"
path = "daemon.rs"

[[bin]]
name = "bootyctl"
path = "cli.rs"

[dependencies]
booty-core = { path = "../core" }
booty-id-filebot = { path = "../identity/filebot" }

+ 3
- 0
bootyd/cli.rs View File

@@ -0,0 +1,3 @@
fn main() {
println!("also not implemented yet");
}

+ 7
- 0
bootyd/daemon.rs View File

@@ -0,0 +1,7 @@
extern crate booty_core;

extern crate booty_id_filebot;

fn main() {
println!("not yet implemented");
}

+ 10
- 0
core/Cargo.toml View File

@@ -0,0 +1,10 @@
[package]
name = "booty-core"
version = "0.1.0"
authors = ["treyzania <treyzania@gmail.com>"]

[lib]
name = "booty_core"
path = "lib.rs"

[dependencies]

+ 78
- 0
core/ident.rs View File

@@ -0,0 +1,78 @@

/// Identifier for a particular movie or episode. Doesn't handle different
/// releases of movies or anything like that.
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub enum MediaId {
Movie {
/// Name of the movie.
name: String,

/// Year released, to disambiguate.
year: String
},

/// Episode of some TV show or anime.
Episode {
/// Name of the show.
name: String,
/// Some shows aren't released as seasons, often anime.
season: Option<u32>,

/// Episode with the season, or overall of no seasons.
episode: u32,

/// What kind of TV is it?
cat: TvCategory
}
}

#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum TvCategory {
/// Regular TV, typically western but mostly everything else.
Tv,

/// Anime, which often is categorized seperately.
Anime
}

/// Hint to provide to matching engine about content identity.
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub enum IdHint {
/// Name of thing, like "Inception", or "Game of Thrones".
Name(String),

/// Year released, usually for movies, like "2010".
Year(String),

/// Season of a show, like "S06".
Season(String),

/// Episode number, usually passed *with* a season, like "E11".
Episode(String)
}

/// Some kind of error that can happen when trying to identify a match.
#[derive(Debug)]
enum MatchError {
/// No matches found.
NoMatches,

/// Muliple matches for the file, should handle accordingly.
Multiple(Vec<MediaId>),

/// Error with the network.
NetworkError,

/// File permissions error.
PermissionsError,
/// In case they're using the wrong version of filebot.
NonlibreError,

}

// TODO Decide what we want to be able to do with an engine.
trait MatchinEngine {
fn identify(&self, path: &Path) -> Result<MediaId, MatchError>;
}

+ 7
- 0
core/lib.rs View File

@@ -0,0 +1,7 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}

+ 11
- 0
identity/filebot/Cargo.toml View File

@@ -0,0 +1,11 @@
[package]
name = "booty-id-filebot"
version = "0.1.0"
authors = ["treyzania <treyzania@gmail.com>"]

[lib]
name = "booty_id_filebot"
path = "lib.rs"

[dependencies]
booty-core = { path = "../../core" }

+ 9
- 0
identity/filebot/lib.rs View File

@@ -0,0 +1,9 @@
extern crate booty_core;

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}

+ 11
- 0
identity/parley/Cargo.toml View File

@@ -0,0 +1,11 @@
[package]
name = "booty-id-parley"
version = "0.1.0"
authors = ["treyzania <treyzania@gmail.com>"]

[lib]
name = "booty_id_parley"
path = "lib.rs"

[dependencies]
booty-core = { path = "../../core" }

+ 9
- 0
identity/parley/lib.rs View File

@@ -0,0 +1,9 @@
extern crate booty_core;

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}

+ 0
- 5
localconfig-plunder View File

@@ -1,5 +0,0 @@
ssh_opts=
ssh_prop=localhost
remote_rx_dir=rx
remote_mv_dir=rename


+ 0
- 40
plunder.sh View File

@@ -1,40 +0,0 @@
#!/bin/bash

MAIN_CONFIG="~/.config/bootybot/plunder.conf"
if [ -f localconfig ]; then
source localconfig-plunder
elif [ -f "$MAIN_CONFIG" ]; then
source $MAIN_CONFIG
else
echo 'error: no valid config found'
exit 1
fi

# This is from the Deluge Execute plugin.
tid=$1
tname=$2
tpath=$3

########

troot="$tpath/$tid"
rxpath="$remote_rx_dir/$tid"
mvpath="$remote_mv_dir/$tid"

function remote_exec () {
ssh $ssh_opts $ssh_prop $@
}

# Setup.
remote_exec mkdir -p $remote_rx_dir
remote_exec mkdir -p $remote_mv_dir

# Actual transfer.
remote_exec mkdir "$txpath"
scp -r $troot $ssh_prop:"$remote_rx_dir"

# Cleanup. This should be very fast.
remote_exec mv "$rxpath" "$mvpath"

# TODO Automaticially invoke (& fork) the rename script?


Loading…
Cancel
Save