Skip to content

Commit

Permalink
fix(*): Fix bugs
Browse files Browse the repository at this point in the history
- Fix getCaptionTrack endpoint
- Add error handling to getCaptionTrack
- Fix bad request from front-end to getCaptionTrack
- Fix error display on stylish-url
  • Loading branch information
jacob-ian committed Jul 11, 2021
1 parent 01947f5 commit 4ebb670
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 60 deletions.
12 changes: 6 additions & 6 deletions functions/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

114 changes: 69 additions & 45 deletions functions/src/captions/restful/getCaptionTrack.endpoint.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as functions from 'firebase-functions';
import { Get } from 'firebase-backend';
import { Request, Response } from 'express';
import base64url from 'base64url';
Expand All @@ -10,32 +9,42 @@ const { fetch } = context({
});

export default new Get(async (req: Request, res: Response) => {
const captionTrackUrl = getCaptionUrlFromRequest(req.body);
const captionTrackXml = await getCaptionTrackXml(captionTrackUrl);
return res.status(200).send(captionTrackXml);
try {
let captionTrack = await getCaptionTrack(req);
return respondWithCaptionTrack(res, captionTrack);
} catch (error) {
return respondWithError(res, error);
}
});

function getCaptionUrlFromRequest(body: any): string {
const videoQuery = getDecodedVideoQuery(body['data']);
const translation = getTranslationParam(body['tlang']);
async function getCaptionTrack(req: Request): Promise<string> {
const captionTrackUrl = getCaptionUrlFromRequest(req);
const captionTrackXml = await getCaptionTrackXml(captionTrackUrl);
return captionTrackXml;
}

function getCaptionUrlFromRequest(req: any): string {
const videoQuery = getDecodedVideoQuery(req.query['data']);
const translation = getTranslationParam(req.query['tlang']);

if (!videoQuery) {
throw new functions.https.HttpsError(
'invalid-argument',
"Missing parameter 'data'."
);
throw { code: 400, message: "Missing parameter 'data'." };
}

const captionTrackUrl = createCaptionTrackUrl(videoQuery, translation);
return captionTrackUrl;
}

function getDecodedVideoQuery(data: string | undefined): string | undefined {
return data ? base64url.decode(data) : undefined;
try {
return !!data ? base64url.decode(data) : undefined;
} catch (error) {
throw { code: 500, message: 'Could not decode requested video.' };
}
}

function getTranslationParam(tlang: string | undefined): string {
return tlang ? `&tlang=${tlang}` : '';
return !!tlang ? `&tlang=${tlang}` : '';
}

function createCaptionTrackUrl(videoQuery: string, translation: string) {
Expand All @@ -54,27 +63,10 @@ async function getReadableStreamFromUrl(
): Promise<NodeJS.ReadableStream> {
try {
let response = await fetch(location);
return getReadableFromResponse(response);
let readableStream = getReadableFromResponse(response);
return readableStream;
} catch (error) {
switch (error.code) {
case 400:
throw new functions.https.HttpsError(
'invalid-argument',
'A bad request was made to YouTube.'
);
case 403:
throw new functions.https.HttpsError(
'permission-denied',
`Access to YouTube was denied.`
);
case 404:
throw new functions.https.HttpsError(
'not-found',
`The YouTube video doesn't exist.`
);
default:
throw new functions.https.HttpsError('internal', 'An error occurred.');
}
throw error;
}
}

Expand All @@ -93,10 +85,10 @@ async function getRawTranscriptFromStream(
try {
return await getDataFromStream(stream);
} catch (error) {
throw new functions.https.HttpsError(
'internal',
"Couldn't download transcript. Try again later."
);
throw {
code: 500,
message: "Couldn't download transcript. Try again later.",
};
}
}

Expand All @@ -113,10 +105,10 @@ function getDataFromStream(stream: NodeJS.ReadableStream): Promise<any> {
async function parseTranscriptXml(unparsedXml: string): Promise<string> {
let parsedXml = await parseXmlString(unparsedXml);
if (!parsedXml) {
throw new functions.https.HttpsError(
'internal',
'We were unable to parse the transcript.'
);
throw {
code: 500,
message: 'We were unable to create the transcript. Please try again.',
};
}
let transcript = parsedXml.transcript;
return transcript;
Expand All @@ -126,9 +118,41 @@ async function parseXmlString(unparsedXml: string): Promise<any> {
try {
return await parseStringPromise(unparsedXml);
} catch (error) {
throw new functions.https.HttpsError(
'internal',
'Could not load transcript.'
);
throw {
code: 500,
message: 'Could not load the transcript.',
context: error,
};
}
}

function respondWithCaptionTrack(
res: Response,
captionTrack: string
): Response {
return res
.set({ 'Access-Control-Allow-Origin': '*' })
.status(200)
.send(captionTrack);
}

function respondWithError(res: Response, error: any): Response {
res = enableCors(res);
logErrorToConsole(error);

if (error.code) {
return res
.status(error.code)
.json({ error: error.code, error_message: error.message });
}

return res.status(500).json(error);
}

function logErrorToConsole(error: any): void {
console.error(`Error: ${JSON.stringify(error)}`);
}

function enableCors(res: Response): Response {
return res.set({ 'Access-Control-Allow-Origin': '*' });
}
5 changes: 2 additions & 3 deletions src/app/stylish-url/stylish-url.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,8 @@ export class StylishUrlComponent implements ControlValueAccessor, OnInit {

// Input and output variables for the captionsList binding
@Input('captionsList') captionsList: CaptionsList;
@Output('captionsListChange') captionsListChange = new EventEmitter<
CaptionsList
>();
@Output('captionsListChange') captionsListChange =
new EventEmitter<CaptionsList>();

// Input and output variables for the url binding
@Input('url') url: string;
Expand Down
24 changes: 18 additions & 6 deletions src/app/transcrypt.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class TranscryptService {
try {
return await this.get(GET_CAPTION_LIST_URL, { videoId }).toPromise();
} catch (error) {
throw error.error;
throw { message: error.error.error_message };
}
}

Expand All @@ -73,10 +73,7 @@ export class TranscryptService {
translationLanguage: string
): Promise<Transcripts> {
try {
return await this.get(GET_CAPTION_TRACK_URL, {
data: encodedBaseUrl,
tlang: translationLanguage,
})
return await this.getCaptionTrack(encodedBaseUrl, translationLanguage)
.pipe(
map((captionTrack) => {
return this.formatCaptionTrack(captionTrack);
Expand All @@ -87,10 +84,25 @@ export class TranscryptService {
if (error.error.error_message) {
throw { message: error.error.error_message };
}
throw { message: error.message };
throw { message: JSON.stringify(error) };
}
}

private getCaptionTrack(data: string, tlang: string): Observable<any> {
let params: any;
if (tlang) {
params = {
data,
tlang,
};
} else {
params = {
data,
};
}
return this.get(GET_CAPTION_TRACK_URL, params);
}

private formatCaptionTrack(captionTrack: any): Transcripts {
try {
let transcriptNoTimestamps = this.formatTranscript(captionTrack, false);
Expand Down

0 comments on commit 4ebb670

Please sign in to comment.