Giter Club home page Giter Club logo

popyt's Introduction

Popyt

Want to access data from the YouTube Data v3 API? Want a Node.js YouTube API wrapper with typings, promises, and caching? No problem! We've got ya covered. npm i popyt

GitHub issues GitHub stars GitHub license Release coverage Actions status DeepScan grade Downloads Version

Examples

Here are some basic methods (try it on CodeSandbox):

Instantiate the object:

const { YouTube } = require('popyt')
const youtube = new YouTube(apiKey)

Instantiate the object without caching:

const { YouTube } = require('popyt')
const youtube = new YouTube(apiKey, undefined, { cache: false })

Get a video by ID:

const video = await youtube.getVideo('dQw4w9WgXcQ')
console.log(video)

You can do the same thing with playlists, channels, and comments by replacing Video with any of them.

Get a video by URL:

const video = await youtube.getVideo('https://youtube.com/watch?v=dQw4w9WgXcQ')
console.log(video)

Get a video by title (or similar title):

const video = await youtube.getVideo('never gonna give you up')
console.log(video)

Search videos:

const search = await youtube.searchVideos('never gonna give you up')
console.log(search.items.map(v => v.title).join('\n')) // titles of 50 beautiful videos

Note: This wrapper does not implement every feature of the YouTube API. If you would like anything added, feel free to open an issue. The limits imposed by the wrapper are not imposed by YouTube.

popyt's People

Contributors

brandonbothell avatar dependabot[bot] avatar maxcell avatar rafaneri avatar renovate-bot avatar renovate[bot] avatar sogehige avatar tenpi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

popyt's Issues

Undefined LiveStatus for searchChannels

What behaviour is expected:

A value of "live", "upcoming" or "false" according to the docs

What behaviour is observed:

A value of undefined is returned

Steps/models to reproduce:

let search = await youtube.searchChannels('PewDiePie', 1); console.log(search);

