Esempio n. 1
0
    def withStatus(self, status, types=None, with_doc=True):

        db = get_db()

        if types and not isinstance(types, (list, tuple)):
            types = [types]

        status = list(status if isinstance(status, (list,
                                                    tuple)) else [status])

        for s in status:
            for ms in db.get_many('media_status', s):
                if with_doc:
                    try:
                        doc = db.get('id', ms['_id'])

                        if types and doc.get('type') not in types:
                            continue

                        yield doc
                    except (RecordDeleted, RecordNotFound):
                        log.debug('Record not found, skipping: %s', ms['_id'])
                    except (ValueError, EOFError):
                        fire_event('database.delete_corrupted',
                                   ms.get('_id'),
                                   traceback_error=traceback.format_exc(0))
                else:
                    yield ms
Esempio n. 2
0
    def updateReleaseDate(self, media_id):
        """
        Update release_date (eta) info only

        @param media_id: document id
        @return: dict, with dates dvd, theater, bluray, expires
        """

        try:
            db = get_db()

            media = db.get('id', media_id)

            if not media.get('info'):
                media = self.update(media_id)
                dates = media.get('info', {}).get('release_date')
            else:
                dates = media.get('info').get('release_date')

            if dates and (dates.get('expires', 0) < time.time() or dates.get('expires', 0) > time.time() + (604800 * 4)) or not dates:
                dates = fireEvent('movie.info.release_date', identifier = getIdentifier(media), merge = True)
                media['info'].update({'release_date': dates})
                db.update(media)

            return dates
        except:
            log.error('Failed updating release dates: %s', traceback.format_exc())

        return {}
Esempio n. 3
0
    def delete(self, id = None, **kwargs):

        try:
            db = get_db()

            success = False
            message = ''
            try:
                c = db.get('id', id)
                db.delete(c)

                # Force defaults on all empty category movies
                self.removeFromMovie(id)

                success = True
            except:
                message = log.error('Failed deleting category: %s', traceback.format_exc())

            return {
                'success': success,
                'message': message
            }
        except:
            log.error('Failed: %s', traceback.format_exc())

        return {
            'success': False
        }
Esempio n. 4
0
    def get(self, media_id):

        db = get_db()

        imdb_id = getImdb(str(media_id))

        media = None
        if imdb_id:
            media = db.get('media', 'imdb-%s' % imdb_id, with_doc=True)['doc']
        else:
            media = db.get('id', media_id)

        if media:

            # Attach category
            try:
                media['category'] = db.get('id', media.get('category_id'))
            except:
                pass

            media['releases'] = fireEvent('release.for_media',
                                          media['_id'],
                                          single=True)

        return media
Esempio n. 5
0
    def manualDownload(self, id = None, **kwargs):

        db = get_db()

        try:
            release = db.get('id', id)
            item = release['info']
            movie = db.get('id', release['media_id'])

            fireEvent('notify.frontend', type = 'release.manual_download', data = True, message = 'Snatching "%s"' % item['name'])

            # Get matching provider
            provider = fireEvent('provider.belongs_to', item['url'], provider = item.get('provider'), single = True)

            if item.get('protocol') != 'torrent_magnet':
                item['download'] = provider.loginDownload if provider.urls.get('login') else provider.download

            success = self.download(data = item, media = movie, manual = True)

            if success:
                fireEvent('notify.frontend', type = 'release.manual_download', data = True, message = 'Successfully snatched "%s"' % item['name'])

            return {
                'success': success == True
            }

        except:
            log.error('Couldn\'t find release with id: %s: %s', (id, traceback.format_exc()))
            return {
                'success': False
            }
Esempio n. 6
0
    def clean(self, release_id):

        try:
            db = get_db()
            rel = db.get('id', release_id)
            raw_files = rel.get('files')

            if len(raw_files) == 0:
                self.delete(rel['_id'])
            else:

                files = {}
                for file_type in raw_files:

                    for release_file in raw_files.get(file_type, []):
                        if os.path.isfile(sp(release_file)):
                            if file_type not in files:
                                files[file_type] = []
                            files[file_type].append(release_file)

                rel['files'] = files
                db.update(rel)

            return True
        except:
            log.error('Failed: %s', traceback.format_exc())

        return False
Esempio n. 7
0
    def updateReleaseDate(self, media_id):
        """
        Update release_date (eta) info only

        @param media_id: document id
        @return: dict, with dates dvd, theater, bluray, expires
        """

        try:
            db = get_db()

            media = db.get('id', media_id)

            if not media.get('info'):
                media = self.update(media_id)
                dates = media.get('info', {}).get('release_date')
            else:
                dates = media.get('info').get('release_date')

            if dates and (dates.get('expires', 0) < time.time() or dates.get('expires', 0) > time.time() + (604800 * 4)) or not dates:
                dates = fireEvent('movie.info.release_date', identifier = getIdentifier(media), merge = True)
                media['info'].update({'release_date': dates})
                db.update(media)

            return dates
        except:
            log.error('Failed updating release dates: %s', traceback.format_exc())

        return {}
Esempio n. 8
0
    def forceDefaults(self):

        db = get_db()

        # Fill qualities and profiles if they are empty somehow..
        if db.count(db.all, "profile") == 0:

            if db.count(db.all, "quality") == 0:
                fireEvent("quality.fill", single=True)

            self.fill()

        # Get all active movies without profile
        try:
            medias = fireEvent("media.with_status", "active", single=True)

            profile_ids = [x.get("_id") for x in self.all()]
            default_id = profile_ids[0]

            for media in medias:
                if media.get("profile_id") not in profile_ids:
                    media["profile_id"] = default_id
                    db.update(media)
        except:
            log.error("Failed: %s", traceback.format_exc())
