mirror of
https://github.com/mii443/ncb-chat.git
synced 2025-08-22 16:15:27 +00:00
init
This commit is contained in:
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
target
|
||||||
|
audio
|
47
.github/workflows/build.yml
vendored
Normal file
47
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- '**'
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
name: Checkout
|
||||||
|
- uses: docker/metadata-action@v3
|
||||||
|
id: meta
|
||||||
|
with:
|
||||||
|
images: ghcr.io/morioka22/ncb-ping
|
||||||
|
tags: |
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
- uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: morioka22
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- name: Cache Docker layers
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /tmp/.buildx-cache
|
||||||
|
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-buildx-
|
||||||
|
|
||||||
|
- uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
cache-from: type=local,src=/tmp/.buildx-cache
|
||||||
|
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
|
||||||
|
- name: Move cache
|
||||||
|
run: |
|
||||||
|
rm -rf /tmp/.buildx-cache
|
||||||
|
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
Cargo.lock
|
||||||
|
/target
|
||||||
|
config.toml
|
||||||
|
*.swp
|
26
Cargo.toml
Normal file
26
Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
[package]
|
||||||
|
name = "ncb-ping"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde_json = "1.0"
|
||||||
|
serde = "1.0"
|
||||||
|
toml = "0.5"
|
||||||
|
async-trait = "0.1.57"
|
||||||
|
chrono = "0.4.23"
|
||||||
|
|
||||||
|
[dependencies.uuid]
|
||||||
|
version = "0.8"
|
||||||
|
features = ["serde", "v4"]
|
||||||
|
|
||||||
|
[dependencies.serenity]
|
||||||
|
version = "0.11.5"
|
||||||
|
features = ["builder", "cache", "client", "gateway", "model", "utils", "unstable_discord_api", "collector", "rustls_backend", "framework", "voice"]
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies.tokio]
|
||||||
|
version = "1.0"
|
||||||
|
features = ["macros", "rt-multi-thread", "sync"]
|
19
Dockerfile
Normal file
19
Dockerfile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
FROM lukemathwalker/cargo-chef:latest-rust-1 AS chef
|
||||||
|
WORKDIR app
|
||||||
|
|
||||||
|
FROM chef AS planner
|
||||||
|
COPY . .
|
||||||
|
RUN cargo chef prepare --recipe-path recipe.json
|
||||||
|
|
||||||
|
FROM chef AS builder
|
||||||
|
COPY --from=planner /app/recipe.json recipe.json
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends libssl-dev pkg-config gcc && apt-get -y clean
|
||||||
|
RUN cargo chef cook --release --recipe-path recipe.json
|
||||||
|
COPY . .
|
||||||
|
RUN cargo build --release
|
||||||
|
|
||||||
|
FROM debian:bullseye-slim AS runtime
|
||||||
|
WORKDIR /ncb-ping
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates libssl-dev && apt-get -y clean
|
||||||
|
COPY --from=builder /app/target/release/ncb-ping /usr/local/bin
|
||||||
|
ENTRYPOINT ["/usr/local/bin/ncb-ping"]
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 mii8080
|
||||||
|
|
||||||
|
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.
|
9
docker-compose.yml
Normal file
9
docker-compose.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
ncb-tts-r2:
|
||||||
|
container_name: ncb-tts-r2
|
||||||
|
image: ghcr.io/morioka22/ncb-tts-r2:1.2
|
||||||
|
environment:
|
||||||
|
- NCB_TOKEN=YOUR_BOT_TOKEN
|
||||||
|
- NCB_APP_ID=YOUR_BOT_ID
|
28
manifest/ncb-ping.yaml
Normal file
28
manifest/ncb-ping.yaml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: ncb-ping-deployment
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: ncb-ping
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: ncb-ping
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: ping
|
||||||
|
image: ghcr.io/morioka22/ncb-ping
|
||||||
|
env:
|
||||||
|
- name: NCB_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: ncb-secret
|
||||||
|
key: BOT_TOKEN
|
||||||
|
- name: NCB_APP_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: ncb-secret
|
||||||
|
key: APP_ID
|
7
src/config.rs
Normal file
7
src/config.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
pub token: String,
|
||||||
|
pub application_id: u64,
|
||||||
|
}
|
24
src/data.rs
Normal file
24
src/data.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serenity::{
|
||||||
|
futures::lock::Mutex,
|
||||||
|
model::prelude::{ChannelId, Message, UserId},
|
||||||
|
prelude::TypeMapKey,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Ping {
|
||||||
|
pub channel: ChannelId,
|
||||||
|
pub user_id: UserId,
|
||||||
|
pub author: UserId,
|
||||||
|
pub message: Message,
|
||||||
|
pub time: DateTime<Utc>,
|
||||||
|
pub args: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PingData;
|
||||||
|
|
||||||
|
impl TypeMapKey for PingData {
|
||||||
|
type Value = Arc<Mutex<HashMap<UserId, Ping>>>;
|
||||||
|
}
|
23
src/event_handler.rs
Normal file
23
src/event_handler.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use serenity::{
|
||||||
|
async_trait,
|
||||||
|
client::{Context, EventHandler},
|
||||||
|
model::{
|
||||||
|
channel::Message,
|
||||||
|
gateway::Ready,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::events;
|
||||||
|
|
||||||
|
pub struct Handler;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl EventHandler for Handler {
|
||||||
|
async fn message(&self, ctx: Context, message: Message) {
|
||||||
|
events::message_receive::message(ctx, message).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn ready(&self, ctx: Context, ready: Ready) {
|
||||||
|
events::ready::ready(ctx, ready).await
|
||||||
|
}
|
||||||
|
}
|
58
src/events/message_receive.rs
Normal file
58
src/events/message_receive.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
use chrono::Utc;
|
||||||
|
use serenity::{model::prelude::Message, prelude::Context};
|
||||||
|
|
||||||
|
use crate::data::{PingData, Ping};
|
||||||
|
|
||||||
|
pub async fn message(ctx: Context, message: Message) {
|
||||||
|
if message.author.bot {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let guild_id = message.guild(&ctx.cache);
|
||||||
|
|
||||||
|
if let None = guild_id {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let storage_lock = {
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
data_read
|
||||||
|
.get::<PingData>()
|
||||||
|
.expect("Cannot get PingData")
|
||||||
|
.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if message.mentions.len() == 1 {
|
||||||
|
let user = message.mentions.first().unwrap();
|
||||||
|
let m = format!("PING {} ({}) 56(84) bytes of data.", user.name, user.id.0);
|
||||||
|
let ping_message = message.reply(&ctx.http, m).await.unwrap();
|
||||||
|
|
||||||
|
let ping = Ping {
|
||||||
|
channel: message.channel_id,
|
||||||
|
user_id: user.id,
|
||||||
|
author: message.author.id,
|
||||||
|
time: Utc::now(),
|
||||||
|
message: ping_message,
|
||||||
|
args: vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut storage = storage_lock.lock().await;
|
||||||
|
storage.insert(user.id, ping.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut storage = storage_lock.lock().await;
|
||||||
|
if !storage.contains_key(&message.author.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ping = storage.get_mut(&message.author.id).unwrap();
|
||||||
|
|
||||||
|
if ping.channel == message.channel_id {
|
||||||
|
let user = ping.user_id.to_user(&ctx.http).await.unwrap();
|
||||||
|
let time = Utc::now() - ping.time;
|
||||||
|
ping.message.edit(&ctx.http, |f| f.content(format!("--- {} ping statistics ---\n1 packets transmitted, 1 received, 0% packet loss, time {}ms", user.name, time.num_milliseconds()))).await.unwrap();
|
||||||
|
message.channel_id.send_message(&ctx.http, |f| f.content(format!("<@{}>", ping.author.0))).await.unwrap();
|
||||||
|
storage.remove(&message.author.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
src/events/mod.rs
Normal file
2
src/events/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod message_receive;
|
||||||
|
pub mod ready;
|
5
src/events/ready.rs
Normal file
5
src/events/ready.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use serenity::{model::prelude::Ready, prelude::Context};
|
||||||
|
|
||||||
|
pub async fn ready(_: Context, ready: Ready) {
|
||||||
|
println!("{} is connected!", ready.user.name);
|
||||||
|
}
|
66
src/main.rs
Normal file
66
src/main.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
mod config;
|
||||||
|
mod data;
|
||||||
|
mod event_handler;
|
||||||
|
mod events;
|
||||||
|
|
||||||
|
use std::{collections::HashMap, env, sync::Arc};
|
||||||
|
|
||||||
|
use config::Config;
|
||||||
|
use data::PingData;
|
||||||
|
use event_handler::Handler;
|
||||||
|
use serenity::{
|
||||||
|
client::Client, framework::StandardFramework, futures::lock::Mutex, prelude::GatewayIntents,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Create discord client
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```rust
|
||||||
|
/// let client = create_client("!", "BOT_TOKEN", 123456789123456789).await;
|
||||||
|
///
|
||||||
|
/// client.start().await;
|
||||||
|
/// ```
|
||||||
|
async fn create_client(prefix: &str, token: &str, id: u64) -> Result<Client, serenity::Error> {
|
||||||
|
let framework = StandardFramework::new().configure(|c| c.with_whitespace(true).prefix(prefix));
|
||||||
|
|
||||||
|
Client::builder(token, GatewayIntents::all())
|
||||||
|
.event_handler(Handler)
|
||||||
|
.application_id(id)
|
||||||
|
.framework(framework)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
// Load config
|
||||||
|
let config = {
|
||||||
|
let config = std::fs::read_to_string("./config.toml");
|
||||||
|
if let Ok(config) = config {
|
||||||
|
toml::from_str::<Config>(&config).expect("Cannot load config file.")
|
||||||
|
} else {
|
||||||
|
let token = env::var("NCB_TOKEN").unwrap();
|
||||||
|
let application_id = env::var("NCB_APP_ID").unwrap();
|
||||||
|
|
||||||
|
Config {
|
||||||
|
token,
|
||||||
|
application_id: u64::from_str_radix(&application_id, 10).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create discord client
|
||||||
|
let mut client = create_client("p.", &config.token, config.application_id)
|
||||||
|
.await
|
||||||
|
.expect("Err creating client");
|
||||||
|
|
||||||
|
// Create TTS storage
|
||||||
|
{
|
||||||
|
let mut data = client.data.write().await;
|
||||||
|
data.insert::<PingData>(Arc::new(Mutex::new(HashMap::default())));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run client
|
||||||
|
if let Err(why) = client.start().await {
|
||||||
|
println!("Client error: {:?}", why);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user