@grom.js/effect-tg 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +387 -22
  2. package/dist/BotApi.d.ts +32 -0
  3. package/dist/BotApi.d.ts.map +1 -1
  4. package/dist/BotApi.js +16 -0
  5. package/dist/BotApi.js.map +1 -1
  6. package/dist/BotApiError.js +1 -1
  7. package/dist/BotApiError.js.map +1 -1
  8. package/dist/Dialog.d.ts +24 -23
  9. package/dist/Dialog.d.ts.map +1 -1
  10. package/dist/Dialog.js +15 -17
  11. package/dist/Dialog.js.map +1 -1
  12. package/dist/Markup.d.ts +200 -11
  13. package/dist/Markup.d.ts.map +1 -1
  14. package/dist/Markup.js +39 -0
  15. package/dist/Markup.js.map +1 -1
  16. package/dist/Reply.d.ts +22 -0
  17. package/dist/Reply.d.ts.map +1 -0
  18. package/dist/Reply.js +18 -0
  19. package/dist/Reply.js.map +1 -0
  20. package/dist/Send.d.ts +16 -1
  21. package/dist/Send.d.ts.map +1 -1
  22. package/dist/Send.js +28 -5
  23. package/dist/Send.js.map +1 -1
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/internal/botApi.gen.d.ts +263 -191
  29. package/dist/internal/botApi.gen.d.ts.map +1 -1
  30. package/dist/internal/dialog.d.ts +4 -4
  31. package/dist/internal/dialog.d.ts.map +1 -1
  32. package/dist/internal/dialog.js +12 -13
  33. package/dist/internal/dialog.js.map +1 -1
  34. package/dist/internal/send.d.ts +4 -1
  35. package/dist/internal/send.d.ts.map +1 -1
  36. package/dist/internal/send.js +150 -6
  37. package/dist/internal/send.js.map +1 -1
  38. package/package.json +11 -10
  39. package/src/BotApi.ts +62 -0
  40. package/src/BotApiError.ts +1 -1
  41. package/src/Dialog.ts +31 -30
  42. package/src/Markup.ts +251 -11
  43. package/src/Reply.ts +36 -0
  44. package/src/Send.ts +51 -17
  45. package/src/index.ts +1 -0
  46. package/src/internal/botApi.gen.ts +267 -191
  47. package/src/internal/dialog.ts +16 -17
  48. package/src/internal/send.ts +170 -6
package/src/Markup.ts CHANGED
@@ -1,5 +1,9 @@
1
- import type * as Option from 'effect/Option'
2
1
  import * as Data from 'effect/Data'
2
+ import * as Option from 'effect/Option'
3
+
4
+ // =============================================================================
5
+ // Markup
6
+ // =============================================================================
3
7
 
