feat: enhance typing + remove unused translations

This commit is contained in:
Mohamed Marrouchi 2024-10-19 09:17:51 +01:00
parent a8030378ca
commit 8d846186cc
10 changed files with 95 additions and 205 deletions

View File

@ -56,7 +56,7 @@ export default abstract class ChannelHandler<N extends string = string> {
}
protected getGroup() {
return this.getChannel().replaceAll('-', '_');
return this.getChannel().replaceAll('-', '_') as ChannelSetting<N>['group'];
}
async setup() {
@ -92,9 +92,10 @@ export default abstract class ChannelHandler<N extends string = string> {
* Returns the channel's settings
* @returns Channel's settings
*/
async getSettings() {
async getSettings<S extends string = HyphenToUnderscore<N>>() {
const settings = await this.settingService.getSettings();
return settings[this.getGroup()];
// @ts-expect-error workaround typing
return settings[this.getGroup() as keyof Settings] as Settings[S];
}
/**

View File

@ -28,7 +28,6 @@ import type {
NlpValueDocument,
} from '@/nlp/schemas/nlp-value.schema';
import { type Setting } from '@/setting/schemas/setting.schema';
import type { CheckboxSetting, TextSetting } from '@/setting/schemas/types';
import { type Invitation } from '@/user/schemas/invitation.schema';
import { type Model } from '@/user/schemas/model.schema';
import { type Permission } from '@/user/schemas/permission.schema';
@ -48,17 +47,7 @@ declare module '@nestjs/event-emitter' {
operations: O;
}
interface IHookExtensionsOperationMap {
messenger: TDefinition<
object,
{
get_started_button: Setting;
access_token: Setting;
composer_input_disabled: CheckboxSetting;
greeting_text: TextSetting;
}
>;
}
interface IHookExtensionsOperationMap {}
interface IHookSettingsGroupLabelOperationMap {
chatbot_settings: TDefinition<

View File

@ -9,10 +9,10 @@ declare global {
}
declare module '@nestjs/event-emitter' {
interface IHookSettingsGroupLabelOperationMap {
interface IHookExtensionsOperationMap {
[LIVE_CHAT_TEST_GROUP_NAME]: TDefinition<
object,
SettingObject<typeof DEFAULT_LIVE_CHAT_TEST_SETTINGS>
SettingMapByType<typeof DEFAULT_LIVE_CHAT_TEST_SETTINGS>
>;
}
}

View File

@ -91,4 +91,4 @@ export const DEFAULT_LIVE_CHAT_TEST_SETTINGS = [
'audio/mpeg,audio/x-ms-wma,audio/vnd.rn-realaudio,audio/x-wav,image/gif,image/jpeg,image/png,image/tiff,image/vnd.microsoft.icon,image/vnd.djvu,image/svg+xml,text/css,text/csv,text/html,text/plain,text/xml,video/mpeg,video/mp4,video/quicktime,video/x-ms-wmv,video/x-msvideo,video/x-flv,video/web,application/msword,application/vnd.ms-powerpoint,application/pdf,application/vnd.ms-excel,application/vnd.oasis.opendocument.presentation,application/vnd.oasis.opendocument.tex,application/vnd.oasis.opendocument.spreadsheet,application/vnd.oasis.opendocument.graphics,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.openxmlformats-officedocument.wordprocessingml.document',
type: SettingType.textarea,
},
] as const satisfies ChannelSetting[];
] as const satisfies ChannelSetting<typeof LIVE_CHAT_TEST_CHANNEL_NAME>[];

View File

@ -59,6 +59,7 @@ import { SocketRequest } from '@/websocket/utils/socket-request';
import { SocketResponse } from '@/websocket/utils/socket-response';
import { WebsocketGateway } from '@/websocket/websocket.gateway';
import { OFFLINE_GROUP_NAME } from './settings';
import { Offline } from './types';
import OfflineEventWrapper from './wrapper';
@ -90,7 +91,7 @@ export default class BaseWebChannelHandler<
* @returns -
*/
init(): void {
this.logger.debug('Offline Channel Handler : initialization ...');
this.logger.debug('Web Channel Handler : initialization ...');
}
/**
@ -111,21 +112,21 @@ export default class BaseWebChannelHandler<
await this.verifyToken(verification_token.toString());
try {
this.logger.debug(
'Offline Channel Handler : WS connected .. sending settings',
'Web Channel Handler : WS connected .. sending settings',
);
try {
const menu = await this.menuService.getTree();
return client.emit('settings', { menu, ...settings });
} catch (err) {
this.logger.warn(
'Offline Channel Handler : Unable to retrieve menu ',
'Web Channel Handler : Unable to retrieve menu ',
err,
);
return client.emit('settings', settings);
}
} catch (err) {
this.logger.warn(
'Offline Channel Handler : Unable to verify token, disconnecting ...',
'Web Channel Handler : Unable to verify token, disconnecting ...',
err,
);
client.disconnect();
@ -133,7 +134,7 @@ export default class BaseWebChannelHandler<
}
} catch (err) {
this.logger.error(
'Offline Channel Handler : Unable to initiate websocket connection',
'Web Channel Handler : Unable to initiate websocket connection',
err,
);
}
@ -300,7 +301,8 @@ export default class BaseWebChannelHandler<
* @param verificationToken - Verification Token
*/
private async verifyToken(verificationToken: string) {
const settings = await this.getSettings();
const settings =
(await this.getSettings()) as Settings[typeof OFFLINE_GROUP_NAME];
const verifyToken = settings.verification_token;
if (!verifyToken) {
@ -313,7 +315,7 @@ export default class BaseWebChannelHandler<
throw new Error('Make sure the validation tokens match.');
}
this.logger.log(
'Offline Channel Handler : Token has been verified successfully!',
'Web Channel Handler : Token has been verified successfully!',
);
}
@ -327,7 +329,7 @@ export default class BaseWebChannelHandler<
req: Request | SocketRequest,
res: Response | SocketResponse,
) {
const settings = await this.getSettings();
const settings = await this.getSettings<typeof OFFLINE_GROUP_NAME>();
// If we have an origin header...
if (req.headers && req.headers.origin) {
// Get the allowed origins
@ -344,7 +346,7 @@ export default class BaseWebChannelHandler<
// interpret as, 'no way Jose.'
res.set('Access-Control-Allow-Origin', '');
this.logger.debug(
'Offline Channel Handler : No origin found ',
'Web Channel Handler : No origin found ',
req.headers.origin,
);
throw new Error('CORS - Domain not allowed!');
@ -362,7 +364,7 @@ export default class BaseWebChannelHandler<
}
return;
}
this.logger.debug('Offline Channel Handler : No origin ', req.headers);
this.logger.debug('Web Channel Handler : No origin ', req.headers);
throw new Error('CORS - No origin provided!');
}
@ -379,23 +381,23 @@ export default class BaseWebChannelHandler<
) {
if (!req.session?.offline?.profile?.id) {
this.logger.warn(
'Offline Channel Handler : No session ID to be found!',
'Web Channel Handler : No session ID to be found!',
req.session,
);
return res
.status(403)
.json({ err: 'Offline Channel Handler : Unauthorized!' });
.json({ err: 'Web Channel Handler : Unauthorized!' });
} else if (
('isSocket' in req && !!req.isSocket !== req.session.offline.isSocket) ||
!Array.isArray(req.session.offline.messageQueue)
) {
this.logger.warn(
'Offline Channel Handler : Mixed channel request or invalid session data!',
'Web Channel Handler : Mixed channel request or invalid session data!',
req.session,
);
return res
.status(403)
.json({ err: 'Offline Channel Handler : Unauthorized!' });
.json({ err: 'Web Channel Handler : Unauthorized!' });
}
next(req.session?.offline?.profile);
}
@ -417,15 +419,12 @@ export default class BaseWebChannelHandler<
'verification_token' in req.query ? req.query : req.body;
await this.verifyToken(verification_token);
} catch (err) {
this.logger.warn(
'Offline Channel Handler : Unable to verify token ',
err,
);
this.logger.warn('Web Channel Handler : Unable to verify token ', err);
throw new Error('Unauthorized, invalid token!');
}
} catch (err) {
this.logger.warn(
'Offline Channel Handler : Attempt to access from an unauthorized origin',
'Web Channel Handler : Attempt to access from an unauthorized origin',
err,
);
throw new Error('Unauthorized, invalid origin !');
@ -504,7 +503,7 @@ export default class BaseWebChannelHandler<
// Polling not authorized when using websockets
if ('isSocket' in req && req.isSocket) {
this.logger.warn(
'Offline Channel Handler : Polling not authorized when using websockets',
'Web Channel Handler : Polling not authorized when using websockets',
);
return res
.status(403)
@ -515,7 +514,7 @@ export default class BaseWebChannelHandler<
!(req.session && req.session.offline && req.session.offline.profile.id)
) {
this.logger.warn(
'Offline Channel Handler : Must be connected to poll messages',
'Web Channel Handler : Must be connected to poll messages',
);
return res
.status(403)
@ -525,7 +524,7 @@ export default class BaseWebChannelHandler<
// Can only request polling once at a time
if (req.session && req.session.offline && req.session.offline.polling) {
this.logger.warn(
'Offline Channel Handler : Poll rejected ... already requested',
'Web Channel Handler : Poll rejected ... already requested',
);
return res
.status(403)
@ -548,7 +547,7 @@ export default class BaseWebChannelHandler<
return res.status(200).json(messages.map((msg) => ['message', msg]));
} else {
this.logger.error(
'Offline Channel Handler : Polling failed .. no session data',
'Web Channel Handler : Polling failed .. no session data',
);
return res.status(500).json({ err: 'No session data' });
}
@ -556,7 +555,7 @@ export default class BaseWebChannelHandler<
if (req.session.offline) {
req.session.offline.polling = false;
}
this.logger.error('Offline Channel Handler : Polling failed', err);
this.logger.error('Web Channel Handler : Polling failed', err);
return res.status(500).json({ err: 'Polling failed' });
}
};
@ -574,7 +573,7 @@ export default class BaseWebChannelHandler<
res: Response | SocketResponse,
) {
this.logger.debug(
'Offline Channel Handler : subscribe (isSocket=' +
'Web Channel Handler : subscribe (isSocket=' +
('isSocket' in req && !!req.isSocket) +
')',
);
@ -586,7 +585,7 @@ export default class BaseWebChannelHandler<
await req.socket.join(profile.foreign_id);
} catch (err) {
this.logger.error(
'Offline Channel Handler : Unable to subscribe via websocket',
'Web Channel Handler : Unable to subscribe via websocket',
err,
);
}
@ -600,7 +599,7 @@ export default class BaseWebChannelHandler<
return res.status(200).json({ profile, messages });
});
} catch (err) {
this.logger.warn('Offline Channel Handler : Unable to subscribe ', err);
this.logger.warn('Web Channel Handler : Unable to subscribe ', err);
return res.status(500).json({ err: 'Unable to subscribe' });
}
}
@ -620,7 +619,7 @@ export default class BaseWebChannelHandler<
) => void,
): Promise<void> {
try {
this.logger.debug('Offline Channel Handler : Successfully uploaded file');
this.logger.debug('Web Channel Handler : Successfully uploaded file');
const attachment = await this.attachmentService.create({
name: upload.name || '',
@ -631,7 +630,7 @@ export default class BaseWebChannelHandler<
});
this.logger.debug(
'Offline Channel Handler : Successfully stored file as attachment',
'Web Channel Handler : Successfully stored file as attachment',
);
next(null, {
@ -640,7 +639,7 @@ export default class BaseWebChannelHandler<
});
} catch (err) {
this.logger.error(
'Offline Channel Handler : Unable to store uploaded file as attachment',
'Web Channel Handler : Unable to store uploaded file as attachment',
err,
);
next(err, false);
@ -664,12 +663,12 @@ export default class BaseWebChannelHandler<
const data: Offline.IncomingMessage = req.body;
// Check if any file is provided
if (!req.session.offline) {
this.logger.debug('Offline Channel Handler : No session provided');
this.logger.debug('Web Channel Handler : No session provided');
return next(null, false);
}
// Check if any file is provided
if (!data || !data.type || data.type !== 'file') {
this.logger.debug('Offline Channel Handler : No files provided');
this.logger.debug('Web Channel Handler : No files provided');
return next(null, false);
}
@ -701,7 +700,7 @@ export default class BaseWebChannelHandler<
this.storeAttachment(upload, sanitizedFilename, next);
} catch (err) {
this.logger.error(
'Offline Channel Handler : Unable to write uploaded file',
'Web Channel Handler : Unable to write uploaded file',
err,
);
return next(new Error('Unable to upload file!'), false);
@ -719,7 +718,7 @@ export default class BaseWebChannelHandler<
upload(req as Request, res as Response, (err) => {
if (err) {
this.logger.error(
'Offline Channel Handler : Unable to write uploaded file',
'Web Channel Handler : Unable to write uploaded file',
err,
);
return next(new Error('Unable to upload file!'), false);
@ -794,12 +793,12 @@ export default class BaseWebChannelHandler<
(err: Error, upload: Offline.IncomingMessageData) => {
if (err) {
this.logger.warn(
'Offline Channel Handler : Unable to upload file ',
'Web Channel Handler : Unable to upload file ',
err,
);
return res
.status(403)
.json({ err: 'Offline Channel Handler : File upload failed!' });
.json({ err: 'Web Channel Handler : File upload failed!' });
}
// Set data in file upload case
if (upload) {
@ -837,7 +836,7 @@ export default class BaseWebChannelHandler<
this.eventEmitter.emit(`hook:chatbot:${type}`, event);
} else {
this.logger.error(
'Offline Channel Handler : Webhook received unknown event ',
'Web Channel Handler : Webhook received unknown event ',
event,
);
}
@ -863,7 +862,7 @@ export default class BaseWebChannelHandler<
switch (req.query._get) {
case 'settings':
this.logger.debug(
'Offline Channel Handler : connected .. sending settings',
'Web Channel Handler : connected .. sending settings',
);
try {
const menu = await this.menuService.getTree();
@ -874,7 +873,7 @@ export default class BaseWebChannelHandler<
});
} catch (err) {
this.logger.warn(
'Offline Channel Handler : Unable to retrieve menu ',
'Web Channel Handler : Unable to retrieve menu ',
err,
);
return res.status(500).json({ err: 'Unable to retrieve menu' });
@ -884,7 +883,7 @@ export default class BaseWebChannelHandler<
return this.getMessageQueue(req, res as Response);
default:
this.logger.error(
'Offline Channel Handler : Webhook received unknown command',
'Web Channel Handler : Webhook received unknown command',
);
return res
.status(500)
@ -902,10 +901,10 @@ export default class BaseWebChannelHandler<
return this._handleEvent(req, res);
}
} catch (err) {
this.logger.warn('Offline Channel Handler : Request check failed', err);
this.logger.warn('Web Channel Handler : Request check failed', err);
return res
.status(403)
.json({ err: 'Offline Channel Handler : Unauthorized!' });
.json({ err: 'Web Channel Handler : Unauthorized!' });
}
}
@ -1103,7 +1102,7 @@ export default class BaseWebChannelHandler<
// Items count min check
if (!data.length) {
this.logger.error(
'Offline Channel Handler : Unsufficient content count (must be >= 0 for list)',
'Web Channel Handler : Unsufficient content count (must be >= 0 for list)',
);
throw new Error('Unsufficient content count (list >= 0)');
}
@ -1152,7 +1151,7 @@ export default class BaseWebChannelHandler<
// Items count min check
if (data.length === 0) {
this.logger.error(
'Offline Channel Handler : Unsufficient content count (must be > 0 for carousel)',
'Web Channel Handler : Unsufficient content count (must be > 0 for carousel)',
);
throw new Error('Unsufficient content count (carousel > 0)');
}
@ -1263,7 +1262,7 @@ export default class BaseWebChannelHandler<
return next();
} catch (err) {
this.logger.error(
'Offline Channel Handler : Failed in sending typing indicator ',
'Web Channel Handler : Failed in sending typing indicator ',
err,
);
}

View File

@ -5,10 +5,10 @@ declare global {
}
declare module '@nestjs/event-emitter' {
interface IHookSettingsGroupLabelOperationMap {
interface IHookExtensionsOperationMap {
[OFFLINE_GROUP_NAME]: TDefinition<
object,
SettingObject<typeof DEFAULT_OFFLINE_SETTINGS>
SettingMapByType<typeof DEFAULT_OFFLINE_SETTINGS>
>;
}
}

View File

@ -1,3 +1,4 @@
import { SettingByType } from './schemas/types';
import { DEFAULT_SETTINGS } from './seeds/setting.seed-model';
declare global {
@ -19,6 +20,12 @@ declare global {
[K in T[number] as K['label']]: TNativeType<K['value']>;
};
type SettingMapByType<
T extends Omit<Setting, 'id' | 'createdAt' | 'updatedAt'>[],
> = {
[K in T[number] as K['label']]: SettingByType<K['type']>;
};
type SettingTree<
T extends Omit<Setting, 'id' | 'createdAt' | 'updatedAt'>[],
> = {

View File

@ -38,6 +38,20 @@ export interface TextSetting extends Setting {
config: never;
}
export interface TextareaSetting extends Setting {
type: SettingType.textarea;
value: string;
options: never;
config: never;
}
export interface SecretSetting extends Setting {
type: SettingType.secret;
value: string;
options: never;
config: never;
}
export interface MultiTextSetting extends Setting {
type: SettingType.multiple_text;
value: string[];
@ -84,6 +98,26 @@ export interface MultipleAttachmentSetting extends Setting {
config: never;
}
export type SettingByType<T extends SettingType> = T extends SettingType.text
? TextSetting
: T extends SettingType.textarea
? TextareaSetting
: T extends SettingType.secret
? SecretSetting
: T extends SettingType.multiple_text
? MultiTextSetting
: T extends SettingType.checkbox
? CheckboxSetting
: T extends SettingType.select
? SelectSetting
: T extends SettingType.number
? NumberSetting
: T extends SettingType.attachment
? AttachmentSetting
: T extends SettingType.multiple_attachment
? MultipleAttachmentSetting
: never;
export type AnySetting =
| TextSetting
| MultiTextSetting

View File

@ -444,51 +444,9 @@
"delete": "Delete",
"role": "Role",
"owner": "Owner",
"app_secret": "Facebook App Secret",
"access_token": "Facebook Page Access Token",
"verify_token": "Webhook Verification Token",
"client_id": "Client ID",
"client_secret": "Client Secret",
"app_id": "ID of the Facebook Application",
"page_id": "ID of the Facebook Page",
"user_fields": "User fields to be retrieved (comma seperated)",
"mode": "Mode",
"mode_options": {
"emulator": "Emulator",
"live": "Live"
},
"get_started_button": "Enable `Get Started` button",
"composer_input_disabled": "Disable composer input",
"greeting_text": "Greeting Text",
"provider": "Provider",
"provider_options": {
"wit": "Wit.ai",
"rasa": "Rasa NLU"
},
"languages": "Available Languages",
"default_lang": "Default Language",
"secret": "Secret",
"verification_token": "Verification Token",
"allowed_domains": "Allowed Domains",
"start_button": "Enable `Get Started`",
"input_disabled": "Disable Input",
"persistent_menu": "Display Persistent Menu",
"greeting_message": "Greeting Message",
"theme_color": "Widget Theme",
"theme_color_options": {
"orange": "Orange",
"red": "Red",
"green": "Green",
"blue": "Blue",
"dark": "Dark"
},
"window_title": "Chat Window Title",
"avatar_url": "Chatbot Avatar URL",
"show_emoji": "Enable Emoji Picker",
"show_file": "Enable Attachment Uploader",
"show_location": "Enable Geolocation Share",
"allowed_upload_size": "Max Upload Size (in bytes)",
"allowed_upload_types": "Allowed Upload Mime Types (comma seperated)",
"channel": "Channel",
"entry": "Entry content",
"thumbnail": "Thumbnail",
@ -619,41 +577,13 @@
"reset": "Forgot your password?"
},
"help": {
"verify_token": "Token that you will returned to Facebook as part of the verification of the Webhook URL.",
"composer_input_disabled": "This means your bot can only be interacted with via the persistent menu, postbacks, buttons, and webviews.",
"get_started_button": "A bot's welcome screen can display a Get Started button. When this button is tapped, the Messenger Platform will send a postback event to your webhook (Payload = `GET_STARTED`).",
"greeting_text": "The greeting property of your bot's Messenger profile allows you to specify the greeting message people will see on the welcome screen of your bot. The welcome screen is displayed for people interacting with your bot for the first time.",
"fallback_message": "If no fallback block is selected, then one of these messages will be sent.",
"app_id": "Mandatory only if you intend to use Facebook Analytics",
"page_id": "Mandatory only if you intend to use Facebook Analytics",
"nlp_train": "You can train your chatbot by adding more examples",
"hit_enter_to_create": "Hit `enter` to create new",
"nlp_precision": "Given an entity, precision is likelihood to make the right prediction.",
"nlp_recall": "Recall is the likelihood to predict an entity out of all entities.",
"nlp_f1score": "The F1 score can be interpreted as a weighted average of the precision and recall",
"nlp_accuracy": "Accuracy score is the proportion of the correctly classified samples.",
"message_tag_shipping_update": "The shipping_update tag may only be used to provide a shipping status notification for a product that has already been purchased. For example, when the product is shipped, in-transit, delivered, or delayed. This tag cannot be used for use cases beyond those listed above or for promotional content (ex: daily deals, coupons and discounts, or sale announcements).",
"message_tag_reservation_update": "The reservation_update tag may only be used to confirm updates to an existing reservation. For example, when there is a change in itinerary, location, or a cancellation (such as when a hotel booking is canceled, a car rental pick-up time changes, or a room upgrade is confirmed). This tag cannot be used for use cases beyond those listed above or for promotional content (ex: daily deals, coupons and discounts, or sale announcements).",
"message_tag_issue_resolution": "The issue_resolution tag may only be used to respond to a customer service issue surfaced in a Messenger conversation after a transaction has taken place. This tag is intended for use cases where the business requires more than 24 hours to resolve an issue and needs to give someone a status update and/or gather additional information. This tag cannot be used for use cases beyond those listed above or for promotional content (ex: daily deals, coupons and discounts, or sale announcements, nor can businesses use the tag to proactively message people to solicit feedback).",
"message_tag_appointment_update": "The appointment_update tag may only be used to provide updates about an existing appointment. For example, when there is a change in time, a location update or a cancellation (such as when a spa treatment is canceled, a real estate agent needs to meet you at a new location or a dental office proposes a new appointment time). This tag cannot be used for use cases beyond those listed above or for promotional content (ex: daily deals, coupons and discounts, or sale announcements).",
"message_tag_game_event": "The game_event tag may only be used to provide an update on user progression, a global event in a game or a live sporting event. For example, when a person\u2019s crops are ready to be collected, their building is finished, their daily tournament is about to start or their favorite soccer team is about to play. This tag cannot be used for use cases beyond those listed above or for promotional content (ex: daily deals, coupons and discounts, or sale announcements).",
"message_tag_transportation_update": "The transportation_update tag may only be used to confirm updates to an existing reservation. For example, when there is a change in status of any flight, train or ferry reservation (such as \u201cride canceled\u201d, \u201ctrip started\u201d or \u201cferry arrived\u201d). This tag cannot be used for use cases beyond those listed above or for promotional content (ex: daily deals, coupons and discounts, or sale announcements).",
"message_tag_feature_functionality_update": "The feature_functionality_update tag may only be used to provide an update on new features or functionality that become available in a bot. For example, announcing the ability to talk to a live agent in a bot, or that the bot has a new skill. This tag cannot be used for use cases beyond those listed above or for promotional content (ex: daily deals, coupons and discounts, or sale announcements).",
"message_tag_ticket_update": "The ticket_update tag may only be used to notify the message recipient of updates or reminders pertaining to an event for which the person has already confirmed attendance. For example, when you want to send a message about a change in time, a location update, a cancellation or a reminder for an upcoming event (such as when a concert is canceled, the venue has changed or a refund opportunity is available). This tag cannot be used for use cases beyond those listed above or for promotional content (ex: daily deals, coupons and discounts, or sale announcements).",
"message_tag_account_update": "The ACCOUNT_UPDATE tag may only be used to confirm updates to a user's account setting. For example, when there is a change in account settings and preferences of a user profile, notification of a password change, or membership expiration. This tag cannot be used for use cases beyond those listed above or for promotional content (ex: promotion for signups, new account creations, or deals to extend subscriptions).",
"message_tag_payment_update": "The PAYMENT_UPDATE tag may be used to provide payment updates to existing transactions. For example, it can be used to send a receipt, out-of-stock, auction ended, refund, or a status change in an existing purchase transaction. This tag cannot be used for use cases beyond those listed above or for promotional content (ex: any cross-sell / up-sell promotions, coupons, or deals to extend subscriptions).",
"message_tag_personal_finance_update": "The PERSONAL_FINANCE_UPDATE tag may be used to confirm a user's financial activity. For example, it can be used to send notifications on bill pay reminders, scheduled payments, receipts of payment, transfer of funds, or other transactional activities in financial services. This tag cannot be used for use cases beyond those listed above or for promotional content (ex: promotion for signups, or offers such as free trials for any financial products).",
"message_tag_pairing_update": "The pairing_update tag can be used to notify the message recipient that a pairing has been identified based on the recipient's prior request. Examples: Match has been confirmed in a dating app. User has confirmed an open parking spot for someone who previously requested one.",
"message_tag_application_update": "The application_update tag can be used to notify the message recipient of an update on the status of their application. Examples: Application is being reviewed. Application has been rejected.",
"message_tag_confirmed_event_reminder": "The confirmed_event_reminder tag can be used to send the message recipient reminders of a scheduled event for which a person is going to attend. Examples: Upcoming classes or events that a person has signed up for. Confirmation of attendance to an accepted event or appointment.",
"message_tag_community_alert": "The community_alert tag can be used to notify the message recipient of utility alerts, or safety checks in your community. Examples: Request a safety check. Notify of an emergency or utility alerts.",
"message_tag_non_promotional_subscription": "The non_promotional_subscription tag can be used to send non-promotional messages under the News, Productivity, and Personal Trackers categories described in the Messenger Platform's subscription messaging policy. You can apply for access to use this tag under the Page Settings > Messenger Platform. Use Cases: News. Productivity. Personal Trackers.",
"supported_message_type_non_promotional_subscription": "All message types and templates are supported, as long as the message adheres to the Messenger Platform's subscription messaging policy.",
"supported_message_type_issue_resolution": "Generic template and text messages are supported.",
"supported_message_type_others": "Only generic template messages are supported.",
"notification_type_regular": "Sound/Vibration",
"notification_type_silent_push": "On-screen notification only",
"notification_type_no_push": "No notification",
"permanent": "When enabled, the variable value will be stored in the subscriber's profile and retained for future conversations."
},
"charts": {

View File

@ -444,52 +444,10 @@
"delete": "Suppression",
"role": "Rôle",
"owner": "Propriétaire",
"app_secret": "Clé secrète Facebook",
"access_token": "Jeton daccès de la Page Facebook",
"verify_token": "Jeton de Verification de l'URL de rappel",
"client_id": "ID Client",
"client_secret": "Clé secrète Client",
"app_id": "ID de l'application Facebook",
"page_id": "ID de la page Facebook",
"user_fields": "Champs utilisateur à récupérer (séparé par des virgules)",
"mode": "Mode",
"mode_options": {
"emulator": "Emulateur",
"live": "Production"
},
"get_started_button": "Activer le bouton `Démarrer`",
"composer_input_disabled": "Désactiver la saisie du compositeur",
"greeting_text": "Texte de bienvenue",
"provider": "Fournisseur",
"provider_options": {
"wit": "Wit.ai",
"rasa": "Rasa NLU"
},
"languages": "Langues disponibles",
"default_lang": "Langue",
"global_fallback": "Activer le message de secours global?",
"secret": "Mot de passe",
"verification_token": "Jeton de vérification",
"allowed_domains": "Domaines autorisés",
"start_button": "Activer `Démarrer`",
"input_disabled": "Désactiver la saisie",
"persistent_menu": "Afficher le menu persistent",
"greeting_message": "Message de bienvenue",
"theme_color": "Thème du widget",
"theme_color_options": {
"orange": "Orange",
"red": "Rouge",
"green": "Vert",
"blue": "Bleu",
"dark": "Sombre"
},
"window_title": "Titre de la fenêtre de chat",
"avatar_url": "Avatar du chatbot (URL)",
"show_emoji": "Activer le sélecteur d'Emojis",
"show_file": "Activer l'upload de fichiers",
"show_location": "Activer le partage de géolocalisation",
"allowed_upload_size": "Taille maximale de téléchargement (en octets)",
"allowed_upload_types": "Types MIME autorisés pour le téléchargement (séparés par des virgules)",
"channel": "Canal",
"entry": "Contenu de l'entrée",
"thumbnail": "Aperçu",
@ -620,41 +578,13 @@
"reset": "Mot de passe oublié?"
},
"help": {
"verify_token": "Token que vous renverra Facebook dans le cadre de la vérification de lURL de rappel.",
"composer_input_disabled": "Cela signifie que votre robot ne peut interagir qu'avec le menu persistant, les valeurs de retours, les boutons et les Webviews.",
"get_started_button": "L'écran de bienvenue d'un chatbot peut afficher un bouton `Démarrer`. Lorsque ce bouton est appuyé, la plate-forme Messenger envoie un événement à votre webhook (Payload = `Démarrer`).",
"greeting_text": "Le texte de bienvenue de votre chatbot vous permet de spécifier le message d'accueil que les utilisateurs verront sur l'écran d'accueil de votre chatbot. L'écran de bienvenue s'affiche pour les personnes qui interagissent avec votre chatbot pour la première fois.",
"fallback_message": "Si aucun bloc de secours n'est spécifié, alors de ces messages sera envoyé.",
"app_id": "Obligatoire seulement si vous comptez utiliser Facebook Analytics",
"page_id": "Obligatoire seulement si vous comptez utiliser Facebook Analytics",
"nlp_train": "Vous pouvez entraîner votre chatbot en ajoutant plusieurs exemples",
"hit_enter_to_create": "Appuyez sur `Entrer` pour créer un nouveau",
"nlp_precision": "Pour une entité, la précision est la probabilité de faire la bonne prédiction.",
"nlp_recall": "Le rappel est la probabilité de reconnaître une entité parmi toutes les entités.",
"nlp_f1score": "Le score F1 peut être interprété comme une moyenne pondérée de la précision et du rappel",
"nlp_accuracy": "Le score de précision est la proportion des échantillons correctement classés.",
"message_tag_shipping_update": "Le tag shipping_update ne peut être utilisé que pour fournir une notification d'état d'expédition pour un produit déjà acheté. Par exemple, lorsque le produit est expédié, en transit, livré ou retardé. Cette étiquette ne peut pas être utilisée pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: offres quotidiennes, coupons et remises, ou annonces de vente).",
"message_tag_reservation_update": "Le tag reservation_update ne peut être utilisé que pour confirmer les mises à jour d'une réservation existante. Par exemple, lorsqu'il y a un changement d'itinéraire, d'emplacement ou d'annulation (par exemple, lorsqu'une réservation d'hôtel est annulée, l'heure de prise en charge d'une location de voiture change ou une surclassement de chambre est confirmée). Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: offres quotidiennes, coupons et remises, ou annonces de vente).",
"message_tag_issue_resolution": "Le tag issue_resolution ne peut être utilisé que pour répondre à un problème de service client apparu dans une conversation Messenger après qu'une transaction a eu lieu. Cette balise est destinée aux cas d'utilisation où l'entreprise a besoin de plus de 24 heures pour résoudre un problème et doit donner à quelqu'un une mise à jour du statut et / ou recueillir des informations supplémentaires. Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux mentionnés ci-dessus ou pour du contenu promotionnel (ex: offres quotidiennes, coupons et remises, ou annonces de vente, les entreprises ne peuvent pas utiliser le tag pour envoyer des commentaires proactifs).",
"message_tag_appointment_update": "Le tag appointment_update ne peut être utilisée que pour fournir des mises à jour sur un rendez-vous existant. Par exemple, lorsqu'il y a un changement dans le temps, une mise à jour ou une annulation (comme lorsqu'un spa est annulé, un agent immobilier doit vous rencontrer dans un nouvel endroit ou un cabinet dentaire propose une nouvelle heure de rendez-vous). Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: offres quotidiennes, coupons et remises, ou annonces de vente).",
"message_tag_game_event": "Le tag game_event ne peut être utilisé que pour fournir une mise à jour sur la progression de l'utilisateur, un événement global dans un jeu ou un événement sportif en direct. Par exemple, quand les récoltes d'une personne sont prêtes à être récoltées, leur construction est terminée, leur tournoi quotidien est sur le point de commencer ou leur équipe de football préférée est sur le point de jouer. Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: offres quotidiennes, coupons et remises, ou annonces de vente).",
"message_tag_transportation_update": "Le tag transportation_update ne peut être utilisé que pour confirmer les mises à jour d'une réservation existante. Par exemple, en cas de changement de statut d'un vol, d'une réservation de train. Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: offres quotidiennes, coupons et remises, ou annonces de vente).",
"message_tag_feature_functionality_update": "Le tag feature_functionality_update ne peut être utilisé que pour fournir une mise à jour sur les nouvelles fonctionnalités ou fonctionnalités qui deviennent disponibles dans un bot. Par exemple, annoncer la possibilité de parler à un agent en direct dans un bot, ou que le bot a une nouvelle compétence. Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: offres quotidiennes, coupons et remises, ou annonces de vente).",
"message_tag_ticket_update": "Le tag ticket_update ne peut être utilisé que pour informer le destinataire du message des mises à jour ou des rappels relatifs à un événement pour lequel la personne a déjà confirmé sa présence. Par exemple, lorsque vous souhaitez envoyer un message concernant un changement d'heure, une mise à jour d'emplacement, une annulation ou un rappel pour un événement à venir (par exemple, lorsqu'un concert est annulé, le lieu a changé ou une possibilité de remboursement est disponible). Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: offres quotidiennes, coupons et remises, ou annonces de vente)",
"message_tag_account_update": "Le tag account_update peut uniquement être utilisé pour confirmer les mises à jour du paramètre de compte d'un utilisateur. Par exemple, en cas de modification des paramètres et des préférences d'un profil utilisateur, de la notification d'un changement de mot de passe ou de l'expiration de l'adhésion. Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: promotion pour les inscriptions, créations de nouveaux comptes ou offres pour étendre les abonnements).",
"message_tag_payment_update": "Le tag payment_update peut être utilisé pour fournir des mises à jour de paiement à des transactions existantes. Par exemple, il peut être utilisé pour envoyer un reçu, un rupture de stock, une enchère terminée, un remboursement ou un changement de statut dans une transaction d'achat existante. Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: toute promotion de vente croisée / incitative, coupons, ou offres d'extension d'abonnements).",
"message_tag_personal_finance_update": "Le tag PERSONAL_FINANCE_UPDATE peut être utilisé pour confirmer l'activité financière d'un utilisateur. Par exemple, il peut être utilisé pour envoyer des notifications sur les rappels de paiement de factures, les paiements programmés, les reçus de paiement, les transferts de fonds ou d'autres activités transactionnelles dans les services financiers. Ce tag ne peut pas être utilisé pour des cas d'utilisation autres que ceux énumérés ci-dessus ou pour du contenu promotionnel (ex: promotion pour les inscriptions, ou des offres telles que des essais gratuits pour tout produit financier).",
"message_tag_pairing_update": "Le tag pairing_update peut être utilisé pour notifier au destinataire du message qu'un jumelage a été identifié en fonction de la demande préalable du destinataire. Exemples: Le jumelage a été confirmé dans une application de rencontres. L'utilisateur a confirmé une place de parking ouverte pour quelqu'un qui en avait précédemment demandé une.",
"message_tag_application_update": "Le tag application_update peut être utilisé pour informer le destinataire du message d'une mise à jour sur l'état de son application. Exemples: L'application est en cours de révision. La demande a été rejetée.",
"message_tag_confirmed_event_reminder": "Le tag confirmed_event_reminder peut être utilisé pour envoyer aux destinataires du message des rappels d'un événement planifié auquel une personne va participer. Exemples: Cours ou événements à venir pour lesquels une personne s'est inscrite. Confirmation de participation à un événement ou à un rendez-vous accepté.",
"message_tag_community_alert": "Le tag community_alert peut être utilisé pour informer le destinataire du message des alertes utilitaires ou des vérifications de sécurité dans votre communauté. Exemples: Demander un contrôle de sécurité. Avertir d'une urgence ou d'alertes d'utilité.",
"message_tag_non_promotional_subscription": "Le tag non_promotion_subscription peut être utilisé pour envoyer des messages non promotionnels dans les catégories Actualités, Productivité et Suivi personnel décrites dans la politique d'abonnement à la messagerie de la plate-forme Messenger. Vous pouvez demander l'accès pour utiliser ce tag, allez dans les paramètres de la page Plate-forme Messenger. Cas d'utilisation: Nouvelles. Productivité. Traqueurs personnels.",
"supported_message_type_non_promotional_subscription": "Tous les types de messages et modèles sont pris en charge, à condition que le message respecte la politique d'abonnement à la messagerie de la plate-forme Messenger.",
"supported_message_type_issue_resolution": "Le modèle générique et les messages texte sont supportés.",
"supported_message_type_others": "Seuls les messages de modèle générique sont pris en charge.",
"notification_type_regular": "Son/Vibration",
"notification_type_silent_push": "Notification à l'écran uniquement",
"notification_type_no_push": "Aucune notification",
"permanent": "Lorsqu'elle est activée, cette variable sera stockée dans le profil de l'abonné(e) et conservée pour les futures conversations."
},
"charts": {