Skip to content

Commit

Permalink
Merge pull request #154 from ttsukagoshi/usage
Browse files Browse the repository at this point in the history
Add menu to get DeepL API usage status
  • Loading branch information
ttsukagoshi authored Feb 20, 2024
2 parents df5da86 + d979f99 commit 7110606
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 9 deletions.
70 changes: 61 additions & 9 deletions src/sheetsl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ interface DeepLTranslationObj {
text: string;
}

interface DeepLUsageResponse {
character_count: number;
character_limit: number;
document_limit?: number;
document_count?: number;
team_document_limit?: number;
team_document_count?: number;
}

/**
* The type of language that should be returned in the GET request
* to the DeepL API to retrieve its supported languages.
Expand All @@ -86,16 +95,17 @@ type PropertiesObj = Record<string, string>;
function onOpen(): void {
const ui = SpreadsheetApp.getUi();
ui.createAddonMenu()
.addItem('Translate', 'translateSelectedRange')
.addSeparator()
.addItem('Check usage', 'checkUsage')
.addSubMenu(
ui
.createMenu('Settings')
.addItem('Set DeepL API Key', 'setDeeplApiKey')
.addItem('Delete DeepL API Key', 'deleteDeeplApiKey')
.addItem('Set language', 'setLanguage')
.addSeparator()
.addItem('Set Language', 'setLanguage'),
.addItem('Set DeepL API Key', 'setDeeplApiKey')
.addItem('Delete DeepL API Key', 'deleteDeeplApiKey'),
)
.addSeparator()
.addItem('Translate', 'translateSelectedRange')
.addToUi();
}

Expand Down Expand Up @@ -397,6 +407,23 @@ export function splitLongArray<T>(
return returnArray;
}

/**
* Check the usage of the DeepL API
* and show the result to the user in an alert box.
*/
export function checkUsage(): void {
const ui = SpreadsheetApp.getUi();
try {
const usage = deepLGetUsage();
ui.alert(
`[${ADDON_NAME}] DeepL API Usage Status:\n\nYou are currently using ${usage.character_count} characters out of ${usage.character_limit} characters (${Math.round((10 * 100 * usage.character_count) / usage.character_limit) / 10}%).`,
);
} catch (error) {
console.error((error as Error).stack);
ui.alert((error as Error).message);
}
}

/**
* Call the DeepL API on the `translate` endpoint
* @param sourceText Array of texts to translate
Expand Down Expand Up @@ -472,14 +499,39 @@ export function deepLGetLanguages(
const apiKey = getDeepLApiKey();
const baseUrl = getDeepLApiBaseUrl(apiKey);
// Call the DeepL API
const url = baseUrl + endpoint + `?auth_key=${apiKey}&type=${type}`;
const response = handleDeepLErrors(
UrlFetchApp.fetch(url, { muteHttpExceptions: true }),
);
const url = baseUrl + endpoint + `?type=${type}`;
const options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
method: 'get',
headers: { Authorization: `DeepL-Auth-Key ${apiKey}` },
muteHttpExceptions: true,
};
const response = handleDeepLErrors(UrlFetchApp.fetch(url, options));

return JSON.parse(response.getContentText()) as DeepLSupportedLanguages[];
}

/**
* Retrieve the usage of the DeepL API.
* @returns The usage of the DeepL API.
* @see https://www.deepl.com/docs-api/general/get-usage
*/
export function deepLGetUsage(): DeepLUsageResponse {
const endpoint = 'usage';
// API key
const apiKey = getDeepLApiKey();
const baseUrl = getDeepLApiBaseUrl(apiKey);
// Call the DeepL API
const options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
method: 'get',
headers: { Authorization: `DeepL-Auth-Key ${apiKey}` },
muteHttpExceptions: true,
};
const response = handleDeepLErrors(
UrlFetchApp.fetch(baseUrl + endpoint, options),
);
return JSON.parse(response.getContentText()) as DeepLUsageResponse;
}

/**
* Get the length of a given string in bytes.
* @param text The string of which to get the bytes.
Expand Down
51 changes: 51 additions & 0 deletions tests/checkUsage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { checkUsage } from '../src/sheetsl';

describe('checkUsage', () => {
beforeEach(() => {
// eslint-disable-next-line @typescript-eslint/no-empty-function
jest.spyOn(console, 'error').mockImplementation(() => {});
global.PropertiesService = {
getUserProperties: jest.fn(() => ({
getProperty: jest.fn(() => 'SampleApiKey'),
})),
} as unknown as GoogleAppsScript.Properties.PropertiesService;
global.SpreadsheetApp = {
getUi: jest.fn(() => ({
alert: jest.fn(),
})),
} as unknown as GoogleAppsScript.Spreadsheet.SpreadsheetApp;
});
afterEach(() => {
jest.clearAllMocks();
});
it('should check usage without errors', () => {
global.UrlFetchApp = {
fetch: jest.fn(() => ({
getContentText: jest.fn(() =>
JSON.stringify({
character_count: 10,
character_limit: 50,
}),
),
getResponseCode: jest.fn(() => 200), // Mock a successful response
})),
} as unknown as GoogleAppsScript.URL_Fetch.UrlFetchApp;
checkUsage();
expect(console.error).not.toHaveBeenCalled();
});
it('should catch an error', () => {
global.UrlFetchApp = {
fetch: jest.fn(() => ({
getContentText: jest.fn(() =>
JSON.stringify({
character_count: 10,
character_limit: 50,
}),
),
getResponseCode: jest.fn(() => 500), // Mock an unsuccessful response
})),
} as unknown as GoogleAppsScript.URL_Fetch.UrlFetchApp;
checkUsage();
expect(console.error).toHaveBeenCalled();
});
});
32 changes: 32 additions & 0 deletions tests/deepLGetUsage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { deepLGetUsage } from '../src/sheetsl';

describe('deepLGetUsage', () => {
beforeEach(() => {
global.PropertiesService = {
getUserProperties: jest.fn(() => ({
getProperty: jest.fn(() => 'SampleApiKey'),
})),
} as unknown as GoogleAppsScript.Properties.PropertiesService;
});
afterEach(() => {
jest.clearAllMocks();
});
it('should get usage', () => {
global.UrlFetchApp = {
fetch: jest.fn(() => ({
getContentText: jest.fn(() =>
JSON.stringify({
character_count: 10,
character_limit: 50,
}),
),
getResponseCode: jest.fn(() => 200), // Mock a successful response
})),
} as unknown as GoogleAppsScript.URL_Fetch.UrlFetchApp;
const usage = deepLGetUsage();
expect(usage).toEqual({
character_count: 10,
character_limit: 50,
});
});
});

0 comments on commit 7110606

Please sign in to comment.