Esempio n. 9
0
    def get(self, media_id):

        try:
            db = get_db()

            imdb_id = getImdb(str(media_id))

            if imdb_id:
                media = db.get('media', 'imdb-%s' % imdb_id, with_doc = True)['doc']
            else:
                media = db.get('id', media_id)

            if media:

                # Attach category
                try: media['category'] = db.get('id', media.get('category_id'))
                except: pass

                media['releases'] = fireEvent('release.for_media', media['_id'], single = True)

            return media

        except (RecordNotFound, RecordDeleted):
            log.error('Media with id "%s" not found', media_id)
        except:
            raise
Esempio n. 10
0
    def notify(self, message = '', data = None, listener = None):
        if not data: data = {}

        try:
            db = get_db()

            data['notification_type'] = listener if listener else 'unknown'

            n = {
                '_t': 'notification',
                'time': int(time.time()),
                'message': toUnicode(message)
            }

            if data.get('sticky'):
                n['sticky'] = True
            if data.get('important'):
                n['important'] = True

            db.insert(n)

            self.frontend(type = listener, data = n)

            return True
        except:
            log.error('Failed notify: %s', traceback.format_exc())
Esempio n. 11
0
    def withStatus(self, status, types = None, with_doc = True):

        db = get_db()

        if types and not isinstance(types, (list, tuple)):
            types = [types]

        status = list(status if isinstance(status, (list, tuple)) else [status])

        for s in status:
            for ms in db.get_many('media_status', s):
                if with_doc:
                    try:
                        doc = db.get('id', ms['_id'])

                        if types and doc.get('type') not in types:
                            continue

                        yield doc
                    except (RecordDeleted, RecordNotFound):
                        log.debug('Record not found, skipping: %s', ms['_id'])
                    except (ValueError, EOFError):
                        fireEvent('database.delete_corrupted', ms.get('_id'), traceback_error = traceback.format_exc(0))
                else:
                    yield ms
Esempio n. 12
0
    def restatus(self, media_id):

        try:
            db = get_db()

            m = db.get('id', media_id)
            previous_status = m['status']

            log.debug('Changing status for %s', getTitle(m))
            if not m['profile_id']:
                m['status'] = 'done'
            else:
                move_to_wanted = True

                profile = db.get('id', m['profile_id'])
                media_releases = fireEvent('release.for_media', m['_id'], single = True)

                for q_identifier in profile['qualities']:
                    index = profile['qualities'].index(q_identifier)

                    for release in media_releases:
                        if q_identifier == release['quality'] and (release.get('status') == 'done' and profile['finish'][index]):
                            move_to_wanted = False

                m['status'] = 'active' if move_to_wanted else 'done'

            # Only update when status has changed
            if previous_status != m['status']:
                db.update(m)

            return True
        except:
            log.error('Failed restatus: %s', traceback.format_exc())
Esempio n. 13
0
    def get(self, media_id):

        try:
            db = get_db()

            imdb_id = getImdb(str(media_id))

            if imdb_id:
                media = db.get("media", "imdb-%s" % imdb_id, with_doc=True)["doc"]
            else:
                media = db.get("id", media_id)

            if media:

                # Attach category
                try:
                    media["category"] = db.get("id", media.get("category_id"))
                except:
                    pass

                media["releases"] = fireEvent("release.for_media", media["_id"], single=True)

            return media

        except (RecordNotFound, RecordDeleted):
            log.error('Media with id "%s" not found', media_id)
        except:
            raise
Esempio n. 14
0
    def notify(self, message='', data=None, listener=None):
        if not data: data = {}

        try:
            db = get_db()

            data['notification_type'] = listener if listener else 'unknown'

            n = {
                '_t': 'notification',
                'time': int(time.time()),
                'message': toUnicode(message)
            }

            if data.get('sticky'):
                n['sticky'] = True
            if data.get('important'):
                n['important'] = True

            db.insert(n)

            self.frontend(type=listener, data=n)

            return True
        except:
            log.error('Failed notify: %s', traceback.format_exc())
Esempio n. 15
0
    def notify(self, message='', data=None, listener=None):
        if not data: data = {}

        n = {
            '_t': 'notification',
            'time': int(time.time()),
        }

        try:
            db = get_db()

            n['message'] = to_unicode(message)

            if data.get('sticky'):
                n['sticky'] = True
            if data.get('important'):
                n['important'] = True

            db.insert(n)

            self.frontend(type=listener, data=n)

            return True
        except:
            log.error('Failed notify "%s": %s', (n, traceback.format_exc()))
Esempio n. 16
0
    def delete(self, id = None, **kwargs):

        try:
            db = get_db()

            success = False
            message = ''
            try:
                c = db.get('id', id)
                db.delete(c)

                # Force defaults on all empty category movies
                self.removeFromMovie(id)

                success = True
            except:
                message = log.error('Failed deleting category: %s', traceback.format_exc())

            return {
                'success': success,
                'message': message
            }
        except:
            log.error('Failed: %s', traceback.format_exc())

        return {
            'success': False
        }