Outputs:
{ results: [ Channel { youtube: [YouTube], data: [Object], full: false, id: 'UC-lHJZR3Gqxm24_Vd_AJ5Yw', liveStatus: undefined, profilePictures: [Object], dateCreated: 2010-04-29T10:54:00.000Z, name: 'PewDiePie', about: 'I make videos.', url: 'https://youtube.com/channel/UC-lHJZR3Gqxm24_Vd_AJ5Yw' } ],

Anything else:

I'm trying to make my Discord bot check whether a youtube channel is live or not, please tell me if I'm missing something as I'm a very new to programming myself.

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

No support for non-URI-friendly searchTerms

I had to figure out why Hungarian searches failed in our Discord bot... it's easy to fix (I did fix it for myself) but it can be confusing, so why not call an encodeURI on the searchTerm at some point.

Add PlaylistItems endpoints

Structure:

{
  "kind": "youtube#playlistItem",
  "etag": etag,
  "id": string,
  "snippet": {
    "publishedAt": datetime,
    "channelId": string,
    "title": string,
    "description": string,
    "thumbnails": {
      (key): {
        "url": string,
        "width": unsigned integer,
        "height": unsigned integer
      }
    },
    "channelTitle": string,
    "playlistId": string,
    "position": unsigned integer,
    "resourceId": {
      "kind": string,
      "videoId": string,
    }
  },
  "contentDetails": {
    "videoId": string,
    "startAt": string,
    "endAt": string,
    "note": string,
    "videoPublishedAt": datetime
  },
  "status": {
    "privacyStatus": string
  }
}

Methods:

  • Insert:

    • POST https://www.googleapis.com/youtube/v3/playlistItems
    • OAuth
    • Parameters:
      • part: string - The parts to both insert and return.
        • contentDetails
        • id
        • snippet
        • status
    • Body:
      • snippet.playlistId - required
      • snippet.position
      • snippet.resourceId - required
      • contentDetails.note
      • contentDetails.startAt
      • contentDetails.endAt
    • Returns: A PlaylistItem resource.
  • Update:

    • PUT https://www.googleapis.com/youtube/v3/playlistItems
    • OAuth
    • Parameters:
      • [same as Insert method]
    • Body:
      • id - required
      • [same as Insert method]
      • If you are submitting an update request, and your request does not specify a value for a property that already has a value, the property's existing value will be deleted.
    • Returns: A PlaylistItem resource.
  • Delete:

    • DELETE https://www.googleapis.com/youtube/v3/playlistItems
    • OAuth
    • Parameters:
      • id: string - YouTube playlist item ID for the playlist item that is being deleted.
    • Body:
      • None
    • Returns: 204 No Content

src/index.ts AI analysis

Overall, the file looks well-structured and organized. Here are a few suggestions for optimizations:

1. Use type aliases for resolvable types: In the current implementation, the GenericService.getId method takes a resolvable parameter which can be either a string, a Video, or a Channel. It would be more type-safe to use type aliases for these resolvable types instead of string | Video | Channel. For example:

type VideoResolvable = string | Video;
type ChannelResolvable = string | Channel;
  1. Remove deprecated methods: The getChannelComments method is marked as deprecated and has a note pointing to a Google support thread. It might be better to remove this method altogether from the file.
    /

  2. Use async/await instead of Promises: The file uses both Promises and async/await syntax for asynchronous operations. It would be more consistent to use async/await throughout the file.

  3. Use destructuring for function parameters: Some functions take multiple parameters, and it might be more readable to use destructuring to extract the required parameters. For example:

~~public async getPlaylistItems (playlistResolvable: string | Playlist, { maxResults = 10, pageToken, parts }: { maxResults?: number, pageToken?: string, parts?: PlaylistItemParts } = {}): Promise<Video[]> {
  const playlistId = await GenericService.getId(this, playlistResolvable, Playlist);
  return (await GenericService.getPaginatedItems(
    { youtube: this, type: PaginatedItemType.PlaylistItems, id: playlistId, maxResults, pageToken, parts })).results as Video[];
}~~
  1. Use default parameters for optional values: Some functions have optional parameters, and it might be better to use default parameters instead of explicitly checking for undefined values. For example:
public async getVideoComments (videoResolvable: string | Video, { maxResults = 20, pageToken, sortOrder = 'time', parts }: { maxResults?: number, pageToken?: string, sortOrder?: 'relevance' | 'time' | 'likes', parts?: CommentThreadParts } = {}): Promise<YTComment[]> {
  const videoId = await GenericService.getId(this, videoResolvable, Video);
  return (await GenericService.getPaginatedItems(
    { youtube: this, type: PaginatedItemType.VideoComments, id: videoId, maxResults, pageToken, parts, order: sortOrder })).results as YTComment[];
}

Split the code into smaller modules: The index.ts file currently contains a lot of code and imports. Consider splitting the code into smaller modules based on functionality. This will improve maintainability and make the codebase easier to navigate.

Group Imports: Instead of importing each entity individually from the ./entities module, you can use a wildcard import to import all entities at once. For example, replace that long devilish thing with:

import * as Entities from './entities';

Add VideoAbuseReportReasons endpoints

Structure:

{
  "kind": "youtube#videoAbuseReportReason",
  "etag": etag,
  "id": string,
  "snippet": {
    "label": string,
    "secondaryReasons": [
      {
        "id": string,
        "label": string
      }
    ]
  }
}

Methods:

  • List:
    • GET https://www.googleapis.com/youtube/v3/videoAbuseReportReasons
    • OAuth
    • Parameters:
      • part: string - Supported values are id and snippet (should use both).
      • hl?: string - Language to use for the response. Defaults to en_US.
    • Body:
      • None
    • Returns:
      • The following:
{
  "kind": "youtube#videoAbuseReportReasonListResponse",
  "etag": etag,
  "items": [
    videoAbuseReportReason resource
  ]
}

Certain channels do not resolve

This may be a YouTube limitation but reporting here in case it's otherwise. If you try getChannel() with this URL it will fail with "Item not found" error:

https://www.youtube.com/c/ChilledCow

but the same URL with a trailing slash will work just fine:

https://www.youtube.com/c/ChilledCow/

Using just "ChilledCow" also works. However, other channels do not work even with trailing slash or with only the end path.

const { YouTube } = require('popyt');
const youtube = new YouTube(YOUTUBE_KEY);

/*
Working:
'https://www.youtube.com/c/ChilledCow/'
'ChilledCow'

"Item not found":
'https://www.youtube.com/c/ChilledCow'
'https://www.youtube.com/c/fosterkittensofficial/'
'https://www.youtube.com/c/fosterkittensofficial'
'fosterkittensofficial'
*/

const query = 'https://www.youtube.com/c/ChilledCow/';

youtube
  .getChannel(query)
  .then(res => console.log(res.data.snippet))
  .catch(err => console.error(err));

When I load those failing URLs in the browser, they load fine and I can't discern any particular difference between the working and non-working URLs. Thank you for the library! ๐Ÿ™‡๐Ÿผโ€โ™‚๏ธ

Add VideoCategories endpoints

Structure:

{
  "kind": "youtube#videoCategory",
  "etag": etag,
  "id": string,
  "snippet": {
    "channelId": "UCBR8-60-B28hp2BmDPdntcQ",
    "title": string,
    "assignable": boolean
  }
}

Methods:

  • List:
    • GET https://www.googleapis.com/youtube/v3/videoCategories
    • Public
    • Parameters:
      • part: string - Set the part to snippet.
      • One of:
        • id: string - Comma-separated list of video category IDs for the resources that you are retrieving.
        • regionCode: string - instructs the API to return the list of video categories available in the specified country. The parameter value is an ISO 3166-1 alpha-2 country code.
    • Body:
      • None
    • Returns:
      • The following:
{
  "kind": "youtube#videoCategoryListResponse",
  "etag": etag,
  "nextPageToken": string,
  "prevPageToken": string,
  "pageInfo": {
    "totalResults": integer,
    "resultsPerPage": integer
  },
  "items": [
    videoCategory resource
  ]
}

Entity interface

Make sure all entities contain the following properties/methods:

  • an endpoint string for the name of the entity's endpoint
  • a fetch method for fetching the entity again
  • an id property
  • a data property
  • a youtube property
  • a full property
  • a url property

(Almost) Full coverage of the YouTube Data v3 API

  • Add Activities endpoints
    #43

  • Add ChannelBanners endpoints
    #42

  • Add Channels endpoints
    #41

  • Add ChannelSections endpoints
    #40

  • Add Comment endpoints
    #39

  • Add GuideCategories endpoints
    #38

  • Add i18nLanguages endpoints
    #37

  • Add i18nRegions endpoints
    #36

  • Add Members endpoint (awaiting special permission by YouTube)
    #94

  • Add MembersipsLevels endpoint (awaiting special permission by YouTube)
    #95

  • Add Captions endpoints
    #103

  • Add PlaylistItems endpoints
    #35

  • Add Playlists endpoints
    #34

  • Add Watermarks endpoints
    #31

src/entities/video.ts AI analysis

Sure, here are some suggestions and optimizations for the Video.ts file:

  1. Use type aliases for complex types: The Video class has several complex types such as VideoUpdateResource, CommentThreadParts, etc. It would be more readable to use type aliases for these types instead of defining them inline.

  2. Use object destructuring to extract properties: Some functions in the Video class take an object as a parameter, and it might be more readable to use object destructuring to extract only the required properties. For example:

public async update ({ title, description, tags, categoryId, privacyStatus }: { title?: string, description?: string, tags?: string[], categoryId?: string, privacyStatus?: 'public' | 'private' | 'unlisted' } = {}): Promise<void> {
  const request: VideoUpdateResource = {
    id: this.id,
    snippet: {
      title: title || this.title,
      description: description || this.description,
      tags: tags || this.tags,
      categoryId: categoryId || this.data.snippet.categoryId
    },
    status: {
      privacyStatus: privacyStatus || this.data.status.privacyStatus
    }
  }
  await this.youtube._updateVideo(request)
  if (title) this.title = title
  if (description) this.description = description
  if (tags) this.tags = tags
  if (categoryId) this.data.snippet.categoryId = categoryId
  if (privacyStatus) this.data.status.privacyStatus = privacyStatus
}
  1. Use const instead of let: Some variables in the Video class are not reassigned and can be declared as const instead of let. For example:
const { items } = await this.youtube._makeRequest({
  method: 'GET',
  params: {
    part: ['snippet', 'contentDetails', 'statistics', 'status'].join(','),
    id: this.id
  }
})
  1. Use arrow functions for class methods: Some class methods in the Video class use function syntax instead of arrow functions. It might be more consistent to use arrow functions throughout the class.

  2. Use optional chaining for nested properties: Some properties in the Video class are nested and might be undefined. It would be more readable to use optional chaining to avoid errors when accessing nested properties. For example:

this._length = Parser.parseIsoDuration(video.contentDetails?.duration)
  1. Add JSDoc comments to public methods: Some public methods in the Video class lack JSDoc comments, which makes it harder to understand their usage and parameters.

  2. Remove unused code: The postComment method is not used in the class, and can be removed.

  3. Remove unreachable code: The this.liveStatus property is always assigned one of two values, so the else block in the corresponding if statement is unreachable and can be removed.

Overall, the Video.ts file looks well-structured and easy to understand, with only minor improvements needed for readability and maintainability.

src/util/caching.ts AI analysis

Rename to cache.ts

Consider Using a Map Instead of Object: Instead of using a plain object { [key: string]: CacheItem } to store cache items, consider using a Map data structure. Maps provide built-in methods for managing key-value pairs and can improve performance and code readability.

Improve Naming: Consider using more descriptive names for variables and functions. For example, instead of using name as a parameter in the set and get methods, consider using a more meaningful name, such as key or cacheKey.

Get all playlists of a given channel

Hello,

Thanks for your hard work : this library is by far the cleanest I have seen for this domain ;)

