diff --git a/Gemfile b/Gemfile
index ecf6f11..d9f491e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,8 +3,4 @@ source 'https://rubygems.org'
gem 'discordrb', git: 'https://github.com/shardlab/discordrb.git', branch: 'main'
gem 'dotenv'
-gem 'pg'
-gem 'prawn'
-gem 'prawn-table'
-gem 'gruff'
-gem 'rmagick'
\ No newline at end of file
+gem 'pg'
\ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
index 3b4efb9..5700f92 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -17,7 +17,6 @@ GEM
remote: https://rubygems.org/
specs:
base64 (0.3.0)
- bigdecimal (3.3.1)
domain_name (0.6.20240107)
dotenv (3.2.0)
event_emitter (0.2.6)
@@ -32,26 +31,18 @@ GEM
ffi (1.17.3-x86_64-darwin)
ffi (1.17.3-x86_64-linux-gnu)
ffi (1.17.3-x86_64-linux-musl)
- gruff (0.29.0)
- bigdecimal (>= 3.0)
- histogram
- rmagick (>= 5.5)
- histogram (0.2.4.1)
http-accept (1.7.0)
http-cookie (1.1.0)
domain_name (~> 0.5)
logger (1.7.0)
- matrix (0.4.3)
mime-types (3.7.0)
logger
mime-types-data (~> 3.2025, >= 3.2025.0507)
mime-types-data (3.2025.0924)
mutex_m (0.3.0)
netrc (0.11.0)
- observer (0.1.2)
opus-ruby (1.0.1)
ffi
- pdf-core (0.10.0)
pg (1.6.3)
pg (1.6.3-aarch64-linux)
pg (1.6.3-aarch64-linux-musl)
@@ -59,23 +50,11 @@ GEM
pg (1.6.3-x86_64-darwin)
pg (1.6.3-x86_64-linux)
pg (1.6.3-x86_64-linux-musl)
- pkg-config (1.6.5)
- prawn (2.5.0)
- matrix (~> 0.4)
- pdf-core (~> 0.10.0)
- ttfunk (~> 1.8)
- prawn-table (0.2.2)
- prawn (>= 1.3.0, < 3.0.0)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
- rmagick (6.1.5)
- observer (~> 0.1)
- pkg-config (~> 1.4)
- ttfunk (1.8.0)
- bigdecimal (~> 3.1)
websocket (1.2.11)
websocket-client-simple (0.9.0)
base64
@@ -99,15 +78,10 @@ PLATFORMS
DEPENDENCIES
discordrb!
dotenv
- gruff
pg
- prawn
- prawn-table
- rmagick
CHECKSUMS
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
- bigdecimal (3.3.1) sha256=eaa01e228be54c4f9f53bf3cc34fe3d5e845c31963e7fcc5bedb05a4e7d52218
discordrb (3.7.2)
discordrb-webhooks (3.7.2)
domain_name (0.6.20240107) sha256=5f693b2215708476517479bf2b3802e49068ad82167bcd2286f899536a17d933
@@ -124,19 +98,14 @@ CHECKSUMS
ffi (1.17.3-x86_64-darwin) sha256=1f211811eb5cfaa25998322cdd92ab104bfbd26d1c4c08471599c511f2c00bb5
ffi (1.17.3-x86_64-linux-gnu) sha256=3746b01f677aae7b16dc1acb7cb3cc17b3e35bdae7676a3f568153fb0e2c887f
ffi (1.17.3-x86_64-linux-musl) sha256=086b221c3a68320b7564066f46fed23449a44f7a1935f1fe5a245bd89d9aea56
- gruff (0.29.0) sha256=ab808cbf507abda7ffacd4ba5805a43c47ad0ec6aa2a7b125cf8a165110047a0
- histogram (0.2.4.1) sha256=9a6e379172b88ea842ab71700a535dd037185a4e17abcce742c7444679ae2abc
http-accept (1.7.0) sha256=c626860682bfbb3b46462f8c39cd470fd7b0584f61b3cc9df5b2e9eb9972a126
http-cookie (1.1.0) sha256=38a5e60d1527eebc396831b8c4b9455440509881219273a6c99943d29eadbb19
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
- matrix (0.4.3) sha256=a0d5ab7ddcc1973ff690ab361b67f359acbb16958d1dc072b8b956a286564c5b
mime-types (3.7.0) sha256=dcebf61c246f08e15a4de34e386ebe8233791e868564a470c3fe77c00eed5e56
mime-types-data (3.2025.0924) sha256=f276bca15e59f35767cbcf2bc10e023e9200b30bd6a572c1daf7f4cc24994728
mutex_m (0.3.0) sha256=cfcb04ac16b69c4813777022fdceda24e9f798e48092a2b817eb4c0a782b0751
netrc (0.11.0) sha256=de1ce33da8c99ab1d97871726cba75151113f117146becbe45aa85cb3dabee3f
- observer (0.1.2) sha256=d8a3107131ba661138d748e7be3dbafc0d82e732fffba9fccb3d7829880950ac
opus-ruby (1.0.1) sha256=8dc808d6773a488469374cccf252808b2ad7bc7e00229a319832f0e09012ce53
- pdf-core (0.10.0) sha256=0a5d101e2063c01e3f941e1ee47cbb97f1adfc1395b58372f4f65f1300f3ce91
pg (1.6.3) sha256=1388d0563e13d2758c1089e35e973a3249e955c659592d10e5b77c468f628a99
pg (1.6.3-aarch64-linux) sha256=0698ad563e02383c27510b76bf7d4cd2de19cd1d16a5013f375dd473e4be72ea
pg (1.6.3-aarch64-linux-musl) sha256=06a75f4ea04b05140146f2a10550b8e0d9f006a79cdaf8b5b130cde40e3ecc2c
@@ -144,12 +113,7 @@ CHECKSUMS
pg (1.6.3-x86_64-darwin) sha256=ee2e04a17c0627225054ffeb43e31a95be9d7e93abda2737ea3ce4a62f2729d6
pg (1.6.3-x86_64-linux) sha256=5d9e188c8f7a0295d162b7b88a768d8452a899977d44f3274d1946d67920ae8d
pg (1.6.3-x86_64-linux-musl) sha256=9c9c90d98c72f78eb04c0f55e9618fe55d1512128e411035fe229ff427864009
- pkg-config (1.6.5) sha256=33f9f81c5322983d22b439b8b672f27777b406fea23bfec74ff14bbeb42ec733
- prawn (2.5.0) sha256=f4e20e3b4f30bf5b9ae37dad15eb421831594553aa930b2391b0fa0a99c43cb6
- prawn-table (0.2.2) sha256=336d46e39e003f77bf973337a958af6a68300b941c85cb22288872dc2b36addb
rest-client (2.1.0) sha256=35a6400bdb14fae28596618e312776c158f7ebbb0ccad752ff4fa142bf2747e3
- rmagick (6.1.5) sha256=91c1734cc0effc3b1be18e6705ea0353d73cb492547002f542763fa08445acd1
- ttfunk (1.8.0) sha256=a7cbc7e489cc46e979dde04d34b5b9e4f5c8f1ee5fc6b1a7be39b829919d20ca
websocket (1.2.11) sha256=b7e7a74e2410b5e85c25858b26b3322f29161e300935f70a0e0d3c35e0462737
websocket-client-simple (0.9.0) sha256=f9a37c5e4922b35a711e21e6d73ed1e25892efa47d183203ab2f5beb4e563109
diff --git a/src/bot.rb b/src/bot.rb
index f0f5fc0..8654978 100644
--- a/src/bot.rb
+++ b/src/bot.rb
@@ -50,12 +50,11 @@ class FrugalityBot
module_name = filename.split('_').map(&:capitalize).join
begin
- # We find the module inside 'Commands' namespace
comm_module = Commands.const_get(module_name)
- # Register the command
comm_module.register(@bot, @db)
puts "Loaded command: #{module_name}"
+ sleep(1.5)
rescue NameError => e
puts "Could not load #{filename}: Module 'Commands::#{module_name}' was not found."
rescue StandardError => e
diff --git a/src/commands/embed.rb b/src/commands/embed.rb
new file mode 100644
index 0000000..3e50dbf
--- /dev/null
+++ b/src/commands/embed.rb
@@ -0,0 +1,44 @@
+# FrugalityBot
+# Copyright (C) 2026 Eri (csxkdv/nxkdv) nxkdv@thenight.club
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+require 'securerandom'
+
+module Commands
+ module Embed
+ extend self
+
+ def register(bot, _db)
+ bot.register_application_command(:embed, 'This is an embed testing', server_id: ENV['TEST_SERVER_ID']) do |cmd|
+ end
+
+ bot.application_command(:embed) do |event|
+ color_generated = ("0x" + Random.bytes(3).unpack1('H*')).to_i(16)
+ embed_generated = {
+ title: "Title testing.",
+ description: "Description testing.",
+ color: color_generated,
+ fields: [
+ { name: "Field 1", value: "Value for field 1", inline: true },
+ { name: "Field 2", value: "Value for field 2", inline: false }
+ ],
+ image: { url: "https://i.kym-cdn.com/photos/images/original/002/349/700/e38.jpg" },
+ footer: { text: "Footer testing." }
+ }
+
+ event.respond(embeds: [embed_generated])
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/src/commands/statement.rb b/src/commands/statement.rb
index 9e93341..77f19ea 100644
--- a/src/commands/statement.rb
+++ b/src/commands/statement.rb
@@ -13,10 +13,9 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-
-require 'prawn'
-require 'prawn/table'
-require 'gruff'
+require 'net/http'
+require 'uri'
+require 'json'
module Commands
module Statement
@@ -36,70 +35,52 @@ module Commands
user_id = event.user.id
period = event.options['period']
+ # For income we fetch the data as stats[:income]
+ # For expenses we fetch the data as stats[:expenses]
+ # For net income we fetch the data as stats[:net]
stats = db.fetch_report(user_id, period)
- # We generate a Graph
- g = Gruff::Pie.new
- g.title = "Report"
- g.theme = Gruff::Themes::PASTEL
+ chart_config = {
+ type: 'doughnut',
+ data: {
+ labels: ['Income', 'Expenses'],
+ datasets: [{
+ data: [stats[:income], stats[:expenses].abs],
+ backgroundColor: ['#9AF5AA', '#F55D5D'],
+ borderWidth: 1
+ }]
+ },
+ options: {
+ plugins: {
+ doughnutlabel: {
+ labels: [
+ { text: stats[:net].to_s, font: { size: 20}},
+ { text: 'Net', font: { size: 10 }}
+ ]
+ }
+ }
+ }
+ }
- # We add data
- g.data('Income', stats[:income])
- g.data('Expenses', stats[:expenses].abs)
+ encoded_config = URI.encode_www_form_component(chart_config.to_json)
+ chart_url = "https://quickchart.io/chart?c=#{encoded_config}&w=500&h=300&bkg=rgb(255,255,255)"
- # We save the graph temporarily
- chart_path = "/tmp/chart_#{user_id}.png"
- g.write(chart_path)
+ color_generated = ("0x" + Random.bytes(3).unpack1('H*')).to_i(16)
+
+ embed_generated = {
+ title: "Financial Statement",
+ description: "Report generated for **#{event.user.name}** (#{period})",
+ color: color_generated,
+ fields: [
+ { name: "Income", value: "#{stats[:income]} coins", inline: true },
+ { name: "Expenses", value: "#{stats[:expenses].abs} coins", inline: true },
+ { name: "Net Change", value: "#{stats[:net]} coins", inline: false }
+ ],
+ image: { url: chart_url },
+ footer: { text: "By FrugalityBot with QuickChart." }
+ }
- # We generate a PDF
- pdf_path = "/tmp/statement_#{user_id}.pdf"
-
- Prawn::Document.generate(pdf_path) do |pdf|
- pdf.font "Helvetica"
-
- # This should be the Header
- pdf.text "#{event.user.name}'s Financial Statement", size: 24, style: :bold, align: :center
- pdf.move_down 10
- pdf.text "Period: #{period}", align: :center
- pdf.move_down 20
-
- # Summary table goes here
- data = [
- ["Category", "$$$"],
- ["Total Income", "#{stats[:income]} coins"],
- ["Total Expenses", "#{stats[:expenses].abs} coins"],
- ["Net Change", "#{stats[:net]} coins"]
- ]
-
- pdf.table(data, position: :center) do
- row(0).font_style = :bold
- row(0).background_color = "CCCCCC"
- self.header = true
- self.width = 400
- end
-
- pdf.move_down 30
-
- pdf.text "Visual Breakdown:", style: :bold
- pdf.move_down 10
- # We embed the image chart
- pdf.image chart_path, width: 400, position: :center
-
- # Footer
- pdf.move_down 10
- pdf.text "Generated by Frugality using Gruff and Prawn", size: 10, align: :center, color: "888888"
- end
-
- event.edit_response(content: "Report generated. Sending...")
-
- # Send the report to the user
- File.open(pdf_path, 'r') do |f|
- event.channel.send_file(f, caption: "Here's your report.")
- end
-
- # Cleanup
- File.delete(chart_path) if File.exist?(chart_path)
- File.delete(pdf_path) if File.exist?(pdf_path)
+ event.edit_response(embeds: [embed_generated])
end
end
end