diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f54bb5e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +/.vscode +Cargo.lock \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ee47e4d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "fruity" +version = "2.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serenity = {default-features = false, version = "0", features = ["builder", "cache", "client", "gateway", "http", "model", "utils", "rustls_backend"]} +tokio = {version = "1", features = ["full"]} +leptess = "0" +screenshots = "0" +image = "0" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +display-info = "0.3.2" \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 0000000..24f8604 --- /dev/null +++ b/config.json @@ -0,0 +1,50 @@ +{ + "data": { + "token": "", + "channel": 0, + "message": [ + "FORT", + "SANDORA", + "TOWN", + "MARINE", + "SHELL", + "ISLAND", + "BARATIE", + "ORANGE", + "ROCA", + "COLOSSEUM", + "SPHINX", + "ARLONG", + "PARK", + "KORI", + "LAND", + "SKY", + "GRAVITO", + "FISHMAN", + "PALACE", + "NEPTUNE", + "THRONE", + "COCO", + "MOUNTAIN", + "ROVO", + "DESERT", + "KINGDOM", + "SASHI", + "SPIRIT", + "ARC", + "FORO", + "ABYSS", + "REVERSE", + "THRILLER", + "BARK", + "TRANS", + "VANIA", + "BASE", + "SPAWNED AT", + "HAS SPAWNED", + "SPAWNED" + ], + "role": 0, + "server": "" + } +} diff --git a/eng.traineddata b/eng.traineddata new file mode 100644 index 0000000..176dc32 Binary files /dev/null and b/eng.traineddata differ diff --git a/images/roblox.png b/images/roblox.png new file mode 100644 index 0000000..e69de29 diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..6c48797 --- /dev/null +++ b/readme.md @@ -0,0 +1,37 @@ +### GPO Devil Fruit Spawn Notifier + +Might be useful on other games. +This is a discord bot, that upon getting the fruit has spawned message, sends a message to a discord channel. + +This does not use exploits, it just reads letters from your screen. It doesn't even know if roblox exists. +It is coded for different OSes, but only windows will be provided, since if you use something else, you should be able to compile it yourself. +This has also been semi-allowed by a moderator from the GPO team, though that was a while ago. Not that they can detect it anyways. + +Releasing it because I don't care that much about GPO and my friends stopped played. + +Requirements: + +- Basic Discord Bot Knowledge +- An All-Seeing Eye +- A computer you can run it with, since it needs to be in the foreground foreground + +How to run: + +1. Modify config.json to add the proper values into the variables +2. run fruity.exe +3. Launch GPO and make it fullscreen on your main monitor +4. Stand in front of a solid wall +5. Turn on the least amount of graphics possible +6. Wait +7. Profit + +Build Requirements: + +- Leptonica +- Tesseract +- Rust + +Build Instructions: + +1. View https://github.com/ccouzens/leptonica-sys +2. Figure it out. diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..20d27ca --- /dev/null +++ b/src/main.rs @@ -0,0 +1,111 @@ +use std::{fs}; +use image::{ImageFormat}; +use serde::{Serialize, Deserialize}; +use std::future::Future; +use serenity::{async_trait}; +use serenity::http::Http; +use serenity::model::id::ChannelId; +use serenity::prelude::*; +use tokio::time::{self, Duration, sleep}; +use screenshots::Screen; + +struct Handler; +#[derive(Serialize, Deserialize)] +struct Data { + token: String, + channel: u64, + message: Vec, + role: u64, + server: String +} +#[derive(Serialize, Deserialize)] +struct Config { + data: Data +} + +#[async_trait] +impl EventHandler for Handler {} +#[tokio::main] +async fn main() { + startup().await; + // This is to stop the program from closing + sleep(Duration::from_secs(999999999)).await; +} + +async fn startup() { + set_interval(|| async { + // Reading the configs + let jsonfile = fs::read_to_string("config.json").expect("unable to read file"); + let config: Config = serde_json::from_str(&jsonfile).expect("unable to parse json"); + + // Preparing to read + screenshot().await; + + // Setting up bot + let bot = Http::new(&config.data.token); + let channel_id = ChannelId(config.data.channel); + + // Read the message from image + let msg:String = ocr().await.to_uppercase(); + let mut count = 0usize; + loop { + if count < config.data.message.len() { + count += 1; + if msg.contains(&config.data.message[count -1]) { + let sentmessage = channel_id.send_message(&bot, |m| { + m.content(format!("<@&{}>", config.data.role)).embed(|e| e.title(&msg).description(config.data.server)).add_file("images/roblox.png") + }).await; + sentmessage.unwrap(); + println!("{}", &msg); + break; + } + } else { + println!("{}", &msg); + break; + } + } + }, Duration::from_millis(8500)); +} + +async fn ocr() -> String { + let mut lt = leptess::LepTess::new(None, "eng").unwrap(); + lt.set_image("images/roblox.png").unwrap(); + return lt.get_utf8_text().unwrap(); +} + +async fn screenshot() { + let screen = Screen::from_point(0,0).unwrap(); + let scr = screen.capture().unwrap(); + let buffer = scr.buffer(); + fs::write("images/roblox.png", &buffer).unwrap(); + let mut img = image::open("images/roblox.png").unwrap(); + let x = screen.width / 4; + let y = screen.height / 64; + let width = screen.width / 2; + let height = screen.height / 4; + img = img.crop(x, y, width, height); + let path = format!("images/roblox.png"); + img + .save_with_format(&path, ImageFormat::Png) + .unwrap(); +} + +fn set_interval(mut f: F, dur: Duration) +where + F: Send + 'static + FnMut() -> Fut, + Fut: Future + Send + 'static, +{ + // Create stream of intervals. + let mut interval = time::interval(dur); + + tokio::spawn(async move { + // Skip the first tick at 0ms. + interval.tick().await; + loop { + // Wait until next tick. + interval.tick().await; + // Spawn a task for this tick. + tokio::spawn(f()); + } + }); +} \ No newline at end of file