前提・実現したいこと
Discord4Jを使ってBotを作成し、特定の発言に対してbotが返答を行うだけの簡単なプログラムを書いています。
メッセージを返信する機能を実装中に以下のエラーメッセージが発生しました。
発生している問題・エラーメッセージ
Message could not be sent with error: sx.blah.discord.util.DiscordException: Attempt to send message before shard is ready! at sx.blah.discord.api.IShard.checkReady(IShard.java:73) at sx.blah.discord.handle.impl.obj.Channel.sendMessage(Channel.java:459) at sx.blah.discord.handle.impl.obj.Channel.sendMessage(Channel.java:449) at sx.blah.discord.handle.impl.obj.Channel.sendMessage(Channel.java:439) at main.com.ensemblebox.iberisbot.BotUtils.lambda$sendMessage$0(BotUtils.java:30) at sx.blah.discord.util.RequestBuffer.lambda$request$1(RequestBuffer.java:84) at sx.blah.discord.util.RequestBuffer$RequestFuture$RequestCallable.call(RequestBuffer.java:286) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at sx.blah.discord.util.RequestBuffer$RequestFuture.run(RequestBuffer.java:259) at sx.blah.discord.util.RequestBuffer$RequestFuture.access$200(RequestBuffer.java:162) at sx.blah.discord.util.RequestBuffer.lambda$request$0(RequestBuffer.java:50) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:844)
該当のソースコード
java
1/*Main.java*/ 2package main.com.marumaru.bot; 3 4import sx.blah.discord.api.IDiscordClient; 5 6public class Main { 7 8 public static void main(String[] args) { 9 10 if(args.length != 1){ 11 System.out.println("Please enter the bots token as the first argument e.g java -jar thisjar.jar tokenhere"); 12 return; 13 } 14 15 IDiscordClient client = BotUtils.getBuiltDiscordClient(args[0]); 16 17 /* 18 // Commented out as you don't really want duplicate listeners unless you're intentionally writing your code 19 // like that. 20 // Register a listener via the IListener interface 21 cli.getDispatcher().registerListener(new IListener<MessageReceivedEvent>() { 22 public void handle(MessageReceivedEvent event) { 23 if(event.getMessage().getContent().startsWith(BotUtils.BOT_PREFIX + "test")) 24 BotUtils.sendMessage(event.getChannel(), "I am sending a message from an IListener listener"); 25 } 26 }); 27 */ 28 29 // Register a listener via the EventSubscriber annotation which allows for organisation and delegation of events 30 client.getDispatcher().registerListener(new MyEvents()); 31 32 // Only login after all events are registered otherwise some may be missed. 33 client.login(); 34 } 35 36}
java
1/*BotUtils.java*/ 2package main.com.marumaru.bot; 3 4import sx.blah.discord.api.ClientBuilder; 5import sx.blah.discord.api.IDiscordClient; 6import sx.blah.discord.handle.obj.IChannel; 7import sx.blah.discord.util.DiscordException; 8import sx.blah.discord.util.RequestBuffer; 9 10class BotUtils { 11 12 // Constants for use throughout the bot 13 static String BOT_PREFIX = "i!"; 14 15 // Handles the creation and getting of a IDiscordClient object for a token 16 static IDiscordClient getBuiltDiscordClient(String token) { 17 18 // The ClientBuilder object is where you will attach your params for configuring the instance of your bot. 19 // Such as withToken, setDaemon etc 20 return new ClientBuilder() 21 .withToken(token) 22 .build(); 23 24 } 25 26 // Helper functions to make certain aspects of the bot easier to use. 27 static void sendMessage(IChannel channel, String message){ 28 // This might look weird but it'll be explained in another page. 29 RequestBuffer.request(() -> { 30 try{ 31 channel.sendMessage(message);/* 問題の30行目 */ 32 } catch (DiscordException e){ 33 System.err.println("Message could not be sent with error: "); 34 e.printStackTrace(); 35 } 36 }); 37 38 /* 39 // The below example is written to demonstrate sending a message if you want to catch the RLE for logging purposes 40 RequestBuffer.request(() -> { 41 try{ 42 channel.sendMessage(message); 43 } catch (RateLimitException e){ 44 System.out.println("Do some logging"); 45 throw e; 46 } 47 }); 48 */ 49 50 } 51} 52
java
1/* MyEvents.java*/ 2package main.com.marumaru.bot; 3 4import sx.blah.discord.api.events.EventSubscriber; 5import sx.blah.discord.handle.impl.events.ReadyEvent; 6import sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent; 7 8public class MyEvents { 9 10 @EventSubscriber 11 public void onReady(ReadyEvent event) { 12 System.out.println("Bot is Stand by ready."); 13 } 14 15 @EventSubscriber 16 public void onMessageReceived(MessageReceivedEvent event) { 17 System.out.println(event.getMessage().getContent()); 18 if(event.getMessage().getContent().startsWith(BotUtils.BOT_PREFIX + "test")) 19 BotUtils.sendMessage(event.getChannel(), "I am sending a message from an EventSubscriber listener"); 20 } 21 22}
試したこと
Readyする前にメッセージの送信を行っているからエラーを吐いているのだと思いますが…
参照したQiitaの記事ではログインが完了するとReadyEventsが実行されるとありましたので、client.isLoggedIn()やclient.isReady()などで状態を確認しましたが、ログインはtrueが帰るのに対し、isReadyはfalseを返し続けてしまい。良く分かっていない状態です…
何卒みなさんのお力をお貸ししていただけないでしょうか…?
補足情報(FW/ツールのバージョンなど)
Intellij IDEA
JavaSE10
ソースコード自体はこれと全く同じです。
https://discord4j.readthedocs.io/en/latest/Basic-bot/
あなたの回答
tips
プレビュー