mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
Compare commits
361 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
40f1774655 | ||
|
fddd0f2340 | ||
|
86f9d901fe | ||
|
eaab60898f | ||
|
e40c9335c1 | ||
|
d921b6889d | ||
|
aaef365bdc | ||
|
a01a646cbf | ||
|
5bee5e63d2 | ||
|
815e318610 | ||
|
634c6c99ee | ||
|
6b37b49439 | ||
|
f42afa7eae | ||
|
ccae1c59e9 | ||
|
b0d8137a7a | ||
|
e78a7d0efa | ||
|
1da19a51f6 | ||
|
91eed9dbd8 | ||
|
7ba345b0fc | ||
|
5d775c9589 | ||
|
2bd8ead10c | ||
|
1148ba3e6e | ||
|
5498bec8cc | ||
|
9eed0c6be5 | ||
|
acf6b7cf58 | ||
|
8598419c5f | ||
|
758093eb32 | ||
|
f44dd03f1a | ||
|
8ac5ec9f57 | ||
|
5209ba802a | ||
|
adfce6670c | ||
|
f8fbc71985 | ||
|
d4e2516a17 | ||
|
f62a67e2e6 | ||
|
7895b5e702 | ||
|
28c8ccfb5f | ||
|
79026e0c27 | ||
|
8b228b840a | ||
|
f61c1a159d | ||
|
2cdcdb2b23 | ||
|
8d0a3ecb20 | ||
|
97f1405a94 | ||
|
0622236523 | ||
|
0f240925e8 | ||
|
d583e2b99a | ||
|
2d72f6f498 | ||
|
5143e42dff | ||
|
790c36df8d | ||
|
15709bc8fb | ||
|
f280f72227 | ||
|
4069368beb | ||
|
e036a2d3c9 | ||
|
62a16f3faf | ||
|
231451f978 | ||
|
2bed4e7eac | ||
|
22eea3fa7b | ||
|
8b1767078e | ||
|
6654ccdad5 | ||
|
99827b0fa1 | ||
|
0451551ddf | ||
|
75d0eb631d | ||
|
96ce7e23bb | ||
|
aac475be62 | ||
|
55fae53f6d | ||
|
879f196f8b | ||
|
796086538a | ||
|
3178074828 | ||
|
0a9d53d380 | ||
|
d7fbf44d53 | ||
|
cdd07d0559 | ||
|
80a41c1f38 | ||
|
1631394638 | ||
|
7eb4895570 | ||
|
9b55028ba6 | ||
|
53363d2840 | ||
|
ca5a870bf8 | ||
|
7f5e065c4d | ||
|
86b214163a | ||
|
9dbb08d85f | ||
|
89ca56c77c | ||
|
9e96679099 | ||
|
1280d2b397 | ||
|
c731127607 | ||
|
c15930306a | ||
|
701501d678 | ||
|
fa12fcea58 | ||
|
274219c40b | ||
|
96c9b47da2 | ||
|
b5d1469df1 | ||
|
d7747bd25a | ||
|
7d162d1f04 | ||
|
704d061d46 | ||
|
c39c9061fd | ||
|
619ddba4f8 | ||
|
3acef04b32 | ||
|
83a1d959b1 | ||
|
a1632722bc | ||
|
ee0a28afab | ||
|
2b301c0aab | ||
|
b6b6b4e19e | ||
|
32fc8b6e03 | ||
|
297e2fde0e | ||
|
729f26caab | ||
|
4b12e4e923 | ||
|
12f4ce7f2a | ||
|
00944e08c3 | ||
|
569abd7194 | ||
|
474a1db41d | ||
|
0f6255947e | ||
|
f68f219a25 | ||
|
8f16b11d02 | ||
|
df5eced904 | ||
|
1dcd158f43 | ||
|
757c9b564d | ||
|
07cef3eb5e | ||
|
85c525e19b | ||
|
477581f616 | ||
|
ff30105816 | ||
|
49f04a594b | ||
|
716090a132 | ||
|
c835514c7b | ||
|
b136e7ff0e | ||
|
9dd2997b0f | ||
|
fde5309ea4 | ||
|
a8e4173e9b | ||
|
74b4c4b64d | ||
|
6cc5a160a2 | ||
|
ca8e022db6 | ||
|
cd8c14c607 | ||
|
1340533c21 | ||
|
14d86b9042 | ||
|
3a504a954f | ||
|
822ce0b8de | ||
|
40490a4656 | ||
|
0cf7909fef | ||
|
de8d4b7d9e | ||
|
0123892038 | ||
|
d00e59567a | ||
|
0aba2fdcaf | ||
|
bb910a8188 | ||
|
bdad9cc17a | ||
|
5d76a15dc0 | ||
|
a7be56a562 | ||
|
3c108e531e | ||
|
c473669cbc | ||
|
b97c486b80 | ||
|
716e092fd0 | ||
|
a362ee90fc | ||
|
1de6cdb8dc | ||
|
f473014fe9 | ||
|
2c3e5fe507 | ||
|
ecc192c6a9 | ||
|
f7bd181034 | ||
|
664a4b3604 | ||
|
0326e88910 | ||
|
e4202b33f5 | ||
|
021e7978da | ||
|
28ad6db2de | ||
|
fb62df7aa2 | ||
|
33663d7efc | ||
|
6d1edc07cb | ||
|
c36ab34c4f | ||
|
e85e7c49cb | ||
|
e56190e9da | ||
|
2d16ecf6de | ||
|
2b12269917 | ||
|
79c2dfec2d | ||
|
73356b6beb | ||
|
bc22987330 | ||
|
c033c0e3c8 | ||
|
c9ed2cf4b5 | ||
|
52b87c7776 | ||
|
8b2ed0dbdc | ||
|
9424d4d5f9 | ||
|
67b186a1a5 | ||
|
436f9ed074 | ||
|
c1e51329be | ||
|
ae1193c1c5 | ||
|
9601a4d1a9 | ||
|
bdfde1205a | ||
|
5992628f80 | ||
|
d24e6fd8e7 | ||
|
c31c2e8d8e | ||
|
9aaf062d78 | ||
|
0b9e812d59 | ||
|
dc63e46852 | ||
|
e314686a03 | ||
|
f764a650da | ||
|
67616deb79 | ||
|
d0aa80a004 | ||
|
f66c105cc0 | ||
|
2a528cb3d6 | ||
|
8b40f97a3d | ||
|
fa9263ed32 | ||
|
88c42b74c7 | ||
|
f7406ec90b | ||
|
e446c8ee8b | ||
|
5839e944e1 | ||
|
15e41c10db | ||
|
99a8ea18bb | ||
|
5453f8acfa | ||
|
c95d1421c6 | ||
|
f631f16690 | ||
|
d397c2dce8 | ||
|
273816b8a4 | ||
|
3094c3248b | ||
|
ae6018f0e1 | ||
|
54adbedf9f | ||
|
eb29e34f17 | ||
|
4a402ee673 | ||
|
764babdf06 | ||
|
dd49d202b7 | ||
|
a396c2d9dd | ||
|
15fe8b5daf | ||
|
f8da25a6f3 | ||
|
383acba443 | ||
|
690c03b396 | ||
|
f4ed907134 | ||
|
1b0badd8d8 | ||
|
2c3ada4710 | ||
|
0df3c1a4a1 | ||
|
ac589e0461 | ||
|
8f181eed85 | ||
|
6fefce4c4d | ||
|
d9e080f4b9 | ||
|
762a2eca1f | ||
|
2fba771681 | ||
|
b5e2b6f483 | ||
|
17e5ff8b89 | ||
|
3d287b2afa | ||
|
3f33274cec | ||
|
ee9d8a51bf | ||
|
80a7678a82 | ||
|
de8a0e2207 | ||
|
122b3ae0d9 | ||
|
b4307f9123 | ||
|
5ae18ba1bf | ||
|
44c8c9f459 | ||
|
4e177ff198 | ||
|
ad679a996d | ||
|
7d86a5e3eb | ||
|
214c9a383c | ||
|
f77e1c6b8c | ||
|
7e784b9507 | ||
|
7a14991ed6 | ||
|
4c5c2d7f6e | ||
|
87b90b47ce | ||
|
9f060243f0 | ||
|
d3ab32a7ac | ||
|
7bd081b7cf | ||
|
3a5b482884 | ||
|
db66264bc6 | ||
|
ae1ddd82d0 | ||
|
8523abd6f1 | ||
|
e1892c4ff4 | ||
|
a50a7b3b0e | ||
|
9d2268a925 | ||
|
d77a86c08b | ||
|
d605f685cf | ||
|
bbc1fd28c2 | ||
|
cff8a258d0 | ||
|
1d760a548e | ||
|
25fa8a3852 | ||
|
ca13684c0d | ||
|
0ad6b741e7 | ||
|
4ce756d760 | ||
|
5f2813d3af | ||
|
1b7458529c | ||
|
9c9c8d7490 | ||
|
2700bfdce8 | ||
|
5498c5ce3f | ||
|
6f444a8da0 | ||
|
454c14eee1 | ||
|
30aa8e8186 | ||
|
2ca141810c | ||
|
9da8e4f1c1 | ||
|
ef471c32bb | ||
|
49d557caec | ||
|
4366f908f3 | ||
|
237e66495b | ||
|
15d4117d7f | ||
|
d7daa5f2af | ||
|
b08ff62406 | ||
|
9aa89d3be8 | ||
|
518f2e425e | ||
|
8fae6e621d | ||
|
30f3ae1ade | ||
|
ef4b1c8868 | ||
|
7f64d2661f | ||
|
ab93380d7c | ||
|
a6adf73ecf | ||
|
d9e52038ac | ||
|
be7ddc732b | ||
|
79b25c8a41 | ||
|
12fa209555 | ||
|
28a9f5682e | ||
|
06321380ee | ||
|
b51ce34190 | ||
|
317c94979a | ||
|
df2fd1b3f1 | ||
|
35f0228986 | ||
|
f391027c8c | ||
|
4e570475df | ||
|
e2066f433f | ||
|
78b328dc18 | ||
|
f0cbacd01a | ||
|
d45c39a5fe | ||
|
a6010716e8 | ||
|
d2c7563c5c | ||
|
0c167a9382 | ||
|
b9d2e4baf1 | ||
|
82e230010b | ||
|
03fb1a5ca2 | ||
|
8ac07ce6d7 | ||
|
12da9f3178 | ||
|
ae45329d2b | ||
|
f499380fe8 | ||
|
0083e9ef68 | ||
|
22b7cf5e6c | ||
|
f973766c73 | ||
|
0efdd3300d | ||
|
5016377dd1 | ||
|
2d40a35112 | ||
|
9ea6cd0b32 | ||
|
a52a246982 | ||
|
803fe5db2f | ||
|
39980a1374 | ||
|
d2c4af273b | ||
|
d51dfa88f1 | ||
|
869b9d3b9d | ||
|
f4b26c5b40 | ||
|
15f629ec53 | ||
|
9406a9cc34 | ||
|
52438f45e1 | ||
|
7b2ce072ee | ||
|
89d93dcffb | ||
|
0fb34b1c61 | ||
|
980a6b0af8 | ||
|
5c7a467caa | ||
|
35fd5c415d | ||
|
2762108986 | ||
|
876d63fd8b | ||
|
263ef4b47f | ||
|
1c540476d3 | ||
|
1d0f3d3fd6 | ||
|
c7cec25a29 | ||
|
23c8dc00e8 | ||
|
0da8190637 | ||
|
d766295286 | ||
|
21e3c64e01 | ||
|
9ddcd6d89e | ||
|
a154d5881c | ||
|
fb594e50fd | ||
|
75c5a003bf | ||
|
6f4cbddcad | ||
|
40528150f7 | ||
|
2b80823a1b | ||
|
37ee769119 | ||
|
cfd39ebbd5 | ||
|
0532b30f7f | ||
|
b92a38f49d |
@@ -30,12 +30,17 @@ variables:
|
||||
build:
|
||||
stage: build
|
||||
script:
|
||||
- "dotnet publish -c Release -r linux-x64 --self-contained -p:PublishSingleFile=true -o $LINUX_X64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r linux-arm64 --self-contained -p:PublishSingleFile=true -o $LINUX_ARM64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r win-x64 --self-contained -p:PublishSingleFile=true -o $WIN_X64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r win-arm64 --self-contained -p:PublishSingleFile=true -o $WIN_ARM64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r osx-x64 --self-contained -p:PublishSingleFile=true -o $MACOS_X64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r osx-arm64 --self-contained -p:PublishSingleFile=true -o $MACOS_ARM64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- |
|
||||
VERSION_STRING=""
|
||||
if [ -n "$CI_COMMIT_TAG" ]; then
|
||||
VERSION_STRING="-p:Version=$CI_COMMIT_TAG"
|
||||
fi
|
||||
- "dotnet publish -c Release -r linux-x64 --self-contained $VERSION_STRING -o $LINUX_X64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r linux-arm64 --self-contained $VERSION_STRING -o $LINUX_ARM64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r win-x64 --self-contained $VERSION_STRING -o $WIN_X64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r win-arm64 --self-contained $VERSION_STRING -o $WIN_ARM64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r osx-x64 --self-contained $VERSION_STRING -o $MACOS_X64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
- "dotnet publish -c Release -r osx-arm64 --self-contained $VERSION_STRING -o $MACOS_ARM64_OUTPUT_DIR src/NadekoBot/NadekoBot.csproj"
|
||||
artifacts:
|
||||
paths:
|
||||
- "$LINUX_X64_OUTPUT_DIR/"
|
||||
@@ -81,7 +86,7 @@ release:
|
||||
- if: $CI_COMMIT_TAG
|
||||
script:
|
||||
- |
|
||||
release-cli create --name "NadekoBot v$CI_COMMIT_TAG" --description "## [Changelog](https://gitlab.com/nadeko/nadekobot/-/blob/v5/CHANGELOG.md#$(echo "$CI_COMMIT_TAG" | sed "s/\.//g")-$(date +%d%m%Y))" --tag-name $CI_COMMIT_TAG \
|
||||
release-cli create --name "NadekoBot v$CI_COMMIT_TAG" --description "## [Changelog](https://gitlab.com/kwoth/nadekobot/-/blob/v5/CHANGELOG.md#$(echo "$CI_COMMIT_TAG" | sed "s/\.//g")-$(date +%d%m%Y))" --tag-name $CI_COMMIT_TAG \
|
||||
--assets-link "{\"name\":\"${LINUX_X64_RELEASE}\",\"url\":\"${PACKAGE_REGISTRY_URL}/${LINUX_X64_RELEASE}\"}" \
|
||||
--assets-link "{\"name\":\"${LINUX_ARM64_RELEASE}\",\"url\":\"${PACKAGE_REGISTRY_URL}/${LINUX_ARM64_RELEASE}\"}" \
|
||||
--assets-link "{\"name\":\"${WIN_X64_RELEASE}\",\"url\":\"${PACKAGE_REGISTRY_URL}/${WIN_X64_RELEASE}\"}" \
|
||||
@@ -113,7 +118,7 @@ build-installer:
|
||||
script:
|
||||
- dotnet clean
|
||||
- dotnet restore -f --no-cache -v n
|
||||
- dotnet publish -c Release --runtime win-x64 /p:Version=$CI_COMMIT_TAG src/NadekoBot
|
||||
- dotnet publish -c Release --self-contained --runtime win-x64 /p:Version=$CI_COMMIT_TAG src/NadekoBot
|
||||
- $env:NADEKOBOT_INSTALL_VERSION = $CI_COMMIT_TAG
|
||||
- iscc.exe "/O+" ".\exe_builder.iss"
|
||||
tags:
|
||||
@@ -123,6 +128,8 @@ publish-medusa-package:
|
||||
stage: publish-medusa-package
|
||||
allow_failure: true
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG
|
||||
script:
|
||||
- LAST_TAG=$(git describe --tags --abbrev=0)
|
||||
|
1198
CHANGELOG.md
1198
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
23
Dockerfile
23
Dockerfile
@@ -1,16 +1,24 @@
|
||||
# Use the .NET 8.0 SDK as the base image for the build stage
|
||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||
WORKDIR /source
|
||||
|
||||
# Copy the .csproj files for each project
|
||||
COPY src/Nadeko.Medusa/*.csproj src/Nadeko.Medusa/
|
||||
COPY src/NadekoBot/*.csproj src/NadekoBot/
|
||||
COPY src/NadekoBot.Coordinator/*.csproj src/NadekoBot.Coordinator/
|
||||
COPY src/NadekoBot.Generators/*.csproj src/NadekoBot.Generators/
|
||||
COPY src/NadekoBot.Voice/*.csproj src/NadekoBot.Voice/
|
||||
COPY NuGet.Config ./
|
||||
|
||||
# Restore the dependencies for the NadekoBot project
|
||||
RUN dotnet restore src/NadekoBot/
|
||||
|
||||
# Copy the rest of the source code
|
||||
COPY . .
|
||||
|
||||
# Set the working directory to the NadekoBot project
|
||||
WORKDIR /source/src/NadekoBot
|
||||
|
||||
# Build and publish the NadekoBot project, then clean up unnecessary files
|
||||
RUN set -xe; \
|
||||
dotnet --version; \
|
||||
dotnet publish -c Release -o /app --no-restore; \
|
||||
@@ -19,28 +27,33 @@ RUN set -xe; \
|
||||
find /app -type f -exec chmod -x {} \; ;\
|
||||
chmod +x /app/NadekoBot
|
||||
|
||||
# final stage/image
|
||||
# Use the .NET 8.0 runtime as the base image for the final stage
|
||||
FROM mcr.microsoft.com/dotnet/runtime:8.0
|
||||
WORKDIR /app
|
||||
|
||||
# Create a new user, install dependencies, and set up sudoers file
|
||||
RUN set -xe; \
|
||||
useradd -m nadeko; \
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends libopus0 libsodium23 libsqlite3-0 curl ffmpeg python3 sudo; \
|
||||
update-alternatives --install /usr/local/bin/python python /usr/bin/python3.9 1; \
|
||||
apt-get install -y --no-install-recommends libsqlite3-0 curl ffmpeg sudo python3; \
|
||||
echo 'Defaults>nadeko env_keep+="ASPNETCORE_* DOTNET_* NadekoBot_* shard_id total_shards TZ"' > /etc/sudoers.d/nadeko; \
|
||||
curl -Lo /usr/local/bin/yt-dlp https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp; \
|
||||
chmod a+rx /usr/local/bin/yt-dlp; \
|
||||
apt-get autoremove -y; \
|
||||
apt-get autoclean -y
|
||||
|
||||
# Copy the built application and the entrypoint script from the build stage
|
||||
COPY --from=build /app ./
|
||||
COPY docker-entrypoint.sh /usr/local/sbin
|
||||
|
||||
# Set environment variables
|
||||
ENV shard_id=0
|
||||
ENV total_shards=1
|
||||
ENV NadekoBot__creds=/app/data/creds.yml
|
||||
|
||||
# Define the data directory as a volume
|
||||
VOLUME [ "/app/data" ]
|
||||
|
||||
# Set the entrypoint and default command
|
||||
ENTRYPOINT [ "/usr/local/sbin/docker-entrypoint.sh" ]
|
||||
CMD dotnet NadekoBot.dll "$shard_id" "$total_shards"
|
||||
CMD dotnet NadekoBot.dll "$shard_id" "$total_shards"
|
@@ -12,7 +12,6 @@ ProjectSection(SolutionItems) = preProject
|
||||
README.md = README.md
|
||||
.gitlab-ci.yml = .gitlab-ci.yml
|
||||
Dockerfile = Dockerfile
|
||||
NuGet.Config = NuGet.Config
|
||||
migrate.ps1 = migrate.ps1
|
||||
remove-migration.ps1 = remove-migration.ps1
|
||||
EndProjectSection
|
||||
@@ -31,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nadeko.Medusa", "src\Nadeko
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.Generators", "src\NadekoBot.Generators\NadekoBot.Generators.csproj", "{92770AF3-83EE-49F1-A0BB-79124D19A13D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot.GrpcApiBase", "src\NadekoBot.GrpcApiBase\NadekoBot.GrpcApiBase.csproj", "{FB74B9EA-10B9-4542-ACB1-35523A95A587}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -80,6 +81,12 @@ Global
|
||||
{92770AF3-83EE-49F1-A0BB-79124D19A13D}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
|
||||
{92770AF3-83EE-49F1-A0BB-79124D19A13D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{92770AF3-83EE-49F1-A0BB-79124D19A13D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -92,6 +99,7 @@ Global
|
||||
{E685977E-31A4-46F4-A5D7-4E3E39E82E43} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
||||
{92770AF3-83EE-49F1-A0BB-79124D19A13D} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
||||
{2F4CF6D6-0C2F-4944-B204-9508CDA53195} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
||||
{FB74B9EA-10B9-4542-ACB1-35523A95A587} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5F3F555C-855F-4BE8-B526-D062D3E8ACA4}
|
||||
|
@@ -1,6 +0,0 @@
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
<add key="nadeko.bot" value="https://www.myget.org/F/nadeko/api/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>
|
@@ -1,23 +0,0 @@
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
nadeko:
|
||||
image: insert-image-name-here:latest
|
||||
depends_on:
|
||||
- redis
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
NadekoBot_RedisOptions: redis,name=nadeko
|
||||
#NadekoBot_ShardRunCommand: dotnet
|
||||
#NadekoBot_ShardRunArguments: /app/NadekoBot.dll {0} {1}
|
||||
volumes:
|
||||
- /srv/nadeko/conf:/app/conf:ro
|
||||
- /srv/nadeko/data:/app/data
|
||||
|
||||
redis:
|
||||
image: redis:4-alpine
|
||||
sysctls:
|
||||
- net.core.somaxconn=511
|
||||
command: redis-server --maxmemory 32M --maxmemory-policy volatile-lru
|
||||
volumes:
|
||||
- /srv/nadeko/redis-data:/data
|
@@ -1,5 +1,5 @@
|
||||
# Config
|
||||
`.config` is the new `.bce`, it gives you a fast and easy way to edit most bot settings/values. Use `.h .config` for explanation.
|
||||
`.config` gives you a fast and easy way to edit most bot settings/values. Use `.h .config` for explanation.
|
||||
|
||||
Use `.config` to see the list of editable config files
|
||||
Use `.config <config-name>` to see the list of settable properties on that config
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# How to contribute
|
||||
|
||||
1. Make Merge Requests to the [**v5 branch**](https://gitlab.com/nadeko/nadekobot/tree/v5)
|
||||
1. Make Merge Requests to the [**v5 branch**](https://gitlab.com/kwoth/nadekobot/tree/v5)
|
||||
2. Keep a single Merge Request to a single feature
|
||||
3. Fill out the MR template
|
||||
|
||||
|
@@ -1,27 +1,30 @@
|
||||
## Creds Guide
|
||||
|
||||
This document aims to guide you through the process of creating a Discord account for your bot
|
||||
(the Discord Bot application), and inviting that account into your Discord server.
|
||||
This guide will show you how to create your own discord bot, invite it to your server, and copy it's credentials to your `creds.yml` in order to run your bot.
|
||||
|
||||
- Start by opening your creds.yml
|
||||
- If you're on a windows installer version, click on the creds button next to your bot's RUN button.
|
||||
- If you're on linux from source or windows from source version, open `nadekobot/output/creds.yml`. Please use visual studio code, notepad++ or another code editor. Usage of notepad is discouraged.
|
||||
|
||||

|
||||
|
||||
- Go to [the Discord developer application page][DiscordApp].
|
||||
- Log in with your Discord account.
|
||||
- Click **New Application**.
|
||||
- Fill out the `Name` field however you like.
|
||||
- Go to the **Bot** tab on the left sidebar.
|
||||
- Click on the `Add a Bot` button and confirm that you do want to add a bot to this app.
|
||||
- **Optional:** Add bot's avatar and description.
|
||||
- Copy your Token to `creds.yml` as shown above.
|
||||
- Scroll down to the **`Privileged Gateway Intents`** section
|
||||
- **Enable the following:**
|
||||
1. Go to [the Discord developer application page][DiscordApp].
|
||||
2. Log in with your Discord account.
|
||||
3. Click **New Application**.
|
||||
3. Fill out the `Name` field however you like, accept the terms, and confirm.
|
||||
1. Go to the **Bot** tab on the left sidebar.
|
||||
1. Click on the `Add a Bot` button and confirm that you do want to add a bot to this app.
|
||||
1. **Optional:** Add bot's avatar and description.
|
||||
1. Copy your Token to `creds.yml` as shown above.
|
||||
1. Scroll down to the **`Privileged Gateway Intents`** section
|
||||
- Enable the following:
|
||||
- **PRESENCE INTENT**
|
||||
- **SERVER MEMBERS INTENT**
|
||||
- **MESSAGE CONTENT INTENT**
|
||||
|
||||
These are required for a number of features to function properly, and all should be on.
|
||||
|
||||
##### Getting Owner ID*(s)*:
|
||||
##### Getting Owner ID
|
||||
|
||||
- Go to your Discord server and attempt to mention yourself, but put a backslash at the start
|
||||
*(to make it slightly easier, add the backslash after the mention has been typed)*.
|
||||
|
@@ -7,10 +7,9 @@ Donations go a long way in helping us keep the project alive, and we appreciate
|
||||
|
||||
Donating to us also gives you the following benefits:
|
||||
|
||||
- A hoisted **Donators role** in our [Discord server][discord-server]
|
||||
- A hoisted **Patron** role in [Nadeko Discord server][discord-server]
|
||||
- Access to exclusive **#noticed** text and voice channels
|
||||
- **1000 flowers** on the public bot per dollar donated (after fees)
|
||||
- **Expressions** on the public bot for [Patreon pledges][patreon] of $5 or higher
|
||||
- **3000 flowers** on the public bot per dollar donated (after fees)
|
||||
|
||||
## Patreon
|
||||
|
||||
@@ -26,11 +25,11 @@ You can set up a monthly pledge on [Patreon][patreon] and support the project's
|
||||
You can also donate to us through [PayPal][paypal] for one-time donations using the button below, or by donating to `nadekodiscordbot@gmail.com`.
|
||||
|
||||
!!! Note
|
||||
Mention your Discord tag (Username#1234) in the payment note to receive flower rewards.
|
||||
Mention your Discord username or user id in the payment note to receive flower rewards.
|
||||
|
||||
[![img][paypal-button]][paypal]
|
||||
|
||||
[gitlab]: https://gitlab.com/nadeko/nadekobot
|
||||
[gitlab]: https://gitlab.com/kwoth/nadekobot
|
||||
[discord-server]: https://discord.nadeko.bot/
|
||||
[patreon]: https://www.patreon.com/nadekobot
|
||||
[patreon-button]: ./assets/patreon.png
|
||||
|
@@ -1,46 +1,76 @@
|
||||
# Setting up NadekoBot with Docker
|
||||
# Deploying NadekoBot with Docker: A Comprehensive Guide
|
||||
|
||||
# WORK IN PROGRESS
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
Ensure Docker and Docker Compose are installed on your system. If not, follow the official Docker guides for your specific operating system:
|
||||
|
||||
- [Docker Installation Guide](https://docs.docker.com/engine/install/)
|
||||
- [Docker Compose Installation Guide](https://docs.docker.com/compose/install/)
|
||||
|
||||
## Step-by-Step Installation
|
||||
|
||||
1. **Choose Your Workspace:** Select a directory where you'll set up your NadekoBot stack. Use your terminal to navigate to this directory. For the purpose of this guide, we'll use `/opt/stacks/nadekobot/` as an example, but you can choose any directory that suits your needs.
|
||||
|
||||
2. **Create a Docker Compose File:** In this directory, create a Docker Compose file named `docker-compose.yml`. You can use any text editor for this task. For instance, to use the `nano` editor, type `nano docker-compose.yml`.
|
||||
|
||||
3. **Configure Your Docker Compose File:** Populate your Docker Compose file with the following configuration:
|
||||
|
||||
1. Create a `/srv/nadeko` folder
|
||||
- `mkdir -p /srv/nadeko`
|
||||
2. Create a `docker-compose.yml`
|
||||
- nano `docker-compose.yml`
|
||||
- copy the following contents into it:
|
||||
##### docker-compose.yml
|
||||
```yml
|
||||
version: "3.7"
|
||||
services:
|
||||
nadeko:
|
||||
image: registry.gitlab.com/nadeko/nadekobot:latest
|
||||
depends_on:
|
||||
- redis
|
||||
image: registry.gitlab.com/kwoth/nadekobot:latest
|
||||
container_name: nadeko
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
NadekoBot_RedisOptions: redis,name=nadeko
|
||||
#NadekoBot_ShardRunCommand: dotnet
|
||||
#NadekoBot_ShardRunArguments: /app/NadekoBot.dll {0} {1}
|
||||
TZ: Europe/Rome
|
||||
volumes:
|
||||
- /srv/nadeko/conf/creds.yml:/app/creds.yml:ro
|
||||
- /srv/nadeko/data:/app/data
|
||||
|
||||
redis:
|
||||
image: redis:4-alpine
|
||||
sysctls:
|
||||
- net.core.somaxconn=511
|
||||
command: redis-server --maxmemory 32M --maxmemory-policy volatile-lru
|
||||
volumes:
|
||||
- /srv/nadeko/redis-data:/data
|
||||
- /opt/stacks/nadekobot/conf/creds.yml:/app/data/creds.yml
|
||||
- /opt/stacks/nadekobot/data:/app/data
|
||||
networks: {}
|
||||
```
|
||||
3. Save your file and run docker compose
|
||||
- `docker-compose up`
|
||||
4. Edit creds in `/srv/nadeko/conf/creds.yml`
|
||||
5. Run it again with
|
||||
- `docker-compose up`
|
||||
|
||||
### Updating
|
||||
- `cd /srv/nadeko`
|
||||
- `docker-compose pull`
|
||||
- `docker-compose up -d`
|
||||
4. **Prepare Your Credentials File:** Before running Docker Compose, ensure the `creds.yml` file exists in the `/opt/stacks/nadekobot/conf/` directory. If it's missing, create it using `touch /opt/stacks/nadekobot/conf/creds.yml`. You may need to use `sudo`. Remember to replace `/opt/stacks/nadekobot/` with your chosen directory.
|
||||
|
||||
5. **Edit Your Credentials File:** Populate the `creds.yml` file in `/opt/stacks/nadekobot/conf/creds.yml` with your bot's credentials. You can use any text editor for this task. For instance, to use the `nano` editor, type `nano /opt/stacks/nadekobot/conf/creds.yml`. You may need to use `sudo`. Again, replace `/opt/stacks/nadekobot/` with your chosen directory.
|
||||
|
||||
6. **Launch Your Bot:** Now, you're ready to run Docker Compose. Use the following command: `docker-compose up -d`.
|
||||
|
||||
## Keeping Your Bot Up-to-Date
|
||||
|
||||
There are two methods to update your NadekoBot:
|
||||
|
||||
### Manual Update
|
||||
|
||||
1. **Navigate to Your Directory:** Use `cd /path/to/your/directory` to go to the directory containing your Docker Compose file.
|
||||
|
||||
2. **Pull the Latest Images:** Use `docker-compose pull` to fetch the latest images.
|
||||
|
||||
3. **Restart Your Containers:** Use `docker-compose up -d` to restart the containers.
|
||||
|
||||
### Automatic Update with Watchtower
|
||||
|
||||
If you prefer an automated update process, consider using Watchtower. Watchtower automatically updates your Docker containers to the latest versions.
|
||||
|
||||
To use Watchtower with NadekoBot, you need to add a specific label to the service in your Docker Compose file. Here's how your Docker Compose file should look:
|
||||
|
||||
```yml
|
||||
services:
|
||||
nadeko:
|
||||
image: registry.gitlab.com/kwoth/nadekobot:latest
|
||||
container_name: nadeko
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
environment:
|
||||
TZ: Europe/Rome
|
||||
volumes:
|
||||
- /opt/stacks/nadekobot/conf/creds.yml:/app/data/creds.yml
|
||||
- /opt/stacks/nadekobot/data:/app/data
|
||||
networks: {}
|
||||
```
|
||||
|
||||
Remember to replace `/opt/stacks/nadekobot/` with your chosen directory in the Docker Compose file.
|
||||
|
||||
To install and run Watchtower, follow the guide provided by Containrrr:
|
||||
|
||||
- [Watchtower Installation and Usage Guide](https://containrrr.dev/watchtower/)
|
@@ -15,12 +15,13 @@
|
||||
|
||||
##### Compatible operating systems:
|
||||
|
||||
- Ubuntu: 18.04, 20.04, 22.04, 22.10
|
||||
- Ubuntu: 20.04, 22.04, 24.04
|
||||
- Mint: 19, 20, 21
|
||||
- Debian: 10, 11
|
||||
- CentOS: 7
|
||||
- openSUSE 15
|
||||
- ~~Fedora: 33, 34, 35~~ (Fedora is Pending Support)
|
||||
- Debian: 10, 11, 12
|
||||
- RockyLinux: 8, 9
|
||||
- AlmaLinux: 8, 9
|
||||
- openSUSE Leap: 15.5, 15.6 & Tumbleweed
|
||||
- Fedora: 38, 39, 40, 41, 42
|
||||
|
||||
## Linux From Source
|
||||
|
||||
@@ -28,7 +29,7 @@
|
||||
|
||||
Follow the following few steps only if you're migrating from v3. If not, skip to installation instructions.
|
||||
|
||||
Use the new installer script: `cd ~ && wget -N https://gitlab.com/Kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
Use the new installer script: `cd ~ && wget -N https://gitlab.com/kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
> - Install prerequisites (type `1` and press `enter`)
|
||||
> - Download (type `2` and press `enter`)
|
||||
> - Run (type `3` and press `enter`)
|
||||
@@ -38,7 +39,7 @@ Use the new installer script: `cd ~ && wget -N https://gitlab.com/Kwoth/nadeko-
|
||||
|
||||
Open Terminal (if you're on an installation with a window manager) and navigate to the location where you want to install the bot (for example `cd ~`)
|
||||
|
||||
1. Download and run the **new** installer script `cd ~ && wget -N https://gitlab.com/Kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
1. Download and run the **new** installer script `cd ~ && wget -N https://gitlab.com/kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
2. Install prerequisites (type `1` and press enter)
|
||||
3. Download the bot (type `2` and press enter)
|
||||
4. Exit the installer (type `6` and press enter)
|
||||
@@ -50,13 +51,13 @@ Open Terminal (if you're on an installation with a window manager) and navigate
|
||||
- `CTRL` + `X`
|
||||
- `Y`
|
||||
- `Enter`
|
||||
8. Run the installer script again `cd ~ && wget -N https://gitlab.com/Kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
8. Run the installer script again `cd ~ && wget -N https://gitlab.com/kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
9. Run the bot (type `3` and press enter)
|
||||
|
||||
##### Source Update Instructions
|
||||
|
||||
1. ⚠ Stop the bot ⚠
|
||||
2. Update and run the **new** installer script `cd ~ && wget -N https://gitlab.com/Kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
2. Update and run the **new** installer script `cd ~ && wget -N https://gitlab.com/kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
3. Update the bot (type `2` and press enter)
|
||||
4. Run the bot (type `3` and press enter)
|
||||
5. 🎉
|
||||
@@ -69,16 +70,16 @@ Open Terminal (if you're on an installation with a window manager) and navigate
|
||||
|
||||
1. (Optional) Installing Redis
|
||||
- ubuntu installation command: `sudo apt-get install redis-server`
|
||||
2. Playing music requires `ffmpeg`, `libopus`, `libsodium` and `youtube-dl` (which in turn requires python3)
|
||||
- ubuntu installation command: `sudo apt-get install ffmpeg libopus0 opus-tools libopus-dev libsodium-dev -y`
|
||||
2. Playing music requires `ffmpeg`, `libopus`, `libsodium` and `yt-dlp` (which in turn requires python3)
|
||||
- Ubuntu installation command: `sudo apt-get install ffmpeg libopus0 opus-tools libopus-dev libsodium-dev -y`
|
||||
- yt-dlp installation command: `sudo wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -O /usr/local/bin/yt-dlp && sudo chmod a+rx /usr/local/bin/yt-dlp`
|
||||
3. Make sure your python is version 3+ with `python --version`
|
||||
- if it's not, you can install python 3 and make it the default with: `sudo apt-get install python3.8 python-is-python3`
|
||||
|
||||
*You can use nadeko bash script [prerequisites installer](https://gitlab.com/Kwoth/nadeko-bash-installer/-/blob/v5/n-prereq.sh) as a reference*
|
||||
*You can use nadeko bash script [prerequisites installer](https://gitlab.com/kwoth/nadeko-bash-installer/-/blob/v5/n-prereq.sh) as a reference*
|
||||
|
||||
##### Installation Instructions
|
||||
|
||||
1. Download the latest release from <https://gitlab.com/nadeko/nadekobot/-/releases>
|
||||
1. Download the latest release from <https://gitlab.com/kwoth/nadekobot/-/releases>
|
||||
- Look for the file called "X.XX.X-linux-x64-build.tar" (where X.XX.X is a series of numbers) and download it
|
||||
2. Untar it
|
||||
- ⚠ Make sure that you change X.XX.X to the same series of numbers as in step 1!
|
||||
@@ -102,7 +103,7 @@ Open Terminal (if you're on an installation with a window manager) and navigate
|
||||
##### Release Update Instructions
|
||||
|
||||
1. Stop the bot
|
||||
2. Download the latest release from <https://gitlab.com/nadeko/nadekobot/-/releases>
|
||||
2. Download the latest release from <https://gitlab.com/kwoth/nadekobot/-/releases>
|
||||
- Look for the file called "x.x.x-linux-x64-build.tar" (where `X.X.X` is a version, for example 3.0.4) and download it
|
||||
3. Untar it
|
||||
- ⚠ Make sure that you change `X.X.X` to the same series of numbers as in step 2!
|
||||
@@ -267,7 +268,7 @@ This method is similar to the one above, but requires one extra step, with the a
|
||||
echo '#!/bin/bash'
|
||||
echo ""
|
||||
echo "echo \"Running NadekoBot in the background with auto restart\"
|
||||
youtube-dl -U
|
||||
yt-dlp -U
|
||||
|
||||
# If you want Nadeko to be compiled prior to every startup, uncomment the lines
|
||||
# below. Note that it's not necessary unless you are personally modifying the
|
||||
@@ -299,7 +300,7 @@ This method is similar to the one above, but requires one extra step, with the a
|
||||
|
||||
echo \"Waiting for 5 seconds...\"
|
||||
sleep 5
|
||||
youtube-dl -U
|
||||
yt-dlp -U
|
||||
echo \"Restarting NadekoBot...\"
|
||||
done
|
||||
|
||||
|
@@ -31,7 +31,7 @@ sudo ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/
|
||||
|
||||
##### Installation Instructions
|
||||
|
||||
1. Download and run the **new** installer script `cd ~ && wget -N https://gitlab.com/Kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
1. Download and run the **new** installer script `cd ~ && wget -N https://gitlab.com/kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
2. Install prerequisites (type `1` and press enter)
|
||||
3. Download the bot (type `2` and press enter)
|
||||
4. Exit the installer in order to set up your `creds.yml`
|
||||
@@ -49,7 +49,7 @@ sudo ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/
|
||||
##### Update Instructions
|
||||
|
||||
1. ⚠ Stop the bot
|
||||
2. Update and run the **new** installer script `cd ~ && wget -N https://gitlab.com/Kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
2. Update and run the **new** installer script `cd ~ && wget -N https://gitlab.com/kwoth/nadeko-bash-installer/-/raw/v5/linuxAIO.sh && bash linuxAIO.sh`
|
||||
3. Update the bot (type `2` and press enter)
|
||||
4. Run the bot (type `3` and press enter)
|
||||
5. 🎉
|
||||
@@ -60,7 +60,7 @@ sudo ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/
|
||||
|
||||
##### Installation Instructions
|
||||
|
||||
1. Download the latest release from <https://gitlab.com/nadeko/nadekobot/-/releases>
|
||||
1. Download the latest release from <https://gitlab.com/kwoth/nadekobot/-/releases>
|
||||
- Look for the file called "X.XX.X-linux-x64-build.tar" (where X.XX.X is a series of numbers) and download it
|
||||
2. Untar it
|
||||
⚠ Make sure that you change X.XX.X to the same series of numbers as in step 1!
|
||||
@@ -84,7 +84,7 @@ sudo ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/
|
||||
##### Update Instructions
|
||||
|
||||
1. Stop the bot
|
||||
2. Download the latest release from <https://gitlab.com/nadeko/nadekobot/-/releases>
|
||||
2. Download the latest release from <https://gitlab.com/kwoth/nadekobot/-/releases>
|
||||
- Look for the file called "X.XX.X-linux-x64-build.tar" (where X.XX.X is a series of numbers) and download it
|
||||
3. Untar it
|
||||
⚠ Make sure that you change X.XX.X to the same series of numbers as in step 2!
|
||||
|
@@ -1,11 +1,11 @@
|
||||
## Setting Up NadekoBot on Windows With the Updater
|
||||
|
||||
| Table of Contents|
|
||||
| :---------------------------------------------------------------------------------------------------------------------------|
|
||||
| [Prerequisites](#prerequisites) |
|
||||
| [Setup](#setup) |
|
||||
| [Starting the Bot](#starting-the-bot) |
|
||||
| [Updating Nadeko](#updating-nadeko) |
|
||||
| :-|
|
||||
| [Prerequisites](#prerequisites) |
|
||||
| [Setup](#setup) |
|
||||
| [Starting the Bot](#starting-the-bot) |
|
||||
| [Updating Nadeko](#updating-nadeko) |
|
||||
| [Manually Installing the Prerequisites from the Updater](#music-prerequisites) |
|
||||
|
||||
*Note: If you want to make changes to Nadeko's source code, please follow the [From Source](#windows-from-source) guide instead.*
|
||||
@@ -13,7 +13,6 @@
|
||||
#### Prerequisites
|
||||
|
||||
- Windows 10 or later (64-bit)
|
||||
- [Create a Discord Bot application and invite the bot to your server](../creds-guide.md)
|
||||
|
||||
**Optional**
|
||||
|
||||
@@ -29,8 +28,7 @@
|
||||

|
||||
- Click on **`DOWNLOAD`** at the lower right
|
||||

|
||||
- **Note: Redis is optional. install Redis manually here: [Redis] Download and run the **`.msi`** file.**
|
||||
- If you will use the music module, click on **`Install`** next to **`FFMPEG`** and **`Youtube-DLP`**.
|
||||
- If you want to use the music module, click on **`Install`** next to **`FFMPEG`** and **`Youtube-DLP`**.
|
||||
- If any dependencies fail to install, you can temporarily disable your Windows Defender/AV until you install them. If you don't want to, then read [the last section of this guide](#Manual-Prerequisite-Installation).
|
||||
- When installation is finished, click on **`CREDS`** to the left of **`RUN`** at the lower right.
|
||||
- Follow the guide on how to [Set up the creds.yml](../../creds-guide) file.
|
||||
@@ -39,8 +37,6 @@
|
||||
|
||||
- Either click on **`RUN`** button in the updater or run the bot via its desktop shortcut.
|
||||
|
||||
### If you get a "No owner channels created..." message. Please follow the creds guide again [**HERE**](../../creds-guide).
|
||||
|
||||
#### Updating Nadeko
|
||||
|
||||
- Make sure Nadeko is closed and not running
|
||||
@@ -52,67 +48,6 @@
|
||||
- Launch the bot
|
||||
- You've updated and are running again, easy as that!
|
||||
|
||||
#### Manual Prerequisite Installation
|
||||
|
||||
You can still install them manually:
|
||||
|
||||
- [Redis] (OPTIONAL) - Download and run the **`.msi`** file
|
||||
- [ffmpeg-32bit] | [ffmpeg-64bit] - Download the **appropriate version** for your system (32 bit if you're running a 32 bit OS, or 64 if you're running a 64bit OS). Unzip it, and move `ffmpeg.exe` to a path that's in your PATH environment variable. If you don't know what that is, then just move the `ffmpeg.exe` file to NadekoBot/system
|
||||
- [youtube-dlp] - Click to download the `yt-dlp.exe` file then put `yt-dlp.exe` in a path that's in your PATH environment variable. If you don't know what that is, then just move the `yt-dlp.exe` file to NadekoBot/system
|
||||
|
||||
## **⚠ IF YOU ARE FOLLOWING THE GUIDE ABOVE, IGNORE THIS SECTION ⚠**
|
||||
|
||||
### Windows From Source
|
||||
|
||||
##### Prerequisites
|
||||
|
||||
**Install these before proceeding or your bot will not work!**
|
||||
- [.net 7](https://dotnet.microsoft.com/en-us/download) - needed to compile and run the bot
|
||||
- [git](https://git-scm.com/downloads) - needed to clone the repository (you can also download the zip manually and extract it, but this guide assumes you're using git)
|
||||
- [Redis] (OPTIONAL)- to cache things needed by some features and persist through restarts
|
||||
|
||||
##### Installation Instructions
|
||||
|
||||
Open PowerShell (press windows button on your keyboard and type powershell, it should show up; alternatively, right click the start menu and select Windows PowerShell), and navigate to the location where you want to install the bot (for example `cd ~/Desktop/`)
|
||||
|
||||
1. `git clone https://gitlab.com/nadeko/nadekobot -b v5 --depth 1`
|
||||
2. `cd nadekobot`
|
||||
3. `dotnet publish -c Release -o output/ src/NadekoBot/`
|
||||
4. `cd output`
|
||||
5. `cp creds_example.yml creds.yml`
|
||||
6. Open `creds.yml` with your favorite text editor (Please don't use Notepad or WordPad. You can use Notepad++, VSCode, Atom, Sublime, or something similar)
|
||||
7. [Enter your bot's token](#creds-guide)
|
||||
8. Run the bot `dotnet NadekoBot.dll`
|
||||
9. 🎉
|
||||
|
||||
##### Update Instructions
|
||||
|
||||
Open PowerShell as described above and run the following commands:
|
||||
|
||||
1. Stop the bot
|
||||
- ⚠️ Make sure you don't have your database, credentials or any other nadekobot folder open in some application, this might prevent some of the steps from executing succesfully
|
||||
2. Navigate to your bot's folder, example:
|
||||
- `cd ~/Desktop/nadekobot`
|
||||
3. Pull the new version
|
||||
- `git pull`
|
||||
- ⚠️ If this fails, you may want to stash or remove your code changes if you don't know how to resolve merge conflicts
|
||||
4. **Backup** old output in case your data is overwritten
|
||||
- `cp -r -fo output/ output-old`
|
||||
5. Build the bot again
|
||||
- `dotnet publish -c Release -o output/ src/NadekoBot/`
|
||||
6. Remove old strings and aliases to avoid overwriting the updated versions of those files
|
||||
- ⚠ If you've modified said files, back them up instead
|
||||
- `rm output-old/data/aliases.yml`
|
||||
- `rm -r output-old/data/strings`
|
||||
7. Copy old data
|
||||
- `cp -Recurse .\output-old\data\ .\output\ -Force`
|
||||
8. Copy creds.yml
|
||||
- `cp output-old/creds.yml output/`
|
||||
9. Run the bot
|
||||
- `cd output`
|
||||
- `dotnet NadekoBot.dll`
|
||||
|
||||
🎉 Enjoy
|
||||
|
||||
#### Music prerequisites
|
||||
In order to use music commands, you need ffmpeg and yt-dlp installed.
|
||||
@@ -127,4 +62,4 @@ In order to use music commands, you need ffmpeg and yt-dlp installed.
|
||||
[Visual C++ 2017 (x64)]: https://aka.ms/vs/15/release/vc_redist.x64.exe
|
||||
[ffmpeg-32bit]: https://cdn.nadeko.bot/dl/ffmpeg-32.zip
|
||||
[ffmpeg-64bit]: https://cdn.nadeko.bot/dl/ffmpeg-64.zip
|
||||
[youtube-dlp]: https://github.com/yt-dlp/yt-dlp/releases
|
||||
[youtube-dlp]: https://github.com/yt-dlp/yt-dlp/releases
|
77
docs/guides/windows-source-guide.md
Normal file
77
docs/guides/windows-source-guide.md
Normal file
@@ -0,0 +1,77 @@
|
||||
## Setting Up NadekoBot on Windows from source
|
||||
|
||||
1. Prerequisites
|
||||
|
||||
- Windows 10 or later (64-bit)
|
||||
- [.net 8 sdk](https://dotnet.microsoft.com/download/dotnet/8.0)
|
||||
- If you want nadeko to play music: [Visual C++ 2010 (x86)] and [Visual C++ 2017 (x64)] (both are required, you may install them later)
|
||||
- [git](https://git-scm.com/downloads) - needed to clone the repository (you can also download the zip manually and extract it, but this guide assumes you're using git)
|
||||
- **Optional** Any code editor, for example [Visual Studio Code](https://code.visualstudio.com/Download)
|
||||
- You'll need to at least modify creds.yml, notepad is inadequate
|
||||
|
||||
|
||||
##### Installation Instructions
|
||||
|
||||
Open PowerShell (press windows button on your keyboard and type powershell, it should show up; alternatively, right click the start menu and select Windows PowerShell), and
|
||||
|
||||
|
||||
0. Navigate to the location where you want to install the bot
|
||||
- for example, type `cd ~/Desktop/` and press enter
|
||||
1. `git clone https://gitlab.com/kwoth/nadekobot -b v5 --depth 1`
|
||||
2. `cd nadekobot`
|
||||
3. `dotnet publish -c Release -o output/ src/NadekoBot/`
|
||||
4. `cd output`
|
||||
5. `cp creds_example.yml creds.yml`
|
||||
6. "You're done installing, you may now proceed to set up your bot's credentials by following the [#creds-guide]
|
||||
- Once done, come back here and run the last command
|
||||
8. Run the bot `dotnet NadekoBot.dll`
|
||||
9. 🎉 Enjoy
|
||||
|
||||
##### Update Instructions
|
||||
|
||||
Open PowerShell as described above and run the following commands:
|
||||
|
||||
1. Stop the bot
|
||||
- ⚠️ Make sure you don't have your database, credentials or any other nadekobot folder open in some application, this might prevent some of the steps from executing succesfully
|
||||
2. Navigate to your bot's folder, example:
|
||||
- `cd ~/Desktop/nadekobot`
|
||||
3. Pull the new version, and make sure you're on the v5 branch
|
||||
- *⚠️ If you're on v4, you must run these commands, if not, you may skip them.*
|
||||
- `git remote set-branches origin '*'`
|
||||
- `git fetch -v --depth=1`
|
||||
- `git checkout v5`
|
||||
- `git pull`
|
||||
- ⚠️ If this fails, you may want to stash or remove your code changes if you don't know how to resolve merge conflicts
|
||||
4. **Backup** old output in case your data is overwritten
|
||||
- `cp -r -fo output/ output-old`
|
||||
5. Build the bot again
|
||||
- `dotnet publish -c Release -o output/ src/NadekoBot/`
|
||||
6. Remove old strings and aliases to avoid overwriting the updated versions of those files
|
||||
- ⚠ If you've modified said files, back them up instead
|
||||
- `rm output-old/data/aliases.yml`
|
||||
- `rm -r output-old/data/strings`
|
||||
7. Copy old data, and new strings
|
||||
- `cp -Recurse -Force .\output-old\data\ .\output\`
|
||||
- `cp -Recurse -Force src/NadekoBot/data/strings/ output/data/`
|
||||
8. Copy creds.yml
|
||||
- `cp output-old/creds.yml output/`
|
||||
9. Run the bot
|
||||
- `cd output`
|
||||
- `dotnet NadekoBot.dll`
|
||||
|
||||
🎉 Enjoy
|
||||
|
||||
#### Music prerequisites
|
||||
In order to use music commands, you need ffmpeg and yt-dlp installed.
|
||||
- [ffmpeg-32bit] | [ffmpeg-64bit] - Download the **appropriate version** for your system (32 bit if you're running a 32 bit OS, or 64 if you're running a 64bit OS). Unzip it, and move `ffmpeg.exe` to a path that's in your PATH environment variable. If you don't know what that is, just move the `ffmpeg.exe` file to `NadekoBot/output`.
|
||||
- [youtube-dlp] - Click to download the `yt-dlp.exe` file, then move `yt-dlp.exe` to a path that's in your PATH environment variable. If you don't know what that is, just move the `yt-dlp.exe` file to `NadekoBot/system`.
|
||||
|
||||
[Updater]: https://dl.nadeko.bot/v3/
|
||||
[Notepad++]: https://notepad-plus-plus.org/
|
||||
[.net]: https://dotnet.microsoft.com/download/dotnet/8.0
|
||||
[Redis]: https://github.com/MicrosoftArchive/redis/releases/download/win-3.0.504/Redis-x64-3.0.504.msi
|
||||
[Visual C++ 2010 (x86)]: https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe
|
||||
[Visual C++ 2017 (x64)]: https://aka.ms/vs/15/release/vc_redist.x64.exe
|
||||
[ffmpeg-32bit]: https://cdn.nadeko.bot/dl/ffmpeg-32.zip
|
||||
[ffmpeg-64bit]: https://cdn.nadeko.bot/dl/ffmpeg-64.zip
|
||||
[youtube-dlp]: https://github.com/yt-dlp/yt-dlp/releases
|
@@ -16,6 +16,7 @@ To self-host your own Nadeko, use the guides below:
|
||||
- [:material-microsoft-windows: Windows guide][windows-guide]
|
||||
- [:material-linux: Linux guide][linux-guide]
|
||||
- [:material-apple: Mac OS guide][macos-guide]
|
||||
- [:material-microsoft-windows: Windows (from source) guide][windows-source-guide]
|
||||
|
||||
In case you need any help, join our [Discord server][discord-server] where we may provide support.
|
||||
|
||||
@@ -32,10 +33,11 @@ If you're unsure whether something is an issue, ask in our support server first.
|
||||
[invite]: https://invite.nadeko.bot/
|
||||
[commands]: https://nadeko.bot/commands/
|
||||
[windows-guide]: ./guides/windows-guide.md
|
||||
[windows-source-guide]: ./guides/windows-source-guide.md
|
||||
[linux-guide]: ./guides/linux-guide.md
|
||||
[macos-guide]: ./guides/osx-guide.md
|
||||
[from-source-guide]: ./guides/from-source.md
|
||||
[discord-server]: https://discord.nadeko.bot/
|
||||
[gitlab]: https://gitlab.com/nadeko/nadekobot
|
||||
[issues]: https://gitlab.com/nadeko/nadekobot/issues
|
||||
[gitlab]: https://gitlab.com/kwoth/nadekobot
|
||||
[issues]: https://gitlab.com/kwoth/nadekobot/issues
|
||||
[donate]: ./donate.md
|
||||
|
@@ -1,14 +1,61 @@
|
||||
# Creating A Medusa
|
||||
|
||||
## Theory
|
||||
## Getting started
|
||||
|
||||
### Introduction
|
||||
This section will guide you through how to create a simple custom medusa. You can find the entirety of this code hosted [here](https://gitlab.com/nadeko/example_medusa)
|
||||
|
||||
#### Prerequisite
|
||||
- [.net8 sdk](https://dotnet.microsoft.com/en-us/download) installed
|
||||
- Optional: use [vscode](https://code.visualstudio.com/download) to write code
|
||||
|
||||
#### Guide
|
||||
|
||||
- Open your favorite terminal and navigate to a folder where you will keep your project .
|
||||
|
||||
- Create a new folder and move into it
|
||||
- `mkdir example_medusa `
|
||||
- `cd example_medusa`
|
||||
|
||||
- Install nadeko-medusa template
|
||||
- `dotnet new install nadeko-medusa`
|
||||
|
||||
- Make a new Nadeko Medusa project
|
||||
- `dotnet new nadeko-medusa`
|
||||
|
||||
### Build it
|
||||
|
||||
- Build your Medusa into a dll that Nadeko can load. In your terminal, type:
|
||||
- `dotnet publish -o bin/medusae/example_medusa /p:DebugType=embedded`
|
||||
|
||||
- Done. You can now try it out in action.
|
||||
|
||||
### Try it out
|
||||
|
||||
- Copy the `bin/medusae/example_medusa` folder into your NadekoBot's `data/medusae/` folder. (Nadeko version 4.1.0+)
|
||||
|
||||
- Load it with `.meload example_medusa`
|
||||
|
||||
- In the channel your bot can see, run the following commands to try it out
|
||||
- `.hello` and
|
||||
- `.hello @<someone>`
|
||||
|
||||
- Check its information with
|
||||
- `.meinfo example_medusa`
|
||||
|
||||
- Unload it
|
||||
- `.meunload example_medusa`
|
||||
|
||||
- :tada: Congrats! You've just made your first medusa! :tada:
|
||||
|
||||
|
||||
|
||||
## Theory
|
||||
|
||||
Medusa system allows you to write independent medusae (known as "modules", "cogs" or "plugins" in other software) which you can then load, unload and update at will without restarting the bot.
|
||||
|
||||
The system itself borrows some design from the current way Nadeko's Modules are written but mostly from never-released `Ayu.Commands` system which was designed to be used for a full Nadeko v3 rewrite.
|
||||
|
||||
The medusa base classes used for development are open source [here](https://gitlab.com/nadeko/nadekobot/-/tree/v5/src/Nadeko.Medusa) in case you need reference, as there is no generated documentation at the moment.
|
||||
The medusa base classes used for development are open source [here](https://gitlab.com/kwoth/nadekobot/-/tree/v5/src/Nadeko.Medusa) in case you need reference, as there is no generated documentation at the moment.
|
||||
|
||||
### Term list
|
||||
|
||||
@@ -99,9 +146,9 @@ If you don't want any auxiliary files, and you don't want to bother making new .
|
||||
|
||||
If you update your response strings .yml file(s) while the medusa is loaded and running, running `.stringsreload` will reload the responses without the need to reload the medusa or restart the bot.
|
||||
|
||||
#### Config
|
||||
#### Bot medusa config file
|
||||
|
||||
- Medusa config is kept in `medusae/medusa.yml` file
|
||||
- Medusa config is kept in `data/medusae/medusa.yml` file in NadekoBot installation folder
|
||||
- At the moment this config only keeps track of which medusae are currently loaded (they will also be always loaded at startup)
|
||||
- If a medusa is causing issues and you're unable to unload it, you can remove it from the `loaded:` list in this config file and restart the bot. It won't be loaded next time the bot is started up
|
||||
|
||||
@@ -115,138 +162,4 @@ To make sure your medusa can be properly unloaded/reloaded you must:
|
||||
|
||||
- If you are still having issues, you can always run `.meunload` followed by a bot restart, or if you want to find what is causing the medusa unloadability issues, you can check the [microsoft's assembly unloadability debugging guide](https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability)
|
||||
|
||||
## Practice
|
||||
|
||||
This section will guide you through how to create a simple custom medusa. You can find the entirety of this code hosted [here](https://gitlab.com/nadeko/example_medusa)
|
||||
|
||||
#### Prerequisite
|
||||
- [.net6 sdk](https://dotnet.microsoft.com/en-us/download) installed
|
||||
- Optional: use [vscode](https://code.visualstudio.com/download) to write code
|
||||
|
||||
#### Guide
|
||||
|
||||
|
||||
- Open your favorite terminal and navigate to a folder where you will keep your project .
|
||||
|
||||
- Create a new folder
|
||||
- `mkdir example_medusa`
|
||||
- Create a new .net class library
|
||||
- `dotnet new classlib`
|
||||
- Open the current folder with your favorite editor/IDE. In this case we'll use VsCode
|
||||
- `code .`
|
||||
- Remove the `Class1.cs` file
|
||||
- Replace the contents of the `.csproj` file with the following contents
|
||||
```xml
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<!-- Reduces some boilerplate in your .cs files -->
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
<!-- Use latest .net features -->
|
||||
<LangVersion>preview</LangVersion>
|
||||
<EnablePreviewFeatures>true</EnablePreviewFeatures>
|
||||
<GenerateRequiresPreviewFeaturesAttribute>true</GenerateRequiresPreviewFeaturesAttribute>
|
||||
|
||||
<!-- tell .net that this library will be used as a plugin -->
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Base medusa package. You MUST reference this in order to have a working medusa -->
|
||||
<!-- Also, this package comes from MyGet, which requires you to have a NuGet.Config file next to your .csproj -->
|
||||
<PackageReference Include="Nadeko.Medusa" Version="4.3.9">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
<!-- Note: If you want to use NadekoBot services etc... You will have to manually clone
|
||||
the https://gitlab.com/nadeko/nadekobot repo locally and reference the NadekoBot.csproj because there is no NadekoBot package atm.
|
||||
It is strongly recommended that you checkout a specific tag which matches your version of nadeko,
|
||||
as there could be breaking changes even between minor versions of NadekoBot.
|
||||
For example if you're running NadekoBot 4.1.0 locally for which you want to create a medusa for,
|
||||
you should do "git checkout 4.1.0" in your NadekoBot solution and then reference the NadekoBot.csproj
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Copy shortcut and full strings to output (if they exist) -->
|
||||
<ItemGroup>
|
||||
<None Update="res.yml;cmds.yml;strings/**">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
```
|
||||
- Create a `MySnek.cs` file and add the following contents
|
||||
```cs
|
||||
using Nadeko.Snake;
|
||||
using NadekoBot;
|
||||
using Discord;
|
||||
|
||||
public sealed class MySnek : Snek
|
||||
{
|
||||
[cmd]
|
||||
public async Task Hello(AnyContext ctx)
|
||||
{
|
||||
await ctx.Channel.SendMessageAsync($"Hello everyone!");
|
||||
}
|
||||
|
||||
[cmd]
|
||||
public async Task Hello(AnyContext ctx, IUser target)
|
||||
{
|
||||
await ctx.ConfirmLocalizedAsync("hello", target);
|
||||
}
|
||||
}
|
||||
```
|
||||
- Create `res.yml` and `cmds.yml` files with the following contents
|
||||
`res.yml`
|
||||
```yml
|
||||
medusa.description: "This is my medusa's description"
|
||||
hello: "Hello {0}, from res.yml!"
|
||||
```
|
||||
|
||||
`cmds.yml`
|
||||
```yml
|
||||
hello:
|
||||
desc: "This is a basic hello command"
|
||||
args:
|
||||
- ""
|
||||
- "@Someone"
|
||||
```
|
||||
|
||||
- Add `NuGet.Config` file which will let you use the base Nadeko.Medusa package. This file should always look like this and you shouldn't change it
|
||||
|
||||
```xml
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||
<add key="nadeko.bot" value="https://www.myget.org/F/nadeko/api/v3/index.json" protocolVersion="3" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
### Build it
|
||||
|
||||
- Build your Medusa into a dll that Nadeko can load. In your terminal, type:
|
||||
- `dotnet publish -o bin/medusae/example_medusa /p:DebugType=embedded`
|
||||
|
||||
- Done. You can now try it out in action.
|
||||
|
||||
### Try it out
|
||||
|
||||
- Copy the `bin/medusae/example_medusa` folder into your NadekoBot's `data/medusae/` folder. (Nadeko version 4.1.0+)
|
||||
|
||||
- Load it with `.meload example_medusa`
|
||||
|
||||
- In the channel your bot can see, run the following commands to try it out
|
||||
- `.hello` and
|
||||
- `.hello @<someone>`
|
||||
|
||||
- Check its information with
|
||||
- `.meinfo example_medusa`
|
||||
|
||||
- Unload it
|
||||
- `.meunload example_medusa`
|
||||
|
||||
- Congrats! You've just made your first medusa!
|
||||
|
@@ -75,6 +75,7 @@ nav:
|
||||
- Windows Guide: guides/windows-guide.md
|
||||
- Linux Guide: guides/linux-guide.md
|
||||
- OSX Guide: guides/osx-guide.md
|
||||
- Windows Guide (from source): guides/windows-source-guide.md
|
||||
- Docker Guide (unsupported): guides/docker-guide.md
|
||||
- Commands:
|
||||
- Readme: commands-readme.md
|
||||
|
@@ -1,4 +0,0 @@
|
||||
dotnet ef migrations remove -c SqliteContext -f
|
||||
dotnet ef migrations remove -c PostgreSqlContext -f
|
||||
dotnet ef migrations remove -c MysqlContext -f
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using Discord;
|
||||
using NadekoBot;
|
||||
|
||||
namespace NadekoBot.Medusa;
|
||||
|
||||
|
@@ -9,9 +9,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Discord.Net.Core" Version="3.204.0" />
|
||||
<PackageReference Include="Discord.Net.Core" Version="3.16.0" />
|
||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||
<PackageReference Include="YamlDotNet" Version="15.1.2" />
|
||||
<PackageReference Include="YamlDotNet" Version="15.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Version)' == '' ">
|
||||
|
@@ -14,7 +14,7 @@
|
||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="15.1.2" />
|
||||
<PackageReference Include="YamlDotNet" Version="15.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -417,8 +417,7 @@ namespace NadekoBot.Coordinator
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
if (shardId >= _shardStatuses.Length)
|
||||
throw new ArgumentOutOfRangeException(nameof(shardId));
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(shardId, _shardStatuses.Length);
|
||||
|
||||
return _shardStatuses[shardId];
|
||||
}
|
||||
|
184
src/NadekoBot.Generators/GrpcApiPermGenerator.cs
Normal file
184
src/NadekoBot.Generators/GrpcApiPermGenerator.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
#nullable enable
|
||||
using System.CodeDom.Compiler;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace NadekoBot.Generators
|
||||
{
|
||||
public readonly record struct MethodPermData
|
||||
{
|
||||
public readonly ImmutableArray<(string Name, string Value)> MethodPerms;
|
||||
public readonly ImmutableArray<string> NoAuthRequired;
|
||||
|
||||
public MethodPermData(ImmutableArray<(string Name, string Value)> methodPerms,
|
||||
ImmutableArray<string> noAuthRequired)
|
||||
{
|
||||
MethodPerms = methodPerms;
|
||||
NoAuthRequired = noAuthRequired;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Generator]
|
||||
public class GrpcApiPermGenerator : IIncrementalGenerator
|
||||
{
|
||||
public const string GRPC_API_PERM_ATTRIBUTE =
|
||||
"""
|
||||
namespace NadekoBot.GrpcApi;
|
||||
|
||||
[System.AttributeUsage(System.AttributeTargets.Method)]
|
||||
public class GrpcApiPermAttribute : System.Attribute
|
||||
{
|
||||
public GuildPerm Value { get; }
|
||||
public GrpcApiPermAttribute(GuildPerm value) => Value = value;
|
||||
}
|
||||
""";
|
||||
|
||||
public const string GRPC_NO_AUTH_REQUIRED_ATTRIBUTE =
|
||||
"""
|
||||
namespace NadekoBot.GrpcApi;
|
||||
|
||||
[System.AttributeUsage(System.AttributeTargets.Method)]
|
||||
public class GrpcNoAuthRequiredAttribute : System.Attribute
|
||||
{
|
||||
}
|
||||
""";
|
||||
|
||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||
{
|
||||
context.RegisterPostInitializationOutput(ctx => ctx.AddSource("GrpcApiPermAttribute.cs",
|
||||
SourceText.From(GRPC_API_PERM_ATTRIBUTE, Encoding.UTF8)));
|
||||
|
||||
context.RegisterPostInitializationOutput(ctx => ctx.AddSource("GrpcNoAuthRequiredAttribute.cs",
|
||||
SourceText.From(GRPC_NO_AUTH_REQUIRED_ATTRIBUTE, Encoding.UTF8)));
|
||||
|
||||
var perms = context.SyntaxProvider
|
||||
.ForAttributeWithMetadataName(
|
||||
"NadekoBot.GrpcApi.GrpcApiPermAttribute",
|
||||
predicate: static (s, _) => s is MethodDeclarationSyntax,
|
||||
transform: static (ctx, _) => GetMethodSemanticTargets(ctx.SemanticModel, ctx.TargetNode))
|
||||
.Where(static m => m is not null)
|
||||
.Select(static (x, _) => x!.Value)
|
||||
.Collect();
|
||||
|
||||
|
||||
var all = context.SyntaxProvider
|
||||
.ForAttributeWithMetadataName(
|
||||
"NadekoBot.GrpcApi.GrpcNoAuthRequiredAttribute",
|
||||
predicate: static (s, _) => s is MethodDeclarationSyntax,
|
||||
transform: static (ctx, _) => GetNoAuthMethodName(ctx.SemanticModel, ctx.TargetNode))
|
||||
.Collect()
|
||||
.Combine(perms)
|
||||
.Select((x, _) => new MethodPermData(x.Right, x.Left));
|
||||
|
||||
context.RegisterSourceOutput(all,
|
||||
static (spc, source) => Execute(source, spc));
|
||||
}
|
||||
|
||||
private static string GetNoAuthMethodName(SemanticModel model, SyntaxNode node)
|
||||
=> ((MethodDeclarationSyntax)node).Identifier.Text;
|
||||
|
||||
private static (string Name, string Value)? GetMethodSemanticTargets(SemanticModel model, SyntaxNode node)
|
||||
{
|
||||
var method = (MethodDeclarationSyntax)node;
|
||||
|
||||
var name = method.Identifier.Text;
|
||||
var attr = method.AttributeLists
|
||||
.SelectMany(x => x.Attributes)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (attr is null)
|
||||
return null;
|
||||
|
||||
return (name, attr.ArgumentList?.Arguments[0].ToString() ?? "__missing_perm__");
|
||||
}
|
||||
|
||||
private static void Execute(MethodPermData data, SourceProductionContext ctx)
|
||||
{
|
||||
using (var stringWriter = new StringWriter())
|
||||
using (var sw = new IndentedTextWriter(stringWriter))
|
||||
{
|
||||
sw.WriteLine("using System.Collections.Frozen;");
|
||||
sw.WriteLine();
|
||||
sw.WriteLine("namespace NadekoBot.GrpcApi;");
|
||||
sw.WriteLine();
|
||||
|
||||
sw.WriteLine("public partial class GrpcApiPermsInterceptor");
|
||||
sw.WriteLine("{");
|
||||
|
||||
sw.Indent++;
|
||||
|
||||
sw.WriteLine(
|
||||
"private static FrozenDictionary<string, GuildPerm> _perms = new Dictionary<string, GuildPerm>()");
|
||||
sw.WriteLine("{");
|
||||
|
||||
sw.Indent++;
|
||||
foreach (var field in data.MethodPerms)
|
||||
{
|
||||
sw.WriteLine("{{ \"{0}\", {1} }},", field.Name, field.Value);
|
||||
}
|
||||
|
||||
sw.Indent--;
|
||||
sw.WriteLine("}.ToFrozenDictionary();");
|
||||
|
||||
sw.WriteLine();
|
||||
sw.WriteLine("private static FrozenSet<string> _noAuthRequired = new HashSet<string>()");
|
||||
sw.WriteLine("{");
|
||||
|
||||
sw.Indent++;
|
||||
foreach (var noauth in data.NoAuthRequired)
|
||||
{
|
||||
sw.WriteLine("{{ \"{0}\" }},", noauth);
|
||||
}
|
||||
|
||||
sw.WriteLine("");
|
||||
|
||||
sw.Indent--;
|
||||
sw.WriteLine("}.ToFrozenSet();");
|
||||
|
||||
sw.Indent--;
|
||||
sw.WriteLine("}");
|
||||
|
||||
sw.Flush();
|
||||
ctx.AddSource("GrpcApiInterceptor.g.cs", stringWriter.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private List<TranslationPair> GetFields(string? dataText)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(dataText))
|
||||
return new();
|
||||
|
||||
Dictionary<string, string> data;
|
||||
try
|
||||
{
|
||||
var output = JsonConvert.DeserializeObject<Dictionary<string, string>>(dataText!);
|
||||
if (output is null)
|
||||
return new();
|
||||
|
||||
data = output;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Debug.WriteLine("Failed parsing responses file.");
|
||||
return new();
|
||||
}
|
||||
|
||||
var list = new List<TranslationPair>();
|
||||
foreach (var entry in data)
|
||||
{
|
||||
list.Add(new(
|
||||
entry.Key,
|
||||
entry.Value
|
||||
));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,7 +9,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.4.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
</ItemGroup>
|
||||
|
21
src/NadekoBot.GrpcApiBase/NadekoBot.GrpcApiBase.csproj
Normal file
21
src/NadekoBot.GrpcApiBase/NadekoBot.GrpcApiBase.csproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.28.2" />
|
||||
<PackageReference Include="Grpc" Version="2.46.6" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.66.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Protobuf Include="protos/*.proto">
|
||||
<GrpcServices>Server</GrpcServices>
|
||||
</Protobuf>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
47
src/NadekoBot.GrpcApiBase/protos/canvas.proto
Normal file
47
src/NadekoBot.GrpcApiBase/protos/canvas.proto
Normal file
@@ -0,0 +1,47 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
package ncanvas;
|
||||
|
||||
service GrpcNCanvas {
|
||||
rpc GetCanvas(google.protobuf.Empty) returns (CanvasReply);
|
||||
rpc GetPixel(GetPixelRequest) returns (GetPixelReply);
|
||||
rpc SetPixel(SetPixelRequest) returns (SetPixelReply);
|
||||
}
|
||||
|
||||
message CanvasReply {
|
||||
repeated uint32 pixels = 1;
|
||||
int32 width = 2;
|
||||
int32 height = 3;
|
||||
}
|
||||
|
||||
message GetPixelRequest {
|
||||
int32 x = 1;
|
||||
int32 y = 2;
|
||||
}
|
||||
|
||||
message GetPixelReply {
|
||||
string color = 1;
|
||||
uint32 packedColor = 2;
|
||||
int32 positionX = 3;
|
||||
int32 positionY = 4;
|
||||
int64 price = 5;
|
||||
string text = 6;
|
||||
string position = 7;
|
||||
}
|
||||
|
||||
message SetPixelRequest {
|
||||
string position = 1;
|
||||
string color = 2;
|
||||
string text = 3;
|
||||
int64 price = 4;
|
||||
}
|
||||
|
||||
message SetPixelReply {
|
||||
string error = 1;
|
||||
bool success = 2;
|
||||
optional GetPixelReply pixel = 3;
|
||||
}
|
89
src/NadekoBot.GrpcApiBase/protos/exprs.proto
Normal file
89
src/NadekoBot.GrpcApiBase/protos/exprs.proto
Normal file
@@ -0,0 +1,89 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
package exprs;
|
||||
|
||||
service GrpcExprs {
|
||||
rpc GetExprs(GetExprsRequest) returns (GetExprsReply);
|
||||
rpc AddExpr(AddExprRequest) returns (AddExprReply);
|
||||
rpc DeleteExpr(DeleteExprRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc GetQuotes(GetQuotesRequest) returns (GetQuotesReply);
|
||||
rpc AddQuote(AddQuoteRequest) returns (AddQuoteReply);
|
||||
rpc DeleteQuote(DeleteQuoteRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message DeleteExprRequest {
|
||||
string id = 1;
|
||||
uint64 guildId = 2;
|
||||
}
|
||||
|
||||
message GetExprsRequest {
|
||||
uint64 guildId = 1;
|
||||
string query = 2;
|
||||
int32 page = 3;
|
||||
}
|
||||
|
||||
message GetExprsReply {
|
||||
repeated ExprDto expressions = 1;
|
||||
int32 totalCount = 2;
|
||||
}
|
||||
|
||||
message ExprDto {
|
||||
string id = 1;
|
||||
string trigger = 2;
|
||||
string response = 3;
|
||||
|
||||
bool ca = 4;
|
||||
bool ad = 5;
|
||||
bool dm = 6;
|
||||
bool at = 7;
|
||||
}
|
||||
|
||||
message AddExprRequest {
|
||||
uint64 guildId = 1;
|
||||
ExprDto expr = 2;
|
||||
}
|
||||
|
||||
message AddExprReply {
|
||||
string id = 1;
|
||||
bool success = 2;
|
||||
}
|
||||
|
||||
message GetQuotesRequest {
|
||||
uint64 guildId = 1;
|
||||
string query = 2;
|
||||
int32 page = 3;
|
||||
}
|
||||
|
||||
message GetQuotesReply {
|
||||
repeated QuoteDto quotes = 1;
|
||||
int32 totalCount = 2;
|
||||
}
|
||||
|
||||
message QuoteDto {
|
||||
string id = 1;
|
||||
string trigger = 2;
|
||||
string response = 3;
|
||||
|
||||
uint64 authorId = 4;
|
||||
string authorName = 5;
|
||||
}
|
||||
|
||||
message AddQuoteRequest {
|
||||
uint64 guildId = 1;
|
||||
QuoteDto quote = 2;
|
||||
}
|
||||
|
||||
message AddQuoteReply {
|
||||
string id = 1;
|
||||
bool success = 2;
|
||||
}
|
||||
|
||||
message DeleteQuoteRequest {
|
||||
string id = 1;
|
||||
uint64 guildId = 2;
|
||||
}
|
60
src/NadekoBot.GrpcApiBase/protos/fin.proto
Normal file
60
src/NadekoBot.GrpcApiBase/protos/fin.proto
Normal file
@@ -0,0 +1,60 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
package fin;
|
||||
|
||||
service GrpcFin {
|
||||
rpc GetTransactions(GetTransactionsRequest) returns (GetTransactionsReply);
|
||||
rpc GetHoldings(GetHoldingsRequest) returns (GetHoldingsReply);
|
||||
rpc Withdraw(WithdrawRequest) returns (WithdrawReply);
|
||||
rpc Deposit(DepositRequest) returns (DepositReply);
|
||||
}
|
||||
|
||||
message GetTransactionsRequest {
|
||||
int32 page = 1;
|
||||
uint64 userId = 2;
|
||||
}
|
||||
|
||||
message GetTransactionsReply {
|
||||
repeated TransactionReply transactions = 1;
|
||||
int32 total = 2;
|
||||
}
|
||||
|
||||
message TransactionReply {
|
||||
int64 amount = 1;
|
||||
string note = 2;
|
||||
string type = 3;
|
||||
string extra = 4;
|
||||
google.protobuf.Timestamp timestamp = 5;
|
||||
string id = 6;
|
||||
}
|
||||
|
||||
message GetHoldingsRequest {
|
||||
uint64 userId = 1;
|
||||
}
|
||||
|
||||
message GetHoldingsReply {
|
||||
int64 cash = 1;
|
||||
int64 bank = 2;
|
||||
}
|
||||
|
||||
message WithdrawRequest {
|
||||
uint64 userId = 1;
|
||||
int64 amount = 2;
|
||||
}
|
||||
|
||||
message WithdrawReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message DepositRequest {
|
||||
uint64 userId = 1;
|
||||
int64 amount = 2;
|
||||
}
|
||||
|
||||
message DepositReply {
|
||||
bool success = 1;
|
||||
}
|
51
src/NadekoBot.GrpcApiBase/protos/greet.proto
Normal file
51
src/NadekoBot.GrpcApiBase/protos/greet.proto
Normal file
@@ -0,0 +1,51 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
package greet;
|
||||
|
||||
service GrpcGreet {
|
||||
rpc GetGreetSettings (GetGreetRequest) returns (GrpcGreetSettings);
|
||||
rpc UpdateGreet (UpdateGreetRequest) returns (UpdateGreetReply);
|
||||
rpc TestGreet (TestGreetRequest) returns (TestGreetReply);
|
||||
}
|
||||
|
||||
message GrpcGreetSettings {
|
||||
string channelId = 1;
|
||||
string message = 2;
|
||||
bool isEnabled = 3;
|
||||
GrpcGreetType type = 4;
|
||||
}
|
||||
|
||||
message GetGreetRequest {
|
||||
uint64 guildId = 1;
|
||||
GrpcGreetType type = 2;
|
||||
}
|
||||
|
||||
message UpdateGreetRequest {
|
||||
uint64 guildId = 1;
|
||||
GrpcGreetSettings settings = 2;
|
||||
}
|
||||
|
||||
enum GrpcGreetType {
|
||||
Greet = 0;
|
||||
GreetDm = 1;
|
||||
Bye = 2;
|
||||
Boost = 3;
|
||||
}
|
||||
|
||||
message UpdateGreetReply {
|
||||
bool Success = 1;
|
||||
}
|
||||
|
||||
message TestGreetRequest {
|
||||
uint64 guildId = 1;
|
||||
uint64 channelId = 2;
|
||||
uint64 userId = 3;
|
||||
GrpcGreetType type = 4;
|
||||
}
|
||||
|
||||
message TestGreetReply {
|
||||
bool success = 1;
|
||||
string error = 2;
|
||||
}
|
144
src/NadekoBot.GrpcApiBase/protos/other.proto
Normal file
144
src/NadekoBot.GrpcApiBase/protos/other.proto
Normal file
@@ -0,0 +1,144 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
package other;
|
||||
|
||||
service GrpcOther {
|
||||
rpc BotOnGuild(BotOnGuildRequest) returns (BotOnGuildReply);
|
||||
rpc GetTextChannels(GetTextChannelsRequest) returns (GetTextChannelsReply);
|
||||
rpc GetRoles(GetRolesRequest) returns (GetRolesReply);
|
||||
|
||||
rpc GetCurrencyLb(GetLbRequest) returns (CurrencyLbReply);
|
||||
rpc GetXpLb(GetLbRequest) returns (XpLbReply);
|
||||
rpc GetWaifuLb(GetLbRequest) returns (WaifuLbReply);
|
||||
|
||||
rpc GetShardStats(google.protobuf.Empty) returns (stream ShardStatsReply);
|
||||
rpc GetCommandFeed(google.protobuf.Empty) returns (stream CommandFeedEntry);
|
||||
rpc GetServerInfo(ServerInfoRequest) returns (GetServerInfoReply);
|
||||
}
|
||||
|
||||
message CommandFeedEntry {
|
||||
string command = 1;
|
||||
}
|
||||
|
||||
message GetRolesRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message GetRolesReply {
|
||||
repeated RoleReply roles = 1;
|
||||
}
|
||||
|
||||
message BotOnGuildRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message BotOnGuildReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message ShardStatsReply {
|
||||
int32 id = 1;
|
||||
string status = 2;
|
||||
|
||||
int32 guildCount = 3;
|
||||
string uptime = 4;
|
||||
int64 commands = 5;
|
||||
}
|
||||
|
||||
message GetTextChannelsRequest{
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message GetTextChannelsReply {
|
||||
repeated TextChannelReply textChannels = 1;
|
||||
}
|
||||
|
||||
message TextChannelReply {
|
||||
uint64 id = 1;
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
message CurrencyLbReply {
|
||||
repeated CurrencyLbEntryReply entries = 1;
|
||||
}
|
||||
|
||||
message CurrencyLbEntryReply {
|
||||
string user = 1;
|
||||
uint64 userId = 2;
|
||||
int64 amount = 3;
|
||||
string avatar = 4;
|
||||
}
|
||||
|
||||
message GetLbRequest {
|
||||
int32 page = 1;
|
||||
int32 perPage = 2;
|
||||
}
|
||||
|
||||
message XpLbReply {
|
||||
repeated XpLbEntryReply entries = 1;
|
||||
}
|
||||
|
||||
message XpLbEntryReply {
|
||||
string user = 1;
|
||||
uint64 userId = 2;
|
||||
int64 totalXp = 3;
|
||||
int64 level = 4;
|
||||
}
|
||||
|
||||
message WaifuLbReply {
|
||||
repeated WaifuLbEntry entries = 1;
|
||||
}
|
||||
|
||||
message WaifuLbEntry {
|
||||
string user = 1;
|
||||
string claimedBy = 2;
|
||||
int64 value = 3;
|
||||
bool isMutual = 4;
|
||||
}
|
||||
|
||||
message ServerInfoRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message GetServerInfoReply {
|
||||
uint64 id = 1;
|
||||
string name = 2;
|
||||
string iconUrl = 3;
|
||||
uint64 ownerId = 4;
|
||||
string ownerName = 5;
|
||||
repeated RoleReply roles = 6;
|
||||
repeated EmojiReply emojis = 7;
|
||||
repeated string features = 8;
|
||||
int32 textChannels = 9;
|
||||
int32 voiceChannels = 10;
|
||||
int32 memberCount = 11;
|
||||
int64 createdAt = 12;
|
||||
}
|
||||
|
||||
message RoleReply {
|
||||
uint64 id = 1;
|
||||
string name = 2;
|
||||
string iconUrl = 3;
|
||||
string color = 4;
|
||||
}
|
||||
|
||||
message EmojiReply {
|
||||
string name = 1;
|
||||
string url = 2;
|
||||
string code = 3;
|
||||
}
|
||||
|
||||
message ChannelReply {
|
||||
uint64 id = 1;
|
||||
string name = 2;
|
||||
ChannelType type = 3;
|
||||
}
|
||||
|
||||
enum ChannelType {
|
||||
Text = 0;
|
||||
Voice = 1;
|
||||
}
|
107
src/NadekoBot.GrpcApiBase/protos/warn.proto
Normal file
107
src/NadekoBot.GrpcApiBase/protos/warn.proto
Normal file
@@ -0,0 +1,107 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
package warn;
|
||||
|
||||
service GrpcWarn {
|
||||
rpc GetWarnSettings (WarnSettingsRequest) returns (WarnSettingsReply);
|
||||
|
||||
rpc SetWarnExpiry(SetWarnExpiryRequest) returns (SetWarnExpiryReply);
|
||||
rpc AddWarnp (AddWarnpRequest) returns (AddWarnpReply);
|
||||
rpc DeleteWarnp (DeleteWarnpRequest) returns (DeleteWarnpReply);
|
||||
|
||||
rpc GetLatestWarnings(GetLatestWarningsRequest) returns (GetLatestWarningsReply);
|
||||
rpc GetUserWarnings(GetUserWarningsRequest) returns (GetUserWarningsReply);
|
||||
|
||||
rpc ForgiveWarning(ForgiveWarningRequest) returns (ForgiveWarningReply);
|
||||
rpc DeleteWarning(ForgiveWarningRequest) returns (ForgiveWarningReply);
|
||||
|
||||
}
|
||||
message WarnSettingsRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message WarnPunishment {
|
||||
int32 threshold = 1;
|
||||
string action = 2;
|
||||
int32 duration = 3;
|
||||
string role = 4;
|
||||
}
|
||||
|
||||
message WarnSettingsReply {
|
||||
repeated WarnPunishment punishments = 1;
|
||||
int32 expiryDays = 2;
|
||||
bool deleteOnExpire = 3;
|
||||
}
|
||||
|
||||
message AddWarnpRequest {
|
||||
uint64 guildId = 1;
|
||||
WarnPunishment punishment = 2;
|
||||
}
|
||||
|
||||
message AddWarnpReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message DeleteWarnpRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 threshold = 2;
|
||||
}
|
||||
|
||||
message DeleteWarnpReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message GetUserWarningsRequest {
|
||||
uint64 guildId = 1;
|
||||
string user = 2;
|
||||
int32 page = 3;
|
||||
}
|
||||
|
||||
message GetUserWarningsReply {
|
||||
repeated Warning warnings = 1;
|
||||
int32 totalCount = 2;
|
||||
}
|
||||
|
||||
message Warning {
|
||||
string id = 1;
|
||||
string reason = 2;
|
||||
int64 timestamp = 3;
|
||||
int64 weight = 4;
|
||||
bool forgiven = 5;
|
||||
string forgivenBy = 6;
|
||||
string user = 7;
|
||||
uint64 userId = 8;
|
||||
string moderator = 9;
|
||||
}
|
||||
|
||||
message ForgiveWarningRequest {
|
||||
uint64 guildId = 1;
|
||||
string warnId = 2;
|
||||
string modName = 3;
|
||||
}
|
||||
|
||||
message ForgiveWarningReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message SetWarnExpiryRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 expiryDays = 2;
|
||||
bool deleteOnExpire = 3;
|
||||
}
|
||||
|
||||
message SetWarnExpiryReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message GetLatestWarningsRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 page = 2;
|
||||
}
|
||||
|
||||
message GetLatestWarningsReply {
|
||||
repeated Warning warnings = 1;
|
||||
int32 totalCount = 2;
|
||||
}
|
120
src/NadekoBot.GrpcApiBase/protos/xp.proto
Normal file
120
src/NadekoBot.GrpcApiBase/protos/xp.proto
Normal file
@@ -0,0 +1,120 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "NadekoBot.GrpcApi";
|
||||
|
||||
package xp;
|
||||
|
||||
service GrpcXp {
|
||||
rpc GetXpLb(GetXpLbRequest) returns (GetXpLbReply);
|
||||
rpc ResetUserXp(ResetUserXpRequest) returns (ResetUserXpReply);
|
||||
|
||||
rpc GetXpSettings(GetXpSettingsRequest) returns (GetXpSettingsReply);
|
||||
|
||||
rpc AddExclusion(AddExclusionRequest) returns (AddExclusionReply);
|
||||
rpc DeleteExclusion(DeleteExclusionRequest) returns (DeleteExclusionReply);
|
||||
|
||||
rpc AddReward(AddRewardRequest) returns (AddRewardReply);
|
||||
rpc DeleteReward(DeleteRewardRequest) returns (DeleteRewardReply);
|
||||
|
||||
rpc SetServerExclusion(SetServerExclusionRequest) returns (SetServerExclusionReply);
|
||||
}
|
||||
|
||||
message SetServerExclusionRequest {
|
||||
uint64 guildId = 1;
|
||||
bool serverExcluded = 2;
|
||||
}
|
||||
|
||||
message SetServerExclusionReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message GetXpLbRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 page = 2;
|
||||
}
|
||||
|
||||
message GetXpLbReply {
|
||||
repeated XpLbUserReply users = 1;
|
||||
int32 total = 2;
|
||||
}
|
||||
|
||||
message XpLbUserReply {
|
||||
uint64 userId = 1;
|
||||
string username = 2;
|
||||
int64 xp = 3;
|
||||
int64 level = 4;
|
||||
int64 levelPercent = 5;
|
||||
string avatar = 6;
|
||||
}
|
||||
|
||||
message ResetUserXpRequest {
|
||||
uint64 guildId = 1;
|
||||
uint64 userId = 2;
|
||||
}
|
||||
|
||||
message ResetUserXpReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message GetXpSettingsReply {
|
||||
repeated ExclItemReply exclusions = 1;
|
||||
repeated RewItemReply rewards = 2;
|
||||
bool serverExcluded = 3;
|
||||
}
|
||||
|
||||
message GetXpSettingsRequest {
|
||||
uint64 guildId = 1;
|
||||
}
|
||||
|
||||
message ExclItemReply {
|
||||
string type = 1;
|
||||
uint64 id = 2;
|
||||
string name = 3;
|
||||
}
|
||||
|
||||
message RewItemReply {
|
||||
int32 level = 1;
|
||||
string type = 2;
|
||||
string value = 3;
|
||||
}
|
||||
|
||||
message AddExclusionRequest {
|
||||
uint64 guildId = 1;
|
||||
string type = 2;
|
||||
uint64 id = 3;
|
||||
}
|
||||
|
||||
message AddExclusionReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message DeleteExclusionRequest {
|
||||
uint64 guildId = 1;
|
||||
string type = 2;
|
||||
uint64 id = 3;
|
||||
}
|
||||
|
||||
message DeleteExclusionReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message AddRewardRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 level = 2;
|
||||
string type = 3;
|
||||
string value = 4;
|
||||
}
|
||||
|
||||
message AddRewardReply {
|
||||
bool success = 1;
|
||||
}
|
||||
|
||||
message DeleteRewardRequest {
|
||||
uint64 guildId = 1;
|
||||
int32 level = 2;
|
||||
string type = 3;
|
||||
}
|
||||
|
||||
message DeleteRewardReply {
|
||||
bool success = 1;
|
||||
}
|
88
src/NadekoBot.Tests/FishTests.cs
Normal file
88
src/NadekoBot.Tests/FishTests.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Diagnostics;
|
||||
// using System.IO;
|
||||
// using System.Linq;
|
||||
// using Nadeko.Common;
|
||||
// using NadekoBot.Modules.Games;
|
||||
// using NUnit.Framework;
|
||||
//
|
||||
// namespace NadekoBot.Tests;
|
||||
//
|
||||
// public class FishTests
|
||||
// {
|
||||
// [Test]
|
||||
// public void TestWeather()
|
||||
// {
|
||||
// var fs = new FishService(null, null);
|
||||
//
|
||||
// var rng = new Random();
|
||||
//
|
||||
// // output = @"ro+dD:bN0uVqV3ZOAv6r""EFeA'A]u]uSyz2Qd'r#0Vf:5zOX\VgSsF8LgRCL/uOW";
|
||||
// while (true)
|
||||
// {
|
||||
// var output = "";
|
||||
// for (var i = 0; i < 64; i++)
|
||||
// {
|
||||
// var c = (char)rng.Next(33, 123);
|
||||
// output += c;
|
||||
// }
|
||||
//
|
||||
// output = "";
|
||||
// var weathers = new List<FishingWeather>();
|
||||
// for (var i = 0; i < 1_000_000; i++)
|
||||
// {
|
||||
// var w = fs.GetWeather(DateTime.UtcNow.AddHours(6 * i), output);
|
||||
// weathers.Add(w);
|
||||
// }
|
||||
//
|
||||
// var vals = weathers.GroupBy(x => x)
|
||||
// .ToDictionary(x => x.Key, x => x.Count());
|
||||
//
|
||||
// var str = weathers.Select(x => (int)x).Join("");
|
||||
// var maxLength = MaxLength(str);
|
||||
//
|
||||
// if (maxLength < 12)
|
||||
// {
|
||||
// foreach (var v in vals)
|
||||
// {
|
||||
// Console.WriteLine($"{v.Key}: {v.Value}");
|
||||
// }
|
||||
//
|
||||
// Console.WriteLine(output);
|
||||
// Console.WriteLine(maxLength);
|
||||
//
|
||||
// File.WriteAllText("data.txt", weathers.Select(x => (int)x).Join(""));
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // string with same characters
|
||||
// static int MaxLength(String s)
|
||||
// {
|
||||
// int ans = 1, temp = 1;
|
||||
//
|
||||
// // Traverse the string
|
||||
// for (int i = 1; i < s.Length; i++)
|
||||
// {
|
||||
// // If character is same as
|
||||
// // previous increment temp value
|
||||
// if (s[i] == s[i - 1])
|
||||
// {
|
||||
// ++temp;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ans = Math.Max(ans, temp);
|
||||
// temp = 1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ans = Math.Max(ans, temp);
|
||||
//
|
||||
// // Return the required answer
|
||||
// return ans;
|
||||
// }
|
||||
// }
|
@@ -1,76 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Nadeko.Common;
|
||||
using NadekoBot.Services;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace NadekoBot.Tests
|
||||
{
|
||||
public class GroupGreetTests
|
||||
{
|
||||
private GreetGrouper<int> _grouper;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
=> _grouper = new GreetGrouper<int>();
|
||||
|
||||
[Test]
|
||||
public void CreateTest()
|
||||
{
|
||||
var created = _grouper.CreateOrAdd(0, 5);
|
||||
|
||||
Assert.True(created);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateClearTest()
|
||||
{
|
||||
_grouper.CreateOrAdd(0, 5);
|
||||
_grouper.ClearGroup(0, 5, out var items);
|
||||
|
||||
Assert.AreEqual(0, items.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NotCreatedTest()
|
||||
{
|
||||
_grouper.CreateOrAdd(0, 5);
|
||||
var created = _grouper.CreateOrAdd(0, 4);
|
||||
|
||||
Assert.False(created);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ClearAddedTest()
|
||||
{
|
||||
_grouper.CreateOrAdd(0, 5);
|
||||
_grouper.CreateOrAdd(0, 4);
|
||||
_grouper.ClearGroup(0, 5, out var items);
|
||||
|
||||
var list = items.ToList();
|
||||
|
||||
Assert.AreEqual(1, list.Count, $"Count was {list.Count}");
|
||||
Assert.AreEqual(4, list[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ClearManyTest()
|
||||
{
|
||||
_grouper.CreateOrAdd(0, 5);
|
||||
|
||||
// add 15 items
|
||||
await Enumerable.Range(10, 15)
|
||||
.Select(x => Task.Run(() => _grouper.CreateOrAdd(0, x))).WhenAll();
|
||||
|
||||
// get 5 at most
|
||||
_grouper.ClearGroup(0, 5, out var items);
|
||||
var list = items.ToList();
|
||||
Assert.AreEqual(5, list.Count, $"Count was {list.Count}");
|
||||
|
||||
// try to get 15, but there should be 10 left
|
||||
_grouper.ClearGroup(0, 15, out items);
|
||||
list = items.ToList();
|
||||
Assert.AreEqual(10, list.Count, $"Count was {list.Count}");
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
using Nadeko.Common;
|
||||
using System;
|
||||
using Nadeko.Common;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace NadekoBot.Tests
|
||||
@@ -120,5 +121,12 @@ namespace NadekoBot.Tests
|
||||
num = new kwum(int.MaxValue);
|
||||
Assert.AreEqual("3zzzzzz", num.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPower()
|
||||
{
|
||||
var num = new kwum((int)Math.Pow(32, 2));
|
||||
Assert.AreEqual("322", num.ToString());
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,7 +8,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
@@ -77,7 +77,6 @@ csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_accessors = true:suggestion
|
||||
csharp_style_expression_bodied_constructors = when_on_single_line:suggestion
|
||||
csharp_style_expression_bodied_indexers = true:suggestion
|
||||
csharp_style_expression_bodied_lambdas = true:suggestion
|
||||
csharp_style_expression_bodied_local_functions = true:suggestion
|
||||
@@ -181,9 +180,9 @@ dotnet_naming_rule.private_readonly_field.symbols = private_readonly_field
|
||||
dotnet_naming_rule.private_readonly_field.style = begins_with_underscore
|
||||
dotnet_naming_rule.private_readonly_field.severity = warning
|
||||
|
||||
dotnet_naming_rule.private_field.symbols = private_field
|
||||
dotnet_naming_rule.private_field.style = camel_case
|
||||
dotnet_naming_rule.private_field.severity = warning
|
||||
# dotnet_naming_rule.private_field.symbols = private_field
|
||||
# dotnet_naming_rule.private_field.style = camel_case
|
||||
# dotnet_naming_rule.private_field.severity = warning
|
||||
|
||||
dotnet_naming_rule.const_fields.symbols = const_fields
|
||||
dotnet_naming_rule.const_fields.style = all_upper
|
||||
@@ -358,3 +357,4 @@ resharper_arrange_redundant_parentheses_highlighting = hint
|
||||
# IDE0011: Add braces
|
||||
dotnet_diagnostic.IDE0011.severity = warning
|
||||
|
||||
resharper_arrange_type_member_modifiers_highlighting = hint
|
@@ -1,5 +1,6 @@
|
||||
#nullable disable
|
||||
using DryIoc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NadekoBot.Common.Configs;
|
||||
@@ -24,7 +25,7 @@ public sealed class Bot : IBot
|
||||
public bool IsReady { get; private set; }
|
||||
public int ShardId { get; set; }
|
||||
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly IBotCreds _creds;
|
||||
private readonly CommandService _commandService;
|
||||
private readonly DbService _db;
|
||||
|
||||
@@ -41,6 +42,9 @@ public sealed class Bot : IBot
|
||||
_credsProvider = new BotCredsProvider(totalShards, credPath);
|
||||
_creds = _credsProvider.GetCreds();
|
||||
|
||||
LogSetup.SetupLogger(shardId, _creds);
|
||||
Log.Information("Pid: {ProcessId}", Environment.ProcessId);
|
||||
|
||||
_db = new NadekoDbService(_credsProvider);
|
||||
|
||||
var messageCacheSize =
|
||||
@@ -80,26 +84,26 @@ public sealed class Bot : IBot
|
||||
// _interactionService = new(Client.Rest);
|
||||
|
||||
Client.Log += Client_Log;
|
||||
_loadedAssemblies = new[]
|
||||
{
|
||||
typeof(Bot).Assembly, // bot
|
||||
};
|
||||
_loadedAssemblies =
|
||||
[
|
||||
typeof(Bot).Assembly // bot
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public IReadOnlyList<ulong> GetCurrentGuildIds()
|
||||
=> Client.Guilds.Select(x => x.Id).ToList();
|
||||
=> Client.Guilds.Select(x => x.Id).ToList().AsReadOnly();
|
||||
|
||||
private void AddServices()
|
||||
private async Task AddServices()
|
||||
{
|
||||
var startingGuildIdList = GetCurrentGuildIds();
|
||||
var sw = Stopwatch.StartNew();
|
||||
var startingGuildIdList = GetCurrentGuildIds().ToList();
|
||||
var startTime = Stopwatch.GetTimestamp();
|
||||
var bot = Client.CurrentUser;
|
||||
|
||||
using (var uow = _db.GetDbContext())
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
AllGuildConfigs = await uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList);
|
||||
uow.EnsureUserCreated(bot.Id, bot.Username, bot.Discriminator, bot.AvatarId);
|
||||
AllGuildConfigs = uow.Set<GuildConfig>().GetAllGuildConfigs(startingGuildIdList).ToImmutableArray();
|
||||
}
|
||||
|
||||
// var svcs = new StandardKernel(new NinjectSettings()
|
||||
@@ -109,12 +113,12 @@ public sealed class Bot : IBot
|
||||
// });
|
||||
|
||||
var svcs = new Container();
|
||||
|
||||
|
||||
// this is required in order for medusa unloading to work
|
||||
// svcs.Components.Remove<IPlanner, Planner>();
|
||||
// svcs.Components.Add<IPlanner, RemovablePlanner>();
|
||||
|
||||
svcs.AddSingleton<IBotCredentials, IBotCredentials>(_ => _credsProvider.GetCreds());
|
||||
svcs.AddSingleton<IBotCreds>(_ => _credsProvider.GetCreds());
|
||||
svcs.AddSingleton<DbService, DbService>(_db);
|
||||
svcs.AddSingleton<IBotCredsProvider>(_credsProvider);
|
||||
svcs.AddSingleton<DiscordSocketClient>(Client);
|
||||
@@ -161,8 +165,8 @@ public sealed class Bot : IBot
|
||||
LoadTypeReaders(a);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Log.Information("All services loaded in {ServiceLoadTime:F2}s", sw.Elapsed.TotalSeconds);
|
||||
Log.Information("All services loaded in {ServiceLoadTime:F2}s",
|
||||
Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
||||
}
|
||||
|
||||
private void LoadTypeReaders(Assembly assembly)
|
||||
@@ -214,12 +218,12 @@ public sealed class Bot : IBot
|
||||
catch (HttpException ex)
|
||||
{
|
||||
LoginErrorHandler.Handle(ex);
|
||||
Helpers.ReadErrorAndExit(3);
|
||||
Helpers.ReadErrorAndExit(101);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoginErrorHandler.Handle(ex);
|
||||
Helpers.ReadErrorAndExit(4);
|
||||
Helpers.ReadErrorAndExit(5);
|
||||
}
|
||||
|
||||
await clientReady.Task.ConfigureAwait(false);
|
||||
@@ -259,23 +263,24 @@ public sealed class Bot : IBot
|
||||
if (ShardId == 0)
|
||||
await _db.SetupAsync();
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
var startTime = Stopwatch.GetTimestamp();
|
||||
|
||||
await LoginAsync(_creds.Token);
|
||||
|
||||
|
||||
Log.Information("Shard {ShardId} loading services...", Client.ShardId);
|
||||
try
|
||||
{
|
||||
AddServices();
|
||||
await AddServices();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Error adding services");
|
||||
Helpers.ReadErrorAndExit(9);
|
||||
Helpers.ReadErrorAndExit(103);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
Log.Information("Shard {ShardId} connected in {Elapsed:F2}s", Client.ShardId, sw.Elapsed.TotalSeconds);
|
||||
Log.Information("Shard {ShardId} connected in {Elapsed:F2}s",
|
||||
Client.ShardId,
|
||||
Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
||||
var commandHandler = Services.GetRequiredService<CommandHandler>();
|
||||
|
||||
// start handling messages received in commandhandler
|
||||
@@ -340,26 +345,26 @@ public sealed class Bot : IBot
|
||||
if (arg.Exception is { InnerException: WebSocketClosedException { CloseCode: 4014 } })
|
||||
{
|
||||
Log.Error("""
|
||||
Login failed.
|
||||
|
||||
*** Please enable privileged intents ***
|
||||
|
||||
Certain Nadeko features require Discord's privileged gateway intents.
|
||||
These include greeting and goodbye messages, as well as creating the Owner message channels for DM forwarding.
|
||||
|
||||
How to enable privileged intents:
|
||||
1. Head over to the Discord Developer Portal https://discord.com/developers/applications/
|
||||
2. Select your Application.
|
||||
3. Click on `Bot` in the left side navigation panel, and scroll down to the intents section.
|
||||
4. Enable all intents.
|
||||
5. Restart your bot.
|
||||
|
||||
Read this only if your bot is in 100 or more servers:
|
||||
|
||||
You'll need to apply to use the intents with Discord, but for small selfhosts, all that is required is enabling the intents in the developer portal.
|
||||
Yes, this is a new thing from Discord, as of October 2020. No, there's nothing we can do about it. Yes, we're aware it worked before.
|
||||
While waiting for your bot to be accepted, you can change the 'usePrivilegedIntents' inside your creds.yml to 'false', although this will break many of the nadeko's features
|
||||
""");
|
||||
Login failed.
|
||||
|
||||
*** Please enable privileged intents ***
|
||||
|
||||
Certain Nadeko features require Discord's privileged gateway intents.
|
||||
These include greeting and goodbye messages, as well as creating the Owner message channels for DM forwarding.
|
||||
|
||||
How to enable privileged intents:
|
||||
1. Head over to the Discord Developer Portal https://discord.com/developers/applications/
|
||||
2. Select your Application.
|
||||
3. Click on `Bot` in the left side navigation panel, and scroll down to the intents section.
|
||||
4. Enable all intents.
|
||||
5. Restart your bot.
|
||||
|
||||
Read this only if your bot is in 100 or more servers:
|
||||
|
||||
You'll need to apply to use the intents with Discord, but for small selfhosts, all that is required is enabling the intents in the developer portal.
|
||||
Yes, this is a new thing from Discord, as of October 2020. No, there's nothing we can do about it. Yes, we're aware it worked before.
|
||||
While waiting for your bot to be accepted, you can change the 'usePrivilegedIntents' inside your creds.yml to 'false', although this will break many of the nadeko's features
|
||||
""");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
@@ -20,48 +20,45 @@ public static class DiscordUserExtensions
|
||||
string discrim,
|
||||
string avatarId)
|
||||
=> ctx.GetTable<DiscordUser>()
|
||||
.InsertOrUpdate(
|
||||
() => new()
|
||||
{
|
||||
UserId = userId,
|
||||
Username = username,
|
||||
Discriminator = discrim,
|
||||
AvatarId = avatarId,
|
||||
TotalXp = 0,
|
||||
CurrencyAmount = 0
|
||||
},
|
||||
old => new()
|
||||
{
|
||||
Username = username,
|
||||
Discriminator = discrim,
|
||||
AvatarId = avatarId
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
UserId = userId
|
||||
});
|
||||
.InsertOrUpdate(
|
||||
() => new()
|
||||
{
|
||||
UserId = userId,
|
||||
Username = username,
|
||||
AvatarId = avatarId,
|
||||
TotalXp = 0,
|
||||
CurrencyAmount = 0
|
||||
},
|
||||
old => new()
|
||||
{
|
||||
Username = username,
|
||||
AvatarId = avatarId
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
UserId = userId
|
||||
});
|
||||
|
||||
public static Task EnsureUserCreatedAsync(
|
||||
this DbContext ctx,
|
||||
ulong userId)
|
||||
=> ctx.GetTable<DiscordUser>()
|
||||
.InsertOrUpdateAsync(
|
||||
() => new()
|
||||
{
|
||||
UserId = userId,
|
||||
Username = "Unknown",
|
||||
Discriminator = "????",
|
||||
AvatarId = string.Empty,
|
||||
TotalXp = 0,
|
||||
CurrencyAmount = 0
|
||||
},
|
||||
old => new()
|
||||
{
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
UserId = userId
|
||||
});
|
||||
.InsertOrUpdateAsync(
|
||||
() => new()
|
||||
{
|
||||
UserId = userId,
|
||||
Username = "??Unknown",
|
||||
AvatarId = string.Empty,
|
||||
TotalXp = 0,
|
||||
CurrencyAmount = 0
|
||||
},
|
||||
old => new()
|
||||
{
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
UserId = userId
|
||||
});
|
||||
|
||||
//temp is only used in updatecurrencystate, so that i don't overwrite real usernames/discrims with Unknown
|
||||
public static DiscordUser GetOrCreateUser(
|
||||
@@ -83,25 +80,22 @@ public static class DiscordUserExtensions
|
||||
|
||||
public static int GetUserGlobalRank(this DbSet<DiscordUser> users, ulong id)
|
||||
=> users.AsQueryable()
|
||||
.Where(x => x.TotalXp
|
||||
> users.AsQueryable().Where(y => y.UserId == id).Select(y => y.TotalXp).FirstOrDefault())
|
||||
.Count()
|
||||
.Where(x => x.TotalXp
|
||||
> users.AsQueryable().Where(y => y.UserId == id).Select(y => y.TotalXp).FirstOrDefault())
|
||||
.Count()
|
||||
+ 1;
|
||||
|
||||
public static DiscordUser[] GetUsersXpLeaderboardFor(this DbSet<DiscordUser> users, int page, int perPage)
|
||||
=> users.AsQueryable().OrderByDescending(x => x.TotalXp).Skip(page * perPage).Take(perPage).AsEnumerable()
|
||||
.ToArray();
|
||||
|
||||
|
||||
public static Task<List<DiscordUser>> GetTopRichest(
|
||||
this DbSet<DiscordUser> users,
|
||||
ulong botId,
|
||||
int page = 0, int perPage = 9)
|
||||
int page = 0,
|
||||
int perPage = 9)
|
||||
=> users.AsQueryable()
|
||||
.Where(c => c.CurrencyAmount > 0 && botId != c.UserId)
|
||||
.OrderByDescending(c => c.CurrencyAmount)
|
||||
.Skip(page * perPage)
|
||||
.Take(perPage)
|
||||
.ToListAsyncLinqToDB();
|
||||
.Where(c => c.CurrencyAmount > 0 && botId != c.UserId)
|
||||
.OrderByDescending(c => c.CurrencyAmount)
|
||||
.Skip(page * perPage)
|
||||
.Take(perPage)
|
||||
.ToListAsyncLinqToDB();
|
||||
|
||||
public static async Task<long> GetUserCurrencyAsync(this DbSet<DiscordUser> users, ulong userId)
|
||||
=> (await users.FirstOrDefaultAsyncLinqToDB(x => x.UserId == userId))?.CurrencyAmount ?? 0;
|
||||
@@ -118,8 +112,8 @@ public static class DiscordUserExtensions
|
||||
|
||||
public static decimal GetTopOnePercentCurrency(this DbSet<DiscordUser> users, ulong botId)
|
||||
=> users.AsQueryable()
|
||||
.Where(x => x.UserId != botId)
|
||||
.OrderByDescending(x => x.CurrencyAmount)
|
||||
.Take(users.Count() / 100 == 0 ? 1 : users.Count() / 100)
|
||||
.Sum(x => x.CurrencyAmount);
|
||||
.Where(x => x.UserId != botId)
|
||||
.OrderByDescending(x => x.CurrencyAmount)
|
||||
.Take(users.Count() / 100 == 0 ? 1 : users.Count() / 100)
|
||||
.Sum(x => x.CurrencyAmount);
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
#nullable disable
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
@@ -7,19 +8,20 @@ namespace NadekoBot.Db;
|
||||
public static class GuildConfigExtensions
|
||||
{
|
||||
private static List<WarningPunishment> DefaultWarnPunishments
|
||||
=> new()
|
||||
{
|
||||
=>
|
||||
[
|
||||
new()
|
||||
{
|
||||
Count = 3,
|
||||
Punishment = PunishmentAction.Kick
|
||||
},
|
||||
|
||||
new()
|
||||
{
|
||||
Count = 5,
|
||||
Punishment = PunishmentAction.Ban
|
||||
}
|
||||
};
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Gets full stream role settings for the guild with the specified id.
|
||||
@@ -31,8 +33,8 @@ public static class GuildConfigExtensions
|
||||
{
|
||||
var conf = ctx.GuildConfigsForId(guildId,
|
||||
set => set.Include(y => y.StreamRole)
|
||||
.Include(y => y.StreamRole.Whitelist)
|
||||
.Include(y => y.StreamRole.Blacklist));
|
||||
.Include(y => y.StreamRole.Whitelist)
|
||||
.Include(y => y.StreamRole.Blacklist));
|
||||
|
||||
if (conf.StreamRole is null)
|
||||
conf.StreamRole = new();
|
||||
@@ -41,19 +43,27 @@ public static class GuildConfigExtensions
|
||||
}
|
||||
|
||||
private static IQueryable<GuildConfig> IncludeEverything(this DbSet<GuildConfig> configs)
|
||||
=> configs.AsQueryable()
|
||||
.AsSplitQuery()
|
||||
.Include(gc => gc.CommandCooldowns)
|
||||
.Include(gc => gc.FollowedStreams)
|
||||
.Include(gc => gc.StreamRole)
|
||||
.Include(gc => gc.XpSettings)
|
||||
.ThenInclude(x => x.ExclusionList)
|
||||
.Include(gc => gc.DelMsgOnCmdChannels);
|
||||
=> configs
|
||||
.AsSplitQuery()
|
||||
.Include(gc => gc.CommandCooldowns)
|
||||
.Include(gc => gc.FollowedStreams)
|
||||
.Include(gc => gc.StreamRole)
|
||||
.Include(gc => gc.DelMsgOnCmdChannels)
|
||||
.Include(gc => gc.XpSettings)
|
||||
.ThenInclude(x => x.ExclusionList);
|
||||
|
||||
public static IEnumerable<GuildConfig> GetAllGuildConfigs(
|
||||
public static async Task<GuildConfig[]> GetAllGuildConfigs(
|
||||
this DbSet<GuildConfig> configs,
|
||||
IReadOnlyList<ulong> availableGuilds)
|
||||
=> configs.IncludeEverything().AsNoTracking().Where(x => availableGuilds.Contains(x.GuildId)).ToList();
|
||||
List<ulong> availableGuilds)
|
||||
{
|
||||
var result = await configs
|
||||
.IncludeEverything()
|
||||
.Where(x => availableGuilds.Contains(x.GuildId))
|
||||
.AsNoTracking()
|
||||
.ToArrayAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and creates if it doesn't exist a config for a guild.
|
||||
@@ -79,20 +89,19 @@ public static class GuildConfigExtensions
|
||||
|
||||
if (config is null)
|
||||
{
|
||||
ctx.Set<GuildConfig>().Add(config = new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
Permissions = Permissionv2.GetDefaultPermlist,
|
||||
WarningsInitialized = true,
|
||||
WarnPunishments = DefaultWarnPunishments
|
||||
});
|
||||
ctx.Set<GuildConfig>()
|
||||
.Add(config = new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
Permissions = Permissionv2.GetDefaultPermlist,
|
||||
WarningsInitialized = true,
|
||||
});
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
|
||||
if (!config.WarningsInitialized)
|
||||
{
|
||||
config.WarningsInitialized = true;
|
||||
config.WarnPunishments = DefaultWarnPunishments;
|
||||
}
|
||||
|
||||
return config;
|
||||
@@ -121,18 +130,18 @@ public static class GuildConfigExtensions
|
||||
public static LogSetting LogSettingsFor(this DbContext ctx, ulong guildId)
|
||||
{
|
||||
var logSetting = ctx.Set<LogSetting>()
|
||||
.AsQueryable()
|
||||
.Include(x => x.LogIgnores)
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.FirstOrDefault();
|
||||
.AsQueryable()
|
||||
.Include(x => x.LogIgnores)
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (logSetting is null)
|
||||
{
|
||||
ctx.Set<LogSetting>()
|
||||
.Add(logSetting = new()
|
||||
{
|
||||
GuildId = guildId
|
||||
});
|
||||
.Add(logSetting = new()
|
||||
{
|
||||
GuildId = guildId
|
||||
});
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
|
||||
@@ -148,18 +157,20 @@ public static class GuildConfigExtensions
|
||||
|
||||
public static GuildConfig GcWithPermissionsFor(this DbContext ctx, ulong guildId)
|
||||
{
|
||||
var config = ctx.Set<GuildConfig>().AsQueryable()
|
||||
.Where(gc => gc.GuildId == guildId)
|
||||
.Include(gc => gc.Permissions)
|
||||
.FirstOrDefault();
|
||||
var config = ctx.Set<GuildConfig>()
|
||||
.AsQueryable()
|
||||
.Where(gc => gc.GuildId == guildId)
|
||||
.Include(gc => gc.Permissions)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (config is null) // if there is no guildconfig, create new one
|
||||
{
|
||||
ctx.Set<GuildConfig>().Add(config = new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
Permissions = Permissionv2.GetDefaultPermlist
|
||||
});
|
||||
ctx.Set<GuildConfig>()
|
||||
.Add(config = new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
Permissions = Permissionv2.GetDefaultPermlist
|
||||
});
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
else if (config.Permissions is null || !config.Permissions.Any()) // if no perms, add default ones
|
||||
@@ -176,30 +187,21 @@ public static class GuildConfigExtensions
|
||||
|
||||
public static IEnumerable<FollowedStream> GetFollowedStreams(this DbSet<GuildConfig> configs, List<ulong> included)
|
||||
=> configs.AsQueryable()
|
||||
.Where(gc => included.Contains(gc.GuildId))
|
||||
.Include(gc => gc.FollowedStreams)
|
||||
.SelectMany(gc => gc.FollowedStreams)
|
||||
.ToList();
|
||||
.Where(gc => included.Contains(gc.GuildId))
|
||||
.Include(gc => gc.FollowedStreams)
|
||||
.SelectMany(gc => gc.FollowedStreams)
|
||||
.ToList();
|
||||
|
||||
public static void SetCleverbotEnabled(this DbSet<GuildConfig> configs, ulong id, bool cleverbotEnabled)
|
||||
{
|
||||
var conf = configs.FirstOrDefault(gc => gc.GuildId == id);
|
||||
|
||||
if (conf is null)
|
||||
return;
|
||||
|
||||
conf.CleverbotEnabled = cleverbotEnabled;
|
||||
}
|
||||
|
||||
public static XpSettings XpSettingsFor(this DbContext ctx, ulong guildId)
|
||||
{
|
||||
var gc = ctx.GuildConfigsForId(guildId,
|
||||
set => set.Include(x => x.XpSettings)
|
||||
.ThenInclude(x => x.RoleRewards)
|
||||
.Include(x => x.XpSettings)
|
||||
.ThenInclude(x => x.CurrencyRewards)
|
||||
.Include(x => x.XpSettings)
|
||||
.ThenInclude(x => x.ExclusionList));
|
||||
.ThenInclude(x => x.RoleRewards)
|
||||
.Include(x => x.XpSettings)
|
||||
.ThenInclude(x => x.CurrencyRewards)
|
||||
.Include(x => x.XpSettings)
|
||||
.ThenInclude(x => x.ExclusionList));
|
||||
|
||||
if (gc.XpSettings is null)
|
||||
gc.XpSettings = new();
|
||||
@@ -209,15 +211,15 @@ public static class GuildConfigExtensions
|
||||
|
||||
public static IEnumerable<GeneratingChannel> GetGeneratingChannels(this DbSet<GuildConfig> configs)
|
||||
=> configs.AsQueryable()
|
||||
.Include(x => x.GenerateCurrencyChannelIds)
|
||||
.Where(x => x.GenerateCurrencyChannelIds.Any())
|
||||
.SelectMany(x => x.GenerateCurrencyChannelIds)
|
||||
.Select(x => new GeneratingChannel
|
||||
{
|
||||
ChannelId = x.ChannelId,
|
||||
GuildId = x.GuildConfig.GuildId
|
||||
})
|
||||
.ToArray();
|
||||
.Include(x => x.GenerateCurrencyChannelIds)
|
||||
.Where(x => x.GenerateCurrencyChannelIds.Any())
|
||||
.SelectMany(x => x.GenerateCurrencyChannelIds)
|
||||
.Select(x => new GeneratingChannel
|
||||
{
|
||||
ChannelId = x.ChannelId,
|
||||
GuildId = x.GuildConfig.GuildId
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
public class GeneratingChannel
|
||||
{
|
||||
|
@@ -1,53 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class QuoteExtensions
|
||||
{
|
||||
public static IEnumerable<Quote> GetForGuild(this DbSet<Quote> quotes, ulong guildId)
|
||||
=> quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
||||
|
||||
public static IReadOnlyCollection<Quote> GetGroup(
|
||||
this DbSet<Quote> quotes,
|
||||
ulong guildId,
|
||||
int page,
|
||||
OrderType order)
|
||||
{
|
||||
var q = quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
||||
if (order == OrderType.Keyword)
|
||||
q = q.OrderBy(x => x.Keyword);
|
||||
else
|
||||
q = q.OrderBy(x => x.Id);
|
||||
|
||||
return q.Skip(15 * page).Take(15).ToArray();
|
||||
}
|
||||
|
||||
public static async Task<Quote> GetRandomQuoteByKeywordAsync(
|
||||
this DbSet<Quote> quotes,
|
||||
ulong guildId,
|
||||
string keyword)
|
||||
{
|
||||
return (await quotes.AsQueryable().Where(q => q.GuildId == guildId && q.Keyword == keyword).ToArrayAsync())
|
||||
.RandomOrDefault();
|
||||
}
|
||||
|
||||
public static async Task<Quote> SearchQuoteKeywordTextAsync(
|
||||
this DbSet<Quote> quotes,
|
||||
ulong guildId,
|
||||
string keyword,
|
||||
string text)
|
||||
{
|
||||
return (await quotes.AsQueryable()
|
||||
.Where(q => q.GuildId == guildId
|
||||
&& (keyword == null || q.Keyword == keyword)
|
||||
&& (EF.Functions.Like(q.Text.ToUpper(), $"%{text.ToUpper()}%")
|
||||
|| EF.Functions.Like(q.AuthorName, text)))
|
||||
.ToArrayAsync())
|
||||
.RandomOrDefault();
|
||||
}
|
||||
|
||||
public static void RemoveAllByKeyword(this DbSet<Quote> quotes, ulong guildId, string keyword)
|
||||
=> quotes.RemoveRange(quotes.AsQueryable().Where(x => x.GuildId == guildId && x.Keyword.ToUpper() == keyword));
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
#nullable disable
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class SelfAssignableRolesExtensions
|
||||
{
|
||||
public static bool DeleteByGuildAndRoleId(this DbSet<SelfAssignedRole> roles, ulong guildId, ulong roleId)
|
||||
{
|
||||
var role = roles.FirstOrDefault(s => s.GuildId == guildId && s.RoleId == roleId);
|
||||
|
||||
if (role is null)
|
||||
return false;
|
||||
|
||||
roles.Remove(role);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static IReadOnlyCollection<SelfAssignedRole> GetFromGuild(this DbSet<SelfAssignedRole> roles, ulong guildId)
|
||||
=> roles.AsQueryable().Where(s => s.GuildId == guildId).ToArray();
|
||||
}
|
@@ -1,14 +1,15 @@
|
||||
#nullable disable
|
||||
using LinqToDB;
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public static class UserXpExtensions
|
||||
{
|
||||
public static async Task<UserXpStats?> GetGuildUserXp(this ITable<UserXpStats> table, ulong guildId, ulong userId)
|
||||
=> await table.FirstOrDefaultAsyncLinqToDB(x => x.GuildId == guildId && x.UserId == userId);
|
||||
|
||||
public static UserXpStats GetOrCreateUserXpStats(this DbContext ctx, ulong guildId, ulong userId)
|
||||
{
|
||||
var usr = ctx.Set<UserXpStats>().FirstOrDefault(x => x.UserId == userId && x.GuildId == guildId);
|
||||
@@ -19,7 +20,6 @@ public static class UserXpExtensions
|
||||
{
|
||||
Xp = 0,
|
||||
UserId = userId,
|
||||
NotifyOnLevelUp = XpNotificationLocation.None,
|
||||
GuildId = guildId
|
||||
});
|
||||
}
|
||||
@@ -27,46 +27,31 @@ public static class UserXpExtensions
|
||||
return usr;
|
||||
}
|
||||
|
||||
public static List<UserXpStats> GetUsersFor(this DbSet<UserXpStats> xps, ulong guildId, int page)
|
||||
=> xps.AsQueryable()
|
||||
.AsNoTracking()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.OrderByDescending(x => x.Xp + x.AwardedXp)
|
||||
.Skip(page * 9)
|
||||
.Take(9)
|
||||
.ToList();
|
||||
public static async Task<List<UserXpStats>> GetTopUserXps(this DbSet<UserXpStats> xps, ulong guildId, int count)
|
||||
=> await xps.ToLinqToDBTable()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.OrderByDescending(x => x.Xp)
|
||||
.Take(count)
|
||||
.ToListAsyncLinqToDB();
|
||||
|
||||
public static List<UserXpStats> GetTopUserXps(this DbSet<UserXpStats> xps, ulong guildId, int count)
|
||||
=> xps.AsQueryable()
|
||||
.AsNoTracking()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.OrderByDescending(x => x.Xp + x.AwardedXp)
|
||||
.Take(count)
|
||||
.ToList();
|
||||
|
||||
public static int GetUserGuildRanking(this DbSet<UserXpStats> xps, ulong userId, ulong guildId)
|
||||
=> xps.AsQueryable()
|
||||
.AsNoTracking()
|
||||
.Where(x => x.GuildId == guildId
|
||||
&& x.Xp + x.AwardedXp
|
||||
> xps.AsQueryable()
|
||||
.Where(y => y.UserId == userId && y.GuildId == guildId)
|
||||
.Select(y => y.Xp + y.AwardedXp)
|
||||
.FirstOrDefault())
|
||||
.Count()
|
||||
public static async Task<int> GetUserGuildRanking(this DbSet<UserXpStats> xps, ulong userId, ulong guildId)
|
||||
=> await xps.ToLinqToDBTable()
|
||||
.Where(x => x.GuildId == guildId
|
||||
&& x.Xp
|
||||
> xps.AsQueryable()
|
||||
.Where(y => y.UserId == userId && y.GuildId == guildId)
|
||||
.Select(y => y.Xp)
|
||||
.FirstOrDefault())
|
||||
.CountAsyncLinqToDB()
|
||||
+ 1;
|
||||
|
||||
public static void ResetGuildUserXp(this DbSet<UserXpStats> xps, ulong userId, ulong guildId)
|
||||
=> xps.Delete(x => x.UserId == userId && x.GuildId == guildId);
|
||||
|
||||
public static void ResetGuildXp(this DbSet<UserXpStats> xps, ulong guildId)
|
||||
=> xps.Delete(x => x.GuildId == guildId);
|
||||
|
||||
|
||||
public static async Task<LevelStats> GetLevelDataFor(this ITable<UserXpStats> userXp, ulong guildId, ulong userId)
|
||||
=> await userXp
|
||||
.Where(x => x.GuildId == guildId && x.UserId == userId)
|
||||
.FirstOrDefaultAsyncLinqToDB() is UserXpStats uxs
|
||||
? new(uxs.Xp + uxs.AwardedXp)
|
||||
: new(0);
|
||||
|
||||
=> await userXp
|
||||
.Where(x => x.GuildId == guildId && x.UserId == userId)
|
||||
.FirstOrDefaultAsyncLinqToDB() is UserXpStats uxs
|
||||
? new(uxs.Xp)
|
||||
: new(0);
|
||||
}
|
@@ -22,8 +22,7 @@ public static class WarningExtensions
|
||||
string mod,
|
||||
int index)
|
||||
{
|
||||
if (index < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(index);
|
||||
|
||||
var warn = warnings.AsQueryable()
|
||||
.Where(x => x.GuildId == guildId && x.UserId == userId)
|
||||
|
@@ -4,38 +4,28 @@ namespace NadekoBot.Db;
|
||||
|
||||
public readonly struct LevelStats
|
||||
{
|
||||
public const int XP_REQUIRED_LVL_1 = 36;
|
||||
|
||||
public long Level { get; }
|
||||
public long LevelXp { get; }
|
||||
public long RequiredXp { get; }
|
||||
public long TotalXp { get; }
|
||||
|
||||
public LevelStats(long xp)
|
||||
public LevelStats(long totalXp)
|
||||
{
|
||||
if (xp < 0)
|
||||
xp = 0;
|
||||
if (totalXp < 0)
|
||||
totalXp = 0;
|
||||
|
||||
TotalXp = xp;
|
||||
|
||||
const int baseXp = XP_REQUIRED_LVL_1;
|
||||
|
||||
var required = baseXp;
|
||||
var totalXp = 0;
|
||||
var lvl = 1;
|
||||
while (true)
|
||||
{
|
||||
required = (int)(baseXp + (baseXp / 4.0 * (lvl - 1)));
|
||||
|
||||
if (required + totalXp > xp)
|
||||
break;
|
||||
|
||||
totalXp += required;
|
||||
lvl++;
|
||||
}
|
||||
|
||||
Level = lvl - 1;
|
||||
LevelXp = xp - totalXp;
|
||||
RequiredXp = required;
|
||||
TotalXp = totalXp;
|
||||
Level = GetLevelByTotalXp(totalXp);
|
||||
LevelXp = totalXp - GetTotalXpReqForLevel(Level);
|
||||
RequiredXp = (9 * (Level + 1)) + 27;
|
||||
}
|
||||
|
||||
public static LevelStats CreateForLevel(long level)
|
||||
=> new(GetTotalXpReqForLevel(level));
|
||||
|
||||
public static long GetTotalXpReqForLevel(long level)
|
||||
=> ((9 * level * level) + (63 * level)) / 2;
|
||||
|
||||
public static long GetLevelByTotalXp(long totalXp)
|
||||
=> (long)((-7.0 / 2) + (1 / 6.0 * Math.Sqrt((8 * totalXp) + 441)));
|
||||
}
|
@@ -3,6 +3,8 @@ namespace NadekoBot.Db.Models;
|
||||
|
||||
public class DelMsgOnCmdChannel : DbEntity
|
||||
{
|
||||
public int GuildConfigId { get; set; }
|
||||
|
||||
public ulong ChannelId { get; set; }
|
||||
public bool State { get; set; }
|
||||
|
||||
|
@@ -7,7 +7,7 @@ public class DiscordUser : DbEntity
|
||||
{
|
||||
public ulong UserId { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Discriminator { get; set; }
|
||||
// public string Discriminator { get; set; }
|
||||
public string AvatarId { get; set; }
|
||||
|
||||
public int? ClubId { get; set; }
|
||||
@@ -27,9 +27,6 @@ public class DiscordUser : DbEntity
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Discriminator) || Discriminator == "0000")
|
||||
return Username;
|
||||
|
||||
return Username + "#" + Discriminator;
|
||||
return Username;
|
||||
}
|
||||
}
|
8
src/NadekoBot/Db/Models/FlagTranslateChannel.cs
Normal file
8
src/NadekoBot/Db/Models/FlagTranslateChannel.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class FlagTranslateChannel : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
}
|
@@ -9,7 +9,8 @@ public class FollowedStream : DbEntity
|
||||
Picarto = 3,
|
||||
Youtube = 4,
|
||||
Facebook = 5,
|
||||
Trovo = 6
|
||||
Trovo = 6,
|
||||
Kick = 7,
|
||||
}
|
||||
|
||||
public ulong GuildId { get; set; }
|
||||
|
@@ -1,11 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class GroupName : DbEntity
|
||||
{
|
||||
public int GuildConfigId { get; set; }
|
||||
public GuildConfig GuildConfig { get; set; }
|
||||
|
||||
public int Number { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
@@ -5,14 +5,15 @@ namespace NadekoBot.Db.Models;
|
||||
public class GuildColors
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
public ulong GuildId { get; set; }
|
||||
|
||||
[Length(0, 9)]
|
||||
[MaxLength(9)]
|
||||
public string? OkColor { get; set; }
|
||||
|
||||
[Length(0, 9)]
|
||||
[MaxLength(9)]
|
||||
public string? ErrorColor { get; set; }
|
||||
|
||||
[Length(0, 9)]
|
||||
[MaxLength(9)]
|
||||
public string? PendingColor { get; set; }
|
||||
}
|
@@ -3,6 +3,7 @@ namespace NadekoBot.Db.Models;
|
||||
|
||||
public class GuildConfig : DbEntity
|
||||
{
|
||||
// public bool Keep { get; set; }
|
||||
public ulong GuildId { get; set; }
|
||||
|
||||
public string Prefix { get; set; }
|
||||
@@ -12,26 +13,11 @@ public class GuildConfig : DbEntity
|
||||
|
||||
public string AutoAssignRoleIds { get; set; }
|
||||
|
||||
//greet stuff
|
||||
public int AutoDeleteGreetMessagesTimer { get; set; } = 30;
|
||||
public int AutoDeleteByeMessagesTimer { get; set; } = 30;
|
||||
|
||||
public ulong GreetMessageChannelId { get; set; }
|
||||
public ulong ByeMessageChannelId { get; set; }
|
||||
|
||||
public bool SendDmGreetMessage { get; set; }
|
||||
public string DmGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
||||
|
||||
public bool SendChannelGreetMessage { get; set; }
|
||||
public string ChannelGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!";
|
||||
|
||||
public bool SendChannelByeMessage { get; set; }
|
||||
public string ChannelByeMessageText { get; set; } = "%user% has left!";
|
||||
|
||||
//self assignable roles
|
||||
//todo FUTURE: DELETE, UNUSED
|
||||
public bool ExclusiveSelfAssignedRoles { get; set; }
|
||||
public bool AutoDeleteSelfAssignedRoleMessages { get; set; }
|
||||
|
||||
|
||||
|
||||
//stream notifications
|
||||
public HashSet<FollowedStream> FollowedStreams { get; set; } = new();
|
||||
|
||||
@@ -50,31 +36,38 @@ public class GuildConfig : DbEntity
|
||||
public HashSet<FilterChannelId> FilterInvitesChannelIds { get; set; } = new();
|
||||
public HashSet<FilterLinksChannelId> FilterLinksChannelIds { get; set; } = new();
|
||||
|
||||
//public bool FilterLinks { get; set; }
|
||||
//public HashSet<FilterLinksChannelId> FilterLinksChannels { get; set; } = new HashSet<FilterLinksChannelId>();
|
||||
|
||||
public bool FilterWords { get; set; }
|
||||
public HashSet<FilteredWord> FilteredWords { get; set; } = new();
|
||||
public HashSet<FilterWordsChannelId> FilterWordsChannelIds { get; set; } = new();
|
||||
|
||||
// mute
|
||||
public HashSet<MutedUserId> MutedUsers { get; set; } = new();
|
||||
|
||||
public string MuteRoleName { get; set; }
|
||||
|
||||
// chatterbot
|
||||
public bool CleverbotEnabled { get; set; }
|
||||
|
||||
// protection
|
||||
public AntiRaidSetting AntiRaidSetting { get; set; }
|
||||
public AntiSpamSetting AntiSpamSetting { get; set; }
|
||||
public AntiAltSetting AntiAltSetting { get; set; }
|
||||
|
||||
// time
|
||||
public string Locale { get; set; }
|
||||
public string TimeZoneId { get; set; }
|
||||
|
||||
|
||||
// timers
|
||||
public HashSet<UnmuteTimer> UnmuteTimers { get; set; } = new();
|
||||
public HashSet<UnbanTimer> UnbanTimer { get; set; } = new();
|
||||
public HashSet<UnroleTimer> UnroleTimer { get; set; } = new();
|
||||
|
||||
// vcrole
|
||||
public HashSet<VcRoleInfo> VcRoleInfos { get; set; }
|
||||
|
||||
// aliases
|
||||
public HashSet<CommandAlias> CommandAliases { get; set; } = new();
|
||||
public List<WarningPunishment> WarnPunishments { get; set; } = new();
|
||||
public bool WarningsInitialized { get; set; }
|
||||
public HashSet<SlowmodeIgnoredUser> SlowmodeIgnoredUsers { get; set; }
|
||||
public HashSet<SlowmodeIgnoredRole> SlowmodeIgnoredRoles { get; set; }
|
||||
@@ -89,19 +82,10 @@ public class GuildConfig : DbEntity
|
||||
public List<FeedSub> FeedSubs { get; set; } = new();
|
||||
public bool NotifyStreamOffline { get; set; }
|
||||
public bool DeleteStreamOnlineMessage { get; set; }
|
||||
public List<GroupName> SelfAssignableRoleGroupNames { get; set; }
|
||||
public int WarnExpireHours { get; set; }
|
||||
public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear;
|
||||
|
||||
public bool DisableGlobalExpressions { get; set; } = false;
|
||||
|
||||
#region Boost Message
|
||||
|
||||
public bool SendBoostMessage { get; set; }
|
||||
public string BoostMessage { get; set; } = "%user% just boosted this server!";
|
||||
public ulong BoostMessageChannelId { get; set; }
|
||||
public int BoostMessageDeleteAfter { get; set; }
|
||||
public bool StickyRoles { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
11
src/NadekoBot/Db/Models/HoneypotChannel.cs
Normal file
11
src/NadekoBot/Db/Models/HoneypotChannel.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class HoneypotChannel
|
||||
{
|
||||
[Key]
|
||||
public ulong GuildId { get; set; }
|
||||
|
||||
public ulong ChannelId { get; set; }
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class IgnoredVoicePresenceChannel : DbEntity
|
||||
{
|
||||
public LogSetting LogSetting { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
}
|
19
src/NadekoBot/Db/Models/NCanvas/NCanvas.cs
Normal file
19
src/NadekoBot/Db/Models/NCanvas/NCanvas.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class NCPixel
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public required int Position { get; init; }
|
||||
|
||||
public required long Price { get; init; }
|
||||
|
||||
public required ulong OwnerId { get; init; }
|
||||
public required uint Color { get; init; }
|
||||
|
||||
[MaxLength(256)]
|
||||
public required string Text { get; init; }
|
||||
}
|
24
src/NadekoBot/Db/Models/Notify.cs
Normal file
24
src/NadekoBot/Db/Models/Notify.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class Notify
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
public NotifyType Type { get; set; }
|
||||
|
||||
[MaxLength(10_000)]
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public enum NotifyType
|
||||
{
|
||||
LevelUp = 0,
|
||||
Protection = 1, Prot = 1,
|
||||
AddRoleReward = 2,
|
||||
RemoveRoleReward = 3,
|
||||
}
|
@@ -33,10 +33,7 @@ public class Permissionv2 : DbEntity, IIndexed
|
||||
};
|
||||
|
||||
public static List<Permissionv2> GetDefaultPermlist
|
||||
=> new()
|
||||
{
|
||||
AllowAllPerm
|
||||
};
|
||||
=> [AllowAllPerm];
|
||||
}
|
||||
|
||||
public enum PrimaryPermissionType
|
||||
|
18
src/NadekoBot/Db/Models/SarGroup.cs
Normal file
18
src/NadekoBot/Db/Models/SarGroup.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public sealed class SarGroup
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public int GroupNumber { get; set; }
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong? RoleReq { get; set; }
|
||||
public ICollection<Sar> Roles { get; set; } = [];
|
||||
public bool IsExclusive { get; set; }
|
||||
|
||||
[MaxLength(100)]
|
||||
public string? Name { get; set; }
|
||||
}
|
@@ -40,6 +40,9 @@ public class StreamRoleSettings : DbEntity
|
||||
|
||||
public class StreamRoleBlacklistedUser : DbEntity
|
||||
{
|
||||
public int StreamRoleSettingsId { get; set; }
|
||||
public StreamRoleSettings StreamRoleSettings { get; set; }
|
||||
|
||||
public ulong UserId { get; set; }
|
||||
public string Username { get; set; }
|
||||
|
||||
@@ -57,6 +60,9 @@ public class StreamRoleBlacklistedUser : DbEntity
|
||||
|
||||
public class StreamRoleWhitelistedUser : DbEntity
|
||||
{
|
||||
public int StreamRoleSettingsId { get; set; }
|
||||
public StreamRoleSettings StreamRoleSettings { get; set; }
|
||||
|
||||
public ulong UserId { get; set; }
|
||||
public string Username { get; set; }
|
||||
|
||||
|
@@ -2,8 +2,9 @@
|
||||
|
||||
public class AntiAltSetting
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int GuildConfigId { get; set; }
|
||||
|
||||
public int Id { get; set; }
|
||||
public TimeSpan MinAge { get; set; }
|
||||
public PunishmentAction Action { get; set; }
|
||||
public int ActionDurationMinutes { get; set; }
|
||||
|
@@ -5,8 +5,7 @@ namespace NadekoBot.Db.Models;
|
||||
public class AntiRaidSetting : DbEntity
|
||||
{
|
||||
public int GuildConfigId { get; set; }
|
||||
public GuildConfig GuildConfig { get; set; }
|
||||
|
||||
|
||||
public int UserThreshold { get; set; }
|
||||
public int Seconds { get; set; }
|
||||
public PunishmentAction Action { get; set; }
|
||||
|
@@ -4,8 +4,7 @@
|
||||
public class AntiSpamSetting : DbEntity
|
||||
{
|
||||
public int GuildConfigId { get; set; }
|
||||
public GuildConfig GuildConfig { get; set; }
|
||||
|
||||
|
||||
public PunishmentAction Action { get; set; }
|
||||
public int MessageThreshold { get; set; } = 3;
|
||||
public int MuteTime { get; set; }
|
||||
|
27
src/NadekoBot/Db/Models/btnrole/ButtonRole.cs
Normal file
27
src/NadekoBot/Db/Models/btnrole/ButtonRole.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public sealed class ButtonRole
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
[MaxLength(200)]
|
||||
public string ButtonId { get; set; } = string.Empty;
|
||||
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
public ulong MessageId { get; set; }
|
||||
|
||||
public int Position { get; set; }
|
||||
public ulong RoleId { get; set; }
|
||||
|
||||
[MaxLength(100)]
|
||||
public string Emote { get; set; } = string.Empty;
|
||||
|
||||
[MaxLength(50)]
|
||||
public string Label { get; set; } = string.Empty;
|
||||
|
||||
public bool Exclusive { get; set; }
|
||||
}
|
@@ -14,17 +14,3 @@ public class FilterChannelId : DbEntity
|
||||
public override int GetHashCode()
|
||||
=> ChannelId.GetHashCode();
|
||||
}
|
||||
|
||||
public class FilterWordsChannelId : DbEntity
|
||||
{
|
||||
public ulong ChannelId { get; set; }
|
||||
|
||||
public bool Equals(FilterWordsChannelId other)
|
||||
=> ChannelId == other.ChannelId;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
=> obj is FilterWordsChannelId fci && Equals(fci);
|
||||
|
||||
public override int GetHashCode()
|
||||
=> ChannelId.GetHashCode();
|
||||
}
|
17
src/NadekoBot/Db/Models/filter/FilterWordsChannelId.cs
Normal file
17
src/NadekoBot/Db/Models/filter/FilterWordsChannelId.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
#nullable disable
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class FilterWordsChannelId : DbEntity
|
||||
{
|
||||
public int? GuildConfigId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
|
||||
public bool Equals(FilterWordsChannelId other)
|
||||
=> ChannelId == other.ChannelId;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
=> obj is FilterWordsChannelId fci && Equals(fci);
|
||||
|
||||
public override int GetHashCode()
|
||||
=> ChannelId.GetHashCode();
|
||||
}
|
@@ -3,6 +3,7 @@ namespace NadekoBot.Db.Models;
|
||||
|
||||
public class WarningPunishment : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
public int Count { get; set; }
|
||||
public PunishmentAction Punishment { get; set; }
|
||||
public int Time { get; set; }
|
||||
|
@@ -1,11 +1,24 @@
|
||||
#nullable disable
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class SelfAssignedRole : DbEntity
|
||||
public sealed class Sar
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong RoleId { get; set; }
|
||||
|
||||
public int Group { get; set; }
|
||||
public int LevelRequirement { get; set; }
|
||||
public int SarGroupId { get; set; }
|
||||
public int LevelReq { get; set; }
|
||||
}
|
||||
|
||||
public sealed class SarAutoDelete
|
||||
{
|
||||
[Key]
|
||||
public int Id { get; set; }
|
||||
|
||||
public ulong GuildId { get; set; }
|
||||
public bool IsEnabled { get; set; } = false;
|
||||
}
|
12
src/NadekoBot/Db/Models/roles/TempRole.cs
Normal file
12
src/NadekoBot/Db/Models/roles/TempRole.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public class TempRole
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public ulong GuildId { get; set; }
|
||||
public bool Remove { get; set; }
|
||||
public ulong RoleId { get; set; }
|
||||
public ulong UserId { get; set; }
|
||||
|
||||
public DateTime ExpiresAt { get; set; }
|
||||
}
|
@@ -1,32 +1,12 @@
|
||||
#nullable disable
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Contains data about usage of Patron-Only commands per user
|
||||
/// in order to provide support for quota limitations
|
||||
/// (allow user x who is pledging amount y to use the specified command only
|
||||
/// x amount of times in the specified time period)
|
||||
/// </summary>
|
||||
public class PatronQuota
|
||||
{
|
||||
public ulong UserId { get; set; }
|
||||
public FeatureType FeatureType { get; set; }
|
||||
public string Feature { get; set; }
|
||||
public uint HourlyCount { get; set; }
|
||||
public uint DailyCount { get; set; }
|
||||
public uint MonthlyCount { get; set; }
|
||||
}
|
||||
|
||||
public enum FeatureType
|
||||
{
|
||||
Command,
|
||||
Group,
|
||||
Module,
|
||||
Limit
|
||||
}
|
||||
|
||||
public class PatronUser
|
||||
{
|
||||
// [Key]
|
||||
// public int Id { get; set; }
|
||||
public string UniquePlatformUserId { get; set; }
|
||||
public ulong UserId { get; set; }
|
||||
public int AmountCents { get; set; }
|
||||
|
@@ -6,8 +6,4 @@ public class UserXpStats : DbEntity
|
||||
public ulong UserId { get; set; }
|
||||
public ulong GuildId { get; set; }
|
||||
public long Xp { get; set; }
|
||||
public long AwardedXp { get; set; }
|
||||
public XpNotificationLocation NotifyOnLevelUp { get; set; }
|
||||
}
|
||||
|
||||
public enum XpNotificationLocation { None, Dm, Channel }
|
||||
}
|
8
src/NadekoBot/Db/Models/xp/XpNotificationLocation.cs
Normal file
8
src/NadekoBot/Db/Models/xp/XpNotificationLocation.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace NadekoBot.Db.Models;
|
||||
|
||||
public enum XpNotificationLocation
|
||||
{
|
||||
None,
|
||||
Dm,
|
||||
Channel
|
||||
}
|
@@ -51,6 +51,8 @@ public class XpCurrencyReward : DbEntity
|
||||
|
||||
public class ExcludedItem : DbEntity
|
||||
{
|
||||
public XpSettings XpSettings { get; set; }
|
||||
|
||||
public ulong ItemId { get; set; }
|
||||
public ExcludedItemType ItemType { get; set; }
|
||||
|
||||
|
@@ -1,38 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
|
||||
namespace NadekoBot.Db;
|
||||
|
||||
public sealed class MysqlContext : NadekoContext
|
||||
{
|
||||
private readonly string _connStr;
|
||||
private readonly string _version;
|
||||
|
||||
protected override string CurrencyTransactionOtherIdDefaultValue
|
||||
=> "NULL";
|
||||
|
||||
public MysqlContext(string connStr = "Server=localhost", string version = "8.0")
|
||||
{
|
||||
_connStr = connStr;
|
||||
_version = version;
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
optionsBuilder
|
||||
.UseLowerCaseNamingConvention()
|
||||
.UseMySql(_connStr, ServerVersion.Parse(_version));
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// mysql is case insensitive by default
|
||||
// we can set binary collation to change that
|
||||
modelBuilder.Entity<ClubInfo>()
|
||||
.Property(x => x.Name)
|
||||
.UseCollation("utf8mb4_bin");
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NadekoBot.Db.Models;
|
||||
using NadekoBot.Modules.Administration.Services;
|
||||
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||
|
||||
@@ -10,10 +11,10 @@ namespace NadekoBot.Db;
|
||||
public abstract class NadekoContext : DbContext
|
||||
{
|
||||
public DbSet<GuildConfig> GuildConfigs { get; set; }
|
||||
public DbSet<GreetSettings> GreetSettings { get; set; }
|
||||
|
||||
public DbSet<Quote> Quotes { get; set; }
|
||||
public DbSet<Reminder> Reminders { get; set; }
|
||||
public DbSet<SelfAssignedRole> SelfAssignableRoles { get; set; }
|
||||
public DbSet<MusicPlaylist> MusicPlaylists { get; set; }
|
||||
public DbSet<NadekoExpression> Expressions { get; set; }
|
||||
public DbSet<CurrencyTransaction> CurrencyTransactions { get; set; }
|
||||
@@ -28,7 +29,6 @@ public abstract class NadekoContext : DbContext
|
||||
|
||||
//logging
|
||||
public DbSet<LogSetting> LogSettings { get; set; }
|
||||
public DbSet<IgnoredVoicePresenceChannel> IgnoredVoicePresenceCHannels { get; set; }
|
||||
public DbSet<IgnoredLogItem> IgnoredLogChannels { get; set; }
|
||||
|
||||
public DbSet<RotatingPlayingStatus> RotatingStatus { get; set; }
|
||||
@@ -54,16 +54,15 @@ public abstract class NadekoContext : DbContext
|
||||
|
||||
public DbSet<PatronUser> Patrons { get; set; }
|
||||
|
||||
public DbSet<PatronQuota> PatronQuotas { get; set; }
|
||||
|
||||
public DbSet<StreamOnlineMessage> StreamOnlineMessages { get; set; }
|
||||
|
||||
|
||||
public DbSet<StickyRole> StickyRoles { get; set; }
|
||||
|
||||
|
||||
public DbSet<TodoModel> Todos { get; set; }
|
||||
public DbSet<ArchivedTodoListModel> TodosArchive { get; set; }
|
||||
|
||||
// todo add guild colors
|
||||
public DbSet<HoneypotChannel> HoneyPotChannels { get; set; }
|
||||
|
||||
|
||||
// public DbSet<GuildColors> GuildColors { get; set; }
|
||||
|
||||
|
||||
@@ -75,6 +74,136 @@ public abstract class NadekoContext : DbContext
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
// load all entities from current assembly
|
||||
modelBuilder.ApplyConfigurationsFromAssembly(typeof(NadekoContext).Assembly);
|
||||
|
||||
#region Notify
|
||||
|
||||
modelBuilder.Entity<Notify>(e =>
|
||||
{
|
||||
e.HasAlternateKey(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
Event = x.Type
|
||||
});
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region TempRoles
|
||||
|
||||
modelBuilder.Entity<TempRole>(e =>
|
||||
{
|
||||
e.HasAlternateKey(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.UserId,
|
||||
x.RoleId
|
||||
});
|
||||
|
||||
e.HasIndex(x => x.ExpiresAt);
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region GuildColors
|
||||
|
||||
modelBuilder.Entity<GuildColors>()
|
||||
.HasIndex(x => x.GuildId)
|
||||
.IsUnique(true);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Button Roles
|
||||
|
||||
modelBuilder.Entity<ButtonRole>(br =>
|
||||
{
|
||||
br.HasIndex(x => x.GuildId)
|
||||
.IsUnique(false);
|
||||
|
||||
br.HasAlternateKey(x => new
|
||||
{
|
||||
x.RoleId,
|
||||
x.MessageId,
|
||||
});
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region New Sar
|
||||
|
||||
modelBuilder.Entity<SarGroup>(sg =>
|
||||
{
|
||||
sg.HasAlternateKey(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.GroupNumber
|
||||
});
|
||||
|
||||
sg.HasMany(x => x.Roles)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Sar>()
|
||||
.HasAlternateKey(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.RoleId
|
||||
});
|
||||
|
||||
modelBuilder.Entity<SarAutoDelete>()
|
||||
.HasIndex(x => x.GuildId)
|
||||
.IsUnique();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Rakeback
|
||||
|
||||
modelBuilder.Entity<Rakeback>()
|
||||
.HasKey(x => x.UserId);
|
||||
|
||||
#endregion
|
||||
|
||||
#region UserBetStats
|
||||
|
||||
modelBuilder.Entity<UserBetStats>(ubs =>
|
||||
{
|
||||
ubs.HasIndex(x => new
|
||||
{
|
||||
x.UserId,
|
||||
x.Game
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
ubs.HasIndex(x => x.MaxWin)
|
||||
.IsUnique(false);
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region Flag Translate
|
||||
|
||||
modelBuilder.Entity<FlagTranslateChannel>()
|
||||
.HasIndex(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.ChannelId
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
#endregion
|
||||
|
||||
#region NCanvas
|
||||
|
||||
modelBuilder.Entity<NCPixel>()
|
||||
.HasAlternateKey(x => x.Position);
|
||||
|
||||
modelBuilder.Entity<NCPixel>()
|
||||
.HasIndex(x => x.OwnerId);
|
||||
|
||||
#endregion
|
||||
|
||||
#region QUOTES
|
||||
|
||||
var quoteEntity = modelBuilder.Entity<Quote>();
|
||||
@@ -86,15 +215,84 @@ public abstract class NadekoContext : DbContext
|
||||
#region GuildConfig
|
||||
|
||||
var configEntity = modelBuilder.Entity<GuildConfig>();
|
||||
|
||||
configEntity.HasIndex(c => c.GuildId)
|
||||
.IsUnique();
|
||||
|
||||
configEntity.Property(x => x.VerboseErrors)
|
||||
.HasDefaultValue(true);
|
||||
|
||||
modelBuilder.Entity<AntiSpamSetting>().HasOne(x => x.GuildConfig).WithOne(x => x.AntiSpamSetting);
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.DelMsgOnCmdChannels)
|
||||
.WithOne()
|
||||
.HasForeignKey(x => x.GuildConfigId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<AntiRaidSetting>().HasOne(x => x.GuildConfig).WithOne(x => x.AntiRaidSetting);
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.FollowedStreams)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.GenerateCurrencyChannelIds)
|
||||
.WithOne(x => x.GuildConfig)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.Permissions)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.CommandCooldowns)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.FilterInvitesChannelIds)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.FilterLinksChannelIds)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.FilteredWords)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.FilterWordsChannelIds)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.MutedUsers)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasOne(x => x.AntiRaidSetting)
|
||||
.WithOne()
|
||||
.HasForeignKey<AntiRaidSetting>(x => x.GuildConfigId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// start antispam
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasOne(x => x.AntiSpamSetting)
|
||||
.WithOne()
|
||||
.HasForeignKey<AntiSpamSetting>(x => x.GuildConfigId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<AntiSpamSetting>()
|
||||
.HasMany(x => x.IgnoredChannels)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// end antispam
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasOne(x => x.AntiAltSetting)
|
||||
@@ -102,6 +300,88 @@ public abstract class NadekoContext : DbContext
|
||||
.HasForeignKey<AntiAltSetting>(x => x.GuildConfigId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.UnmuteTimers)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.UnbanTimer)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.UnroleTimer)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.VcRoleInfos)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.CommandAliases)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.SlowmodeIgnoredRoles)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.SlowmodeIgnoredUsers)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// start shop
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.ShopEntries)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<ShopEntry>()
|
||||
.HasMany(x => x.Items)
|
||||
.WithOne()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// end shop
|
||||
|
||||
// start streamrole
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasOne(x => x.StreamRole)
|
||||
.WithOne(x => x.GuildConfig)
|
||||
.HasForeignKey<StreamRoleSettings>(x => x.GuildConfigId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<StreamRoleSettings>()
|
||||
.HasMany(x => x.Whitelist)
|
||||
.WithOne(x => x.StreamRoleSettings)
|
||||
.HasForeignKey(x => x.StreamRoleSettingsId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<StreamRoleSettings>()
|
||||
.HasMany(x => x.Blacklist)
|
||||
.WithOne(x => x.StreamRoleSettings)
|
||||
.HasForeignKey(x => x.StreamRoleSettingsId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// end streamrole
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasOne(x => x.XpSettings)
|
||||
.WithOne(x => x.GuildConfig)
|
||||
.HasForeignKey<XpSettings>(x => x.GuildConfigId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GuildConfig>()
|
||||
.HasMany(x => x.FeedSubs)
|
||||
.WithOne(x => x.GuildConfig)
|
||||
.HasForeignKey(x => x.GuildConfigId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<FeedSub>()
|
||||
.HasAlternateKey(x => new
|
||||
{
|
||||
@@ -117,24 +397,16 @@ public abstract class NadekoContext : DbContext
|
||||
|
||||
#endregion
|
||||
|
||||
#region streamrole
|
||||
#region WarningPunishments
|
||||
|
||||
modelBuilder.Entity<StreamRoleSettings>().HasOne(x => x.GuildConfig).WithOne(x => x.StreamRole);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Self Assignable Roles
|
||||
|
||||
var selfassignableRolesEntity = modelBuilder.Entity<SelfAssignedRole>();
|
||||
|
||||
selfassignableRolesEntity.HasIndex(s => new
|
||||
{
|
||||
s.GuildId,
|
||||
s.RoleId
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
selfassignableRolesEntity.Property(x => x.Group).HasDefaultValue(0);
|
||||
var warnpunishmentEntity = modelBuilder.Entity<WarningPunishment>(b =>
|
||||
{
|
||||
b.HasAlternateKey(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.Count
|
||||
});
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -184,6 +456,7 @@ public abstract class NadekoContext : DbContext
|
||||
du.HasIndex(x => x.TotalXp);
|
||||
du.HasIndex(x => x.CurrencyAmount);
|
||||
du.HasIndex(x => x.UserId);
|
||||
du.HasIndex(x => x.Username);
|
||||
});
|
||||
|
||||
#endregion
|
||||
@@ -213,13 +486,6 @@ public abstract class NadekoContext : DbContext
|
||||
xps.HasIndex(x => x.UserId);
|
||||
xps.HasIndex(x => x.GuildId);
|
||||
xps.HasIndex(x => x.Xp);
|
||||
xps.HasIndex(x => x.AwardedXp);
|
||||
|
||||
#endregion
|
||||
|
||||
#region XpSettings
|
||||
|
||||
modelBuilder.Entity<XpSettings>().HasOne(x => x.GuildConfig).WithOne(x => x.XpSettings);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -233,6 +499,21 @@ public abstract class NadekoContext : DbContext
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<XpSettings>()
|
||||
.HasMany(x => x.RoleRewards)
|
||||
.WithOne(x => x.XpSettings)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<XpSettings>()
|
||||
.HasMany(x => x.CurrencyRewards)
|
||||
.WithOne(x => x.XpSettings)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<XpSettings>()
|
||||
.HasMany(x => x.ExclusionList)
|
||||
.WithOne(x => x.XpSettings)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Club
|
||||
@@ -310,30 +591,13 @@ public abstract class NadekoContext : DbContext
|
||||
|
||||
#endregion
|
||||
|
||||
#region GroupName
|
||||
|
||||
modelBuilder.Entity<GroupName>()
|
||||
.HasIndex(x => new
|
||||
{
|
||||
x.GuildConfigId,
|
||||
x.Number
|
||||
})
|
||||
.IsUnique();
|
||||
|
||||
modelBuilder.Entity<GroupName>()
|
||||
.HasOne(x => x.GuildConfig)
|
||||
.WithMany(x => x.SelfAssignableRoleGroupNames)
|
||||
.IsRequired();
|
||||
|
||||
#endregion
|
||||
|
||||
#region BanTemplate
|
||||
|
||||
modelBuilder.Entity<BanTemplate>().HasIndex(x => x.GuildId).IsUnique();
|
||||
modelBuilder.Entity<BanTemplate>()
|
||||
.Property(x => x.PruneDays)
|
||||
.HasDefaultValue(null)
|
||||
.IsRequired(false);
|
||||
.Property(x => x.PruneDays)
|
||||
.HasDefaultValue(null)
|
||||
.IsRequired(false);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -433,19 +697,9 @@ public abstract class NadekoContext : DbContext
|
||||
});
|
||||
|
||||
// quotes are per user id
|
||||
modelBuilder.Entity<PatronQuota>(pq =>
|
||||
{
|
||||
pq.HasIndex(x => x.UserId).IsUnique(false);
|
||||
pq.HasKey(x => new
|
||||
{
|
||||
x.UserId,
|
||||
x.FeatureType,
|
||||
x.Feature
|
||||
});
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Xp Item Shop
|
||||
|
||||
modelBuilder.Entity<XpShopOwnedItem>(
|
||||
@@ -453,76 +707,100 @@ public abstract class NadekoContext : DbContext
|
||||
{
|
||||
// user can own only one of each item
|
||||
x.HasIndex(model => new
|
||||
{
|
||||
model.UserId,
|
||||
model.ItemType,
|
||||
model.ItemKey
|
||||
})
|
||||
.IsUnique();
|
||||
{
|
||||
model.UserId,
|
||||
model.ItemType,
|
||||
model.ItemKey
|
||||
})
|
||||
.IsUnique();
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region AutoPublish
|
||||
|
||||
modelBuilder.Entity<AutoPublishChannel>(apc => apc
|
||||
.HasIndex(x => x.GuildId)
|
||||
.IsUnique());
|
||||
.HasIndex(x => x.GuildId)
|
||||
.IsUnique());
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region GamblingStats
|
||||
|
||||
modelBuilder.Entity<GamblingStats>(gs => gs
|
||||
.HasIndex(x => x.Feature)
|
||||
.IsUnique());
|
||||
.HasIndex(x => x.Feature)
|
||||
.IsUnique());
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Sticky Roles
|
||||
|
||||
|
||||
modelBuilder.Entity<StickyRole>(sr => sr.HasIndex(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.UserId
|
||||
}).IsUnique());
|
||||
|
||||
{
|
||||
x.GuildId,
|
||||
x.UserId
|
||||
})
|
||||
.IsUnique());
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region Giveaway
|
||||
|
||||
modelBuilder.Entity<GiveawayModel>()
|
||||
.HasMany(x => x.Participants)
|
||||
.WithOne()
|
||||
.HasForeignKey(x => x.GiveawayId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
.HasMany(x => x.Participants)
|
||||
.WithOne()
|
||||
.HasForeignKey(x => x.GiveawayId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<GiveawayUser>(gu => gu
|
||||
.HasIndex(x => new
|
||||
{
|
||||
x.GiveawayId,
|
||||
x.UserId
|
||||
})
|
||||
.IsUnique());
|
||||
|
||||
.HasIndex(x => new
|
||||
{
|
||||
x.GiveawayId,
|
||||
x.UserId
|
||||
})
|
||||
.IsUnique());
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Todo
|
||||
|
||||
modelBuilder.Entity<TodoModel>()
|
||||
.HasKey(x => x.Id);
|
||||
|
||||
|
||||
modelBuilder.Entity<TodoModel>()
|
||||
.HasIndex(x => x.UserId)
|
||||
.IsUnique(false);
|
||||
|
||||
.HasIndex(x => x.UserId)
|
||||
.IsUnique(false);
|
||||
|
||||
modelBuilder.Entity<ArchivedTodoListModel>()
|
||||
.HasMany(x => x.Items)
|
||||
.WithOne()
|
||||
.HasForeignKey(x => x.ArchiveId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
.HasMany(x => x.Items)
|
||||
.WithOne()
|
||||
.HasForeignKey(x => x.ArchiveId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
#endregion
|
||||
|
||||
#region GreetSettings
|
||||
|
||||
modelBuilder
|
||||
.Entity<GreetSettings>(gs => gs.HasIndex(x => new
|
||||
{
|
||||
x.GuildId,
|
||||
x.GreetType
|
||||
})
|
||||
.IsUnique());
|
||||
|
||||
modelBuilder.Entity<GreetSettings>(gs =>
|
||||
{
|
||||
gs
|
||||
.Property(x => x.IsEnabled)
|
||||
.HasDefaultValue(false);
|
||||
|
||||
gs
|
||||
.Property(x => x.AutoDeleteTimer)
|
||||
.HasDefaultValue(0);
|
||||
});
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
@@ -44,8 +44,6 @@ public sealed class NadekoDbService : DbService
|
||||
case "postgres":
|
||||
case "pgsql":
|
||||
return new PostgreSqlContext(connString);
|
||||
case "mysql":
|
||||
return new MysqlContext(connString);
|
||||
case "sqlite":
|
||||
return new SqliteContext(connString);
|
||||
default:
|
||||
|
@@ -5,18 +5,57 @@ namespace NadekoBot.Migrations;
|
||||
|
||||
public static class MigrationQueries
|
||||
{
|
||||
public static void MergeAwardedXp(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql("""
|
||||
UPDATE UserXpStats
|
||||
SET Xp = AwardedXp + Xp,
|
||||
AwardedXp = 0
|
||||
WHERE AwardedXp > 0;
|
||||
""");
|
||||
}
|
||||
|
||||
public static void MigrateSar(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (migrationBuilder.IsNpgsql())
|
||||
return;
|
||||
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO GroupName (Number, GuildConfigId)
|
||||
SELECT DISTINCT "Group", GC.Id
|
||||
FROM SelfAssignableRoles as SAR
|
||||
INNER JOIN GuildConfigs as GC
|
||||
ON SAR.GuildId = GC.GuildId
|
||||
WHERE SAR.GuildId not in (SELECT GuildConfigs.GuildId from GroupName LEFT JOIN GuildConfigs ON GroupName.GuildConfigId = GuildConfigs.Id);
|
||||
|
||||
INSERT INTO SarGroup (Id, GroupNumber, Name, IsExclusive, GuildId)
|
||||
SELECT GN.Id, GN.Number, GN.Name, GC.ExclusiveSelfAssignedRoles, GC.GuildId
|
||||
FROM GroupName as GN
|
||||
INNER JOIN GuildConfigs as GC ON GN.GuildConfigId = GC.Id;
|
||||
|
||||
INSERT INTO Sar (GuildId, RoleId, SarGroupId, LevelReq)
|
||||
SELECT SAR.GuildId, SAR.RoleId, (SELECT Id FROM SarGroup WHERE SG.Number = SarGroup.GroupNumber AND SG.GuildId = SarGroup.GuildId), MIN(SAR.LevelRequirement)
|
||||
FROM SelfAssignableRoles as SAR
|
||||
INNER JOIN (SELECT GuildId, gn.Number FROM GroupName as gn
|
||||
INNER JOIN GuildConfigs as gc ON gn.GuildConfigId =gc.Id
|
||||
) as SG
|
||||
ON SG.GuildId = SAR.GuildId
|
||||
WHERE SG.Number IN (SELECT GroupNumber FROM SarGroup WHERE Sar.GuildId = SarGroup.GuildId)
|
||||
GROUP BY SAR.GuildId, SAR.RoleId;
|
||||
|
||||
INSERT INTO SarAutoDelete (GuildId, IsEnabled)
|
||||
SELECT GuildId, AutoDeleteSelfAssignedRoleMessages FROM GuildConfigs WHERE AutoDeleteSelfAssignedRoleMessages = TRUE;
|
||||
""");
|
||||
}
|
||||
|
||||
public static void UpdateUsernames(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql("UPDATE DiscordUser SET Username = '??' || Username WHERE Discriminator = '????';");
|
||||
}
|
||||
|
||||
public static void MigrateRero(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
if (migrationBuilder.IsMySql())
|
||||
{
|
||||
migrationBuilder.Sql(
|
||||
@"INSERT IGNORE into reactionroles(guildid, channelid, messageid, emote, roleid, `group`, levelreq, dateadded)
|
||||
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;");
|
||||
}
|
||||
else if (migrationBuilder.IsSqlite())
|
||||
if (migrationBuilder.IsSqlite())
|
||||
{
|
||||
migrationBuilder.Sql(
|
||||
@"insert or ignore into reactionroles(guildid, channelid, messageid, emote, roleid, 'group', levelreq, dateadded)
|
||||
@@ -27,7 +66,8 @@ left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;")
|
||||
}
|
||||
else if (migrationBuilder.IsNpgsql())
|
||||
{
|
||||
migrationBuilder.Sql(@"insert into reactionroles(guildid, channelid, messageid, emote, roleid, ""group"", levelreq, dateadded)
|
||||
migrationBuilder.Sql(
|
||||
@"insert into reactionroles(guildid, channelid, messageid, emote, roleid, ""group"", levelreq, dateadded)
|
||||
select guildid, channelid, messageid, emotename, roleid, exclusive::int, 0, reactionrolemessage.dateadded
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
@@ -39,4 +79,55 @@ left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;")
|
||||
throw new NotSupportedException("This database provider doesn't have an implementation for MigrateRero");
|
||||
}
|
||||
}
|
||||
|
||||
public static void GuildConfigCleanup(MigrationBuilder builder)
|
||||
{
|
||||
builder.Sql($"""
|
||||
DELETE FROM "DelMsgOnCmdChannel" WHERE "GuildConfigId" is NULL;
|
||||
DELETE FROM "WarningPunishment" WHERE "GuildConfigId" NOT IN (SELECT "Id" from "GuildConfigs");
|
||||
DELETE FROM "StreamRoleBlacklistedUser" WHERE "StreamRoleSettingsId" is NULL;
|
||||
DELETE FROM "Permissions" WHERE "GuildConfigId" NOT IN (SELECT "Id" from "GuildConfigs");
|
||||
""");
|
||||
}
|
||||
|
||||
public static void GreetSettingsCopy(MigrationBuilder builder)
|
||||
{
|
||||
builder.Sql("""
|
||||
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||
SELECT GuildId, 0, ChannelGreetMessageText, SendChannelGreetMessage, GreetMessageChannelId, AutoDeleteGreetMessagesTimer
|
||||
FROM GuildConfigs
|
||||
WHERE SendChannelGreetMessage = TRUE;
|
||||
|
||||
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||
SELECT GuildId, 1, DmGreetMessageText, SendDmGreetMessage, GreetMessageChannelId, 0
|
||||
FROM GuildConfigs
|
||||
WHERE SendDmGreetMessage = TRUE;
|
||||
|
||||
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||
SELECT GuildId, 2, ChannelByeMessageText, SendChannelByeMessage, ByeMessageChannelId, AutoDeleteByeMessagesTimer
|
||||
FROM GuildConfigs
|
||||
WHERE SendChannelByeMessage = TRUE;
|
||||
|
||||
INSERT INTO GreetSettings (GuildId, GreetType, MessageText, IsEnabled, ChannelId, AutoDeleteTimer)
|
||||
SELECT GuildId, 3, BoostMessage, SendBoostMessage, BoostMessageChannelId, BoostMessageDeleteAfter
|
||||
FROM GuildConfigs
|
||||
WHERE SendBoostMessage = TRUE;
|
||||
""");
|
||||
}
|
||||
|
||||
public static void AddGuildIdsToWarningPunishment(MigrationBuilder builder)
|
||||
{
|
||||
builder.Sql("""
|
||||
DELETE FROM WarningPunishment WHERE GuildConfigId IS NULL OR GuildConfigId NOT IN (SELECT Id FROM GuildConfigs);
|
||||
UPDATE WarningPunishment
|
||||
SET GuildId = (SELECT GuildId FROM GuildConfigs WHERE Id = GuildConfigId);
|
||||
|
||||
DELETE FROM WarningPunishment as wp
|
||||
WHERE (wp.Count, wp.GuildConfigId) in (
|
||||
SELECT wp2.Count, wp2.GuildConfigId FROM WarningPunishment as wp2
|
||||
GROUP BY wp2.Count, wp2.GuildConfigId
|
||||
HAVING COUNT(id) > 1
|
||||
);
|
||||
""");
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class stondel : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "deletestreamonlinemessage",
|
||||
table: "guildconfigs",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "deletestreamonlinemessage",
|
||||
table: "guildconfigs");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class bank : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "bankusers",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
balance = table.Column<long>(type: "bigint", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_bankusers", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_bankusers_userid",
|
||||
table: "bankusers",
|
||||
column: "userid",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "bankusers");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,121 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class newrero : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "reactionroles",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
guildid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
messageid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
emote = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
roleid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
group = table.Column<int>(type: "int", nullable: false),
|
||||
levelreq = table.Column<int>(type: "int", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_reactionroles", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reactionroles_guildid",
|
||||
table: "reactionroles",
|
||||
column: "guildid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reactionroles_messageid_emote",
|
||||
table: "reactionroles",
|
||||
columns: new[] { "messageid", "emote" },
|
||||
unique: true);
|
||||
|
||||
MigrationQueries.MigrateRero(migrationBuilder);
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "reactionrole");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "reactionrolemessage");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "reactionroles");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "reactionrolemessage",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
guildconfigid = table.Column<int>(type: "int", nullable: false),
|
||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||
exclusive = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
index = table.Column<int>(type: "int", nullable: false),
|
||||
messageid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_reactionrolemessage", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_reactionrolemessage_guildconfigs_guildconfigid",
|
||||
column: x => x.guildconfigid,
|
||||
principalTable: "guildconfigs",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "reactionrole",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||
emotename = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
reactionrolemessageid = table.Column<int>(type: "int", nullable: true),
|
||||
roleid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_reactionrole", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "fk_reactionrole_reactionrolemessage_reactionrolemessageid",
|
||||
column: x => x.reactionrolemessageid,
|
||||
principalTable: "reactionrolemessage",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reactionrole_reactionrolemessageid",
|
||||
table: "reactionrole",
|
||||
column: "reactionrolemessageid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_reactionrolemessage_guildconfigid",
|
||||
table: "reactionrolemessage",
|
||||
column: "guildconfigid");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,176 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class patronagesystem : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "patreonuserid",
|
||||
table: "rewardedusers",
|
||||
newName: "platformuserid");
|
||||
|
||||
migrationBuilder.RenameIndex(
|
||||
name: "ix_rewardedusers_patreonuserid",
|
||||
table: "rewardedusers",
|
||||
newName: "ix_rewardedusers_platformuserid");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "xp",
|
||||
table: "userxpstats",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "awardedxp",
|
||||
table: "userxpstats",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "amountrewardedthismonth",
|
||||
table: "rewardedusers",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int");
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "verboseerrors",
|
||||
table: "guildconfigs",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: true,
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "tinyint(1)");
|
||||
|
||||
migrationBuilder.AlterColumn<long>(
|
||||
name: "totalxp",
|
||||
table: "discorduser",
|
||||
type: "bigint",
|
||||
nullable: false,
|
||||
defaultValue: 0L,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "int",
|
||||
oldDefaultValue: 0);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "patronquotas",
|
||||
columns: table => new
|
||||
{
|
||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
featuretype = table.Column<int>(type: "int", nullable: false),
|
||||
feature = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
hourlycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
||||
dailycount = table.Column<uint>(type: "int unsigned", nullable: false),
|
||||
monthlycount = table.Column<uint>(type: "int unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_patronquotas", x => new { x.userid, x.featuretype, x.feature });
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "patrons",
|
||||
columns: table => new
|
||||
{
|
||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
uniqueplatformuserid = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
amountcents = table.Column<int>(type: "int", nullable: false),
|
||||
lastcharge = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
validthru = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_patrons", x => x.userid);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_patronquotas_userid",
|
||||
table: "patronquotas",
|
||||
column: "userid");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_patrons_uniqueplatformuserid",
|
||||
table: "patrons",
|
||||
column: "uniqueplatformuserid",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "patronquotas");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "patrons");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "platformuserid",
|
||||
table: "rewardedusers",
|
||||
newName: "patreonuserid");
|
||||
|
||||
migrationBuilder.RenameIndex(
|
||||
name: "ix_rewardedusers_platformuserid",
|
||||
table: "rewardedusers",
|
||||
newName: "ix_rewardedusers_patreonuserid");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "xp",
|
||||
table: "userxpstats",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "bigint");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "awardedxp",
|
||||
table: "userxpstats",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "bigint");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "amountrewardedthismonth",
|
||||
table: "rewardedusers",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "bigint");
|
||||
|
||||
migrationBuilder.AlterColumn<bool>(
|
||||
name: "verboseerrors",
|
||||
table: "guildconfigs",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
oldClrType: typeof(bool),
|
||||
oldType: "tinyint(1)",
|
||||
oldDefaultValue: true);
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "totalxp",
|
||||
table: "discorduser",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(long),
|
||||
oldType: "bigint",
|
||||
oldDefaultValue: 0L);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,39 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class stondeldbcache : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "streamonlinemessages",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
messageid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
type = table.Column<int>(type: "int", nullable: false),
|
||||
name = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_streamonlinemessages", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "streamonlinemessages");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class logwarns : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<ulong>(
|
||||
name: "logwarnsid",
|
||||
table: "logsettings",
|
||||
type: "bigint unsigned",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "logwarnsid",
|
||||
table: "logsettings");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,45 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class xpitemshop : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "xpshopowneditem",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "int", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
userid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||
itemtype = table.Column<int>(type: "int", nullable: false),
|
||||
isusing = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||
itemkey = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_xpshopowneditem", x => x.id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_xpshopowneditem_userid_itemtype_itemkey",
|
||||
table: "xpshopowneditem",
|
||||
columns: new[] { "userid", "itemtype", "itemkey" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "xpshopowneditem");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,26 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class linkonlychannels : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "type",
|
||||
table: "imageonlychannels",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "type",
|
||||
table: "imageonlychannels");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,49 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class removeobsoletexpcolumns : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "lastlevelup",
|
||||
table: "userxpstats");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "lastlevelup",
|
||||
table: "discorduser");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "lastxpgain",
|
||||
table: "discorduser");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "lastlevelup",
|
||||
table: "userxpstats",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValueSql: "(UTC_TIMESTAMP)");
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "lastlevelup",
|
||||
table: "discorduser",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValueSql: "(UTC_TIMESTAMP)");
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "lastxpgain",
|
||||
table: "discorduser",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValueSql: "(UTC_TIMESTAMP - INTERVAL 1 year)");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations.Mysql
|
||||
{
|
||||
public partial class banprune : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "prunedays",
|
||||
table: "bantemplates",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "prunedays",
|
||||
table: "bantemplates");
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user