Esempio n. 17
0
    def cleanDone(self):
        log.debug('Removing releases from dashboard')

        now = time.time()
        week = 604800

        db = get_db()

        # Get (and remove) parentless releases
        releases = db.all('release', with_doc=True)
        media_exist = []
        for release in releases:
            if release.get('key') in media_exist:
                continue

            try:
                db.get('id', release.get('key'))
                media_exist.append(release.get('key'))

                try:
                    if release['doc'].get('status') == 'ignore':
                        release['doc']['status'] = 'ignored'
                        db.update(release['doc'])
                except:
                    log.error('Failed fixing mis-status tag: %s',
                              traceback.format_exc())
            except RecordDeleted:
                db.delete(release['doc'])
                log.debug('Deleted orphaned release: %s', release['doc'])
            except:
                log.debug('Failed cleaning up orphaned releases: %s',
                          traceback.format_exc())

        del media_exist

        # get movies last_edit more than a week ago
        medias = fireEvent('media.with_status', ['done', 'active'],
                           single=True)

        for media in medias:
            if media.get('last_edit', 0) > (now - week):
                continue

            for rel in fireEvent('release.for_media',
                                 media['_id'],
                                 single=True):

                # Remove all available releases
                if rel['status'] in ['available']:
                    self.delete(rel['_id'])

                # Set all snatched and downloaded releases to ignored to make sure they are ignored when re-adding the media
                elif rel['status'] in ['snatched', 'downloaded']:
                    self.updateStatus(rel['_id'], status='ignored')

            if 'recent' in media.get('tags', []):
                fireEvent('media.untag',
                          media.get('_id'),
                          'recent',
                          single=True)
Esempio n. 18
0
    def get(self, media_id):

        try:
            db = get_db()

            imdb_id = get_imdb(str(media_id))

            if imdb_id:
                media = db.get('media', 'imdb-%s' % imdb_id,
                               with_doc=True)['doc']
            else:
                media = db.get('id', media_id)

            if media:

                # Attach category
                try:
                    media['category'] = db.get('id', media.get('category_id'))
                except:
                    pass

                media['releases'] = fire_event('release.for_media',
                                               media['_id'],
                                               single=True)

            return media

        except (RecordNotFound, RecordDeleted):
            log.error('Media with id "%s" not found', media_id)
        except:
            raise
Esempio n. 19
0
    def updateSuggestionCache(self, ignore_imdb = None, limit = 6, ignored = None, seen = None):

        # Combine with previous suggestion_cache
        cached_suggestion = self.getCache('suggestion_cached') or []
        new_suggestions = []
        ignored = [] if not ignored else ignored
        seen = [] if not seen else seen

        if ignore_imdb:
            suggested_imdbs = []
            for cs in cached_suggestion:
                if cs.get('imdb') != ignore_imdb and cs.get('imdb') not in suggested_imdbs:
                    suggested_imdbs.append(cs.get('imdb'))
                    new_suggestions.append(cs)

        # Get new results and add them
        if len(new_suggestions) - 1 < limit:
            db = get_db()
            active_movies = fireEvent('media.with_status', ['active', 'done'], single = True)
            movies = [getIdentifier(x) for x in active_movies]
            movies.extend(seen)

            ignored.extend([x.get('imdb') for x in cached_suggestion])
            suggestions = fireEvent('movie.suggest', movies = movies, ignore = removeDuplicate(ignored), single = True)

            if suggestions:
                new_suggestions.extend(suggestions)

        self.setCache('suggestion_cached', new_suggestions, timeout = 3024000)

        return new_suggestions
Esempio n. 20
0
    def forMedia(self, media_id):

        db = get_db()
        raw_releases = db.get_many('release', media_id)

        releases = []
        for r in raw_releases:
            try:
                doc = db.get('id', r.get('_id'))
                releases.append(doc)
            except RecordDeleted:
                pass
            except (ValueError, EOFError):
                fire_event('database.delete_corrupted',
                           r.get('_id'),
                           traceback_error=traceback.format_exc(0))

        releases = sorted(releases,
                          key=lambda k: k.get('info', {}).get('score', 0),
                          reverse=True)

        # Sort based on preferred search method
        download_preference = self.conf('preferred_method', section='searcher')
        if download_preference != 'both':
            releases = sorted(
                releases,
                key=lambda k: k.get('info', {}).get('protocol', '')[:3],
                reverse=(download_preference == 'torrent'))

        return releases or []
Esempio n. 21
0
    def updateStatus(self, release_id, status = None):
        if not status: return False

        try:
            db = get_db()

            rel = db.get('id', release_id)
            if rel and rel.get('status') != status:

                release_name = None
                if rel.get('files'):
                    for file_type in rel.get('files', {}):
                        if file_type == 'movie':
                            for release_file in rel['files'][file_type]:
                                release_name = os.path.basename(release_file)
                                break

                if not release_name and rel.get('info'):
                    release_name = rel['info'].get('name')

                #update status in Db
                log.debug('Marking release %s as %s', (release_name, status))
                rel['status'] = status
                rel['last_edit'] = int(time.time())

                db.update(rel)

                #Update all movie info as there is no release update function
                fireEvent('notify.frontend', type = 'release.update_status', data = rel)

            return True
        except:
            log.error('Failed: %s', traceback.format_exc())

        return False
Esempio n. 22
0
    def updateReleaseDate(self, media_id):
        """
        Update release_date (eta) info only

        @param media_id: document id
        @return: dict, with dates dvd, theater, bluray, expires
        """

        try:
            db = get_db()

            media = db.get("id", media_id)

            if not media.get("info"):
                media = self.update(media_id)
                dates = media.get("info", {}).get("release_date")
            else:
                dates = media.get("info").get("release_date")

            if (
                dates
                and (dates.get("expires", 0) < time.time() or dates.get("expires", 0) > time.time() + (604800 * 4))
                or not dates
            ):
                dates = fireEvent("movie.info.release_date", identifier=getIdentifier(media), merge=True)
                media["info"].update({"release_date": dates})
                db.update(media)

            return dates
        except:
            log.error("Failed updating release dates: %s", traceback.format_exc())

        return {}