Like the title said, I would like to get all the playlists for a channel ( for exemple mine :
UCG0N7IV-C43AM9psxslejCQ ). Your searchPlaylists function doesn't include a parameter for that.

From what I read on the docs , you only have to include the optional parameter channelId in your requests. ( demo url )

Thank you in advance

Add Watermarks endpoints

Structure:

{
  "timing": {
    "type": string,
    "offsetMs": unsigned long,
    "durationMs": unsigned long
  },
  "position": {
    "type": string,
    "cornerPosition": string
  },
  "imageUrl": string,
  "imageBytes": bytes,
  "targetChannelId": string
}

Methods:

  • Set:
    • POST https://www.googleapis.com/upload/youtube/v3/watermarks/set
    • OAuth
    • Parameters:
      • channelId: string - YouTube channel ID for which the watermark is being provided.
    • Body:
      • Provide a Watermark resource in the request body
    • Returns: 204 No Content
  • Unset:
    • POST https://www.googleapis.com/youtube/v3/watermarks/unset
    • OAuth
    • Parameters:
      • channelId: string - YouTube channel ID for which the watermark is being unset.
    • Body:
      • None
    • Returns: 204 No Content

Fetchvideos max number of elements

Hello
When I tried to call fetchVideos with a number greater than 50, the library throws an error. This seems a bit harsh given that 100 still seems like a reasonable size for playlists.
Why does this limitation exist? Is there a workaround to indeed do fetch all the videos of the playlist, at least up to a greater limit? This is really a serious limitation for me at the moment, as I'm using the library for developing a musicbot on Discord. I hope there can be a solution.
Thank you for a response.

