Python isodate.parse_duration() Examples

The following are 26 code examples of isodate.parse_duration(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module isodate , or try the search function .
Example #1
Source File: scrape.py    From scrape-schema-recipe with Apache License 2.0 6 votes vote down vote up
def _pythonize_objects(scrapings: List[Dict], python_objects: Union[bool,
                       List, Tuple]) -> List[Dict]:

    if python_objects is False:
        # this really should not be happening
        return scrapings

    # this should work, mypy gives error, this isn't bulletproof code
    if python_objects is True or datetime.timedelta in python_objects:  # type: ignore
        # convert ISO 8601 date times into timedelta
        scrapings = _convert_properties_scrape(scrapings, DURATION_PROPERTIES,
                                               isodate.parse_duration)

    if python_objects is True or _have_matching_items((datetime.date, datetime.datetime), python_objects):
        # convert ISO 8601 date times into datetimes.datetime objects
        scrapings = _convert_properties_scrape(scrapings, DATETIME_PROPERTIES,
                                               _parse_determine_date_datetime)

    return scrapings 
Example #2
Source File: utils.py    From python3-saml with MIT License 6 votes vote down vote up
def parse_duration(duration, timestamp=None):
        """
        Interprets a ISO8601 duration value relative to a given timestamp.

        :param duration: The duration, as a string.
        :type: string

        :param timestamp: The unix timestamp we should apply the duration to.
                          Optional, default to the current time.
        :type: string

        :return: The new timestamp, after the duration is applied.
        :rtype: int
        """
        assert isinstance(duration, compat.str_type)
        assert timestamp is None or isinstance(timestamp, int)

        timedelta = duration_parser(duration)
        if timestamp is None:
            data = datetime.utcnow() + timedelta
        else:
            data = datetime.utcfromtimestamp(timestamp) + timedelta
        return calendar.timegm(data.utctimetuple()) 
Example #3
Source File: bandcamp.py    From beets-bandcamp with GNU General Public License v2.0 6 votes vote down vote up
def _parse_album_track(self, track_html):
        """Returns a TrackInfo derived from the html describing a track in a
        bandcamp album page.
        """
        track_num = track_html['rel'].split('=')[1]
        track_num = int(track_num)

        title_html = track_html.find(attrs={'class': 'title-col'})
        title = title_html.find(attrs={'itemprop': 'name'}).text.strip()
        artist = None
        if self.config['split_artist_title']:
            artist, title = self._split_artist_title(title)
        track_url = title_html.find(attrs={'itemprop': 'url'})
        if track_url is None:
            raise BandcampException('No track url (id) for track {0} - {1}'.format(track_num, title))
        track_id = track_url['href']
        try:
            duration = title_html.find('meta', attrs={'itemprop': 'duration'})['content']
            duration = duration.replace('P', 'PT')
            track_length = isodate.parse_duration(duration).total_seconds()
        except TypeError:
            track_length = None

        return TrackInfo(title, track_id, index=track_num, length=track_length, artist=artist) 
Example #4
Source File: 3dda56f1c4c6_migrate_num_period_compare_and_period_.py    From incubator-superset with Apache License 2.0 6 votes vote down vote up
def compute_time_compare(granularity, periods):
    if not granularity:
        return None
    # convert old db_engine_spec granularity to ISO duration
    if granularity in db_engine_specs_map:
        granularity = db_engine_specs_map[granularity]

    try:
        obj = isodate.parse_duration(granularity) * periods
    except isodate.isoerror.ISO8601Error:
        # if parse_human_timedelta can parse it, return it directly
        delta = "{0} {1}{2}".format(periods, granularity, "s" if periods > 1 else "")
        obj = parse_human_timedelta(delta)
        if obj:
            return delta
        raise Exception("Unable to parse: {0}".format(granularity))

    if isinstance(obj, isodate.duration.Duration):
        return isodate_duration_to_string(obj)
    elif isinstance(obj, datetime.timedelta):
        return timedelta_to_string(obj) 
Example #5
Source File: test_serialization.py    From msrest-for-python with MIT License 6 votes vote down vote up
def test_attr_duration(self):
        """
        Test serializing a duration
        """
        test_obj = self.TestObj()
        test_obj.attr_f = timedelta(days=1)

        message = self.s._serialize(test_obj)
        self.assertEqual("P1D", message["AttrF"])

        test_obj = self.TestObj()
        test_obj.attr_f = isodate.parse_duration("P3Y6M4DT12H30M5S")

        message = self.s.body({
            "attr_f": isodate.parse_duration("P3Y6M4DT12H30M5S")},
            'TestObj')
        self.assertEqual("P3Y6M4DT12H30M5S", message["AttrF"]) 
Example #6
Source File: serialization.py    From msrest-for-python with MIT License 6 votes vote down vote up
def deserialize_duration(attr):
        """Deserialize ISO-8601 formatted string into TimeDelta object.

        :param str attr: response string to be deserialized.
        :rtype: TimeDelta
        :raises: DeserializationError if string format invalid.
        """
        if isinstance(attr, ET.Element):
            attr = attr.text
        try:
            duration = isodate.parse_duration(attr)
        except(ValueError, OverflowError, AttributeError) as err:
            msg = "Cannot deserialize duration object."
            raise_with_traceback(DeserializationError, msg, err)
        else:
            return duration 
Example #7
Source File: pleblist.py    From pajbot with MIT License 5 votes vote down vote up
def create_pleblist_song_info(youtube_id):
        import isodate
        from apiclient.errors import HttpError

        if PleblistManager.youtube is None:
            log.warning("youtube was not initialized")
            return False

        try:
            video_response = (
                PleblistManager.youtube.videos().list(id=str(youtube_id), part="snippet,contentDetails").execute()
            )
        except HttpError as e:
            log.exception("Youtube HTTPError")
            log.info(e.content)
            log.info(e.resp)
            log.info(e.uri)
            return False
        except:
            log.exception("uncaught exception in videos().list()")
            return False

        if not video_response.get("items", []):
            log.warning(f"Got no valid responses for {youtube_id}")
            return False

        video = video_response["items"][0]

        title = video["snippet"]["title"]
        duration = int(isodate.parse_duration(video["contentDetails"]["duration"]).total_seconds())
        default_thumbnail = video["snippet"]["thumbnails"]["default"]["url"]

        return PleblistSongInfo(youtube_id, title, duration, default_thumbnail) 
Example #8
Source File: custom.py    From azure-cli-extensions with MIT License 5 votes vote down vote up
def execute_query(cmd, client, application, analytics_query, start_time=None, end_time=None, offset='1h', resource_group_name=None):
    """Executes a query against the provided Application Insights application."""
    from .vendored_sdks.applicationinsights.models import QueryBody
    targets = get_query_targets(cmd.cli_ctx, application, resource_group_name)
    if not isinstance(offset, datetime.timedelta):
        offset = isodate.parse_duration(offset)
    try:
        return client.query.execute(targets[0], QueryBody(query=analytics_query, timespan=get_timespan(cmd.cli_ctx, start_time, end_time, offset), applications=targets[1:]))
    except ErrorResponseException as ex:
        if "PathNotFoundError" in ex.message:
            raise ValueError("The Application Insight is not found. Please check the app id again.")
        raise ex 
Example #9
Source File: youtube.py    From CloudBot with GNU General Public License v3.0 5 votes vote down vote up
def youtime(text):
    """youtime <query> -- Gets the total run time of the first YouTube search result for <query>."""
    if not dev_key:
        return "This command requires a Google Developers Console API key."

    json = requests.get(search_api_url, params={"q": text, "key": dev_key, "type": "video"}).json()

    if json.get('error'):
        if json['error']['code'] == 403:
            return err_no_api
        else:
            return 'Error performing search.'

    if json['pageInfo']['totalResults'] == 0:
        return 'No results found.'

    video_id = json['items'][0]['id']['videoId']
    json = requests.get(api_url.format(video_id, dev_key)).json()

    if json.get('error'):
        return
    data = json['items']
    snippet = data[0]['snippet']
    content_details = data[0]['contentDetails']
    statistics = data[0]['statistics']

    if not content_details.get('duration'):
        return

    length = isodate.parse_duration(content_details['duration'])
    l_sec = int(length.total_seconds())
    views = int(statistics['viewCount'])
    total = int(l_sec * views)

    length_text = timeformat.format_time(l_sec, simple=True)
    total_text = timeformat.format_time(total, accuracy=8)

    return 'The video \x02{}\x02 has a length of {} and has been viewed {:,} times for ' \
           'a total run time of {}!'.format(snippet['title'], length_text, views,
                                            total_text) 
Example #10
Source File: api.py    From linkedevents with MIT License 5 votes vote down vote up
def to_internal_value(self, data):
        if data:
            value = parse_duration(data)
            return (
                value.days * 24 * 3600 * 1000000 +
                value.seconds * 1000 +
                value.microseconds / 1000
            )
        else:
            return 0 
Example #11
Source File: rule.py    From k8s-snapshots with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def parse_deltas(
        delta_string: str
) -> List[Union[timedelta, isodate.Duration]]:
    """q§Parse the given string into a list of ``timedelta`` instances.
    """
    if delta_string is None:
        raise DeltasParseError(
            f'Delta string is None',
        )

    deltas = []
    for item in delta_string.split(' '):
        item = item.strip()
        if not item:
            continue
        try:
            deltas.append(isodate.parse_duration(item))
        except ValueError as exc:
            raise DeltasParseError(
                f'Could not parse duration: {item!r}',
                error=exc,
                item=item,
                deltas=deltas,
                delta_string=delta_string,
            ) from exc

    if deltas and len(deltas) < 2:
        raise DeltasParseError(
            'At least two deltas are required',
            deltas=deltas,
            delta_string=delta_string,
        )

    return deltas 
Example #12
Source File: extended_json.py    From datapackage-pipelines with MIT License 5 votes vote down vote up
def object_hook(cls, obj):
        if 'type{decimal}' in obj:
            try:
                return decimal.Decimal(obj['type{decimal}'])
            except decimal.InvalidOperation:
                pass
        if 'type{time}' in obj:
            try:
                return datetime.datetime \
                    .strptime(obj["type{time}"], TIME_FORMAT) \
                    .time()
            except ValueError:
                pass
        if 'type{datetime}' in obj:
            try:
                return datetime.datetime \
                    .strptime(obj["type{datetime}"], DATETIME_FORMAT)
            except ValueError:
                pass
        if 'type{date}' in obj:
            try:
                return datetime.datetime \
                    .strptime(obj["type{date}"], DATE_FORMAT) \
                    .date()
            except ValueError:
                pass
        if 'type{duration}' in obj:
            try:
                return isodate.parse_duration(obj["type{duration}"])
            except ValueError:
                pass
        if 'type{set}' in obj:
            try:
                return set(obj['type{set}'])
            except ValueError:
                pass

        return obj 
Example #13
Source File: duration.py    From tableschema-py with MIT License 5 votes vote down vote up
def cast_duration(format, value, **options):
    if not isinstance(value, (isodate.Duration, datetime.timedelta)):
        if not isinstance(value, six.string_types):
            return ERROR
        try:
            value = isodate.parse_duration(value)
        except Exception:
            return ERROR
    return value 
Example #14
Source File: dash_manifest.py    From streamlink with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def duration(duration):
        return parse_duration(duration) 
Example #15
Source File: serialization.py    From msrest-for-python with MIT License 5 votes vote down vote up
def serialize_duration(attr, **kwargs):
        """Serialize TimeDelta object into ISO-8601 formatted string.

        :param TimeDelta attr: Object to be serialized.
        :rtype: str
        """
        if isinstance(attr, str):
            attr = isodate.parse_duration(attr)
        return isodate.duration_isoformat(attr) 
Example #16
Source File: util.py    From exchangelib with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def xml_text_to_value(value, value_type):
    # We can't handle bytes in this function because str == bytes on Python2
    from .ewsdatetime import EWSDateTime
    return {
        bool: lambda v: True if v == 'true' else False if v == 'false' else None,
        int: int,
        Decimal: Decimal,
        datetime.timedelta: isodate.parse_duration,
        EWSDateTime: EWSDateTime.from_string,
        str: lambda v: v
    }[value_type](value) 
Example #17
Source File: youtube.py    From CloudBot with GNU General Public License v3.0 5 votes vote down vote up
def youtime(text: str, reply) -> str:
    """<query> - Gets the total run time of the first YouTube search result for <query>."""
    parts = ["statistics", "contentDetails", "snippet"]
    try:
        video_id = get_video_id(text)
        request = get_video(video_id, parts)
        raise_api_errors(request)
    except NoResultsError as e:
        return e.message
    except APIError as e:
        reply(e.message)
        raise

    json = request.json()

    data = json["items"]
    item = data[0]
    snippet = item["snippet"]
    content_details = item["contentDetails"]
    statistics = item["statistics"]

    duration = content_details.get("duration")
    if not duration:
        return "Missing duration in API response"

    length = isodate.parse_duration(duration)
    l_sec = int(length.total_seconds())
    views = int(statistics["viewCount"])
    total = int(l_sec * views)

    length_text = timeformat.format_time(l_sec, simple=True)
    total_text = timeformat.format_time(total, accuracy=8)

    return (
        "The video \x02{}\x02 has a length of {} and has been viewed {:,} times for "
        "a total run time of {}!".format(
            snippet["title"], length_text, views, total_text
        )
    ) 
Example #18
Source File: iso8601.py    From pscheduler with Apache License 2.0 5 votes vote down vote up
def iso8601_as_timedelta(iso):
    """Convert an ISO 8601 string to a timdelta"""
    # TODO: Decide what to do with months or years.
    try:
        duration = isodate.parse_duration(iso)
    except isodate.isoerror.ISO8601Error:
        raise ValueError("Invalid ISO duration")
    if type(duration) != datetime.timedelta:
        raise ValueError("Cannot support months or years")
    return duration 
Example #19
Source File: extended_json.py    From dataflows with MIT License 4 votes vote down vote up
def object_hook(cls, obj):
        if 'type{decimal}' in obj:
            try:
                return decimal.Decimal(obj['type{decimal}'])
            except decimal.InvalidOperation:
                pass
        if 'type{time}' in obj:
            try:
                return datetime.datetime \
                    .strptime(obj["type{time}"], TIME_FORMAT) \
                    .time()
            except ValueError:
                pass
        if 'type{datetime}' in obj:
            try:
                (isoformat, tzofs, tzname) = obj["type{datetime}"]
                parsed = datetime.datetime \
                    .strptime(isoformat, DATETIME_FORMAT)
                if tzname is not None:
                    return datetime.datetime \
                        .combine(parsed.date(), parsed.time(),
                                 datetime.timezone(datetime.timedelta(seconds=tzofs), tzname))
                else:
                    return parsed
            except ValueError:
                pass
        if 'type{date}' in obj:
            try:
                return datetime.datetime \
                    .strptime(obj["type{date}"], DATE_FORMAT) \
                    .date()
            except ValueError:
                pass
        if 'type{duration}' in obj:
            try:
                return isodate.parse_duration(obj["type{duration}"])
            except ValueError:
                pass
        if 'type{set}' in obj:
            try:
                return set(obj['type{set}'])
            except ValueError:
                pass

        return obj 
Example #20
Source File: config.py    From modmail with GNU Affero General Public License v3.0 4 votes vote down vote up
def set(self, key: str, item: typing.Any, convert=True) -> None:
        if not convert:
            return self.__setitem__(key, item)

        if key in self.colors:
            try:
                hex_ = str(item)
                if hex_.startswith("#"):
                    hex_ = hex_[1:]
                if len(hex_) == 3:
                    hex_ = "".join(s for s in hex_ for _ in range(2))
                if len(hex_) != 6:
                    raise InvalidConfigError("Invalid color name or hex.")
                try:
                    int(hex_, 16)
                except ValueError:
                    raise InvalidConfigError("Invalid color name or hex.")

            except InvalidConfigError:
                name = str(item).lower()
                name = re.sub(r"[\-+|. ]+", " ", name)
                hex_ = ALL_COLORS.get(name)
                if hex_ is None:
                    name = re.sub(r"[\-+|. ]+", "", name)
                    hex_ = ALL_COLORS.get(name)
                    if hex_ is None:
                        raise
            return self.__setitem__(key, "#" + hex_)

        if key in self.time_deltas:
            try:
                isodate.parse_duration(item)
            except isodate.ISO8601Error:
                try:
                    converter = UserFriendlyTimeSync()
                    time = converter.convert(None, item)
                    if time.arg:
                        raise ValueError
                except BadArgument as exc:
                    raise InvalidConfigError(*exc.args)
                except Exception as e:
                    logger.debug(e)
                    raise InvalidConfigError(
                        "Unrecognized time, please use ISO-8601 duration format "
                        'string or a simpler "human readable" time.'
                    )
                item = isodate.duration_isoformat(time.dt - converter.now)
            return self.__setitem__(key, item)

        if key in self.booleans:
            try:
                return self.__setitem__(key, strtobool(item))
            except ValueError:
                raise InvalidConfigError("Must be a yes/no value.")

        # elif key in self.special_types:
        #     if key == "status":

        return self.__setitem__(key, item) 
Example #21
Source File: webserver.py    From motorway with Apache License 2.0 4 votes vote down vote up
def process(self, message):
        self.process_statistics = message.content['process_statistics']
        self.stream_consumers = message.content['stream_consumers']
        self.failed_messages = message.content['failed_messages']

        for process_id, stats in self.process_statistics.items():
            if process_id in self.process_id_to_name:

                stats['state'] = 'available'
                if stats['waiting'] > 0:
                    stats['state'] = 'busy'
                    processed_last_few_minutes = 0
                    for minute in self.get_last_minutes(3):
                        processed_last_few_minutes += stats['histogram'][str(minute)]['processed_count']
                    if stats['waiting'] > processed_last_few_minutes:
                        stats['state'] = 'overloaded'

                group_name = self.process_id_to_name[process_id].split('-')[0]
                new_stats = self.groups.get(group_name, {'processes': {}.copy()}.copy())
                new_stats['processes'][process_id] = stats
                self.groups[group_name] = new_stats

        for group in self.groups.values():
            group['waiting'] = sum([process['waiting'] for process in group['processes'].values()])
            group['time_taken'] = datetime.timedelta()
            group['histogram'] = {str(minute): {'error_count': 0, 'success_count': 0, 'timeout_count': 0, 'processed_count': 0}.copy() for minute in range(0, 60)}.copy()
            for process_id, process in group['processes'].items():

                # Remove stale processes (those no longer in the connection thread)
                if process_id not in self.process_id_to_name:
                    del group['processes'][process_id]
                    continue

                # Calculate statistics on the active processes
                group['time_taken'] += parse_duration(process['time_taken']) or datetime.timedelta(seconds=0)
                for minute, histogram_dict in process.get('histogram').items():
                    group['histogram'][minute]['error_count'] += histogram_dict['error_count']
                    group['histogram'][minute]['success_count'] += histogram_dict['success_count']
                    group['histogram'][minute]['timeout_count'] += histogram_dict['timeout_count']
                    group['histogram'][minute]['processed_count'] += histogram_dict['processed_count']
            group['frequency'] = sum([sum(process['frequency'].values()) for process in group['processes'].values()]) or 1  # Fallback to at least one, otherwise division fails below

            group['avg_time_taken'] = group['time_taken'] / group['frequency'] / len(group['processes']) if len(group['processes']) else 0

        yield 
Example #22
Source File: config.py    From modmail with GNU Affero General Public License v3.0 4 votes vote down vote up
def get(self, key: str, convert=True) -> typing.Any:
        value = self.__getitem__(key)

        if not convert:
            return value

        if key in self.colors:
            try:
                return int(value.lstrip("#"), base=16)
            except ValueError:
                logger.error("Invalid %s provided.", key)
            value = int(self.remove(key).lstrip("#"), base=16)

        elif key in self.time_deltas:
            if not isinstance(value, isodate.Duration):
                try:
                    value = isodate.parse_duration(value)
                except isodate.ISO8601Error:
                    logger.warning(
                        "The {account} age limit needs to be a "
                        'ISO-8601 duration formatted duration, not "%s".',
                        value,
                    )
                    value = self.remove(key)

        elif key in self.booleans:
            try:
                value = strtobool(value)
            except ValueError:
                value = self.remove(key)

        elif key in self.special_types:
            if value is None:
                return None

            if key == "status":
                try:
                    # noinspection PyArgumentList
                    value = discord.Status(value)
                except ValueError:
                    logger.warning("Invalid status %s.", value)
                    value = self.remove(key)

            elif key == "activity_type":
                try:
                    # noinspection PyArgumentList
                    value = discord.ActivityType(value)
                except ValueError:
                    logger.warning("Invalid activity %s.", value)
                    value = self.remove(key)

        return value 
Example #23
Source File: soundcloud.py    From rssit with MIT License 4 votes vote down vote up
def generate_user(config, user):
    url = "https://www.soundcloud.com/" + user

    data = rssit.util.download(url)

    soup = bs4.BeautifulSoup(data, 'lxml')

    author = html.unescape(soup.find("meta", attrs={"property": "og:title"})["content"])

    if config["author_username"]:
        author = user

    description = html.unescape(soup.find("p", attrs={"itemprop": "description"}).text).strip()
    if len(description) <= 0:
        description = "%s's soundcloud" % user

    feed = {
        "title": author,
        "description": description,
        "url": url,
        "author": user,
        "entries": []
    }

    tracks = soup.findAll("article", attrs={"itemprop": "track"})
    for track in tracks:
        tracka = track.find("a", attrs={"itemprop": "url"})
        trackname = tracka.text
        trackurl = urllib.parse.urljoin(url, tracka["href"])
        date = parse(track.find("time").text)

        title = trackname
        duration_delta = isodate.parse_duration(track.find("meta", attrs={"itemprop": "duration"})["content"])
        duration_seconds = duration_delta.total_seconds()
        duration_text = "[%s:%s:%s]" % (
            str(int(duration_seconds / 3600)).zfill(2),
            str(int((duration_seconds % 3600) / 60)).zfill(2),
            str(int(duration_seconds % 60)).zfill(2)
        )

        content = "<p>%s <a href='%s'>%s</a> by <a href='%s'>%s</a></p>" % (
            duration_text,

            trackurl,
            trackname,

            url,
            author
        )

        feed["entries"].append({
            "url": trackurl,
            "title": title,
            "content": content,
            "author": user,
            "date": date,
        })

    return ("feed", feed) 
Example #24
Source File: turnEntityOffInXIntent.py    From appdaemon-scripts with MIT License 4 votes vote down vote up
def getIntentResponse(self, slots, devicename):
        ############################################
        # an Intent to give back the state from a light.
        # but it also can be any other kind of entity
        ############################################
        try:

            entityname = self.listService.getSwitchable()[slots["device"]]
            # to upper because of https://github.com/gweis/isodate/issues/52
            duration = isodate.parse_duration(slots["duration"].upper())
            self.timer_handle_list.append(
                self.run_in(
                    self.turn_off_callback,
                    duration.total_seconds(),
                    entityname=entityname,
                )
            )
            minutes, seconds = divmod(duration.total_seconds(), 60)
            minutes = int(minutes)
            seconds = int(seconds)
            if minutes == 0:
                if seconds == 1:
                    timeText = " einer Sekunde"
                else:
                    timeText = " {} Sekunden".format(seconds)
            elif minutes == 1:
                if seconds == 1:
                    timeText = " einer Minute und einer Sekunde"
                elif seconds == 0:
                    timeText = " einer Minute"
                else:
                    timeText = " einer Minute und {} Sekunden".format(seconds)
            else:
                if seconds == 1:
                    timeText = " {} Minuten und einer Sekunde".format(minutes)
                elif seconds == 0:
                    timeText = " {} Minuten".format(minutes)
                else:
                    timeText = " {} Minuten und {} Sekunden".format(minutes, seconds)
            text = self.args["textLine"] + timeText + " ab."
        except Exception as e:
            self.log("Exception: {}".format(e))
            self.log("slots: {}".format(slots))
            text = self.random_arg(self.args["Error"])
        return text 
Example #25
Source File: youtube.py    From CloudBot with GNU General Public License v3.0 4 votes vote down vote up
def get_video_description(video_id):
    json = requests.get(api_url.format(video_id, dev_key)).json()

    if json.get('error'):
        if json['error']['code'] == 403:
            return err_no_api
        else:
            return

    data = json['items']
    snippet = data[0]['snippet']
    statistics = data[0]['statistics']
    content_details = data[0]['contentDetails']

    out = '\x02{}\x02'.format(snippet['title'])

    if not content_details.get('duration'):
        return out

    length = isodate.parse_duration(content_details['duration'])
    out += ' - length \x02{}\x02'.format(timeformat.format_time(int(length.total_seconds()), simple=True))
    try:
        total_votes = (float(statistics['likeCount']) +
                       float(statistics['dislikeCount']))
    except KeyError:
        total_votes = "N/A"

    if total_votes != 0:
        # format
        try:
            likes = pluralize(int(statistics['likeCount']), "like")
            dislikes = pluralize(int(statistics['dislikeCount']), "dislike")
            percent = 100 * float(statistics['likeCount']) / total_votes

            out += ' - {}, {} (\x02{:.1f}\x02%)'.format(likes,
                                                        dislikes, percent)
        except (KeyError, ValueError):
            out += ' - {}, {}, (\x02{})'.format('N/A', 'N/A', 'N/A')

    if 'viewCount' in statistics:
        views = int(statistics['viewCount'])
        out += ' - \x02{:,}\x02 view{}'.format(views, "s"[views == 1:])

    uploader = snippet['channelTitle']

    upload_time = time.strptime(snippet['publishedAt'], "%Y-%m-%dT%H:%M:%S.000Z")
    out += ' - \x02{}\x02 on \x02{}\x02'.format(uploader,
                                                time.strftime("%Y.%m.%d", upload_time))

    if 'contentRating' in content_details:
        out += ' - \x034NSFW\x02'

    return out 
Example #26
Source File: youtube.py    From CloudBot with GNU General Public License v3.0 4 votes vote down vote up
def get_video_description(video_id: str) -> str:
    parts = ["statistics", "contentDetails", "snippet"]
    request = get_video(video_id, parts)
    raise_api_errors(request)

    json = request.json()

    data = json["items"]
    if not data:
        raise NoResultsError()

    item = data[0]
    snippet = item["snippet"]
    statistics = item["statistics"]
    content_details = item["contentDetails"]

    out = "\x02{}\x02".format(snippet["title"])

    if not content_details.get("duration"):
        return out

    length = isodate.parse_duration(content_details["duration"])
    out += " - length \x02{}\x02".format(
        timeformat.format_time(int(length.total_seconds()), simple=True)
    )
    try:
        total_votes = float(statistics["likeCount"]) + float(statistics["dislikeCount"])
    except (LookupError, ValueError):
        total_votes = 0

    if total_votes != 0:
        # format
        likes = pluralize_suffix(int(statistics["likeCount"]), "like")
        dislikes = pluralize_suffix(int(statistics["dislikeCount"]), "dislike")

        percent = 100 * float(statistics["likeCount"]) / total_votes
        out += " - {}, {} (\x02{:.1f}\x02%)".format(likes, dislikes, percent)

    if "viewCount" in statistics:
        views = int(statistics["viewCount"])
        out += " - \x02{:,}\x02 view{}".format(views, "s"[views == 1 :])

    uploader = snippet["channelTitle"]

    upload_time = isodate.parse_datetime(snippet["publishedAt"])
    out += " - \x02{}\x02 on \x02{}\x02".format(
        uploader, upload_time.strftime("%Y.%m.%d")
    )

    try:
        yt_rating = content_details["contentRating"]["ytRating"]
    except KeyError:
        pass
    else:
        if yt_rating == "ytAgeRestricted":
            out += colors.parse(" - $(red)NSFW$(reset)")

    return out