Esempio n. 23
0
    def fill(self):

        try:
            db = get_db()

            order = 0
            for q in self.qualities:

                db.insert({
                    '_t': 'quality',
                    'order': order,
                    'identifier': q.get('identifier'),
                    'size_min': tryInt(q.get('size')[0]),
                    'size_max': tryInt(q.get('size')[1]),
                })

                log.info('Creating profile: %s', q.get('label'))
                db.insert({
                    '_t': 'profile',
                    'order': order + 20,  # Make sure it goes behind other profiles
                    'core': True,
                    'qualities': [q.get('identifier')],
                    'label': toUnicode(q.get('label')),
                    'finish': [True],
                    'wait_for': [0],
                })

                order += 1

            return True
        except:
            log.error('Failed: %s', traceback.format_exc())

        return False
Esempio n. 24
0
    def createFromSearch(self, search_results, media, quality):

        try:
            db = get_db()

            found_releases = []

            is_3d = False
            try: is_3d = quality['custom']['3d']
            except: pass

            for rel in search_results:

                rel_identifier = md5(rel['url'])
                found_releases.append(rel_identifier)

                release = {
                    '_t': 'release',
                    'identifier': rel_identifier,
                    'media_id': media.get('_id'),
                    'quality': quality.get('identifier'),
                    'is_3d': is_3d,
                    'status': rel.get('status', 'available'),
                    'last_edit': int(time.time()),
                    'info': {}
                }

                # Add downloader info if provided
                try:
                    release['download_info'] = rel['download_info']
                    del rel['download_info']
                except:
                    pass

                try:
                    rls = db.get('release_identifier', rel_identifier, with_doc = True)['doc']
                except:
                    rls = db.insert(release)
                    rls.update(release)

                # Update info, but filter out functions
                for info in rel:
                    try:
                        if not isinstance(rel[info], (str, unicode, int, long, float)):
                            continue

                        rls['info'][info] = toUnicode(rel[info]) if isinstance(rel[info], (str, unicode)) else rel[info]
                    except:
                        log.debug('Couldn\'t add %s to ReleaseInfo: %s', (info, traceback.format_exc()))

                db.update(rls)

                # Update release in search_results
                rel['status'] = rls.get('status')

            return found_releases
        except:
            log.error('Failed: %s', traceback.format_exc())

        return []
Esempio n. 25
0
    def delete(self, id = None, **kwargs):

        try:
            db = get_db()

            success = False
            message = ''

            try:
                p = db.get('id', id)
                db.delete(p)

                # Force defaults on all empty profile movies
                self.forceDefaults()

                success = True
            except Exception as e:
                message = log.error('Failed deleting Profile: %s', e)

            return {
                'success': success,
                'message': message
            }
        except:
            log.error('Failed: %s', traceback.format_exc())

        return {
            'success': False
        }
Esempio n. 26
0
    def forceDefaults(self):

        db = get_db()

        # Fill qualities and profiles if they are empty somehow..
        if db.count(db.all, 'profile') == 0:

            if db.count(db.all, 'quality') == 0:
                fireEvent('quality.fill', single = True)

            self.fill()

        # Get all active movies without profile
        try:
            medias = fireEvent('media.with_status', 'active', single = True)

            profile_ids = [x.get('_id') for x in self.all()]
            default_id = profile_ids[0]

            for media in medias:
                if media.get('profile_id') not in profile_ids:
                    media['profile_id'] = default_id
                    db.update(media)
        except:
            log.error('Failed: %s', traceback.format_exc())
Esempio n. 27
0
    def updateStatus(self, release_id, status=None):
        if not status: return False

        try:
            db = get_db()

            rel = db.get('id', release_id)
            if rel and rel.get('status') != status:

                release_name = rel['info'].get('name')
                if rel.get('files'):
                    for file_type in rel.get('files', {}):
                        if file_type == 'movie':
                            for release_file in rel['files'][file_type]:
                                release_name = os.path.basename(release_file)
                                break

                #update status in Db
                log.debug('Marking release %s as %s', (release_name, status))
                rel['status'] = status
                rel['last_edit'] = int(time.time())

                db.update(rel)

                #Update all movie info as there is no release update function
                fireEvent('notify.frontend',
                          type='release.update_status',
                          data=rel)

            return True
        except:
            log.error('Failed: %s', traceback.format_exc())

        return False
Esempio n. 28
0
    def forceDefaults(self):

        db = get_db()

        # Fill qualities and profiles if they are empty somehow..
        if db.count(db.all, 'profile') == 0:

            if db.count(db.all, 'quality') == 0:
                fireEvent('quality.fill', single=True)

            self.fill()

        # Get all active movies without profile
        try:
            medias = fireEvent('media.with_status', 'active', single=True)

            profile_ids = [x.get('_id') for x in self.all()]
            default_id = profile_ids[0]

            for media in medias:
                if media.get('profile_id') not in profile_ids:
                    media['profile_id'] = default_id
                    db.update(media)
        except:
            log.error('Failed: %s', traceback.format_exc())
Esempio n. 29
0
    def forMedia(self, media_id):

        db = get_db()
        raw_releases = db.get_many('release', media_id)

        releases = []
        for r in raw_releases:
            try:
                doc = db.get('id', r.get('_id'))
                releases.append(doc)
            except RecordDeleted:
                pass

        releases = sorted(releases,
                          key=lambda k: k.get('info', {}).get('score', 0),
                          reverse=True)

        # Sort based on preferred search method
        download_preference = self.conf('preferred_method', section='searcher')
        if download_preference != 'both':
            releases = sorted(
                releases,
                key=lambda k: k.get('info', {}).get('protocol', '')[:3],
                reverse=(download_preference == 'torrent'))

        return releases
