コンテンツにスキップ

v0.x

  • クラス型ビルダーを廃止し、関数型ビルダーへ変更
  • ビルダーのコードを共通化
  • ビルダーにより生成された型の具体性を強化
  • ビルダー最適化に関する周辺コードの変更
new Command('autocomplete', 'auto').options(
new SubCommand('sub', 'sub command').options(
new Option('option', 'op').autocomplete().required(),
new Option('option2', 'op2').autocomplete(),
),
),
makeSlashCommand('autocomplete', 'auto').options([
makeSubCommand('sub', 'sub command').options([
makeStringOption('option', 'op').autocomplete(true).required(true),
makeStringOption('option2', 'op2').autocomplete(true),
]),
]),
  • Command -> makeSlashCommand, makeUserCommand, makeMessageCommand, or makeEntryPointCommand
  • SubCommand -> makeSubCommand
  • SubGroup -> makeSubCommandGroup
  • Option -> makeStringOption, makeIntegerOption, makeBooleanOption, makeUserOption, makeChannelOption, makeRoleOption, makeMentionableOption, makeNumberOption, or makeAttachmentOption
  • 一部の簡易記述で、正確な記述を求めるように変更
    • .required() -> .required(true) ‘true’ の自動処理を廃止し、明示的に記述
    • .options(option, option, ...) -> .options([option, option, ...]) 配列の自動処理を廃止し、明示的に記述
c.resAutocomplete(
new Autocomplete(c.focused?.value).choices(
{ name: 'test1', value: 'v-test1' },
{ name: 'test2', value: 'v-test2' },
),
),
c.resAutocomplete([
{ name: 'test1', value: 'v-test1' },
{ name: 'test2', value: 'v-test2' },
]),

※一致するコードではありません

  • Autocompleteクラスによる独自のフィルターを廃止
  • resAutocompleteが配列を受け入れるよう拡張
components: new Components().row(
new Button('https://discord-hono.luis.fun', ['📑', 'Docs'], 'Link'),
component_delete.component,
),
components: [
makeActionRow([
makeLinkButton('https://discord-hono.luis.fun', ['📑', 'Docs']),
component_delete.component,
]),
],
  • Components -> makeActionRow
  • Button -> makeButton, makeLinkButton, or makePremiumButton
await c.followup(
{
components: [
new Content('text top'),
new Layout('Container').components(
new Layout('Action Row').components(component_image_update2.component, component_delete.component),
new Layout('Separator'),
new Content('container - text'),
new Layout('Section')
.components(new Content('container - section - text'), new Content('container - section - text2'))
.accessory(new Content('image.webp', 'Thumbnail')),
new Content('container - text2'),
new Content('image.webp', 'Media Gallery'),
),
makeTextDisplay('text top'),
makeContainer([
makeActionRow([component_image_update2.component, component_delete.component]),
makeSeparator(),
makeTextDisplay('container - text'),
makeSection(
[makeTextDisplay('container - section - text'), makeTextDisplay('container - section - text2')],
makeThumbnail('attachment://image.webp'),
),
makeTextDisplay('container - text2'),
makeMediaGallery(['attachment://image.webp']),
]),
],
},
{ blob, name: 'image.webp' },
)
  • Content -> makeTextDisplay, makeThumbnail, makeMediaGallery, or makeFile
  • Layout -> makeActionRow, makeSection, makeSeparator, makeContainer, or makeLabel
new Modal('modal', 'Modal Test')
.row(new TextInput('modal_text', 'Modal Text').required())
.component('Channel Select', new Select('channel', 'Channel'))
makeModal('modal', 'Modal Test', [
makeActionRow([makeTextInput('modal_text', 'Modal Text').required(true)]),
makeLabel('Channel Select', makeChannelSelect('channel')),
]),
  • Modal -> makeModal, makeActionRow, and makeLabel
  • TextInput -> makeTextInput
new Embed()
makeEmbed()
new Poll()
.question('What is your favorite color?')
.answers(['🔴', 'Red'], ['🟢', 'Green'], 'Blue', 'Yellow')
.allow_multiselect()
.duration(1)
makePoll(
'What is your favorite color?',
[['🔴', 'Red'], ['🟢', 'Green'], 'Blue', 'Yellow']
)
.allow_multiselect(true)
.duration(1)
factory.command<{ text: string }>(...)
factory.command<any, { text: string }>(...)
  • 第一引数の型推測を行うように変更したため、型引数の一部を any などで対応
  • 簡易参照用の c.ref を追加
  • custom_id をより一貫性のある取り扱いをし、以前の custom_idcustom_value とする
  • rest-path の $_ を入れ替え
