From 92cec51f3e8666cd379b8adbcaf4e06703eb460a Mon Sep 17 00:00:00 2001 From: Dimitrios Gkegkas Date: Fri, 7 May 2021 15:50:54 +0300 Subject: [PATCH 1/7] Add Carousel as element to viber-elements and Rename Old Carousel to RichMedia --- .../src/modules/getStarted/actions.ts | 54 +++++- .../lib/viberAPI/attachments.ts | 16 +- .../viber-elements/lib/viberAPI/carousel.ts | 167 ++++++++++++++++++ packages/viber-elements/lib/viberAPI/index.ts | 1 + .../viber-elements/lib/viberAPI/interfaces.ts | 13 +- .../viber-elements/lib/viberAPI/message.ts | 5 +- tsconfig.json | 2 +- 7 files changed, 239 insertions(+), 19 deletions(-) create mode 100644 packages/viber-elements/lib/viberAPI/carousel.ts diff --git a/examples/viber-demo-bot/src/modules/getStarted/actions.ts b/examples/viber-demo-bot/src/modules/getStarted/actions.ts index 4cb6c2f..f1dde87 100644 --- a/examples/viber-demo-bot/src/modules/getStarted/actions.ts +++ b/examples/viber-demo-bot/src/modules/getStarted/actions.ts @@ -1,5 +1,6 @@ import { bot } from '../../bot'; -import { Carousel, Button, Message } from '@ebenos/viber-elements'; +import { RichMedia, Button, Message } from '@ebenos/viber-elements'; +import { Carousel } from '@ebenos/viber-elements'; import { addAction, addTextRule, InMemoryUser } from '@ebenos/framework'; import getStartedModule from '.'; @@ -46,7 +47,7 @@ async function getTest6(user: InMemoryUser, payload: string) { sender: { name: 'Giorgos' }, - rich_media: new Carousel({ + rich_media: new RichMedia({ ButtonsGroupColumns: 2, ButtonsGroupRows: 1, BgColor: '#FFFFFF', @@ -69,6 +70,55 @@ async function getTest6(user: InMemoryUser, payload: string) { .end(); } +const staticButtons = [ + { + title: '❓ Δεν μπορώ να συνδεθώ στον λογαριασμό μου.', + subtitle: 'Προβλήματα σύνδεσης στο νέο Pamestoixima.gr.', + buttons: [ + { + text: 'ΠΕΡΙΣΣΟΤΕΡΑ...', + payload: 'faq_account' + } + ] + }, + { + title: '❓ Δεν μπορώ να δω το ιστορικό συναλλαγών/στοιχημάτων.', + subtitle: 'Τοποθετημένα στοιχήματα, παλιά στοιχήματα και συναλλαγές.', + buttons: [ + { + text: 'ΠΕΡΙΣΣΟΤΕΡΑ...', + payload: 'faq_history' + } + ] + }, + { + title: '❓ Έχω πρόβλημα με το site.', + subtitle: 'Δεν ανοίγει ή δεν μπορώ να μπω καθόλου στο site του νέου Pamestoixima.gr', + buttons: [ + { + text: 'ΠΕΡΙΣΣΟΤΕΡΑ...', + payload: 'technical' + } + ] + } +]; + +addAction(getStartedModule, getTest7); +addTextRule(getStartedModule, getTest7, /TEST7/); +async function getTest7(user: InMemoryUser, payload: string) { + await bot + .scenario(user) + .send( + new Message({ + sender: { + name: 'Giorgos' + }, + rich_media: new Carousel(staticButtons) + }) + ) + .end(); +} + addAction(getStartedModule, getStartedSecond); addTextRule(getStartedModule, getStartedSecond, /.*/); async function getStartedSecond(user: InMemoryUser, payload: string) { diff --git a/packages/viber-elements/lib/viberAPI/attachments.ts b/packages/viber-elements/lib/viberAPI/attachments.ts index 1c22ac3..df1ee2c 100644 --- a/packages/viber-elements/lib/viberAPI/attachments.ts +++ b/packages/viber-elements/lib/viberAPI/attachments.ts @@ -1,11 +1,11 @@ import { - ICarouselOptions, + IRichMediaOptions, IPictureOptions, ActionType, TextVAlign, TextHAlign, TextSize, - ISerializedCarousel, + ISerializedRichMedia, MediaType, ScaleType, OpenURLType, @@ -19,7 +19,7 @@ import { } from './interfaces'; import { ISerializable } from '@ebenos/framework'; -/**Viber Carousel Button */ +/**Viber RichMedia Button */ export class Button implements ISerializable { public Columns = 6; public Rows = 1; @@ -166,15 +166,15 @@ export class Button implements ISerializable { } } -/** Viber Carousel Attachment */ -export class Carousel implements ISerializable { +/** Viber RichMedia Attachment */ +export class RichMedia implements ISerializable { public ButtonsGroupColumns?: number; public ButtonsGroupRows?: number; public BgColor?: string; public Buttons: Button[]; public HeightScale = 100; - constructor(options: ICarouselOptions) { + constructor(options: IRichMediaOptions) { const { ButtonsGroupColumns, ButtonsGroupRows, BgColor, Buttons, HeightScale } = options; this.ButtonsGroupColumns = ButtonsGroupColumns; @@ -187,8 +187,8 @@ export class Carousel implements ISerializable { } } - public serialize(): ISerializedCarousel { - const obj: ISerializedCarousel = { + public serialize(): ISerializedRichMedia { + const obj: ISerializedRichMedia = { Type: 'rich_media', Buttons: this.Buttons.map((b) => b.serialize()), HeightScale: this.HeightScale diff --git a/packages/viber-elements/lib/viberAPI/carousel.ts b/packages/viber-elements/lib/viberAPI/carousel.ts new file mode 100644 index 0000000..b5ef24b --- /dev/null +++ b/packages/viber-elements/lib/viberAPI/carousel.ts @@ -0,0 +1,167 @@ +import { Button, RichMedia } from './attachments'; +import { IFrame, IRichMediaOptions } from './interfaces'; +import { ISerializable } from '@ebenos/framework'; + +export interface ICarouselElement { + title?: string; + image?: string; + subtitle?: string; + buttons: Array<{ text: string; url: string } | { text: string; payload: string }>; +} + +interface ICarouselElementStyle { + textColor: string; + backgroundColor: string; +} + +type DeepPartial = { + [P in keyof T]?: DeepPartial; +}; + +export interface ICarouselStyle { + button: ICarouselElementStyle; + title: ICarouselElementStyle; + subtitle: ICarouselElementStyle; + imageBackgroundColor: string; + backgroundColor: string; +} +export interface ICarouselOptions { + style?: DeepPartial; + frame?: IFrame; +} + +function createCarousel( + elements: ICarouselElement[], + options?: ICarouselOptions +): IRichMediaOptions { + const color = (k: keyof ICarouselStyle, t?: keyof ICarouselElementStyle) => { + const defaultStyle: ICarouselStyle = { + title: { + textColor: '#ffffff', + backgroundColor: '#ffffff' + }, + button: { + textColor: '#ffffff', + backgroundColor: '#2db9b9' + }, + subtitle: { + backgroundColor: '#ffffff', + textColor: '#696969' + }, + backgroundColor: '#ffffff', + imageBackgroundColor: '#ffffff' + }; + + if (k === 'imageBackgroundColor' || k === 'backgroundColor') { + return options?.style ? options.style[k] : defaultStyle[k]; + } + + if (t === undefined) { + throw new Error('Need to identify subproperty'); + } + + const element = options?.style ? options.style[k] : defaultStyle[k]; + if (element === undefined) { + throw new Error('Non-existant element'); + } + + const style = element[t]; + + return style ? style : defaultStyle[k][t]; + }; + + const frame = options?.frame ? options.frame : undefined; + + let hasSubtitle = false, + hasTitle = false, + hasImage = false, + largerButtons = 0; + for (const e of elements) { + if (e.subtitle !== undefined) { + hasSubtitle = true; + } + + if (e.title !== undefined) { + hasTitle = true; + } + + if (e.image !== undefined) { + hasImage = true; + } + + if (largerButtons < e.buttons.length) { + largerButtons = e.buttons.length; + } + } + + const maxRows = largerButtons + (hasSubtitle ? 1 : 0) + (hasTitle ? 1 : 0) + (hasImage ? 3 : 0); + const buttonsArray = elements.map((e) => [ + ...(hasImage + ? [ + new Button({ + Rows: 3, + BgColor: color('imageBackgroundColor'), + Columns: 6, + Image: e.image, + ActionType: 'none', + ActionBody: '' + }) + ] + : []), + ...(hasTitle + ? [ + new Button({ + Rows: 1, + Columns: 6, + BgColor: color('title', 'backgroundColor'), + Text: `${e.title}`, + ActionType: 'none', + ActionBody: '' + }) + ] + : []), + ...(hasSubtitle + ? [ + new Button({ + Rows: 1, + Columns: 6, + BgColor: color('subtitle', 'backgroundColor'), + Text: `${ + e.subtitle ? e.subtitle : '' + }`, + ActionType: 'none', + TextSize: 'small', + TextHAlign: 'left', + ActionBody: '' + }) + ] + : []), + ...e.buttons.map( + (button) => + new Button({ + Rows: 1, + Columns: 6, + Text: `${ + button.text + }`, + BgColor: color('button', 'backgroundColor'), + ActionType: 'url' in button ? 'open-url' : 'reply', + Silent: 'url' in button, + ActionBody: 'url' in button ? button.url : button.payload, + Frame: frame + }) + ) + ]); + return { + ButtonsGroupColumns: 6, + ButtonsGroupRows: maxRows, + BgColor: color('backgroundColor'), + Buttons: buttonsArray.flat() + }; +} + +export class Carousel extends RichMedia implements ISerializable { + constructor(elements: ICarouselElement[], options?: ICarouselOptions) { + super(createCarousel(elements, options)); + } +} diff --git a/packages/viber-elements/lib/viberAPI/index.ts b/packages/viber-elements/lib/viberAPI/index.ts index 5e1edfc..a426e89 100644 --- a/packages/viber-elements/lib/viberAPI/index.ts +++ b/packages/viber-elements/lib/viberAPI/index.ts @@ -12,3 +12,4 @@ export * from './attachments'; export * from './keyboard'; export * from './message'; export * from './interfaces'; +export * from './carousel'; diff --git a/packages/viber-elements/lib/viberAPI/interfaces.ts b/packages/viber-elements/lib/viberAPI/interfaces.ts index 1be22a9..7b12015 100644 --- a/packages/viber-elements/lib/viberAPI/interfaces.ts +++ b/packages/viber-elements/lib/viberAPI/interfaces.ts @@ -1,4 +1,5 @@ -import { Carousel, Picture, Button } from './attachments'; +import { RichMedia, Picture, Button } from './attachments'; +import { Carousel } from './carousel'; import { Keyboard } from './keyboard'; export type ScaleType = 'crop' | 'fill' | 'fit'; @@ -30,7 +31,7 @@ export type MessageType = | 'location' | 'contact' | 'sticker' - | 'carousel content' + | 'RichMedia content' | 'rich_media' | 'url'; export type OpenURLMediaType = 'not-media' | 'video' | 'gif' | 'picture'; @@ -48,7 +49,7 @@ export interface IMessageOptions { type?: MessageType; text?: string; attachment?: Picture; - rich_media?: Carousel; + rich_media?: RichMedia | Carousel; keyboard?: Keyboard; } @@ -58,7 +59,7 @@ export interface ISerializedTextMessage { sender: ISender; tracking_data?: string; attachment?: Picture; - rich_media?: ISerializedCarousel; + rich_media?: ISerializedRichMedia; keyboard?: ISerializedKeyboard; min_api_version: string; } @@ -70,7 +71,7 @@ export interface IPictureOptions { thumbnail?: string; } -export interface ICarouselOptions { +export interface IRichMediaOptions { ButtonsGroupColumns?: number; ButtonsGroupRows?: number; BgColor?: string; @@ -188,7 +189,7 @@ export interface ISerializedButton { MediaPlayer?: IMediaPlayer; } -export interface ISerializedCarousel { +export interface ISerializedRichMedia { Type: 'rich_media'; Buttons: ISerializedButton[]; HeightScale: number; diff --git a/packages/viber-elements/lib/viberAPI/message.ts b/packages/viber-elements/lib/viberAPI/message.ts index 23a4af0..52c7895 100644 --- a/packages/viber-elements/lib/viberAPI/message.ts +++ b/packages/viber-elements/lib/viberAPI/message.ts @@ -1,7 +1,8 @@ import { ISerializable } from '@ebenos/framework'; import { IMessageOptions, ISender, MessageType, ISerializedTextMessage } from './interfaces'; -import { Picture, Carousel } from './attachments'; +import { Picture, RichMedia } from './attachments'; import { Keyboard } from './keyboard'; +import { Carousel } from './carousel'; /** Message Class */ export class Message implements ISerializable { @@ -10,7 +11,7 @@ export class Message implements ISerializable { public type?: MessageType; public text?: string; public attachment?: Picture; - public rich_media?: Carousel; + public rich_media?: RichMedia | Carousel; public keyboard?: Keyboard; /** diff --git a/tsconfig.json b/tsconfig.json index 9e80382..42ba66b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { /* Basic Options */ - "target": "ES2015" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, + "target": "ES2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ From 325462d99996b1e1f82e33659132cf80d5a5203e Mon Sep 17 00:00:00 2001 From: Dimitrios Gkegkas Date: Wed, 12 May 2021 18:13:52 +0300 Subject: [PATCH 2/7] Add URL element in Viber's Framework --- .../src/modules/getStarted/actions.ts | 19 +++++++- packages/viber-elements/lib/viberAPI/index.ts | 1 + .../viber-elements/lib/viberAPI/interfaces.ts | 18 ++++++++ packages/viber-elements/lib/viberAPI/url.ts | 45 +++++++++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 packages/viber-elements/lib/viberAPI/url.ts diff --git a/examples/viber-demo-bot/src/modules/getStarted/actions.ts b/examples/viber-demo-bot/src/modules/getStarted/actions.ts index f1dde87..221d749 100644 --- a/examples/viber-demo-bot/src/modules/getStarted/actions.ts +++ b/examples/viber-demo-bot/src/modules/getStarted/actions.ts @@ -1,5 +1,5 @@ import { bot } from '../../bot'; -import { RichMedia, Button, Message } from '@ebenos/viber-elements'; +import { RichMedia, Button, Message, URL } from '@ebenos/viber-elements'; import { Carousel } from '@ebenos/viber-elements'; import { addAction, addTextRule, InMemoryUser } from '@ebenos/framework'; import getStartedModule from '.'; @@ -119,6 +119,23 @@ async function getTest7(user: InMemoryUser, payload: string) { .end(); } +addAction(getStartedModule, getTest8); +addTextRule(getStartedModule, getTest8, /TEST8/); +async function getTest8(user: InMemoryUser, payload: string) { + await bot + .scenario(user) + .send( + new URL({ + sender: { + name: 'Giorgos' + }, + media: + 'https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif' + }) + ) + .end(); +} + addAction(getStartedModule, getStartedSecond); addTextRule(getStartedModule, getStartedSecond, /.*/); async function getStartedSecond(user: InMemoryUser, payload: string) { diff --git a/packages/viber-elements/lib/viberAPI/index.ts b/packages/viber-elements/lib/viberAPI/index.ts index a426e89..110a9bd 100644 --- a/packages/viber-elements/lib/viberAPI/index.ts +++ b/packages/viber-elements/lib/viberAPI/index.ts @@ -13,3 +13,4 @@ export * from './keyboard'; export * from './message'; export * from './interfaces'; export * from './carousel'; +export * from './url'; diff --git a/packages/viber-elements/lib/viberAPI/interfaces.ts b/packages/viber-elements/lib/viberAPI/interfaces.ts index 7b12015..d3caccf 100644 --- a/packages/viber-elements/lib/viberAPI/interfaces.ts +++ b/packages/viber-elements/lib/viberAPI/interfaces.ts @@ -64,6 +64,24 @@ export interface ISerializedTextMessage { min_api_version: string; } +export interface IURLOptions { + sender: ISender; + media: string; + tracking_data?: string | Record; + type?: MessageType; + keyboard?: Keyboard; +} + +export interface ISerializedURL { + text?: string; + type: MessageType; + sender: ISender; + media: string; + tracking_data?: string; + keyboard?: ISerializedKeyboard; + min_api_version: string; +} + /** ATTACHMENTS */ export interface IPictureOptions { diff --git a/packages/viber-elements/lib/viberAPI/url.ts b/packages/viber-elements/lib/viberAPI/url.ts new file mode 100644 index 0000000..516fbca --- /dev/null +++ b/packages/viber-elements/lib/viberAPI/url.ts @@ -0,0 +1,45 @@ +import { ISerializable } from '@ebenos/framework'; +import { ISender, MessageType, IURLOptions, ISerializedURL } from './interfaces'; +import { Keyboard } from './keyboard'; + +/** URL Class */ +export class URL implements ISerializable { + public sender: ISender; + public media: string; + public tracking_data?: string | Record; + public type?: MessageType; + public keyboard?: Keyboard; + + constructor(options: IURLOptions) { + const { sender, media, tracking_data, type, keyboard } = options; + + this.sender = sender; + this.tracking_data = tracking_data; + this.type = type; + this.media = media; + this.keyboard = keyboard; + } + + public serialize(): ISerializedURL { + const obj: ISerializedURL = { + type: 'url', + sender: this.sender, + min_api_version: '7', + media: this.media + }; + + if (this.tracking_data !== undefined) { + if (typeof this.tracking_data === 'string') { + obj.tracking_data = this.tracking_data; + } else { + obj.tracking_data = JSON.stringify(this.tracking_data); + } + } + + if (this.keyboard !== undefined) { + obj.keyboard = this.keyboard.serialize(); + } + + return obj; + } +} From 99ff87ca43d226c4875bb03fd6df7852ee7be49b Mon Sep 17 00:00:00 2001 From: Dimitrios Gkegkas Date: Thu, 13 May 2021 12:04:55 +0300 Subject: [PATCH 3/7] Message now supports url --- .../src/modules/getStarted/actions.ts | 6 +- .../viber-elements/lib/viberAPI/interfaces.ts | 47 +++++++------- .../viber-elements/lib/viberAPI/message.ts | 62 +++++++++++++------ packages/viber-elements/lib/viberAPI/url.ts | 45 -------------- 4 files changed, 72 insertions(+), 88 deletions(-) delete mode 100644 packages/viber-elements/lib/viberAPI/url.ts diff --git a/examples/viber-demo-bot/src/modules/getStarted/actions.ts b/examples/viber-demo-bot/src/modules/getStarted/actions.ts index 221d749..aa3fd59 100644 --- a/examples/viber-demo-bot/src/modules/getStarted/actions.ts +++ b/examples/viber-demo-bot/src/modules/getStarted/actions.ts @@ -1,5 +1,5 @@ import { bot } from '../../bot'; -import { RichMedia, Button, Message, URL } from '@ebenos/viber-elements'; +import { RichMedia, Button, Message } from '@ebenos/viber-elements'; import { Carousel } from '@ebenos/viber-elements'; import { addAction, addTextRule, InMemoryUser } from '@ebenos/framework'; import getStartedModule from '.'; @@ -120,12 +120,12 @@ async function getTest7(user: InMemoryUser, payload: string) { } addAction(getStartedModule, getTest8); -addTextRule(getStartedModule, getTest8, /TEST8/); +addTextRule(getStartedModule, getTest8, /TEST9/); async function getTest8(user: InMemoryUser, payload: string) { await bot .scenario(user) .send( - new URL({ + new Message({ sender: { name: 'Giorgos' }, diff --git a/packages/viber-elements/lib/viberAPI/interfaces.ts b/packages/viber-elements/lib/viberAPI/interfaces.ts index d3caccf..2488f99 100644 --- a/packages/viber-elements/lib/viberAPI/interfaces.ts +++ b/packages/viber-elements/lib/viberAPI/interfaces.ts @@ -43,45 +43,50 @@ export interface ISender { avatar?: string; } -export interface IMessageOptions { +export interface IGeneralMessageOptions { sender: ISender; tracking_data?: string | Record; type?: MessageType; - text?: string; - attachment?: Picture; - rich_media?: RichMedia | Carousel; keyboard?: Keyboard; + attachment?: Picture; +} + +export interface ITextOptions extends IGeneralMessageOptions { + text: string; +} + +export interface IRichMediaMessageOptions extends IGeneralMessageOptions { + rich_media: RichMedia | Carousel; } -export interface ISerializedTextMessage { - text?: string; +export interface IURLOptions extends IGeneralMessageOptions { + media: string; +} + +export type IMessageOptions = ITextOptions | IURLOptions | IRichMediaMessageOptions; + +export interface ISerializedGeneralMessage { type: MessageType; sender: ISender; + min_api_version: string; tracking_data?: string; attachment?: Picture; - rich_media?: ISerializedRichMedia; keyboard?: ISerializedKeyboard; - min_api_version: string; } -export interface IURLOptions { - sender: ISender; +export interface ISerializedText extends ISerializedGeneralMessage { + text: string; +} +export interface ISerializedURL extends ISerializedGeneralMessage { media: string; - tracking_data?: string | Record; - type?: MessageType; - keyboard?: Keyboard; } -export interface ISerializedURL { - text?: string; - type: MessageType; - sender: ISender; - media: string; - tracking_data?: string; - keyboard?: ISerializedKeyboard; - min_api_version: string; +export interface ISerializedRichMediaMessage extends ISerializedGeneralMessage { + rich_media: ISerializedRichMedia; } +export type ISerializedMessage = ISerializedText | ISerializedURL | ISerializedRichMediaMessage; + /** ATTACHMENTS */ export interface IPictureOptions { diff --git a/packages/viber-elements/lib/viberAPI/message.ts b/packages/viber-elements/lib/viberAPI/message.ts index 52c7895..beccd62 100644 --- a/packages/viber-elements/lib/viberAPI/message.ts +++ b/packages/viber-elements/lib/viberAPI/message.ts @@ -1,5 +1,11 @@ import { ISerializable } from '@ebenos/framework'; -import { IMessageOptions, ISender, MessageType, ISerializedTextMessage } from './interfaces'; +import { + IMessageOptions, + ISender, + MessageType, + ISerializedMessage, + ISerializedGeneralMessage +} from './interfaces'; import { Picture, RichMedia } from './attachments'; import { Keyboard } from './keyboard'; import { Carousel } from './carousel'; @@ -13,21 +19,30 @@ export class Message implements ISerializable { public attachment?: Picture; public rich_media?: RichMedia | Carousel; public keyboard?: Keyboard; + public media?: string; /** * Create a message * @param {MessageOptions|string} options - The message elements */ constructor(options: IMessageOptions) { - const { text, sender, tracking_data, type, attachment, rich_media, keyboard } = options; - - this.text = text; + const { sender, tracking_data, type, attachment, keyboard } = options; this.sender = sender; this.tracking_data = tracking_data; this.type = type; this.attachment = attachment; - this.rich_media = rich_media; this.keyboard = keyboard; + + if ('media' in options) { + const { media } = options; + this.media = media; + } else if ('rich_media' in options) { + const { rich_media } = options; + this.rich_media = rich_media; + } else { + const { text } = options; + this.text = text; + } } private determineType(): MessageType { @@ -43,25 +58,24 @@ export class Message implements ISerializable { if (this.text !== undefined) { return 'text'; } + if (this.media !== undefined) { + return 'url'; + } throw new Error('Cannot determine message type!'); } - public serialize(): ISerializedTextMessage { - if (this.rich_media !== undefined && this.text !== undefined) { - throw new Error("Rich media can't be combined with text!"); - } + public serialize(): ISerializedMessage | ISerializedGeneralMessage { + /* + * Common for all Serialized messages + **/ - const obj: ISerializedTextMessage = { + const obj: ISerializedGeneralMessage = { type: this.determineType(), sender: this.sender, min_api_version: '7' }; - if (this.text !== undefined) { - obj.text = this.text; - } - if (this.tracking_data !== undefined) { if (typeof this.tracking_data === 'string') { obj.tracking_data = this.tracking_data; @@ -74,14 +88,24 @@ export class Message implements ISerializable { obj.attachment = this.attachment.serialize(); } - if (this.rich_media !== undefined) { - obj.rich_media = this.rich_media.serialize(); - } - if (this.keyboard !== undefined) { obj.keyboard = this.keyboard.serialize(); } - + /* + * Properties that depend on the type of message + **/ + if (this.rich_media !== undefined) { + const objR: ISerializedMessage = { ...obj, rich_media: this.rich_media.serialize() }; + return objR; + } + if (this.text !== undefined) { + const objR: ISerializedMessage = { ...obj, text: this.text }; + return objR; + } + if (this.media !== undefined) { + const objR: ISerializedMessage = { ...obj, media: this.media }; + return objR; + } return obj; } } diff --git a/packages/viber-elements/lib/viberAPI/url.ts b/packages/viber-elements/lib/viberAPI/url.ts deleted file mode 100644 index 516fbca..0000000 --- a/packages/viber-elements/lib/viberAPI/url.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { ISerializable } from '@ebenos/framework'; -import { ISender, MessageType, IURLOptions, ISerializedURL } from './interfaces'; -import { Keyboard } from './keyboard'; - -/** URL Class */ -export class URL implements ISerializable { - public sender: ISender; - public media: string; - public tracking_data?: string | Record; - public type?: MessageType; - public keyboard?: Keyboard; - - constructor(options: IURLOptions) { - const { sender, media, tracking_data, type, keyboard } = options; - - this.sender = sender; - this.tracking_data = tracking_data; - this.type = type; - this.media = media; - this.keyboard = keyboard; - } - - public serialize(): ISerializedURL { - const obj: ISerializedURL = { - type: 'url', - sender: this.sender, - min_api_version: '7', - media: this.media - }; - - if (this.tracking_data !== undefined) { - if (typeof this.tracking_data === 'string') { - obj.tracking_data = this.tracking_data; - } else { - obj.tracking_data = JSON.stringify(this.tracking_data); - } - } - - if (this.keyboard !== undefined) { - obj.keyboard = this.keyboard.serialize(); - } - - return obj; - } -} From 70e3e3d29e1e148cb77f2ca59556fcc3aa668efe Mon Sep 17 00:00:00 2001 From: Dimitrios Gkegkas Date: Fri, 14 May 2021 10:49:28 +0300 Subject: [PATCH 4/7] Clean Interfaces and types in message class --- .../viber-elements/lib/viberAPI/interfaces.ts | 71 ++++++++++--------- .../viber-elements/lib/viberAPI/message.ts | 41 ++++------- 2 files changed, 52 insertions(+), 60 deletions(-) diff --git a/packages/viber-elements/lib/viberAPI/interfaces.ts b/packages/viber-elements/lib/viberAPI/interfaces.ts index 2488f99..3dc3968 100644 --- a/packages/viber-elements/lib/viberAPI/interfaces.ts +++ b/packages/viber-elements/lib/viberAPI/interfaces.ts @@ -65,28 +65,6 @@ export interface IURLOptions extends IGeneralMessageOptions { export type IMessageOptions = ITextOptions | IURLOptions | IRichMediaMessageOptions; -export interface ISerializedGeneralMessage { - type: MessageType; - sender: ISender; - min_api_version: string; - tracking_data?: string; - attachment?: Picture; - keyboard?: ISerializedKeyboard; -} - -export interface ISerializedText extends ISerializedGeneralMessage { - text: string; -} -export interface ISerializedURL extends ISerializedGeneralMessage { - media: string; -} - -export interface ISerializedRichMediaMessage extends ISerializedGeneralMessage { - rich_media: ISerializedRichMedia; -} - -export type ISerializedMessage = ISerializedText | ISerializedURL | ISerializedRichMediaMessage; - /** ATTACHMENTS */ export interface IPictureOptions { @@ -154,17 +132,6 @@ export interface IInternalBrowser { ActionReplyData?: string; } -export interface ISerializedKeyboard { - Buttons: ISerializedButton[]; - InputFieldState: InputFieldState; - DefaultHeight: boolean; - ButtonsGroupColumns: number; - ButtonsGroupRows: number; - BgColor?: string; - CustomDefaultHeight?: number; - FavoritesMetadata?: string; -} - export interface ICoordinates { Latitude: string; Longitude: string; @@ -183,6 +150,44 @@ export interface IMediaPlayer { Loop?: boolean; } +/* + * Serialized Structers + **/ +export interface ISerializedGeneralMessage { + type: MessageType; + sender: ISender; + min_api_version: string; + tracking_data?: string; + attachment?: Picture; + keyboard?: ISerializedKeyboard; +} + +export interface ISerializedText extends ISerializedGeneralMessage { + text: string; +} +export interface ISerializedURL extends ISerializedGeneralMessage { + media: string; +} +export interface ISerializedRichMediaMessage extends ISerializedGeneralMessage { + rich_media: ISerializedRichMedia; +} +export interface ISerializedImage extends ISerializedGeneralMessage { + attachment: Picture; +} + +export type ISerializedMessage = ISerializedText | ISerializedURL | ISerializedRichMediaMessage; + +export interface ISerializedKeyboard { + Buttons: ISerializedButton[]; + InputFieldState: InputFieldState; + DefaultHeight: boolean; + ButtonsGroupColumns: number; + ButtonsGroupRows: number; + BgColor?: string; + CustomDefaultHeight?: number; + FavoritesMetadata?: string; +} + export interface ISerializedButton { Columns?: number; Rows?: number; diff --git a/packages/viber-elements/lib/viberAPI/message.ts b/packages/viber-elements/lib/viberAPI/message.ts index beccd62..55c1a00 100644 --- a/packages/viber-elements/lib/viberAPI/message.ts +++ b/packages/viber-elements/lib/viberAPI/message.ts @@ -36,36 +36,27 @@ export class Message implements ISerializable { if ('media' in options) { const { media } = options; this.media = media; + this.type = 'url'; } else if ('rich_media' in options) { const { rich_media } = options; this.rich_media = rich_media; + this.type = 'rich_media'; } else { const { text } = options; this.text = text; + this.type = 'text'; } } private determineType(): MessageType { - if (this.type !== undefined) { + if (this.type) { return this.type; + } else { + throw new Error('Cannot determine message type!'); } - if (this.rich_media !== undefined) { - return 'rich_media'; - } - if (this.attachment !== undefined) { - return 'picture'; - } - if (this.text !== undefined) { - return 'text'; - } - if (this.media !== undefined) { - return 'url'; - } - - throw new Error('Cannot determine message type!'); } - public serialize(): ISerializedMessage | ISerializedGeneralMessage { + public serialize(): ISerializedMessage { /* * Common for all Serialized messages **/ @@ -94,18 +85,14 @@ export class Message implements ISerializable { /* * Properties that depend on the type of message **/ + let objR: Partial = obj; if (this.rich_media !== undefined) { - const objR: ISerializedMessage = { ...obj, rich_media: this.rich_media.serialize() }; - return objR; - } - if (this.text !== undefined) { - const objR: ISerializedMessage = { ...obj, text: this.text }; - return objR; - } - if (this.media !== undefined) { - const objR: ISerializedMessage = { ...obj, media: this.media }; - return objR; + objR = { ...obj, rich_media: this.rich_media.serialize() }; + } else if (this.media !== undefined) { + objR = { ...obj, media: this.media }; + } else if (this.text !== undefined) { + objR = { ...obj, text: this.text }; } - return obj; + return objR as ISerializedMessage; } } From 202f70d074cc2d2eacbb02b12780add6b7f1cedb Mon Sep 17 00:00:00 2001 From: Christos Panagiotakopoulos Date: Fri, 14 May 2021 18:19:41 +0300 Subject: [PATCH 5/7] Fixes from live coding session --- packages/viber-elements/lib/viberAPI/index.ts | 1 - .../viber-elements/lib/viberAPI/interfaces.ts | 1 - .../viber-elements/lib/viberAPI/message.ts | 34 ++++++++++++------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/viber-elements/lib/viberAPI/index.ts b/packages/viber-elements/lib/viberAPI/index.ts index 110a9bd..a426e89 100644 --- a/packages/viber-elements/lib/viberAPI/index.ts +++ b/packages/viber-elements/lib/viberAPI/index.ts @@ -13,4 +13,3 @@ export * from './keyboard'; export * from './message'; export * from './interfaces'; export * from './carousel'; -export * from './url'; diff --git a/packages/viber-elements/lib/viberAPI/interfaces.ts b/packages/viber-elements/lib/viberAPI/interfaces.ts index 3dc3968..38e94a6 100644 --- a/packages/viber-elements/lib/viberAPI/interfaces.ts +++ b/packages/viber-elements/lib/viberAPI/interfaces.ts @@ -46,7 +46,6 @@ export interface ISender { export interface IGeneralMessageOptions { sender: ISender; tracking_data?: string | Record; - type?: MessageType; keyboard?: Keyboard; attachment?: Picture; } diff --git a/packages/viber-elements/lib/viberAPI/message.ts b/packages/viber-elements/lib/viberAPI/message.ts index 55c1a00..944721c 100644 --- a/packages/viber-elements/lib/viberAPI/message.ts +++ b/packages/viber-elements/lib/viberAPI/message.ts @@ -14,7 +14,7 @@ import { Carousel } from './carousel'; export class Message implements ISerializable { public sender: ISender; public tracking_data?: string | Record; - public type?: MessageType; + public type: MessageType; public text?: string; public attachment?: Picture; public rich_media?: RichMedia | Carousel; @@ -26,10 +26,9 @@ export class Message implements ISerializable { * @param {MessageOptions|string} options - The message elements */ constructor(options: IMessageOptions) { - const { sender, tracking_data, type, attachment, keyboard } = options; + const { sender, tracking_data, attachment, keyboard } = options; this.sender = sender; this.tracking_data = tracking_data; - this.type = type; this.attachment = attachment; this.keyboard = keyboard; @@ -60,7 +59,6 @@ export class Message implements ISerializable { /* * Common for all Serialized messages **/ - const obj: ISerializedGeneralMessage = { type: this.determineType(), sender: this.sender, @@ -85,14 +83,26 @@ export class Message implements ISerializable { /* * Properties that depend on the type of message **/ - let objR: Partial = obj; - if (this.rich_media !== undefined) { - objR = { ...obj, rich_media: this.rich_media.serialize() }; - } else if (this.media !== undefined) { - objR = { ...obj, media: this.media }; - } else if (this.text !== undefined) { - objR = { ...obj, text: this.text }; + // let objR: Partial = obj; + + switch (this.type) { + case 'text': + if (this.text === undefined) { + throw new Error('This should never happen'); + } + return { ...obj, text: this.text }; + case 'rich_media': + if (this.rich_media === undefined) { + throw new Error('This should never happen'); + } + return { ...obj, rich_media: this.rich_media.serialize() }; + case 'url': + if (this.media === undefined) { + throw new Error('This should never happen'); + } + return { ...obj, media: this.media }; } - return objR as ISerializedMessage; + + throw new Error('This should never happen'); } } From de73e740b83eec90dadb601097395cc2def6856b Mon Sep 17 00:00:00 2001 From: Dimitrios Gkegkas Date: Mon, 17 May 2021 10:49:44 +0300 Subject: [PATCH 6/7] Add type guard in message class --- .../viber-elements/lib/viberAPI/message.ts | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/viber-elements/lib/viberAPI/message.ts b/packages/viber-elements/lib/viberAPI/message.ts index 944721c..c424f73 100644 --- a/packages/viber-elements/lib/viberAPI/message.ts +++ b/packages/viber-elements/lib/viberAPI/message.ts @@ -4,12 +4,25 @@ import { ISender, MessageType, ISerializedMessage, - ISerializedGeneralMessage + ISerializedGeneralMessage, + ITextOptions, + IURLOptions, + IRichMediaMessageOptions } from './interfaces'; import { Picture, RichMedia } from './attachments'; import { Keyboard } from './keyboard'; import { Carousel } from './carousel'; +function isText(options: IMessageOptions): options is ITextOptions { + return (options as ITextOptions).text !== undefined; +} +function isUrl(options: IMessageOptions): options is IURLOptions { + return (options as IURLOptions).media !== undefined; +} +function isRichMedia(options: IMessageOptions): options is IRichMediaMessageOptions { + return (options as IRichMediaMessageOptions).rich_media !== undefined; +} + /** Message Class */ export class Message implements ISerializable { public sender: ISender; @@ -31,19 +44,24 @@ export class Message implements ISerializable { this.tracking_data = tracking_data; this.attachment = attachment; this.keyboard = keyboard; + this.type = 'text'; - if ('media' in options) { + if (isUrl(options)) { const { media } = options; this.media = media; this.type = 'url'; - } else if ('rich_media' in options) { + } else if (isRichMedia(options)) { const { rich_media } = options; this.rich_media = rich_media; this.type = 'rich_media'; - } else { + } else if (isText(options)) { const { text } = options; this.text = text; this.type = 'text'; + } else { + const _exhaustiveCheck: never = options; + console.log(_exhaustiveCheck); + throw new Error('This should never happen'); } } From d79e15d73e2fc1e665b53d7b0e5edfdbcf470768 Mon Sep 17 00:00:00 2001 From: Dimitrios Gkegkas Date: Mon, 17 May 2021 11:11:51 +0300 Subject: [PATCH 7/7] Deal commends --- packages/viber-elements/lib/viberAPI/message.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/viber-elements/lib/viberAPI/message.ts b/packages/viber-elements/lib/viberAPI/message.ts index c424f73..e3cc815 100644 --- a/packages/viber-elements/lib/viberAPI/message.ts +++ b/packages/viber-elements/lib/viberAPI/message.ts @@ -101,7 +101,6 @@ export class Message implements ISerializable { /* * Properties that depend on the type of message **/ - // let objR: Partial = obj; switch (this.type) { case 'text':