Esempio n. 30
0
    def getDB(self):

        if not self.db:
            from couchpotato import get_db
            self.db = get_db()

        return self.db
Esempio n. 31
0
    def treeView(self, media_id, **kwargs):
        db = get_db()
        media = db.get('id', media_id)

        return {
            'result': fireEvent('library.tree', media, single = True)
        }
Esempio n. 32
0
    def manualDownload(self, id = None, **kwargs):

        db = get_db()

        try:
            release = db.get('id', id)
            item = release['info']
            movie = db.get('id', release['media_id'])

            fireEvent('notify.frontend', type = 'release.manual_download', data = True, message = 'Snatching "%s"' % item['name'])

            # Get matching provider
            provider = fireEvent('provider.belongs_to', item['url'], provider = item.get('provider'), single = True)

            if item.get('protocol') != 'torrent_magnet':
                item['download'] = provider.loginDownload if provider.urls.get('login') else provider.download

            success = self.download(data = item, media = movie, manual = True)

            if success:
                fireEvent('notify.frontend', type = 'release.manual_download', data = True, message = 'Successfully snatched "%s"' % item['name'])

            return {
                'success': success == True
            }

        except:
            log.error('Couldn\'t find release with id: %s: %s', (id, traceback.format_exc()))
            return {
                'success': False
            }
Esempio n. 33
0
    def clean(self, release_id):

        try:
            db = get_db()
            rel = db.get('id', release_id)
            raw_files = rel.get('files')

            if len(raw_files) == 0:
                self.delete(rel['_id'])
            else:

                files = {}
                for file_type in raw_files:

                    for release_file in raw_files.get(file_type, []):
                        if os.path.isfile(sp(release_file)):
                            if file_type not in files:
                                files[file_type] = []
                            files[file_type].append(release_file)

                rel['files'] = files
                db.update(rel)

            return True
        except:
            log.error('Failed: %s', traceback.format_exc())

        return False
Esempio n. 34
0
    def save(self, **kwargs):

        try:
            db = get_db()

            category = {
                '_t': 'category',
                'order': kwargs.get('order', 999),
                'label': toUnicode(kwargs.get('label', '')),
                'ignored': toUnicode(kwargs.get('ignored', '')),
                'preferred': toUnicode(kwargs.get('preferred', '')),
                'required': toUnicode(kwargs.get('required', '')),
                'destination': toUnicode(kwargs.get('destination', '')),
            }

            try:
                c = db.get('id', kwargs.get('id'))
                category['order'] = c.get('order', category['order'])
                c.update(category)

                db.update(c)
            except:
                c = db.insert(category)
                c.update(category)

            return {'success': True, 'category': c}
        except:
            log.error('Failed: %s', traceback.format_exc())

        return {'success': False, 'category': None}
Esempio n. 35
0
    def delete(self, media_id, delete_from=None):

        try:
            db = get_db()

            media = db.get('id', media_id)
            if media:
                deleted = False

                media_releases = fireEvent('release.for_media',
                                           media['_id'],
                                           single=True)

                if delete_from == 'all':
                    # Delete connected releases
                    for release in media_releases:
                        db.delete(release)

                    db.delete(media)
                    deleted = True
                else:

                    total_releases = len(media_releases)
                    total_deleted = 0
                    new_media_status = None

                    for release in media_releases:
                        if delete_from in ['wanted', 'snatched', 'late']:
                            if release.get('status') != 'done':
                                db.delete(release)
                                total_deleted += 1
                            new_media_status = 'done'
                        elif delete_from == 'manage':
                            if release.get('status') == 'done':
                                db.delete(release)
                                total_deleted += 1

                    if (total_releases == total_deleted
                            and media['status'] != 'active') or (
                                delete_from == 'wanted' and media['status']
                                == 'active') or (not new_media_status
                                                 and delete_from == 'late'):
                        db.delete(media)
                        deleted = True
                    elif new_media_status:
                        media['status'] = new_media_status
                        db.update(media)
                    else:
                        fireEvent('media.restatus',
                                  media.get('_id'),
                                  single=True)

                if deleted:
                    fireEvent('notify.frontend',
                              type='media.deleted',
                              data=media)
        except:
            log.error('Failed deleting media: %s', traceback.format_exc())

        return True
Esempio n. 36
0
    def updateReleaseDate(self, media_id):
        """
        Update release_date (eta) info only

        @param media_id: document id
        @return: dict, with dates dvd, theater, bluray, expires
        """

        try:
            db = get_db()

            media = db.get('id', media_id)

            if not media.get('info'):
                media = self.update(media_id)
                dates = media.get('info', {}).get('release_date')
            else:
                dates = media.get('info').get('release_date')

            if dates and (dates.get('expires', 0) < time.time()
                          or dates.get('expires', 0) > time.time() +
                          (604800 * 4)) or not dates:
                dates = fireEvent('movie.info.release_date',
                                  identifier=getIdentifier(media),
                                  merge=True)
                media['info'].update({'release_date': dates})
                db.update(media)

            # Workaround for a bug in https://api.couchpota.to/eta/<imdbid>
            # CP uses this API to retrieve movie release dates. The API always returns
            # "{dvd":0,"theater":0,"bluray":false,"expires":<some-bogus-time-about-11-days-in-the future>}
            # Because of this, CP will never auto-snatch movies because it can't establish a valid ETA
            # This workaround tries to extract a valid release-date from the 'released' field of the media info
            # which seems to be valid but seems to vary in format.
            # If it fails to convert the date, it uses the expires value.
            if dates['theater'] == 0:
                released = media.get('info').get('released')
                formats = ['%d %b %Y', '%Y-%m-%d']
                for format in formats:
                    try:
                        dates['theater'] = int(
                            time.mktime(
                                datetime.strptime(released,
                                                  format).timetuple()))
                        log.info('Extracted release date for "%s" from "%s"',
                                 (media['title'], released))
                    except ValueError:
                        continue
                if dates['theater'] == 0:
                    dates['theater'] = dates['expires']
                    log.info('Using expired date as release date for "%s": %d',
                             (media['title'], dates['expires']))

            return dates
        except:
            log.error('Failed updating release dates: %s',
                      traceback.format_exc())

        return {}
