@firefliesai/fireflies-node-sdk
Version:
Node.js SDK for Fireflies.ai API
393 lines (392 loc) • 13.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FirefliesSDK = void 0;
const axios_1 = __importDefault(require("axios"));
const helper_js_1 = require("./helper.js");
class FirefliesSDK {
constructor(config) {
this.client = axios_1.default.create({
baseURL: config.baseURL || FirefliesSDK.DEFAULT_BASE_URL,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${config.apiKey}`
}
});
}
async executeGraphQL(query, variables = {}) {
var _a, _b, _c;
try {
const response = await this.client.post('', {
query,
variables
});
// GraphQL responses always have a data property containing the actual response
return response.data.data;
}
catch (error) {
if (axios_1.default.isAxiosError(error)) {
console.log((_a = error.response) === null || _a === void 0 ? void 0 : _a.data);
throw new Error(`Fireflies API Error: ${((_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) || error.message}`);
}
throw error;
}
}
async getAIAppsOutputs(params = {}, filter) {
const query = `
query GetAIAppsOutputs($app_id: String, $transcript_id: String, $skip: Float, $limit: Float) {
apps(app_id: $app_id, transcript_id: $transcript_id, skip: $skip, limit: $limit) {
outputs {
${(0, helper_js_1.generateGraphQLFilter)(filter)}
}
}
}
`;
const response = await this.executeGraphQL(query, params);
return response.apps.outputs;
}
async getUser(userId, filter = []) {
const query = `
query User($userId: String) {
user(id: $userId) {
${(0, helper_js_1.generateGraphQLFilter)(filter)}
}
}
`;
const response = await this.executeGraphQL(query, userId ? { userId } : {});
return response.user;
}
async getUsers(filter = []) {
const query = `
query Users {
users {
${(0, helper_js_1.generateGraphQLFilter)(filter)}
}
}
`;
const response = await this.executeGraphQL(query, {});
return response.users;
}
async getCurrentUser(filter = []) {
return this.getUser('', filter);
}
async getTranscript(transcriptId, filter = []) {
const query = `
query Transcript($transcriptId: String!) {
transcript(id: $transcriptId) {
${(0, helper_js_1.generateGraphQLFilter)(filter)}
}
}
`;
const response = await this.executeGraphQL(query, { transcriptId });
return response.transcript;
}
async getTranscripts(params = {}, filter = []) {
const query = `
query Transcripts(
$title: String
$date: Float
$limit: Int
$skip: Int
$hostEmail: String
$participantEmail: String
$userId: String
$mine: Boolean
) {
transcripts(
title: $title
date: $date
limit: $limit
skip: $skip
host_email: $hostEmail
participant_email: $participantEmail
user_id: $userId
mine: $mine
) {
${(0, helper_js_1.generateGraphQLFilter)(filter)}
}
}
`;
const response = await this.executeGraphQL(query, {
...params,
hostEmail: params.host_email,
organizerEmail: params.organizer_email,
participantEmail: params.participant_email,
userId: params.user_id
});
return response.transcripts;
}
async getBite(biteId, filter = []) {
const query = `
query Bite($biteId: ID!) {
bite(id: $biteId) {
${(0, helper_js_1.generateGraphQLFilter)(filter)}
}
}
`;
const response = await this.executeGraphQL(query, { biteId });
return response.bite;
}
async getBites(params = {}, filter = []) {
const query = `
query Bites($mine: Boolean, $transcript_id: ID, $my_team: Boolean, $limit: Int) {
bites(mine: $mine, transcript_id: $transcript_id, my_team: $my_team, limit: $limit) {
${(0, helper_js_1.generateGraphQLFilter)(filter)}
}
}
`;
const response = await this.executeGraphQL(query, params);
return response.bites;
}
async setUserRole(userId, role) {
const query = `
mutation SetUserRole($userId: String!, $role: Role!) {
setUserRole(user_id: $userId, role: $role) {
name
is_admin
}
}
`;
const response = await this.executeGraphQL(query, {
userId,
role
});
return response.setUserRole;
}
async deleteTranscript(transcriptId) {
const query = `
mutation DeleteTranscript($transcriptId: String!) {
deleteTranscript(id: $transcriptId) {
title
date
duration
organizer_email
}
}
`;
const response = await this.executeGraphQL(query, { transcriptId });
return response.deleteTranscript;
}
async uploadAudio(input) {
const query = `
mutation UploadAudio($input: AudioUploadInput!) {
uploadAudio(input: $input) {
success
title
message
}
}
`;
const response = await this.executeGraphQL(query, { input });
return response.uploadAudio;
}
async createBite(input) {
const query = `
mutation CreateBite(
$transcript_id: ID!,
$name: String,
$start_time: Float!,
$end_time: Float!,
$media_type: String,
$privacies: [String],
$summary: String
) {
createBite(
transcript_id: $transcript_id,
name: $name,
start_time: $start_time,
end_time: $end_time,
media_type: $media_type,
privacies: $privacies,
summary: $summary
) {
status
name
id
}
}
`;
const response = await this.executeGraphQL(query, input);
return response.createBite;
}
async addToLiveMeeting(input) {
const query = `
mutation AddToLiveMeeting(
$meeting_link: String!
$title: String
$meeting_password: String
$duration: Int
$language: String
$attendees: [Attendee]
) {
addToLiveMeeting(
meeting_link: $meeting_link
title: $title
meeting_password: $meeting_password
duration: $duration
language: $language
attendees: $attendees
) {
success
}
}
`;
const response = await this.executeGraphQL(query, input);
return response.addToLiveMeeting;
}
/**
* Get meetings/transcripts for multiple users by providing a list of API keys.
* This implementation includes batch processing, rate limiting, and deduplication of meetings.
* @param apiKeys - Array of API keys for different users
* @param filter - Fields to include in the response
* @param outputType - Type of output ('console' or 'json')
* @returns Promise<{ [key: string]: BatchProcessResult }>
*/
static async getMeetingsForMultipleUsers(apiKeys, filter = [], outputType = 'console') {
if (!apiKeys.length) {
throw new Error('Please provide at least one API key');
}
const deduplicatedObj = await helper_js_1.MeetingsHelper.getDedeuplicatedMeetingIds(apiKeys);
const results = {};
for (const apiKey of Object.keys(deduplicatedObj)) {
const tasks = deduplicatedObj[apiKey].map(item => async () => {
const sdk = new FirefliesSDK({ apiKey });
return { data: { transcript: await sdk.getTranscript(item, filter) } };
});
try {
const result = await helper_js_1.MeetingsHelper.batchProcess(tasks, apiKey);
results[apiKey] = result;
// Handle output
await helper_js_1.MeetingsHelper.handleOutput(result, apiKey, outputType);
}
catch (error) {
if (error instanceof Error) {
console.error(`An error occurred while fetching meetings for apiKey: ${apiKey}`, error.message);
}
results[apiKey] = {
meetings: [],
errors: [error instanceof Error ? error.message : 'Unknown error']
};
}
}
return results;
}
/**
* Find questions asked by external participants in meetings
* @param companyEmailDomain - Your company email domain (e.g. '@company.com')
* @returns Promise<{ externalParticipants: string[], questions: string[] }>
*/
async findExternalParticipantQuestions(companyEmailDomain) {
if (!companyEmailDomain.startsWith('@')) {
throw new Error('Company email domain must start with @');
}
const query = `
query Transcripts {
transcripts {
participants
sentences {
ai_filters {
question
}
speaker_name
}
}
}
`;
const response = await this.executeGraphQL(query);
const results = response.transcripts;
// Find external participants by querying emails != companyEmailDomain
const externalParticipants = [
...new Set(results
.map(transcript => transcript.participants
.filter(participant => !participant.endsWith(companyEmailDomain))
.map(email => email.split('@')[0]))
.flat())
];
// Find questions from external participants by comparing speaker_name to email
const questionsFromExternalParticipants = results
.map(transcript => transcript.sentences
.filter(sentence => {
if (!sentence.speaker_name) {
return false;
}
const regexPattern = new RegExp('^' + sentence.speaker_name.split(' ')[0], 'i');
return (externalParticipants.some(participant => regexPattern.test(participant)) &&
sentence.ai_filters.question &&
sentence.speaker_name);
})
.map(sentence => `${sentence.speaker_name}: ${sentence.ai_filters.question}`))
.flat()
.filter(Boolean);
return {
externalParticipants,
questions: questionsFromExternalParticipants
};
}
/**
* Get video URLs from meetings/transcripts
* @returns Promise<Array<{ id: string, title: string, video_url: string | null }>>
*/
async getMeetingVideos() {
const query = `
query Transcripts {
transcripts {
id
title
video_url
}
}
`;
const response = await this.executeGraphQL(query);
return response.transcripts;
}
/**
* Get summary of a specific transcript/meeting
* @param transcriptId - ID of the transcript to get summary for
* @returns Promise<Summary>
*/
async getTranscriptSummary(transcriptId) {
const query = `
query Transcript($transcriptId: String!) {
transcript(id: $transcriptId) {
summary {
keywords
action_items
outline
shorthand_bullet
overview
bullet_gist
gist
short_summary
short_overview
meeting_type
topics_discussed
transcript_chapters
}
}
}
`;
const response = await this.executeGraphQL(query, { transcriptId });
return response.transcript.summary;
}
}
exports.FirefliesSDK = FirefliesSDK;
FirefliesSDK.DEFAULT_BASE_URL = 'https://api.fireflies.ai/graphql';
// Re-export types for convenience
__exportStar(require("./types"), exports);