-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.rs
More file actions
151 lines (136 loc) · 4.53 KB
/
main.rs
File metadata and controls
151 lines (136 loc) · 4.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/// Rustic Economy: a small example plugin backed by SQLite.
///
/// This example demonstrates how to:
/// - Use `#[derive(Plugin)]` to declare plugin metadata and register commands.
/// - Use `#[derive(Command)]` to define a typed command enum.
/// - Hold state (a `SqlitePool`) inside your plugin struct.
/// - Use `Ctx` to reply to the invoking player.
/// - Use `#[event_handler]` for event subscriptions (even when you don't
/// implement any event methods yet).
use dragonfly_plugin::{
Command, Plugin, PluginRunner, command::Ctx, event::EventHandler, event_handler, types,
};
use sqlx::{SqlitePool, sqlite::SqlitePoolOptions};
#[derive(Plugin)]
#[plugin(
id = "rustic-economy",
name = "Rustic Economy",
version = "0.3.0",
api = "1.0.0",
commands(Eco)
)]
struct RusticEconomy {
db: SqlitePool,
}
/// Database helpers for the Rustic Economy example.
impl RusticEconomy {
async fn new() -> Result<Self, Box<dyn std::error::Error>> {
// Create database connection
let db = SqlitePoolOptions::new()
.max_connections(5)
.connect("sqlite:economy.db")
.await?;
// Create table if it doesn't exist.
//
// NOTE: This example stores balances as REAL/f64 for simplicity.
// For real-world money you should use an integer representation
// (e.g. cents as i64) to avoid floating point rounding issues.
sqlx::query(
"CREATE TABLE IF NOT EXISTS users (
uuid TEXT PRIMARY KEY,
balance REAL NOT NULL DEFAULT 0.0
)",
)
.execute(&db)
.await?;
Ok(Self { db })
}
async fn get_balance(&self, uuid: &str) -> Result<f64, sqlx::Error> {
let result: Option<(f64,)> = sqlx::query_as("SELECT balance FROM users WHERE uuid = ?")
.bind(uuid)
.fetch_optional(&self.db)
.await?;
Ok(result.map(|(bal,)| bal).unwrap_or(0.0))
}
async fn add_money(&self, uuid: &str, amount: f64) -> Result<f64, sqlx::Error> {
// Insert or update user balance
sqlx::query(
"INSERT INTO users (uuid, balance) VALUES (?, ?)
ON CONFLICT(uuid) DO UPDATE SET balance = balance + ?",
)
.bind(uuid)
.bind(amount)
.bind(amount)
.execute(&self.db)
.await?;
self.get_balance(uuid).await
}
}
#[derive(Command)]
#[command(
name = "eco",
description = "Rustic Economy commands.",
aliases("economy", "rustic_eco")
)]
pub enum Eco {
#[subcommand(aliases("donate"))]
Pay { amount: f64 },
#[subcommand(aliases("balance", "money"))]
Bal,
}
impl EcoHandler for RusticEconomy {
async fn pay(&self, ctx: Ctx<'_>, amount: f64) {
match self.add_money(&ctx.sender, amount).await {
Ok(new_balance) => {
if let Err(e) = ctx
.reply(format!(
"Added ${:.2}! New balance: ${:.2}",
amount, new_balance
))
.await
{
eprintln!("Failed to send payment reply: {}", e);
}
}
Err(e) => {
eprintln!("Database error: {}", e);
if let Err(send_err) = ctx
.reply("Error processing payment!".to_string())
.await
{
eprintln!("Failed to send error reply: {}", send_err);
}
}
}
}
async fn bal(&self, ctx: Ctx<'_>) {
match self.get_balance(&ctx.sender).await {
Ok(balance) => {
if let Err(e) = ctx
.reply(format!("Your balance: ${:.2}", balance))
.await
{
eprintln!("Failed to send balance reply: {}", e);
}
}
Err(e) => {
eprintln!("Database error: {}", e);
if let Err(send_err) = ctx
.reply("Error checking balance!".to_string())
.await
{
eprintln!("Failed to send error reply: {}", send_err);
}
}
}
}
}
#[event_handler]
impl EventHandler for RusticEconomy {}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Starting the plugin...");
println!("Initializing database...");
let plugin = RusticEconomy::new().await?;
PluginRunner::run(plugin, "tcp://127.0.0.1:50050").await
}