Esempio n. 37
0
    def restatus(self, media_id, tag_recent=True, allowed_restatus=None):

        try:
            db = get_db()

            m = db.get('id', media_id)
            previous_status = m['status']

            log.debug('Changing status for %s', get_title(m))
            if not m['profile_id']:
                m['status'] = 'done'
            else:
                m['status'] = 'active'

                try:
                    profile = db.get('id', m['profile_id'])
                    media_releases = fire_event('release.for_media',
                                                m['_id'],
                                                single=True)
                    done_releases = [
                        release for release in media_releases
                        if release.get('status') == 'done'
                    ]

                    if done_releases:

                        # Check if we are finished with the media
                        for release in done_releases:
                            if fire_event('quality.isfinish', {
                                    'identifier': release['quality'],
                                    'is_3d': release.get('is_3d', False)
                            },
                                          profile,
                                          timedelta(seconds=time.time() -
                                                    release['last_edit']).days,
                                          single=True):
                                m['status'] = 'done'
                                break

                    elif previous_status == 'done':
                        m['status'] = 'done'

                except RecordNotFound:
                    log.debug('Failed restatus, keeping previous: %s',
                              traceback.format_exc())
                    m['status'] = previous_status

            # Only update when status has changed
            if previous_status != m['status'] and (
                    not allowed_restatus or m['status'] in allowed_restatus):
                db.update(m)

                # Tag media as recent
                if tag_recent:
                    self.tag(media_id, 'recent', update_edited=True)

            return m['status']
        except:
            log.error('Failed restatus: %s', traceback.format_exc())
Esempio n. 38
0
    def fill(self):

        try:
            db = get_db()

            profiles = [{
                'label': 'Best',
                'qualities': ['720p', '1080p', 'brrip', 'dvdrip']
            }, {
                'label': 'HD',
                'qualities': ['720p', '1080p']
            }, {
                'label': 'SD',
                'qualities': ['dvdrip', 'dvdr']
            }, {
                'label': 'Prefer 3D HD',
                'qualities': ['1080p', '720p', '720p', '1080p'],
                '3d': [True, True]
            }, {
                'label': '3D HD',
                'qualities': ['1080p', '720p'],
                '3d': [True, True]
            }, {
                'label': 'UHD 4K',
                'qualities': ['720p', '1080p', '2160p']
            }]

            # Create default quality profile
            order = 0
            for profile in profiles:
                log.info('Creating default profile: %s', profile.get('label'))

                pro = {
                    '_t': 'profile',
                    'label': toUnicode(profile.get('label')),
                    'order': order,
                    'qualities': profile.get('qualities'),
                    'minimum_score': 1,
                    'finish': [],
                    'wait_for': [],
                    'stop_after': [],
                    '3d': []
                }

                threed = profile.get('3d', [])
                for q in profile.get('qualities'):
                    pro['finish'].append(True)
                    pro['wait_for'].append(0)
                    pro['stop_after'].append(0)
                    pro['3d'].append(threed.pop() if threed else False)

                db.insert(pro)
                order += 1

            return True
        except:
            log.error('Failed: %s', traceback.format_exc())

        return False
Esempio n. 39
0
    def fill(self):

        try:
            db = get_db()

            profiles = [{
                'label': 'Best',
                'qualities': ['720p', '1080p', 'brrip', 'dvdrip']
            }, {
                'label': 'HD',
                'qualities': ['720p', '1080p']
            }, {
                'label': 'SD',
                'qualities': ['dvdrip', 'dvdr']
            }, {
                'label': 'Prefer 3D HD',
                'qualities': ['1080p', '720p', '720p', '1080p'],
                '3d': [True, True]
            }, {
                'label': '3D HD',
                'qualities': ['1080p', '720p'],
                '3d': [True, True]
            }, {
                'label': 'UHD 4K',
                'qualities': ['720p', '1080p', '2160p']
            }]

            # Create default quality profile
            order = 0
            for profile in profiles:
                log.info('Creating default profile: %s', profile.get('label'))

                pro = {
                    '_t': 'profile',
                    'label': toUnicode(profile.get('label')),
                    'order': order,
                    'qualities': profile.get('qualities'),
                    'minimum_score': 1,
                    'finish': [],
                    'wait_for': [],
                    'stop_after': [],
                    '3d': []
                }

                threed = profile.get('3d', [])
                for q in profile.get('qualities'):
                    pro['finish'].append(True)
                    pro['wait_for'].append(0)
                    pro['stop_after'].append(0)
                    pro['3d'].append(threed.pop() if threed else False)

                db.insert(pro)
                order += 1

            return True
        except:
            log.error('Failed: %s', traceback.format_exc())

        return False
Esempio n. 40
0
 def clean(self):
     try:
         db = get_db()
         for n in db.all('notification', with_doc = True):
             if n['doc'].get('time', 0) <= (int(time.time()) - 2419200):
                 db.delete(n['doc'])
     except:
         log.error('Failed cleaning notification: %s', traceback.format_exc())
