1- use super :: { types :: LifetimedPinnedBoxedFutureResult , Priority , Service , ServiceInfo , ServiceManager } ;
1+ use super :: { BoxedError , Priority , Service , ServiceInfo , ServiceManager } ;
22use log:: { error, info, warn} ;
33use serenity:: {
44 all:: { GatewayIntents , Ready } ,
@@ -52,97 +52,97 @@ impl DiscordService {
5252 }
5353}
5454
55+ //TODO: When Rust allows async trait methods to be object-safe, refactor this to not use async_trait anymore
56+ #[ async_trait]
5557impl Service for DiscordService {
5658 fn info ( & self ) -> & ServiceInfo {
5759 & self . info
5860 }
5961
60- fn start ( & mut self , _service_manager : Arc < ServiceManager > ) -> LifetimedPinnedBoxedFutureResult < ' _ , ( ) > {
61- Box :: pin ( async move {
62- let client_ready_notify = Arc :: new ( Notify :: new ( ) ) ;
62+ async fn start ( & mut self , _service_manager : Arc < ServiceManager > ) -> Result < ( ) , BoxedError > {
63+ let client_ready_notify = Arc :: new ( Notify :: new ( ) ) ;
6364
64- let framework = StandardFramework :: new ( ) ;
65- framework. configure ( Configuration :: new ( ) . prefix ( "!" ) ) ;
65+ let framework = StandardFramework :: new ( ) ;
66+ framework. configure ( Configuration :: new ( ) . prefix ( "!" ) ) ;
6667
67- let mut client = Client :: builder ( self . discord_token . as_str ( ) , GatewayIntents :: all ( ) )
68- . framework ( framework)
69- . event_handler ( EventHandler :: new (
70- Arc :: clone ( & self . ready ) ,
71- Arc :: clone ( & client_ready_notify) ,
72- ) )
73- . await ?;
68+ let mut client = Client :: builder ( self . discord_token . as_str ( ) , GatewayIntents :: all ( ) )
69+ . framework ( framework)
70+ . event_handler ( EventHandler :: new (
71+ Arc :: clone ( & self . ready ) ,
72+ Arc :: clone ( & client_ready_notify) ,
73+ ) )
74+ . await ?;
7475
75- if self . cache . set ( Arc :: clone ( & client. cache ) ) . is_err ( ) {
76- error ! ( "Could not set cache OnceLock because it was already set. This should never happen." ) ;
77- return Err ( "Could not set cache OnceLock because it was already set." . into ( ) ) ;
78- }
76+ if self . cache . set ( Arc :: clone ( & client. cache ) ) . is_err ( ) {
77+ error ! ( "Could not set cache OnceLock because it was already set. This should never happen." ) ;
78+ return Err ( "Could not set cache OnceLock because it was already set." . into ( ) ) ;
79+ }
7980
80- if self . data . set ( Arc :: clone ( & client. data ) ) . is_err ( ) {
81- error ! ( "Could not set data OnceLock because it was already set. This should never happen." ) ;
82- return Err ( "Could not set data OnceLock because it was already set." . into ( ) ) ;
83- }
81+ if self . data . set ( Arc :: clone ( & client. data ) ) . is_err ( ) {
82+ error ! ( "Could not set data OnceLock because it was already set. This should never happen." ) ;
83+ return Err ( "Could not set data OnceLock because it was already set." . into ( ) ) ;
84+ }
8485
85- if self . http . set ( Arc :: clone ( & client. http ) ) . is_err ( ) {
86- error ! ( "Could not set http OnceLock because it was already set. This should never happen." ) ;
87- return Err ( "Could not set http OnceLock because it was already set." . into ( ) ) ;
88- }
86+ if self . http . set ( Arc :: clone ( & client. http ) ) . is_err ( ) {
87+ error ! ( "Could not set http OnceLock because it was already set. This should never happen." ) ;
88+ return Err ( "Could not set http OnceLock because it was already set." . into ( ) ) ;
89+ }
8990
90- if self . shard_manager . set ( Arc :: clone ( & client. shard_manager ) ) . is_err ( ) {
91- error ! ( "Could not set shard_manager OnceLock because it was already set. This should never happen." ) ;
92- return Err ( "Could not set shard_manager OnceLock because it was already set." . into ( ) ) ;
93- }
91+ if self . shard_manager . set ( Arc :: clone ( & client. shard_manager ) ) . is_err ( ) {
92+ error ! (
93+ "Could not set shard_manager OnceLock because it was already set. This should never happen."
94+ ) ;
95+ return Err ( "Could not set shard_manager OnceLock because it was already set." . into ( ) ) ;
96+ }
9497
95- if let Some ( voice_manager) = & client. voice_manager {
96- if self . voice_manager . set ( Arc :: clone ( voice_manager) ) . is_err ( ) {
97- error ! ( "Could not set voice_manager OnceLock because it was already set. This should never happen." ) ;
98- return Err ( "Could not set voice_manager OnceLock because it was already set." . into ( ) ) ;
99- }
100- } else {
101- warn ! ( "Voice manager is not available" ) ;
98+ if let Some ( voice_manager) = & client. voice_manager {
99+ if self . voice_manager . set ( Arc :: clone ( voice_manager) ) . is_err ( ) {
100+ error ! ( "Could not set voice_manager OnceLock because it was already set. This should never happen." ) ;
101+ return Err ( "Could not set voice_manager OnceLock because it was already set." . into ( ) ) ;
102102 }
103+ } else {
104+ warn ! ( "Voice manager is not available" ) ;
105+ }
103106
104- if self . ws_url . set ( Arc :: clone ( & client. ws_url ) ) . is_err ( ) {
105- error ! ( "Could not set ws_url OnceLock because it was already set. This should never happen." ) ;
106- return Err ( "Could not set ws_url OnceLock because it was already set." . into ( ) ) ;
107- }
107+ if self . ws_url . set ( Arc :: clone ( & client. ws_url ) ) . is_err ( ) {
108+ error ! ( "Could not set ws_url OnceLock because it was already set. This should never happen." ) ;
109+ return Err ( "Could not set ws_url OnceLock because it was already set." . into ( ) ) ;
110+ }
108111
109- let client_handle = spawn ( async move { client. start ( ) . await } ) ;
112+ let client_handle = spawn ( async move { client. start ( ) . await } ) ;
110113
111- select ! {
112- _ = client_ready_notify. notified( ) => { } ,
113- _ = sleep( Duration :: from_secs( 2 ) ) => { } ,
114- }
114+ select ! {
115+ _ = client_ready_notify. notified( ) => { } ,
116+ _ = sleep( Duration :: from_secs( 2 ) ) => { } ,
117+ }
115118
116- if client_handle. is_finished ( ) {
117- client_handle. await ??;
118- return Err ( "Discord client stopped unexpectedly" . into ( ) ) ;
119- }
119+ if client_handle. is_finished ( ) {
120+ client_handle. await ??;
121+ return Err ( "Discord client stopped unexpectedly" . into ( ) ) ;
122+ }
120123
121- self . client_handle = Some ( client_handle) ;
122- Ok ( ( ) )
123- } )
124+ self . client_handle = Some ( client_handle) ;
125+ Ok ( ( ) )
124126 }
125127
126- fn stop ( & mut self ) -> LifetimedPinnedBoxedFutureResult < ' _ , ( ) > {
127- Box :: pin ( async move {
128- if let Some ( client_handle) = self . client_handle . take ( ) {
129- info ! ( "Waiting for Discord client to stop..." ) ;
128+ async fn stop ( & mut self ) -> Result < ( ) , BoxedError > {
129+ if let Some ( client_handle) = self . client_handle . take ( ) {
130+ info ! ( "Waiting for Discord client to stop..." ) ;
130131
131- client_handle. abort ( ) ; // Should trigger a JoinError in the client_handle, if the task hasn't already ended
132+ client_handle. abort ( ) ; // Should trigger a JoinError in the client_handle, if the task hasn't already ended
132133
133- // If the thread ended WITHOUT a JoinError, the client already stopped unexpectedly
134- let result = async move {
135- match client_handle. await {
136- Ok ( result) => result,
137- Err ( _) => Ok ( ( ) ) ,
138- }
134+ // If the thread ended WITHOUT a JoinError, the client already stopped unexpectedly
135+ let result = async move {
136+ match client_handle. await {
137+ Ok ( result) => result,
138+ Err ( _) => Ok ( ( ) ) ,
139139 }
140- . await ;
141- result?;
142140 }
141+ . await ;
142+ result?;
143+ }
143144
144- Ok ( ( ) )
145- } )
145+ Ok ( ( ) )
146146 }
147147}
148148
@@ -157,6 +157,7 @@ impl EventHandler {
157157 }
158158}
159159
160+ //TODO: When Rust allows async trait methods to be object-safe, refactor this to not use async_trait anymore
160161#[ async_trait]
161162impl client:: EventHandler for EventHandler {
162163 async fn ready ( & self , _ctx : Context , data_about_bot : Ready ) {
0 commit comments