use crate::model::events::*;
use crate::prelude::LavalinkClient;
use pyo3::prelude::*;
pyo3::import_exception!(builtins, NameError);
#[pymodule]
pub fn event(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<EventHandler>()?;
Ok(())
}
#[pyclass(subclass)]
#[derive(Debug, Clone)]
pub struct EventHandler {
pub inner: PyObject,
pub current_loop: PyObject,
}
#[pymethods]
impl EventHandler {
#[new]
fn new(py: Python<'_>) -> PyResult<Self> {
let current_loop = pyo3_async_runtimes::get_running_loop(py)?;
let loop_ref = PyObject::from(current_loop);
Ok(Self {
current_loop: loop_ref,
inner: py.None(),
})
}
#[pyo3(text_signature = "($self, client, session_id, event, /)")]
fn stats(&self) {}
#[pyo3(text_signature = "($self, client, session_id, event, /)")]
fn player_update(&self) {}
#[pyo3(text_signature = "($self, client, session_id, event, /)")]
fn track_start(&self) {}
#[pyo3(text_signature = "($self, client, session_id, event, /)")]
fn track_end(&self) {}
#[pyo3(text_signature = "($self, client, session_id, event, /)")]
fn track_exception(&self) {}
#[pyo3(text_signature = "($self, client, session_id, event, /)")]
fn track_stuck(&self) {}
#[pyo3(text_signature = "($self, client, session_id, event, /)")]
fn websocket_closed(&self) {}
#[pyo3(text_signature = "($self, client, session_id, event, /)")]
fn ready(&self) {}
}
impl EventHandler {
pub(crate) async fn event_stats(
&self,
client: LavalinkClient,
session_id: String,
event: Stats,
) {
call_event(self, client, session_id, event, "stats");
}
pub(crate) async fn event_player_update(
&self,
client: LavalinkClient,
session_id: String,
event: PlayerUpdate,
) {
call_event(self, client, session_id, event, "player_update");
}
pub(crate) async fn event_track_start(
&self,
client: LavalinkClient,
session_id: String,
event: TrackStart,
) {
call_event(self, client, session_id, event, "track_start");
}
pub(crate) async fn event_track_end(
&self,
client: LavalinkClient,
session_id: String,
event: TrackEnd,
) {
call_event(self, client, session_id, event, "track_end");
}
pub(crate) async fn event_track_exception(
&self,
client: LavalinkClient,
session_id: String,
event: TrackException,
) {
call_event(self, client, session_id, event, "track_exception");
}
pub(crate) async fn event_track_stuck(
&self,
client: LavalinkClient,
session_id: String,
event: TrackStuck,
) {
call_event(self, client, session_id, event, "track_stuck");
}
pub(crate) async fn event_websocket_closed(
&self,
client: LavalinkClient,
session_id: String,
event: WebSocketClosed,
) {
call_event(self, client, session_id, event, "websocket_closed");
}
pub(crate) async fn event_ready(
&self,
client: LavalinkClient,
session_id: String,
event: Ready,
) {
call_event(self, client, session_id, event, "ready");
}
}
fn call_event<T: Send + Sync + for<'a> pyo3::IntoPyObject<'a> + 'static>(
handler: &EventHandler,
client: LavalinkClient,
session_id: String,
event: T,
name: &'static str,
) {
let (slf1, slf2) = Python::with_gil(|_| (handler.clone(), handler.clone()));
Python::with_gil(|py| {
let current_loop = slf1.current_loop.into_bound(py);
pyo3_async_runtimes::tokio::future_into_py_with_locals(
py,
pyo3_async_runtimes::TaskLocals::new(current_loop),
async move {
let future = Python::with_gil(|py| {
let coro_result =
slf2.inner
.call_method(py, name, (client, session_id, event), None);
if let Ok(coro) = coro_result {
pyo3_async_runtimes::tokio::into_future(coro.into_bound(py))
} else {
Err(NameError::new_err("Undefined event"))
}
});
if let Ok(f) = future {
if let Err(e) = f.await {
Python::with_gil(|py| {
e.print_and_set_sys_last_vars(py);
});
}
}
Ok(Python::with_gil(|py| py.None()))
},
)
.unwrap();
});
}