c.key
c.ref.key
c.var.custom_id
c.ref.custom_value
c.var.xxx (select values)
c.ref.values
(Button or Select).custom_id
(Button or Select).custom_value
await c.rest('POST', _channels_$_messages, [channel], { content: 'this is rest' })
await c.rest('POST', $channels$_$messages, [channel], { content: 'this is rest' })

GET メソッドは影響する可能性が高いです。

await c.rest(
'GET', _channels_$_messages,
[channel_id], { limit: 10 },
[channel_id, { limit: 10 }],
)
await c.rest('METHOD', 'PATH', ['PATH_VAR'], DATA_OBJ or QUERY_OBJ)
await c.rest('METHOD', 'PATH', ['PATH_VAR', QUERY_OBJ], DATA_OBJ)

Context の統合

const app = new DiscordHono().cron("", async c => {
console.log(c.cronEvent)
console.log(c.interaction)
})

CronContext を type 情報のみに変更

Section titled “CronContext を type 情報のみに変更”

v0.17.0 -> v0.18.0

return c.update().resDefer(c.followupDelete)
return c.update().resDefer(c => c.followup())

v0.16.x 以前 -> v0.18.0

return c.resDeferUpdate(c.followupDelete)
return c.update().resDefer(c => c.followup())

c.req は Hono の c.req と混同される可能性があり、また Discord Bot では Request オブジェクトを扱う必要がないため、削除されました。
もしこの機能がどうしても必要な場合は、代わりに Hono のミドルウェアを利用することを検討してください。
どうしても代替手段が見つからず、c.req が必要な場合は Issue を作成してください。

c.waitUntil() は、その機能が c.resDefer() に含まれており、使用頻度も低かったため削除されました。
代わりに c.executionCtx.waitUntil() を使用してください。

c.waitUntil(/*process*/)
c.executionCtx.waitUntil(/*process*/)

c.resUpdate(), c.resDeferUpdate() -> c.update()

Section titled “c.resUpdate(), c.resDeferUpdate() -> c.update()”
return c.resUpdate("update text")
return c.update().res("update text")
return c.resDeferUpdate("update text")
return c.update().resDefer("update text")

c.suppressEmbeds(), c.ephemeral(), c.suppressNotifications() -> c.flags()

Section titled “c.suppressEmbeds(), c.ephemeral(), c.suppressNotifications() -> c.flags()”
return c.ephemeral().suppressNotifications().res("ephemeral text")
return c.flags("EPHEMERAL", "SUPPRESS_NOTIFICATIONS").res("ephemeral text")

開発者の実装ミスによる意図しない破壊的変更

v0.16.5以前のバージョンでは、followup は POST を通して処理されていました。
v0.16.6以降では、followup は PATCH を通して処理されます。
これは、意図的に複数回 followup を呼び出している場合にのみ互換性を崩す変更となります。
そのような場合は、新しい followup を作成するために c.rest を使用してください。

const rest = new Rest('token')
const rest = createRest('token')
const res = c.rest.post(_channels_$_messages, [channel_id], { content: 'this is rest' })
const res = c.rest('POST', _channels_$_messages, [channel_id], { content: 'this is rest' })
const app = factory.discord()
factory.loader(app, Object.values(handlers))
.loader(Object.values(handlers))
export default app

Restにおけるgetメソッドの戻り値

Section titled “Restにおけるgetメソッドの戻り値”
const { result } = await c.rest.get('/applications/@me', [])
const result = await c.rest.get('/applications/@me', []).then(r => r.json())

正規表現キーをサポートしない

Section titled “正規表現キーをサポートしない”

.component() および .modal() では、正規表現キーの代わりに custom_id を使用してください。
正規表現キーをどうしても使用する必要がある場合は、この例を参照してください。

const app = new DiscordHono()
.command(/regex/, c => c.res('regex'))
.command('regex', c => c.res('regex'))
const handler= (c: ComponentContext<Env, 'Button'>) => {
const handler= (c: ComponentContext<Env, Button>) => {
//...
}
const func = (c: CommandContext<Env> | ComponentContext<Env>) => {
//...
if (c instanceof CommandContext)
if (c.interaction.type === 2)
//...
}