Error: Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential

Hi,

I am getting the following error when I tried to call function

const youtube = new YouTube(process.env.YOUTUBE_API_KEY, { cache: false })
const YTCategories = await youtube.getCategories()
console.log(process.env.YTCategories);

Error: Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
at IncomingMessage. (D:\xampp\htdocs\nextjs-prisma-devcomm\node_modules\popyt\out\util\request.js:148:39)

Can you please help me to resolve this asap?

Thanks,

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update dependency @types/merge2 to v1.4.4
  • chore(deps): update dependency eslint-plugin-import to v2.29.1
  • chore(deps): update dependency ts-node to v10.9.2
  • chore(deps): update dependency typedoc-plugin-markdown to v3.17.1
  • chore(deps): update dependency dotenv to v16.4.5
  • chore(deps): update dependency eslint to v8.57.0
  • chore(deps): update dependency eslint-plugin-jsdoc to v46.10.1
  • chore(deps): update dependency eslint-plugin-unused-imports to v3.2.0
  • chore(deps): update dependency mocha to v10.4.0 (mocha, @types/mocha)
  • chore(deps): update node.js to v20.13.1 (node, @types/node)
  • chore(deps): update react monorepo (@types/react, @types/react-dom, react, react-dom)
  • chore(deps): update typescript-eslint monorepo to v6.21.0 (@typescript-eslint/eslint-plugin, @typescript-eslint/parser)
  • fix(deps): update dependency clsx to v2.1.1
  • chore(deps): update actions/setup-node action to v4
  • chore(deps): update borales/actions-yarn action to v5
  • chore(deps): update codecov/codecov-action action to v4
  • chore(deps): update dependency @googleapis/youtube to v16
  • chore(deps): update dependency chai to v5
  • chore(deps): update dependency docusaurus-plugin-typedoc to v1
  • chore(deps): update dependency eslint to v9
  • chore(deps): update dependency eslint-plugin-jsdoc to v48
  • chore(deps): update dependency typedoc-plugin-markdown to v4
  • chore(deps): update typescript-eslint monorepo to v7 (major) (@typescript-eslint/eslint-plugin, @typescript-eslint/parser)
  • fix(deps): update dependency @mdx-js/react to v3
  • fix(deps): update docusaurus monorepo to v3 (major) (@docusaurus/core, @docusaurus/module-type-aliases, @docusaurus/preset-classic, @docusaurus/theme-classic, @docusaurus/theme-common, @docusaurus/tsconfig, @docusaurus/types)
  • ๐Ÿ” Create all rate-limited PRs at once ๐Ÿ”

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