Esempio n. 41
0
 def clean(self):
     try:
         db = get_db()
         for n in db.all("notification", with_doc=True):
             if n["doc"].get("time", 0) <= (int(time.time()) - 2419200):
                 db.delete(n["doc"])
     except:
         log.error("Failed cleaning notification: %s", traceback.format_exc())
Esempio n. 42
0
    def root(self, media):
        db = get_db()
        cur = media

        while cur and cur.get('parent_id'):
            cur = db.get('id', cur['parent_id'])

        return cur
Esempio n. 43
0
    def update(self, media_id = None, identifier = None, default_title = None, extended = False):
        """
        Update movie information inside media['doc']['info']

        @param media_id: document id
        @param default_title: default title, if empty, use first one or existing one
        @param extended: update with extended info (parses more info, actors, images from some info providers)
        @return: dict, with media
        """

        if self.shuttingDown():
            return

        lock_key = 'media.get.%s' % media_id if media_id else identifier
        self.acquireLock(lock_key)

        media = {}
        try:
            db = get_db()

            if media_id:
                media = db.get('id', media_id)
            else:
                media = db.get('media', 'imdb-%s' % identifier, with_doc = True)['doc']

            info = fireEvent('movie.info', merge = True, extended = extended, identifier = getIdentifier(media))

            # Don't need those here
            try: del info['in_wanted']
            except: pass
            try: del info['in_library']
            except: pass

            if not info or len(info) == 0:
                log.error('Could not update, no movie info to work with: %s', identifier)
                return False

            # Update basic info
            media['info'] = info

            titles = info.get('titles', [])
            log.debug('Adding titles: %s', titles)

            # Define default title
            if default_title or media.get('title') == 'UNKNOWN' or len(media.get('title', '')) == 0:
                media['title'] = self.getDefaultTitle(info, default_title)

            # Files
            image_urls = info.get('images', [])

            self.getPoster(media, image_urls)

            db.update(media)
        except:
            log.error('Failed update media: %s', traceback.format_exc())

        self.releaseLock(lock_key)
        return media
Esempio n. 44
0
    def update(self, media_id = None, identifier = None, default_title = None, extended = False):
        """
        Update movie information inside media['doc']['info']

        @param media_id: document id
        @param default_title: default title, if empty, use first one or existing one
        @param extended: update with extended info (parses more info, actors, images from some info providers)
        @return: dict, with media
        """

        if self.shuttingDown():
            return

        lock_key = 'media.get.%s' % media_id if media_id else identifier
        self.acquireLock(lock_key)

        media = {}
        try:
            db = get_db()

            if media_id:
                media = db.get('id', media_id)
            else:
                media = db.get('media', 'imdb-%s' % identifier, with_doc = True)['doc']

            info = fire_event('movie.info', merge=True, extended=extended, identifier=get_identifier(media))

            # Don't need those here
            try: del info['in_wanted']
            except: pass
            try: del info['in_library']
            except: pass

            if not info or len(info) == 0:
                log.error('Could not update, no movie info to work with: %s', identifier)
                return False

            # Update basic info
            media['info'] = info

            titles = info.get('titles', [])
            log.debug('Adding titles: %s', titles)

            # Define default title
            if default_title or media.get('title') == 'UNKNOWN' or len(media.get('title', '')) == 0:
                media['title'] = self.getDefaultTitle(info, default_title)

            # Files
            image_urls = info.get('images', [])

            self.getPoster(media, image_urls)

            db.update(media)
        except:
            log.error('Failed update media: %s', traceback.format_exc())

        self.releaseLock(lock_key)
        return media
Esempio n. 45
0
    def availableChars(self, types=None, status=None, release_status=None):

        db = get_db()

        # Make a list from string
        if status and not isinstance(status, (list, tuple)):
            status = [status]
        if release_status and not isinstance(release_status, (list, tuple)):
            release_status = [release_status]
        if types and not isinstance(types, (list, tuple)):
            types = [types]

        # query media ids
        if types:
            all_media_ids = set()
            for media_type in types:
                all_media_ids = all_media_ids.union(
                    set([
                        x['_id']
                        for x in db.get_many('media_by_type', media_type)
                    ]))
        else:
            all_media_ids = set([x['_id'] for x in db.all('media')])

        media_ids = all_media_ids
        filter_by = {}

        # Filter on movie status
        if status and len(status) > 0:
            filter_by['media_status'] = set()
            for media_status in fire_event('media.with_status',
                                           status,
                                           with_doc=False,
                                           single=True):
                filter_by['media_status'].add(media_status.get('_id'))

        # Filter on release status
        if release_status and len(release_status) > 0:
            filter_by['release_status'] = set()
            for release_status in fire_event('release.with_status',
                                             release_status,
                                             with_doc=False,
                                             single=True):
                filter_by['release_status'].add(release_status.get('media_id'))

        # Filter by combining ids
        for x in filter_by:
            media_ids = [n for n in media_ids if n in filter_by[x]]

        chars = set()
        for x in db.all('media_startswith'):
            if x['_id'] in media_ids:
                chars.add(x['key'])

            if len(chars) == 27:
                break

        return list(chars)
Esempio n. 46
0
        def onComplete():
            try:
                db = get_db()
                media = fireEvent('media.get', media_id, single = True)
                event_name = '%s.searcher.single' % media.get('type')

                fireEventAsync(event_name, media, on_complete = self.createNotifyFront(media_id))
            except:
                log.error('Failed creating onComplete: %s', traceback.format_exc())
