UNPKG

ringcentral-widgets

Version:
399 lines (354 loc) 10.8 kB
import formatMessage from 'format-message'; import { RcVDialInNumberObj } from 'ringcentral-integration/interfaces/Rcv.model'; import { MEETING_URI_REGEXP, rcvAttTeleconference, rcvTeleconference, } from './config'; import { formatMeetingId } from './formatMeetingId'; import i18n from './i18n'; import { CommonBrand, FormatToHtmlOptions, RcmMainParams, RcvMainParams, TplResult, } from './index.interface'; function formatSmartphones( dialInNumber: string | RcVDialInNumberObj[], pinNumber: string, showMeetingPasswordPSTN: boolean, meetingPasswordPSTN: string, ) { if (!dialInNumber || dialInNumber.length === 0) { return ''; } if (typeof dialInNumber === 'string') { return `${dialInNumber},,${pinNumber}#${ showMeetingPasswordPSTN ? `,,${meetingPasswordPSTN}#` : '' }`; } return dialInNumber .map((obj) => { const passwordField = showMeetingPasswordPSTN ? `,,${meetingPasswordPSTN}#` : ''; const locationField = obj?.country?.name && obj.location ? `${obj.country.name} (${obj.location})` : obj?.country?.name || ''; return `${obj.phoneNumber},,${pinNumber}#${passwordField} ${locationField}`; }) .join('\n\t'); } function formatDialInNumber(dialInNumber: string | RcVDialInNumberObj[]) { if (!dialInNumber || dialInNumber.length === 0) { return ''; } if (typeof dialInNumber === 'string') { return dialInNumber; } return dialInNumber .map((obj) => { const locationField = obj?.country?.name && obj.location ? `${obj.country.name} (${obj.location})` : obj?.country?.name || ''; return `${obj.phoneNumber} ${locationField}`; }) .join('\n\t'); } function getPasswordTpl( meetingPassword: string, currentLocale: string, ): string { const passwordLiteral = i18n.getString('password', currentLocale); return meetingPassword ? `${passwordLiteral}: ${meetingPassword}` : ''; } /** * replace all text link into anchor link * Should match: http://www.example.com * Should not match: <a href="http://www.example.com">http://www.example.com </a> * Then replace it into <a href="http://www.example.com">http://www.example.com </a> * @param input */ function replaceTextLinksToAnchors(input: string): string { /** * [^<>\]]+ means should match any characters except < or > or ] * (?!\s*<\/a>) means url should not be followed by either "</a>" or " </a>" * (?!"[^>]*>) means url should not followed by "> * further explanation: origin string: <a href="http://www.example.com">http://www.example.com </a> should not match * (?=[\s!,?\]]|$) means url can be followed by punctuations or whitespace or nothing */ // https://stackoverflow.com/questions/19060460/url-replace-with-anchor-not-replacing-existing-anchors const pattern: RegExp = /(?:(?:ht|f)tps?:\/\/|www)[^<>\]]+(?!\s*<\/a>)(?!"[^>]*>)(?=[\s!,?\]<]|$)/gim; return input.replace(pattern, ($0: string): string => { return `<a target="_blank" href="${$0}">${$0}</a>`; }); } const htmlNewLine: string = '<br>'; const htmlIndentation: string = '&nbsp;'; const htmlTabIndentation: string = htmlIndentation.repeat(4); function formatTextToHtml( plantText: string, options: FormatToHtmlOptions = {}, ): string { const { links = [], searchLinks = false, newLine = htmlNewLine, indentation = htmlIndentation, tabIndentation = htmlTabIndentation, } = options; let htmlContent = plantText .replace(/\r\n|\n|\r/g, '\n') // formalize newline .split('\n') // split with formalized newline .map((line) => { return line .replace(/\t/g, tabIndentation) // replace all Tab with 4 indentations .replace(/^\s*/, ($0) => indentation.repeat($0.length)); // replace leading whtespaces with indentations }) .join(newLine); links.forEach((uri) => { if (uri) { htmlContent = htmlContent.replace( uri, `<a target="_blank" href="${uri}">${uri}</a>`, ); } }); if (searchLinks) { htmlContent = replaceTextLinksToAnchors(htmlContent); } return htmlContent; } /** * Dial-in password: ${passwordPstn} */ function getRcvPstnPasswordTpl( meetingPasswordPSTN: string, currentLocale: string, ): string { const passwordPstnLiteral = i18n.getString('passwordPstn', currentLocale); return `${passwordPstnLiteral} ${meetingPasswordPSTN}`; } function getBaseRcmTpl( { meeting, serviceInfo, extensionInfo, invitationInfo }: RcmMainParams, brand: CommonBrand, currentLocale: string, ): TplResult { const accountName = extensionInfo.name; const meetingId = meeting.id; const joinUri = meeting.links.joinUri; const password = meeting.password; const mobileDialingNumberTpl = serviceInfo.mobileDialingNumberTpl; const phoneDialingNumberTpl = serviceInfo.phoneDialingNumberTpl; const passwordTpl = getPasswordTpl(password, currentLocale); const teleconference = brand.brandConfig.teleconference; let formattedMsg = invitationInfo?.invitation; if (!formattedMsg) { formattedMsg = formatMessage( i18n.getString('inviteMeetingContent', currentLocale), { accountName, brandName: i18n.getString(brand.name), joinUri, passwordTpl, mobileDialingNumberTpl, phoneDialingNumberTpl, meetingId: formatMeetingId(meetingId), teleconference, }, ); } return { formattedMsg, links: { joinUri, teleconference, }, }; } function getRcmEventTpl( mainInfo: RcmMainParams, brand: CommonBrand, currentLocale: string, ): string { const tplResult = getBaseRcmTpl(mainInfo, brand, currentLocale); return tplResult.formattedMsg; } function getRcmHtmlEventTpl( mainInfo: RcmMainParams, brand: CommonBrand, currentLocale: string, ): string { const tplResult = getBaseRcmTpl(mainInfo, brand, currentLocale); return formatTextToHtml(tplResult.formattedMsg, { links: [tplResult.links.joinUri, tplResult.links.teleconference], }); } function getBaseRcvTpl( { meeting, extensionInfo, dialInNumber, invitationInfo }: RcvMainParams, brand: CommonBrand, currentLocale: string, enableRcvConnector = false, ): TplResult { const joinUri = meeting.joinUri; const isATT = brand.code === 'att'; const teleconference = isATT ? rcvAttTeleconference : rcvTeleconference; if (invitationInfo?.body) { return { formattedMsg: invitationInfo.body, links: { joinUri, teleconference, }, }; } const accountName = extensionInfo.name; const { meetingPassword, meetingPasswordPSTN, isMeetingSecret } = meeting; let productName; const meetingContent: Array<string> = []; const showMeetingPasswordPSTN = !!(isMeetingSecret && meetingPasswordPSTN); if (brand.name === 'RingCentral') { productName = 'RingCentral Video'; meetingContent.push( i18n.getString('rcvRCBrandInviteMeetingContent', currentLocale), ); } else { productName = brand.name; meetingContent.push( i18n.getString('rcvInviteMeetingContent', currentLocale), ); } if (dialInNumber && dialInNumber.length > 0) { /* TODO: after get the translation, remove rcvInviteMeetingContentDial * rcvInviteMeetingContentCountryDial is the correct one */ meetingContent.push( i18n.getString( typeof dialInNumber === 'string' ? 'rcvInviteMeetingContentDial' : 'rcvInviteMeetingContentCountryDial', currentLocale, ), ); if (showMeetingPasswordPSTN) { meetingContent.push( getRcvPstnPasswordTpl(meetingPasswordPSTN, currentLocale), ); } } meetingContent.push(`${i18n.getString('rcvTeleconference', currentLocale)}`); const passwordTpl = isMeetingSecret ? getPasswordTpl(meetingPassword, currentLocale) : ''; if (enableRcvConnector) { meetingContent.push(`${i18n.getString('rcvSipHeader', currentLocale)}`); const rcvSipContent = isMeetingSecret ? 'rcvSipContentWithPwd' : 'rcvSipContentNoPwd'; meetingContent.push(`${i18n.getString(rcvSipContent, currentLocale)}`); } const shortId = meeting.shortId; const meetingId = meeting.id; const formattedMsg = formatMessage(meetingContent.join(''), { accountName, brandName: isATT ? `AT&T ${brand.name}` : i18n.getString(brand.name), joinUri, passwordTpl, meetingPasswordPSTN, meetingId, pinNumber: formatMeetingId(meeting.shortId), teleconference, productName, dialNumber: formatDialInNumber(dialInNumber), smartphones: formatSmartphones( dialInNumber, shortId, showMeetingPasswordPSTN, meetingPasswordPSTN, ), }); return { formattedMsg, links: { joinUri, teleconference, }, }; } function getRcvEventTpl( mainInfo: RcvMainParams, brand: CommonBrand, currentLocale: string, enableRcvConnector = false, ): string { const tplResult = getBaseRcvTpl( mainInfo, brand, currentLocale, enableRcvConnector, ); return tplResult.formattedMsg; } function getRcvHtmlEventTpl( mainInfo: RcvMainParams, brand: CommonBrand, currentLocale: string, ): string { const tplResult = getBaseRcvTpl(mainInfo, brand, currentLocale); return formatTextToHtml(tplResult.formattedMsg, { links: [tplResult.links.joinUri, tplResult.links.teleconference], }); } function getMeetingId(meetingUri: string): string { if (meetingUri) { const regs = [MEETING_URI_REGEXP.RCM, MEETING_URI_REGEXP.RCV]; for (let i = 0; i < regs.length; i += 1) { const matches = regs[i].exec(meetingUri); if (matches && matches.length > 0) { const match0 = matches[0]; const link = (match0.indexOf('?') > -1 ? matches[0].substring(0, matches[0].indexOf('?')) : match0 ).split('/'); const id = link[link.length - 1]; return id; } } } return null; } function stripMeetingLinks(text: string): string { let result = text; [MEETING_URI_REGEXP.RCM, MEETING_URI_REGEXP.RCV].forEach((reg) => { while (reg.test(result)) { result = result.replace(reg, ''); } }); return result; } function meetingLinkContains( text?: string, ): { hasRCM: boolean; hasRCV: boolean } { return { hasRCM: MEETING_URI_REGEXP.RCM.test(text ?? ''), hasRCV: MEETING_URI_REGEXP.RCV.test(text ?? ''), }; } export { formatMeetingId, stripMeetingLinks, meetingLinkContains, replaceTextLinksToAnchors, htmlNewLine, htmlIndentation, htmlTabIndentation, formatTextToHtml, getRcmEventTpl, getRcmHtmlEventTpl, getRcvEventTpl, getRcvHtmlEventTpl, getMeetingId, };