-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add an API call example with sendChunk
- Loading branch information
Showing
5 changed files
with
255 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# YouTube: Get information about a YouTube channel | ||
|
||
This quickstart demonstrates how to query the | ||
[YouTube Data API](https://developers.google.com/youtube/v3) using **Cloud | ||
Functions for Firebase** with an HTTPS trigger. | ||
|
||
## Introduction | ||
|
||
The function `getChannelInfo` returns information about a Youtube channel. By | ||
default it will return information about the | ||
[Firebase YouTube channel](https://www.youtube.com/user/Firebase), but you can pass it a | ||
`channelId` URL Query parameter to query any channel you'd like. | ||
|
||
## Setup | ||
|
||
### Get a YouTube API Key | ||
|
||
1. Create a Firebase Project on the | ||
[Firebase Console](https://console.firebase.google.com) if you don't already have a project you want to use. | ||
1. Upgrade your Firebase project to the | ||
[Blaze "pay as you go" plan](https://firebase.google.com/pricing) | ||
1. Enable the Youtube API by visiting the | ||
[API console](http://console.cloud.google.com/marketplace/product/google/youtube.googleapis.com), | ||
selecting your Firebase project, and clicking "ENABLE". | ||
1. Once the API is enabled, visit the | ||
[credentials tab](http://console.cloud.google.com/apis/api/youtube.googleapis.com/credentials) | ||
and click "CREATE CREDENTIALS" to create a YouTube API key. | ||
|
||
### Clone and configure the function | ||
|
||
1. Install the Firebase CLI and log in: | ||
``` | ||
npm install --global firebase-tools | ||
firebase login | ||
``` | ||
1. Clone or download this repo and open the `youtube` directory. | ||
1. `cd` into the `functions` directory and install dependencies with `npm install` | ||
1. Set up your Firebase project by running `firebase use --add` with the | ||
Firebase CLI, select your Project ID and follow the instructions. | ||
1. Set the YouTube API key as an environment variable: | ||
```bash | ||
firebase functions:config:set youtube.key="THE API KEY" | ||
``` | ||
|
||
### Run your function locally with the Firebase Emulator Suite | ||
|
||
1. Set up the Firebase emulators with your config ([docs](https://firebase.google.com/docs/functions/local-emulator#set_up_functions_configuration_optional)): | ||
```bash | ||
cd functions | ||
firebase functions:config:get > .runtimeconfig.json | ||
``` | ||
1. Run the following command to start the emulator: | ||
```bash | ||
firebase emulators:start --only functions | ||
``` | ||
1. Check the emulator output to find the URL of the `getChannelInfo` function. It will looks something like `http://localhost:5001/my-project-id/us-central1/getChannelInfo` | ||
1. Via CURL or in your browser, visit the URL that the function is running at. Optionally, add a query string `?channelId=SOME_CHANNEL_ID` to the end of the URL. | ||
1. You should get a JSON response with information about the YouTube channel! | ||
|
||
|
||
## Deploy the app to prod | ||
|
||
Deploy to Firebase using the following command: | ||
|
||
```bash | ||
firebase deploy | ||
``` | ||
|
||
This deploys and activates the `getChannelInfo` function. | ||
|
||
> The first time you call `firebase deploy` on a new project with Functions will take longer than usual. | ||
|
||
## Modify it to your needs | ||
|
||
Now that you've got this sample working, modify it to work for your use case! Some ideas: | ||
- Check out the other things you can query with the [YouTube Data API](https://developers.google.com/youtube/v3/docs) | ||
- Convert `getChannelInfo` function to a scheduled function, and write the new latest videos for a channel into Firestore or Realtime Database | ||
- ...anything else you can think of! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"functions": { | ||
"codebase": "youtube", | ||
"predeploy": [ | ||
"npm --prefix \"$RESOURCE_DIR\" run lint" | ||
], | ||
"source": "functions" | ||
}, | ||
"emulators": { | ||
"functions": { | ||
"port": 5001 | ||
}, | ||
"ui": { | ||
"enabled": true | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* Copyright 2023 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
module.exports = { | ||
root: true, | ||
env: { | ||
es2020: true, | ||
node: true, | ||
}, | ||
extends: [ | ||
"eslint:recommended", | ||
"google", | ||
], | ||
rules: { | ||
quotes: ["error", "double"], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/** | ||
* Copyright 2023 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
const {onCall, HttpsError} = require("firebase-functions/v2/https"); | ||
const {defineString, defineSecret} = require("firebase-functions/params"); | ||
|
||
const {google} = require("googleapis"); | ||
|
||
const youtubeKey = defineSecret("YOUTUBE_API_KEY"); | ||
const defaultChannelId = defineString("DEFAULT_CHANNEL_ID", { | ||
default: "UCP4bf6IHJJQehibu6ai__cg", | ||
}); | ||
|
||
exports.getChannelInfo = onCall( | ||
{secrets: [youtubeKey]}, | ||
|
||
async (request, response) => { | ||
const youtube = google.youtube({ | ||
version: "v3", | ||
auth: youtubeKey.value(), | ||
}); | ||
const channelId = request.data.channelId || defaultChannelId; | ||
|
||
const channelInfo = {id: channelId}; | ||
|
||
// Fetch channel information | ||
let channelData; | ||
try { | ||
// tell the client app we're starting | ||
response.sendChunk({status: "fetching channel info", channelInfo}); | ||
|
||
// https://developers.google.com/youtube/v3/docs/channels/list | ||
const {data} = await youtube.channels.list({ | ||
part: "snippet,statistics", | ||
id: channelId, | ||
maxResults: 1, | ||
}); | ||
channelData = data; | ||
} catch (error) { | ||
throw new HttpsError("internal", "Failed to fetch channel data."); | ||
} | ||
|
||
if (!channelData.items || channelData.items.length !== 1) { | ||
throw new HttpsError( | ||
"invalid-argument", | ||
`Channel with ID ${channelId} not found.`, | ||
); | ||
} | ||
|
||
const channel = channelData.items[0]; | ||
(channelInfo.channelTitle = channel.snippet.title), | ||
(channelInfo.channelDescription = channel.snippet.description), | ||
(channelInfo.subscriberCount = channel.statistics.subscriberCount), | ||
// send latest data to the client app | ||
response.sendChunk({status: "found channel info", channelInfo}); | ||
|
||
// Fetch the channel's latest videos | ||
let videoData; | ||
try { | ||
// tell the client app we're starting to fetch videos | ||
response.sendChunk({status: "fetching latest videos", channelInfo}); | ||
// https://developers.google.com/youtube/v3/docs/search/list | ||
const {data} = await youtube.search.list({ | ||
part: "id, snippet", | ||
order: "date", | ||
channelId, | ||
maxResults: 3, | ||
}); | ||
videoData = data; | ||
} catch (error) { | ||
throw new HttpsError("internal", "Failed to fetch video data."); | ||
} | ||
const videos = (videoData.items || []).map((video) => ({ | ||
videoTitle: video.snippet.title, | ||
videoUrl: `https://www.youtube.com/watch?v=${video.id.videoId}`, | ||
videoDescription: video.snippet.description, | ||
})); | ||
|
||
channelInfo.recentVideos = videos; | ||
// send the latest data to the client app | ||
response.sendChunk({ | ||
status: `found ${videos.length} videos`, | ||
channelInfo, | ||
}); | ||
|
||
return channelInfo; | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"name": "functions", | ||
"description": "Cloud Functions for Firebase", | ||
"scripts": { | ||
"lint": "eslint .", | ||
"serve": "firebase emulators:start --only functions", | ||
"shell": "firebase functions:shell", | ||
"start": "npm run shell", | ||
"deploy": "firebase deploy --only functions", | ||
"logs": "firebase functions:log" | ||
}, | ||
"engines": { | ||
"node": "18" | ||
}, | ||
"main": "index.js", | ||
"dependencies": { | ||
"firebase-admin": "^11.9.0", | ||
"firebase-functions": "^4.4.1", | ||
"googleapis": "^66.0.0" | ||
}, | ||
"devDependencies": { | ||
"eslint": "^8.40.0", | ||
"firebase-functions-test": "^3.1.0" | ||
}, | ||
"private": true | ||
} |