UNPKG

silverdiamond

Version:

JS wrapper for Silver Diamond Artificial Intelligence service

663 lines (585 loc) 18 kB
const fetch = require('node-fetch') const Language = { Spanish: 'es', English: 'en', German: 'de', French: 'fr', Portuguese: 'pt', Italian: 'it', Dutch: 'nl', Polish: 'pl', Russian: 'ru' } const Sentiment = { VeryPositive: 'Very positive', Positive: 'Positive', Neutral: 'Neutral', Negative: 'Negative', VeryNegative: 'Very negative' } const Readability = { VeryEasy: 'Very Easy', Easy: 'Easy', FairlyEasy: 'Fairly Easy', Standard: 'Standard', FairlyDifficult: 'Fairly Difficult', Difficult: 'Difficult', VeryDifficult: 'Very Difficult' } class Client { constructor (apiKey) { this.apiKey = apiKey this.base = 'https://api.silverdiamond.io/v1/service/' } request (endpoint, data) { endpoint = endpoint.replace(/^\/+|\/+$/g, '') return new Promise((resolve, reject) => { fetch(this.base + endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer ' + this.apiKey }, body: JSON.stringify(data) }) .then(response => response.json()) .then(response => { if (response.message || response.error) { return reject(new Error(response.message || response.error)) } resolve(response) }) .catch(error => reject(error)) }) } } class SilverDiamond { /** * Initializes a Silver Diamond instance * @param {string} apiKey */ constructor (apiKey) { if (!apiKey) { throw new Error('No API Key was provided') } this._apiKey = apiKey this.client = new Client(apiKey) } /** * Returns the iso code of the detected `text` language * @param {string} text */ language (text) { text = this._normalizeText(text) return new Promise((resolve, reject) => { this.client.request('language-detection', { text: text }) .then(response => { if (!response.language) { return reject(new Error('Unknown error')) } resolve(response.language) }) .catch(error => reject(error)) }) } /** * Returns true if the discovered language is included in `isoCodes` * * @param {string} text * @param {string|array} isoCodes */ languageIs (text, isoCodes) { if (typeof isoCodes === 'string') { isoCodes = [isoCodes] } if (!Array.isArray(isoCodes)) { throw new Error('ISO Codes must be a string or an array') } isoCodes = isoCodes.map(code => code.trim().toLowerCase()) return new Promise((resolve, reject) => { this.language(text) .then(language => resolve(isoCodes.includes(language.toLowerCase()))) .catch(error => reject(error)) }) } /** * Returns true if the discovered language is Spanish * * @param {string} text */ languageIsSpanish (text) { return this.languageIs(text, [Language.Spanish]) } /** * Returns true if the discovered language is English * * @param {string} text */ languageIsEnglish (text) { return this.languageIs(text, [Language.English]) } /** * Returns true if the discovered language is German * * @param {string} text */ languageIsGerman (text) { return this.languageIs(text, [Language.German]) } /** * Returns true if the discovered language is French * * @param {string} text */ languageIsFrench (text) { return this.languageIs(text, [Language.French]) } /** * Returns true if the discovered language is Portuguese * * @param {string} text */ languageIsPortuguese (text) { return this.languageIs(text, [Language.Portuguese]) } /** * Returns true if the discovered language is Italian * * @param {string} text */ languageIsItalian (text) { return this.languageIs(text, [Language.Italian]) } /** * Returns true if the discovered language is Dutch * * @param {string} text */ languageIsDutch (text) { return this.languageIs(text, [Language.Dutch]) } /** * Returns true if the discovered language is Polish * * @param {string} text */ languageIsPolish (text) { return this.languageIs(text, [Language.Polish]) } /** * Returns true if the discovered language is Russian * * @param {string} text */ languageIsRussian (text) { return this.languageIs(text, [Language.Russian]) } /** * Returns the overall sentiment detected in `text` * * @param {string} text */ sentiment (text) { text = this._normalizeText(text) return new Promise((resolve, reject) => { this.client.request('sentiment-analysis', { text: text }) .then(response => { if (!response.sentiment) { return reject(new Error('Unknown error')) } resolve(response.sentiment) }) .catch(error => reject(error)) }) } /** * Returns true if the text sentiment is included in `sentiments` * * @param {string} text * @param {string|array} sentiments */ sentimentIs (text, sentiments) { if (typeof sentiments === 'string') { sentiments = [sentiments] } if (!Array.isArray(sentiments)) { throw new Error('Sentiments must be a string or an array') } sentiments = sentiments.map(sentiment => sentiment.trim().toLowerCase()) return new Promise((resolve, reject) => { this.sentiment(text) .then(sentiment => resolve(sentiments.includes(sentiment.toLowerCase()))) .catch(error => reject(error)) }) } /** * Returns true if the text sentiment is classified as *Positive* or *Very positive* * * @param {string} text */ sentimentIsPositive (text) { return this.sentimentIs(text, [Sentiment.Positive, Sentiment.VeryPositive]) } /** * Returns true if the text sentiment is classified as *Neutral* * * @param {string} text */ sentimentIsNeutral (text) { return this.sentimentIs(text, [Sentiment.Neutral]) } /** * Returns true if the text sentiment is classified as *Negative* or *Very negative* * * @param {string} text */ sentimentIsNegative (text) { return this.sentimentIs(text, [Sentiment.Negative, Sentiment.VeryNegative]) } /** * Performs a spam detection API call and returns the response * * @param {string} text * @param {string} ip */ spam (text, ip) { const data = { text: text } if (ip) { data.ip = ip } return new Promise((resolve, reject) => { this.client.request('spam-detection', data) .then(response => { if (!response.hasOwnProperty('spam') || !response.hasOwnProperty('ham')) { return reject('Unknown error') } resolve(response) }) .catch(error => reject(error)) }) } /** * Returns true if the provided text [and the IP Address] are classified as SPAM * * @param {string} text * @param {string} ip */ isSpam (text, ip) { return this.spam(text, ip) .then(response => !!response.spam) } /** * Returns true if the provided text [and the IP Address] are classified as HAM * * @param {string} text * @param {string} ip */ isHam (text, ip) { return this.spam(text, ip) .then(response => !!response.ham) } /** * Returns the spam score of a certain text [and IP Address] between 0 and 10. Higher means more spam probability * * @param {string} text * @param {string} ip */ spamScore (text, ip) { return this.spam(text, ip) .then(response => parseFloat(response.spamScore) || 0.0) } /** * Returns the similarity of two texts between 0 and 1. Higher means more similar * * @param {string} text1 * @param {string} text2 */ similarity (text1, text2) { text1 = this._normalizeText(text1) text2 = this._normalizeText(text2) const data = { texts: [text1, text2] } return new Promise((resolve, reject) => { this.client.request('short-text-similarity', data) .then(response => { if (!response.hasOwnProperty('similarity')) { return reject(new Error('Unknown error')) } resolve(response.similarity) }) .catch(error => reject(error)) }) } /** * Returns a list of keywords extracted from the text * * @param {string} text */ textRankKeywords (text) { text = this._normalizeText(text) const data = { text: text } return new Promise((resolve, reject) => { this.client.request('text-rank-keywords', data) .then(response => { if (!response.hasOwnProperty('keywords') || !Array.isArray(response.keywords)) { return reject(new Error('Unknown error')) } resolve(response.keywords) }) .catch(error => reject(error)) }) } /** * Returns a list of keywords extracted from the text * * @param {string} text */ textRankSummary (text) { text = this._normalizeText(text) const data = { text: text } return new Promise((resolve, reject) => { this.client.request('text-rank-summary', data) .then(response => { if (!response.hasOwnProperty('summary')) { return reject(new Error('Unknown error')) } resolve(response.summary) }) .catch(error => reject(error)) }) } /** * Translates text into `targetLang`, optionally specifying `sourceLang` * * @param {string} text * @param {string} targetLang * @param {string} sourceLang */ translate (text, targetLang, sourceLang) { text = this._normalizeText(text) const data = { text: text, target_lang: targetLang } if (sourceLang) { data.source_lang = sourceLang } return new Promise((resolve, reject) => { this.client.request('translation', data) .then(response => { if (!response.translation) { return reject(new Error('Unknown error')) } resolve(response.translation) }) .catch(error => reject(error)) }) } /** * Returns the readability and readability scores of the provided `text` written in `lang` * @param {string} text * @param {string} lang */ readability (text, lang = 'en') { text = this._normalizeText(text) const data = { text: text, lang: lang } return new Promise((resolve, reject) => { this.client.request('text-readability', data) .then(response => { if (!response.hasOwnProperty('score') || !response.hasOwnProperty('readability')) { return reject(new Error('Unknown error')) } resolve(response) }) .catch(reject) }) } /** * Returns a `Readability` value for the provided `text` written in `lang` * * @param {string} text * @param {string} lang */ readabilityCategory (text, lang = 'en') { return this.readability(text, lang) .then(readability => readability.readability) } /** * Returns the readability score for the provided `text` written in `lang` * * @param {string} text * @param {string} lang */ readabilityScore (text, lang = 'en') { return this.readability(text, lang) .then(readability => readability.score) } /** * Returns true if the readability of the provided `text` written in `lang` is in `readabilities` * * @param {string} text * @param {string} lang * @param {array} readabilities */ readabilityIs (text, lang = 'en', readabilities = []) { return this.readabilityCategory(text, lang) .then(readability => readabilities.includes(readability)) } /** * Returns true if the given `text` written in `lang` is considered as readable * * @param {string} text * @param {string} lang */ isReadable (text, lang = 'en') { return this.readabilityIs(text, lang, [ Readability.VeryEasy, Readability.Easy, Readability.FairlyEasy, Readability.Standard ]) } /** * Returns true if the given `text` written in `lang` is considered as not readable * * @param {string} text * @param {string} lang */ isNotReadable (text, lang = 'en') { return this.readabilityIs(text, lang, [ Readability.VeryDifficult, Readability.Difficult, Readability.FairlyDifficult ]) } /** * Generates an alt description for the given `imageUrl` written in `lang` * * @param {string} imageUrl * @param {string} lang */ describeImage (imageUrl, lang = 'en') { const data = { image_url: imageUrl, lang: lang } return new Promise((resolve, reject) => { this.client.request('image-alt-detection', data) .then(response => { if (!response.hasOwnProperty('alt') || !response.hasOwnProperty('confidence')) { return reject(new Error('Unknown error')) } resolve(response) }) .catch(reject) }) } /** * Returns the BERT Score for a given URL and Keyword. * * BERT Score represents, from 0 to 100, how well the content of your URL * answers the user's search intent. * * @param {string} url * @param {string} keyword */ bertScore (url, keyword) { const data = { url: url, keyword: keyword } return new Promise((resolve, reject) => { this.client.request('bert-score', data) .then(response => { if (!response.hasOwnProperty('bert_score')) { return reject(new Error('Unknown error')) } resolve(response['bert_score']) }) .catch(reject) }) } /** * Returns the detected objects inside $imageUrl * * @param {string} imageUrl */ recognizeObjects (imageUrl) { const data = { image_url: imageUrl } return new Promise((resolve, reject) => { this.client.request('image-object-recognition', data) .then(response => { if (!response.hasOwnProperty('objects')) { return reject(new Error('Unknown error')) } resolve(response['objects']) }) .catch(reject) }) } /** * Runs a nudity detection analysis * * @param {string} imageUrl */ nudityDetection (imageUrl) { const data = { image_url: imageUrl } return new Promise((resolve, reject) => { this.client.request('nudity-detection', data) .then(response => { if (!response.hasOwnProperty('has_nudity')) { return reject(new Error('Unknown error')) } resolve(response) }) .catch(reject) }) } /** * Checks if the given image contains nudity. * * @param {string} imageUrl */ hasNudity (imageUrl) { return this.nudityDetection(imageUrl) .then(response => response.has_nudity) } /** * Returns the probability of the given image containing nudity. * * @param {string} imageUrl */ nudityProbability (imageUrl) { return this.nudityDetection(imageUrl) .then(response => response.probability) } _normalizeText (text) { if (typeof text !== 'string') { throw new Error('Text must be a string') } text = text.trim() if (text.length === 0) { throw new Error('Text must not be empty') } return text } } module.exports = { Api: SilverDiamond, Language: Language, Sentiment: Sentiment, Readability: Readability }