4
8
  /**
5
9
  * Reply markup for the message.
@@ -11,23 +15,259 @@ export type Markup =
11
15
  | ForceReply
12
16
 
13
17
  export class InlineKeyboard extends Data.TaggedClass('InlineKeyboard')<{
14
- rows: [] // TODO
18
+ readonly rows: ReadonlyArray<ReadonlyArray<InlineButton>>
15
19
  }> {}
16
20
 
17
21
  export class ReplyKeyboard extends Data.TaggedClass('ReplyKeyboard')<{
18
- rows: [] // TODO
19
- persistent: boolean
20
- resizable: boolean
21
- oneTime: boolean
22
- selective: boolean
23
- inputPlaceholder: Option.Option<string>
22
+ readonly rows: ReadonlyArray<ReadonlyArray<ReplyButton>>
23
+ readonly persistent: boolean
24
+ readonly resizable: boolean
25
+ readonly oneTime: boolean
26
+ readonly selective: boolean
27
+ readonly inputPlaceholder: Option.Option<string>
24
28
  }> {}
25
29
 
26
30
  export class ReplyKeyboardRemove extends Data.TaggedClass('ReplyKeyboardRemove')<{
27
- selective: boolean
31
+ readonly selective: boolean
28
32
  }> {}
29
33
 
30
34
  export class ForceReply extends Data.TaggedClass('ForceReply')<{
31
- selective: boolean
32
- inputPlaceholder: Option.Option<string>
35
+ readonly selective: boolean
36
+ readonly inputPlaceholder: Option.Option<string>
33
37
  }> {}
38
+
39
+ // =============================================================================
40
+ // Constructors
41
+ // =============================================================================
42
+
43
+ export const inlineKeyboard = (
44
+ rows: ReadonlyArray<ReadonlyArray<InlineButton>>,
45
+ ): InlineKeyboard => new InlineKeyboard({ rows })
46
+
47
+ export const replyKeyboard = (
48
+ rows: ReadonlyArray<ReadonlyArray<ReplyButton>>,
49
+ options?: {
50
+ readonly persistent?: boolean
51
+ readonly resizable?: boolean
52
+ readonly oneTime?: boolean
53
+ readonly selective?: boolean
54
+ readonly inputPlaceholder?: string
55
+ },
56
+ ): ReplyKeyboard =>
57
+ new ReplyKeyboard({
58
+ rows,
59
+ persistent: options?.persistent ?? false,
60
+ resizable: options?.resizable ?? false,
61
+ oneTime: options?.oneTime ?? false,
62
+ selective: options?.selective ?? false,
63
+ inputPlaceholder: Option.fromNullable(options?.inputPlaceholder),
64
+ })
65
+
66
+ export const replyKeyboardRemove = (options?: { readonly selective?: boolean }): ReplyKeyboardRemove =>
67
+ new ReplyKeyboardRemove({ selective: options?.selective ?? false })
68
+
69
+ export const forceReply = (options?: {
70
+ readonly selective?: boolean
71
+ readonly inputPlaceholder?: string
72
+ }): ForceReply =>
73
+ new ForceReply({
74
+ selective: options?.selective ?? false,
75
+ inputPlaceholder: Option.fromNullable(options?.inputPlaceholder),
76
+ })
77
+
78
+ // =============================================================================
79
+ // Inline button
80
+ // =============================================================================
81
+
82
+ /**
83
+ * Button of an inline keyboard.
84
+ *
85
+ * Exactly one action field must be specified per button.
86
+ */
87
+ export type InlineButton =
88
+ | { readonly text: string, readonly url: string } & ButtonAppearance
89
+ | { readonly text: string, readonly callbackData: string } & ButtonAppearance
90
+ | { readonly text: string, readonly webApp: WebAppInfo } & ButtonAppearance
91
+ | { readonly text: string, readonly loginUrl: LoginUrl } & ButtonAppearance
92
+ | { readonly text: string, readonly switchInlineQuery: string } & ButtonAppearance
93
+ | { readonly text: string, readonly switchInlineQueryCurrentChat: string } & ButtonAppearance
94
+ | { readonly text: string, readonly switchInlineQueryChosenChat: SwitchInlineQueryChosenChat } & ButtonAppearance
95
+ | { readonly text: string, readonly copyText: string } & ButtonAppearance
96
+ | { readonly text: string, readonly callbackGame: CallbackGame } & ButtonAppearance
97
+ | { readonly text: string, readonly pay: true } & ButtonAppearance
98
+
99
+ export const InlineButton = {
100
+ url: (text: string, url: string, options?: ButtonAppearance): InlineButton =>
101
+ ({ text, url, ...options }),
102
+
103
+ callback: (text: string, callbackData: string, options?: ButtonAppearance): InlineButton =>
104
+ ({ text, callbackData, ...options }),
105
+
106
+ webApp: (text: string, url: string, options?: ButtonAppearance): InlineButton =>
107
+ ({ text, webApp: { url }, ...options }),
108
+
109
+ loginUrl: (text: string, loginUrl: LoginUrl, options?: ButtonAppearance): InlineButton =>
110
+ ({ text, loginUrl, ...options }),
111
+
112
+ switchInline: (text: string, query?: string, options?: ButtonAppearance): InlineButton =>
113
+ ({ text, switchInlineQuery: query ?? '', ...options }),
114
+
115
+ switchInlineCurrentChat: (text: string, query?: string, options?: ButtonAppearance): InlineButton =>
116
+ ({ text, switchInlineQueryCurrentChat: query ?? '', ...options }),
117
+
118
+ switchInlineChosenChat: (text: string, chosenChat?: SwitchInlineQueryChosenChat, options?: ButtonAppearance): InlineButton =>
119
+ ({ text, switchInlineQueryChosenChat: chosenChat ?? {}, ...options }),
120
+
121
+ copyText: (text: string, copyText: string, options?: ButtonAppearance): InlineButton =>
122
+ ({ text, copyText, ...options }),
123
+
124
+ callbackGame: (text: string, options?: ButtonAppearance): InlineButton =>
125
+ ({ text, callbackGame: {}, ...options }),
126
+
127
+ pay: (text: string): InlineButton =>
128
+ ({ text, pay: true as const }),
129
+ }
130
+
131
+ // =============================================================================
132
+ // Reply button
133
+ // =============================================================================
134
+
135
+ /**
136
+ * Button of a custom reply keyboard.
137
+ *
138
+ * - For simple text buttons, the string can be used instead of an object.
139
+ * - At most one action field may be specified per button.
140
+ */
141
+ export type ReplyButton =
142
+ | string
143
+ | { readonly text: string } & ButtonAppearance
144
+ | { readonly text: string, readonly requestUsers: RequestUsers } & ButtonAppearance
145
+ | { readonly text: string, readonly requestChat: RequestChat } & ButtonAppearance
146
+ | { readonly text: string, readonly requestContact: true } & ButtonAppearance
147
+ | { readonly text: string, readonly requestLocation: true } & ButtonAppearance
148
+ | { readonly text: string, readonly requestPoll: true | 'quiz' | 'regular' } & ButtonAppearance
149
+ | { readonly text: string, readonly webApp: WebAppInfo } & ButtonAppearance
150
+
151
+ export const ReplyButton = {
152
+ text: (text: string, options?: ButtonAppearance): ReplyButton => ({ text, ...options }),
153
+
154
+ requestUsers: (text: string, requestUsers: RequestUsers, options?: ButtonAppearance): ReplyButton =>
155
+ ({ text, requestUsers, ...options }),
156
+
157
+ requestChat: (text: string, requestChat: RequestChat, options?: ButtonAppearance): ReplyButton =>
158
+ ({ text, requestChat, ...options }),
159
+
160
+ requestContact: (text: string, options?: ButtonAppearance): ReplyButton =>
161
+ ({ text, requestContact: true, ...options }),
162
+
163
+ requestLocation: (text: string, options?: ButtonAppearance): ReplyButton =>
164
+ ({ text, requestLocation: true, ...options }),
165
+
166
+ requestPoll: (text: string, type?: 'quiz' | 'regular', options?: ButtonAppearance): ReplyButton =>
167
+ ({ text, requestPoll: type ?? true, ...options }),
168
+
169
+ webApp: (text: string, url: string, options?: ButtonAppearance): ReplyButton =>
170
+ ({ text, webApp: { url }, ...options }),
171
+ }
172
+
173
+ // =============================================================================
174
+ // Miscellaneous
175
+ // =============================================================================
176
+
177
+ /**
178
+ * Button style for inline and reply keyboards.
179
+ */
180
+ export type ButtonStyle = 'danger' | 'success' | 'primary'
181
+
182
+ /**
183
+ * Appearance options for inline and reply keyboard buttons.
184
+ */
185
+ export interface ButtonAppearance {
186
+ readonly style?: ButtonStyle
187
+ readonly iconEmojiId?: string
188
+ }
189
+
190
+ /**
191
+ * Information about a Web App (a.k.a. Mini App).
192
+ */
193
+ export interface WebAppInfo {
194
+ readonly url: string
195
+ }
196
+
197
+ /**
198
+ * Login URL for inline keyboard buttons.
199
+ */
200
+ export interface LoginUrl {
201
+ readonly url: string
202
+ readonly forwardText?: string
203
+ readonly botUsername?: string
204
+ readonly requestWriteAccess?: boolean
205
+ }
206
+
207
+ /**
208
+ * Switch inline query chosen chat options.
209
+ */
210
+ export interface SwitchInlineQueryChosenChat {
211
+ readonly query?: string
212
+ readonly allowUserChats?: boolean
213
+ readonly allowBotChats?: boolean
214
+ readonly allowGroupChats?: boolean
215
+ readonly allowChannelChats?: boolean
216
+ }
217
+
218
+ /**
219
+ * Placeholder for a game button. Use [BotFather](https://t.me/botfather) to set up your game.
220
+ */
221
+ export interface CallbackGame {}
222
+
223
+ /**
224
+ * Criteria for requesting suitable users. Used with request_users.
225
+ */
226
+ export interface RequestUsers {
227
+ readonly requestId: number
228
+ readonly userIsBot?: boolean
229
+ readonly userIsPremium?: boolean
230
+ readonly maxQuantity?: number
231
+ readonly requestName?: boolean
232
+ readonly requestUsername?: boolean
233
+ readonly requestPhoto?: boolean
234
+ }
235
+
236
+ /**
237
+ * Rights of an administrator in a chat.
238
+ */
239
+ export interface ChatAdminRights {
240
+ readonly isAnonymous: boolean
241
+ readonly canManageChat: boolean
242
+ readonly canDeleteMessages: boolean
243
+ readonly canManageVideoChats: boolean
244
+ readonly canRestrictMembers: boolean
245
+ readonly canPromoteMembers: boolean
246
+ readonly canChangeInfo: boolean
247
+ readonly canInviteUsers: boolean
248
+ readonly canPostStories: boolean
249
+ readonly canEditStories: boolean
250
+ readonly canDeleteStories: boolean
251
+ readonly canPostMessages?: boolean
252
+ readonly canEditMessages?: boolean
253
+ readonly canPinMessages?: boolean
254
+ readonly canManageTopics?: boolean
255
+ readonly canManageDirectMessages?: boolean
256
+ }
257
+
258
+ /**
259
+ * Criteria for requesting a suitable chat. Used with request_chat.
260
+ */
261
+ export interface RequestChat {
262
+ readonly requestId: number
263
+ readonly chatIsChannel: boolean
264
+ readonly chatIsForum?: boolean
265
+ readonly chatHasUsername?: boolean
266
+ readonly chatIsCreated?: boolean
267
+ readonly userAdministratorRights?: ChatAdminRights
268
+ readonly botAdministratorRights?: ChatAdminRights
269
+ readonly botIsMember?: boolean
270
+ readonly requestTitle?: boolean
271
+ readonly requestUsername?: boolean
272
+ readonly requestPhoto?: boolean
273
+ }
package/src/Reply.ts ADDED
@@ -0,0 +1,36 @@
1
+ import type * as BotApi from './BotApi.ts'
2
+ import * as Data from 'effect/Data'
3
+ import * as Option from 'effect/Option'
4
+ import * as Dialog from './Dialog.ts'
5
+
6
+ export class Reply extends Data.Class<{
7
+ dialog: Dialog.Peer | Dialog.DialogId
8
+ messageId: number
9
+ optional: boolean
10
+ taskId: Option.Option<number>
11
+ }> {}
12
+
13
+ export const make = (args: {
14
+ dialog: Dialog.Peer | Dialog.DialogId
15
+ messageId: number
16
+ optional?: boolean
17
+ taskId?: number
18
+ }): Reply => new Reply({
19
+ dialog: args.dialog,
20
+ messageId: args.messageId,
21
+ optional: args.optional ?? false,
22
+ taskId: Option.fromNullable(args.taskId),
23
+ })
24
+
25
+ export const toMessage = (
26
+ message: BotApi.Types.Message,
27
+ options?: {
28
+ optional?: boolean
29
+ taskId?: number
30
+ },
31
+ ): Reply => new Reply({
32
+ dialog: Dialog.DialogId(message.chat.id),
33
+ messageId: message.message_id,
34
+ optional: options?.optional ?? false,
35
+ taskId: Option.fromNullable(options?.taskId),
36
+ })
package/src/Send.ts CHANGED
@@ -7,6 +7,7 @@ import type * as BotApiError from './BotApiError.ts'
7
7
  import type * as Content from './Content.ts'