github-actions
.github/workflows/coverage.yml
  • actions/checkout v3
  • actions/setup-node v3.8.2
  • borales/actions-yarn v4
  • codecov/codecov-action v3
.github/workflows/main.yml
  • actions/checkout v3
  • actions/setup-node v3.8.2
  • borales/actions-yarn v4
  • borales/actions-yarn v4
  • borales/actions-yarn v4
  • actions/checkout v3
  • actions/setup-node v3.8.2
  • borales/actions-yarn v4
  • codecov/codecov-action v3
.github/workflows/release.yml
  • actions/checkout v3
  • actions/setup-node v3.8.2
  • borales/actions-yarn v4
  • borales/actions-yarn v4
  • actions/checkout v3
  • actions/setup-node v3.8.2
  • borales/actions-yarn v4
  • borales/actions-yarn v4
.github/workflows/renovate.yml
  • actions/checkout v3
  • actions/setup-node v3.8.2
  • borales/actions-yarn v4
  • borales/actions-yarn v4
  • borales/actions-yarn v4
  • borales/actions-yarn v4
npm
.yarn/sdks/eslint/package.json
.yarn/sdks/typescript/package.json
docusaurus/package.json
  • @docusaurus/core 2.4.3
  • @docusaurus/preset-classic 2.4.3
  • @mdx-js/react 1.6.22
  • @types/react 18.2.35
  • clsx 2.0.0
  • prism-react-renderer 1.3.5
  • react 18.2.0
  • react-dom 18.2.0
  • @docusaurus/module-type-aliases 2.4.3
  • @docusaurus/theme-classic 2.4.3
  • @docusaurus/theme-common 2.4.3
  • @docusaurus/tsconfig 0.0.0-5601
  • @docusaurus/types 2.4.3
  • @types/node 20.9.0
  • docusaurus-plugin-typedoc 0.19.2
  • typedoc 0.24.8
  • typedoc-plugin-markdown 3.17.0
  • typescript 5.1.6
  • node >=16.14
  • @types/react 18.2.35
  • @types/react-dom 18.2.14
  • yarn 3.6.2
