Generate Google Meet link from shell
I wanted a shell command that:
- creates a meeting
- prints out its links
- copies it to clipboard
- opens it in the browser for correct account
It takes ~10 minutes to set up and is based on Google Meet API guide.
Prerequisites
- Personal Google Cloud Platform account
- Node.js installed
0. Prepare project directory
~ 1 minute
Create an empty NodeJS project in a directory of your choice (i put mine in ~/.config/scripts/
):
mkdir -p ~/.config/scripts/auto-meet
cd ~/.config/scripts/auto-meet
npm init -y
npm i @google-apps/meet @google-cloud/local-auth
1. Create a GCP project
~ 1 minute
Go to Google Cloud Console and create a new project. Use your personal account as this project might be handy for other utils in the future.
2. Enable Google Meet API
< 1 minute
When project is created, go to Enabled APIs and Services and enable Google Meet REST API.
3. Configure OAuth consent screen
~ 5 minutes
When API is enabled, you’ll see invitation to create credentials, which will take you to Wizard.
In this wizard:
- What data will you be accessing? User data
- Scopes > Add or remove scopes > Search for mettings.space.created > Add
- Application type > Desktop app
- Name > Whatever you want
After that you’ll be presented with a button to download credentials. Save them as credentials.json
in project dir.
Now go to OAuth consent screen and fill in the required fields. On 3rd step add all your relevant emails to the test users.
4. Create a script
~ 1 minute
Put following code into index.js
in your project directory.
Based on Google’s own example script. All i’m really changing is what is being printed out in the end (clean meeting url).
// index.js
const fs = require("fs").promises;
const path = require("path");
const process = require("process");
const { authenticate } = require("@google-cloud/local-auth");
const { SpacesServiceClient } = require("@google-apps/meet").v2;
const { auth } = require("google-auth-library");
const SCOPES = ["https://www.googleapis.com/auth/meetings.space.created"];
const TOKEN_PATH = path.join(process.cwd(), "token.json");
const CREDENTIALS_PATH = path.join(process.cwd(), "credentials.json");
async function loadSavedCredentialsIfExist() {
const content = await fs.readFile(TOKEN_PATH);
const credentials = JSON.parse(content);
return auth.fromJSON(credentials);
}
async function saveCredentials(client) {
const content = await fs.readFile(CREDENTIALS_PATH);
const keys = JSON.parse(content);
const key = keys.installed || keys.web;
const payload = JSON.stringify({
type: "authorized_user",
client_id: key.client_id,
client_secret: key.client_secret,
refresh_token: client.credentials.refresh_token,
});
await fs.writeFile(TOKEN_PATH, payload);
}
async function authorize() {
let client = await loadSavedCredentialsIfExist();
if (client) return client;
client = await authenticate({
scopes: SCOPES,
keyfilePath: CREDENTIALS_PATH,
});
if (client.credentials) {
await saveCredentials(client);
}
return client;
}
async function createSpace(authClient) {
const meetClient = new SpacesServiceClient({ authClient });
const response = await meetClient.createSpace({});
console.log(response[0].meetingUri);
}
authorize().then(createSpace).catch(console.error);
5. Create a shell function
~ 1 minute
Add this to your .bashrc
or .zshrc
.
Make sure to replace ~/.config/scripts/auto-meet
with your project directory!
function meet() {
url=$(node ~/.config/scripts/auto-meet/index.ts)
if [ -z "$url" ]; then
echo "Failed to get the meeting url"
return 1
fi
echo $url
echo $url | pbcopy
open $url
return 0
}
Usage and remarks
First run
Source your shell config or just restart it. First time you run meet
, you’ll be prompted in your browser to authenticate with your Google account. After that, the token will be saved in token.json
and you won’t be asked again. If token expires or gets revoked, you’ll have to delete token.json
and re-run the script.
Multiple Google accounts and ?authuser=
Let me rant quickly that ?authuser=
is a mistake and i’d rather have to log in/out of console sometimes but be able to click links without switching to correct account afterwards. Eh.
If you have multiple Google accounts active on your browser, you can modify the function to something like this:
...
echo $url
echo $url | pbcopy
open "$url?authuser=1"
return 0
}
Or parametrize the authuser
value to call it like meet 1
or meet 2
:
open "$url?authuser=$1"
In that case, browser will open with correct ?authuser=
parameter. But the copied link will be account-agnostic. Beware that the owner of the call is whoever produced the token, i.e. the account you authenticated with on the OAuth screen.