8
8
  import type * as Dialog from './Dialog.ts'
9
9
  import type * as Markup from './Markup.ts'
10
+ import type * as Reply from './Reply.ts'
10
11
  import * as Context from 'effect/Context'
11
12
  import * as Data from 'effect/Data'
12
13
  import * as Effect from 'effect/Effect'
@@ -26,8 +27,9 @@ import * as internal from './internal/send.ts'
26
27
  export const sendMessage: (params: {
27
28
  content: Content.Content
28
29
  dialog: Dialog.Dialog | Dialog.DialogId
29
- options?: Options
30
30
  markup?: Markup.Markup
31
+ reply?: Reply.Reply
32
+ options?: Options
31
33
  }) => Effect.Effect<
32
34
  BotApi.Types.Message,
33
35
  BotApiError.BotApiError,
@@ -56,6 +58,7 @@ export interface MessageToSend extends
56
58
  readonly [MessageToSendTypeId]: typeof MessageToSendTypeId
57
59
  readonly content: Content.Content
58
60
  readonly markup?: Markup.Markup
61
+ readonly reply?: Reply.Reply
59
62
  readonly options?: Options
60
63
  }
61
64
 
@@ -72,6 +75,7 @@ const MessageToSendProto = {
72
75
  dialog,
73
76
  content: this.content,
74
77
  markup: this.markup,
78
+ reply: this.reply,
75
79
  options: this.options,
76
80
  }),
