Skip to content

Instantly share code, notes, and snippets.

@udoprog
Last active May 23, 2019 03:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save udoprog/dc075c6b03929d17d088327fda6c1b75 to your computer and use it in GitHub Desktop.
Save udoprog/dc075c6b03929d17d088327fda6c1b75 to your computer and use it in GitHub Desktop.
diff --git a/bot/src/module/countdown.rs b/bot/src/module/countdown.rs
index 632d68d..b87f0ba 100644
--- a/bot/src/module/countdown.rs
+++ b/bot/src/module/countdown.rs
@@ -87,6 +87,8 @@ impl super::Module for Module {
handlers.insert("countdown", Handler { sender });
+ let path = self.path.clone();
+
let future = async move {
let mut current = OptionStream::<Current>::new(None);
@@ -106,7 +108,7 @@ impl super::Module for Module {
template,
elapsed: Default::default(),
interval: timer::Interval::new_interval(time::Duration::from_secs(1)),
- path: self.path.clone(),
+ path: path.clone(),
};
c.write_log();
diff --git a/bot/src/player.rs b/bot/src/player.rs
index 44bb6c1..85c21bd 100644
--- a/bot/src/player.rs
+++ b/bot/src/player.rs
@@ -827,66 +827,70 @@ impl PlayerClient {
max_duration: Option<utils::Duration>,
min_currency: Option<i64>,
) -> Result<(usize, Arc<Item>), AddTrackError> {
- let queue_inner = self.queue.queue.read();
- let len = queue_inner.len();
+ let (user_count, len) = {
+ let queue_inner = self.queue.queue.read();
+ let len = queue_inner.len();
- if !is_moderator {
- if let Some(reason) = self.closed.read().as_ref() {
- return Err(AddTrackError::PlayerClosed(reason.clone()));
- }
+ if !is_moderator {
+ if let Some(reason) = self.closed.read().as_ref() {
+ return Err(AddTrackError::PlayerClosed(reason.clone()));
+ }
- let max_queue_length = *self.max_queue_length.read();
+ let max_queue_length = *self.max_queue_length.read();
- // NB: moderator is allowed to violate max queue length.
- if len >= max_queue_length as usize {
- return Err(AddTrackError::QueueFull);
- }
+ // NB: moderator is allowed to violate max queue length.
+ if len >= max_queue_length as usize {
+ return Err(AddTrackError::QueueFull);
+ }
- let duplicate_duration = self.duplicate_duration.read().clone();
-
- if !duplicate_duration.is_empty() {
- if let Some(last) = self
- .queue
- .last_song_within(&track_id, duplicate_duration.clone())
- .map_err(AddTrackError::Error)?
- {
- let added_at = DateTime::from_utc(last.added_at, Utc);
-
- return Err(AddTrackError::Duplicate(
- added_at,
- last.user,
- duplicate_duration.as_std(),
- ));
+ let duplicate_duration = self.duplicate_duration.read().clone();
+
+ if !duplicate_duration.is_empty() {
+ if let Some(last) = self
+ .queue
+ .last_song_within(&track_id, duplicate_duration.clone())
+ .map_err(AddTrackError::Error)?
+ {
+ let added_at = DateTime::from_utc(last.added_at, Utc);
+
+ return Err(AddTrackError::Duplicate(
+ added_at,
+ last.user,
+ duplicate_duration.as_std(),
+ ));
+ }
}
- }
- if let Some(min_currency) = min_currency {
- let balance = self
- .db
- .balance_of(channel.as_str(), user.as_str())
- .map_err(AddTrackError::Error)?
- .unwrap_or_default();
-
- if balance < min_currency {
- return Err(AddTrackError::NotEnoughCurrency {
- balance,
- required: min_currency,
- });
+ if let Some(min_currency) = min_currency {
+ let balance = self
+ .db
+ .balance_of(channel.as_str(), user.as_str())
+ .map_err(AddTrackError::Error)?
+ .unwrap_or_default();
+
+ if balance < min_currency {
+ return Err(AddTrackError::NotEnoughCurrency {
+ balance,
+ required: min_currency,
+ });
+ }
}
}
- }
- let mut user_count = 0;
+ let mut user_count = 0;
- for (index, i) in queue_inner.iter().enumerate() {
- if i.track_id == track_id {
- return Err(AddTrackError::QueueContainsTrack(index));
- }
+ for (index, i) in queue_inner.iter().enumerate() {
+ if i.track_id == track_id {
+ return Err(AddTrackError::QueueContainsTrack(index));
+ }
- if i.user.as_ref().map(|u| *u == user).unwrap_or_default() {
- user_count += 1;
+ if i.user.as_ref().map(|u| *u == user).unwrap_or_default() {
+ user_count += 1;
+ }
}
- }
+
+ (user_count, len)
+ };
let max_songs_per_user = *self.max_songs_per_user.read();
Compiling setmod-bot v0.2.7 (E:\work\repo\setmod\bot)
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> bot\src\module\countdown.rs:92:33
|
92 | let future = async move {
| _________________________________^
93 | | let mut current = OptionStream::<Current>::new(None);
94 | |
95 | | loop {
... |
126 | | }
127 | | };
| |_________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 80:5...
--> bot\src\module\countdown.rs:80:5
|
80 | / fn hook(
81 | | &self,
82 | | module::HookContext {
83 | | handlers, futures, ..
... |
130 | | Ok(())
131 | | }
| |_____^
= note: ...so that the types are compatible:
expected &module::countdown::Module
found &module::countdown::Module
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = std::result::Result<(), failure::error::Error>> + std::marker::Send + 'static)>>
found std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = std::result::Result<(), failure::error::Error>> + std::marker::Send>>
error: aborting due to previous error
error: Could not compile `setmod-bot`.
To learn more, run the command again with --verbose.
error[E0277]: `*mut ()` cannot be sent between threads safely
--> bot\src\module\song.rs:277:13
|
277 | ctx.spawn_async(future);
| ^^^^^^^^^^^ `*mut ()` cannot be sent between threads safely
|
= help: within `futures_util::future::map::Map<impl core::future::future::Future, [closure@bot\src\module\song.rs:269:33: 275:10 user:irc::OwnedUser]>`, the trait `std::marker::Send` is not implemented for `*mut ()`
= note: required because it appears within the type `lock_api::GuardNoSend`
= note: required because it appears within the type `(&std::collections::VecDeque<std::sync::Arc<player::Item>>, lock_api::GuardNoSend)`
= note: required because it appears within the type `std::marker::PhantomData<(&std::collections::VecDeque<std::sync::Arc<player::Item>>, lock_api::GuardNoSend)>`
= note: required because it appears within the type `lock_api::rwlock::RwLockReadGuard<'_, parking_lot::raw_rwlock::RawRwLock, std::collections::VecDeque<std::sync::Arc<player::Item>>>`
= note: required because it appears within the type `for<'r, 's> {&'r player::PlayerClient, std::string::String, track_id::TrackId, bool, std::option::Option<utils::duration::Duration>, std::option::Option<i64>, lock_api::rwlock::RwLockReadGuard<'s, parking_lot::raw_rwlock::RawRwLock, std::collections::VecDeque<std::sync::Arc<player::Item>>>, usize, u32, fn(std::result::Result<player::Item, player::AddTrackError>) -> std::result::Result<<std::result::Result<player::Item, player::AddTrackError> as std::ops::Try>::Ok, <std::result::Result<player::Item, player::AddTrackError> as std::ops::Try>::Error> {<std::result::Result<player::Item, player::AddTrackError> as std::ops::Try>::into_result}, futures_util::compat::compat01as03::Compat01As03<impl warp::Future>, (), player::Item, std::sync::Arc<player::Item>, fn(std::result::Result<(), player::AddTrackError>) -> std::result::Result<<std::result::Result<(), player::AddTrackError> as std::ops::Try>::Ok, <std::result::Result<(), player::AddTrackError> as std::ops::Try>::Error> {<std::result::Result<(), player::AddTrackError> as std::ops::Try>::into_result}, futures_util::compat::compat01as03::Compat01As03<player::PushBackFuture>}`
= note: required because it appears within the type `[static generator@bot\src\player.rs:841:52: 946:6 self:&player::PlayerClient, channel:std::string::String, user:std::string::String, track_id:track_id::TrackId, is_moderator:bool,
max_duration:std::option::Option<utils::duration::Duration>, min_currency:std::option::Option<i64> for<'r, 's> {&'r player::PlayerClient, std::string::String, track_id::TrackId, bool, std::option::Option<utils::duration::Duration>, std::option::Option<i64>, lock_api::rwlock::RwLockReadGuard<'s, parking_lot::raw_rwlock::RawRwLock, std::collections::VecDeque<std::sync::Arc<player::Item>>>, usize, u32, fn(std::result::Result<player::Item, player::AddTrackError>) -> std::result::Result<<std::result::Result<player::Item, player::AddTrackError> as std::ops::Try>::Ok, <std::result::Result<player::Item, player::AddTrackError> as std::ops::Try>::Error> {<std::result::Result<player::Item, player::AddTrackError>
as std::ops::Try>::into_result}, futures_util::compat::compat01as03::Compat01As03<impl warp::Future>, (), player::Item, std::sync::Arc<player::Item>, fn(std::result::Result<(), player::AddTrackError>) -> std::result::Result<<std::result::Result<(), player::AddTrackError> as std::ops::Try>::Ok, <std::result::Result<(), player::AddTrackError> as std::ops::Try>::Error> {<std::result::Result<(), player::AddTrackError> as std::ops::Try>::into_result}, futures_util::compat::compat01as03::Compat01As03<player::PushBackFuture>}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@bot\src\player.rs:841:52: 946:6 self:&player::PlayerClient, channel:std::string::String, user:std::string::String, track_id:track_id::TrackId, is_moderator:bool, max_duration:std::option::Option<utils::duration::Duration>, min_currency:std::option::Option<i64> for<'r, 's> {&'r player::PlayerClient, std::string::String, track_id::TrackId, bool, std::option::Option<utils::duration::Duration>, std::option::Option<i64>, lock_api::rwlock::RwLockReadGuard<'s, parking_lot::raw_rwlock::RawRwLock, std::collections::VecDeque<std::sync::Arc<player::Item>>>, usize, u32, fn(std::result::Result<player::Item, player::AddTrackError>) -> std::result::Result<<std::result::Result<player::Item, player::AddTrackError> as std::ops::Try>::Ok, <std::result::Result<player::Item, player::AddTrackError> as std::ops::Try>::Error> {<std::result::Result<player::Item,
player::AddTrackError> as std::ops::Try>::into_result}, futures_util::compat::compat01as03::Compat01As03<impl warp::Future>, (), player::Item, std::sync::Arc<player::Item>, fn(std::result::Result<(), player::AddTrackError>) -> std::result::Result<<std::result::Result<(), player::AddTrackError> as std::ops::Try>::Ok, <std::result::Result<(), player::AddTrackError> as std::ops::Try>::Error> {<std::result::Result<(), player::AddTrackError> as std::ops::Try>::into_result},
futures_util::compat::compat01as03::Compat01As03<player::PushBackFuture>}]>`
= note: required because it appears within the type `impl core::future::future::Future`
= note: required because it appears within the type `impl core::future::future::Future`
= note: required because it appears within the type `for<'r, 's, 't0> {std::option::Option<track_id::TrackId>, track_id::TrackId, fn(std::result::Result<std::option::Option<track_id::TrackId>, failure::error::Error>) -> std::result::Result<<std::result::Result<std::option::Option<track_id::TrackId>, failure::error::Error> as std::ops::Try>::Ok, <std::result::Result<std::option::Option<track_id::TrackId>, failure::error::Error> as std::ops::Try>::Error> {<std::result::Result<std::option::Option<track_id::TrackId>, failure::error::Error> as std::ops::Try>::into_result}, impl core::future::future::Future, (), &'s str, bool, std::option::Option<utils::duration::Duration>, std::option::Option<i64>, impl core::future::future::Future, std::result::Result<(usize, std::sync::Arc<player::Item>), player::AddTrackError>, usize, std::sync::Arc<player::Item>, std::sync::Arc<currency::Currency>, futures_util::compat::compat01as03::Compat01As03<impl warp::Future>}`
= note: required because it appears within the type `[static generator@bot\src\module\song.rs:83:33: 265:10 track_id:std::option::Option<track_id::TrackId>, player:player::PlayerClient, q:std::string::String, user:irc::OwnedUser, spotify_subscriber_only:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, bool>>, youtube_subscriber_only:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, bool>>, subscriber_only:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, bool>>, is_moderator:bool, stream_info:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, stream_info::StreamInfo>>, spotify_max_duration:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, utils::duration::Duration>>, youtube_max_duration:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, utils::duration::Duration>>, spotify_min_currency:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, u32>>, youtube_min_currency:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, u32>>, currency:std::option::Option<std::sync::Arc<currency::Currency>>, request_reward:u32, db:db::Database for<'r, 's, 't0> {std::option::Option<track_id::TrackId>, track_id::TrackId, fn(std::result::Result<std::option::Option<track_id::TrackId>, failure::error::Error>) -> std::result::Result<<std::result::Result<std::option::Option<track_id::TrackId>, failure::error::Error> as std::ops::Try>::Ok, <std::result::Result<std::option::Option<track_id::TrackId>, failure::error::Error> as std::ops::Try>::Error> {<std::result::Result<std::option::Option<track_id::TrackId>, failure::error::Error> as std::ops::Try>::into_result}, impl core::future::future::Future, (), &'s str, bool, std::option::Option<utils::duration::Duration>, std::option::Option<i64>,
impl core::future::future::Future, std::result::Result<(usize, std::sync::Arc<player::Item>), player::AddTrackError>, usize, std::sync::Arc<player::Item>, std::sync::Arc<currency::Currency>, futures_util::compat::compat01as03::Compat01As03<impl warp::Future>}]`
= note: required because it appears within the type `std::future::GenFuture<[static generator@bot\src\module\song.rs:83:33: 265:10 track_id:std::option::Option<track_id::TrackId>, player:player::PlayerClient, q:std::string::String, user:irc::OwnedUser, spotify_subscriber_only:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, bool>>, youtube_subscriber_only:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, bool>>, subscriber_only:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, bool>>, is_moderator:bool, stream_info:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, stream_info::StreamInfo>>, spotify_max_duration:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, utils::duration::Duration>>, youtube_max_duration:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, utils::duration::Duration>>, spotify_min_currency:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, u32>>, youtube_min_currency:std::sync::Arc<lock_api::rwlock::RwLock<parking_lot::raw_rwlock::RawRwLock, u32>>, currency:std::option::Option<std::sync::Arc<currency::Currency>>, request_reward:u32, db:db::Database for<'r, 's, 't0> {std::option::Option<track_id::TrackId>, track_id::TrackId, fn(std::result::Result<std::option::Option<track_id::TrackId>, failure::erroompat01as03::Compat01As03<impl warp::Future>}]>` = note: required because it appears within the type `impl core::future::future::Future` = note: required because it appears within the type `futures_util::future::map::Map<impl core::future::future::Future, [closure@bot\src\module\song.rs:269:33: 275:10 user:irc::OwnedUser]>`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment