Skip to content

Commit

Permalink
Merge branch 'Blonteractor:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
spaceavenue authored Feb 1, 2024
2 parents 0afb318 + 39d38ca commit b040e46
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 35 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
./amizone/proto/googleapis/
68 changes: 68 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
on:
push:
tags:
- '**'
branches:
- '**'
workflow_dispatch:

name: CI

jobs:
checks:
runs-on: ubuntu-latest
# env:
# DATABASE_URL: ${{ secrets.DATABASE_URL }}
# PRIVATE_ENCRPYPTION_KEY: ${{ secrets.PRIVATE_ENCRPYPTION_KEY }}

steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: 'true'

- name: Bootstrap rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: rustfmt, clippy
target: x86_64-unknown-linux-gnu
continue-on-error: true

- name: Bootstrap protoc
uses: arduino/setup-protoc@v2

- name: Update rust
run: |
rustup update
continue-on-error: true

- name: Add target
run: |
rustup target add x86_64-unknown-linux-gnu
continue-on-error: true

- name: Formatting
run: |
cargo fmt --all -- --check
- name: Lints
run: |
cargo clippy -- --no-deps -D warnings
# - name: Tests
# run: |
# cargo test --release crud
# cargo test --release api
# cargo test --release bot

- name: Bootstrap fly
uses: superfly/flyctl-actions/setup-flyctl@master
if: success() && github.ref == 'refs/heads/main'

- name: Deploy
run: |
flyctl deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
if: success() && github.ref == 'refs/heads/main'
22 changes: 8 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Stage 1: Build the bot and the server to later shift to a minimal image
FROM rust:1.71 AS builder
FROM rust:1.75 AS builder
RUN apt-get update && apt-get install -y protobuf-compiler

WORKDIR /app
Expand All @@ -11,33 +11,27 @@ COPY Cargo.toml Cargo.toml
COPY Cargo.lock Cargo.lock

# Clone the protobuf dependencies
RUN <<EOF
[ "$(ls -A ./amizone/proto/googleapis)" ] && echo "Found protobuf deps" || git clone https://www.github.com/googleapis/googleapis.git ./amizone/proto/googleapis
EOF
RUN rm -rf ./amizone/proto/googleapis && git clone https://www.github.com/googleapis/googleapis.git ./amizone/proto/googleapis

# Build the Bot
RUN cargo build --release

# Stage 2: Create minimal ubuntu image, for running the bot
FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl

# Expose the port for Discord communication
EXPOSE 443

WORKDIR /app

# Copy the .env file from the build context into the Docker image
COPY .env /app/.env
# Copy the .env file from the build context into the Docker image, the wildcard is used to copy optionally, only if it exists
COPY .en* /app/.env

RUN mkdir tls && curl https://letsencrypt.org/certs/lets-encrypt-r3.pem -o tls/lets-encrypt.pem

# Copy the built Bot from the builder stage
COPY --from=builder /app/target/release/bot /app/bot
RUN chmod 755 /app/bot

# Create entrypoint script
COPY <<EOF /app/entrypoint.sh
/app/bot
EOF
RUN chmod +x /app/entrypoint.sh


CMD ["/bin/sh", "/app/entrypoint.sh"]
CMD ["/app/bot"]
36 changes: 23 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,43 @@
# Amibot

