Initial Commit
This commit is contained in:
commit
ef13383f5a
|
@ -0,0 +1,2 @@
|
|||
DISCORD_BOT_TOKEN=
|
||||
RUST_LOG=
|
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
/.env
|
||||
/.vscode
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "arona"
|
||||
version = "0.1.0"
|
||||
authors = ["Rekai Musuka <rekai@musuka.dev>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bluearch-recruitment = { git = "https://github.com/Paoda/bluearch-recruitment.git", branch = "main", version = "^0.1" }
|
||||
dotenv = "^0.15"
|
||||
env_logger = "^0.8"
|
||||
lazy_static = "^1.4"
|
||||
log = "^0.4"
|
||||
serde = "^1.0"
|
||||
serde_json = "^1.0"
|
||||
serenity = "^0.10"
|
||||
tokio = { version = "^1.0", features = ["macros", "rt-multi-thread"] }
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Rekai Nyangadzayi Musuka
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,407 @@
|
|||
[
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ヒナ",
|
||||
"eng": "Hina"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "イオリ",
|
||||
"eng": "Iori"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ハルナ",
|
||||
"eng": "Haruna"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "イズミ",
|
||||
"eng": "Izumi"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Aru",
|
||||
"jpn": "アル"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "スミレ",
|
||||
"eng": "Sumire"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "エイミ",
|
||||
"eng": "Iemi"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Karin",
|
||||
"jpn": "カリン"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ネル",
|
||||
"eng": "Neru"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Maki",
|
||||
"jpn": "マキ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Hibiki",
|
||||
"jpn": "ヒビキ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Saya",
|
||||
"jpn": "サヤ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Shun",
|
||||
"jpn": "シュン"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Shiroko",
|
||||
"jpn": "シロコ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Hoshino",
|
||||
"jpn": "ホシノ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ヒフミ",
|
||||
"eng": "Hifumi"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Tsurugi",
|
||||
"jpn": "ツルギ"
|
||||
}
|
||||
},
|
||||
"rarity": 3
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "アカリ",
|
||||
"eng": "Akari"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ジュンコ",
|
||||
"eng": "Junko"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ムツキ",
|
||||
"eng": "Mutsuki"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Kayoko",
|
||||
"jpn": "カヨコ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "フウカ",
|
||||
"eng": "Fuuka"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ユウカ",
|
||||
"eng": "Yuuka"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Akane",
|
||||
"jpn": "アカネ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ハル",
|
||||
"eng": "Haru"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Utaha",
|
||||
"jpn": "ウタハ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "チセ",
|
||||
"eng": "Chise"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Tsubaki",
|
||||
"jpn": "ツバキ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "セリカ",
|
||||
"eng": "Serika"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "アヤネ",
|
||||
"eng": "Ayane"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Hasumi",
|
||||
"jpn": "ハスミ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Hanae",
|
||||
"jpn": "ハナエ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Airi",
|
||||
"jpn": "アイリ"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ノゾミ",
|
||||
"eng": "Nozomi"
|
||||
}
|
||||
},
|
||||
"rarity": 2
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Chinatsu",
|
||||
"jpn": "チナツ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Haruka",
|
||||
"jpn": "ハルカ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "ジュリ",
|
||||
"eng": "Juri"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "コタマ",
|
||||
"eng": "Kotama"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "アスナ",
|
||||
"eng": "Asuna"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "コトリ",
|
||||
"eng": "Kotori"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "フィーナ",
|
||||
"eng": "Pina"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"jpn": "スズミ",
|
||||
"eng": "Suzumi"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Shimiko",
|
||||
"jpn": "シミコ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Serina",
|
||||
"jpn": "セリナ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"translations": {
|
||||
"eng": "Yoshimi",
|
||||
"jpn": "ヨシミ"
|
||||
}
|
||||
},
|
||||
"rarity": 1
|
||||
}
|
||||
]
|
|
@ -0,0 +1,159 @@
|
|||
use bluearch_recruitment::banner::{Banner, BannerBuilder};
|
||||
use bluearch_recruitment::gacha::{GachaBuilder, Recruitment};
|
||||
use bluearch_recruitment::i18n::Language;
|
||||
use bluearch_recruitment::student::Student;
|
||||
use dotenv::dotenv;
|
||||
use lazy_static::lazy_static;
|
||||
use log::{error, info};
|
||||
use serenity::async_trait;
|
||||
use serenity::client::{Client, Context, EventHandler};
|
||||
use serenity::framework::standard::{
|
||||
macros::{command, group},
|
||||
CommandResult, StandardFramework,
|
||||
};
|
||||
use serenity::model::channel::Message;
|
||||
use std::env;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[group]
|
||||
#[commands(ping)]
|
||||
struct General;
|
||||
|
||||
#[group]
|
||||
#[commands(roll, roll10, banner)]
|
||||
struct RecruitmentCommands;
|
||||
|
||||
struct Handler;
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {}
|
||||
|
||||
const STUDENTS_JSON: &str = include_str!("../data/students.json");
|
||||
|
||||
lazy_static! {
|
||||
static ref STUDENTS: Vec<Student> = serde_json::from_str(STUDENTS_JSON).unwrap();
|
||||
static ref BANNER: Banner = create_banner();
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
dotenv().ok();
|
||||
env_logger::init();
|
||||
|
||||
let framework = StandardFramework::new()
|
||||
.configure(|c| c.prefix("!")) // set the bot's prefix to "!"
|
||||
.group(&GENERAL_GROUP)
|
||||
.group(&RECRUITMENTCOMMANDS_GROUP);
|
||||
|
||||
// Login with a bot token from the environment
|
||||
let token = env::var("DISCORD_BOT_TOKEN").expect("DISCORD_BOT_TOKEN was not set.");
|
||||
info!("アロナ has started with Bot Token: {}", &token);
|
||||
|
||||
let mut client = Client::builder(token)
|
||||
.event_handler(Handler)
|
||||
.framework(framework)
|
||||
.await
|
||||
.expect("Failed to create Serenity Client");
|
||||
|
||||
info!("Successfully created the Serenity Client");
|
||||
|
||||
// start listening for events by starting a single shard
|
||||
if let Err(why) = client.start().await {
|
||||
error!("An error occurred while running the client: {:?}", why);
|
||||
}
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
let author_name = format!("{}#{}", msg.author.name, msg.author.discriminator);
|
||||
info!("Ping received from: {}", author_name);
|
||||
|
||||
let now = SystemTime::now();
|
||||
|
||||
match now.duration_since(UNIX_EPOCH) {
|
||||
Ok(now_timestamp) => {
|
||||
let diff = now_timestamp.as_millis() - msg.timestamp.timestamp_millis() as u128;
|
||||
msg.reply(ctx, format!("Pong! (Response: {}ms)", diff))
|
||||
.await?;
|
||||
}
|
||||
Err(_) => {
|
||||
msg.reply(ctx, "Pong! (Response: ??ms)").await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn roll(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
let author_name = format!("{}#{}", msg.author.name, msg.author.discriminator);
|
||||
info!("{} Requested a single roll", author_name);
|
||||
|
||||
let student = BANNER.roll();
|
||||
|
||||
msg.reply(
|
||||
ctx,
|
||||
format!(
|
||||
"You Pulled: {} {}",
|
||||
student.name.get(Language::English).unwrap(),
|
||||
student.rarity
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn roll10(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
let author_name = format!("{}#{}", msg.author.name, msg.author.discriminator);
|
||||
info!("{} Requested a 10-roll", author_name);
|
||||
|
||||
let students = BANNER.roll10();
|
||||
let mut response = "You Pulled:\n".to_string();
|
||||
|
||||
for student in students.iter() {
|
||||
response += &format!(
|
||||
"{} {}\n",
|
||||
student.name.get(Language::English).unwrap(),
|
||||
student.rarity
|
||||
);
|
||||
}
|
||||
|
||||
msg.reply(ctx, response).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[command]
|
||||
async fn banner(ctx: &Context, msg: &Message) -> CommandResult {
|
||||
msg.reply(ctx, format!("Current Banner: {}", BANNER.name))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn create_banner() -> Banner {
|
||||
let pool: Vec<Student> = STUDENTS
|
||||
.iter()
|
||||
.filter(|student| student.name != "ノゾミ")
|
||||
.map(|student| student.clone())
|
||||
.collect();
|
||||
|
||||
let sparkable: Vec<Student> = pool
|
||||
.iter()
|
||||
.filter(|student| student.name == "ホシノ" || student.name == "シロコ")
|
||||
.map(|student| student.clone())
|
||||
.collect();
|
||||
|
||||
let gacha = GachaBuilder::new(79.0, 18.5, 2.5)
|
||||
.with_pool(pool)
|
||||
.with_priority(&sparkable, 0.7)
|
||||
.finish()
|
||||
.unwrap();
|
||||
|
||||
BannerBuilder::new("ピックアップ募集")
|
||||
.with_gacha(&gacha)
|
||||
.with_name_translation(Language::English, "Rate-Up Recruitment")
|
||||
.with_sparkable_students(&sparkable)
|
||||
.finish()
|
||||
.unwrap()
|
||||
}
|
Loading…
Reference in New Issue