77
81
  )
@@ -82,6 +86,7 @@ const MessageToSendProto = {
82
86
  _id: this[MessageToSendTypeId].description,
83
87
  content: this.content,
84
88
  markup: this.markup,
89
+ reply: this.reply,
85
90
  options: this.options,
86
91
  }
87
92
  },
@@ -93,11 +98,13 @@ const MessageToSendProto = {
93
98
  */
94
99
  export const message = (content: Content.Content, params?: {
95
100
  markup?: Markup.Markup
101
+ reply?: Reply.Reply
96
102
  options?: Options
97
103
  }): MessageToSend => {
98
104
  const self = Object.create(MessageToSendProto)
99
105
  self.content = content
100
106
  self.markup = params?.markup
107
+ self.reply = params?.reply
101
108
  self.options = params?.options
102
109
  return self
103
110
  }
@@ -140,12 +147,11 @@ export const withMarkup: {
140
147
  } = Function.dual(2, (
141
148
  self: MessageToSend,
142
149
  markup: Markup.Markup,
143
- ): MessageToSend => (
144
- message(self.content, {
145
- markup,
146
- options: self.options,
147
- })
148
- ))
150
+ ): MessageToSend => message(self.content, {
151
+ markup,
152
+ reply: self.reply,
153
+ options: self.options,
154
+ }))
149
155
 
