Example #1
0
    def save_video(self) -> Union[None, str]:
        """save the Video instance to the database

        Return:
            None: success
            str: test mode message
        """

        if self._mode == 'test':
            return 'Data cannot be saved in test mode'

        dct = self.__dict__
        doc = {}

        # pop the private modifier of the attribute name before saving
        for k, v in dct.items():
            if k == '_video_id':
                doc['_id'] = v
            elif k == '_processed':
                doc['Processed'] = v
            else:
                dk = k.lstrip('_')
                doc[dk] = v

        COLLECTION.replace_one({'_id': self._video_id}, doc)
        logger.info('%s updated', self._video_id)
        return None
Example #2
0
    def get_video(self) -> None:
        """ Download video and write output to folder """
        self.create_path()

        output_folder = self.get_path()['path']
        COLLECTION.update_one({'_id': self.video_id},
                              {'$set': {
                                  'path': output_folder
                              }})

        y = YoutubeDl(output_folder=output_folder, mode=self.mode)
        ydl = y.ydl
        """
        Update the processing attribute to True whilst
        the video is being downloaded so that other
        processes don't attempt to download the video
        whilst it's in progress. Finally update the
        processed Flag to true and processing Flag to
        False
        """
        try:
            with ydl:
                self.vid.processing = True
                info_dict = ydl.extract_info(self.video_id)
                ydl.process_info(info_dict)
                self.vid.processing = False
                self.vid.processed = True
                self.vid.file_path = output_folder
                self.vid.save_video()
        except (DownloadError, SameFileError) as e:
            logger.error(e)
            logger.info('failed to download video %s', self.video_id)
 def setUpClass(cls):
     # update query to file objects with different field states
     query = COLLECTION.find_one()
     query['_id'] = 'testing'
     COLLECTION.insert_one(query)
     copy = COLLECTION.find_one({'_id': 'testing'})
     cls.videoObj = VideoSearch.query_result_to_video(copy)
    def write_nfo(self) -> None:
        """ Create an nfo file and write to path"""

        i = COLLECTION.find_one({'_id': self.video_id}, {
            '_id': True,
            'uploader': True,
            'title': True,
            'description': True,
            'upload_date': True
        })

        try:
            with open(os.path.join(APP_PATH, 'template.nfo'), 'r') as fl:
                template = Template(fl.read())
        except FileNotFoundError as e:
            logger.error(e)

        out_template = template.substitute(unique_id=i['_id'],
                                           studio=i['uploader'],
                                           title=i['title'],
                                           plot=i['description'],
                                           date_prem=i['upload_date'])
        path = os.path.join(self.get_path()['path'], 'tvshow.nfo')
        logger.info('writing nfo to path %s', path)
        with open(path, 'w') as fl:
            fl.write(out_template)
Example #5
0
    def delete_video(self, check: bool = False) -> Union[Tuple, str]:
        """Remove the current object from the database
        along with any files or folders

        Args:
            check (bool): a value to be explicitly set
            in order for the video to be deleted

        Returns:
           tuple: (int: 0, str: '') - the document was not found
           tuple: (int: 1, str: '') - the document was found and deleted
            but had not path key
           tuple: (int: 2, str: '') - the document and path were found
            both were deleted
           str: check did not pass
        """

        if self._mode == 'test':
            return 'Data cannot be deleted in test mode'

        if not check:
            return ''

        result = COLLECTION.find_one({'_id': self.video_id}, {
            '_id': True,
            'path': True
        })

        if not result:
            res = (0, '')
        elif 'path' not in result.keys():
            COLLECTION.delete_one({'_id': self.video_id})
            res = (1, '')
            logger.info('video_id %s deleted - no folder found', self.video_id)
        else:
            COLLECTION.delete_one({'_id': self.video_id})
            path: str = result['path']
            try:
                shutil.rmtree(os.path.split(path)[0], ignore_errors=True)
            except FileNotFoundError as e:
                logger.error(e)
            res = (2, path)
            logger.info('video_id %s deleted - folder %s deleted',
                        self.video_id, path)

        return res
 def get_thumbnail(self) -> None:
     # TODO fix path to use same as video_downloader
     """Download thumbnail to path
     """
     url = COLLECTION.find_one({'_id': self.video_id},
                               {'thumbnail': True})['thumbnail']
     data = requests.get(url, stream=True)
     image_data = Image.open(io.BytesIO(data.content))
     path = self.get_path()['path']
     logger.info('writing thumbnail to path %s', path)
     image_data.save(os.path.join(path, 'thumbnail.jpg'), 'jpeg')
