Initial Commit

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-02-10 19:14:12 -06:00
commit ef13383f5a
7 changed files with 2101 additions and 0 deletions

2
.env.example Normal file
View File

@ -0,0 +1,2 @@
DISCORD_BOT_TOKEN=
RUST_LOG=

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/target
/.env
/.vscode

1491
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

18
Cargo.toml Normal file
View File

@ -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"] }

21
LICENSE Normal file
View File

@ -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.

407
data/students.json Normal file
View File

@ -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
}
]

159
src/main.rs Normal file
View File

@ -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()
}