150
156
  /**
151
157
  * Removes the reply markup from the message.
@@ -153,7 +159,36 @@ export const withMarkup: {
153
159
  export const withoutMarkup: (
154
160
  self: MessageToSend,
155
161
  ) => MessageToSend = self => message(self.content, {
156
- markup: undefined,
162
+ reply: self.reply,
163
+ options: self.options,
164
+ })
165
+
166
+ // =============================================================================
167
+ // Reply Options
168
+ // =============================================================================
169
+
170
+ /**
171
+ * Sets the information about the message to reply to.
172
+ */
173
+ export const withReply: {
174
+ (reply: Reply.Reply): (self: MessageToSend) => MessageToSend
175
+ (self: MessageToSend, reply: Reply.Reply): MessageToSend
176
+ } = Function.dual(2, (
177
+ self: MessageToSend,
178
+ reply: Reply.Reply,
179
+ ): MessageToSend => message(self.content, {
180
+ markup: self.markup,
181
+ reply,
182
+ options: self.options,
183
+ }))
184
+
185
+ /**
186
+ * Removes the reply options from the message.
187
+ */
188
+ export const withoutReply: (
189
+ self: MessageToSend,
190
+ ) => MessageToSend = self => message(self.content, {
191
+ markup: self.markup,
157
192
  options: self.options,
158
193
  })
159
194
 
@@ -190,15 +225,14 @@ export const withOptions: {
190
225
  } = Function.dual(2, (
191
226
  self: MessageToSend,
192
227
  options: Options,
193
- ): MessageToSend => (
194
- message(self.content, {
195
- markup: self.markup,
196
- options: new Options({
197
- ...self.options,
198
- ...options,
199
- }),
200
- })
201
- ))
228
+ ): MessageToSend => message(self.content, {
229
+ markup: self.markup,
230
+ reply: self.reply,
231
+ options: new Options({
232
+ ...self.options,
233
+ ...options,
234
+ }),
235
+ }))
202
236
 
203
237
  /**
204
238
  * Disables notification for the message.
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ export * as Dialog from './Dialog.ts'
8
8
  export * as File from './File.ts'
9
9
  export * as LinkPreview from './LinkPreview.ts'
10
10
  export * as Markup from './Markup.ts'
11
+ export * as Reply from './Reply.ts'
11
12
  export * as Runner from './Runner.ts'
12
13
  export * as Send from './Send.ts'
13
14
  export * as Text from './Text.ts'