forked from natto1784/singh3
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
60adc1e937 | |||
af80a94cfb | |||
cdf5c2bce6 | |||
25735e3581 | |||
a3919853b0 | |||
a4e7c64193 | |||
0453caee43 | |||
5779f54f2d | |||
1d63fc050c | |||
05dc40863e | |||
c04ec75f3e | |||
5d24893af6 | |||
cee2e47b6c | |||
cffeff4e27 | |||
d20326a846 | |||
a7a15dc3b1 | |||
18b19f0695 | |||
f59a2c1b7f | |||
9a01af14f7 | |||
8e732b34ca | |||
5c911042be | |||
8177787376 | |||
44aba55f5e | |||
b43472227a | |||
5f8ceb94b2 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Cargo.nix linguist-generated
|
21
.github/workflows/main.yml
vendored
21
.github/workflows/main.yml
vendored
@@ -1,21 +0,0 @@
|
|||||||
name: main
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
|
||||||
jobs:
|
|
||||||
packages:
|
|
||||||
name: test packages
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2.3.4
|
|
||||||
- uses: cachix/install-nix-action@v13
|
|
||||||
with:
|
|
||||||
install_url: https://github.com/numtide/nix-flakes-installer/releases/download/nix-2.4pre20210429_d15a196/install
|
|
||||||
extra_nix_config: |
|
|
||||||
experimental-features = nix-command flakes
|
|
||||||
- uses: cachix/cachix-action@v10
|
|
||||||
with:
|
|
||||||
name: natto1784
|
|
||||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
|
||||||
- run: nix build
|
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,2 +1,7 @@
|
|||||||
target/
|
target/
|
||||||
result
|
result
|
||||||
|
\#*\#
|
||||||
|
.\#*
|
||||||
|
.*~*~
|
||||||
|
*~
|
||||||
|
result-bin
|
||||||
|
714
Cargo.lock
generated
714
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,22 @@
|
|||||||
|
cargo-features = ["edition2021"]
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "singh3"
|
name = "singh3"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = [ "Amneesh Singh <natto@weirdnatto.in>" ]
|
authors = [ "Amneesh Singh <natto@weirdnatto.in>" ]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tracing = "*"
|
tracing = "*"
|
||||||
regex = "*"
|
regex = "1"
|
||||||
tokio-postgres = "*"
|
tokio-postgres = "*"
|
||||||
rand = "*"
|
rand = "*"
|
||||||
|
|
||||||
[dependencies.serenity]
|
[dependencies.serenity]
|
||||||
version = "0.10.*"
|
version = "0.10.10"
|
||||||
features = ["cache", "framework", "standard_framework", "rustls_backend", "unstable_discord_api", "collector"]
|
features = ["cache", "framework", "standard_framework", "rustls_backend", "unstable_discord_api", "collector"]
|
||||||
|
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
features = ["macros", "signal", "rt-multi-thread"]
|
features = ["macros", "signal", "rt-multi-thread"]
|
||||||
|
|
||||||
|
10
README.md
Normal file
10
README.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[](https://ci.weirdnatto.in/teams/main/pipelines/singh3) [](https://hub.docker.com/repository/docker/natto17/singh3)
|
||||||
|
# Singh3
|
||||||
|
My stupid discord bot that I will probably stop maintaining again like I did for the past 8+ months
|
||||||
|
Real shit code
|
||||||
|
- Not really a useful bot, run at your own risk
|
||||||
|
- You need postgresql too
|
||||||
|
- Environment Variables
|
||||||
|
- DISCORD_TOKEN={{.your-discord-token}}
|
||||||
|
- DB_URL={{.your-postgresql-db-url}}
|
||||||
|
- Image size is kinda large cuz it uses ubuntu for libraries that are dynamically needed
|
85
ci/pipeline.yml
Normal file
85
ci/pipeline.yml
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
resource_types:
|
||||||
|
- name: nomad
|
||||||
|
type: registry-image
|
||||||
|
source:
|
||||||
|
repository: natto17/concourse-nomad-resource
|
||||||
|
tag: latest
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- name: image
|
||||||
|
type: registry-image
|
||||||
|
icon: docker
|
||||||
|
source:
|
||||||
|
repository: ((docker.user))/singh3
|
||||||
|
tag: latest
|
||||||
|
username: ((docker.user))
|
||||||
|
password: ((docker.pass))
|
||||||
|
|
||||||
|
- name: nomad-job
|
||||||
|
type: nomad
|
||||||
|
source:
|
||||||
|
url: https://nomad.weirdnatto.in
|
||||||
|
name: singh3
|
||||||
|
token: ((nomad.token))
|
||||||
|
consul_token: ((nomad.consul))
|
||||||
|
vault_token: ((nomad.vault))
|
||||||
|
|
||||||
|
- name: repo
|
||||||
|
type: git
|
||||||
|
icon: discord
|
||||||
|
source:
|
||||||
|
uri: https://git.weirdnatto.in/natto1784/singh3.git
|
||||||
|
branch: master
|
||||||
|
|
||||||
|
- name: nix
|
||||||
|
type: registry-image
|
||||||
|
icon: docker
|
||||||
|
source:
|
||||||
|
repository: nixos/nix
|
||||||
|
tag: latest
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- name: configure-self
|
||||||
|
public: true
|
||||||
|
plan:
|
||||||
|
- get: repo
|
||||||
|
trigger: true
|
||||||
|
- set_pipeline: self
|
||||||
|
file: repo/ci/pipeline.yml
|
||||||
|
- name: singh3
|
||||||
|
plan:
|
||||||
|
- get: repo
|
||||||
|
trigger: true
|
||||||
|
passed: [configure-self]
|
||||||
|
- get: nix
|
||||||
|
trigger: false
|
||||||
|
- task: build
|
||||||
|
image: nix
|
||||||
|
config:
|
||||||
|
params:
|
||||||
|
CACHIX_NAME: ((cachix.name))
|
||||||
|
CACHIX_AUTH_TOKEN: ((cachix.token))
|
||||||
|
inputs:
|
||||||
|
- name: repo
|
||||||
|
outputs:
|
||||||
|
- name: upload
|
||||||
|
platform: linux
|
||||||
|
run:
|
||||||
|
path: sh
|
||||||
|
args:
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
nix-env -iA nixpkgs.cachix nixpkgs.gzip
|
||||||
|
cachix use $CACHIX_NAME
|
||||||
|
cachix watch-exec pain nix -- --extra-experimental-features "nix-command flakes" build ./repo
|
||||||
|
nix --extra-experimental-features "nix-command flakes" build ./repo#image -o result
|
||||||
|
gzip -cd < $(readlink result) > ./upload/image.tar
|
||||||
|
- put: image
|
||||||
|
inputs: [upload]
|
||||||
|
params:
|
||||||
|
image: upload/image.tar
|
||||||
|
- put: nomad-job
|
||||||
|
params:
|
||||||
|
job_path: repo/singh3.nomad
|
||||||
|
templating: false
|
||||||
|
restart: true
|
10
default.nix
Normal file
10
default.nix
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
(import
|
||||||
|
(
|
||||||
|
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
|
||||||
|
fetchTarball {
|
||||||
|
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||||
|
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
{ src = ./.; }
|
||||||
|
).defaultNix
|
108
flake.lock
generated
108
flake.lock
generated
@@ -1,12 +1,47 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"cargo2nix": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"rust-overlay": "rust-overlay"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1648397583,
|
||||||
|
"narHash": "sha256-g1Ej9APkfHjGd9ExBDvpmyAvsKcfMOsNH6p95xc8E/Y=",
|
||||||
|
"owner": "cargo2nix",
|
||||||
|
"repo": "cargo2nix",
|
||||||
|
"rev": "4362ae00fe824d120e94dd5d6f6e63969dc3d264",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cargo2nix",
|
||||||
|
"repo": "cargo2nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1614513358,
|
"lastModified": 1638122382,
|
||||||
"narHash": "sha256-LakhOx3S1dRjnh0b5Dg3mbZyH0ToC9I8Y2wKSkBaTzU=",
|
"narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "5466c5bbece17adaab2d82fae80b46e807611bf3",
|
"rev": "74f7e4319258e287b0f9cb95426c9853b282730b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1637014545,
|
||||||
|
"narHash": "sha256-26IZAc5yzlD9FlDT54io1oqG/bBoyka+FJk5guaX4x4=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "bba5dcc8e0b20ab664967ad83d24d64cb64ec4f4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -16,6 +51,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1638109994,
|
||||||
|
"narHash": "sha256-OpA37PTiPMIqoRJbufbl5rOLII7HeeGcA0yl7FoyCIE=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "a284564b7f75ac4db73607db02076e8da9d42c9d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "release-21.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1622966049,
|
"lastModified": 1622966049,
|
||||||
"narHash": "sha256-6g+28v94ISkVk9TBSsITVOnB2slK8plieWPIF2jo/l0=",
|
"narHash": "sha256-6g+28v94ISkVk9TBSsITVOnB2slK8plieWPIF2jo/l0=",
|
||||||
@@ -31,39 +82,66 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1617325113,
|
"lastModified": 1637453606,
|
||||||
"narHash": "sha256-GksR0nvGxfZ79T91UUtWjjccxazv6Yh/MvEJ82v1Xmw=",
|
"narHash": "sha256-Gy6cwUswft9xqsjWxFYEnx/63/qzaFUwatcbV5GF/GQ=",
|
||||||
"owner": "nixos",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "54c1e44240d8a527a8f4892608c4bce5440c3ecb",
|
"rev": "8afc4e543663ca0a6a4f496262cd05233737e732",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs",
|
"cargo2nix": "cargo2nix",
|
||||||
"rust-overlay": "rust-overlay",
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"rust-overlay": "rust-overlay_2",
|
||||||
"utils": "utils"
|
"utils": "utils"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rust-overlay": {
|
"rust-overlay": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": [
|
||||||
"nixpkgs": "nixpkgs_2"
|
"cargo2nix",
|
||||||
|
"flake-utils"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"cargo2nix",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1623034161,
|
"lastModified": 1638152159,
|
||||||
"narHash": "sha256-cbw9X+nVFcpIuBga0hkbtzXbW2fyDWBon6oUN/uQmu0=",
|
"narHash": "sha256-Q0UHsm36cCxk16I/bF1rHJHxjIflESKk2ej76P39j90=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "0b952cdfa37f8b0fc70fc75fbd4605227cd0b272",
|
"rev": "d9a664513558376595e838b21348cdac0ba3115e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-overlay_2": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": "nixpkgs_3"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1648953213,
|
||||||
|
"narHash": "sha256-kXWcXFwqcvooHjcDoEK4mtvKU/8LuetwhrofU+9KMS0=",
|
||||||
|
"owner": "oxalica",
|
||||||
|
"repo": "rust-overlay",
|
||||||
|
"rev": "caa1a7ea867138d4f4e05bd2f41d707df0a61cde",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
73
flake.nix
73
flake.nix
@@ -1,37 +1,54 @@
|
|||||||
{
|
{
|
||||||
description = "A simple filehost written in rust";
|
description = "singh3 discord bot";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = github:nixos/nixpkgs/nixos-unstable;
|
nixpkgs.url = github:nixos/nixpkgs/nixos-unstable;
|
||||||
utils.url = github:numtide/flake-utils;
|
utils.url = github:numtide/flake-utils;
|
||||||
rust-overlay.url = github:oxalica/rust-overlay;
|
rust-overlay.url = github:oxalica/rust-overlay;
|
||||||
|
cargo2nix.url = github:cargo2nix/cargo2nix;
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, utils, rust-overlay }:
|
outputs = { self, nixpkgs, utils, rust-overlay, cargo2nix }:
|
||||||
utils.lib.eachDefaultSystem
|
utils.lib.eachDefaultSystem
|
||||||
(system:
|
(system:
|
||||||
let
|
let
|
||||||
overlays = [ (import rust-overlay) ];
|
overlays =
|
||||||
pkgs = import nixpkgs {
|
[
|
||||||
inherit system overlays;
|
(import "${cargo2nix}/overlay")
|
||||||
};
|
rust-overlay.overlay
|
||||||
in
|
];
|
||||||
{
|
|
||||||
devShell = with pkgs; mkShell {
|
pkgs = import nixpkgs {
|
||||||
buildInputs = [
|
inherit system overlays;
|
||||||
rust-bin.nightly.latest.default
|
};
|
||||||
rust-analyzer
|
|
||||||
];
|
rustPkgs = pkgs.rustBuilder.makePackageSet' {
|
||||||
};
|
rustChannel = "latest";
|
||||||
defaultPackage = pkgs.rustPlatform.buildRustPackage rec {
|
packageFun = import ./Cargo.nix;
|
||||||
pname = "singh3";
|
};
|
||||||
version = "0.1.0";
|
|
||||||
src = ./. ;
|
in
|
||||||
nativeBuildInputs = with pkgs; [
|
rec {
|
||||||
rust-bin.nightly.latest.default
|
devShell = with pkgs; mkShell {
|
||||||
];
|
buildInputs = [
|
||||||
cargoSha256 = "sha256-K+WHOEo6reNfcs7pOZZmHZfZl4pUqlykfTdqgSyVURU=";
|
rust-bin.nightly.latest.default
|
||||||
};
|
rust-analyzer
|
||||||
}
|
postgresql
|
||||||
);
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
packages = {
|
||||||
|
default = (rustPkgs.workspace.singh3 { }).bin;
|
||||||
|
image = pkgs.dockerTools.buildImage {
|
||||||
|
name = "singh3";
|
||||||
|
tag = "latest";
|
||||||
|
created = "now";
|
||||||
|
contents = [ packages.default ];
|
||||||
|
config.Cmd = [ "/bin/singh3" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultPackage = packages.default;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
8
init.sql
8
init.sql
@@ -3,3 +3,11 @@ CREATE TABLE IF NOT EXISTS words (
|
|||||||
name varchar not null,
|
name varchar not null,
|
||||||
reg varchar not null,
|
reg varchar not null,
|
||||||
owner varchar );
|
owner varchar );
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS tags (
|
||||||
|
id serial primary key,
|
||||||
|
name varchar unique not null,
|
||||||
|
value varchar not null,
|
||||||
|
owner varchar );
|
||||||
|
|
||||||
|
CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;
|
||||||
|
48
singh3.nomad
48
singh3.nomad
@@ -1,52 +1,71 @@
|
|||||||
job "singh3" {
|
job "singh3" {
|
||||||
region = "global"
|
region = "global"
|
||||||
datacenters = [ "nazrin" ]
|
datacenters = ["nazrin"]
|
||||||
type = "service"
|
type = "service"
|
||||||
|
|
||||||
group "svc" {
|
group "svc" {
|
||||||
count = 1
|
count = 1
|
||||||
|
|
||||||
network {
|
network {
|
||||||
mode = "bridge"
|
mode = "bridge"
|
||||||
|
|
||||||
port "db" {
|
port "db" {
|
||||||
static = 5454
|
static = 5454
|
||||||
to = 5432
|
to = 5432
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vault {
|
vault {
|
||||||
policies = [ "singh3-policy" ]
|
policies = ["singh3-policy"]
|
||||||
}
|
}
|
||||||
|
|
||||||
service {
|
service {
|
||||||
name = "singh3-db"
|
name = "singh3-db"
|
||||||
port = "db"
|
port = "db"
|
||||||
}
|
}
|
||||||
|
|
||||||
task "db" {
|
task "db" {
|
||||||
template {
|
template {
|
||||||
data = <<EOF
|
data = <<EOF
|
||||||
{{with secret "kv/data/singh3/db"}}{{.Data.data.pass}}{{end}}
|
{{with secret "kv/data/singh3/db"}}{{.Data.data.pass}}{{end}}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
destination = "${NOMAD_SECRETS_DIR}/db.pass"
|
destination = "${NOMAD_SECRETS_DIR}/db.pass"
|
||||||
}
|
}
|
||||||
|
|
||||||
driver = "docker"
|
driver = "docker"
|
||||||
|
|
||||||
config {
|
config {
|
||||||
image = "postgres:alpine"
|
image = "postgres:alpine"
|
||||||
ports = ["db"]
|
ports = ["db"]
|
||||||
volumes = [ "/var/lib/nomad-st/postgres-singh3:/var/lib/postgresql/data" ]
|
volumes = ["/var/lib/nomad-st/postgres-singh3:/var/lib/postgresql/data"]
|
||||||
}
|
}
|
||||||
|
|
||||||
env {
|
env {
|
||||||
POSTGRES_USER = "singh3"
|
POSTGRES_USER = "singh3"
|
||||||
POSTGRES_PASSWORD_FILE = "${NOMAD_SECRETS_DIR}/db.pass"
|
POSTGRES_PASSWORD_FILE = "${NOMAD_SECRETS_DIR}/db.pass"
|
||||||
POSTGRES_DB = "singh3"
|
POSTGRES_DB = "singh3"
|
||||||
}
|
}
|
||||||
|
|
||||||
resources {
|
resources {
|
||||||
cpu = 256
|
cpu = 128
|
||||||
memory = 128
|
memory = 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task "bot" {
|
task "bot" {
|
||||||
driver = "docker"
|
driver = "docker"
|
||||||
|
|
||||||
config {
|
config {
|
||||||
image = "natto17/singh3:latest"
|
image = "natto17/singh3:latest"
|
||||||
force_pull = true
|
force_pull = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 128
|
||||||
|
memory = 100
|
||||||
|
}
|
||||||
|
|
||||||
template {
|
template {
|
||||||
data = <<EOF
|
data = <<EOF
|
||||||
{{with secret "kv/data/singh3/db"}}
|
{{with secret "kv/data/singh3/db"}}
|
||||||
@@ -57,8 +76,9 @@ DISCORD_TOKEN="{{.Data.data.token}}"
|
|||||||
{{end}}
|
{{end}}
|
||||||
RUST_BACKTRACE=1
|
RUST_BACKTRACE=1
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
destination = "${NOMAD_SECRETS_DIR}/data.env"
|
destination = "${NOMAD_SECRETS_DIR}/data.env"
|
||||||
env = true
|
env = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,50 +1,65 @@
|
|||||||
|
use crate::lib::components::make_terminal_components;
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
use regex::Regex;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
|
builder::CreateEmbed,
|
||||||
collector::component_interaction_collector::ComponentInteractionCollectorBuilder,
|
collector::component_interaction_collector::ComponentInteractionCollectorBuilder,
|
||||||
framework::standard::{macros::command, Args, CommandResult},
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
futures::StreamExt,
|
futures::StreamExt,
|
||||||
model::{
|
model::{interactions::InteractionResponseType, prelude::*},
|
||||||
channel::ReactionType,
|
|
||||||
interactions::{ButtonStyle, InteractionData},
|
|
||||||
prelude::*,
|
|
||||||
},
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
utils::Colour,
|
utils::Colour,
|
||||||
};
|
};
|
||||||
use tokio_postgres::Row;
|
use tokio_postgres::Row;
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
pub async fn kitna(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
#[aliases("kitna", "c")]
|
||||||
let query: String = args.raw().collect::<Vec<&str>>().join(" ");
|
pub async fn count(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
if query == "" {
|
if args.len() > 2 || args.len() == 0 {
|
||||||
msg.reply(ctx, "bruh kitna kya?").await?;
|
msg.reply(ctx, "Please use `,count <word> <user>`").await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let query = args.single::<String>().unwrap();
|
||||||
|
let user = if args.len() == 2 {
|
||||||
|
let user = args.single::<UserId>();
|
||||||
|
match user {
|
||||||
|
Ok(id) => match id.to_user(&ctx.http).await {
|
||||||
|
Ok(u) => u,
|
||||||
|
Err(_) => {
|
||||||
|
msg.reply(ctx, "No such user").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
msg.reply(ctx, "No such user").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msg.author.clone()
|
||||||
|
};
|
||||||
|
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
let db = data_read
|
let db = data_read
|
||||||
.get::<crate::Database>()
|
.get::<crate::Database>()
|
||||||
.expect("Expected Database in TypeMap.")
|
.expect("Expected Database in TypeMap.")
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let id = msg.author.id.to_string();
|
let id = user.id.to_string();
|
||||||
let mut query_helper = db
|
let mut query_helper = db
|
||||||
.query(
|
.query("SELECT name FROM words WHERE $1 ~ reg", &[&query])
|
||||||
format!("select name from words where '{}' ~ reg", query).as_str(),
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if query_helper.is_empty() {
|
if query_helper.is_empty() {
|
||||||
query_helper = db
|
query_helper = db
|
||||||
.query(
|
.query("SELECT name FROM words WHERE name=$1", &[&query])
|
||||||
format!("select name from words where name='{}'", query).as_str(),
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
if query_helper.is_empty() {
|
if query_helper.is_empty() {
|
||||||
msg.reply(
|
msg.reply(
|
||||||
ctx,
|
ctx,
|
||||||
format!(
|
format!(
|
||||||
"No entry for '{}' found. If you want to add it, run ',count add {}&<regex>'",
|
"No entry for '{}' found. If you want to add it, run `,cadd {} <regex>`",
|
||||||
query, query
|
query, query
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -59,25 +74,103 @@ pub async fn kitna(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||||||
};
|
};
|
||||||
for row in query_helper {
|
for row in query_helper {
|
||||||
let name: &str = row.get(0);
|
let name: &str = row.get(0);
|
||||||
let query_result: i32 = db
|
let count_query = db
|
||||||
.query_one(
|
.query(
|
||||||
format!("select count from user{} where name='{}'", id, name).as_str(),
|
format!("SELECT count FROM user{} WHERE name=$1", id).as_str(),
|
||||||
&[],
|
&[&name],
|
||||||
)
|
)
|
||||||
.await?
|
.await?;
|
||||||
.get(0);
|
let query_result: i32 = if count_query.is_empty() {
|
||||||
reply = reply + &format!("\n{} count for you: {}", name, query_result);
|
0
|
||||||
|
} else {
|
||||||
|
count_query[0].get(0)
|
||||||
|
};
|
||||||
|
reply += &format!("\n{} count for {}: {}", name, user.name, query_result);
|
||||||
}
|
}
|
||||||
msg.reply(ctx, reply).await?;
|
msg.reply(ctx, reply).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
pub async fn add(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
pub async fn cadd(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
|
let query: String = args.raw().collect::<Vec<&str>>().join(" ");
|
||||||
|
let queries = query.splitn(2, " ").collect::<Vec<&str>>();
|
||||||
|
if queries.len() != 2 {
|
||||||
|
msg.reply(ctx, "Please use the proper syntax: `,cadd <name> <regex>`\nIf you don't know what regex is, just do: `,cadd <name> <name>`")
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let r = Regex::new(&format!("(?i){}", queries[1]));
|
||||||
|
|
||||||
|
if r.is_err() {
|
||||||
|
msg.reply(ctx, "Please enter a valid regex").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let reg = r.unwrap();
|
||||||
|
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
let db = data_read
|
||||||
|
.get::<crate::Database>()
|
||||||
|
.expect("Expected Database in TypeMap.")
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let check_existense = db
|
||||||
|
.query("SELECT name, reg FROM words WHERE name=$1", &[&queries[0]])
|
||||||
|
.await?;
|
||||||
|
if check_existense.len() != 0 {
|
||||||
|
let reg: String = check_existense[0].get(1);
|
||||||
|
msg.reply(
|
||||||
|
ctx,
|
||||||
|
format!("This word already exists with the regex '{}'", reg),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
db.execute(
|
||||||
|
"INSERT INTO words(name, reg, owner) VALUES($1, $2, $3)",
|
||||||
|
&[&queries[0], ®.to_string(), &msg.author.id.to_string()],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
msg.reply(ctx, "Added").await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
#[aliases("crm")]
|
||||||
|
pub async fn cremove(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
|
let query: String = args.raw().collect::<Vec<&str>>().join(" ");
|
||||||
|
if query == "" {
|
||||||
|
msg.reply(ctx, "remove what?").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
let db = data_read
|
||||||
|
.get::<crate::Database>()
|
||||||
|
.expect("Expected Database in TypeMap.")
|
||||||
|
.clone();
|
||||||
|
let owner = db
|
||||||
|
.query("SELECT owner FROM words WHERE name=$1", &[&query])
|
||||||
|
.await?;
|
||||||
|
if owner.len() == 1 {
|
||||||
|
let owner_id: String = owner[0].get(0);
|
||||||
|
if owner_id != msg.author.id.to_string() {
|
||||||
|
msg.reply(ctx, "You don't even own this word").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
db.execute("DELETE FROM words WHERE name=$1", &[&query])
|
||||||
|
.await?;
|
||||||
|
msg.reply(ctx, "Deleted if it existed").await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
pub async fn cedit(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
let query: String = args.raw().collect::<Vec<&str>>().join(" ");
|
let query: String = args.raw().collect::<Vec<&str>>().join(" ");
|
||||||
let queries = query.splitn(2, "&").collect::<Vec<&str>>();
|
let queries = query.splitn(2, "&").collect::<Vec<&str>>();
|
||||||
if queries.len() != 2 {
|
if queries.len() != 2 {
|
||||||
msg.reply(ctx, "Please use the proper syntax: `,count add <name>&<regex>`\nIf you don't know what regex is, just do: `,count add <name>&<name>`")
|
msg.reply(ctx, "Please use the proper syntax\n,cedit <name>&<regex>")
|
||||||
.await?;
|
.await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -86,57 +179,12 @@ pub async fn add(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
let db = data_read
|
|
||||||
.get::<crate::Database>()
|
|
||||||
.expect("Expected Database in TypeMap.")
|
|
||||||
.clone();
|
|
||||||
let check_existense = db
|
|
||||||
.query(
|
|
||||||
format!("select name, reg from words where name='{}'", queries[0]).as_str(),
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
if check_existense.len() != 0 {
|
|
||||||
let reg: String = check_existense[0].get(1);
|
|
||||||
msg.reply(
|
|
||||||
ctx,
|
|
||||||
format!("This word already exists with the regex '{}'", reg),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
db.execute(
|
|
||||||
format!(
|
|
||||||
"insert into words(name, reg, owner) values('{}','(?i){}', '{}')",
|
|
||||||
queries[0],
|
|
||||||
queries[1],
|
|
||||||
msg.author.id.to_string()
|
|
||||||
)
|
|
||||||
.as_str(),
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
msg.reply(ctx, "Added").await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[command]
|
|
||||||
pub async fn rm(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|
||||||
let query: String = args.raw().collect::<Vec<&str>>().join(" ");
|
|
||||||
if query == "" {
|
|
||||||
msg.reply(ctx, "remove what?").await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let data_read = ctx.data.read().await;
|
|
||||||
let db = data_read
|
let db = data_read
|
||||||
.get::<crate::Database>()
|
.get::<crate::Database>()
|
||||||
.expect("Expected Database in TypeMap.")
|
.expect("Expected Database in TypeMap.")
|
||||||
.clone();
|
.clone();
|
||||||
let owner = db
|
let owner = db
|
||||||
.query(
|
.query("SELECT owner FROM words WHERE name=$1", &[&queries[0]])
|
||||||
format!("select owner from words where name = '{}'", query).as_str(),
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
if owner.len() == 1 {
|
if owner.len() == 1 {
|
||||||
let owner_id: String = owner[0].get(0);
|
let owner_id: String = owner[0].get(0);
|
||||||
@@ -146,175 +194,165 @@ pub async fn rm(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.execute(
|
db.execute(
|
||||||
format!("delete from words where name='{}'", query,).as_str(),
|
"UPDATE words SET reg=$1 WHERE name=$2",
|
||||||
&[],
|
&[&("(?i)".to_string() + queries[1]), &queries[0]],
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
msg.reply(ctx, "Deleted if it existed").await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[command]
|
|
||||||
pub async fn change(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|
||||||
let query: String = args.raw().collect::<Vec<&str>>().join(" ");
|
|
||||||
let queries = query.splitn(2, "&").collect::<Vec<&str>>();
|
|
||||||
if queries.len() != 2 {
|
|
||||||
msg.reply(
|
|
||||||
ctx,
|
|
||||||
"Please use the proper syntax\n,count change <name>&<regex>",
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
if queries[1].contains(" ") {
|
|
||||||
msg.reply(ctx, "Not a valid regex").await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let data_read = ctx.data.read().await;
|
|
||||||
let db = data_read
|
|
||||||
.get::<crate::Database>()
|
|
||||||
.expect("Expected Database in TypeMap.")
|
|
||||||
.clone();
|
|
||||||
let owner = db
|
|
||||||
.query(
|
|
||||||
format!("select owner from words where name = '{}'", queries[0]).as_str(),
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
if owner.len() == 1 {
|
|
||||||
let owner_id: String = owner[0].get(0);
|
|
||||||
if owner_id != msg.author.id.to_string() {
|
|
||||||
msg.reply(ctx, "You don't even own this word").await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
db.execute(
|
|
||||||
format!(
|
|
||||||
"update words set reg='(?i){}' where name='{}'",
|
|
||||||
queries[1], queries[0]
|
|
||||||
)
|
|
||||||
.as_str(),
|
|
||||||
&[],
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
msg.reply(ctx, "Changed the value if it existed").await?;
|
msg.reply(ctx, "Changed the value if it existed").await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! make_embed {
|
fn make_list_embed(cur: usize, group: &[Row]) -> CreateEmbed {
|
||||||
($e: expr, $cur: expr, $group: expr) => {{
|
let mut e = CreateEmbed::default();
|
||||||
$e = $e
|
e.title(format!("List of words: Page {}", cur))
|
||||||
.title(format!("List of words: Page {}", $cur))
|
.color(Colour::TEAL);
|
||||||
.color(Colour::TEAL);
|
for row in group {
|
||||||
for row in $group {
|
let idx: i64 = row.get(0);
|
||||||
let idx: i32 = row.get(0);
|
let name: String = row.get(1);
|
||||||
let name: String = row.get(1);
|
let owner_id: String = row.get(2);
|
||||||
let owner_id: String = row.get(3);
|
e.field(
|
||||||
$e = $e.field(
|
format!("{}. {}", idx, name),
|
||||||
format!("{}. {}", idx, name),
|
format!(" by <@{}>", owner_id),
|
||||||
format!(" by <@{}>", owner_id),
|
false,
|
||||||
true,
|
);
|
||||||
);
|
}
|
||||||
}
|
e
|
||||||
$e
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! make_terminal_components {
|
|
||||||
($c: expr, $terminal: expr ) => {{
|
|
||||||
$c.create_action_row(|ar| {
|
|
||||||
ar.create_button(|b| {
|
|
||||||
b.style(ButtonStyle::Primary)
|
|
||||||
.label("Prev")
|
|
||||||
.emoji(ReactionType::Unicode("\u{2B05}".to_string()))
|
|
||||||
.custom_id("prev")
|
|
||||||
.disabled($terminal == "first")
|
|
||||||
})
|
|
||||||
.create_button(|b| {
|
|
||||||
b.style(ButtonStyle::Primary)
|
|
||||||
.label("Next")
|
|
||||||
.emoji(ReactionType::Unicode("\u{27A1}".to_string()))
|
|
||||||
.custom_id("next")
|
|
||||||
.disabled($terminal == "last")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
pub async fn ls(ctx: &Context, msg: &Message, _: Args) -> CommandResult {
|
#[aliases("cls")]
|
||||||
|
pub async fn clist(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
|
let size = if args.len() > 0 {
|
||||||
|
args.single::<usize>()?
|
||||||
|
} else {
|
||||||
|
5usize
|
||||||
|
};
|
||||||
|
|
||||||
|
if size > 15 {
|
||||||
|
msg.reply(ctx, "Please input a number less than 15").await?;
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
let data_read = ctx.data.read().await;
|
let data_read = ctx.data.read().await;
|
||||||
let db = data_read
|
let db = data_read
|
||||||
.get::<crate::Database>()
|
.get::<crate::Database>()
|
||||||
.expect("Expected Database in TypeMap.")
|
.expect("Expected Database in TypeMap.")
|
||||||
.clone();
|
.clone();
|
||||||
let rows = db.query("select * from words", &[]).await?;
|
|
||||||
|
let rows = db
|
||||||
|
.query(
|
||||||
|
"SELECT ROW_NUMBER() OVER (ORDER BY id), name, owner FROM words",
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
if rows.is_empty() {
|
if rows.is_empty() {
|
||||||
msg.reply(ctx, "No words stored").await?;
|
msg.reply(ctx, "No words stored").await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let groups: Vec<&[Row]> = rows.chunks(5).collect();
|
|
||||||
let mut cur = 1;
|
|
||||||
|
|
||||||
|
let groups: Vec<&[Row]> = rows.chunks(size).collect();
|
||||||
|
let mut cur = 1;
|
||||||
let message = msg
|
let message = msg
|
||||||
.channel_id
|
.channel_id
|
||||||
.send_message(ctx, |m| {
|
.send_message(ctx, |m| {
|
||||||
m.embed(|mut e| make_embed!(e, cur, groups[cur - 1]))
|
m.set_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
.components(|c| make_terminal_components!(c, "first"))
|
.set_components(make_terminal_components("first", groups.len()))
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let mut collector = ComponentInteractionCollectorBuilder::new(&ctx)
|
let mut collector = ComponentInteractionCollectorBuilder::new(&ctx)
|
||||||
.timeout(Duration::from_secs(90))
|
.timeout(Duration::from_secs(90))
|
||||||
.author_id(msg.author.id)
|
.author_id(msg.author.id)
|
||||||
.message_id(message.id)
|
.message_id(message.id)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
while let Some(interaction) = collector.next().await {
|
while let Some(interaction) = collector.next().await {
|
||||||
if let InteractionData::MessageComponent(component) = interaction.data.as_ref().unwrap() {
|
match interaction.data.custom_id.as_ref() {
|
||||||
match component.custom_id.as_ref() {
|
"next" => {
|
||||||
"next" => {
|
if cur != groups.len() {
|
||||||
if cur != groups.len() {
|
cur += 1;
|
||||||
let _ = interaction
|
let _ = interaction
|
||||||
.create_interaction_response(&ctx, |r| {
|
.create_interaction_response(&ctx, |r| {
|
||||||
r.kind(InteractionResponseType::UpdateMessage)
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
.interaction_response_data(|m| {
|
.interaction_response_data(|m| {
|
||||||
cur += 1;
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
m.create_embed(|mut e| make_embed!(e, cur, groups[cur - 1]))
|
.set_components(make_terminal_components(
|
||||||
.components(|c| {
|
if cur == groups.len() { "last" } else { "mid" },
|
||||||
make_terminal_components!(
|
groups.len(),
|
||||||
c,
|
))
|
||||||
if cur == groups.len() {
|
})
|
||||||
"last"
|
})
|
||||||
} else {
|
.await;
|
||||||
"mid"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"prev" => {
|
|
||||||
if cur != 1 {
|
|
||||||
let _ = interaction
|
|
||||||
.create_interaction_response(&ctx, |r| {
|
|
||||||
r.kind(InteractionResponseType::UpdateMessage)
|
|
||||||
.interaction_response_data(|m| {
|
|
||||||
cur -= 1;
|
|
||||||
m.create_embed(|mut e| make_embed!(e, cur, groups[cur - 1]))
|
|
||||||
.components(|c| {
|
|
||||||
make_terminal_components!(
|
|
||||||
c,
|
|
||||||
if cur == 1 { "first" } else { "mid" }
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
"prev" => {
|
||||||
|
if cur != 1 {
|
||||||
|
cur -= 1;
|
||||||
|
let _ = interaction
|
||||||
|
.create_interaction_response(&ctx, |r| {
|
||||||
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
|
.interaction_response_data(|m| {
|
||||||
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components(
|
||||||
|
if cur == 1 { "first" } else { "mid" },
|
||||||
|
groups.len(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"first" => {
|
||||||
|
cur = 1;
|
||||||
|
let _ = interaction
|
||||||
|
.create_interaction_response(&ctx, |r| {
|
||||||
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
|
.interaction_response_data(|m| {
|
||||||
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components("first", groups.len()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
"last" => {
|
||||||
|
cur = groups.len();
|
||||||
|
let _ = interaction
|
||||||
|
.create_interaction_response(&ctx, |r| {
|
||||||
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
|
.interaction_response_data(|m| {
|
||||||
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components("last", groups.len()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
"delete" => {
|
||||||
|
message.delete(ctx).await?;
|
||||||
|
msg.delete(ctx).await?;
|
||||||
|
}
|
||||||
|
"range" => {
|
||||||
|
cur = interaction.data.values[0].parse().unwrap();
|
||||||
|
let _ = interaction
|
||||||
|
.create_interaction_response(&ctx, |r| {
|
||||||
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
|
.interaction_response_data(|m| {
|
||||||
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components(
|
||||||
|
if cur == 1 {
|
||||||
|
"first"
|
||||||
|
} else if cur == groups.len() {
|
||||||
|
"last"
|
||||||
|
} else {
|
||||||
|
"mid"
|
||||||
|
},
|
||||||
|
groups.len(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@@ -1,9 +1,6 @@
|
|||||||
use serenity::prelude::*;
|
use serenity::framework::standard::{macros::command, CommandResult};
|
||||||
use serenity::model::prelude::*;
|
use serenity::model::prelude::*;
|
||||||
use serenity::framework::standard::{
|
use serenity::prelude::*;
|
||||||
CommandResult,
|
|
||||||
macros::command
|
|
||||||
};
|
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
pub async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
|
pub async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
pub mod general;
|
|
||||||
pub mod count;
|
pub mod count;
|
||||||
|
pub mod general;
|
||||||
pub mod minigames;
|
pub mod minigames;
|
||||||
|
pub mod tags;
|
||||||
|
394
src/commands/tags.rs
Normal file
394
src/commands/tags.rs
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
use crate::lib::{components::make_terminal_components, messages::ExtractInfo};
|
||||||
|
use core::time::Duration;
|
||||||
|
use serenity::{
|
||||||
|
builder::CreateEmbed,
|
||||||
|
collector::component_interaction_collector::ComponentInteractionCollectorBuilder,
|
||||||
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
|
futures::StreamExt,
|
||||||
|
model::{interactions::InteractionResponseType, prelude::*},
|
||||||
|
prelude::*,
|
||||||
|
utils::Colour,
|
||||||
|
};
|
||||||
|
use tokio_postgres::Row;
|
||||||
|
|
||||||
|
const GUILD_ID: u64 = 874699899067838535;
|
||||||
|
const ROLE_ID: u64 = 957155053184102400;
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
#[aliases("t")]
|
||||||
|
pub async fn tag(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
|
let query: String = args.raw().collect::<Vec<&str>>().join("");
|
||||||
|
if query == "" {
|
||||||
|
msg.reply(ctx, "Mention the tag retard").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
let db = data_read
|
||||||
|
.get::<crate::Database>()
|
||||||
|
.expect("Expected Database in TypeMap.")
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let query_helper = db
|
||||||
|
.query("SELECT name, value FROM tags WHERE name=$1", &[&query])
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if query_helper.is_empty() {
|
||||||
|
const DIST_LIMIT: i32 = 2;
|
||||||
|
let leven = db
|
||||||
|
.query(
|
||||||
|
"SELECT name, levenshtein_less_equal(name, $1, $2) AS lev FROM tags ORDER BY lev LIMIT 1 ",
|
||||||
|
&[&query, &DIST_LIMIT],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let dist: i32 = leven[0].get(1);
|
||||||
|
|
||||||
|
let l = if dist > DIST_LIMIT {
|
||||||
|
"".to_string()
|
||||||
|
} else {
|
||||||
|
let leven_name: String = leven[0].get(0);
|
||||||
|
format!("\nDid you mean `{}`?", leven_name)
|
||||||
|
};
|
||||||
|
|
||||||
|
msg.reply(
|
||||||
|
ctx,
|
||||||
|
format!(
|
||||||
|
"No entry for '{}' found. If you want to add it, run `,tadd {} <value>`{}",
|
||||||
|
query, query, l
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let value: String = query_helper[0].get(1);
|
||||||
|
msg.reply(ctx, value).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
pub async fn tadd(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
|
let tag_value = msg.extract_text(2, true);
|
||||||
|
|
||||||
|
if tag_value.is_none() {
|
||||||
|
msg.reply(
|
||||||
|
ctx,
|
||||||
|
"Please use the proper syntax: `,tadd <name> <value>` or attach something",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let tag_name = args.single::<String>().unwrap();
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
let db = data_read
|
||||||
|
.get::<crate::Database>()
|
||||||
|
.expect("Expected Database in TypeMap.")
|
||||||
|
.clone();
|
||||||
|
let check_existense = db
|
||||||
|
.query("SELECT name FROM tags WHERE name=$1", &[&tag_name])
|
||||||
|
.await?;
|
||||||
|
if check_existense.len() != 0 {
|
||||||
|
msg.reply(ctx, format!("This tag already exists")).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
db.execute(
|
||||||
|
"INSERT INTO tags(name, value, owner) VALUES($1, $2, $3)",
|
||||||
|
&[&tag_name, &tag_value, &msg.author.id.to_string()],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
msg.reply(ctx, "Added").await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
#[aliases("tcp")]
|
||||||
|
pub async fn tcopy(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
|
let queries: Vec<&str> = args.raw().collect::<Vec<&str>>();
|
||||||
|
if queries.len() != 2 {
|
||||||
|
msg.reply(
|
||||||
|
ctx,
|
||||||
|
"Please use the proper syntax: `,tcopy <original> <new>`",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
let db = data_read
|
||||||
|
.get::<crate::Database>()
|
||||||
|
.expect("Expected Database in TypeMap.")
|
||||||
|
.clone();
|
||||||
|
let check_existense = db
|
||||||
|
.query("SELECT name FROM tags WHERE name=$1", &[&queries[0]])
|
||||||
|
.await?;
|
||||||
|
if check_existense.len() == 0 {
|
||||||
|
msg.reply(ctx, format!("This tag does not exist")).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
db.execute(
|
||||||
|
"INSERT INTO tags(name, value, owner) SELECT $1, value, $2 FROM tags WHERE name=$3",
|
||||||
|
&[&queries[1], &msg.author.id.to_string(), &queries[0]],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
msg.reply(ctx, format!("Copied {} to {}", queries[0], queries[1]))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
#[aliases("trm")]
|
||||||
|
pub async fn tremove(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
|
let query: String = args.raw().collect::<Vec<&str>>().join(" ");
|
||||||
|
if query == "" {
|
||||||
|
msg.reply(ctx, "remove what?").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
let db = data_read
|
||||||
|
.get::<crate::Database>()
|
||||||
|
.expect("Expected Database in TypeMap.")
|
||||||
|
.clone();
|
||||||
|
let owner = db
|
||||||
|
.query("SELECT owner FROM tags WHERE name=$1", &[&query])
|
||||||
|
.await?;
|
||||||
|
if owner.len() == 1 {
|
||||||
|
let owner_id: String = owner[0].get(0);
|
||||||
|
if owner_id != msg.author.id.to_string()
|
||||||
|
&& !msg.author.has_role(&ctx.http, GUILD_ID, ROLE_ID).await?
|
||||||
|
{
|
||||||
|
msg.reply(ctx, "You don't even own this tag").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
db.execute("DELETE FROM tags WHERE name=$1", &[&query])
|
||||||
|
.await?;
|
||||||
|
msg.reply(ctx, format!("Deleted {} if it existed", query))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
pub async fn tedit(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
|
let tag_value = msg.extract_text(2, true);
|
||||||
|
|
||||||
|
if tag_value.is_none() {
|
||||||
|
msg.reply(
|
||||||
|
ctx,
|
||||||
|
"Please use the proper syntax: `,tadd <name> <value>` or attach something",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let tag_name = args.single::<String>().unwrap();
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
let db = data_read
|
||||||
|
.get::<crate::Database>()
|
||||||
|
.expect("Expected Database in TypeMap.")
|
||||||
|
.clone();
|
||||||
|
let owner = db
|
||||||
|
.query("SELECT owner FROM tags WHERE name=$1", &[&tag_name])
|
||||||
|
.await?;
|
||||||
|
if owner.len() == 1 {
|
||||||
|
let owner_id: String = owner[0].get(0);
|
||||||
|
if owner_id != msg.author.id.to_string()
|
||||||
|
&& !msg.author.has_role(&ctx.http, GUILD_ID, ROLE_ID).await?
|
||||||
|
{
|
||||||
|
msg.reply(ctx, "You don't even own this tag").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
db.execute(
|
||||||
|
"UPDATE tags SET value=$1 WHERE name=$2",
|
||||||
|
&[&tag_value, &tag_name],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
msg.reply(ctx, "Changed the value if it existed").await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_list_embed(cur: usize, group: &[Row]) -> CreateEmbed {
|
||||||
|
let mut e = CreateEmbed::default();
|
||||||
|
e.title(format!("List of tags: Page {}", cur))
|
||||||
|
.color(Colour::FABLED_PINK);
|
||||||
|
for row in group {
|
||||||
|
let idx: i64 = row.get(0);
|
||||||
|
let name: String = row.get(1);
|
||||||
|
let owner_id: String = row.get(2);
|
||||||
|
e.field(
|
||||||
|
format!("{}. {}", idx, name),
|
||||||
|
format!(" by <@{}>", owner_id),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
e
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
#[aliases("tls")]
|
||||||
|
pub async fn tlist(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
|
let size = if args.len() > 0 {
|
||||||
|
args.single::<usize>()?
|
||||||
|
} else {
|
||||||
|
5usize
|
||||||
|
};
|
||||||
|
|
||||||
|
if size > 15 {
|
||||||
|
msg.reply(ctx, "Please input a number less than 15").await?;
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
let db = data_read
|
||||||
|
.get::<crate::Database>()
|
||||||
|
.expect("Expected Database in TypeMap.")
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let rows = db
|
||||||
|
.query(
|
||||||
|
"SELECT ROW_NUMBER() OVER (ORDER BY id), name, owner FROM tags",
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if rows.is_empty() {
|
||||||
|
msg.reply(ctx, "No tags stored").await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let groups: Vec<&[Row]> = rows.chunks(size).collect();
|
||||||
|
let mut cur = 1;
|
||||||
|
let message = msg
|
||||||
|
.channel_id
|
||||||
|
.send_message(ctx, |m| {
|
||||||
|
m.set_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components("first", groups.len()))
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut collector = ComponentInteractionCollectorBuilder::new(&ctx)
|
||||||
|
.timeout(Duration::from_secs(90))
|
||||||
|
.author_id(msg.author.id)
|
||||||
|
.message_id(message.id)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
while let Some(interaction) = collector.next().await {
|
||||||
|
match interaction.data.custom_id.as_ref() {
|
||||||
|
"next" => {
|
||||||
|
if cur != groups.len() {
|
||||||
|
cur += 1;
|
||||||
|
let _ = interaction
|
||||||
|
.create_interaction_response(&ctx, |r| {
|
||||||
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
|
.interaction_response_data(|m| {
|
||||||
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components(
|
||||||
|
if cur == groups.len() { "last" } else { "mid" },
|
||||||
|
groups.len(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"prev" => {
|
||||||
|
if cur != 1 {
|
||||||
|
cur -= 1;
|
||||||
|
let _ = interaction
|
||||||
|
.create_interaction_response(&ctx, |r| {
|
||||||
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
|
.interaction_response_data(|m| {
|
||||||
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components(
|
||||||
|
if cur == 1 { "first" } else { "mid" },
|
||||||
|
groups.len(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"first" => {
|
||||||
|
cur = 1;
|
||||||
|
let _ = interaction
|
||||||
|
.create_interaction_response(&ctx, |r| {
|
||||||
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
|
.interaction_response_data(|m| {
|
||||||
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components("first", groups.len()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
"last" => {
|
||||||
|
cur = groups.len();
|
||||||
|
let _ = interaction
|
||||||
|
.create_interaction_response(&ctx, |r| {
|
||||||
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
|
.interaction_response_data(|m| {
|
||||||
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components("last", groups.len()))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
"delete" => {
|
||||||
|
message.delete(ctx).await?;
|
||||||
|
msg.delete(ctx).await?;
|
||||||
|
}
|
||||||
|
"range" => {
|
||||||
|
cur = interaction.data.values[0].parse().unwrap();
|
||||||
|
let _ = interaction
|
||||||
|
.create_interaction_response(&ctx, |r| {
|
||||||
|
r.kind(InteractionResponseType::UpdateMessage)
|
||||||
|
.interaction_response_data(|m| {
|
||||||
|
m.add_embed(make_list_embed(cur, groups[cur - 1]))
|
||||||
|
.set_components(make_terminal_components(
|
||||||
|
if cur == 1 {
|
||||||
|
"first"
|
||||||
|
} else if cur == groups.len() {
|
||||||
|
"last"
|
||||||
|
} else {
|
||||||
|
"mid"
|
||||||
|
},
|
||||||
|
groups.len(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
#[aliases(trand)]
|
||||||
|
pub async fn trandom(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
let db = data_read
|
||||||
|
.get::<crate::Database>()
|
||||||
|
.expect("Expected Database in TypeMap.")
|
||||||
|
.clone();
|
||||||
|
let rand = db
|
||||||
|
.query(
|
||||||
|
"SELECT name, value, owner FROM tags OFFSET floor(random() * (SELECT COUNT(*) FROM tags)) LIMIT 1",
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let name: String = rand[0].get(0);
|
||||||
|
let value: String = rand[0].get(1);
|
||||||
|
let owner: String = rand[0].get(2);
|
||||||
|
let user_id = UserId::from(owner.parse::<u64>().unwrap());
|
||||||
|
msg.reply(
|
||||||
|
ctx,
|
||||||
|
format!(
|
||||||
|
"{}'s tag {}: \n{}",
|
||||||
|
user_id.to_user(&ctx.http).await?.name,
|
||||||
|
name,
|
||||||
|
value
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@@ -18,46 +18,38 @@ pub async fn count(msg: Message, db: std::sync::Arc<Client>) {
|
|||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.expect("cant create a user table");
|
.expect("Can't create a user table");
|
||||||
|
|
||||||
for row in db
|
for row in db
|
||||||
.query("SELECT name, reg FROM words", &[])
|
.query("SELECT name, reg FROM words", &[])
|
||||||
.await
|
.await
|
||||||
.expect("can't get the words to count")
|
.expect("Can't get the words to count")
|
||||||
{
|
{
|
||||||
let name: &str = row.get(0);
|
let name: &str = row.get(0);
|
||||||
let regex: Regex = Regex::new(row.get(1)).unwrap();
|
let regex: Regex = Regex::new(row.get(1)).unwrap();
|
||||||
let count = regex.captures_iter(&msg.content).count();
|
let count: i32 = regex.captures_iter(&msg.content).count() as i32;
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
let query_result = db
|
let query_result = db
|
||||||
.query(
|
.query(
|
||||||
format!("SELECT count FROM user{} where name='{}'", id, name).as_str(),
|
format!("SELECT count FROM user{} WHERE name=$1", id).as_str(),
|
||||||
&[],
|
&[&name],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.expect("cant select the count");
|
.expect("Can't select count");
|
||||||
if query_result.is_empty() {
|
if query_result.is_empty() {
|
||||||
db.execute(
|
db.execute(
|
||||||
format!(
|
format!("INSERT INTO user{} (name, count) values ($1, 0)", id).as_str(),
|
||||||
"insert into user{} (name, count) values ('{}', 0)",
|
&[&name],
|
||||||
id, name
|
|
||||||
)
|
|
||||||
.as_str(),
|
|
||||||
&[],
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.expect("cant insert shit");
|
.expect("Can't insert count");
|
||||||
}
|
}
|
||||||
db.execute(
|
db.execute(
|
||||||
format!(
|
format!("UPDATE user{} SET count = count + $1 WHERE name=$2", id).as_str(),
|
||||||
"UPDATE user{} SET count = count + {} where name='{}'",
|
&[&count, &name],
|
||||||
id, count, name
|
|
||||||
)
|
|
||||||
.as_str(),
|
|
||||||
&[],
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.expect("cant update");
|
.expect("Can't update count");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,15 +2,7 @@ mod count;
|
|||||||
mod interactions;
|
mod interactions;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
async_trait,
|
async_trait,
|
||||||
model::{
|
model::{channel::Message, event::ResumedEvent, gateway::Ready},
|
||||||
channel::Message,
|
|
||||||
event::ResumedEvent,
|
|
||||||
gateway::Ready,
|
|
||||||
interactions::{
|
|
||||||
ApplicationCommand, Interaction, InteractionData, InteractionResponseType,
|
|
||||||
InteractionType,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
@@ -19,12 +11,8 @@ pub struct Handler;
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventHandler for Handler {
|
impl EventHandler for Handler {
|
||||||
async fn ready(&self, ctx: Context, ready: Ready) {
|
async fn ready(&self, _: Context, ready: Ready) {
|
||||||
info!("{} connected bhay", ready.user.name);
|
println!("{} connected bhay", ready.user.name);
|
||||||
let _ = ApplicationCommand::create_global_application_commands(&ctx.http, |commands| {
|
|
||||||
commands.set_application_commands(interactions::general())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
async fn resume(&self, _: Context, _: ResumedEvent) {
|
async fn resume(&self, _: Context, _: ResumedEvent) {
|
||||||
info!("how th when the");
|
info!("how th when the");
|
||||||
@@ -37,23 +25,4 @@ impl EventHandler for Handler {
|
|||||||
.clone();
|
.clone();
|
||||||
count::count(msg, db_client).await;
|
count::count(msg, db_client).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
|
||||||
if interaction.kind == InteractionType::ApplicationCommand {
|
|
||||||
if let Some(InteractionData::ApplicationCommand(data)) = interaction.data.as_ref() {
|
|
||||||
if let Err(why) = interaction
|
|
||||||
.create_interaction_response(&ctx.http, |response| {
|
|
||||||
response
|
|
||||||
.kind(InteractionResponseType::ChannelMessageWithSource)
|
|
||||||
.interaction_response_data(|message| {
|
|
||||||
interactions::responses(data.name.to_string(), message)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
println!("Cannot respond to slash command: {}", why);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
62
src/lib/components.rs
Normal file
62
src/lib/components.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
use serenity::{
|
||||||
|
builder::{CreateComponents, CreateSelectMenu},
|
||||||
|
model::{channel::ReactionType, interactions::message_component::ButtonStyle},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn make_range_select_menu(first: usize, last: usize) -> CreateSelectMenu {
|
||||||
|
let mut sm = CreateSelectMenu::default();
|
||||||
|
sm.custom_id("range")
|
||||||
|
.placeholder("Page No")
|
||||||
|
.options(|mut os| {
|
||||||
|
for x in first..=last {
|
||||||
|
os = os.create_option(|o| o.label(x).value(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
os
|
||||||
|
});
|
||||||
|
sm
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_terminal_components(terminal: &str, pages: usize) -> CreateComponents {
|
||||||
|
let mut c = CreateComponents::default();
|
||||||
|
c.create_action_row(|ar| {
|
||||||
|
ar.create_button(|b| {
|
||||||
|
b.style(ButtonStyle::Primary)
|
||||||
|
.label("First")
|
||||||
|
.emoji(ReactionType::Unicode("\u{23EA}".to_string()))
|
||||||
|
.custom_id("first")
|
||||||
|
.disabled(terminal == "first")
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.style(ButtonStyle::Primary)
|
||||||
|
.label("Prev")
|
||||||
|
.emoji(ReactionType::Unicode("\u{25C0}".to_string()))
|
||||||
|
.custom_id("prev")
|
||||||
|
.disabled(terminal == "first")
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.style(ButtonStyle::Primary)
|
||||||
|
.label("Next")
|
||||||
|
.emoji(ReactionType::Unicode("\u{25B6}".to_string()))
|
||||||
|
.custom_id("next")
|
||||||
|
.disabled(terminal == "last")
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.style(ButtonStyle::Primary)
|
||||||
|
.label("Last")
|
||||||
|
.emoji(ReactionType::Unicode("\u{23E9}".to_string()))
|
||||||
|
.custom_id("last")
|
||||||
|
.disabled(terminal == "last")
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.style(ButtonStyle::Danger)
|
||||||
|
.label("Delete")
|
||||||
|
.emoji(ReactionType::Unicode("\u{1F5D1}".to_string()))
|
||||||
|
.custom_id("delete")
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if pages <= 25 {
|
||||||
|
c.create_action_row(|ar| ar.add_select_menu(make_range_select_menu(1, pages)));
|
||||||
|
}
|
||||||
|
c
|
||||||
|
}
|
40
src/lib/messages.rs
Normal file
40
src/lib/messages.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
use serenity::model::channel::Message;
|
||||||
|
|
||||||
|
pub trait ExtractInfo {
|
||||||
|
fn extract_text(&self, skip: usize, with_ref: bool) -> Option<String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtractInfo for Message {
|
||||||
|
fn extract_text(&self, skip: usize, with_ref: bool) -> Option<String> {
|
||||||
|
let mut ret: String = String::from("");
|
||||||
|
|
||||||
|
let raw: Vec<&str> = self.content.splitn(skip + 1, " ").collect();
|
||||||
|
if raw.len() == skip + 1 {
|
||||||
|
ret += raw[skip];
|
||||||
|
ret += "\n";
|
||||||
|
} else if raw.len() < skip {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += &self
|
||||||
|
.attachments
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.url.clone())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
if let Some(msg) = &self.referenced_message {
|
||||||
|
let ref_text = msg.extract_text(0, false);
|
||||||
|
if with_ref && !ref_text.is_none() {
|
||||||
|
ret += "\n";
|
||||||
|
ret += &ref_text.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret.is_empty() {
|
||||||
|
return None;
|
||||||
|
} else {
|
||||||
|
return Some(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
src/lib/mod.rs
Normal file
2
src/lib/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod components;
|
||||||
|
pub mod messages;
|
10
src/main.rs
10
src/main.rs
@@ -1,8 +1,10 @@
|
|||||||
mod commands;
|
mod commands;
|
||||||
mod handler;
|
mod handler;
|
||||||
|
mod lib;
|
||||||
use commands::count::*;
|
use commands::count::*;
|
||||||
use commands::general::*;
|
use commands::general::*;
|
||||||
use commands::minigames::*;
|
use commands::minigames::*;
|
||||||
|
use commands::tags::*;
|
||||||
use handler::Handler;
|
use handler::Handler;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
client::bridge::gateway::ShardManager,
|
client::bridge::gateway::ShardManager,
|
||||||
@@ -36,10 +38,13 @@ impl TypeMapKey for Database {
|
|||||||
struct General;
|
struct General;
|
||||||
|
|
||||||
#[group]
|
#[group]
|
||||||
#[prefix = "count"]
|
#[commands(count, cadd, cremove, cedit, clist)]
|
||||||
#[commands(kitna, add, rm, change, ls)]
|
|
||||||
struct Count;
|
struct Count;
|
||||||
|
|
||||||
|
#[group]
|
||||||
|
#[commands(tag, tadd, tcopy, tremove, tedit, tlist, trandom)]
|
||||||
|
pub struct Tags;
|
||||||
|
|
||||||
#[group]
|
#[group]
|
||||||
#[commands(challenge)]
|
#[commands(challenge)]
|
||||||
struct Minigames;
|
struct Minigames;
|
||||||
@@ -82,6 +87,7 @@ async fn main() {
|
|||||||
.help(&MY_HELP)
|
.help(&MY_HELP)
|
||||||
.group(&GENERAL_GROUP)
|
.group(&GENERAL_GROUP)
|
||||||
.group(&COUNT_GROUP)
|
.group(&COUNT_GROUP)
|
||||||
|
.group(&TAGS_GROUP)
|
||||||
.group(&MINIGAMES_GROUP);
|
.group(&MINIGAMES_GROUP);
|
||||||
|
|
||||||
let mut client = Client::builder(&token)
|
let mut client = Client::builder(&token)
|
||||||
|
Reference in New Issue
Block a user