l3uddz / plex_autoscan

Script to assist sonarr/radarr with plex imports. Will only scan the folder that has been imported, instead of the whole library section.
GNU General Public License v3.0
396 stars 70 forks source link

Scan multiple Plex libraries that share the same media folder #144

Open Bod1985 opened 4 years ago

Bod1985 commented 4 years ago

Describe the problem I have a Plex library for 4K content and below, and a library for 1080p and below.

The 4K > library contains the folders /Media/Movies and /Media/Movies1080 The 1080 > library contains only the folder /Media/Movies1080

When Radarr adds a movie and requests Plex Autoscan to scan that Movie, only the 4K > library gets updated.

Describe any solutions you think might work As I understand it, Plex Autoscan determines the Library using Section ID's.

This could be defined by a boolean config option to check for additional sections during scan.

Additional context

Plex Sections

5: Films 1080p 1: Films 4K> 6: TV 1080p 2: TV 4K>

This shows in my log file where it states Using Section ID '1', ideally based on my below Plex sections, I would need it to also perform the scan for Section ID '5'. Example log with movie name redacted


 2020-03-28 17:55:55,632 -     INFO -  AUTOSCAN [140007010281216]: Using Section ID '1' for '/data/Movies1080/MovieName (0000)/MovieName (0000).mkv'
 2020-03-28 17:55:55,634 -     INFO -  AUTOSCAN [140007010281216]: Added '/data/Movies1080/MovieName (0000)/MovieName (0000).mkv' to Plex Autoscan database.
 2020-03-28 17:55:55,634 -     INFO -  AUTOSCAN [140007010281216]: Proceeding with scan...
 2020-03-28 17:55:55,635 -     INFO -      PLEX [140006978074368]: Scan request from Radarr for '/data/Movies1080/MovieName (0000)/MovieName (0000).mkv'.
 2020-03-28 17:55:55,636 -     INFO -      PLEX [140006978074368]: Sleeping for 180 seconds...
 2020-03-28 17:58:55,733 -     INFO -      PLEX [140006978074368]: File '/mnt/unionfs/Media/Movies1080/MovieName (0000)/MovieName (0000).mkv' exists on check 1 of 10.
 2020-03-28 17:58:55,734 -     INFO -      PLEX [140006978074368]: Scan request is now being processed...
 2020-03-28 17:58:55,897 -     INFO -      PLEX [140006978074368]: Plex is available for media scanning - (Server Account: 'email@email.co.uk')
 2020-03-28 17:58:55,897 -     INFO -      PLEX [140006978074368]: Running Plex Media Scanner for: /data/Movies1080/MovieName (0000)
 2020-03-28 17:58:59,534 -     INFO -      PLEX [140006978074368]: Finished scan!`
Bod1985 commented 4 years ago

Disclaimer: I am not a developer.

I had a go at implementing this and think I'm 90% of the way there. The code works but I think the autoscan database isn't being handled correctly as it fails to remove the entry following a scan (I think this is because it's already removed from the first scan).

I've never used GitHub fully, else I'd have gone through the proper motions to fork and commit changes that way (I've tried and failed so any direction is welcome).

For utils.py, I edited the get_plex_section function:

def get_plex_section(config, path):
    sections = []
    try:
        with sqlite3.connect(config['PLEX_DATABASE_PATH']) as conn:
            conn.row_factory = sqlite3.Row
            conn.text_factory = str
            with closing(conn.cursor()) as c:
                # check if file exists in plex
                logger.debug("Checking if root folder path '%s' matches Plex Library root path in the Plex DB.", path)
                section_data = c.execute("SELECT library_section_id,root_path FROM section_locations").fetchall()
                for section_id, root_path in section_data:
                    if path.startswith(root_path + os.sep):
                        logger.debug("Plex Library Section ID '%d' matching root folder '%s' was found in the Plex DB.",
                                     section_id, root_path)
                        sections.append(int(section_id))
                        #return int(section_id)
                if len(sections) >= 1:
                    return sections
                logger.error("Unable to map '%s' to a Section ID.", path)

    except Exception:
        logger.exception("Exception while trying to map '%s' to a Section ID in the Plex DB: ", path)
    return -1

For scan.py, I edited the start_scan function:

def start_scan(path, scan_for, scan_type, scan_title=None, scan_lookup_type=None, scan_lookup_id=None):
    sections = utils.get_plex_section(conf.configs, path)
    if sections <= 0:
        return False
    elif len(sections) <= 0:
        return False
    else:
        logger.info("Proceeding through section list.")

    for section in sections:
        logger.info("Using Section ID '%d' for '%s'", section, path)
        if conf.configs['SERVER_USE_SQLITE']:
            db_exists, db_file = db.exists_file_root_path(path,section)
            if not db_exists and db.add_item(path, scan_for, section, scan_type):
                logger.info("Added '%s' to Plex Autoscan database for section %d", path, section)
                logger.info("Proceeding with scan...")
            elif db_exists:
                logger.info(
                    "Already processing '%s' from same folder for section %d. Skip adding extra scan request to the queue.", db_file, section)
                resleep_paths.append(db_file)
                return False

        thread.start(plex.scan,
                    args=[conf.configs, scan_lock, path, scan_for, section, scan_type, resleep_paths, scan_title,
                        scan_lookup_type, scan_lookup_id])
    return True

And in db.py, I edited the exists_file_root_path function:

def exists_file_root_path(file_path, section):
    items = get_all_items()
    if '.' in file_path:
        dir_path = os.path.dirname(file_path)
    else:
        dir_path = file_path

    for item in items:
        if dir_path.lower() in item['scan_path'].lower() and section == item['scan_section']:
            return True, item['scan_path']
    return False, None
bakes82 commented 4 years ago

@crwblyth Have you done any more with this?

@l3uddz Where might the spot in the code be for this "as it fails to remove the entry following a scan (I think this is because it's already removed from the first scan)" If this code looks right and I can modify the remove db part, I can issue the PR.

Bod1985 commented 4 years ago

@crwblyth Have you done any more with this?

@l3uddz Where might the spot in the code be for this "as it fails to remove the entry following a scan (I think this is because it's already removed from the first scan)" If this code looks right and I can modify the remove db part, I can issue the PR.

I didn’t really carry on, however this code I’ve been using since March up until I switched to the other Autoscan two weeks ago.

bakes82 commented 4 years ago

@crwblyth Whats the other autoscan?

bakes82 commented 4 years ago

@crwblyth Found it https://github.com/Cloudbox/autoscan It "looks" like it supports multi libs out of the box based on the code, that true =) Any problems?

Bod1985 commented 4 years ago

@crwblyth Found it https://github.com/Cloudbox/autoscan It "looks" like it supports multi libs out of the box based on the code, that true =) Any problems?

Supports it out the box due to the nature of how the new Plex scanner works I think. Required Plex Beta last time I checked. Works fine for me. Still very much a work in progress though I believe.