Compare commits
No commits in common. "master" and "cpp" have entirely different histories.
@ -1,5 +0,0 @@
|
|||||||
[registry]
|
|
||||||
default = "crates-io"
|
|
||||||
|
|
||||||
[registries.elnafo-vcs]
|
|
||||||
index = "sparse+https://vcs.elnafo.ru/api/packages/L-Nafaryus/cargo/"
|
|
5
.clang-format
Normal file
5
.clang-format
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
---
|
||||||
|
Language: Cpp
|
6
.containerignore
Normal file
6
.containerignore
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
**
|
||||||
|
!lib/**
|
||||||
|
!CMakeLists.txt
|
||||||
|
!main.cc
|
||||||
|
!include.hh
|
||||||
|
!extern.cc
|
@ -1,23 +0,0 @@
|
|||||||
name: nix-build-publish
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check:
|
|
||||||
runs-on: nix-runner
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: |
|
|
||||||
NIXPKGS_ALLOW_BROKEN=1 nix flake check --allow-import-from-derivation --keep-going --impure
|
|
||||||
build:
|
|
||||||
runs-on: nix-runner
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: cachix/cachix-action@v14
|
|
||||||
with:
|
|
||||||
name: bonfire
|
|
||||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
|
||||||
- run: nix build -L
|
|
123
.gitignore
vendored
123
.gitignore
vendored
@ -1,5 +1,118 @@
|
|||||||
/result
|
build*/
|
||||||
/target
|
.floo
|
||||||
Secrets*.toml
|
token.dat
|
||||||
/temp
|
cmake-build-*/
|
||||||
.tmp
|
scratch.txt
|
||||||
|
env
|
||||||
|
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/jetbrains+all
|
||||||
|
|
||||||
|
### JetBrains+all ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff:
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/dictionaries
|
||||||
|
|
||||||
|
# Sensitive or high-churn files:
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.xml
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
|
||||||
|
# Gradle:
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-debug/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin:
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
## File-based project format:
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
## Plugin-specific files:
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
### JetBrains+all Patch ###
|
||||||
|
# Ignores the whole idea folder
|
||||||
|
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/jetbrains+all
|
||||||
|
|
||||||
|
# Created by https://www.gitignore.io/api/visualstudiocode
|
||||||
|
# Edit at https://www.gitignore.io/?templates=visualstudiocode
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
### VisualStudioCode Patch ###
|
||||||
|
# Ignore all local history of files
|
||||||
|
.history
|
||||||
|
|
||||||
|
# End of https://www.gitignore.io/api/visualstudiocode
|
||||||
|
|
||||||
|
*.log
|
||||||
|
59
CMakeLists.txt
Normal file
59
CMakeLists.txt
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(discord-oscuro LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic")
|
||||||
|
|
||||||
|
include(cmake/macros.cmake)
|
||||||
|
include(cmake/CPM.cmake)
|
||||||
|
|
||||||
|
CPMAddPackage("gh:DiscordPP/discordpp#daf04ea")
|
||||||
|
CPMAddPackage("gh:DiscordPP/rest-simpleweb#4cf911b")
|
||||||
|
CPMAddPackage("gh:DiscordPP/websocket-simpleweb#9082991")
|
||||||
|
CPMAddPackage("gh:DiscordPP/plugin-native#238b7e8")
|
||||||
|
CPMAddPackage("gh:DiscordPP/plugin-overload#8862ac5")
|
||||||
|
CPMAddPackage("gh:DiscordPP/plugin-responder#3c2c485")
|
||||||
|
CPMAddPackage("gh:DiscordPP/plugin-interactionhandler#df07fd3")
|
||||||
|
CPMAddPackage("gh:DiscordPP/plugin-ratelimit#2c8cb34")
|
||||||
|
CPMAddPackage("gh:libcpr/cpr#1.10.4")
|
||||||
|
|
||||||
|
set(DISCORDPP_USE_BOOST OFF CACHE BOOL "Override option" FORCE)
|
||||||
|
|
||||||
|
CREATE_DISCORDPP_DEFINITIONS()
|
||||||
|
CREATE_DISCORDPP_INCLUDE()
|
||||||
|
|
||||||
|
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
|
||||||
|
if(${DISCORDPP_USE_BOOST})
|
||||||
|
find_package(Boost 1.71.0 REQUIRED system date_time)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME}
|
||||||
|
source/main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
#target_precompile_headers(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/source/main.hpp)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
${Boost_LIBRARIES}
|
||||||
|
Threads::Threads
|
||||||
|
${OPENSSL_LIBRARIES}
|
||||||
|
discordpp
|
||||||
|
discordpp-rest-simpleweb
|
||||||
|
discordpp-websocket-simpleweb
|
||||||
|
discordpp-plugin-native
|
||||||
|
discordpp-plugin-overload
|
||||||
|
discordpp-plugin-responder
|
||||||
|
discordpp-plugin-interactionhandler
|
||||||
|
discordpp-plugin-ratelimit
|
||||||
|
cpr::cpr
|
||||||
|
)
|
||||||
|
|
||||||
|
copy_file("env")
|
||||||
|
|
2881
Cargo.lock
generated
2881
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
24
Cargo.toml
24
Cargo.toml
@ -1,24 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "oscuro"
|
|
||||||
version = "0.1.1"
|
|
||||||
edition = "2021"
|
|
||||||
description = "Oscuro is a fancy multibot"
|
|
||||||
license = "MIT"
|
|
||||||
repository = "https://vcs.elnafo.ru/L-Nafaryus/oscuro"
|
|
||||||
publish = ["vcs-elnafo"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
async-process = "2.2.3"
|
|
||||||
poise = "0.6.1"
|
|
||||||
rand = "0.8.5"
|
|
||||||
serde = { version = "1.0.204", features = ["derive"] }
|
|
||||||
serde_json = "1.0.120"
|
|
||||||
teloxide = { version = "0.12.2", features = ["macros"] }
|
|
||||||
tokio = { version = "1.26.0", features = ["macros", "rt-multi-thread"] }
|
|
||||||
toml = "0.8.15"
|
|
||||||
tracing = "0.1.40"
|
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
|
||||||
|
|
||||||
[workspace]
|
|
||||||
resolver = "2"
|
|
||||||
members = []
|
|
29
Containerfile
Normal file
29
Containerfile
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
FROM alpine:latest AS build
|
||||||
|
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
build-base \
|
||||||
|
cmake \
|
||||||
|
samurai \
|
||||||
|
boost-dev \
|
||||||
|
git \
|
||||||
|
openssl-dev
|
||||||
|
|
||||||
|
WORKDIR /echo_bot
|
||||||
|
COPY . .
|
||||||
|
RUN cmake -B build -G Ninja .
|
||||||
|
RUN cmake --build build
|
||||||
|
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
libgcc \
|
||||||
|
libstdc++ \
|
||||||
|
libc6-compat \
|
||||||
|
openssl-dev
|
||||||
|
|
||||||
|
WORKDIR /echo_bot
|
||||||
|
COPY --from=build /echo_bot/build/echo_bot .
|
||||||
|
CMD source /run/secrets/discord-oscuro-env; ./echo_bot
|
35
LICENSE
35
LICENSE
@ -1,22 +1,21 @@
|
|||||||
The MIT License (MIT)
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2023-2024 George Kusayko [L-Nafaryus] <l.nafaryus@gmail.com>
|
Copyright (c) 2023 George Kusayko <L-Nafaryus>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
a copy of this software and associated documentation files (the
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
"Software"), to deal in the Software without restriction, including
|
in the Software without restriction, including without limitation the rights
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
furnished to do so, subject to the following conditions:
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
The above copyright notice and this permission notice shall be included in all
|
||||||
included in all copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
SOFTWARE.
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
# Oscuro - Discord Bot
|
# Oscuro - Discord Bot (c++)
|
||||||
|
|
||||||
|
## Note
|
||||||
|
- Create `env` file:
|
||||||
|
```sh
|
||||||
|
export BOT_TOKEN="Bot ....."
|
||||||
|
```
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
|
23
cmake/CPM.cmake
Normal file
23
cmake/CPM.cmake
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
set(CPM_DOWNLOAD_VERSION 0.38.1)
|
||||||
|
|
||||||
|
if(CPM_SOURCE_CACHE)
|
||||||
|
# Expand relative path. This is important if the provided path contains a tilde (~)
|
||||||
|
get_filename_component(CPM_SOURCE_CACHE ${CPM_SOURCE_CACHE} ABSOLUTE)
|
||||||
|
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||||
|
|
||||||
|
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
|
||||||
|
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||||
|
|
||||||
|
else()
|
||||||
|
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION}))
|
||||||
|
message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}")
|
||||||
|
file(DOWNLOAD
|
||||||
|
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
|
||||||
|
${CPM_DOWNLOAD_LOCATION}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(${CPM_DOWNLOAD_LOCATION})
|
8
cmake/macros.cmake
Normal file
8
cmake/macros.cmake
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
function(copy_file FILE)
|
||||||
|
if (EXISTS ${CMAKE_SOURCE_DIR}/${FILE})
|
||||||
|
configure_file(${FILE} ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)
|
||||||
|
elseif (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${FILE})
|
||||||
|
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/${FILE})
|
||||||
|
endif ()
|
||||||
|
endfunction()
|
535
flake.lock
535
flake.lock
@ -1,535 +0,0 @@
|
|||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"ags": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721306136,
|
|
||||||
"narHash": "sha256-VKPsIGf3/a+RONBipx4lEE4LXG2sdMNkWQu22LNQItg=",
|
|
||||||
"owner": "Aylur",
|
|
||||||
"repo": "ags",
|
|
||||||
"rev": "344ea72cd3b8d4911f362fec34bce7d8fb37028c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "Aylur",
|
|
||||||
"repo": "ags",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"blobs": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1604995301,
|
|
||||||
"narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=",
|
|
||||||
"owner": "simple-nixos-mailserver",
|
|
||||||
"repo": "blobs",
|
|
||||||
"rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265",
|
|
||||||
"type": "gitlab"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "simple-nixos-mailserver",
|
|
||||||
"repo": "blobs",
|
|
||||||
"type": "gitlab"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"bonfire": {
|
|
||||||
"inputs": {
|
|
||||||
"ags": "ags",
|
|
||||||
"catppuccin": "catppuccin",
|
|
||||||
"crane": "crane",
|
|
||||||
"fenix": "fenix",
|
|
||||||
"home-manager": "home-manager",
|
|
||||||
"nixos-mailserver": "nixos-mailserver",
|
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"nixvim": "nixvim",
|
|
||||||
"obs-image-reaction": "obs-image-reaction",
|
|
||||||
"oscuro": [],
|
|
||||||
"sops-nix": "sops-nix",
|
|
||||||
"wezterm": "wezterm"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1723204928,
|
|
||||||
"narHash": "sha256-r6oYWnHf5H9+5n80QocRTRwpZxsDK+BEq2Hg9QS4pxo=",
|
|
||||||
"owner": "L-Nafaryus",
|
|
||||||
"repo": "bonfire",
|
|
||||||
"rev": "bb7c9204f5070d47334da89adf611e5fda8a3f41",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "L-Nafaryus",
|
|
||||||
"repo": "bonfire",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"catppuccin": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1720472194,
|
|
||||||
"narHash": "sha256-CYscFEts6tyvosc1T29nxhzIYJAj/1CCEkV3ZMzSN/c=",
|
|
||||||
"owner": "catppuccin",
|
|
||||||
"repo": "nix",
|
|
||||||
"rev": "d75d5803852fb0833767dc969a4581ac13204e22",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "catppuccin",
|
|
||||||
"repo": "nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"crane": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721322122,
|
|
||||||
"narHash": "sha256-a0G1NvyXGzdwgu6e1HQpmK5R5yLsfxeBe07nNDyYd+g=",
|
|
||||||
"owner": "ipetkov",
|
|
||||||
"repo": "crane",
|
|
||||||
"rev": "8a68b987c476a33e90f203f0927614a75c3f47ea",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "ipetkov",
|
|
||||||
"repo": "crane",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fenix": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"rust-analyzer-src": [
|
|
||||||
"bonfire"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721629802,
|
|
||||||
"narHash": "sha256-GKlvM9M0mkKJrL6N1eMG4DrROO25Ds1apFw3/b8594w=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "fenix",
|
|
||||||
"rev": "1270fb024c6987dd825a20cd27319384a8d8569e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "fenix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-compat": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1696426674,
|
|
||||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "edolstra",
|
|
||||||
"repo": "flake-compat",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-parts": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs-lib": [
|
|
||||||
"bonfire",
|
|
||||||
"nixvim",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1719994518,
|
|
||||||
"narHash": "sha256-pQMhCCHyQGRzdfAkdJ4cIWiw+JNuWsTX7f0ZYSyz0VY=",
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "flake-parts",
|
|
||||||
"rev": "9227223f6d922fee3c7b190b2cc238a99527bbb7",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "hercules-ci",
|
|
||||||
"repo": "flake-parts",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1710146030,
|
|
||||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"freetype2": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1687587065,
|
|
||||||
"narHash": "sha256-+Fh+/k+NWL5Ow9sDLtp8Cv/8rLNA1oByQQCIQS/bysY=",
|
|
||||||
"owner": "wez",
|
|
||||||
"repo": "freetype2",
|
|
||||||
"rev": "e4586d960f339cf75e2e0b34aee30a0ed8353c0d",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "wez",
|
|
||||||
"repo": "freetype2",
|
|
||||||
"rev": "e4586d960f339cf75e2e0b34aee30a0ed8353c0d",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"harfbuzz": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1711722720,
|
|
||||||
"narHash": "sha256-GdxcAPx5QyniSHPAN1ih28AD9JLUPR0ItqW9JEsl3pU=",
|
|
||||||
"owner": "harfbuzz",
|
|
||||||
"repo": "harfbuzz",
|
|
||||||
"rev": "63973005bc07aba599b47fdd4cf788647b601ccd",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "harfbuzz",
|
|
||||||
"ref": "8.4.0",
|
|
||||||
"repo": "harfbuzz",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"home-manager": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721534365,
|
|
||||||
"narHash": "sha256-XpZOkaSJKdOsz1wU6JfO59Rx2fqtcarQ0y6ndIOKNpI=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "home-manager",
|
|
||||||
"rev": "635563f245309ef5320f80c7ebcb89b2398d2949",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "home-manager",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"libpng": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1549245649,
|
|
||||||
"narHash": "sha256-1+cRp0Ungme/OGfc9kGJbklYIWAFxk8Il1M+NV4KSgw=",
|
|
||||||
"owner": "glennrp",
|
|
||||||
"repo": "libpng",
|
|
||||||
"rev": "8439534daa1d3a5705ba92e653eda9251246dd61",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "glennrp",
|
|
||||||
"repo": "libpng",
|
|
||||||
"rev": "8439534daa1d3a5705ba92e653eda9251246dd61",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixos-mailserver": {
|
|
||||||
"inputs": {
|
|
||||||
"blobs": "blobs",
|
|
||||||
"flake-compat": "flake-compat",
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-24_05": "nixpkgs-24_05"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721121314,
|
|
||||||
"narHash": "sha256-zwc7YXga/1ppaZMWFreZykXtFwBgXodxUZiUx969r+g=",
|
|
||||||
"owner": "simple-nixos-mailserver",
|
|
||||||
"repo": "nixos-mailserver",
|
|
||||||
"rev": "059b50b2e729729ea00c6831124d3837c494f3d5",
|
|
||||||
"type": "gitlab"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "simple-nixos-mailserver",
|
|
||||||
"repo": "nixos-mailserver",
|
|
||||||
"type": "gitlab"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721379653,
|
|
||||||
"narHash": "sha256-8MUgifkJ7lkZs3u99UDZMB4kbOxvMEXQZ31FO3SopZ0=",
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "1d9c2c9b3e71b9ee663d11c5d298727dace8d374",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-24_05": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1717144377,
|
|
||||||
"narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "805a384895c696f802a9bf5bf4720f37385df547",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nixpkgs",
|
|
||||||
"ref": "nixos-24.05",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-stable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721524707,
|
|
||||||
"narHash": "sha256-5NctRsoE54N86nWd0psae70YSLfrOek3Kv1e8KoXe/0=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "556533a23879fc7e5f98dd2e0b31a6911a213171",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "release-24.05",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1719223410,
|
|
||||||
"narHash": "sha256-jtIo8xR0Zp4SalIwmD+OdCwHF4l7OU6PD63UUK4ckt4=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "efb39c6052f3ce51587cf19733f5f4e5d515aa13",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixpkgs-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixvim": {
|
|
||||||
"inputs": {
|
|
||||||
"devshell": [
|
|
||||||
"bonfire"
|
|
||||||
],
|
|
||||||
"flake-compat": [
|
|
||||||
"bonfire"
|
|
||||||
],
|
|
||||||
"flake-parts": "flake-parts",
|
|
||||||
"git-hooks": [
|
|
||||||
"bonfire"
|
|
||||||
],
|
|
||||||
"home-manager": [
|
|
||||||
"bonfire"
|
|
||||||
],
|
|
||||||
"nix-darwin": [
|
|
||||||
"bonfire"
|
|
||||||
],
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"treefmt-nix": [
|
|
||||||
"bonfire"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721772245,
|
|
||||||
"narHash": "sha256-//9p3Qm8gLbPUTsSGN2EMYkDwE5Sqq9B9P2X/z2+npw=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixvim",
|
|
||||||
"rev": "ab67ee7e8b33e788fc53d26dc6f423f9358e3e66",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "nixvim",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"obs-image-reaction": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs_2"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1719314544,
|
|
||||||
"narHash": "sha256-GZa3+2OELKp/9b2+EwwzaIMNvR9niCy/YZ5OERhG9Hg=",
|
|
||||||
"owner": "L-Nafaryus",
|
|
||||||
"repo": "obs-image-reaction",
|
|
||||||
"rev": "0dcb3c27de5782dfdf95cb047ccceb3e65360e6b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "L-Nafaryus",
|
|
||||||
"repo": "obs-image-reaction",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"bonfire": "bonfire",
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rust-overlay": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"wezterm",
|
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721441897,
|
|
||||||
"narHash": "sha256-gYGX9/22tPNeF7dR6bWN5rsrpU4d06GnQNNgZ6ZiXz0=",
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"rev": "b7996075da11a2d441cfbf4e77c2939ce51506fd",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "oxalica",
|
|
||||||
"repo": "rust-overlay",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sops-nix": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"nixpkgs-stable": "nixpkgs-stable"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1721531171,
|
|
||||||
"narHash": "sha256-AsvPw7T0tBLb53xZGcUC3YPqlIpdxoSx56u8vPCr6gU=",
|
|
||||||
"owner": "Mic92",
|
|
||||||
"repo": "sops-nix",
|
|
||||||
"rev": "909e8cfb60d83321d85c8d17209d733658a21c95",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "Mic92",
|
|
||||||
"repo": "sops-nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1689347949,
|
|
||||||
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default-linux",
|
|
||||||
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default-linux",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wezterm": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"freetype2": "freetype2",
|
|
||||||
"harfbuzz": "harfbuzz",
|
|
||||||
"libpng": "libpng",
|
|
||||||
"nixpkgs": [
|
|
||||||
"bonfire",
|
|
||||||
"nixpkgs"
|
|
||||||
],
|
|
||||||
"rust-overlay": "rust-overlay",
|
|
||||||
"zlib": "zlib"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"dir": "nix",
|
|
||||||
"lastModified": 1722353247,
|
|
||||||
"narHash": "sha256-pPH+IJ8pljR+PmeOdckoHvbQVfSBdStKbgXcaqdkTRk=",
|
|
||||||
"owner": "wez",
|
|
||||||
"repo": "wezterm",
|
|
||||||
"rev": "56a27e93a9ee50aab50ff4d78308f9b3154b5122",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"dir": "nix",
|
|
||||||
"owner": "wez",
|
|
||||||
"repo": "wezterm",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zlib": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1484501380,
|
|
||||||
"narHash": "sha256-j5b6aki1ztrzfCqu8y729sPar8GpyQWIrajdzpJC+ww=",
|
|
||||||
"owner": "madler",
|
|
||||||
"repo": "zlib",
|
|
||||||
"rev": "cacf7f1d4e3d44d871b605da3b647f07d718623f",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "madler",
|
|
||||||
"ref": "v1.2.11",
|
|
||||||
"repo": "zlib",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
191
flake.nix
191
flake.nix
@ -1,191 +0,0 @@
|
|||||||
{
|
|
||||||
description = "Oscuro is a fancy multibot";
|
|
||||||
|
|
||||||
nixConfig = {
|
|
||||||
extra-substituters = [
|
|
||||||
"https://cache.elnafo.ru"
|
|
||||||
"https://bonfire.cachix.org"
|
|
||||||
];
|
|
||||||
extra-trusted-public-keys = [
|
|
||||||
"cache.elnafo.ru:j3VD+Hn+is2Qk3lPXDSdPwHJQSatizk7V82iJ2RP1yo="
|
|
||||||
"bonfire.cachix.org-1:mzAGBy/Crdf8NhKail5ciK7ZrGRbPJJobW6TwFb7WYM="
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
inputs = {
|
|
||||||
bonfire = {
|
|
||||||
url = "github:L-Nafaryus/bonfire";
|
|
||||||
inputs = {
|
|
||||||
oscuro.follows = "";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
nixpkgs.follows = "bonfire/nixpkgs";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = {
|
|
||||||
self,
|
|
||||||
nixpkgs,
|
|
||||||
bonfire,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
|
||||||
lib = pkgs.lib;
|
|
||||||
fenixPkgs = bonfire.inputs.fenix.packages.x86_64-linux;
|
|
||||||
craneLib = (bonfire.inputs.crane.mkLib pkgs).overrideToolchain fenixPkgs.complete.toolchain;
|
|
||||||
in {
|
|
||||||
packages.x86_64-linux = rec {
|
|
||||||
oscuro = let
|
|
||||||
common = {
|
|
||||||
src = pkgs.lib.cleanSourceWith {
|
|
||||||
src = ./.;
|
|
||||||
filter = path: type: (craneLib.filterCargoSources path type);
|
|
||||||
};
|
|
||||||
|
|
||||||
strictDeps = true;
|
|
||||||
|
|
||||||
nativeBuildInputs = [pkgs.pkg-config pkgs.makeWrapper];
|
|
||||||
|
|
||||||
buildInputs = [pkgs.openssl];
|
|
||||||
};
|
|
||||||
|
|
||||||
cargoArtifacts = craneLib.buildDepsOnly common;
|
|
||||||
in
|
|
||||||
craneLib.buildPackage (common
|
|
||||||
// rec {
|
|
||||||
pname = "oscuro";
|
|
||||||
version = "0.1.0";
|
|
||||||
inherit cargoArtifacts;
|
|
||||||
postInstall = ''
|
|
||||||
wrapProgram $out/bin/${pname} \
|
|
||||||
--prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath common.buildInputs} \
|
|
||||||
'';
|
|
||||||
});
|
|
||||||
|
|
||||||
default = oscuro;
|
|
||||||
};
|
|
||||||
|
|
||||||
hydraJobs = {
|
|
||||||
packages = self.packages;
|
|
||||||
};
|
|
||||||
|
|
||||||
devShells.x86_64-linux.default = pkgs.mkShell {
|
|
||||||
nativeBuildInputs = [pkgs.pkg-config];
|
|
||||||
buildInputs = [
|
|
||||||
fenixPkgs.complete.toolchain
|
|
||||||
pkgs.cargo-release
|
|
||||||
pkgs.openssl
|
|
||||||
];
|
|
||||||
LD_LIBRARY_PATH = lib.makeLibraryPath [pkgs.openssl];
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosModules = rec {
|
|
||||||
oscuro = {
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
with lib; let
|
|
||||||
cfg = config.services.oscuro;
|
|
||||||
opt = options.services.oscuro;
|
|
||||||
pkg = self.packages.${pkgs.system}.oscuro;
|
|
||||||
configFile = pkgs.writeText "config.toml" ''
|
|
||||||
discord_token = "#discord_token#"
|
|
||||||
'';
|
|
||||||
in {
|
|
||||||
options.services.oscuro = {
|
|
||||||
enable = mkEnableOption "Enables the Oscuro bot";
|
|
||||||
|
|
||||||
package = mkPackageOption pkgs "oscuro" {};
|
|
||||||
|
|
||||||
dataDir = mkOption {
|
|
||||||
type = types.path;
|
|
||||||
default = "/var/lib/oscuro";
|
|
||||||
description = lib.mdDoc "Directory to store Oscuro files";
|
|
||||||
};
|
|
||||||
|
|
||||||
discordToken = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
example = "Bot TOKENTOKENTOKEN";
|
|
||||||
};
|
|
||||||
|
|
||||||
discordTokenFile = mkOption {
|
|
||||||
type = types.nullOr types.str;
|
|
||||||
default = null;
|
|
||||||
example = "/var/lib/secrets/oscuro/discord_token";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
assertions = [
|
|
||||||
{
|
|
||||||
assertion = cfg.discordToken != null || cfg.discordTokenFile != null;
|
|
||||||
message = "Discord token must be set. Use `services.oscuro.discordToken` or `services.oscuro.discordTokenFile`.";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
users.users.oscuro = {
|
|
||||||
description = "Oscuro bot service user";
|
|
||||||
home = cfg.dataDir;
|
|
||||||
createHome = true;
|
|
||||||
isSystemUser = true;
|
|
||||||
group = "oscuro";
|
|
||||||
};
|
|
||||||
users.groups.oscuro = {};
|
|
||||||
|
|
||||||
systemd.services.oscuro = {
|
|
||||||
description = "Oscuro";
|
|
||||||
wantedBy = ["multi-user.target"];
|
|
||||||
after = ["network.target"];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Restart = "always";
|
|
||||||
ExecStart = "${pkg}/bin/oscuro";
|
|
||||||
User = "oscuro";
|
|
||||||
WorkingDirectory = cfg.dataDir;
|
|
||||||
};
|
|
||||||
|
|
||||||
preStart = let
|
|
||||||
runConfig = "${cfg.dataDir}/config.toml";
|
|
||||||
replaceSecret = "${pkgs.replace-secret}/bin/replace-secret";
|
|
||||||
in ''
|
|
||||||
cp -f '${configFile}' '${runConfig}'
|
|
||||||
chmod u+w '${runConfig}'
|
|
||||||
|
|
||||||
${lib.optionalString (cfg.discordTokenFile != null) ''
|
|
||||||
${replaceSecret} '#discord_token#' '${cfg.discordTokenFile}' '${runConfig}'
|
|
||||||
''}
|
|
||||||
${lib.optionalString (cfg.discordToken != null) ''
|
|
||||||
sed -i 's/#discord_token#/${cfg.discordToken}/g' '${runConfig}'
|
|
||||||
''}
|
|
||||||
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
default = oscuro;
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosConfigurations.oscuro = nixpkgs.lib.nixosSystem {
|
|
||||||
system = "x86_64-linux";
|
|
||||||
modules = [
|
|
||||||
self.nixosModules.oscuro
|
|
||||||
({pkgs, ...}: {
|
|
||||||
boot.isContainer = true;
|
|
||||||
|
|
||||||
networking.hostName = "oscuro";
|
|
||||||
networking.useDHCP = false;
|
|
||||||
|
|
||||||
services.oscuro = {
|
|
||||||
enable = true;
|
|
||||||
discordToken = ""; # insert token
|
|
||||||
};
|
|
||||||
|
|
||||||
system.stateVersion = "24.05";
|
|
||||||
})
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
22
source/bot.hpp
Normal file
22
source/bot.hpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <discordpp/bot.hh>
|
||||||
|
#include <discordpp/rest-simpleweb.hh>
|
||||||
|
#include <discordpp/websocket-simpleweb.hh>
|
||||||
|
#include <discordpp/plugin-native.hh>
|
||||||
|
#include <discordpp/plugin-overload.hh>
|
||||||
|
#include <discordpp/plugin-responder.hh>
|
||||||
|
#include <discordpp/plugin-interactionhandler.hh>
|
||||||
|
#include <discordpp/plugin-ratelimit.hh>
|
||||||
|
|
||||||
|
|
||||||
|
using Bot = discordpp::PluginRateLimit
|
||||||
|
<discordpp::PluginInteractionHandler
|
||||||
|
<discordpp::PluginResponder
|
||||||
|
<discordpp::PluginOverload
|
||||||
|
<discordpp::PluginNative
|
||||||
|
<discordpp::WebsocketSimpleWeb
|
||||||
|
<discordpp::RestSimpleWeb
|
||||||
|
<discordpp::Bot>>>>>>>;
|
||||||
|
|
||||||
|
namespace dpp = discordpp;
|
19
source/commands.hpp
Normal file
19
source/commands.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include "bot.hpp"
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
using event = std::function<void(const json)>;
|
||||||
|
|
||||||
|
|
||||||
|
auto help(const std::shared_ptr<Bot>& bot)
|
||||||
|
{
|
||||||
|
return [&bot](const dpp::MessageCreateEvent& msg)
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
218
source/main.cpp
Normal file
218
source/main.cpp
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#ifdef ASIO_STANDALONE
|
||||||
|
#include <asio.hpp>
|
||||||
|
#else
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
namespace asio = boost::asio;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "bot.hpp"
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
#include <cpr/cpr.h>
|
||||||
|
#include "utils.hpp"
|
||||||
|
#include "commands.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
dpp::log::filter = dpp::log::debug;
|
||||||
|
dpp::log::out = &std::cerr;
|
||||||
|
|
||||||
|
std::cout << "Starting bot ..." << std::endl;
|
||||||
|
|
||||||
|
std::string token = getToken();
|
||||||
|
if (token.empty()) {
|
||||||
|
std::cerr << "Failed to read token from environment. Exiting ..." << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dpp::User self;
|
||||||
|
auto bot = std::make_shared<Bot>();
|
||||||
|
|
||||||
|
bot->debugUnhandled = true;
|
||||||
|
bot->intents = dpp::intents::NONE | dpp::intents::GUILD_MESSAGES;
|
||||||
|
|
||||||
|
bot->handlers.insert({
|
||||||
|
"READY",
|
||||||
|
[&self](dpp::ReadyEvent ready){ self = *ready.user; }
|
||||||
|
});
|
||||||
|
|
||||||
|
bot->prefix = "/";
|
||||||
|
|
||||||
|
bot->respond("test", help(bot));
|
||||||
|
bot->respond("help", "Mention me and I'll echo your message back!");
|
||||||
|
|
||||||
|
bot->respond("about", [&bot](dpp::MessageCreateEvent msg) {
|
||||||
|
std::ostringstream content;
|
||||||
|
content << "Sure thing, "
|
||||||
|
<< *(msg.member->nick ? msg.author->username : msg.member->nick)
|
||||||
|
<< "!\n"
|
||||||
|
<< "I'm a simple bot meant to demonstrate the "
|
||||||
|
"Discord++ library.\n"
|
||||||
|
<< "You can learn more about Discord++ at "
|
||||||
|
"https://discord.gg/VHAyrvspCx";
|
||||||
|
bot->createMessage()
|
||||||
|
->channel_id(*msg.channel_id)
|
||||||
|
->content(content.str())
|
||||||
|
->run();
|
||||||
|
});
|
||||||
|
|
||||||
|
bot->respond("lookatthis", [&bot](dpp::MessageCreateEvent msg) {
|
||||||
|
std::ifstream ifs("image.jpg", std::ios::binary);
|
||||||
|
if (!ifs) {
|
||||||
|
std::cerr << "Couldn't load file 'image.jpg'!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ifs.seekg(0, std::ios::end);
|
||||||
|
std::ifstream::pos_type fileSize = ifs.tellg();
|
||||||
|
ifs.seekg(0, std::ios::beg);
|
||||||
|
auto file = std::make_shared<std::string>(fileSize, '\0');
|
||||||
|
ifs.read(file->data(), fileSize);
|
||||||
|
|
||||||
|
bot->createMessage()
|
||||||
|
->channel_id(*msg.channel_id)
|
||||||
|
->content("Look at this photograph")
|
||||||
|
->filename("image.jpg")
|
||||||
|
->filetype("image/jpg")
|
||||||
|
->file(file)
|
||||||
|
->run();
|
||||||
|
});
|
||||||
|
|
||||||
|
bot->respond("notacat", [&bot](dpp::MessageCreateEvent msg)
|
||||||
|
{
|
||||||
|
cpr::Response res = cpr::Get(cpr::Url{"https://cataas.com/cat"});
|
||||||
|
std::cout << "Fetching a cat: " << res.status_code << ", " << res.header["content-type"] << std::endl;
|
||||||
|
bot->createMessage()
|
||||||
|
->channel_id(*msg.channel_id)
|
||||||
|
->filename("cat.jpg")
|
||||||
|
->filetype(res.header["content-type"])
|
||||||
|
->file(res.text)
|
||||||
|
->run();
|
||||||
|
});
|
||||||
|
|
||||||
|
bot->respond("channelinfo", [&bot](dpp::MessageCreateEvent msg) {
|
||||||
|
bot->getChannel()
|
||||||
|
->channel_id(*msg.channel_id)
|
||||||
|
->onRead([&bot, msg](bool error, json res) {
|
||||||
|
bot->createMessage()
|
||||||
|
->channel_id(*msg.channel_id)
|
||||||
|
->content("```json\n" + res["body"].dump(4) + "\n```")
|
||||||
|
->run();
|
||||||
|
})
|
||||||
|
->run();
|
||||||
|
});
|
||||||
|
|
||||||
|
bot->respond("register", [&bot, &self](dpp::MessageCreateEvent msg) {
|
||||||
|
if (*msg.author->id == 272712928074006528) {
|
||||||
|
bot->createGuildApplicationCommand()
|
||||||
|
->application_id(*self.id)
|
||||||
|
->guild_id(*msg.guild_id)
|
||||||
|
->name("echo")
|
||||||
|
->description("Echoes what you say")
|
||||||
|
->options({dpp::ApplicationCommandOption(
|
||||||
|
dpp::ApplicationCommandOptionType::STRING,
|
||||||
|
std::string("message"), dpp::omitted, std::string("The message to echo"),
|
||||||
|
dpp::omitted, true)})
|
||||||
|
->command_type(dpp::ApplicationCommandType::CHAT_INPUT)
|
||||||
|
->onRead([](bool error, json res) {
|
||||||
|
std::cout << res.dump(4) << std::endl;
|
||||||
|
})
|
||||||
|
->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
bot->createGuildApplicationCommand()
|
||||||
|
->application_id(*self.id)
|
||||||
|
->guild_id(*msg.guild_id)
|
||||||
|
->name("lookatthis")
|
||||||
|
->description("Help information")
|
||||||
|
->options({dpp::ApplicationCommandOption(
|
||||||
|
dpp::ApplicationCommandOptionType::STRING,
|
||||||
|
std::string("message"), dpp::omitted, std::string("The message to echo"),
|
||||||
|
dpp::omitted, true)})
|
||||||
|
->command_type(dpp::ApplicationCommandType::CHAT_INPUT)
|
||||||
|
->onRead([](bool error, json res) {
|
||||||
|
std::cout << res.dump(4) << std::endl;
|
||||||
|
})
|
||||||
|
->run();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
bot->interactionHandlers.insert(
|
||||||
|
{1102290596896460850, [&bot](dpp::Interaction msg) {
|
||||||
|
bot->createResponse()
|
||||||
|
->interaction_id(*msg.id)
|
||||||
|
->interaction_token(*msg.token)
|
||||||
|
->interaction_type(
|
||||||
|
dpp::InteractionCallbackType::CHANNEL_MESSAGE_WITH_SOURCE)
|
||||||
|
->data({{
|
||||||
|
"content",
|
||||||
|
*std::get<dpp::ApplicationCommandData>(*msg.data).options->at(0).value
|
||||||
|
}})
|
||||||
|
->run();
|
||||||
|
}});
|
||||||
|
|
||||||
|
// Create handler for the MESSAGE_CREATE payload, this receives all messages
|
||||||
|
// sent that the bot can see.
|
||||||
|
bot->handlers.insert(
|
||||||
|
{"MESSAGE_CREATE", [&bot, &self](const dpp::MessageCreateEvent msg) {
|
||||||
|
// Ignore messages from other bots
|
||||||
|
if (msg.webhook_id || (msg.author->bot && *msg.author->bot)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan through mentions in the message for self
|
||||||
|
bool mentioned = false;
|
||||||
|
for (const dpp::User &mention : *msg.mentions) {
|
||||||
|
mentioned = mentioned || (*mention.id == *self.id);
|
||||||
|
}
|
||||||
|
if (mentioned) {
|
||||||
|
// Identify and remove mentions of self from the message
|
||||||
|
std::stringstream content;
|
||||||
|
content << "чё тебе надо, ";//*msg.content;
|
||||||
|
/*unsigned int oldlength, length = content.length();
|
||||||
|
do {
|
||||||
|
oldlength = length;
|
||||||
|
content = std::regex_replace(
|
||||||
|
content,
|
||||||
|
std::regex(R"(<@!?)" + std::to_string(*self.id) +
|
||||||
|
R"(> ?)"),
|
||||||
|
"");
|
||||||
|
length = content.length();
|
||||||
|
} while (oldlength > length);
|
||||||
|
*/
|
||||||
|
// Get the target user's display name
|
||||||
|
std::string name = *(msg.member->nick ? msg.member->nick
|
||||||
|
: msg.author->username);
|
||||||
|
content << name << "?";
|
||||||
|
//std::cout << "Echoing " << name << '\n';
|
||||||
|
|
||||||
|
// Echo the created message
|
||||||
|
bot->createMessage()
|
||||||
|
->channel_id(*msg.channel_id)
|
||||||
|
->content(content.str())
|
||||||
|
->run();
|
||||||
|
|
||||||
|
// Set status to Playing "with [author]"
|
||||||
|
/*bot->send(3,
|
||||||
|
{{"game", {{"name", "with " + name}, {"type", 0}}},
|
||||||
|
{"status", "online"},
|
||||||
|
{"afk", false},
|
||||||
|
{"since", "null"}});*/
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
|
||||||
|
auto asioCtx = std::make_shared<asio::io_context>();
|
||||||
|
|
||||||
|
bot->initBot(9, token, asioCtx);
|
||||||
|
bot->run();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
74
source/utils.hpp
Normal file
74
source/utils.hpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
/*/
|
||||||
|
* Source: https://stackoverflow.com/a/6089413/1526048
|
||||||
|
/*/
|
||||||
|
std::istream &safeGetline(std::istream& is, std::string& str)
|
||||||
|
{
|
||||||
|
str.clear();
|
||||||
|
|
||||||
|
// The characters in the stream are read one-by-one using a std::streambuf.
|
||||||
|
// That is faster than reading them one-by-one using the std::istream.
|
||||||
|
// Code that uses streambuf this way must be guarded by a sentry object.
|
||||||
|
// The sentry object performs various tasks,
|
||||||
|
// such as thread synchronization and updating the stream state.
|
||||||
|
|
||||||
|
std::istream::sentry se(is, true);
|
||||||
|
std::streambuf *sb = is.rdbuf();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int c = sb->sbumpc();
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '\n':
|
||||||
|
return is;
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
if (sb->sgetc() == '\n') {
|
||||||
|
sb->sbumpc();
|
||||||
|
}
|
||||||
|
return is;
|
||||||
|
|
||||||
|
case std::streambuf::traits_type::eof():
|
||||||
|
// Also handle the case when the last line has no line ending
|
||||||
|
if (str.empty())
|
||||||
|
is.setstate(std::ios::eofbit);
|
||||||
|
|
||||||
|
return is;
|
||||||
|
|
||||||
|
default:
|
||||||
|
str += (char)c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getToken(const std::string& filename = "")
|
||||||
|
{
|
||||||
|
std::string token;
|
||||||
|
char const *env = std::getenv("BOT_TOKEN");
|
||||||
|
|
||||||
|
if (env != nullptr)
|
||||||
|
{
|
||||||
|
token = std::string(env);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::ifstream tokenFile(filename);
|
||||||
|
|
||||||
|
if (!tokenFile)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
safeGetline(tokenFile, token);
|
||||||
|
tokenFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
|||||||
use std::env;
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct Config {
|
|
||||||
pub discord_token: Option<String>,
|
|
||||||
pub telegram_token: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config {
|
|
||||||
pub fn data_dir() -> Result<std::path::PathBuf, ConfigError> {
|
|
||||||
let cwd = std::env::current_dir()?;
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
Ok(cwd.join("temp"))
|
|
||||||
} else {
|
|
||||||
Ok(cwd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn open(path: &std::path::Path) -> Result<Config, ConfigError> {
|
|
||||||
fs::read_to_string(path)?.parse()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_string(&self) -> Result<String, ConfigError> {
|
|
||||||
Ok(toml::to_string(self)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(&self, path: &std::path::Path) -> Result<(), ConfigError> {
|
|
||||||
Ok(fs::write(path, self.to_string()?)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_env(mut self) -> Self {
|
|
||||||
if let Ok(token) = env::var("OSCURO_DISCORD_TOKEN") {
|
|
||||||
self.discord_token = Some(token);
|
|
||||||
};
|
|
||||||
if let Ok(token) = env::var("OSCURO_TELEGRAM_TOKEN") {
|
|
||||||
self.telegram_token = Some(token);
|
|
||||||
};
|
|
||||||
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Config {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
discord_token: Some(String::new()),
|
|
||||||
telegram_token: Some(String::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::str::FromStr for Config {
|
|
||||||
type Err = ConfigError;
|
|
||||||
fn from_str(s: &str) -> Result<Self, ConfigError> {
|
|
||||||
toml::from_str(s).map_err(|_| ConfigError::Parse)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ConfigError {
|
|
||||||
Parse,
|
|
||||||
StringParse,
|
|
||||||
Serialize,
|
|
||||||
IO,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for ConfigError {}
|
|
||||||
|
|
||||||
impl std::fmt::Display for ConfigError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Parse => write!(f, "Failed to parse config from string"),
|
|
||||||
Self::StringParse => write!(f, "Failed to parse environment variable"),
|
|
||||||
Self::Serialize => write!(f, "Failed to serialize Config to TOML"),
|
|
||||||
Self::IO => write!(f, "Failed to write file"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<toml::ser::Error> for ConfigError {
|
|
||||||
fn from(_: toml::ser::Error) -> Self {
|
|
||||||
ConfigError::Serialize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<std::io::Error> for ConfigError {
|
|
||||||
fn from(_: std::io::Error) -> Self {
|
|
||||||
ConfigError::IO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<std::num::ParseIntError> for ConfigError {
|
|
||||||
fn from(_: std::num::ParseIntError) -> Self {
|
|
||||||
ConfigError::StringParse
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
use async_process::Command;
|
|
||||||
use poise::serenity_prelude as serenity;
|
|
||||||
use rand::Rng;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::str;
|
|
||||||
|
|
||||||
use super::Context;
|
|
||||||
use crate::errors::BoxedError;
|
|
||||||
|
|
||||||
#[poise::command(prefix_command)]
|
|
||||||
pub async fn register(ctx: Context<'_>) -> Result<(), BoxedError> {
|
|
||||||
poise::builtins::register_application_commands_buttons(ctx).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command)]
|
|
||||||
pub async fn age(
|
|
||||||
ctx: Context<'_>,
|
|
||||||
#[description = "Ooph user"] user: Option<serenity::User>,
|
|
||||||
) -> Result<(), BoxedError> {
|
|
||||||
let u = user.as_ref().unwrap_or_else(|| ctx.author());
|
|
||||||
let response = format!("{}'s account was created at {}", u.name, u.created_at());
|
|
||||||
ctx.say(response).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command)]
|
|
||||||
pub async fn dice(ctx: Context<'_>) -> Result<(), BoxedError> {
|
|
||||||
let number = {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
rng.gen_range(1..21)
|
|
||||||
};
|
|
||||||
|
|
||||||
let response = format!("{} throws {}.", ctx.author(), number);
|
|
||||||
let response = match number {
|
|
||||||
20 => format!("{} Critical success.", response),
|
|
||||||
1 => format!("{} Critical failure.", response),
|
|
||||||
_ => response,
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.say(response).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, poise::ChoiceParameter)]
|
|
||||||
pub enum ServiceChoice {
|
|
||||||
#[name = "Elnafo VCS"]
|
|
||||||
ElnafoVcs,
|
|
||||||
#[name = "Elnafo Mail"]
|
|
||||||
ElnafoMail,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command)]
|
|
||||||
pub async fn status(
|
|
||||||
ctx: Context<'_>,
|
|
||||||
#[description = "Check service status"] service: ServiceChoice,
|
|
||||||
) -> Result<(), BoxedError> {
|
|
||||||
let mut systemctl = Command::new("systemctl");
|
|
||||||
let service_info = match service {
|
|
||||||
ServiceChoice::ElnafoVcs => systemctl.arg("show").arg("gitea.service"),
|
|
||||||
ServiceChoice::ElnafoMail => systemctl.arg("show").arg("acpid.service"),
|
|
||||||
};
|
|
||||||
let output = service_info.output().await?;
|
|
||||||
|
|
||||||
let mut data: HashMap<&str, &str> = HashMap::new();
|
|
||||||
|
|
||||||
for line in str::from_utf8(&output.stdout)?.lines() {
|
|
||||||
let kv: Vec<&str> = line.split('=').collect();
|
|
||||||
data.insert(kv[0], kv[1]);
|
|
||||||
}
|
|
||||||
println!("{:?} {:?}", data["LoadState"], data["SubState"]);
|
|
||||||
|
|
||||||
if data["LoadState"] == "loaded" && data["SubState"] == "running" {
|
|
||||||
ctx.say(format!(
|
|
||||||
"{:?} is up and running for {}",
|
|
||||||
service, data["ExecMainStartTimestamp"]
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
ctx.say(format!("{:?} is dead", service)).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,148 +0,0 @@
|
|||||||
pub mod commands;
|
|
||||||
|
|
||||||
use crate::config::Config;
|
|
||||||
use crate::errors::BoxedError;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use poise::serenity_prelude::{
|
|
||||||
self as serenity,
|
|
||||||
builder::{CreateEmbed, CreateMessage},
|
|
||||||
model::id::ChannelId,
|
|
||||||
prelude::TypeMapKey,
|
|
||||||
//Client,
|
|
||||||
};
|
|
||||||
use serenity::GatewayIntents;
|
|
||||||
|
|
||||||
use teloxide::prelude::*;
|
|
||||||
use teloxide::types::Recipient;
|
|
||||||
|
|
||||||
use crate::telegram;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct BotState {
|
|
||||||
pub config: Config,
|
|
||||||
pub telegram_agent: Option<telegram::Client>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TypeMapKey for BotState {
|
|
||||||
type Value = BotState;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Context<'a> = poise::Context<'a, BotState, BoxedError>;
|
|
||||||
|
|
||||||
pub struct Client {
|
|
||||||
client: serenity::Client,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Client {
|
|
||||||
pub async fn new(config: Config) -> Result<Self, BoxedError> {
|
|
||||||
let telegram_agent = if config.clone().telegram_token.is_some() {
|
|
||||||
Some(telegram::Client::new(config.clone()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let state = BotState {
|
|
||||||
config: config.clone(),
|
|
||||||
telegram_agent: telegram_agent,
|
|
||||||
};
|
|
||||||
|
|
||||||
let intents = GatewayIntents::GUILDS
|
|
||||||
| GatewayIntents::GUILD_MESSAGES
|
|
||||||
| GatewayIntents::MESSAGE_CONTENT;
|
|
||||||
let state_copy = state.clone();
|
|
||||||
let framework = poise::Framework::builder()
|
|
||||||
.options(poise::FrameworkOptions {
|
|
||||||
commands: vec![
|
|
||||||
commands::register(),
|
|
||||||
commands::age(),
|
|
||||||
commands::dice(),
|
|
||||||
commands::status(),
|
|
||||||
],
|
|
||||||
event_handler: |ctx, event, framework, data| {
|
|
||||||
Box::pin(event_handler(ctx, event, framework, data))
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.setup(|ctx, _ready, framework| {
|
|
||||||
Box::pin(async move {
|
|
||||||
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
|
|
||||||
Ok(state_copy)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let client =
|
|
||||||
serenity::ClientBuilder::new(state.clone().config.discord_token.unwrap(), intents)
|
|
||||||
.framework(framework)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut data = client.data.write().await;
|
|
||||||
data.insert::<BotState>(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self { client })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn start(&mut self) -> Result<(), BoxedError> {
|
|
||||||
self.client.start().await;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send(&self, chat_id: u64, msg: String) -> Result<(), BoxedError> {
|
|
||||||
let builder = CreateMessage::new().content(msg);
|
|
||||||
let message = ChannelId::new(chat_id)
|
|
||||||
.send_message(&self.client.http, builder)
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn event_handler(
|
|
||||||
ctx: &serenity::Context,
|
|
||||||
event: &serenity::FullEvent,
|
|
||||||
_framework: poise::FrameworkContext<'_, BotState, BoxedError>,
|
|
||||||
_state: &BotState,
|
|
||||||
) -> Result<(), BoxedError> {
|
|
||||||
match event {
|
|
||||||
serenity::FullEvent::Ready { data_about_bot, .. } => {
|
|
||||||
tracing::info!("discord: Logged in as {}", data_about_bot.user.name);
|
|
||||||
|
|
||||||
// We can use ChannelId directly to send a message to a specific channel; in this case, the
|
|
||||||
// message would be sent to the #testing channel on the discord server.
|
|
||||||
/*let embed = CreateEmbed::new().title("System Resource Load").field(
|
|
||||||
"CPU Load Average",
|
|
||||||
format!("{:.2}%", 10.0),
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
let builder = CreateMessage::new().embed(embed);
|
|
||||||
let message = ChannelId::new(1145642256443904002)
|
|
||||||
.send_message(&ctx, builder)
|
|
||||||
.await;
|
|
||||||
if let Err(why) = message {
|
|
||||||
eprintln!("Error sending message: {why:?}");
|
|
||||||
};*/
|
|
||||||
}
|
|
||||||
serenity::FullEvent::Message { new_message } => {
|
|
||||||
let mut data = ctx.data.write().await;
|
|
||||||
let state = data.get_mut::<BotState>().unwrap();
|
|
||||||
println!("{:?}", new_message);
|
|
||||||
|
|
||||||
let author = new_message
|
|
||||||
.author
|
|
||||||
.global_name
|
|
||||||
.clone()
|
|
||||||
.or(Some(new_message.author.name.clone()))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if let Some(agent) = &state.telegram_agent {
|
|
||||||
agent
|
|
||||||
.send(-4221527632, format!("{}: {}", author, new_message.content))
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
pub type BoxedError = Box<dyn std::error::Error + Send + Sync>;
|
|
76
src/main.rs
76
src/main.rs
@ -1,76 +0,0 @@
|
|||||||
mod config;
|
|
||||||
mod discord;
|
|
||||||
mod errors;
|
|
||||||
mod telegram;
|
|
||||||
|
|
||||||
use config::Config;
|
|
||||||
|
|
||||||
use tokio::signal;
|
|
||||||
use tokio::task::JoinSet;
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() -> Result<(), errors::BoxedError> {
|
|
||||||
tracing_subscriber::fmt()
|
|
||||||
.with_target(false)
|
|
||||||
.compact()
|
|
||||||
.init();
|
|
||||||
|
|
||||||
tracing::info!("Working directory: {:?}", Config::data_dir()?);
|
|
||||||
|
|
||||||
let config = match Config::open(Config::data_dir()?.join("config.toml").as_path()) {
|
|
||||||
Ok(config) => config,
|
|
||||||
Err(err) => {
|
|
||||||
tracing::debug!("{}", err);
|
|
||||||
tracing::info!("Using default configuration");
|
|
||||||
Config::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.with_env();
|
|
||||||
|
|
||||||
let mut runset = JoinSet::new();
|
|
||||||
|
|
||||||
if !config.clone().discord_token.is_some() {
|
|
||||||
tracing::warn!("Missing discord token");
|
|
||||||
} else {
|
|
||||||
let mut discord_client = discord::Client::new(config.clone())
|
|
||||||
.await
|
|
||||||
.expect("Failed to create discord client");
|
|
||||||
|
|
||||||
runset.spawn(async move {
|
|
||||||
|
|
||||||
let res = discord_client.start().await;
|
|
||||||
if let Err(err) = res {
|
|
||||||
tracing::error!("{}", err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if !config.clone().telegram_token.is_some() {
|
|
||||||
tracing::warn!("Missing telegram token");
|
|
||||||
} else {
|
|
||||||
let telegram_client = telegram::Client::new(config);
|
|
||||||
|
|
||||||
runset.spawn(async move {
|
|
||||||
let res = telegram_client.start().await;
|
|
||||||
if let Err(err) = res {
|
|
||||||
tracing::error!("{}", err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
while let Some(res) = runset.join_next().await {
|
|
||||||
if let Err(err) = res {
|
|
||||||
tracing::error!("{}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match signal::ctrl_c().await {
|
|
||||||
Ok(()) => {}
|
|
||||||
Err(err) => {
|
|
||||||
eprintln!("Unable to listen for shutdown signal: {}", err);
|
|
||||||
// we also shut down in case of error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
use teloxide::prelude::*;
|
|
||||||
use teloxide::types::Recipient;
|
|
||||||
use teloxide::utils::command::BotCommands;
|
|
||||||
|
|
||||||
use crate::config::Config;
|
|
||||||
use crate::errors;
|
|
||||||
use rand::Rng;
|
|
||||||
|
|
||||||
async fn main() {
|
|
||||||
let bot = Bot::from_env();
|
|
||||||
|
|
||||||
/*let http = Http::new("");
|
|
||||||
let webhook = Webhook::from_url(&http, "https://discord.com/api/webhooks/1259860143579987999/whI0ozB5uc17Wdzkb2-HSrVGi8h_MyR2_4eyCsGuGpQN4KcjMhq7rfQH1JIdbD1HNaW_")
|
|
||||||
.await
|
|
||||||
.expect("Replace the webhook with your own");
|
|
||||||
|
|
||||||
let builder = ExecuteWebhook::new().content("hello there").username("Webhook test");
|
|
||||||
webhook.execute(&http, false, builder).await.expect("Could not execute webhook.");
|
|
||||||
*/
|
|
||||||
teloxide::repl(bot, |bot: Bot, msg: Message| async move {
|
|
||||||
bot.send_dice(msg.chat.id).await?;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
/*bot.send_message(Recipient::Id(ChatId(-4221527632)), "Heya!")
|
|
||||||
.await
|
|
||||||
.expect("err");*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct Client {
|
|
||||||
bot: Bot,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Client {
|
|
||||||
pub fn new(config: Config) -> Self {
|
|
||||||
Self {
|
|
||||||
bot: Bot::new(config.telegram_token.unwrap()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn start(&self) -> Result<(), errors::BoxedError> {
|
|
||||||
Command::repl(self.bot.clone(), event_handler).await;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send(&self, chat_id: i64, msg: String) -> ResponseResult<()> {
|
|
||||||
self.bot
|
|
||||||
.send_message(Recipient::Id(ChatId(chat_id)), msg)
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(BotCommands, Clone)]
|
|
||||||
#[command(rename_rule = "lowercase")]
|
|
||||||
pub enum Command {
|
|
||||||
#[command()]
|
|
||||||
Dice,
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn event_handler(bot: Bot, msg: Message, cmd: Command) -> ResponseResult<()> {
|
|
||||||
match cmd {
|
|
||||||
Command::Dice => {
|
|
||||||
let number = {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
rng.gen_range(1..21)
|
|
||||||
};
|
|
||||||
|
|
||||||
let response = format!("{} throws {}.", "test", number);
|
|
||||||
let response = match number {
|
|
||||||
20 => format!("{} Critical success.", response),
|
|
||||||
1 => format!("{} Critical failure.", response),
|
|
||||||
_ => response,
|
|
||||||
};
|
|
||||||
// -4221527632
|
|
||||||
|
|
||||||
bot.send_message(Recipient::Id(msg.chat.id), response)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user