package.json
  • @googleapis/youtube 11.0.1
  • @istanbuljs/nyc-config-typescript 1.0.2
  • @types/chai 4.3.10
  • @types/gulp 4.0.16
  • @types/gulp-sourcemaps 0.0.37
  • @types/merge2 1.4.3
  • @types/mocha 10.0.3
  • @types/node 20.9.0
  • @typescript-eslint/eslint-plugin 6.13.0
  • @typescript-eslint/parser 6.13.0
  • chai 4.3.10
  • cross-env 7.0.3
  • dotenv 16.3.1
  • eslint 8.53.0
  • eslint-plugin-import 2.29.0
  • eslint-plugin-jsdoc 46.8.2
  • eslint-plugin-unused-imports 3.0.0
  • mocha 10.2.0
  • nyc 15.1.0
  • source-map-support 0.5.21
  • ts-node 10.9.1
  • typescript 5.1.6
  • node 20.9.0
  • node-preload 0.2.0
  • yarn 3.6.2

  • Check this box to trigger a request for Renovate to run again on this repository

Length of video on playlist.fetchVideos()

Would it be possible to add the length of the videos when we request a playlist? When I use playlist.fetchVideos(), it returns a lot of information, but the length of the videos doesn't come.

Add Playlists endpoints

Structure:

{
  "kind": "youtube#playlist",
  "etag": etag,
  "id": string,
  "snippet": {
    "publishedAt": datetime,
    "channelId": string,
    "title": string,
    "description": string,
    "thumbnails": {
      (key): {
        "url": string,
        "width": unsigned integer,
        "height": unsigned integer
      }
    },
    "channelTitle": string,
    "tags": [
      string
    ],
    "defaultLanguage": string,
    "localized": {
      "title": string,
      "description": string
    }
  },
  "status": {
    "privacyStatus": string
  },
  "contentDetails": {
    "itemCount": unsigned integer
  },
  "player": {
    "embedHtml": string
  },
  "localizations": {
    (key): {
      "title": string,
      "description": string
    }
  }
}

Methods:

  • Insert:

    • POST https://www.googleapis.com/youtube/v3/playlists
    • OAuth
    • Parameters:
      • part: string - The parts to insert and to return.
        • contentDetails
        • id
        • localizations
        • player
        • snippet
        • status
    • Body:
      • snippet.title - required
      • snippet.description
      • status.privacyStatus
      • snippet.tags[]
      • snippet.defaultLanguage
      • localizations.(key)
      • localizations.(key).title
      • localizations.(key).description
    • Returns: A Playlist resource.
  • Update:

    • PUT https://www.googleapis.com/youtube/v3/playlists
    • OAuth
    • Parameters:
      • [same as Insert method]
    • Body:
      • id - required
      • [same as Insert method]
      • If you are submitting an update request, and your request does not specify a value for a property that already has a value, the property's existing value will be deleted.
    • Returns: A Playlist resource.
  • Delete:

    • DELETE https://www.googleapis.com/youtube/v3/playlists
    • OAuth
    • Parameters:
      • id: string - YouTube playlist ID for the playlist that is being deleted.
    • Body:
      • None
    • Returns: 204 No Content

Items must either specify an ID or the 'mine' parameter.

When I try to use popyt with my discord bot, this error shows up:
(node:14684) UnhandledPromiseRejectionWarning: Items must either specify an ID or the 'mine' parameter. (node:14684) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2) (node:14684) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I don't know why is this happening, everything should be working.
The code is:
const Discord = require("discord.js"); const { YouTube } = require('popyt'); const prefix = "~" const youtube = new YouTube('<token here>'); module.exports.run = async (bot, msg, args) => { const argums = msg.content.slice(prefix.length).split(' '); if (!argums.length) { return msg.channel.send(You didn't provide any arguments, ${msg.author}!); } else { const video = await youtube.getVideo(argums) msg.channel.send(video); } }

Video duration from playlist

video.minutes and video.seconds are undefined when fetching videos from a playlist so I have to use getVideo() using the fetched videos to get the duration
image

getVideoComments gives error "commentThreads not found"

What behaviour is expected

Running the following code snippet should return a list of comments for the given video:

const comments = await youtube.getVideoComments(Video, 0)

What behaviour is observed

I get the error commentThreads not found

Additional context

Full snippet:

const channel = await youtube.getChannel(process.env.YOUTUBE_CHANNEL_ID)
const uploadsPlaylistId = channel.data.contentDetails.relatedPlaylists.uploads
const playlist = await youtube.getPlaylistItems(uploadsPlaylistId, 0)

for(let video of playlist) {
      const comments = await youtube.getVideoComments(video, 0)
      console.log(comments)
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.