Example #7
0
def add_queue(video_id: str, tags: list = None) -> bool:
    """If the video_id does not exist, insert
    an entry into the database from the information
    provided by get_video_info

    Args:
        video_id (str): The id of a youtube video
        tags (list): A list of tags

    Returns:
        True: item was added
        False: exception occurred

    Raises:
        TypeError: invalid video_id type
    """
    ret = False
    vid_info = None

    if tags is None:
        tags = ['undefined']
    if not isinstance(video_id, str):
        raise TypeError(f'{video_id} should be str not {type(video_id)}')

    if check_db(video_id) is True:
        logger.info('video_id %s already exists in database', video_id)
        ret = False
    else:
        vid_info = get_video_info(video_id, tags)

    if vid_info is not None:
        COLLECTION.insert_one(get_video_info(video_id, tags))
        logger.info('%s successfully inserted', video_id)
        ret = True

    return ret
Example #8
0
    def get_next_unprocessed(mode: str = '') -> Union[None, Video]:
        """Find the next unprocessed video

        Args:
            mode (str): mode flag to pass to Video

        Returns:
            Video: A Video instance
            None: no value found
        """
        res = COLLECTION.find_one({'Processed': False})

        if res:
            ret = VideoSearch.query_result_to_video(res, mode)
        else:
            ret = None

        return ret
Example #9
0
    def exact_find_video(**kwarg: str) -> Union[Video, None]:
        """ match a value exactly

        Args:
            kwarg (dict): kv corresponding to value in db

        Return:
            Video: an instance of Video
            None: no value found

        """

        search = COLLECTION.find_one(kwarg)
        if search:
            ret = VideoSearch.query_result_to_video(search)
        else:
            ret = None

        return ret
Example #10
0
    def get_path(self) -> dict:
        """ Build a path from the VIDEO_DIR, tags and title

        Returns:
            dict: {path: True || False} if path does or doesn't exist

        Raises:
            TypeError: supplied tags not type str or list
        """

        tags: list = COLLECTION.find_one({'_id': self.video_id},
                                         {'tags': True})['tags']

        sub_dir = '/'.join(tags)

        path: str = os.path.join(VIDEO_DIR, sub_dir, self.video_folder_name())
        if os.path.exists(path):
            result = {'path': path, 'exists': True}
        else:
            result = {'path': path, 'exists': False}

        return result
Example #11
0
def check_db(video_id: str) -> bool:
    """Query the database and assert if the value exists.

    Args:
        video_id (str): The id of a youtube video

    Returns:
        False: if video does not exist
        True: if video does exist

    Raises:
        TypeError: invalid video_id type
    """

    if not isinstance(video_id, str):
        raise TypeError(f'{video_id} should be str not {type(video_id)}')

    result = [i['_id'] for i in COLLECTION.find({'_id': video_id})]

    if not result:
        ret = False
    else:
        ret = True
    return ret
Example #12
0
#!/usr/bin/env python3
# pylint: disable=all
from app.database import COLLECTION

videos = [(i['title'], i['_id']) for i in COLLECTION.find({}, {
    'title': True,
    '_id': True
})]

for i in videos:
    print(i[1] + '~$' + i[0])
 def tearDownClass(cls):
     COLLECTION.delete_many({'_id': 'testing'})