mirror of
https://github.com/roleypoly/roleypoly.git
synced 2025-04-24 19:39:11 +00:00
remove bot, force role order
This commit is contained in:
parent
677d91b17b
commit
dc1e7718bc
13 changed files with 15 additions and 1659 deletions
79
.github/workflows/build.yml
vendored
79
.github/workflows/build.yml
vendored
|
@ -72,69 +72,6 @@ jobs:
|
||||||
path: packages/api/dist/index.mjs
|
path: packages/api/dist/index.mjs
|
||||||
destination: roleypoly-artifacts/workers/${{ github.sha }}
|
destination: roleypoly-artifacts/workers/${{ github.sha }}
|
||||||
|
|
||||||
docker_build:
|
|
||||||
name: Docker Build & Publish
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: startsWith(github.ref, 'refs/heads/dependabot/') != true
|
|
||||||
needs:
|
|
||||||
- node_test
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
dockerfile:
|
|
||||||
- bot
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@master
|
|
||||||
|
|
||||||
- uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: /tmp/.buildx-cache
|
|
||||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-buildx-
|
|
||||||
|
|
||||||
- name: Docker meta
|
|
||||||
id: docker_meta
|
|
||||||
uses: crazy-max/ghaction-docker-meta@v1
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
ghcr.io/roleypoly/${{matrix.dockerfile}}
|
|
||||||
tag-sha: true
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
id: buildx
|
|
||||||
uses: docker/setup-buildx-action@v1
|
|
||||||
with:
|
|
||||||
install: true
|
|
||||||
|
|
||||||
- name: Login to GHCR
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: roleypoly
|
|
||||||
password: ${{ secrets.GHCR_PAT }}
|
|
||||||
|
|
||||||
- name: Build and push
|
|
||||||
uses: docker/build-push-action@v2
|
|
||||||
id: docker
|
|
||||||
with:
|
|
||||||
context: ./packages/${{ matrix.dockerfile }}
|
|
||||||
file: ./packages/${{ matrix.dockerfile }}/Dockerfile
|
|
||||||
push: true
|
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache
|
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
|
||||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
|
||||||
|
|
||||||
- name: Pre-deploy - Save digest.txt
|
|
||||||
run: |
|
|
||||||
echo "${{ steps.docker.outputs.digest }}" > digest.txt
|
|
||||||
|
|
||||||
- name: Pre-deploy - Make digest artifact
|
|
||||||
uses: actions/upload-artifact@v2.2.4
|
|
||||||
with:
|
|
||||||
name: ${{ matrix.dockerfile }}-digest
|
|
||||||
path: digest.txt
|
|
||||||
|
|
||||||
trigger_deploy:
|
trigger_deploy:
|
||||||
name: Deploy to Stage
|
name: Deploy to Stage
|
||||||
needs:
|
needs:
|
||||||
|
@ -143,19 +80,6 @@ jobs:
|
||||||
if: github.ref == 'refs/heads/main'
|
if: github.ref == 'refs/heads/main'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Get Bot digest
|
|
||||||
uses: actions/download-artifact@v2
|
|
||||||
with:
|
|
||||||
name: bot-digest
|
|
||||||
path: .digests/bot
|
|
||||||
|
|
||||||
- name: Set digests as addressable
|
|
||||||
id: digests
|
|
||||||
env:
|
|
||||||
IMAGES: bot
|
|
||||||
run: |
|
|
||||||
echo ::set-output name=bot::@$(cat .digests/bot/digest.txt)
|
|
||||||
|
|
||||||
- name: Invoke Deploy workflow
|
- name: Invoke Deploy workflow
|
||||||
uses: benc-uk/workflow-dispatch@v1
|
uses: benc-uk/workflow-dispatch@v1
|
||||||
with:
|
with:
|
||||||
|
@ -164,6 +88,5 @@ jobs:
|
||||||
inputs: |-
|
inputs: |-
|
||||||
{
|
{
|
||||||
"environment": "stage",
|
"environment": "stage",
|
||||||
"worker_tag": "${{ github.sha }}",
|
"worker_tag": "${{ github.sha }}"
|
||||||
"bot_tag": "${{ steps.digests.outputs.bot }}"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,8 @@ export const getGuild = async (
|
||||||
.filter((x) => x !== undefined) as APIRole[]
|
.filter((x) => x !== undefined) as APIRole[]
|
||||||
)?.position || -1;
|
)?.position || -1;
|
||||||
|
|
||||||
const roles = guildRaw.roles.map<Role>((role) => ({
|
const roles = guildRaw.roles
|
||||||
|
.map<Role>((role) => ({
|
||||||
id: role.id,
|
id: role.id,
|
||||||
name: role.name,
|
name: role.name,
|
||||||
color: role.color,
|
color: role.color,
|
||||||
|
@ -55,7 +56,9 @@ export const getGuild = async (
|
||||||
position: role.position,
|
position: role.position,
|
||||||
permissions: role.permissions,
|
permissions: role.permissions,
|
||||||
safety: calculateRoleSafety(role, highestRolePosition),
|
safety: calculateRoleSafety(role, highestRolePosition),
|
||||||
}));
|
}))
|
||||||
|
// sort so that highest is first
|
||||||
|
.sort((a, b) => b.position - a.position);
|
||||||
|
|
||||||
const guild: Guild & OwnRoleInfo = {
|
const guild: Guild & OwnRoleInfo = {
|
||||||
id,
|
id,
|
||||||
|
|
1
packages/bot/.gitignore
vendored
1
packages/bot/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
target
|
|
1283
packages/bot/Cargo.lock
generated
1283
packages/bot/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,12 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "bot"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
serenity = { version = "0.10.10", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "unstable_discord_api", "collector"] }
|
|
||||||
dotenv = "0.15.0"
|
|
||||||
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
|
|
||||||
url = "2.2.2"
|
|
|
@ -1,22 +0,0 @@
|
||||||
# Leveraging the pre-built Docker images with
|
|
||||||
# cargo-chef and the Rust toolchain
|
|
||||||
FROM lukemathwalker/cargo-chef:latest-rust-1.58.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
|
|
||||||
# Build dependencies - this is the caching Docker layer!
|
|
||||||
RUN cargo chef cook --release --recipe-path recipe.json
|
|
||||||
# Build application
|
|
||||||
COPY . .
|
|
||||||
RUN cargo build --release --bin bot
|
|
||||||
|
|
||||||
# We do not need the Rust toolchain to run the binary!
|
|
||||||
FROM debian:bullseye-slim AS runtime
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=builder /app/target/release/bot /usr/local/bin/bot
|
|
||||||
ENTRYPOINT ["/usr/local/bin/bot"]
|
|
|
@ -1,19 +0,0 @@
|
||||||
# Roleypoly Mention Responder
|
|
||||||
|
|
||||||
This is written in Rust.
|
|
||||||
|
|
||||||
You'll need:
|
|
||||||
|
|
||||||
- The rust toolchain (cargo, rust, etc)
|
|
||||||
|
|
||||||
...and nothing else.
|
|
||||||
|
|
||||||
## Premise of why Rust
|
|
||||||
|
|
||||||
Node.js is slow. It's fast enough for 90% of what we want to do, but due to the slowness and memory constraints we'd like to utilize, something else, particularly one designed for extreme multiprocessing (like Rust or Go) is infinitely better. More threads, more memory control (e.g. we can GC the majority of incoming info before we care about it), just better.
|
|
||||||
|
|
||||||
This was a very simple Node.js app, but it just couldn't be used with the production workload.
|
|
||||||
|
|
||||||
Roleypoly Legacy was running a Go-based bot that worked extremely well, and this iteration's de-evolution back to JS didn't end up working.
|
|
||||||
|
|
||||||
**tl;dr:** this piece of shit only responds to mentions. it has no real logic. it shouldn't take a $45/m cloud server to run it.
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@roleypoly/bot",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"scripts": {
|
|
||||||
"start": "cargo run"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
extern crate dotenv;
|
|
||||||
extern crate tokio;
|
|
||||||
|
|
||||||
use dotenv::dotenv;
|
|
||||||
use std::env;
|
|
||||||
use serenity::{
|
|
||||||
async_trait,
|
|
||||||
model::{
|
|
||||||
channel::Message,
|
|
||||||
gateway::Ready,
|
|
||||||
interactions::{
|
|
||||||
message_component::ButtonStyle,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
prelude::*,
|
|
||||||
client::bridge::gateway::GatewayIntents
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Handler {
|
|
||||||
ui_public_uri : String,
|
|
||||||
ui_hostname : String,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl EventHandler for Handler {
|
|
||||||
async fn message(&self, ctx: Context, msg: Message) {
|
|
||||||
// No DMs, bots, or self.
|
|
||||||
if msg.is_private() || msg.author.bot {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore messages that don't mention the bot
|
|
||||||
if !msg.mentions_me(&ctx).await.unwrap_or(false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.channel_id.send_message(&ctx, |m| {
|
|
||||||
m.reference_message(&msg).allowed_mentions(|f| {
|
|
||||||
f.replied_user(false)
|
|
||||||
});
|
|
||||||
|
|
||||||
let guild_url = format!("{}/s/{}", self.ui_public_uri, msg.guild_id.unwrap().0);
|
|
||||||
|
|
||||||
m.embed(|e| {
|
|
||||||
e.title(":beginner: Howdy, pick your roles here!");
|
|
||||||
e.description("Roleypoly will open in your browser.\n\nIf that's not cool with you, try the `/roleypoly` command!");
|
|
||||||
e.url(&guild_url);
|
|
||||||
e.color(0x453e3d);
|
|
||||||
e
|
|
||||||
});
|
|
||||||
|
|
||||||
m.components(|c| {
|
|
||||||
c.create_action_row(|r| {
|
|
||||||
r.create_button(|b| {
|
|
||||||
b.style(ButtonStyle::Link);
|
|
||||||
b.url(&guild_url);
|
|
||||||
b.label(format!("Pick your roles on {}", self.ui_hostname));
|
|
||||||
b
|
|
||||||
});
|
|
||||||
r
|
|
||||||
});
|
|
||||||
c
|
|
||||||
});
|
|
||||||
m
|
|
||||||
}).await.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn ready(&self, _: Context, ready: Ready) {
|
|
||||||
println!("{} is connected! (shard: {:?})", ready.user.name, ready.shard.unwrap_or_default());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
dotenv().ok();
|
|
||||||
let token = env::var("BOT_TOKEN").expect("BOT_TOKEN not set");
|
|
||||||
let client_id: u64 = env::var("BOT_CLIENT_ID").expect("BOT_CLIENT_ID not set").parse().unwrap();
|
|
||||||
let ui_public_uri = env::var("UI_PUBLIC_URI").expect("UI_PUBLIC_URI not set");
|
|
||||||
let ui_hostname = url::Url::parse(&ui_public_uri).unwrap().host_str().unwrap().to_string();
|
|
||||||
|
|
||||||
let mut client =
|
|
||||||
Client::builder(&token).application_id(client_id)
|
|
||||||
.intents(GatewayIntents::GUILD_MESSAGES)
|
|
||||||
.event_handler(Handler {
|
|
||||||
ui_public_uri,
|
|
||||||
ui_hostname,
|
|
||||||
}).await.expect("Err creating client");
|
|
||||||
|
|
||||||
if let Err(why) = client.start_autosharded().await {
|
|
||||||
println!("Client error: {:?}", why);
|
|
||||||
}
|
|
||||||
}
|
|
114
terraform/bot.tf
114
terraform/bot.tf
|
@ -1,114 +0,0 @@
|
||||||
locals {
|
|
||||||
botTag = var.bot_tag == "" ? ":main" : var.bot_tag
|
|
||||||
botRegion = var.gcp_region
|
|
||||||
}
|
|
||||||
|
|
||||||
data "google_compute_zones" "gcp_zones" {
|
|
||||||
region = local.botRegion
|
|
||||||
status = "UP"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "random_integer" "zone_index" {
|
|
||||||
min = 0
|
|
||||||
max = length(data.google_compute_zones.gcp_zones.names) - 1
|
|
||||||
keepers = {
|
|
||||||
region = local.botRegion
|
|
||||||
envtag = var.environment_tag
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data "google_compute_subnetwork" "default_subnet" {
|
|
||||||
name = "default"
|
|
||||||
region = local.botRegion
|
|
||||||
}
|
|
||||||
|
|
||||||
data "google_compute_default_service_account" "default_service_account" {
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "random_pet" "name" {
|
|
||||||
keepers = {
|
|
||||||
region = local.botRegion
|
|
||||||
envtag = var.environment_tag
|
|
||||||
version = local.botTag
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
locals {
|
|
||||||
instance_name = "roleypoly-bot-${var.environment_tag}-${random_pet.name.id}"
|
|
||||||
}
|
|
||||||
|
|
||||||
module "gce_container" {
|
|
||||||
source = "terraform-google-modules/container-vm/google"
|
|
||||||
version = ">=3.0.0"
|
|
||||||
|
|
||||||
// https://cloud.google.com/container-optimized-os/docs/release-notes/m93#cos-93-16623-102-5
|
|
||||||
cos_image_name = "cos-93-16623-102-5"
|
|
||||||
|
|
||||||
container = {
|
|
||||||
image = "ghcr.io/roleypoly/bot${local.botTag}"
|
|
||||||
|
|
||||||
env = [
|
|
||||||
{
|
|
||||||
name = "BOT_TOKEN",
|
|
||||||
value = var.bot_token
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name = "BOT_CLIENT_ID",
|
|
||||||
value = var.bot_client_id
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name = "UI_PUBLIC_URI",
|
|
||||||
value = var.ui_public_uri
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
restart_policy = "Always"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_compute_instance" "vm" {
|
|
||||||
count = var.deploy_bot ? 1 : 0
|
|
||||||
|
|
||||||
project = var.gcp_project
|
|
||||||
name = local.instance_name
|
|
||||||
machine_type = var.bot_instance_size
|
|
||||||
zone = data.google_compute_zones.gcp_zones.names[random_integer.zone_index.result]
|
|
||||||
|
|
||||||
allow_stopping_for_update = true
|
|
||||||
boot_disk {
|
|
||||||
initialize_params {
|
|
||||||
image = module.gce_container.source_image
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
network_interface {
|
|
||||||
subnetwork = data.google_compute_subnetwork.default_subnet.self_link
|
|
||||||
access_config {
|
|
||||||
network_tier = "STANDARD"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata = {
|
|
||||||
gce-container-declaration = module.gce_container.metadata_value
|
|
||||||
google-logging-enabled = "true"
|
|
||||||
google-monitoring-enabled = "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
labels = {
|
|
||||||
container-vm = module.gce_container.vm_container_label
|
|
||||||
}
|
|
||||||
|
|
||||||
service_account {
|
|
||||||
email = data.google_compute_default_service_account.default_service_account.email
|
|
||||||
scopes = [
|
|
||||||
"https://www.googleapis.com/auth/cloud-platform",
|
|
||||||
"https://www.googleapis.com/auth/logging.write",
|
|
||||||
"https://www.googleapis.com/auth/monitoring.write",
|
|
||||||
"https://www.googleapis.com/auth/trace.append",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
lifecycle {
|
|
||||||
create_before_destroy = true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -58,24 +58,6 @@ variable "root_users" {
|
||||||
description = "Root users to use for role elevation calculations"
|
description = "Root users to use for role elevation calculations"
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "deploy_bot" {
|
|
||||||
type = bool
|
|
||||||
default = false
|
|
||||||
description = "Bot is an optional piece of the system. It's only typically deployed in prod."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "bot_instance_size" {
|
|
||||||
type = string
|
|
||||||
default = "f1-micro"
|
|
||||||
description = "Google Compute Engine VM size"
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "bot_tag" {
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
description = ":tag or @sha265: of ghcr.io/roleypoly/bot"
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "worker_tag" {
|
variable "worker_tag" {
|
||||||
type = string
|
type = string
|
||||||
default = ""
|
default = ""
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
environment_tag = "prod"
|
environment_tag = "prod"
|
||||||
deploy_bot = true
|
deploy_bot = false
|
||||||
bot_instance_size = "e2-small"
|
bot_instance_size = "e2-small"
|
||||||
ui_public_uri = "https://roleypoly.com"
|
ui_public_uri = "https://roleypoly.com"
|
||||||
api_public_uri = "https://api-prod.roleypoly.com"
|
api_public_uri = "https://api-prod.roleypoly.com"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
environment_tag = "stage"
|
environment_tag = "stage"
|
||||||
deploy_bot = true
|
deploy_bot = false
|
||||||
bot_instance_size = "e2-micro"
|
bot_instance_size = "e2-micro"
|
||||||
ui_public_uri = "https://stage.roleypoly.com"
|
ui_public_uri = "https://stage.roleypoly.com"
|
||||||
api_public_uri = "https://api-stage.roleypoly.com"
|
api_public_uri = "https://api-stage.roleypoly.com"
|
||||||
|
|
Loading…
Add table
Reference in a new issue