[![Discord](https://img.shields.io/static/v1?logo=Discord&logoColor=fff&labelColor=5562ea&label=Amibot%20Early%20Access&message=⬅️%20Click%20to%20use%20&color=50524f)](https://discord.gg/T9ZDVTw4mQ)
[![Discord](https://img.shields.io/static/v1?logo=Discord&logoColor=fff&labelColor=5562ea&label=Amibot%20Early%20Access&message=⬅️%20Click%20to%20use%20&color=50524f)](https://discord.com/api/oauth2/authorize?client_id=1098463516664537129&permissions=0&scope=bot)

![Rust](https://img.shields.io/badge/Rust-%23000000.svg?style=flat&logo=rust&logoColor=white)
![MongoDB Logo](https://img.shields.io/badge/-MongoDB-47A248?logo=MongoDB&logoColor=fff)
[![go-amizone Logo](https://img.shields.io/badge/go%20amizone-2D8CFF?logo=go&logoColor=white)](https://github.com/ditsuke/go-amizone)
[![Issues](https://img.shields.io/github/issues/blonteractor/discord-amibot?logo=github)](https://github.com/blonteractor/discord-amibot/issues)
[![License](https://img.shields.io/github/license/Blonteractor/discord-amibot)](./LICENSE)

This is a Discord bot that allows users to access their student portal directly in Discord. The bot is written in Rust and uses [go-amizone](https://github.com/ditsuke/go-amizone) as its backend.
This project uses [poise.rs](https://github.com/serenity-rs/poise) as its Discord bot framework.
This is a Discord bot that allows users to access their student portal directly
in Discord. The bot is written in Rust and uses
[go-amizone](https://github.com/ditsuke/go-amizone) as its backend. This project
uses [poise.rs](https://github.com/serenity-rs/poise) as its Discord bot
framework.

## Getting Started

1. Clone this repository to your local machine.
2. Install Rust and its package manager, Cargo, if you haven't already.
3. Install the required dependencies by running `cargo build`.
4. Create a Discord bot and obtain its token.
5. Install an [intermediate certificate](https://letsencrypt.org/certificates/#intermediate-certificates) from Let's Encrypt, rename it to 'lets-encrypt.pem' and put it in a folder named 'tls/' in the root of the project.
6. Create a `.env` file in the root directory of the project and set the following environment variables:
- `DISCORD_TOKEN`
- `DATABASE_URL`
- `AMIZONE_API_URL`
- `DEV_ID`
- `DEV_SERVER_ID` (optional if you compile with the --release flag)
- `PRIVATE_ENCRYPTION_KEY` (AES 256 bit key, _encoded to Base64_)
5. Install an
[intermediate certificate](https://letsencrypt.org/certificates/#intermediate-certificates)
from Let's Encrypt, rename it to 'lets-encrypt.pem' and put it in a folder
named 'tls/' in the root of the project.
6. Create a `.env` file in the root directory of the project and set the
following environment variables:
- `DISCORD_TOKEN`
- `DATABASE_URL`
- `AMIZONE_API_URL`
- `DEV_ID`
- `DEV_SERVER_ID` (optional if you compile with the --release flag)
- `PRIVATE_ENCRYPTION_KEY` (AES 256 bit key, _encoded to Base64_)
7. Run the bot by running `cargo run`.

## Commands

> **Note**: Bot is in active developement, all commands might not be stable, see [issues](https://github.com/Blonteractor/discord-amibot/issues)
> **Note**: Bot is in active developement, all commands might not be stable, see
> [issues](https://github.com/Blonteractor/discord-amibot/issues)
- `/attendance`: Displays the user's attendance for the current semester.
- `/schedule <YYYY-MM-DD>`: Displays the user's schedule for the given date.
Expand All @@ -43,7 +51,9 @@ This project uses [poise.rs](https://github.com/serenity-rs/poise) as its Discor

## Contributing

Contributions are welcome! If you find a bug or have a feature request, please open an issue. If you'd like to contribute code, please fork the repository and create a pull request.
Contributions are welcome! If you find a bug or have a feature request, please
open an issue. If you'd like to contribute code, please fork the repository and
create a pull request.

[Contribution Guide](./CONTRIBUTING.md)

Expand Down
6 changes: 3 additions & 3 deletions bot/src/callbacks.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::error::BotError;
use super::{Connections, Context, Data, Result, IGNORE_CHECK};
use log::{debug, info, trace, error};
use log::{debug, error, info, trace};
use std::collections::HashMap;
use std::env;
use std::str::FromStr;
Expand Down Expand Up @@ -44,10 +44,10 @@ pub async fn on_ready<'a>(
trace!("Setting up connections");
let connections = Connections {
amizone: amizoneapi::new_amizone_connection(
env::var("AMIZONE_API_URL").expect("missing AMIZONE_API_URL"),
env::var("AMIZONE_API_URL").unwrap_or("https://amizone.fly.dev".to_string()),
)
.await
.expect("`AMIZONE_API_URL` not found"),
.expect("Failed to initialize connection to go-amizone."),
db: amizoneapi::new_db_connection(
env::var("DATABASE_URL").expect("missing `DATABASE_URL`"),
)
Expand Down
2 changes: 1 addition & 1 deletion bot/src/commands/attendance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Note: This command requires you to be logged in using the /login command. If you
/// Retrieves your attendance records for the current semester.
#[poise::command(prefix_command, slash_command, help_text_fn = "attendance_help")]
pub async fn attendance(ctx: Context<'_>) -> CommandResult {
ctx.defer().await?;
ctx.defer_ephemeral().await?;
let mut invocation_data = ctx.invocation_data::<Result<UserClient>>().await.unwrap();

let client = invocation_data.as_mut()?;
Expand Down
2 changes: 1 addition & 1 deletion bot/src/commands/courses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub async fn courses(
ctx: Context<'_>,
#[description = "Semester number"] semester: Option<usize>,
) -> CommandResult {
ctx.defer().await?;
ctx.defer_ephemeral().await?;
let mut invocation_data = ctx.invocation_data::<Result<UserClient>>().await.unwrap();

let client = invocation_data.as_mut()?;
Expand Down
1 change: 0 additions & 1 deletion bot/src/commands/exam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ pub async fn datesheet(ctx: Context<'_>) -> CommandResult {
let (title, datesheet) = client.get_exam_schedule().await?;

if !datesheet.is_empty() {

let mut message = format!("**{}**```", title);
// let mut message = String::new;

Expand Down
2 changes: 1 addition & 1 deletion bot/src/commands/profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The information is presented in an embedded format with different fields.";
/// Retrieve and display your user profile information.
#[poise::command(prefix_command, slash_command, help_text_fn = "profile_help")]
pub async fn profile(ctx: Context<'_>) -> CommandResult {
ctx.defer().await?;
ctx.defer_ephemeral().await?;
let mut invocation_data = ctx.invocation_data::<Result<UserClient>>().await.unwrap();

let client = invocation_data.as_mut()?;
Expand Down
2 changes: 1 addition & 1 deletion bot/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ async fn main() {
..Default::default()
})
.token(env::var("DISCORD_TOKEN").expect("missing DISCORD_TOKEN"))
.intents(serenity::GatewayIntents::all())
.intents(serenity::GatewayIntents::non_privileged())
.setup(|ctx, ready, framework| Box::pin(callbacks::on_ready(ctx, ready, framework)));

framework.run().await.expect("Failed to run framework");
Expand Down
17 changes: 17 additions & 0 deletions fly.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
app = "discord-amibot"
primary_region = "lax"

[build]

[http_service]
internal_port = 443
force_https = true
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1
processes = ["app"]

[[vm]]
cpu_kind = "shared"
cpus = 1
memory_mb = 1024

0 comments on commit b040e46

Please sign in to comment.