Esempio n. 47
0
    def delete(self, media_id, delete_from = None):

        try:
            db = get_db()

            media = db.get('id', media_id)
            if media:
                deleted = False

                media_releases = fireEvent('release.for_media', media['_id'], single = True)

                if delete_from == 'all':
                    # Delete connected releases
                    for release in media_releases:
                        db.delete(release)

                    db.delete(media)
                    deleted = True
                else:

                    total_releases = len(media_releases)
                    total_deleted = 0
                    new_media_status = None

                    for release in media_releases:
                        if delete_from in ['wanted', 'snatched', 'late']:
                            if release.get('status') != 'done':
                                db.delete(release)
                                total_deleted += 1
                            new_media_status = 'done'
                        elif delete_from == 'manage':
                            if release.get('status') == 'done' or media.get('status') == 'done':
                                db.delete(release)
                                total_deleted += 1

                    if (total_releases == total_deleted) or (total_releases == 0 and not new_media_status) or (not new_media_status and delete_from == 'late'):
                        db.delete(media)
                        deleted = True
                    elif new_media_status:
                        media['status'] = new_media_status

                        # Remove profile (no use for in manage)
                        if new_media_status == 'done':
                            media['profile_id'] = None
                        
                        db.update(media)

                        fireEvent('media.untag', media['_id'], 'recent', single = True)
                    else:
                        fireEvent('media.restatus', media.get('_id'), single = True)

                if deleted:
                    fireEvent('notify.frontend', type = 'media.deleted', data = media)
        except:
            log.error('Failed deleting media: %s', traceback.format_exc())

        return True
Esempio n. 48
0
    def withStatus(self, status, with_doc = True):

        db = get_db()

        status = list(status if isinstance(status, (list, tuple)) else [status])

        for s in status:
            for ms in db.get_many('media_status', s, with_doc = with_doc):
                yield ms['doc'] if with_doc else ms
Esempio n. 49
0
    def automationView(self, force_update=False, **kwargs):

        db = get_db()

        charts = fire_event('automation.get_chart_list', merge=True)
        ignored = split_string(Env.prop('charts_ignore', default=''))

        # Create a list the movie/list.js can use
        for chart in charts:
            medias = []
            for media in chart.get('list', []):

                identifier = media.get('imdb')
                if identifier in ignored:
                    continue

                try:
                    try:
                        in_library = db.get('media', 'imdb-%s' % identifier)
                        if in_library:
                            continue
                    except RecordNotFound:
                        pass
                except:
                    pass

                # Cache poster
                posters = media.get('images', {}).get('poster', [])
                poster = [x for x in posters if 'tmdb' in x]
                posters = poster if len(poster) > 0 else posters

                cached_poster = fire_event(
                    'file.download', url=posters[0],
                    single=True) if len(posters) > 0 else False
                files = {
                    'image_poster': [cached_poster]
                } if cached_poster else {}

                medias.append({
                    'status': 'chart',
                    'title': get_title(media),
                    'type': 'movie',
                    'info': media,
                    'files': files,
                    'identifiers': {
                        'imdb': identifier
                    }
                })

            chart['list'] = medias

        return {
            'success': True,
            'count': len(charts),
            'charts': charts,
            'ignored': ignored,
        }
Esempio n. 50
0
    def delete(self, media_id, delete_from=None):

        try:
            db = get_db()

            media = db.get("id", media_id)
            if media:
                deleted = False

                media_releases = fireEvent("release.for_media", media["_id"], single=True)

                if delete_from == "all":
                    # Delete connected releases
                    for release in media_releases:
                        db.delete(release)

                    db.delete(media)
                    deleted = True
                else:

                    total_releases = len(media_releases)
                    total_deleted = 0
                    new_media_status = None

                    for release in media_releases:
                        if delete_from in ["wanted", "snatched", "late"]:
                            if release.get("status") != "done":
                                db.delete(release)
                                total_deleted += 1
                            new_media_status = "done"
                        elif delete_from == "manage":
                            if release.get("status") == "done" or media.get("status") == "done":
                                db.delete(release)
                                total_deleted += 1

                    if (
                        (total_releases == total_deleted)
                        or (total_releases == 0 and not new_media_status)
                        or (not new_media_status and delete_from == "late")
                    ):
                        db.delete(media)
                        deleted = True
                    elif new_media_status:
                        media["status"] = new_media_status
                        db.update(media)

                        fireEvent("media.untag", media["_id"], "recent", single=True)
                    else:
                        fireEvent("media.restatus", media.get("_id"), single=True)

                if deleted:
                    fireEvent("notify.frontend", type="media.deleted", data=media)
        except:
            log.error("Failed deleting media: %s", traceback.format_exc())

        return True
Esempio n. 51
0
    def single(self, identifier = ''):

        db = get_db()
        quality_dict = {}

        quality = db.get('quality', identifier, with_doc = True)['doc']
        if quality:
            quality_dict = mergeDicts(self.getQuality(quality['identifier']), quality)

        return quality_dict
Esempio n. 52
0
    def databaseSetup(self):
        from couchpotato import get_db

        db = get_db()

        try:
            db.add_index(PropertyIndex(db.path, 'property'))
        except:
            self.log.debug('Index for properties already exists')
            db.edit_index(PropertyIndex(db.path, 'property'))
Esempio n. 53
0
    def withStatus(self, status, with_doc=True):

        db = get_db()

        status = list(status if isinstance(status, (list,
                                                    tuple)) else [status])

        for s in status:
            for ms in db.get_many('release_status', s, with_doc=with_doc):
                yield ms['doc'] if with_doc else ms
Esempio n. 54
0
    def cleanupFaults(self):
        medias = fireEvent('media.with_status', 'ignored', single = True) or []

        db = get_db()
        for media in medias:
            try:
                media['status'] = 'done'
                db.update(media)
            except:
                pass