Aller au contenu
Afficher dans l'application

Une meilleure façon de naviguer. En savoir plus.

Asterobot

Une application plein écran sur votre écran d'accueil avec notifications push, badges et plus encore.

Pour installer cette application sur iOS et iPadOS
  1. Appuyez sur Icône de partage dans Safari
  2. Faites défiler le menu et appuyez sur Ajouter à l'écran d'accueil.
  3. Appuyez sur Ajouter dans le coin supérieur droit.
Pour installer cette application sur Android
  1. Appuyez sur le menu à trois points (⋮) dans le coin supérieur droit du navigateur.
  2. Appuyez sur Ajouter à l'écran d'accueil ou Installer l'application.
  3. Confirmez en appuyant sur Installer.

Send messages

Send a message with send(), wait for the game's answer with wait(), know when request() applies, and handle timeouts.

Reading the game is half of what a script does. Here the chat script learns to answer: when someone says !hello, the bot replies in chat and checks that its reply went through.

Warning

On a MITM bot (man-in-the-middle: the bot relays the game session of the Dofus client you play), everything the script sends goes out as your character. The reply on this page is a real chat message that other players can see.

Tip

This page sends the chat message itself, to learn the protocol. In a real package, asterobot:chat's say() sends it through the bot's chat guard, which waits out a channel's cooldown and keeps to the game's limits.

Try the message by hand first

Before writing code, send the message from the Network tool. If it works there, you know the payload is right.

  1. On the bot's page, open Tools > Network > Send a game message.
  2. Keep To the server selected, and pick ChatChannelMessageRequest in the list of messages.
  3. Type some text in content and leave the other fields as they are. Empty fields aren't sent, and a channel left out means GLOBAL, the general channel.
  4. Check the payload under This is what will be sent., then click Send ChatChannelMessageRequest.

Your line appears in the game. If ChatChannelMessageEvent is selected in Settings, Traffic also shows your request going Out and your line coming back In.

send()

await send("ChatChannelMessageRequest", { channel: "GLOBAL", content: "Hello" });

send() takes a message name and a payload holding the message's fields. It builds the message and puts it in line to go to the game server, and its promise resolves at once: it doesn't wait for an answer. Messages leave in the order you send them.

The promise rejects when the message can't be built:

Problem Error
A field the message doesn't have ChatChannelMessageRequest.contnt: unknown protobuf field
A value of the wrong type ChatChannelMessageRequest.content: expected string
A channel name that doesn't exist ChatChannelMessageRequest.channel: unknown enum symbol "GENERAL"
A message name Asterobot can't send semantic protobuf message is not mapped: MyMessageRequest

channel takes a channel's name as a string, such as "GLOBAL", "GUILD" or "PARTY", or the channel's number. The Dofus protocol reference lists every channel.

Wait for the answer

The game doesn't answer a chat line with a response. It sends the line to everyone on the channel as a ChatChannelMessageEvent, you included. To know your line went through, wait for that event.

Send, then wait:

await send("ChatChannelMessageRequest", { channel: "GLOBAL", content: "Hello" });

await wait(
  (traffic) => traffic.type === "ChatChannelMessageEvent" && traffic.payload?.content === "Hello",
  { timeout: 5000 },
);

A wait only sees messages the bot handles after wait() is called. send() resolves before any answer can be handled, so a wait started right after await send() always gets the answer, however fast it comes. Waiting explains more.

wait() resolves with the next inbound message that matches, and you choose what matches: a message name, or a function that returns true for the message you want. The function above checks the name and the text, so another player's line doesn't count.

wait() has no timeout of its own. A wait that never matches stays open until the script stops, so always pass { timeout }, in milliseconds. When the time runs out, the promise rejects with protocol wait timed out.

request()

request() sends a message and resolves with the game's response to it. Only a handful of Dofus requests get a response, matched to them by uid, and none of them is something a first script needs to send. For every other message nothing comes back: request() waits until its timeout, 30 seconds unless you pass another one, and then rejects with context deadline exceeded.

So for almost everything, wait for the event the game answers with while you send(), as this page does. Sending covers request(), and the to option that sends a message to the Dofus client instead of the server.

Timeouts

Function Default timeout To change it
send() None needed: it resolves as soon as the message is in line
request() 30 seconds { timeout: milliseconds } as the third argument
wait() None: it waits until the script stops { timeout: milliseconds } as the second argument

A timeout must be a positive number of milliseconds. Anything else rejects with timeout/milliseconds must be a finite positive Number.

The complete script

import { session, botInfo, botWarn } from "asterobot:bot";
import { on, send, wait } from "asterobot:protocol";

const TRIGGER = "!hello";
const REPLY = "Hello from my first script";

export default async function behavior(launch) {
  on("ChatChannelMessageEvent", async (traffic) => {
    // Only the exact trigger: the game also sends our own reply back to us,
    // and answering that echo would start a loop.
    if (traffic.payload?.content !== TRIGGER) return;

    try {
      await send("ChatChannelMessageRequest", { channel: "GLOBAL", content: REPLY });
      // Started right after the send, so even a quick echo isn't missed.
      await wait(
        (echo) => echo.type === "ChatChannelMessageEvent" && echo.payload?.content === REPLY,
        { timeout: 5000 },
      );
      botInfo("Reply delivered");
    } catch (error) {
      // An error that escapes a handler stops the whole script.
      botWarn("Reply not delivered:", String(error));
    }
  });

  // A new game connection starts with this message. MITM bots never launch
  // with "initial": the Dofus client has already identified their session.
  if (launch.reason === "initial") {
    await send("IdentificationRequest", {
      ticketKey: session.gameToken,
      languageCode: session.language,
    });
  }
}

The handler is async so that it can await. Handlers don't wait for each other: while this one waits for the echo, the bot keeps handling other messages, the echo included, which is how wait() gets to see it.

The try/catch keeps a failed reply from ending the script, and String(error) turns the error into text the console can print.

Anyone who says !hello on a channel your character receives gets an answer in the general channel, so stop the script when you're done testing.

Test it

  1. Run the package on your MITM bot.
  2. Say !hello in the Dofus chat.
  3. The bot answers in the general channel, and its Console shows Reply delivered.

If the console shows Reply not delivered: followed by a reason, select ChatChannelMessageRequest and ChatChannelMessageEvent in the Network tool's Settings, try again, and check in Traffic whether the request went out and whether the line came back.

Next, Add a setting lets people change the trigger and the reply without editing your code. Waiting covers every way to wait for a message.

Compte

Navigation

Recherche

Recherche

Configurer les notifications push du navigateur

Chrome (Android)
  1. Appuyez sur l'icône de cadenas à côté de la barre d'adresse.
  2. Tap Autorisations → Notifications.
  3. Ajustez vos préférences.
Chrome (Desktop)
  1. Cliquez sur l'icône représentant un cadenas dans la barre d'adresse..
  2. Select Paramètres du site.
  3. Find Notifications et ajustez vos préférences.