Compare commits
73 commits
Author | SHA1 | Date | |
---|---|---|---|
ec0057ad19 | |||
a54880c71f | |||
2e4e317e45 | |||
231e77452f | |||
76bafd076f | |||
c5442f9144 | |||
6f64a15cd4 | |||
0ee5c0dd94 | |||
11b3705939 | |||
5e95abadc8 | |||
da0eff4339 | |||
3653d97c90 | |||
81677ee761 | |||
0ead1290e9 | |||
dc12a7558e | |||
b45d4f9e44 | |||
e07b95d302 | |||
00cac99cda | |||
13496e4a51 | |||
600625c83c | |||
9cd67a22c4 | |||
71242d3e80 | |||
e01f48b2e9 | |||
f391e07b2e | |||
06b17e3835 | |||
343e74be6b | |||
4f1cdde9b2 | |||
d9c27021aa | |||
acdb707a31 | |||
0ea185f769 | |||
c40b98786c | |||
cd62822697 | |||
204f426764 | |||
4b0f00e81f | |||
5a235b0565 | |||
37601286f5 | |||
9f660431c2 | |||
06970eb9d3 | |||
dbc312dd9d | |||
5d9326b65e | |||
96c4ea0637 | |||
fd464731d5 | |||
a960a1b277 | |||
4192d493df | |||
f5a0c81e64 | |||
fcb3d8d73d | |||
6ef732a1f0 | |||
3f26f9f8f5 | |||
138d3441e4 | |||
fda37f0e15 | |||
fd5b7959c5 | |||
964833502c | |||
8a9e117366 | |||
0e2e9c0ec6 | |||
86a4a1ca99 | |||
fb2642904d | |||
bc4ab57a67 | |||
4c572d25d8 | |||
53179abfbb | |||
12bcae137a | |||
3dcf08baf5 | |||
de8da558f7 | |||
5cb344455a | |||
5450d40bae | |||
e97fbe64c5 | |||
c66968856d | |||
45b507bf79 | |||
211f610d28 | |||
df17221c67 | |||
6d70f28db7 | |||
3e96405954 | |||
ba01b9ae6a | |||
2138d94d56 |
376 changed files with 13508 additions and 264886 deletions
.dockerignore.gitignoreDockerfileLICENSEdocker-entrypoint.shexe_builder.iss
src
Ellie.Marmalade
EllieBot.Coordinator
EllieBot.Generators
EllieBot.GrpcApiBase
EllieBot.Tests
BotStringsTests.csConcurrentHashSetTests.csEllieBot.Tests.csprojFishTests.csIndexedCollectionTests.csKwumTests.csNewDeckTests.csPubSubTests.csRandom.cs
EllieBot.Voice
EllieBot.VotesApi
EllieBot
.editorconfigBot.cs
Db
EllieContext.csEllieDbService.cs
EllieBot.csprojEllieBot.csproj.DotSettingsExtensions
Models
Migrations
MigrationQueries.cs
PostgreSql
20220409170719_mysql-init.Designer.cs20220428044547_stondel.Designer.cs20220428044547_stondel.cs20220429044808_bank.Designer.cs20220429044808_bank.cs20220504162457_new-rero.Designer.cs20220504162457_new-rero.cs20220614071421_patronage-system.Designer.cs20220614071421_patronage-system.cs20220623090729_stondel-db-cache.Designer.cs20220623090729_stondel-db-cache.cs20220703194412_logwarns.Designer.cs20220703194412_logwarns.cs20220725155941_xpitemshop.Designer.cs20220725155941_xpitemshop.cs20220727033944_linkonly-channels.Designer.cs20220727033944_linkonly-channels.cs20220808142559_remove-obsolete-xp-columns.Designer.cs20220808142559_remove-obsolete-xp-columns.cs20220831142735_banprune.Designer.cs20220831142735_banprune.cs20220913192529_shop-role-req.Designer.cs20220913192529_shop-role-req.cs20220916194523_autopub.Designer.cs20220916194523_autopub.cs
|
@ -10,4 +10,5 @@
|
||||||
|
|
||||||
# ignore bin and obj folders in projects
|
# ignore bin and obj folders in projects
|
||||||
src/**/bin/*
|
src/**/bin/*
|
||||||
src/**/obj/*
|
src/**/obj/*
|
||||||
|
src/EllieBot/data/creds.yml
|
20
.gitignore
vendored
20
.gitignore
vendored
|
@ -7,19 +7,13 @@ src/EllieBot/data/marmalades/
|
||||||
|
|
||||||
# other
|
# other
|
||||||
|
|
||||||
command_errors*.txt
|
|
||||||
output/
|
output/
|
||||||
src/EllieBot/output
|
src/EllieBot/output
|
||||||
src/EllieBot/creds.yml
|
src/EllieBot/creds.yml
|
||||||
|
src/EllieBot/data/creds.yml
|
||||||
src/EllieBot/Command Errors*.txt
|
src/EllieBot/Command Errors*.txt
|
||||||
|
src/EllieBot/data/EllieBot.db.*
|
||||||
src/EllieBot/creds.yml
|
# scripts
|
||||||
# credentials file before and after v3
|
|
||||||
src/EllieBot/credentials.json
|
|
||||||
src/EllieBot/old_credentials.json
|
|
||||||
src/EllieBot/credentials.json.bak
|
|
||||||
src/EllieBot/data/EllieBot.db
|
|
||||||
ellie-menu.ps1
|
ellie-menu.ps1
|
||||||
package.sh
|
package.sh
|
||||||
|
|
||||||
|
@ -371,4 +365,10 @@ __pycache__/
|
||||||
|
|
||||||
### VisualStudio Patch ###
|
### VisualStudio Patch ###
|
||||||
build/
|
build/
|
||||||
site/
|
site/
|
||||||
|
|
||||||
|
## AI
|
||||||
|
|
||||||
|
.aider.*
|
||||||
|
PROMPT.md
|
||||||
|
.aider*
|
57
Dockerfile
57
Dockerfile
|
@ -1,4 +1,4 @@
|
||||||
# Use the .NET 8.0 SDK as the base image for the build stage
|
# Build stage
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
WORKDIR /source
|
WORKDIR /source
|
||||||
|
|
||||||
|
@ -8,53 +8,42 @@ COPY src/EllieBot/*.csproj src/EllieBot/
|
||||||
COPY src/EllieBot.Coordinator/*.csproj src/EllieBot.Coordinator/
|
COPY src/EllieBot.Coordinator/*.csproj src/EllieBot.Coordinator/
|
||||||
COPY src/EllieBot.Generators/*.csproj src/EllieBot.Generators/
|
COPY src/EllieBot.Generators/*.csproj src/EllieBot.Generators/
|
||||||
COPY src/EllieBot.Voice/*.csproj src/EllieBot.Voice/
|
COPY src/EllieBot.Voice/*.csproj src/EllieBot.Voice/
|
||||||
|
COPY src/EllieBot.GrpcApiBase/*.csproj src/EllieBot.GrpcApiBase/
|
||||||
|
|
||||||
# Restore the dependencies for the EllieBot project
|
# Restore the dependencies for the EllieBot project
|
||||||
RUN dotnet restore src/EllieBot/
|
RUN dotnet restore src/EllieBot/ -r linux-musl-x64
|
||||||
|
|
||||||
# Copy the rest of the source code
|
# Copy the rest of the source code
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Set the working directory to the EllieBot project
|
|
||||||
WORKDIR /source/src/EllieBot
|
WORKDIR /source/src/EllieBot
|
||||||
|
|
||||||
# Build and publish the EllieBot project, then clean up unnecessary files
|
# Build for linux-musl-x64 runtime as the image is based on alpine
|
||||||
RUN set -xe; \
|
RUN dotnet publish -c Release -o /app --self-contained -r linux-musl-x64 --no-restore \
|
||||||
dotnet --version; \
|
&& mv /app/data /app/data_init \
|
||||||
dotnet restore; \
|
&& chmod +x /app/EllieBot
|
||||||
dotnet publish -c Release -o /app --no-restore; \
|
|
||||||
mv /app/data /app/data_init; \
|
|
||||||
rm -Rf libopus* libsodium* opus.* runtimes/win* runtimes/osx* runtimes/linux-arm* runtimes/linux-mips*; \
|
|
||||||
find /app -type f -exec chmod -x {} \; ;\
|
|
||||||
chmod +x /app/EllieBot
|
|
||||||
|
|
||||||
# Use the .NET 8.0 runtime as the base image for the final stage
|
# Final stage
|
||||||
FROM mcr.microsoft.com/dotnet/runtime:8.0
|
FROM alpine:3.20
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Create a new user, install dependencies, and set up sudoers file
|
# Music dependencies
|
||||||
RUN set -xe; \
|
ADD --chmod=755 https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux /usr/local/bin/yt-dlp
|
||||||
useradd -m ellie; \
|
RUN apk add --no-cache ffmpeg libsodium
|
||||||
apt-get update; \
|
|
||||||
apt-get install -y --no-install-recommends libopus0 libsodium23 libsqlite3-0 curl ffmpeg python3 sudo; \
|
# Required dependencies
|
||||||
echo 'Defaults>ellie env_keep+="ASPNETCORE_* DOTNET_* EllieBot_* shard_id total_shards TZ"' > /etc/sudoers.d/ellie; \
|
# icu-libs is required for globalization
|
||||||
curl -Lo /usr/local/bin/yt-dlp https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp; \
|
RUN apk update; \
|
||||||
chmod a+rx /usr/local/bin/yt-dlp; \
|
apk add --no-cache libstdc++ libgcc icu-libs libc6-compat \
|
||||||
apt-get autoremove -y; \
|
&& rm -rf /var/cache/apk/*;
|
||||||
apt-get autoclean -y
|
|
||||||
|
|
||||||
# Copy the built application and the entrypoint script from the build stage
|
|
||||||
COPY --from=build /app ./
|
COPY --from=build /app ./
|
||||||
COPY docker-entrypoint.sh /usr/local/sbin
|
COPY docker-entrypoint.sh /usr/local/sbin/
|
||||||
|
|
||||||
# Set environment variables
|
RUN rm /app/data_init/lib/libsodium.so \
|
||||||
ENV shard_id=0
|
&& ln -s /usr/lib/libsodium.so.26 /app/data_init/lib/libsodium.so
|
||||||
ENV total_shards=1
|
|
||||||
ENV EllieBot__creds=/app/data/creds.yml
|
|
||||||
|
|
||||||
# Define the data directory as a volume
|
VOLUME [ "/app/data" ]
|
||||||
VOLUME [" /app/data "]
|
|
||||||
|
|
||||||
# Set the entrypoint and default command
|
|
||||||
ENTRYPOINT [ "/usr/local/sbin/docker-entrypoint.sh" ]
|
ENTRYPOINT [ "/usr/local/sbin/docker-entrypoint.sh" ]
|
||||||
CMD dotnet EllieBot.dll "$shard_id" "$total_shards"
|
CMD [ "./EllieBot" ]
|
756
LICENSE
756
LICENSE
|
@ -1,201 +1,619 @@
|
||||||
Apache License
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
Version 2.0, January 2004
|
Version 3, 19 November 2007
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
1. Definitions.
|
Preamble
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
The licenses for most software and other practical works are designed
|
||||||
the copyright owner that is granting the License.
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
When we speak of free software, we are referring to freedom, not
|
||||||
other entities that control, are controlled by, or are under common
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
control with that entity. For the purposes of this definition,
|
have the freedom to distribute copies of free software (and charge for
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
them if you wish), that you receive source code or can get it if you
|
||||||
direction or management of such entity, whether by contract or
|
want it, that you can change the software or use pieces of it in new
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
free programs, and that you know you can do these things.
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
Developers that use our General Public Licenses protect your rights
|
||||||
exercising permissions granted by this License.
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
A secondary benefit of defending all users' freedom is that
|
||||||
including but not limited to software source code, documentation
|
improvements made in alternate versions of the program, if they
|
||||||
source, and configuration files.
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
The GNU Affero General Public License is designed specifically to
|
||||||
transformation or translation of a Source form, including but
|
ensure that, in such cases, the modified source code becomes available
|
||||||
not limited to compiled object code, generated documentation,
|
to the community. It requires the operator of a network server to
|
||||||
and conversions to other media types.
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
An older license, called the Affero General Public License and
|
||||||
Object form, made available under the License, as indicated by a
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
copyright notice that is included in or attached to the work
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
(an example is provided in the Appendix below).
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
The precise terms and conditions for copying, distribution and
|
||||||
form, that is based on (or derived from) the Work and for which the
|
modification follow.
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
TERMS AND CONDITIONS
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
0. Definitions.
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
works, such as semiconductor masks.
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
modifications, and in Source or Object form, provided that You
|
"recipients" may be individuals or organizations.
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
Derivative Works a copy of this License; and
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
A "covered work" means either the unmodified Program or a work based
|
||||||
stating that You changed the files; and
|
on the Program.
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
To "propagate" a work means to do anything with it that, without
|
||||||
that You distribute, all copyright, patent, trademark, and
|
permission, would make you directly or secondarily liable for
|
||||||
attribution notices from the Source form of the Work,
|
infringement under applicable copyright law, except executing it on a
|
||||||
excluding those notices that do not pertain to any part of
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
the Derivative Works; and
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
To "convey" a work means any kind of propagation that enables other
|
||||||
distribution, then any Derivative Works that You distribute must
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
include a readable copy of the attribution notices contained
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
may provide additional or different license terms and conditions
|
to the extent that it includes a convenient and prominently visible
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
tells the user that there is no warranty for the work (except to the
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
extent that warranties are provided), that licensees may convey the
|
||||||
the conditions stated in this License.
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
1. Source Code.
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
The "source code" for a work means the preferred form of the work
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
for making modifications to it. "Object code" means any non-source
|
||||||
except as required for reasonable and customary use in describing the
|
form of a work.
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
A "Standard Interface" means an interface that either is an official
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
standard defined by a recognized standards body, or, in the case of
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
interfaces specified for a particular programming language, one that
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
is widely used among developers working in that language.
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
The "System Libraries" of an executable work include anything, other
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
unless required by applicable law (such as deliberate and grossly
|
packaging a Major Component, but which is not part of that Major
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
Component, and (b) serves only to enable use of the work with that
|
||||||
liable to You for damages, including any direct, indirect, special,
|
Major Component, or to implement a Standard Interface for which an
|
||||||
incidental, or consequential damages of any character arising as a
|
implementation is available to the public in source code form. A
|
||||||
result of this License or out of the use or inability to use the
|
"Major Component", in this context, means a major essential component
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
(kernel, window system, and so on) of the specific operating system
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
other commercial damages or losses), even if such Contributor
|
produce the work, or an object code interpreter used to run it.
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
The "Corresponding Source" for a work in object code form means all
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
the source code needed to generate, install, and (for an executable
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
work) run the object code and to modify the work, including scripts to
|
||||||
or other liability obligations and/or rights consistent with this
|
control those activities. However, it does not include the work's
|
||||||
License. However, in accepting such obligations, You may act only
|
System Libraries, or general-purpose tools or generally available free
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
programs which are used unmodified in performing those activities but
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
which are not part of the work. For example, Corresponding Source
|
||||||
defend, and hold each Contributor harmless for any liability
|
includes interface definition files associated with source files for
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
the work, and the source code for shared libraries and dynamically
|
||||||
of your accepting any such warranty or additional liability.
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
2. Basic Permissions.
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright 2024 Toastie_t0ast
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
You may make, run and propagate covered works that you do not
|
||||||
you may not use this file except in compliance with the License.
|
convey, without conditions so long as your license otherwise remains
|
||||||
You may obtain a copy of the License at
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
No covered work shall be deemed part of an effective technological
|
||||||
See the License for the specific language governing permissions and
|
measure under any applicable law fulfilling obligations under article
|
||||||
limitations under the License.
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
|
@ -1,28 +1,20 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e;
|
|
||||||
|
|
||||||
data_init=/app/data_init
|
set -e
|
||||||
data=/app/data
|
|
||||||
|
|
||||||
# populate /app/data if empty
|
data_init="/app/data_init"
|
||||||
for i in $(ls $data_init)
|
data="/app/data"
|
||||||
do
|
|
||||||
if [ ! -e "$data/$i" ]; then
|
|
||||||
[ -f "$data_init/$i" ] && cp "$data_init/$i" "$data/$i"
|
|
||||||
[ -d "$data_init/$i" ] && cp -r "$data_init/$i" "$data/$i"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# creds.yml migration
|
ls $data
|
||||||
if [ -f /app/creds.yml ]; then
|
# Merge data_init into data without overwrites.
|
||||||
echo "Default location for creds.yml is now /app/data/creds.yml."
|
cp -R -n $data_init/* $data
|
||||||
echo "Please move your creds.yml and update your docker-compose.yml accordingly."
|
cp -n "$data_init/creds_example.yml" "$data/creds.yml"
|
||||||
|
|
||||||
export Ellie_creds=/app/creds.yml
|
ls $data
|
||||||
fi
|
|
||||||
|
|
||||||
# ensure ellie can write on /app/data
|
echo "Yt-dlp update"
|
||||||
chown -R ellie:ellie "$data"
|
# TODO: Update yt-dlp. It should not crash the entrypoint if ca-certificates is not installed
|
||||||
|
# yt-dlp -U
|
||||||
|
|
||||||
# drop to regular user and launch command
|
echo "Running EllieBot"
|
||||||
exec sudo -u ellie "$@"
|
exec "$@"
|
|
@ -6,7 +6,7 @@
|
||||||
[Setup]
|
[Setup]
|
||||||
AppName = {param:botname|EllieBot}
|
AppName = {param:botname|EllieBot}
|
||||||
AppVersion={#version}
|
AppVersion={#version}
|
||||||
AppPublisher=Toastie
|
AppPublisher=Toastie_t0ast
|
||||||
DefaultDirName={param:installpath|{commonpf}\EllieBot}
|
DefaultDirName={param:installpath|{commonpf}\EllieBot}
|
||||||
DefaultGroupName=EllieBot
|
DefaultGroupName=EllieBot
|
||||||
UninstallDisplayIcon={app}\{#sysfolder}\ellie_icon.ico
|
UninstallDisplayIcon={app}\{#sysfolder}\ellie_icon.ico
|
||||||
|
@ -33,28 +33,25 @@ Uninstallable=no
|
||||||
;install
|
;install
|
||||||
Source: "src\EllieBot\bin\Release\{#platform}\{#target}\publish\*"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: recursesubdirs onlyifdoesntexist ignoreversion createallsubdirs; Excludes: "*.pdb, *.db"
|
Source: "src\EllieBot\bin\Release\{#platform}\{#target}\publish\*"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: recursesubdirs onlyifdoesntexist ignoreversion createallsubdirs; Excludes: "*.pdb, *.db"
|
||||||
|
|
||||||
;reinstall - i want to copy all files, but i don't want to overwrite any data files because users will lose their customization if they don't have a backup,
|
;reinstall - Copy all files, but don't overwrite any data files because users will lose their customization if they don't have a backup
|
||||||
; and i don't want them to have to backup and then copy-merge into data folder themselves, or lose their currency images due to overwrite.
|
Source: "src\EllieBot\bin\Release\{#platform}\{#target}\publish\*"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: recursesubdirs ignoreversion onlyifdestfileexists createallsubdirs; Excludes: "*.pdb, *.db, data\*, creds.yml";
|
||||||
Source: "src\EllieBot\bin\Release\{#platform}\{#target}\publish\*"; DestDir: "{app}\{#sysfolder}"; Permissions: users-full; Flags: recursesubdirs ignoreversion onlyifdestfileexists createallsubdirs; Excludes: "*.pdb, *.db, data\*, credentials.json, creds.yml";
|
|
||||||
Source: "src\EllieBot\bin\Release\{#platform}\{#target}\publish\data\*"; DestDir: "{app}\{#sysfolder}\data"; Permissions: users-full; Flags: recursesubdirs onlyifdoesntexist createallsubdirs;
|
Source: "src\EllieBot\bin\Release\{#platform}\{#target}\publish\data\*"; DestDir: "{app}\{#sysfolder}\data"; Permissions: users-full; Flags: recursesubdirs onlyifdoesntexist createallsubdirs;
|
||||||
; overwrite strings and aliases
|
; overwrite strings
|
||||||
Source: "src\EllieBot\bin\Release\{#platform}\{#target}\publish\data\aliases.yml"; DestDir: "{app}\{#sysfolder}\data\"; Permissions: users-full; Flags: recursesubdirs ignoreversion onlyifdestfileexists createallsubdirs;
|
Source: "src\EllieBot\bin\Release\{#platform}\{#target}\publish\strings\*"; DestDir: "{app}\{#sysfolder}\strings"; Permissions: users-full; Flags: recursesubdirs ignoreversion onlyifdestfileexists createallsubdirs;
|
||||||
Source: "src\EllieBot\bin\Release\{#platform}\{#target}\publish\data\strings\*"; DestDir: "{app}\{#sysfolder}\data\strings"; Permissions: users-full; Flags: recursesubdirs ignoreversion onlyifdestfileexists createallsubdirs;
|
|
||||||
|
|
||||||
[Dirs]
|
[Dirs]
|
||||||
Name:"{app}\{#sysfolder}\data"; Permissions: everyone-modify
|
Name:"{app}\{#sysfolder}\data"; Permissions: everyone-modify
|
||||||
Name:"{app}\{#sysfolder}\config"; Permissions: everyone-modify
|
|
||||||
Name:"{app}\{#sysfolder}"; Permissions: everyone-modify
|
Name:"{app}\{#sysfolder}"; Permissions: everyone-modify
|
||||||
|
|
||||||
; [Run]
|
; [Run]
|
||||||
; Filename: "https://docs.elliebot.net/ellie/"; Flags: postinstall shellexec runasoriginaluser; Description: "Open setup guide"
|
; Filename: "https://docs.elliebot.net/ellie/features/yml-explained/"; Flags: postinstall shellexec runasoriginaluser; Description: "Open setup guide"
|
||||||
; Filename: "{app}\{#sysfolder}\creds.yml"; Flags: postinstall shellexec runasoriginaluser; Description: "Open creds file"
|
; Filename: "{app}\{#sysfolder}\creds.yml"; Flags: postinstall shellexec runasoriginaluser; Description: "Open creds file"
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
; for pretty install directory
|
; for pretty install directory
|
||||||
Name: "{app}\EllieBot"; Filename: "{app}\{#sysfolder}\EllieBot.exe"; IconFilename: "{app}\{#sysfolder}\ellie_icon.ico"
|
Name: "{app}\EllieBot"; Filename: "{app}\{#sysfolder}\EllieBot.exe"; IconFilename: "{app}\{#sysfolder}\ellie_icon.ico"
|
||||||
Name: "{app}\creds"; Filename: "{app}\{#sysfolder}\creds.yml"
|
|
||||||
Name: "{app}\data"; Filename: "{app}\{#sysfolder}\data"
|
Name: "{app}\data"; Filename: "{app}\{#sysfolder}\data"
|
||||||
|
Name: "{app}\strings"; Filename: "{app}\{#sysfolder}\strings"
|
||||||
|
|
||||||
; desktop shortcut
|
; desktop shortcut
|
||||||
Name: "{commondesktop}\{#SetupSetting("AppName")}"; Filename: "{app}\EllieBot";
|
Name: "{commondesktop}\{#SetupSetting("AppName")}"; Filename: "{app}\EllieBot";
|
||||||
|
@ -62,7 +59,7 @@ Name: "{commondesktop}\{#SetupSetting("AppName")}"; Filename: "{app}\EllieBot";
|
||||||
[Code]
|
[Code]
|
||||||
function GetFileName(const AFileName: string): string;
|
function GetFileName(const AFileName: string): string;
|
||||||
begin
|
begin
|
||||||
Result := ExpandConstant('{app}\{#sysfolder}\' + AFileName);
|
Result := ExpandConstant('{app}\{#sysfolder}\data\' + AFileName);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure CurStepChanged(CurStep: TSetupStep);
|
procedure CurStepChanged(CurStep: TSetupStep);
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Discord.Net.Core" Version="3.16.0" />
|
<PackageReference Include="Discord.Net.Core" Version="3.17.1" />
|
||||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
<PackageReference Include="Serilog" Version="4.2.0" />
|
||||||
<PackageReference Include="YamlDotNet" Version="15.1.4" />
|
<PackageReference Include="YamlDotNet" Version="15.1.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Version)' == '' ">
|
<PropertyGroup Condition=" '$(Version)' == '' ">
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Grpc.AspNetCore" Version="2.62.0" />
|
<PackageReference Include="Grpc.AspNetCore" Version="2.67.0" />
|
||||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
<PackageReference Include="Serilog" Version="4.2.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||||
<PackageReference Include="YamlDotNet" Version="15.1.4" />
|
<PackageReference Include="YamlDotNet" Version="15.1.6" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -11,7 +11,7 @@ Project which contains source generators required for EllieBot project
|
||||||
-- How it works --
|
-- How it works --
|
||||||
Creates a file "strs.cs" containing a class called "strs" in "EllieBot" namespace.
|
Creates a file "strs.cs" containing a class called "strs" in "EllieBot" namespace.
|
||||||
|
|
||||||
Loads "data/strings/responses.en-US.json" and creates a property or a function for each key in the responses json file based on whether the value has string format placeholders or not.
|
Loads "strings/responses.en-US.json" and creates a property or a function for each key in the responses json file based on whether the value has string format placeholders or not.
|
||||||
|
|
||||||
- If a value has no placeholders, it creates a property in the strs class which returns an instance of a LocStr struct containing only the key and no replacement parameters
|
- If a value has no placeholders, it creates a property in the strs class which returns an instance of a LocStr struct containing only the key and no replacement parameters
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.28.2" />
|
<PackageReference Include="Google.Protobuf" Version="3.29.3" />
|
||||||
<PackageReference Include="Grpc" Version="2.46.6" />
|
<PackageReference Include="Grpc" Version="2.46.6" />
|
||||||
<PackageReference Include="Grpc.Tools" Version="2.66.0" PrivateAssets="All" />
|
<PackageReference Include="Grpc.Tools" Version="2.69.0" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -11,9 +11,9 @@ namespace EllieBot.Tests
|
||||||
{
|
{
|
||||||
public class CommandStringsTests
|
public class CommandStringsTests
|
||||||
{
|
{
|
||||||
private const string responsesPath = "../../../../EllieBot/data/strings/responses";
|
private const string responsesPath = "../../../../EllieBot/strings/responses";
|
||||||
private const string commandsPath = "../../../../EllieBot/data/strings/commands";
|
private const string commandsPath = "../../../../EllieBot/strings/commands";
|
||||||
private const string aliasesPath = "../../../../EllieBot/data/aliases.yml";
|
private const string aliasesPath = "../../../../EllieBot/strings/aliases.yml";
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void AllCommandNamesHaveStrings()
|
public void AllCommandNamesHaveStrings()
|
||||||
|
@ -36,7 +36,7 @@ namespace EllieBot.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.IsTrue(isSuccess);
|
Assert.That(isSuccess, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string[] GetCommandMethodNames()
|
private static string[] GetCommandMethodNames()
|
||||||
|
@ -46,8 +46,8 @@ namespace EllieBot.Tests
|
||||||
.Where(type => typeof(EllieModule).IsAssignableFrom(type) // if its a top level module
|
.Where(type => typeof(EllieModule).IsAssignableFrom(type) // if its a top level module
|
||||||
|| !(type.GetCustomAttribute<GroupAttribute>(true) is null)) // or a submodule
|
|| !(type.GetCustomAttribute<GroupAttribute>(true) is null)) // or a submodule
|
||||||
.SelectMany(x => x.GetMethods()
|
.SelectMany(x => x.GetMethods()
|
||||||
.Where(mi => mi.CustomAttributes
|
.Where(mi => mi.CustomAttributes
|
||||||
.Any(ca => ca.AttributeType == typeof(CmdAttribute))))
|
.Any(ca => ca.AttributeType == typeof(CmdAttribute))))
|
||||||
.Select(x => x.Name.ToLowerInvariant())
|
.Select(x => x.Name.ToLowerInvariant())
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ namespace EllieBot.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.IsTrue(isSuccess);
|
Assert.That(isSuccess, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -96,7 +96,7 @@ namespace EllieBot.Tests
|
||||||
if (isSuccess)
|
if (isSuccess)
|
||||||
Assert.Pass();
|
Assert.Pass();
|
||||||
else
|
else
|
||||||
Assert.Warn("There are some unused entries in data/aliases.yml");
|
Assert.Warn("There are some unused entries in aliases.yml");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -107,7 +107,7 @@ namespace EllieBot.Tests
|
||||||
var culture = new CultureInfo("en-US");
|
var culture = new CultureInfo("en-US");
|
||||||
|
|
||||||
var methodNames = GetCommandMethodNames()
|
var methodNames = GetCommandMethodNames()
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
|
|
||||||
var isSuccess = true;
|
var isSuccess = true;
|
||||||
// var allCommandNames = CommandNameLoadHelper.LoadCommandStrings(commandsPath));
|
// var allCommandNames = CommandNameLoadHelper.LoadCommandStrings(commandsPath));
|
||||||
|
@ -117,15 +117,13 @@ namespace EllieBot.Tests
|
||||||
|
|
||||||
if (!methodNames.Contains(cmdName))
|
if (!methodNames.Contains(cmdName))
|
||||||
{
|
{
|
||||||
TestContext.Out.WriteLine($"'{cmdName}' from commands.en-US.yml doesn't have a matching command method.");
|
TestContext.Out.WriteLine(
|
||||||
|
$"'{cmdName}' from commands.en-US.yml doesn't have a matching command method.");
|
||||||
isSuccess = false;
|
isSuccess = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSuccess)
|
Assert.That(isSuccess, Is.True, "There are some unused command strings in strings/commands.en-US.yml");
|
||||||
Assert.IsTrue(isSuccess);
|
|
||||||
else
|
|
||||||
Assert.Warn("There are some unused command strings in data/strings/commands.en-US.yml");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,11 +18,11 @@ public class ConcurrentHashSetTests
|
||||||
{
|
{
|
||||||
var result = _set.Add((1, 2));
|
var result = _set.Add((1, 2));
|
||||||
|
|
||||||
Assert.AreEqual(true, result);
|
Assert.That(result, Is.EqualTo(true));
|
||||||
|
|
||||||
result = _set.Add((1, 2));
|
result = _set.Add((1, 2));
|
||||||
|
|
||||||
Assert.AreEqual(false, result);
|
Assert.That(result, Is.EqualTo(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -31,10 +31,10 @@ public class ConcurrentHashSetTests
|
||||||
_set.Add((1, 2));
|
_set.Add((1, 2));
|
||||||
var result = _set.TryRemove((1, 2));
|
var result = _set.TryRemove((1, 2));
|
||||||
|
|
||||||
Assert.AreEqual(true, result);
|
Assert.That(result, Is.EqualTo(true));
|
||||||
|
|
||||||
result = _set.TryRemove((1, 2));
|
result = _set.TryRemove((1, 2));
|
||||||
Assert.AreEqual(false, result);
|
Assert.That(result, Is.EqualTo(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -48,7 +48,7 @@ public class ConcurrentHashSetTests
|
||||||
_set.Add((3, 2)); // 3
|
_set.Add((3, 2)); // 3
|
||||||
_set.Add((3, 2)); // 3
|
_set.Add((3, 2)); // 3
|
||||||
|
|
||||||
Assert.AreEqual(3, _set.Count);
|
Assert.That(_set.Count, Is.EqualTo(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -60,7 +60,7 @@ public class ConcurrentHashSetTests
|
||||||
|
|
||||||
_set.Clear();
|
_set.Clear();
|
||||||
|
|
||||||
Assert.AreEqual(0, _set.Count);
|
Assert.That(_set.Count, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -69,10 +69,10 @@ public class ConcurrentHashSetTests
|
||||||
_set.Add((1, 2));
|
_set.Add((1, 2));
|
||||||
_set.Add((3, 2));
|
_set.Add((3, 2));
|
||||||
|
|
||||||
Assert.AreEqual(true, _set.Contains((1, 2)));
|
Assert.That(_set.Contains((1, 2)), Is.EqualTo(true));
|
||||||
Assert.AreEqual(true, _set.Contains((3, 2)));
|
Assert.That(_set.Contains((3, 2)), Is.EqualTo(true));
|
||||||
Assert.AreEqual(false, _set.Contains((2, 1)));
|
Assert.That(_set.Contains((2, 1)), Is.EqualTo(false));
|
||||||
Assert.AreEqual(false, _set.Contains((2, 3)));
|
Assert.That(_set.Contains((2, 3)), Is.EqualTo(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -86,8 +86,8 @@ public class ConcurrentHashSetTests
|
||||||
// remove tuples which have even second item
|
// remove tuples which have even second item
|
||||||
_set.RemoveWhere(static x => x.Item2 % 2 == 0);
|
_set.RemoveWhere(static x => x.Item2 % 2 == 0);
|
||||||
|
|
||||||
Assert.AreEqual(2, _set.Count);
|
Assert.That(_set.Count, Is.EqualTo(2));
|
||||||
Assert.AreEqual(true, _set.Contains((1, 3)));
|
Assert.That(_set.Contains((1, 3)), Is.EqualTo(true));
|
||||||
Assert.AreEqual(true, _set.Contains((2, 5)));
|
Assert.That(_set.Contains((2, 5)), Is.EqualTo(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,9 +6,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="4.3.2" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
// using System;
|
|
||||||
// using System.Collections.Generic;
|
|
||||||
// using System.Diagnostics;
|
|
||||||
// using System.IO;
|
|
||||||
// using System.Linq;
|
|
||||||
// using Ellie.Common;
|
|
||||||
// using EllieBot.Modules.Games;
|
|
||||||
// using NUnit.Framework;
|
|
||||||
//
|
|
||||||
// namespace EllieBot.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,4 +1,4 @@
|
||||||
using Ellie.Common;
|
using Ellie.Common;
|
||||||
using EllieBot.Db.Models;
|
using EllieBot.Db.Models;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using System;
|
using System;
|
||||||
|
@ -32,7 +32,8 @@ namespace EllieBot.Tests
|
||||||
|
|
||||||
// Evaluate the indices are ordered
|
// Evaluate the indices are ordered
|
||||||
CheckIndices(collection);
|
CheckIndices(collection);
|
||||||
Assert.AreEqual(8, collection.Count);
|
|
||||||
|
Assert.That(collection.Count, Is.EqualTo(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -45,8 +46,9 @@ namespace EllieBot.Tests
|
||||||
collection.RemoveAt(6);
|
collection.RemoveAt(6);
|
||||||
|
|
||||||
// Evaluate if the items got removed
|
// Evaluate if the items got removed
|
||||||
foreach (var item in collection)
|
foreach (var item in collection){
|
||||||
Assert.IsFalse(item.Id == 5 || item.Id == 7, $"Item at index {item.Index} was not removed");
|
Assert.That(item.Id, Is.Not.EqualTo(5).Or.EqualTo(7), $"Item at index {item.Index} was not removed");
|
||||||
|
}
|
||||||
|
|
||||||
CheckIndices(collection);
|
CheckIndices(collection);
|
||||||
|
|
||||||
|
@ -61,7 +63,7 @@ namespace EllieBot.Tests
|
||||||
var collection = GetCollectionSample<ShopEntry>();
|
var collection = GetCollectionSample<ShopEntry>();
|
||||||
collection.Clear();
|
collection.Clear();
|
||||||
|
|
||||||
Assert.IsTrue(collection.Count == 0, "Collection has not been cleared.");
|
Assert.That(collection.Count, Is.EqualTo(0), "Collection has not been cleared.");
|
||||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||||
{
|
{
|
||||||
_ = collection[0];
|
_ = collection[0];
|
||||||
|
@ -78,7 +80,7 @@ namespace EllieBot.Tests
|
||||||
|
|
||||||
// Evaluate copy
|
// Evaluate copy
|
||||||
for (var index = 0; index < fullCopy.Length; index++)
|
for (var index = 0; index < fullCopy.Length; index++)
|
||||||
Assert.AreEqual(index, fullCopy[index].Index);
|
Assert.That(index, Is.EqualTo(fullCopy[index].Index));
|
||||||
|
|
||||||
Assert.Throws<ArgumentException>(() => collection.CopyTo(new ShopEntry[10], 4));
|
Assert.Throws<ArgumentException>(() => collection.CopyTo(new ShopEntry[10], 4));
|
||||||
Assert.Throws<ArgumentException>(() => collection.CopyTo(new ShopEntry[6], 0));
|
Assert.Throws<ArgumentException>(() => collection.CopyTo(new ShopEntry[6], 0));
|
||||||
|
@ -89,10 +91,10 @@ namespace EllieBot.Tests
|
||||||
{
|
{
|
||||||
var collection = GetCollectionSample<ShopEntry>();
|
var collection = GetCollectionSample<ShopEntry>();
|
||||||
|
|
||||||
Assert.AreEqual(4, collection.IndexOf(collection[4]));
|
Assert.That(collection.IndexOf(collection[4]), Is.EqualTo(4));
|
||||||
Assert.AreEqual(0, collection.IndexOf(collection[0]));
|
Assert.That(collection.IndexOf(collection[0]), Is.EqualTo(0));
|
||||||
Assert.AreEqual(7, collection.IndexOf(collection[7]));
|
Assert.That(collection.IndexOf(collection[7]), Is.EqualTo(7));
|
||||||
Assert.AreEqual(9, collection.IndexOf(collection[9]));
|
Assert.That(collection.IndexOf(collection[9]), Is.EqualTo(9));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -104,9 +106,9 @@ namespace EllieBot.Tests
|
||||||
collection.Insert(5, new ShopEntry() { Id = 555 });
|
collection.Insert(5, new ShopEntry() { Id = 555 });
|
||||||
collection.Insert(7, new ShopEntry() { Id = 777 });
|
collection.Insert(7, new ShopEntry() { Id = 777 });
|
||||||
|
|
||||||
Assert.AreEqual(12, collection.Count);
|
Assert.That(collection.Count, Is.EqualTo(12));
|
||||||
Assert.AreEqual(555, collection[5].Id);
|
Assert.That(collection[5].Id, Is.EqualTo(555));
|
||||||
Assert.AreEqual(777, collection[7].Id);
|
Assert.That(collection[7].Id, Is.EqualTo(777));
|
||||||
|
|
||||||
CheckIndices(collection);
|
CheckIndices(collection);
|
||||||
|
|
||||||
|
@ -134,9 +136,9 @@ namespace EllieBot.Tests
|
||||||
collection.Remove(subCol[1]);
|
collection.Remove(subCol[1]);
|
||||||
CheckIndices(collection);
|
CheckIndices(collection);
|
||||||
|
|
||||||
Assert.IsTrue(collection.Contains(subCol[0]));
|
Assert.That(collection.Contains(subCol[0]), Is.True);
|
||||||
Assert.IsFalse(collection.Contains(subCol[1]));
|
Assert.That(collection.Contains(subCol[1]), Is.False);
|
||||||
Assert.IsTrue(collection.Contains(subCol[2]));
|
Assert.That(collection.Contains(subCol[2]), Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -148,7 +150,7 @@ namespace EllieBot.Tests
|
||||||
foreach (var item in collection)
|
foreach (var item in collection)
|
||||||
{
|
{
|
||||||
enumerator.MoveNext();
|
enumerator.MoveNext();
|
||||||
Assert.AreEqual(item, enumerator.Current);
|
Assert.That(enumerator.Current, Is.EqualTo(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,8 +163,8 @@ namespace EllieBot.Tests
|
||||||
collection[7] = new ShopEntry() { Id = 777 };
|
collection[7] = new ShopEntry() { Id = 777 };
|
||||||
CheckIndices(collection);
|
CheckIndices(collection);
|
||||||
|
|
||||||
Assert.AreEqual(444, collection[4].Id);
|
Assert.That(collection[4].Id, Is.EqualTo(444));
|
||||||
Assert.AreEqual(777, collection[7].Id);
|
Assert.That(collection[7].Id, Is.EqualTo(777));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -173,7 +175,7 @@ namespace EllieBot.Tests
|
||||||
private void CheckIndices<T>(IndexedCollection<T> collection) where T : class, IIndexed
|
private void CheckIndices<T>(IndexedCollection<T> collection) where T : class, IIndexed
|
||||||
{
|
{
|
||||||
for (var index = 0; index < collection.Count; index++)
|
for (var index = 0; index < collection.Count; index++)
|
||||||
Assert.AreEqual(index, collection[index].Index);
|
Assert.That(collection[index].Index, Is.EqualTo(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -185,4 +187,4 @@ namespace EllieBot.Tests
|
||||||
private IndexedCollection<T> GetCollectionSample<T>(IEnumerable<T> sample = default) where T : DbEntity, IIndexed, new()
|
private IndexedCollection<T> GetCollectionSample<T>(IEnumerable<T> sample = default) where T : DbEntity, IIndexed, new()
|
||||||
=> new IndexedCollection<T>(sample ?? Enumerable.Range(0, 10).Select(x => new T() { Id = x }));
|
=> new IndexedCollection<T>(sample ?? Enumerable.Range(0, 10).Select(x => new T() { Id = x }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace EllieBot.Tests
|
||||||
{
|
{
|
||||||
var num = default(kwum);
|
var num = default(kwum);
|
||||||
|
|
||||||
Assert.AreEqual(0, num.GetHashCode());
|
Assert.That(0, Is.EqualTo(num.GetHashCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -20,7 +20,7 @@ namespace EllieBot.Tests
|
||||||
var num1 = new kwum("234");
|
var num1 = new kwum("234");
|
||||||
var num2 = new kwum("234");
|
var num2 = new kwum("234");
|
||||||
|
|
||||||
Assert.AreEqual(num1.GetHashCode(), num2.GetHashCode());
|
Assert.That(num1.GetHashCode(), Is.EqualTo(num2.GetHashCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -29,7 +29,7 @@ namespace EllieBot.Tests
|
||||||
var num1 = new kwum("234");
|
var num1 = new kwum("234");
|
||||||
var num2 = new kwum("235");
|
var num2 = new kwum("235");
|
||||||
|
|
||||||
Assert.AreNotEqual(num1.GetHashCode(), num2.GetHashCode());
|
Assert.That(num1.GetHashCode(), Is.Not.EqualTo(num2.GetHashCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -38,7 +38,7 @@ namespace EllieBot.Tests
|
||||||
var num1 = new kwum("hgbkhdbk");
|
var num1 = new kwum("hgbkhdbk");
|
||||||
var num2 = new kwum("hgbkhdbk");
|
var num2 = new kwum("hgbkhdbk");
|
||||||
|
|
||||||
Assert.AreEqual(num1.GetHashCode(), num2.GetHashCode());
|
Assert.That(num1.GetHashCode(), Is.EqualTo(num2.GetHashCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -47,7 +47,7 @@ namespace EllieBot.Tests
|
||||||
var num1 = new kwum("hgbkhd");
|
var num1 = new kwum("hgbkhd");
|
||||||
var num2 = new kwum("hgbkhd");
|
var num2 = new kwum("hgbkhd");
|
||||||
|
|
||||||
Assert.AreEqual(num1, num2);
|
Assert.That(num1, Is.EqualTo(num2));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -56,21 +56,22 @@ namespace EllieBot.Tests
|
||||||
var num1 = new kwum("hgbk5d");
|
var num1 = new kwum("hgbk5d");
|
||||||
var num2 = new kwum("hgbk4d");
|
var num2 = new kwum("hgbk4d");
|
||||||
|
|
||||||
Assert.AreNotEqual(num1, num2);
|
Assert.That(num1, Is.Not.EqualTo(num2));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestParseValidValue()
|
public void TestParseValidValue()
|
||||||
{
|
{
|
||||||
var validValue = "234e";
|
var validValue = "234e";
|
||||||
Assert.True(kwum.TryParse(validValue, out _));
|
|
||||||
|
Assert.That(kwum.TryParse(validValue, out _), Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestParseInvalidValue()
|
public void TestParseInvalidValue()
|
||||||
{
|
{
|
||||||
var invalidValue = "1234";
|
var invalidValue = "1234";
|
||||||
Assert.False(kwum.TryParse(invalidValue, out _));
|
Assert.That(kwum.TryParse(invalidValue, out _), Is.False);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -79,7 +80,7 @@ namespace EllieBot.Tests
|
||||||
var validValue = "qwerf4bm";
|
var validValue = "qwerf4bm";
|
||||||
kwum.TryParse(validValue, out var parsedValue);
|
kwum.TryParse(validValue, out var parsedValue);
|
||||||
|
|
||||||
Assert.AreEqual(parsedValue, new kwum(validValue));
|
Assert.That(parsedValue, Is.EqualTo(new kwum(validValue)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -88,7 +89,7 @@ namespace EllieBot.Tests
|
||||||
var validValue = "46g5yh";
|
var validValue = "46g5yh";
|
||||||
kwum.TryParse(validValue, out var parsedValue);
|
kwum.TryParse(validValue, out var parsedValue);
|
||||||
|
|
||||||
Assert.AreEqual(validValue, parsedValue.ToString());
|
Assert.That(validValue, Is.EqualTo(parsedValue.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -96,37 +97,37 @@ namespace EllieBot.Tests
|
||||||
{
|
{
|
||||||
var num = new kwum(10);
|
var num = new kwum(10);
|
||||||
|
|
||||||
Assert.AreEqual(10, (int)num);
|
Assert.That(10, Is.EqualTo((int)num));
|
||||||
Assert.AreEqual(num, (kwum)10);
|
Assert.That(num, Is.EqualTo((kwum)10));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestConverstionsToString()
|
public void TestConverstionsToString()
|
||||||
{
|
{
|
||||||
var num = new kwum(10);
|
var num = new kwum(10);
|
||||||
Assert.AreEqual("c", num.ToString());
|
Assert.That("c", Is.EqualTo(num.ToString()));
|
||||||
num = new kwum(123);
|
num = new kwum(123);
|
||||||
Assert.AreEqual("5v", num.ToString());
|
Assert.That("5v", Is.EqualTo(num.ToString()));
|
||||||
|
|
||||||
// leading zeros have no meaning
|
// leading zeros have no meaning
|
||||||
Assert.AreEqual(new kwum("22225v"), num);
|
Assert.That(new kwum("22225v"), Is.EqualTo(num));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestMaxValue()
|
public void TestMaxValue()
|
||||||
{
|
{
|
||||||
var num = new kwum(int.MaxValue - 1);
|
var num = new kwum(int.MaxValue - 1);
|
||||||
Assert.AreEqual("3zzzzzy", num.ToString());
|
Assert.That("3zzzzzy", Is.EqualTo(num.ToString()));
|
||||||
|
|
||||||
num = new kwum(int.MaxValue);
|
num = new kwum(int.MaxValue);
|
||||||
Assert.AreEqual("3zzzzzz", num.ToString());
|
Assert.That("3zzzzzz", Is.EqualTo(num.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestPower()
|
public void TestPower()
|
||||||
{
|
{
|
||||||
var num = new kwum((int)Math.Pow(32, 2));
|
var num = new kwum((int)Math.Pow(32, 2));
|
||||||
Assert.AreEqual("322", num.ToString());
|
Assert.That("322", Is.EqualTo(num.ToString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace EllieBot.Tests;
|
namespace EllieBot.Tests;
|
||||||
|
|
||||||
|
|
||||||
public class NewDeckTests
|
public class NewDeckTests
|
||||||
{
|
{
|
||||||
private RegularDeck _deck;
|
private RegularDeck _deck;
|
||||||
|
@ -17,8 +16,8 @@ public class NewDeckTests
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCount()
|
public void TestCount()
|
||||||
{
|
{
|
||||||
Assert.AreEqual(52, _deck.TotalCount);
|
Assert.That(52, Is.EqualTo(_deck.TotalCount));
|
||||||
Assert.AreEqual(52, _deck.CurrentCount);
|
Assert.That(52, Is.EqualTo(_deck.CurrentCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -26,10 +25,10 @@ public class NewDeckTests
|
||||||
{
|
{
|
||||||
var card = _deck.Draw();
|
var card = _deck.Draw();
|
||||||
|
|
||||||
Assert.IsNotNull(card);
|
Assert.That(card, Is.Not.Null);
|
||||||
Assert.AreEqual(card.Suit, RegularSuit.Hearts);
|
Assert.That(card.Suit, Is.EqualTo(RegularSuit.Hearts));
|
||||||
Assert.AreEqual(card.Value, RegularValue.Ace);
|
Assert.That(card.Value, Is.EqualTo(RegularValue.Ace));
|
||||||
Assert.AreEqual(_deck.CurrentCount, _deck.TotalCount - 1);
|
Assert.That(_deck.CurrentCount, Is.EqualTo(_deck.TotalCount - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -42,12 +41,12 @@ public class NewDeckTests
|
||||||
|
|
||||||
var lastCard = _deck.Draw();
|
var lastCard = _deck.Draw();
|
||||||
|
|
||||||
Assert.IsNotNull(lastCard);
|
Assert.That(lastCard, Is.Not.Null);
|
||||||
Assert.AreEqual(new RegularCard(RegularSuit.Spades, RegularValue.King), lastCard);
|
Assert.That(lastCard, Is.EqualTo(new RegularCard(RegularSuit.Spades, RegularValue.King)));
|
||||||
|
|
||||||
var noCard = _deck.Draw();
|
var noCard = _deck.Draw();
|
||||||
|
|
||||||
Assert.IsNull(noCard);
|
Assert.That(noCard, Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -56,8 +55,8 @@ public class NewDeckTests
|
||||||
var ace = _deck.Draw()!;
|
var ace = _deck.Draw()!;
|
||||||
var two = _deck.Draw()!;
|
var two = _deck.Draw()!;
|
||||||
|
|
||||||
Assert.AreEqual("Ace of Hearts", ace.GetName());
|
Assert.That("Ace of Hearts", Is.EqualTo(ace.GetName()));
|
||||||
Assert.AreEqual("Two of Hearts", two.GetName());
|
Assert.That("Two of Hearts", Is.EqualTo(two.GetName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -66,8 +65,8 @@ public class NewDeckTests
|
||||||
var ace = _deck.Peek()!;
|
var ace = _deck.Peek()!;
|
||||||
|
|
||||||
var tenOfSpades = _deck.Peek(48);
|
var tenOfSpades = _deck.Peek(48);
|
||||||
Assert.AreEqual(new RegularCard(RegularSuit.Hearts, RegularValue.Ace), ace);
|
Assert.That(new RegularCard(RegularSuit.Hearts, RegularValue.Ace), Is.EqualTo(ace));
|
||||||
Assert.AreEqual(new RegularCard(RegularSuit.Spades, RegularValue.Ten), tenOfSpades);
|
Assert.That(new RegularCard(RegularSuit.Spades, RegularValue.Ten), Is.EqualTo(tenOfSpades));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -76,9 +75,9 @@ public class NewDeckTests
|
||||||
var quadDeck = new MultipleRegularDeck(4);
|
var quadDeck = new MultipleRegularDeck(4);
|
||||||
var count = quadDeck.TotalCount;
|
var count = quadDeck.TotalCount;
|
||||||
|
|
||||||
Assert.AreEqual(52 * 4, count);
|
Assert.That(52 * 4, Is.EqualTo(count));
|
||||||
|
|
||||||
var card = quadDeck.Peek(54);
|
var card = quadDeck.Peek(54);
|
||||||
Assert.AreEqual(new RegularCard(RegularSuit.Hearts, RegularValue.Three), card);
|
Assert.That(new RegularCard(RegularSuit.Hearts, RegularValue.Three), Is.EqualTo(card));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@ namespace EllieBot.Tests
|
||||||
var pubsub = new EventPubSub();
|
var pubsub = new EventPubSub();
|
||||||
await pubsub.Sub(key, data =>
|
await pubsub.Sub(key, data =>
|
||||||
{
|
{
|
||||||
Assert.AreEqual(expected, data);
|
Assert.That(expected, Is.EqualTo(data));
|
||||||
Assert.Pass();
|
Assert.Pass();
|
||||||
return default;
|
return default;
|
||||||
});
|
});
|
||||||
|
@ -31,7 +31,7 @@ namespace EllieBot.Tests
|
||||||
var pubsub = new EventPubSub();
|
var pubsub = new EventPubSub();
|
||||||
await pubsub.Sub(key, data =>
|
await pubsub.Sub(key, data =>
|
||||||
{
|
{
|
||||||
Assert.AreEqual(expected, data);
|
Assert.That(expected, Is.EqualTo(data));
|
||||||
Assert.Pass();
|
Assert.Pass();
|
||||||
return default;
|
return default;
|
||||||
});
|
});
|
||||||
|
@ -48,13 +48,13 @@ namespace EllieBot.Tests
|
||||||
var pubsub = new EventPubSub();
|
var pubsub = new EventPubSub();
|
||||||
await pubsub.Sub(key, data =>
|
await pubsub.Sub(key, data =>
|
||||||
{
|
{
|
||||||
Assert.AreEqual(expected, data);
|
Assert.That(expected, Is.EqualTo(data));
|
||||||
Assert.Pass();
|
Assert.Pass();
|
||||||
return default;
|
return default;
|
||||||
});
|
});
|
||||||
await pubsub.Unsub(key, data =>
|
await pubsub.Unsub(key, data =>
|
||||||
{
|
{
|
||||||
Assert.AreEqual(expected, data);
|
Assert.That(expected, Is.EqualTo(data));
|
||||||
Assert.Pass();
|
Assert.Pass();
|
||||||
return default;
|
return default;
|
||||||
});
|
});
|
||||||
|
@ -90,7 +90,7 @@ namespace EllieBot.Tests
|
||||||
|
|
||||||
ValueTask Action(byte[] data)
|
ValueTask Action(byte[] data)
|
||||||
{
|
{
|
||||||
Assert.AreEqual(localData, data);
|
Assert.That(localData, Is.EqualTo(data));
|
||||||
Assert.Pass();
|
Assert.Pass();
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
@ -112,14 +112,14 @@ namespace EllieBot.Tests
|
||||||
|
|
||||||
ValueTask Action1(object data)
|
ValueTask Action1(object data)
|
||||||
{
|
{
|
||||||
Assert.AreEqual(localData, data);
|
Assert.That(localData, Is.EqualTo(data));
|
||||||
successCounter += 10;
|
successCounter += 10;
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueTask Action2(object data)
|
ValueTask Action2(object data)
|
||||||
{
|
{
|
||||||
Assert.AreEqual(localData, data);
|
Assert.That(localData, Is.EqualTo(data));
|
||||||
successCounter++;
|
successCounter++;
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ namespace EllieBot.Tests
|
||||||
await pubsub.Unsub(key, Action2); // - 1/
|
await pubsub.Unsub(key, Action2); // - 1/
|
||||||
await pubsub.Pub(key, localData);
|
await pubsub.Pub(key, localData);
|
||||||
|
|
||||||
Assert.AreEqual(successCounter, 11, "Not all events are raised.");
|
Assert.That(successCounter, Is.EqualTo(11), "Not all events are raised.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,7 +17,7 @@ namespace EllieBot.Tests
|
||||||
var point = @"0001F338";
|
var point = @"0001F338";
|
||||||
var hopefullyEmoji = YamlHelper.UnescapeUnicodeCodePoint(point);
|
var hopefullyEmoji = YamlHelper.UnescapeUnicodeCodePoint(point);
|
||||||
|
|
||||||
Assert.AreEqual("🌸", hopefullyEmoji, hopefullyEmoji);
|
Assert.That("🌸", Is.EqualTo(hopefullyEmoji), "Yaml unescape doesn't work properly.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,7 +9,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
<PackageReference Include="Serilog" Version="4.2.0" />
|
||||||
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
|
<PackageReference Include="System.Threading.Channels" Version="9.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace EllieBot.Voice
|
||||||
{
|
{
|
||||||
internal static unsafe class Sodium
|
internal static unsafe class Sodium
|
||||||
{
|
{
|
||||||
|
|
||||||
private const string SODIUM = "data/lib/libsodium";
|
private const string SODIUM = "data/lib/libsodium";
|
||||||
|
|
||||||
[DllImport(SODIUM, EntryPoint = "crypto_secretbox_easy", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(SODIUM, EntryPoint = "crypto_secretbox_easy", CallingConvention = CallingConvention.Cdecl)]
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MorseCode.ITask" Version="2.0.3" />
|
<PackageReference Include="MorseCode.ITask" Version="2.0.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,360 +0,0 @@
|
||||||
root = true
|
|
||||||
# Remove the line below if you want to inherit .editorconfig settings from higher directories
|
|
||||||
|
|
||||||
[obj/**]
|
|
||||||
generated_code = true
|
|
||||||
|
|
||||||
# C# files
|
|
||||||
[*.cs]
|
|
||||||
|
|
||||||
|
|
||||||
#### Core EditorConfig Options ####
|
|
||||||
|
|
||||||
# Indentation and spacing
|
|
||||||
indent_size = 4
|
|
||||||
indent_style = space
|
|
||||||
tab_width = 4
|
|
||||||
|
|
||||||
# New line preferences
|
|
||||||
end_of_line = crlf
|
|
||||||
insert_final_newline = false
|
|
||||||
|
|
||||||
#### .NET Coding Conventions ####
|
|
||||||
|
|
||||||
# Organize usings
|
|
||||||
dotnet_separate_import_directive_groups = false
|
|
||||||
dotnet_sort_system_directives_first = false
|
|
||||||
|
|
||||||
# this. and Me. preferences
|
|
||||||
dotnet_style_qualification_for_event = false
|
|
||||||
dotnet_style_qualification_for_field = false
|
|
||||||
dotnet_style_qualification_for_method = false
|
|
||||||
dotnet_style_qualification_for_property = false
|
|
||||||
|
|
||||||
# Language keywords vs BCL types preferences
|
|
||||||
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
|
||||||
dotnet_style_predefined_type_for_member_access = true:suggestion
|
|
||||||
|
|
||||||
# Parentheses preferences
|
|
||||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
|
|
||||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
|
|
||||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
|
|
||||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
|
|
||||||
|
|
||||||
# Modifier preferences
|
|
||||||
dotnet_style_require_accessibility_modifiers = always:error
|
|
||||||
|
|
||||||
# Expression-level preferences
|
|
||||||
dotnet_style_coalesce_expression = true
|
|
||||||
dotnet_style_collection_initializer = true
|
|
||||||
dotnet_style_explicit_tuple_names = true
|
|
||||||
dotnet_style_namespace_match_folder = true
|
|
||||||
dotnet_style_null_propagation = true
|
|
||||||
dotnet_style_object_initializer = true
|
|
||||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
|
||||||
dotnet_style_prefer_auto_properties = true:warning
|
|
||||||
dotnet_style_prefer_compound_assignment = true
|
|
||||||
dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion
|
|
||||||
dotnet_style_prefer_conditional_expression_over_return = false:suggestion
|
|
||||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true
|
|
||||||
dotnet_style_prefer_inferred_tuple_names = true
|
|
||||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error
|
|
||||||
dotnet_style_prefer_simplified_boolean_expressions = true
|
|
||||||
dotnet_style_prefer_simplified_interpolation = true
|
|
||||||
|
|
||||||
# Field preferences
|
|
||||||
dotnet_style_readonly_field = true:suggestion
|
|
||||||
|
|
||||||
# Parameter preferences
|
|
||||||
dotnet_code_quality_unused_parameters = all:warning
|
|
||||||
|
|
||||||
#### C# Coding Conventions ####
|
|
||||||
|
|
||||||
# var preferences
|
|
||||||
csharp_style_var_elsewhere = true
|
|
||||||
csharp_style_var_for_built_in_types = true:suggestion
|
|
||||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
|
||||||
|
|
||||||
# Expression-bodied members
|
|
||||||
csharp_style_expression_bodied_accessors = true:suggestion
|
|
||||||
csharp_style_expression_bodied_indexers = true:suggestion
|
|
||||||
csharp_style_expression_bodied_lambdas = true:suggestion
|
|
||||||
csharp_style_expression_bodied_local_functions = true:suggestion
|
|
||||||
csharp_style_expression_bodied_methods = when_on_single_line:suggestion
|
|
||||||
csharp_style_expression_bodied_operators = when_on_single_line:suggestion
|
|
||||||
csharp_style_expression_bodied_properties = true:suggestion
|
|
||||||
|
|
||||||
# Pattern matching preferences
|
|
||||||
csharp_style_pattern_matching_over_as_with_null_check = true:error
|
|
||||||
csharp_style_pattern_matching_over_is_with_cast_check = true:error
|
|
||||||
csharp_style_prefer_not_pattern = true:error
|
|
||||||
csharp_style_prefer_pattern_matching = true:suggestion
|
|
||||||
csharp_style_prefer_switch_expression = true
|
|
||||||
|
|
||||||
# Null-checking preferences
|
|
||||||
csharp_style_conditional_delegate_call = true:error
|
|
||||||
|
|
||||||
# Modifier preferences
|
|
||||||
csharp_prefer_static_local_function = true
|
|
||||||
csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async
|
|
||||||
|
|
||||||
# Code-block preferences
|
|
||||||
csharp_prefer_braces = when_multiline:warning
|
|
||||||
csharp_prefer_simple_using_statement = true
|
|
||||||
|
|
||||||
# Expression-level preferences
|
|
||||||
csharp_prefer_simple_default_expression = true
|
|
||||||
csharp_style_deconstructed_variable_declaration = true
|
|
||||||
csharp_style_implicit_object_creation_when_type_is_apparent = true:error
|
|
||||||
csharp_style_inlined_variable_declaration = true:warning
|
|
||||||
csharp_style_pattern_local_over_anonymous_function = true
|
|
||||||
csharp_style_prefer_index_operator = true
|
|
||||||
csharp_style_prefer_range_operator = true
|
|
||||||
csharp_style_throw_expression = true:error
|
|
||||||
csharp_style_unused_value_assignment_preference = discard_variable:warning
|
|
||||||
csharp_style_unused_value_expression_statement_preference = discard_variable
|
|
||||||
|
|
||||||
# 'using' directive preferences
|
|
||||||
csharp_using_directive_placement = outside_namespace:error
|
|
||||||
|
|
||||||
# Enforce file-scoped namespaces
|
|
||||||
csharp_style_namespace_declarations = file_scoped:error
|
|
||||||
|
|
||||||
# New line preferences
|
|
||||||
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
|
|
||||||
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
|
|
||||||
csharp_style_allow_embedded_statements_on_same_line_experimental = false
|
|
||||||
|
|
||||||
#### C# Formatting Rules ####
|
|
||||||
|
|
||||||
# New line preferences
|
|
||||||
csharp_new_line_before_catch = true
|
|
||||||
csharp_new_line_before_else = true
|
|
||||||
csharp_new_line_before_finally = true
|
|
||||||
csharp_new_line_before_members_in_anonymous_types = true
|
|
||||||
csharp_new_line_before_members_in_object_initializers = true
|
|
||||||
csharp_new_line_before_open_brace = all
|
|
||||||
csharp_new_line_between_query_expression_clauses = true
|
|
||||||
|
|
||||||
# Indentation preferences
|
|
||||||
csharp_indent_block_contents = true
|
|
||||||
csharp_indent_braces = false
|
|
||||||
csharp_indent_case_contents = true
|
|
||||||
csharp_indent_case_contents_when_block = true
|
|
||||||
csharp_indent_labels = one_less_than_current
|
|
||||||
csharp_indent_switch_labels = true
|
|
||||||
|
|
||||||
# Space preferences
|
|
||||||
csharp_space_after_cast = false
|
|
||||||
csharp_space_after_colon_in_inheritance_clause = true
|
|
||||||
csharp_space_after_comma = true
|
|
||||||
csharp_space_after_dot = false
|
|
||||||
csharp_space_after_keywords_in_control_flow_statements = true
|
|
||||||
csharp_space_after_semicolon_in_for_statement = true
|
|
||||||
csharp_space_around_binary_operators = before_and_after
|
|
||||||
csharp_space_around_declaration_statements = false
|
|
||||||
csharp_space_before_colon_in_inheritance_clause = true
|
|
||||||
csharp_space_before_comma = false
|
|
||||||
csharp_space_before_dot = false
|
|
||||||
csharp_space_before_open_square_brackets = false
|
|
||||||
csharp_space_before_semicolon_in_for_statement = false
|
|
||||||
csharp_space_between_empty_square_brackets = false
|
|
||||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
|
||||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
|
||||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
|
||||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
|
||||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
|
||||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
|
||||||
csharp_space_between_parentheses = false
|
|
||||||
csharp_space_between_square_brackets = false
|
|
||||||
|
|
||||||
# Wrapping preferences
|
|
||||||
csharp_preserve_single_line_blocks = true
|
|
||||||
csharp_preserve_single_line_statements = false
|
|
||||||
|
|
||||||
#### Naming styles ####
|
|
||||||
|
|
||||||
# Naming rules
|
|
||||||
|
|
||||||
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.const_fields.symbols = const_fields
|
|
||||||
dotnet_naming_rule.const_fields.style = all_upper
|
|
||||||
dotnet_naming_rule.const_fields.severity = warning
|
|
||||||
|
|
||||||
# dotnet_naming_rule.class_should_be_pascal_case.severity = error
|
|
||||||
# dotnet_naming_rule.class_should_be_pascal_case.symbols = class
|
|
||||||
# dotnet_naming_rule.class_should_be_pascal_case.style = pascal_case
|
|
||||||
|
|
||||||
dotnet_naming_rule.struct_should_be_pascal_case.severity = error
|
|
||||||
dotnet_naming_rule.struct_should_be_pascal_case.symbols = struct
|
|
||||||
dotnet_naming_rule.struct_should_be_pascal_case.style = pascal_case
|
|
||||||
|
|
||||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = error
|
|
||||||
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
|
||||||
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
|
||||||
|
|
||||||
# dotnet_naming_rule.types_should_be_pascal_case.severity = error
|
|
||||||
# dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
|
||||||
# dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
|
||||||
|
|
||||||
# dotnet_naming_rule.enum_should_be_pascal_case.severity = error
|
|
||||||
# dotnet_naming_rule.enum_should_be_pascal_case.symbols = enum
|
|
||||||
# dotnet_naming_rule.enum_should_be_pascal_case.style = pascal_case
|
|
||||||
|
|
||||||
# dotnet_naming_rule.property_should_be_pascal_case.severity = error
|
|
||||||
# dotnet_naming_rule.property_should_be_pascal_case.symbols = property
|
|
||||||
# dotnet_naming_rule.property_should_be_pascal_case.style = pascal_case
|
|
||||||
|
|
||||||
dotnet_naming_rule.method_should_be_pascal_case.severity = error
|
|
||||||
dotnet_naming_rule.method_should_be_pascal_case.symbols = method
|
|
||||||
dotnet_naming_rule.method_should_be_pascal_case.style = pascal_case
|
|
||||||
|
|
||||||
dotnet_naming_rule.async_method_should_be_ends_with_async.severity = error
|
|
||||||
dotnet_naming_rule.async_method_should_be_ends_with_async.symbols = async_method
|
|
||||||
dotnet_naming_rule.async_method_should_be_ends_with_async.style = ends_with_async
|
|
||||||
|
|
||||||
# dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = error
|
|
||||||
# dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
|
||||||
# dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
|
||||||
|
|
||||||
dotnet_naming_rule.local_variable_should_be_camel_case.severity = error
|
|
||||||
dotnet_naming_rule.local_variable_should_be_camel_case.symbols = local_variable
|
|
||||||
dotnet_naming_rule.local_variable_should_be_camel_case.style = camel_case
|
|
||||||
|
|
||||||
# Symbol specifications
|
|
||||||
|
|
||||||
dotnet_naming_symbols.const_fields.required_modifiers = const
|
|
||||||
dotnet_naming_symbols.const_fields.applicable_kinds = field
|
|
||||||
|
|
||||||
dotnet_naming_symbols.class.applicable_kinds = class
|
|
||||||
dotnet_naming_symbols.class.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
|
||||||
dotnet_naming_symbols.class.required_modifiers =
|
|
||||||
|
|
||||||
dotnet_naming_symbols.interface.applicable_kinds = interface
|
|
||||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
|
||||||
dotnet_naming_symbols.interface.required_modifiers =
|
|
||||||
|
|
||||||
dotnet_naming_symbols.struct.applicable_kinds = struct
|
|
||||||
dotnet_naming_symbols.struct.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
|
||||||
dotnet_naming_symbols.struct.required_modifiers =
|
|
||||||
|
|
||||||
dotnet_naming_symbols.enum.applicable_kinds = enum
|
|
||||||
dotnet_naming_symbols.enum.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
|
||||||
dotnet_naming_symbols.enum.required_modifiers =
|
|
||||||
|
|
||||||
dotnet_naming_symbols.method.applicable_kinds = method
|
|
||||||
dotnet_naming_symbols.method.applicable_accessibilities = public
|
|
||||||
dotnet_naming_symbols.method.required_modifiers =
|
|
||||||
|
|
||||||
dotnet_naming_symbols.property.applicable_kinds = property
|
|
||||||
dotnet_naming_symbols.property.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
|
||||||
dotnet_naming_symbols.property.required_modifiers =
|
|
||||||
|
|
||||||
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
|
|
||||||
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
|
||||||
dotnet_naming_symbols.types.required_modifiers =
|
|
||||||
|
|
||||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
|
||||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
|
||||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
|
||||||
|
|
||||||
dotnet_naming_symbols.private_readonly_field.applicable_kinds = field
|
|
||||||
dotnet_naming_symbols.private_readonly_field.applicable_accessibilities = private, protected
|
|
||||||
dotnet_naming_symbols.private_readonly_field.required_modifiers = readonly
|
|
||||||
|
|
||||||
dotnet_naming_symbols.private_field.applicable_kinds = field
|
|
||||||
dotnet_naming_symbols.private_field.applicable_accessibilities = private, protected
|
|
||||||
dotnet_naming_symbols.private_field.required_modifiers =
|
|
||||||
|
|
||||||
dotnet_naming_symbols.async_method.applicable_kinds = method, local_function
|
|
||||||
dotnet_naming_symbols.async_method.applicable_accessibilities = *
|
|
||||||
dotnet_naming_symbols.async_method.required_modifiers = async
|
|
||||||
|
|
||||||
dotnet_naming_symbols.local_variable.applicable_kinds = parameter, local
|
|
||||||
dotnet_naming_symbols.local_variable.applicable_accessibilities = local
|
|
||||||
dotnet_naming_symbols.local_variable.required_modifiers =
|
|
||||||
|
|
||||||
# Naming styles
|
|
||||||
|
|
||||||
|
|
||||||
dotnet_naming_style.all_upper.capitalization = all_upper
|
|
||||||
|
|
||||||
dotnet_naming_style.pascal_case.required_prefix =
|
|
||||||
dotnet_naming_style.pascal_case.required_suffix =
|
|
||||||
dotnet_naming_style.pascal_case.word_separator =
|
|
||||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
|
||||||
|
|
||||||
dotnet_naming_style.begins_with_i.required_prefix = I
|
|
||||||
dotnet_naming_style.begins_with_i.required_suffix =
|
|
||||||
dotnet_naming_style.begins_with_i.word_separator =
|
|
||||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
|
||||||
|
|
||||||
dotnet_naming_style.begins_with_underscore.required_prefix = _
|
|
||||||
dotnet_naming_style.begins_with_underscore.required_suffix =
|
|
||||||
dotnet_naming_style.begins_with_underscore.word_separator =
|
|
||||||
dotnet_naming_style.begins_with_underscore.capitalization = camel_case
|
|
||||||
|
|
||||||
dotnet_naming_style.ends_with_async.required_prefix =
|
|
||||||
# dotnet_naming_style.ends_with_async.required_suffix = Async
|
|
||||||
dotnet_naming_style.ends_with_async.word_separator =
|
|
||||||
dotnet_naming_style.ends_with_async.capitalization = pascal_case
|
|
||||||
|
|
||||||
dotnet_naming_style.camel_case.required_prefix =
|
|
||||||
dotnet_naming_style.camel_case.required_suffix =
|
|
||||||
dotnet_naming_style.camel_case.word_separator =
|
|
||||||
dotnet_naming_style.camel_case.capitalization = camel_case
|
|
||||||
|
|
||||||
# CA1822: Mark members as static
|
|
||||||
dotnet_diagnostic.ca1822.severity = suggestion
|
|
||||||
|
|
||||||
# IDE0004: Cast is redundant
|
|
||||||
dotnet_diagnostic.ide0004.severity = warning
|
|
||||||
|
|
||||||
# IDE0058: Expression value is never used
|
|
||||||
dotnet_diagnostic.ide0058.severity = none
|
|
||||||
|
|
||||||
# # IDE0011: Add braces to 'if'/'else' statement
|
|
||||||
# dotnet_diagnostic.ide0011.severity = none
|
|
||||||
|
|
||||||
resharper_wrap_after_invocation_lpar = false
|
|
||||||
resharper_wrap_before_invocation_rpar = false
|
|
||||||
|
|
||||||
# ReSharper properties
|
|
||||||
resharper_align_multiline_calls_chain = true
|
|
||||||
resharper_csharp_wrap_after_declaration_lpar = true
|
|
||||||
resharper_csharp_wrap_after_invocation_lpar = false
|
|
||||||
resharper_csharp_wrap_before_binary_opsign = true
|
|
||||||
resharper_csharp_wrap_before_invocation_rpar = false
|
|
||||||
resharper_csharp_wrap_parameters_style = chop_if_long
|
|
||||||
resharper_force_chop_compound_if_expression = false
|
|
||||||
resharper_keep_existing_linebreaks = true
|
|
||||||
resharper_keep_user_linebreaks = true
|
|
||||||
resharper_max_formal_parameters_on_line = 3
|
|
||||||
resharper_place_simple_embedded_statement_on_same_line = false
|
|
||||||
resharper_wrap_chained_binary_expressions = chop_if_long
|
|
||||||
resharper_wrap_chained_binary_patterns = chop_if_long
|
|
||||||
resharper_wrap_chained_method_calls = chop_if_long
|
|
||||||
resharper_wrap_object_and_collection_initializer_style = chop_always
|
|
||||||
|
|
||||||
resharper_csharp_wrap_before_first_type_parameter_constraint = true
|
|
||||||
resharper_csharp_place_type_constraints_on_same_line = false
|
|
||||||
resharper_csharp_wrap_before_extends_colon = true
|
|
||||||
resharper_csharp_place_constructor_initializer_on_same_line = false
|
|
||||||
resharper_force_attribute_style = separate
|
|
||||||
resharper_csharp_braces_for_ifelse = required_for_multiline_statement
|
|
||||||
resharper_csharp_braces_for_foreach = required_for_multiline
|
|
||||||
resharper_csharp_braces_for_while = required_for_multiline
|
|
||||||
resharper_csharp_braces_for_for = required_for_multiline
|
|
||||||
resharper_arrange_redundant_parentheses_highlighting = hint
|
|
||||||
|
|
||||||
# IDE0011: Add braces
|
|
||||||
dotnet_diagnostic.IDE0011.severity = warning
|
|
||||||
|
|
||||||
resharper_arrange_type_member_modifiers_highlighting = hint
|
|
|
@ -1,12 +1,9 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using EllieBot.Common.Configs;
|
using EllieBot.Common.Configs;
|
||||||
using EllieBot.Common.ModuleBehaviors;
|
using EllieBot.Common.ModuleBehaviors;
|
||||||
using EllieBot.Db.Models;
|
|
||||||
using System.Collections.Immutable;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using RunMode = Discord.Commands.RunMode;
|
using RunMode = Discord.Commands.RunMode;
|
||||||
|
@ -15,15 +12,11 @@ namespace EllieBot;
|
||||||
|
|
||||||
public sealed class Bot : IBot
|
public sealed class Bot : IBot
|
||||||
{
|
{
|
||||||
public event Func<GuildConfig, Task> JoinedGuild = delegate { return Task.CompletedTask; };
|
|
||||||
|
|
||||||
public DiscordSocketClient Client { get; }
|
public DiscordSocketClient Client { get; }
|
||||||
public IReadOnlyCollection<GuildConfig> AllGuildConfigs { get; private set; }
|
|
||||||
|
|
||||||
private IContainer Services { get; set; }
|
private IContainer Services { get; set; }
|
||||||
|
|
||||||
public bool IsReady { get; private set; }
|
public int ShardId { get; }
|
||||||
public int ShardId { get; set; }
|
|
||||||
|
|
||||||
private readonly IBotCreds _creds;
|
private readonly IBotCreds _creds;
|
||||||
private readonly CommandService _commandService;
|
private readonly CommandService _commandService;
|
||||||
|
@ -34,12 +27,13 @@ public sealed class Bot : IBot
|
||||||
private readonly Assembly[] _loadedAssemblies;
|
private readonly Assembly[] _loadedAssemblies;
|
||||||
// private readonly InteractionService _interactionService;
|
// private readonly InteractionService _interactionService;
|
||||||
|
|
||||||
public Bot(int shardId, int? totalShards, string credPath = null)
|
public Bot(int shardId, int? totalShards)
|
||||||
{
|
{
|
||||||
ArgumentOutOfRangeException.ThrowIfLessThan(shardId, 0);
|
ArgumentOutOfRangeException.ThrowIfLessThan(shardId, 0);
|
||||||
|
|
||||||
|
LogSetup.SetupLogger(shardId, null);
|
||||||
ShardId = shardId;
|
ShardId = shardId;
|
||||||
_credsProvider = new BotCredsProvider(totalShards, credPath);
|
_credsProvider = new BotCredsProvider(totalShards);
|
||||||
_creds = _credsProvider.GetCreds();
|
_creds = _credsProvider.GetCreds();
|
||||||
|
|
||||||
LogSetup.SetupLogger(shardId, _creds);
|
LogSetup.SetupLogger(shardId, _creds);
|
||||||
|
@ -102,8 +96,7 @@ public sealed class Bot : IBot
|
||||||
|
|
||||||
await using (var uow = _db.GetDbContext())
|
await using (var uow = _db.GetDbContext())
|
||||||
{
|
{
|
||||||
AllGuildConfigs = await uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList);
|
uow.EnsureUserCreated(bot.Id, bot.Username, bot.AvatarId);
|
||||||
uow.EnsureUserCreated(bot.Id, bot.Username, bot.Discriminator, bot.AvatarId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// var svcs = new StandardKernel(new NinjectSettings()
|
// var svcs = new StandardKernel(new NinjectSettings()
|
||||||
|
@ -114,10 +107,6 @@ public sealed class Bot : IBot
|
||||||
|
|
||||||
var svcs = new Container();
|
var svcs = new Container();
|
||||||
|
|
||||||
// this is required in order for marmalade unloading to work
|
|
||||||
// svcs.Components.Remove<IPlanner, Planner>();
|
|
||||||
// svcs.Components.Add<IPlanner, RemovablePlanner>();
|
|
||||||
|
|
||||||
svcs.AddSingleton<IBotCreds>(_ => _credsProvider.GetCreds());
|
svcs.AddSingleton<IBotCreds>(_ => _credsProvider.GetCreds());
|
||||||
svcs.AddSingleton<DbService, DbService>(_db);
|
svcs.AddSingleton<DbService, DbService>(_db);
|
||||||
svcs.AddSingleton<IBotCredsProvider>(_credsProvider);
|
svcs.AddSingleton<IBotCredsProvider>(_credsProvider);
|
||||||
|
@ -130,7 +119,6 @@ public sealed class Bot : IBot
|
||||||
svcs.AddSingleton<IConfigSeria, YamlSeria>();
|
svcs.AddSingleton<IConfigSeria, YamlSeria>();
|
||||||
svcs.AddSingleton<IMemoryCache, MemoryCache>(new MemoryCache(new MemoryCacheOptions()));
|
svcs.AddSingleton<IMemoryCache, MemoryCache>(new MemoryCache(new MemoryCacheOptions()));
|
||||||
svcs.AddSingleton<IBehaviorHandler, BehaviorHandler>();
|
svcs.AddSingleton<IBehaviorHandler, BehaviorHandler>();
|
||||||
svcs.AddSingleton<ILocalization, Localization>();
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var a in _loadedAssemblies)
|
foreach (var a in _loadedAssemblies)
|
||||||
|
@ -245,16 +233,6 @@ public sealed class Bot : IBot
|
||||||
private Task Client_JoinedGuild(SocketGuild arg)
|
private Task Client_JoinedGuild(SocketGuild arg)
|
||||||
{
|
{
|
||||||
Log.Information("Joined server: {GuildName} [{GuildId}]", arg.Name, arg.Id);
|
Log.Information("Joined server: {GuildName} [{GuildId}]", arg.Name, arg.Id);
|
||||||
_ = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
GuildConfig gc;
|
|
||||||
await using (var uow = _db.GetDbContext())
|
|
||||||
{
|
|
||||||
gc = uow.GuildConfigsForId(arg.Id, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
await JoinedGuild.Invoke(gc);
|
|
||||||
});
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,19 +261,20 @@ public sealed class Bot : IBot
|
||||||
Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
Stopwatch.GetElapsedTime(startTime).TotalSeconds);
|
||||||
var commandHandler = Services.GetRequiredService<CommandHandler>();
|
var commandHandler = Services.GetRequiredService<CommandHandler>();
|
||||||
|
|
||||||
// start handling messages received in commandhandler
|
|
||||||
await commandHandler.StartHandling();
|
|
||||||
|
|
||||||
foreach (var a in _loadedAssemblies)
|
foreach (var a in _loadedAssemblies)
|
||||||
{
|
{
|
||||||
await _commandService.AddModulesAsync(a, Services);
|
await _commandService.AddModulesAsync(a, Services);
|
||||||
}
|
}
|
||||||
|
|
||||||
// await _interactionService.AddModulesAsync(typeof(Bot).Assembly, Services);
|
|
||||||
IsReady = true;
|
|
||||||
|
|
||||||
await EnsureBotOwnershipAsync();
|
await EnsureBotOwnershipAsync();
|
||||||
|
|
||||||
|
await commandHandler.InitializeAsync();
|
||||||
|
|
||||||
_ = Task.Run(ExecuteReadySubscriptions);
|
_ = Task.Run(ExecuteReadySubscriptions);
|
||||||
|
|
||||||
|
await commandHandler.StartHandling();
|
||||||
|
|
||||||
Log.Information("Shard {ShardId} ready", Client.ShardId);
|
Log.Information("Shard {ShardId} ready", Client.ShardId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +287,7 @@ public sealed class Bot : IBot
|
||||||
|
|
||||||
Log.Information("Initializing Owner Id...");
|
Log.Information("Initializing Owner Id...");
|
||||||
var info = await Client.GetApplicationInfoAsync();
|
var info = await Client.GetApplicationInfoAsync();
|
||||||
_credsProvider.ModifyCredsFile(x => x.OwnerIds = new[] { info.Owner.Id });
|
_credsProvider.ModifyCredsFile(x => x.OwnerIds = [info.Owner.Id]);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -331,6 +310,8 @@ public sealed class Bot : IBot
|
||||||
"Failed running OnReadyAsync method on {Type} type: {Message}",
|
"Failed running OnReadyAsync method on {Type} type: {Message}",
|
||||||
toExec.GetType().Name,
|
toExec.GetType().Name,
|
||||||
ex.Message);
|
ex.Message);
|
||||||
|
|
||||||
|
Environment.Exit(9);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -368,12 +349,10 @@ public sealed class Bot : IBot
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GLOBAL_ELLIE || DEBUG
|
|
||||||
if (arg.Exception is not null)
|
if (arg.Exception is not null)
|
||||||
Log.Warning(arg.Exception, "{ErrorSource} | {ErrorMessage}", arg.Source, arg.Message);
|
Log.Warning(arg.Exception, "{ErrorSource} | {ErrorMessage}", arg.Source, arg.Message);
|
||||||
else
|
else
|
||||||
Log.Warning("{ErrorSource} | {ErrorMessage}", arg.Source, arg.Message);
|
Log.Warning("{ErrorSource} | {ErrorMessage}", arg.Source, arg.Message);
|
||||||
#endif
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using EllieBot.Db.Models;
|
using EllieBot.Db.Models;
|
||||||
using EllieBot.Modules.Administration.Services;
|
|
||||||
|
|
||||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
|
||||||
|
@ -11,6 +11,11 @@ namespace EllieBot.Db;
|
||||||
public abstract class EllieContext : DbContext
|
public abstract class EllieContext : DbContext
|
||||||
{
|
{
|
||||||
public DbSet<GuildConfig> GuildConfigs { get; set; }
|
public DbSet<GuildConfig> GuildConfigs { get; set; }
|
||||||
|
public DbSet<Permissionv2> Permissions { get; set; }
|
||||||
|
|
||||||
|
//new
|
||||||
|
public DbSet<XpSettings> XpSettings { get; set; }
|
||||||
|
|
||||||
public DbSet<GreetSettings> GreetSettings { get; set; }
|
public DbSet<GreetSettings> GreetSettings { get; set; }
|
||||||
|
|
||||||
public DbSet<Quote> Quotes { get; set; }
|
public DbSet<Quote> Quotes { get; set; }
|
||||||
|
@ -46,7 +51,6 @@ public abstract class EllieContext : DbContext
|
||||||
public DbSet<AutoTranslateChannel> AutoTranslateChannels { get; set; }
|
public DbSet<AutoTranslateChannel> AutoTranslateChannels { get; set; }
|
||||||
public DbSet<AutoTranslateUser> AutoTranslateUsers { get; set; }
|
public DbSet<AutoTranslateUser> AutoTranslateUsers { get; set; }
|
||||||
|
|
||||||
public DbSet<Permissionv2> Permissions { get; set; }
|
|
||||||
|
|
||||||
public DbSet<BankUser> BankUsers { get; set; }
|
public DbSet<BankUser> BankUsers { get; set; }
|
||||||
|
|
||||||
|
@ -76,7 +80,7 @@ public abstract class EllieContext : DbContext
|
||||||
{
|
{
|
||||||
// load all entities from current assembly
|
// load all entities from current assembly
|
||||||
modelBuilder.ApplyConfigurationsFromAssembly(typeof(EllieContext).Assembly);
|
modelBuilder.ApplyConfigurationsFromAssembly(typeof(EllieContext).Assembly);
|
||||||
|
|
||||||
#region Notify
|
#region Notify
|
||||||
|
|
||||||
modelBuilder.Entity<Notify>(e =>
|
modelBuilder.Entity<Notify>(e =>
|
||||||
|
@ -170,10 +174,10 @@ public abstract class EllieContext : DbContext
|
||||||
modelBuilder.Entity<UserBetStats>(ubs =>
|
modelBuilder.Entity<UserBetStats>(ubs =>
|
||||||
{
|
{
|
||||||
ubs.HasIndex(x => new
|
ubs.HasIndex(x => new
|
||||||
{
|
{
|
||||||
x.UserId,
|
x.UserId,
|
||||||
x.Game
|
x.Game
|
||||||
})
|
})
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
ubs.HasIndex(x => x.MaxWin)
|
ubs.HasIndex(x => x.MaxWin)
|
||||||
|
@ -221,174 +225,8 @@ public abstract class EllieContext : DbContext
|
||||||
|
|
||||||
configEntity.Property(x => x.VerboseErrors)
|
configEntity.Property(x => x.VerboseErrors)
|
||||||
.HasDefaultValue(true);
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
modelBuilder.Entity<GuildConfig>()
|
|
||||||
.HasMany(x => x.DelMsgOnCmdChannels)
|
|
||||||
.WithOne()
|
|
||||||
.HasForeignKey(x => x.GuildConfigId)
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
|
|
||||||
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)
|
|
||||||
.WithOne()
|
|
||||||
.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
|
// 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
|
|
||||||
{
|
|
||||||
x.GuildConfigId,
|
|
||||||
x.Url
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity<PlantedCurrency>().HasIndex(x => x.MessageId).IsUnique();
|
modelBuilder.Entity<PlantedCurrency>().HasIndex(x => x.MessageId).IsUnique();
|
||||||
|
|
||||||
modelBuilder.Entity<PlantedCurrency>().HasIndex(x => x.ChannelId);
|
modelBuilder.Entity<PlantedCurrency>().HasIndex(x => x.ChannelId);
|
||||||
|
@ -397,9 +235,7 @@ public abstract class EllieContext : DbContext
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region WarningPunishments
|
modelBuilder.Entity<WarningPunishment>(b =>
|
||||||
|
|
||||||
var warnpunishmentEntity = modelBuilder.Entity<WarningPunishment>(b =>
|
|
||||||
{
|
{
|
||||||
b.HasAlternateKey(x => new
|
b.HasAlternateKey(x => new
|
||||||
{
|
{
|
||||||
|
@ -408,8 +244,6 @@ public abstract class EllieContext : DbContext
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region MusicPlaylists
|
#region MusicPlaylists
|
||||||
|
|
||||||
var musicPlaylistEntity = modelBuilder.Entity<MusicPlaylist>();
|
var musicPlaylistEntity = modelBuilder.Entity<MusicPlaylist>();
|
||||||
|
@ -489,33 +323,6 @@ public abstract class EllieContext : DbContext
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region XpRoleReward
|
|
||||||
|
|
||||||
modelBuilder.Entity<XpRoleReward>()
|
|
||||||
.HasIndex(x => new
|
|
||||||
{
|
|
||||||
x.XpSettingsId,
|
|
||||||
x.Level
|
|
||||||
})
|
|
||||||
.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
|
#region Club
|
||||||
|
|
||||||
var ci = modelBuilder.Entity<ClubInfo>();
|
var ci = modelBuilder.Entity<ClubInfo>();
|
||||||
|
@ -806,8 +613,15 @@ public abstract class EllieContext : DbContext
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
private static readonly ILoggerFactory _debugLoggerFactory = LoggerFactory.Create(x => x.AddConsole());
|
private static readonly ILoggerFactory _debugLoggerFactory = LoggerFactory.Create(x => x.AddConsole());
|
||||||
|
#endif
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
=> optionsBuilder.UseLoggerFactory(_debugLoggerFactory);
|
{
|
||||||
|
#if DEBUG
|
||||||
|
optionsBuilder.UseLoggerFactory(_debugLoggerFactory);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
optionsBuilder.ConfigureWarnings(x => x.Log(RelationalEventId.PendingModelChangesWarning)
|
||||||
|
.Ignore());
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,17 +1,21 @@
|
||||||
using LinqToDB.Common;
|
using LinqToDB.Common;
|
||||||
using LinqToDB.EntityFrameworkCore;
|
using LinqToDB.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
|
||||||
namespace EllieBot.Db;
|
namespace EllieBot.Db;
|
||||||
|
|
||||||
public sealed class EllieDbService : DbService
|
public sealed class EllieDbService : DbService
|
||||||
{
|
{
|
||||||
private readonly IBotCredsProvider _creds;
|
private readonly IBotCredsProvider _creds;
|
||||||
|
|
||||||
// these are props because creds can change at runtime
|
// these are props because creds can change at runtime
|
||||||
private string DbType => _creds.GetCreds().Db.Type.ToLowerInvariant().Trim();
|
private string DbType
|
||||||
private string ConnString => _creds.GetCreds().Db.ConnectionString;
|
=> _creds.GetCreds().Db.Type.ToLowerInvariant().Trim();
|
||||||
|
|
||||||
|
private string ConnString
|
||||||
|
=> _creds.GetCreds().Db.ConnectionString;
|
||||||
|
|
||||||
public EllieDbService(IBotCredsProvider creds)
|
public EllieDbService(IBotCredsProvider creds)
|
||||||
{
|
{
|
||||||
LinqToDBForEFTools.Initialize();
|
LinqToDBForEFTools.Initialize();
|
||||||
|
@ -22,18 +26,15 @@ public sealed class EllieDbService : DbService
|
||||||
|
|
||||||
public override async Task SetupAsync()
|
public override async Task SetupAsync()
|
||||||
{
|
{
|
||||||
var dbType = DbType;
|
await using var context = CreateRawDbContext(DbType, ConnString);
|
||||||
var connString = ConnString;
|
|
||||||
|
await RunMigration(context);
|
||||||
|
|
||||||
await using var context = CreateRawDbContext(dbType, connString);
|
|
||||||
|
|
||||||
// make sure sqlite db is in wal journal mode
|
// make sure sqlite db is in wal journal mode
|
||||||
if (context is SqliteContext)
|
if (context is SqliteContext)
|
||||||
{
|
{
|
||||||
await context.Database.ExecuteSqlRawAsync("PRAGMA journal_mode=WAL");
|
await context.Database.ExecuteSqlRawAsync("PRAGMA journal_mode=WAL");
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.Database.MigrateAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override EllieContext CreateRawDbContext(string dbType, string connString)
|
public override EllieContext CreateRawDbContext(string dbType, string connString)
|
||||||
|
@ -50,7 +51,7 @@ public sealed class EllieDbService : DbService
|
||||||
throw new NotSupportedException($"The database provide type of '{dbType}' is not supported.");
|
throw new NotSupportedException($"The database provide type of '{dbType}' is not supported.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private EllieContext GetDbContextInternal()
|
private EllieContext GetDbContextInternal()
|
||||||
{
|
{
|
||||||
var dbType = DbType;
|
var dbType = DbType;
|
||||||
|
@ -71,4 +72,57 @@ public sealed class EllieDbService : DbService
|
||||||
|
|
||||||
public override EllieContext GetDbContext()
|
public override EllieContext GetDbContext()
|
||||||
=> GetDbContextInternal();
|
=> GetDbContextInternal();
|
||||||
|
|
||||||
|
|
||||||
|
private static async Task RunMigration(DbContext ctx)
|
||||||
|
{
|
||||||
|
// if database doesn't exist, run the baseline migration
|
||||||
|
if (!await ctx.Database.CanConnectAsync())
|
||||||
|
{
|
||||||
|
Log.Information("Database does not exist. Creating a new database...");
|
||||||
|
await ctx.Database.MigrateAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the latest applied migration
|
||||||
|
|
||||||
|
var applied = await ctx.Database.GetAppliedMigrationsAsync();
|
||||||
|
|
||||||
|
// get all .sql file names from the migrations folder
|
||||||
|
var available = Directory.GetFiles("Migrations/" + GetMigrationDirectory(ctx.Database), "*_*.sql")
|
||||||
|
.Select(x => Path.GetFileNameWithoutExtension(x))
|
||||||
|
.OrderBy(x => x);
|
||||||
|
|
||||||
|
var lastApplied = applied.Last();
|
||||||
|
|
||||||
|
// apply all migrations with names greater than the last applied
|
||||||
|
foreach (var runnable in available)
|
||||||
|
{
|
||||||
|
if (string.Compare(lastApplied, runnable, StringComparison.Ordinal) < 0)
|
||||||
|
{
|
||||||
|
Log.Warning("Applying migration {MigrationName}", runnable);
|
||||||
|
|
||||||
|
var query = await File.ReadAllTextAsync(GetMigrationPath(ctx.Database, runnable));
|
||||||
|
await ctx.Database.ExecuteSqlRawAsync(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// run all migrations that have not been applied yet
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetMigrationPath(DatabaseFacade ctxDatabase, string runnable)
|
||||||
|
{
|
||||||
|
return $"Migrations/{GetMigrationDirectory(ctxDatabase)}/{runnable}.sql";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetMigrationDirectory(DatabaseFacade ctxDatabase)
|
||||||
|
{
|
||||||
|
if (ctxDatabase.IsSqlite())
|
||||||
|
return "Sqlite";
|
||||||
|
|
||||||
|
if (ctxDatabase.IsNpgsql())
|
||||||
|
return "PostgreSql";
|
||||||
|
|
||||||
|
throw new NotSupportedException("This database type is not supported.");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -9,4 +9,48 @@ public static class DbExtensions
|
||||||
public static T GetById<T>(this DbSet<T> set, int id)
|
public static T GetById<T>(this DbSet<T> set, int id)
|
||||||
where T : DbEntity
|
where T : DbEntity
|
||||||
=> set.FirstOrDefault(x => x.Id == id);
|
=> set.FirstOrDefault(x => x.Id == id);
|
||||||
|
|
||||||
|
public static GuildFilterConfig FilterConfigForId(
|
||||||
|
this DbContext ctx,
|
||||||
|
ulong guildId,
|
||||||
|
Func<IQueryable<GuildFilterConfig>, IQueryable<GuildFilterConfig>> includes = default)
|
||||||
|
{
|
||||||
|
includes ??= static set => set;
|
||||||
|
|
||||||
|
var gfc = includes(ctx.Set<GuildFilterConfig>()
|
||||||
|
.Where(gc => gc.GuildId == guildId))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (gfc is null)
|
||||||
|
{
|
||||||
|
ctx.Add(gfc = new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return gfc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GuildConfig GuildConfigsForId(
|
||||||
|
this DbContext ctx,
|
||||||
|
ulong guildId,
|
||||||
|
Func<IQueryable<GuildConfig>, IQueryable<GuildConfig>> includes = default)
|
||||||
|
{
|
||||||
|
includes ??= static set => set;
|
||||||
|
|
||||||
|
var gc = includes(ctx.Set<GuildConfig>()
|
||||||
|
.Where(gc => gc.GuildId == guildId))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (gc is null)
|
||||||
|
{
|
||||||
|
ctx.Add(gc = new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return gc;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -17,7 +17,6 @@ public static class DiscordUserExtensions
|
||||||
this DbContext ctx,
|
this DbContext ctx,
|
||||||
ulong userId,
|
ulong userId,
|
||||||
string username,
|
string username,
|
||||||
string discrim,
|
|
||||||
string avatarId)
|
string avatarId)
|
||||||
=> ctx.GetTable<DiscordUser>()
|
=> ctx.GetTable<DiscordUser>()
|
||||||
.InsertOrUpdate(
|
.InsertOrUpdate(
|
||||||
|
@ -65,11 +64,10 @@ public static class DiscordUserExtensions
|
||||||
this DbContext ctx,
|
this DbContext ctx,
|
||||||
ulong userId,
|
ulong userId,
|
||||||
string username,
|
string username,
|
||||||
string discrim,
|
|
||||||
string avatarId,
|
string avatarId,
|
||||||
Func<IQueryable<DiscordUser>, IQueryable<DiscordUser>> includes = null)
|
Func<IQueryable<DiscordUser>, IQueryable<DiscordUser>> includes = null)
|
||||||
{
|
{
|
||||||
ctx.EnsureUserCreated(userId, username, discrim, avatarId);
|
ctx.EnsureUserCreated(userId, username, avatarId);
|
||||||
|
|
||||||
IQueryable<DiscordUser> queryable = ctx.Set<DiscordUser>();
|
IQueryable<DiscordUser> queryable = ctx.Set<DiscordUser>();
|
||||||
if (includes is not null)
|
if (includes is not null)
|
||||||
|
@ -78,13 +76,6 @@ 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()
|
|
||||||
+ 1;
|
|
||||||
|
|
||||||
public static Task<List<DiscordUser>> GetTopRichest(
|
public static Task<List<DiscordUser>> GetTopRichest(
|
||||||
this DbSet<DiscordUser> users,
|
this DbSet<DiscordUser> users,
|
||||||
ulong botId,
|
ulong botId,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using LinqToDB;
|
||||||
using LinqToDB.EntityFrameworkCore;
|
using LinqToDB.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using EllieBot.Db.Models;
|
using EllieBot.Db.Models;
|
||||||
|
@ -29,125 +30,47 @@ public static class GuildConfigExtensions
|
||||||
/// <param name="ctx">Db Context</param>
|
/// <param name="ctx">Db Context</param>
|
||||||
/// <param name="guildId">Id of the guild to get stream role settings for.</param>
|
/// <param name="guildId">Id of the guild to get stream role settings for.</param>
|
||||||
/// <returns>Guild'p stream role settings</returns>
|
/// <returns>Guild'p stream role settings</returns>
|
||||||
public static StreamRoleSettings GetStreamRoleSettings(this DbContext ctx, ulong guildId)
|
public static async Task<StreamRoleSettings> GetOrCreateStreamRoleSettings(this DbContext ctx, ulong guildId)
|
||||||
{
|
{
|
||||||
var conf = ctx.GuildConfigsForId(guildId,
|
var srs = await ctx.GetTable<StreamRoleSettings>()
|
||||||
set => set.Include(y => y.StreamRole)
|
.Where(x => x.GuildId == guildId)
|
||||||
.Include(y => y.StreamRole.Whitelist)
|
.FirstOrDefaultAsyncEF();
|
||||||
.Include(y => y.StreamRole.Blacklist));
|
|
||||||
|
|
||||||
if (conf.StreamRole is null)
|
if (srs is not null)
|
||||||
conf.StreamRole = new();
|
return srs;
|
||||||
|
|
||||||
return conf.StreamRole;
|
srs = new()
|
||||||
}
|
|
||||||
|
|
||||||
private static IQueryable<GuildConfig> IncludeEverything(this DbSet<GuildConfig> configs)
|
|
||||||
=> 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 async Task<GuildConfig[]> GetAllGuildConfigs(
|
|
||||||
this DbSet<GuildConfig> configs,
|
|
||||||
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.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ctx">Context</param>
|
|
||||||
/// <param name="guildId">Id of the guide</param>
|
|
||||||
/// <param name="includes">Use to manipulate the set however you want. Pass null to include everything</param>
|
|
||||||
/// <returns>Config for the guild</returns>
|
|
||||||
public static GuildConfig GuildConfigsForId(
|
|
||||||
this DbContext ctx,
|
|
||||||
ulong guildId,
|
|
||||||
Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes)
|
|
||||||
{
|
|
||||||
GuildConfig config;
|
|
||||||
|
|
||||||
if (includes is null)
|
|
||||||
config = ctx.Set<GuildConfig>().IncludeEverything().FirstOrDefault(c => c.GuildId == guildId);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
var set = includes(ctx.Set<GuildConfig>());
|
GuildId = guildId,
|
||||||
config = set.FirstOrDefault(c => c.GuildId == guildId);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
if (config is null)
|
ctx.Set<StreamRoleSettings>().Add(srs);
|
||||||
{
|
|
||||||
ctx.Set<GuildConfig>()
|
|
||||||
.Add(config = new()
|
|
||||||
{
|
|
||||||
GuildId = guildId,
|
|
||||||
Permissions = Permissionv2.GetDefaultPermlist,
|
|
||||||
WarningsInitialized = true,
|
|
||||||
});
|
|
||||||
ctx.SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.WarningsInitialized)
|
return srs;
|
||||||
{
|
|
||||||
config.WarningsInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
|
|
||||||
// ctx.GuildConfigs
|
|
||||||
// .ToLinqToDBTable()
|
|
||||||
// .InsertOrUpdate(() => new()
|
|
||||||
// {
|
|
||||||
// GuildId = guildId,
|
|
||||||
// Permissions = Permissionv2.GetDefaultPermlist,
|
|
||||||
// WarningsInitialized = true,
|
|
||||||
// WarnPunishments = DefaultWarnPunishments
|
|
||||||
// },
|
|
||||||
// _ => new(),
|
|
||||||
// () => new()
|
|
||||||
// {
|
|
||||||
// GuildId = guildId
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// if(includes is null)
|
|
||||||
// return ctx.GuildConfigs
|
|
||||||
// .ToLinqToDBTable()
|
|
||||||
// .First(x => x.GuildId == guildId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LogSetting LogSettingsFor(this DbContext ctx, ulong guildId)
|
public static LogSetting LogSettingsFor(this DbContext ctx, ulong guildId)
|
||||||
{
|
{
|
||||||
var logSetting = ctx.Set<LogSetting>()
|
var logSetting = ctx.Set<LogSetting>()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Include(x => x.LogIgnores)
|
.Include(x => x.LogIgnores)
|
||||||
.Where(x => x.GuildId == guildId)
|
.Where(x => x.GuildId == guildId)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
if (logSetting is null)
|
if (logSetting is null)
|
||||||
{
|
{
|
||||||
ctx.Set<LogSetting>()
|
ctx.Set<LogSetting>()
|
||||||
.Add(logSetting = new()
|
.Add(logSetting = new()
|
||||||
{
|
{
|
||||||
GuildId = guildId
|
GuildId = guildId
|
||||||
});
|
});
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
return logSetting;
|
return logSetting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static IEnumerable<GuildConfig> PermissionsForAll(this DbSet<GuildConfig> configs, List<ulong> include)
|
public static IEnumerable<GuildConfig> PermissionsForAll(this DbSet<GuildConfig> configs, List<ulong> include)
|
||||||
{
|
{
|
||||||
var query = configs.AsQueryable().Where(x => include.Contains(x.GuildId)).Include(gc => gc.Permissions);
|
var query = configs.AsQueryable().Where(x => include.Contains(x.GuildId)).Include(gc => gc.Permissions);
|
||||||
|
@ -158,19 +81,19 @@ public static class GuildConfigExtensions
|
||||||
public static GuildConfig GcWithPermissionsFor(this DbContext ctx, ulong guildId)
|
public static GuildConfig GcWithPermissionsFor(this DbContext ctx, ulong guildId)
|
||||||
{
|
{
|
||||||
var config = ctx.Set<GuildConfig>()
|
var config = ctx.Set<GuildConfig>()
|
||||||
.AsQueryable()
|
.AsQueryable()
|
||||||
.Where(gc => gc.GuildId == guildId)
|
.Where(gc => gc.GuildId == guildId)
|
||||||
.Include(gc => gc.Permissions)
|
.Include(gc => gc.Permissions)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
if (config is null) // if there is no guildconfig, create new one
|
if (config is null) // if there is no guildconfig, create new one
|
||||||
{
|
{
|
||||||
ctx.Set<GuildConfig>()
|
ctx.Set<GuildConfig>()
|
||||||
.Add(config = new()
|
.Add(config = new()
|
||||||
{
|
{
|
||||||
GuildId = guildId,
|
GuildId = guildId,
|
||||||
Permissions = Permissionv2.GetDefaultPermlist
|
Permissions = Permissionv2.GetDefaultPermlist
|
||||||
});
|
});
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
}
|
}
|
||||||
else if (config.Permissions is null || !config.Permissions.Any()) // if no perms, add default ones
|
else if (config.Permissions is null || !config.Permissions.Any()) // if no perms, add default ones
|
||||||
|
@ -182,45 +105,27 @@ public static class GuildConfigExtensions
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<FollowedStream> GetFollowedStreams(this DbSet<GuildConfig> configs)
|
public static async Task<XpSettings> XpSettingsFor(this DbContext ctx, ulong guildId,
|
||||||
=> configs.AsQueryable().Include(x => x.FollowedStreams).SelectMany(gc => gc.FollowedStreams).ToArray();
|
Func<IQueryable<XpSettings>, IQueryable<XpSettings>> includes = default)
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
|
|
||||||
public static XpSettings XpSettingsFor(this DbContext ctx, ulong guildId)
|
|
||||||
{
|
{
|
||||||
var gc = ctx.GuildConfigsForId(guildId,
|
includes ??= static set => set;
|
||||||
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));
|
|
||||||
|
|
||||||
if (gc.XpSettings is null)
|
var srs = await includes(ctx.GetTable<XpSettings>()
|
||||||
gc.XpSettings = new();
|
.Where(x => x.GuildId == guildId))
|
||||||
|
.FirstOrDefaultAsyncLinqToDB();
|
||||||
|
|
||||||
return gc.XpSettings;
|
if (srs is not null)
|
||||||
|
return srs;
|
||||||
|
|
||||||
|
srs = await ctx.GetTable<XpSettings>()
|
||||||
|
.InsertWithOutputAsync(() => new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return srs;
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
public class GeneratingChannel
|
public class GeneratingChannel
|
||||||
{
|
{
|
||||||
public ulong GuildId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
|
|
|
@ -9,7 +9,7 @@ public static class UserXpExtensions
|
||||||
{
|
{
|
||||||
public static async Task<UserXpStats?> GetGuildUserXp(this ITable<UserXpStats> table, ulong guildId, ulong userId)
|
public static async Task<UserXpStats?> GetGuildUserXp(this ITable<UserXpStats> table, ulong guildId, ulong userId)
|
||||||
=> await table.FirstOrDefaultAsyncLinqToDB(x => x.GuildId == guildId && x.UserId == userId);
|
=> await table.FirstOrDefaultAsyncLinqToDB(x => x.GuildId == guildId && x.UserId == userId);
|
||||||
|
|
||||||
public static UserXpStats GetOrCreateUserXpStats(this DbContext ctx, ulong guildId, ulong 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);
|
var usr = ctx.Set<UserXpStats>().FirstOrDefault(x => x.UserId == userId && x.GuildId == guildId);
|
||||||
|
|
|
@ -1,8 +1,21 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class CommandAlias : DbEntity
|
public class CommandAlias : DbEntity
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
public string Trigger { get; set; }
|
public string Trigger { get; set; }
|
||||||
public string Mapping { get; set; }
|
public string Mapping { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandAliasEntityConfiguration : IEntityTypeConfiguration<CommandAlias>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<CommandAlias> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => x.GuildId);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,25 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class CommandCooldown : DbEntity
|
public class CommandCooldown : DbEntity
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
public int Seconds { get; set; }
|
public int Seconds { get; set; }
|
||||||
public string CommandName { get; set; }
|
public string CommandName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CommandCooldownEntityConfiguration : IEntityTypeConfiguration<CommandCooldown>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<CommandCooldown> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.CommandName
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,16 +1,25 @@
|
||||||
#nullable disable
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class DelMsgOnCmdChannel : DbEntity
|
public class DelMsgOnCmdChannel : DbEntity
|
||||||
{
|
{
|
||||||
public int GuildConfigId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
public bool State { get; set; }
|
public bool State { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public class DelMsgOnCmdChannelEntityConfiguration : IEntityTypeConfiguration<DelMsgOnCmdChannel>
|
||||||
=> ChannelId.GetHashCode();
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<DelMsgOnCmdChannel> builder)
|
||||||
public override bool Equals(object obj)
|
{
|
||||||
=> obj is DelMsgOnCmdChannel x && x.ChannelId == ChannelId;
|
builder.HasIndex(x => new
|
||||||
}
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.ChannelId
|
||||||
|
}).IsUnique();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
#nullable disable
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
|
||||||
// FUTURE remove LastLevelUp from here and UserXpStats
|
// FUTURE remove LastLevelUp from here and UserXpStats
|
||||||
public class DiscordUser : DbEntity
|
public class DiscordUser : DbEntity
|
||||||
{
|
{
|
||||||
|
public const string DEFAULT_USERNAME = "??Unknown";
|
||||||
|
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
public string Username { get; set; }
|
public string? Username { get; set; }
|
||||||
// public string Discriminator { get; set; }
|
public string? AvatarId { get; set; }
|
||||||
public string AvatarId { get; set; }
|
|
||||||
|
|
||||||
public int? ClubId { get; set; }
|
public int? ClubId { get; set; }
|
||||||
public ClubInfo Club { get; set; }
|
public ClubInfo? Club { get; set; }
|
||||||
public bool IsClubAdmin { get; set; }
|
public bool IsClubAdmin { get; set; }
|
||||||
|
|
||||||
public long TotalXp { get; set; }
|
public long TotalXp { get; set; }
|
||||||
|
@ -18,14 +19,12 @@ public class DiscordUser : DbEntity
|
||||||
|
|
||||||
public long CurrencyAmount { get; set; }
|
public long CurrencyAmount { get; set; }
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object? obj)
|
||||||
=> obj is DiscordUser du ? du.UserId == UserId : false;
|
=> obj is DiscordUser du ? du.UserId == UserId : false;
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> UserId.GetHashCode();
|
=> UserId.GetHashCode();
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
=> Username ?? DEFAULT_USERNAME;
|
||||||
return Username;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,19 +1,29 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class FeedSub : DbEntity
|
public class FeedSub : DbEntity
|
||||||
{
|
{
|
||||||
public int GuildConfigId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
public GuildConfig GuildConfig { get; set; }
|
|
||||||
|
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
|
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public sealed class FeedSubEntityConfiguration : IEntityTypeConfiguration<FeedSub>
|
||||||
=> Url.GetHashCode(StringComparison.InvariantCulture) ^ GuildConfigId.GetHashCode();
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<FeedSub> builder)
|
||||||
public override bool Equals(object obj)
|
{
|
||||||
=> obj is FeedSub s && s.Url.ToLower() == Url.ToLower() && s.GuildConfigId == GuildConfigId;
|
builder
|
||||||
|
.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.Url
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class FlagTranslateChannel : DbEntity
|
public class FlagTranslateChannel : DbEntity
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class FollowedStream : DbEntity
|
public class FollowedStream
|
||||||
{
|
{
|
||||||
public enum FType
|
public enum FType
|
||||||
{
|
{
|
||||||
|
@ -12,7 +15,7 @@ public class FollowedStream : DbEntity
|
||||||
Trovo = 6,
|
Trovo = 6,
|
||||||
Kick = 7,
|
Kick = 7,
|
||||||
}
|
}
|
||||||
|
public int Id { get; set; }
|
||||||
public ulong GuildId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
@ -29,6 +32,17 @@ public class FollowedStream : DbEntity
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
=> obj is FollowedStream fs && Equals(fs);
|
=> obj is FollowedStream fs && Equals(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class FollowedStreamEntityConfig : IEntityTypeConfiguration<FollowedStream>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<FollowedStream> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.Username,
|
||||||
|
x.Type,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,24 @@
|
||||||
#nullable disable
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class GCChannelId : DbEntity
|
public class GCChannelId : DbEntity
|
||||||
{
|
{
|
||||||
public GuildConfig GuildConfig { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public class GCChannelIdEntityConfiguration : IEntityTypeConfiguration<GCChannelId>
|
||||||
=> obj is GCChannelId gc && gc.ChannelId == ChannelId;
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<GCChannelId> builder)
|
||||||
public override int GetHashCode()
|
{
|
||||||
=> ChannelId.GetHashCode();
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.ChannelId
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,85 +1,58 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
public class GuildFilterConfig
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
public bool FilterInvites { get; set; }
|
||||||
|
public bool FilterLinks { get; set; }
|
||||||
|
public bool FilterWords { get; set; }
|
||||||
|
public HashSet<FilterChannelId> FilterInvitesChannelIds { get; set; } = new();
|
||||||
|
public HashSet<FilterLinksChannelId> FilterLinksChannelIds { get; set; } = new();
|
||||||
|
public HashSet<FilteredWord> FilteredWords { get; set; } = new();
|
||||||
|
public HashSet<FilterWordsChannelId> FilterWordsChannelIds { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class GuildFilterConfigEntityConfiguration : IEntityTypeConfiguration<GuildFilterConfig>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<GuildFilterConfig> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => x.GuildId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class GuildConfig : DbEntity
|
public class GuildConfig : DbEntity
|
||||||
{
|
{
|
||||||
// public bool Keep { get; set; }
|
|
||||||
public ulong GuildId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
public string Prefix { get; set; }
|
public string Prefix { get; set; }
|
||||||
|
|
||||||
public bool DeleteMessageOnCommand { get; set; }
|
public bool DeleteMessageOnCommand { get; set; }
|
||||||
public HashSet<DelMsgOnCmdChannel> DelMsgOnCmdChannels { get; set; } = new();
|
|
||||||
|
|
||||||
public string AutoAssignRoleIds { get; set; }
|
public string AutoAssignRoleIds { get; set; }
|
||||||
|
|
||||||
//todo FUTURE: DELETE, UNUSED
|
|
||||||
public bool ExclusiveSelfAssignedRoles { get; set; }
|
|
||||||
public bool AutoDeleteSelfAssignedRoleMessages { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
//stream notifications
|
|
||||||
public HashSet<FollowedStream> FollowedStreams { get; set; } = new();
|
|
||||||
|
|
||||||
//currencyGeneration
|
|
||||||
public HashSet<GCChannelId> GenerateCurrencyChannelIds { get; set; } = new();
|
|
||||||
|
|
||||||
public List<Permissionv2> Permissions { get; set; }
|
|
||||||
public bool VerbosePermissions { get; set; } = true;
|
public bool VerbosePermissions { get; set; } = true;
|
||||||
public string PermissionRole { get; set; }
|
public string PermissionRole { get; set; }
|
||||||
|
|
||||||
public HashSet<CommandCooldown> CommandCooldowns { get; set; } = new();
|
|
||||||
|
|
||||||
//filtering
|
//filtering
|
||||||
public bool FilterInvites { get; set; }
|
|
||||||
public bool FilterLinks { get; set; }
|
|
||||||
public HashSet<FilterChannelId> FilterInvitesChannelIds { get; set; } = new();
|
|
||||||
public HashSet<FilterLinksChannelId> FilterLinksChannelIds { get; set; } = new();
|
|
||||||
|
|
||||||
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; }
|
public string MuteRoleName { get; set; }
|
||||||
|
|
||||||
// chatterbot
|
// chatterbot
|
||||||
public bool CleverbotEnabled { get; set; }
|
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
|
// aliases
|
||||||
public HashSet<CommandAlias> CommandAliases { get; set; } = new();
|
|
||||||
public bool WarningsInitialized { get; set; }
|
public bool WarningsInitialized { get; set; }
|
||||||
public HashSet<SlowmodeIgnoredUser> SlowmodeIgnoredUsers { get; set; }
|
|
||||||
public HashSet<SlowmodeIgnoredRole> SlowmodeIgnoredRoles { get; set; }
|
|
||||||
|
|
||||||
public List<ShopEntry> ShopEntries { get; set; }
|
|
||||||
public ulong? GameVoiceChannel { get; set; }
|
public ulong? GameVoiceChannel { get; set; }
|
||||||
public bool VerboseErrors { get; set; } = true;
|
public bool VerboseErrors { get; set; } = true;
|
||||||
|
|
||||||
public StreamRoleSettings StreamRole { get; set; }
|
|
||||||
|
|
||||||
public XpSettings XpSettings { get; set; }
|
|
||||||
public List<FeedSub> FeedSubs { get; set; } = new();
|
|
||||||
public bool NotifyStreamOffline { get; set; }
|
public bool NotifyStreamOffline { get; set; }
|
||||||
public bool DeleteStreamOnlineMessage { get; set; }
|
public bool DeleteStreamOnlineMessage { get; set; }
|
||||||
public int WarnExpireHours { get; set; }
|
public int WarnExpireHours { get; set; }
|
||||||
|
@ -88,4 +61,9 @@ public class GuildConfig : DbEntity
|
||||||
public bool DisableGlobalExpressions { get; set; } = false;
|
public bool DisableGlobalExpressions { get; set; } = false;
|
||||||
|
|
||||||
public bool StickyRoles { get; set; }
|
public bool StickyRoles { get; set; }
|
||||||
|
|
||||||
|
public string TimeZoneId { get; set; }
|
||||||
|
public string Locale { get; set; }
|
||||||
|
|
||||||
|
public List<Permissionv2> Permissions { get; set; } = [];
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
@ -6,14 +6,14 @@ public class NCPixel
|
||||||
{
|
{
|
||||||
[Key]
|
[Key]
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public required int Position { get; init; }
|
public required int Position { get; init; }
|
||||||
|
|
||||||
public required long Price { get; init; }
|
public required long Price { get; init; }
|
||||||
|
|
||||||
public required ulong OwnerId { get; init; }
|
public required ulong OwnerId { get; init; }
|
||||||
public required uint Color { get; init; }
|
public required uint Color { get; init; }
|
||||||
|
|
||||||
[MaxLength(256)]
|
[MaxLength(256)]
|
||||||
public required string Text { get; init; }
|
public required string Text { get; init; }
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@ public class Notify
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public ulong GuildId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
public ulong ChannelId { get; set; }
|
public ulong? ChannelId { get; set; }
|
||||||
public NotifyType Type { get; set; }
|
public NotifyType Type { get; set; }
|
||||||
|
|
||||||
[MaxLength(10_000)]
|
[MaxLength(10_000)]
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
@ -7,7 +9,8 @@ namespace EllieBot.Db.Models;
|
||||||
[DebuggerDisplay("{PrimaryTarget}{SecondaryTarget} {SecondaryTargetName} {State} {PrimaryTargetId}")]
|
[DebuggerDisplay("{PrimaryTarget}{SecondaryTarget} {SecondaryTargetName} {State} {PrimaryTargetId}")]
|
||||||
public class Permissionv2 : DbEntity, IIndexed
|
public class Permissionv2 : DbEntity, IIndexed
|
||||||
{
|
{
|
||||||
public int? GuildConfigId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
|
|
||||||
public PrimaryPermissionType PrimaryTarget { get; set; }
|
public PrimaryPermissionType PrimaryTarget { get; set; }
|
||||||
|
@ -49,4 +52,12 @@ public enum SecondaryPermissionType
|
||||||
Module,
|
Module,
|
||||||
Command,
|
Command,
|
||||||
AllModules
|
AllModules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class Permissionv2EntityConfiguration : IEntityTypeConfiguration<Permissionv2>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Permissionv2> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => x.GuildId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ public sealed class SarGroup
|
||||||
public ulong? RoleReq { get; set; }
|
public ulong? RoleReq { get; set; }
|
||||||
public ICollection<Sar> Roles { get; set; } = [];
|
public ICollection<Sar> Roles { get; set; } = [];
|
||||||
public bool IsExclusive { get; set; }
|
public bool IsExclusive { get; set; }
|
||||||
|
|
||||||
[MaxLength(100)]
|
[MaxLength(100)]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
}
|
}
|
|
@ -1,16 +1,21 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public enum ShopEntryType
|
public enum ShopEntryType
|
||||||
{
|
{
|
||||||
Role,
|
Role,
|
||||||
|
|
||||||
List,
|
List,
|
||||||
Command
|
Command
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ShopEntry : DbEntity, IIndexed
|
public class ShopEntry : DbEntity, IIndexed
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
public int Price { get; set; }
|
public int Price { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
@ -25,7 +30,7 @@ public class ShopEntry : DbEntity, IIndexed
|
||||||
//list
|
//list
|
||||||
public HashSet<ShopEntryItem> Items { get; set; } = new();
|
public HashSet<ShopEntryItem> Items { get; set; } = new();
|
||||||
public ulong? RoleRequirement { get; set; }
|
public ulong? RoleRequirement { get; set; }
|
||||||
|
|
||||||
// command
|
// command
|
||||||
public string Command { get; set; }
|
public string Command { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -43,4 +48,22 @@ public class ShopEntryItem : DbEntity
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> Text.GetHashCode(StringComparison.InvariantCulture);
|
=> Text.GetHashCode(StringComparison.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ShopEntryEntityConfiguration : IEntityTypeConfiguration<ShopEntry>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<ShopEntry> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.Index
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.HasMany(x => x.Items)
|
||||||
|
.WithOne()
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,16 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class StreamRoleSettings : DbEntity
|
public class StreamRoleSettings : DbEntity
|
||||||
{
|
{
|
||||||
public int GuildConfigId { get; set; }
|
public int GuildConfigId { get; set; }
|
||||||
public GuildConfig GuildConfig { get; set; }
|
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the feature is enabled in the guild.
|
/// Whether the feature is enabled in the guild.
|
||||||
|
@ -42,7 +48,7 @@ public class StreamRoleBlacklistedUser : DbEntity
|
||||||
{
|
{
|
||||||
public int StreamRoleSettingsId { get; set; }
|
public int StreamRoleSettingsId { get; set; }
|
||||||
public StreamRoleSettings StreamRoleSettings { get; set; }
|
public StreamRoleSettings StreamRoleSettings { get; set; }
|
||||||
|
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
||||||
|
@ -62,7 +68,7 @@ public class StreamRoleWhitelistedUser : DbEntity
|
||||||
{
|
{
|
||||||
public int StreamRoleSettingsId { get; set; }
|
public int StreamRoleSettingsId { get; set; }
|
||||||
public StreamRoleSettings StreamRoleSettings { get; set; }
|
public StreamRoleSettings StreamRoleSettings { get; set; }
|
||||||
|
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|
||||||
|
@ -71,4 +77,25 @@ public class StreamRoleWhitelistedUser : DbEntity
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> UserId.GetHashCode();
|
=> UserId.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StreamRoleSettingsEntityConfiguration : IEntityTypeConfiguration<StreamRoleSettings>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<StreamRoleSettings> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => x.GuildId)
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.HasMany(x => x.Whitelist)
|
||||||
|
.WithOne(x => x.StreamRoleSettings)
|
||||||
|
.HasForeignKey(x => x.StreamRoleSettingsId)
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.HasMany(x => x.Blacklist)
|
||||||
|
.WithOne(x => x.StreamRoleSettings)
|
||||||
|
.HasForeignKey(x => x.StreamRoleSettingsId)
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,26 @@
|
||||||
#nullable disable
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class VcRoleInfo : DbEntity
|
public class VcRoleInfo : DbEntity
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
public ulong VoiceChannelId { get; set; }
|
public ulong VoiceChannelId { get; set; }
|
||||||
|
|
||||||
public ulong RoleId { get; set; }
|
public ulong RoleId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VcRoleInfoEntityConfiguration : IEntityTypeConfiguration<VcRoleInfo>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<VcRoleInfo> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.VoiceChannelId
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,30 @@
|
||||||
namespace EllieBot.Db.Models;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class AntiAltSetting
|
public class AntiAltSetting
|
||||||
{
|
{
|
||||||
public int GuildConfigId { get; set; }
|
[Key]
|
||||||
|
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int GuildConfigId { get; set; }
|
||||||
|
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
public TimeSpan MinAge { get; set; }
|
public TimeSpan MinAge { get; set; }
|
||||||
public PunishmentAction Action { get; set; }
|
public PunishmentAction Action { get; set; }
|
||||||
public int ActionDurationMinutes { get; set; }
|
public int ActionDurationMinutes { get; set; }
|
||||||
public ulong? RoleId { get; set; }
|
public ulong? RoleId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AntiAltSettingEntityConfiguration : IEntityTypeConfiguration<AntiAltSetting>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<AntiAltSetting> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => x.GuildId)
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
namespace EllieBot.Db.Models;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class AntiRaidSetting : DbEntity
|
public class AntiRaidSetting : DbEntity
|
||||||
{
|
{
|
||||||
public int GuildConfigId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
public int UserThreshold { get; set; }
|
public int UserThreshold { get; set; }
|
||||||
public int Seconds { get; set; }
|
public int Seconds { get; set; }
|
||||||
public PunishmentAction Action { get; set; }
|
public PunishmentAction Action { get; set; }
|
||||||
|
@ -15,4 +17,13 @@ public class AntiRaidSetting : DbEntity
|
||||||
/// Mute, Chatmute, Voicemute, etc...
|
/// Mute, Chatmute, Voicemute, etc...
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int PunishDuration { get; set; }
|
public int PunishDuration { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AntiRaidSettingEntityConfiguration : IEntityTypeConfiguration<AntiRaidSetting>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<AntiRaidSetting> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => x.GuildId)
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,10 +3,4 @@
|
||||||
public class AntiSpamIgnore : DbEntity
|
public class AntiSpamIgnore : DbEntity
|
||||||
{
|
{
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
=> ChannelId.GetHashCode();
|
|
||||||
|
|
||||||
public override bool Equals(object? obj)
|
|
||||||
=> obj is AntiSpamIgnore inst && inst.ChannelId == ChannelId;
|
|
||||||
}
|
}
|
|
@ -1,13 +1,34 @@
|
||||||
namespace EllieBot.Db.Models;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
public class AntiSpamSetting : DbEntity
|
public class AntiSpamSetting : DbEntity
|
||||||
{
|
{
|
||||||
public int GuildConfigId { get; set; }
|
public int GuildConfigId { get; set; }
|
||||||
|
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
public PunishmentAction Action { get; set; }
|
public PunishmentAction Action { get; set; }
|
||||||
public int MessageThreshold { get; set; } = 3;
|
public int MessageThreshold { get; set; } = 3;
|
||||||
public int MuteTime { get; set; }
|
public int MuteTime { get; set; }
|
||||||
public ulong? RoleId { get; set; }
|
public ulong? RoleId { get; set; }
|
||||||
public HashSet<AntiSpamIgnore> IgnoredChannels { get; set; } = new();
|
public List<AntiSpamIgnore> IgnoredChannels { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup model
|
||||||
|
public class AntiSpamEntityConfiguration : IEntityTypeConfiguration<AntiSpamSetting>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<AntiSpamSetting> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => x.GuildId)
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
builder.HasMany(x => x.IgnoredChannels)
|
||||||
|
.WithOne()
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
@ -24,4 +24,4 @@ public sealed class ButtonRole
|
||||||
public string Label { get; set; } = string.Empty;
|
public string Label { get; set; } = string.Empty;
|
||||||
|
|
||||||
public bool Exclusive { get; set; }
|
public bool Exclusive { get; set; }
|
||||||
}
|
}
|
|
@ -1,16 +1,23 @@
|
||||||
#nullable disable
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class FilterChannelId : DbEntity
|
public class FilterChannelId
|
||||||
{
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int? GuildFilterConfigId { get; set; }
|
||||||
|
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
|
|
||||||
public bool Equals(FilterChannelId other)
|
protected bool Equals(FilterChannelId other)
|
||||||
=> ChannelId == other.ChannelId;
|
=> ChannelId == other.ChannelId;
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object? obj)
|
||||||
=> obj is FilterChannelId fci && Equals(fci);
|
=> obj is FilterChannelId fci && fci.Equals(this);
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> ChannelId.GetHashCode();
|
=> ChannelId.GetHashCode();
|
||||||
}
|
}
|
|
@ -1,12 +1,15 @@
|
||||||
#nullable disable
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class FilterLinksChannelId : DbEntity
|
public class FilterLinksChannelId : DbEntity
|
||||||
{
|
{
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
|
public int? GuildFilterConfigId { get; set; }
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
protected bool Equals(FilterLinksChannelId other)
|
||||||
=> obj is FilterLinksChannelId f && f.ChannelId == ChannelId;
|
=> ChannelId == other.ChannelId;
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
=> obj is FilterLinksChannelId other && Equals(other);
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> ChannelId.GetHashCode();
|
=> ChannelId.GetHashCode();
|
||||||
|
|
|
@ -3,14 +3,14 @@ namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class FilterWordsChannelId : DbEntity
|
public class FilterWordsChannelId : DbEntity
|
||||||
{
|
{
|
||||||
public int? GuildConfigId { get; set; }
|
public int? GuildFilterConfigId { get; set; }
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
|
|
||||||
public bool Equals(FilterWordsChannelId other)
|
protected bool Equals(FilterWordsChannelId other)
|
||||||
=> ChannelId == other.ChannelId;
|
=> ChannelId == other.ChannelId;
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
=> obj is FilterWordsChannelId fci && Equals(fci);
|
=> obj is FilterWordsChannelId other && Equals(other);
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
=> ChannelId.GetHashCode();
|
=> ChannelId.GetHashCode();
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
#nullable disable
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class FilteredWord : DbEntity
|
public class FilteredWord : DbEntity
|
||||||
{
|
{
|
||||||
public string Word { get; set; }
|
public int? GuildFilterConfigId { get; set; }
|
||||||
|
public string? Word { get; set; }
|
||||||
|
|
||||||
|
public override bool Equals(object? obj) => obj is FilteredWord fw && fw.Word == Word;
|
||||||
|
|
||||||
|
public override int GetHashCode() => Word?.GetHashCode() ?? 0;
|
||||||
}
|
}
|
|
@ -1,13 +1,24 @@
|
||||||
#nullable disable
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class MutedUserId : DbEntity
|
public class MutedUserId : DbEntity
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public class MutedUserIdEntityConfiguration : IEntityTypeConfiguration<MutedUserId>
|
||||||
=> UserId.GetHashCode();
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<MutedUserId> builder)
|
||||||
public override bool Equals(object obj)
|
{
|
||||||
=> obj is MutedUserId mui ? mui.UserId == UserId : false;
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.UserId
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,6 @@ public class TempRole
|
||||||
public bool Remove { get; set; }
|
public bool Remove { get; set; }
|
||||||
public ulong RoleId { get; set; }
|
public ulong RoleId { get; set; }
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
|
|
||||||
public DateTime ExpiresAt { get; set; }
|
public DateTime ExpiresAt { get; set; }
|
||||||
}
|
}
|
|
@ -1,20 +1,24 @@
|
||||||
#nullable disable
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class SlowmodeIgnoredRole : DbEntity
|
public class SlowmodeIgnoredRole : DbEntity
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
public ulong RoleId { get; set; }
|
public ulong RoleId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
// override object.Equals
|
public class SlowmodeIgnoredRoleEntityConfiguration : IEntityTypeConfiguration<SlowmodeIgnoredRole>
|
||||||
public override bool Equals(object obj)
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<SlowmodeIgnoredRole> builder)
|
||||||
{
|
{
|
||||||
if (obj is null || GetType() != obj.GetType())
|
builder.HasIndex(x => new
|
||||||
return false;
|
{
|
||||||
|
x.GuildId,
|
||||||
return ((SlowmodeIgnoredRole)obj).RoleId == RoleId;
|
x.RoleId
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
}
|
}
|
||||||
|
|
||||||
// override object.GetHashCode
|
|
||||||
public override int GetHashCode()
|
|
||||||
=> RoleId.GetHashCode();
|
|
||||||
}
|
}
|
|
@ -1,20 +1,24 @@
|
||||||
#nullable disable
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class SlowmodeIgnoredUser : DbEntity
|
public class SlowmodeIgnoredUser : DbEntity
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
// override object.Equals
|
public class SlowmodeIgnoredUserEntityConfiguration : IEntityTypeConfiguration<SlowmodeIgnoredUser>
|
||||||
public override bool Equals(object obj)
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<SlowmodeIgnoredUser> builder)
|
||||||
{
|
{
|
||||||
if (obj is null || GetType() != obj.GetType())
|
builder.HasIndex(x => new
|
||||||
return false;
|
{
|
||||||
|
x.GuildId,
|
||||||
return ((SlowmodeIgnoredUser)obj).UserId == UserId;
|
x.UserId
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
}
|
}
|
||||||
|
|
||||||
// override object.GetHashCode
|
|
||||||
public override int GetHashCode()
|
|
||||||
=> UserId.GetHashCode();
|
|
||||||
}
|
}
|
|
@ -1,14 +1,26 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class UnbanTimer : DbEntity
|
public class UnbanTimer : DbEntity
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
public DateTime UnbanAt { get; set; }
|
public DateTime UnbanAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public class UnbanTimerEntityConfiguration : IEntityTypeConfiguration<UnbanTimer>
|
||||||
=> UserId.GetHashCode();
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<UnbanTimer> builder)
|
||||||
public override bool Equals(object obj)
|
{
|
||||||
=> obj is UnbanTimer ut ? ut.UserId == UserId : false;
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.UserId
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,25 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class UnmuteTimer : DbEntity
|
public class UnmuteTimer : DbEntity
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
public DateTime UnmuteAt { get; set; }
|
public DateTime UnmuteAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public class UnmuteTimerEntityConfiguration : IEntityTypeConfiguration<UnmuteTimer>
|
||||||
=> UserId.GetHashCode();
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<UnmuteTimer> builder)
|
||||||
public override bool Equals(object obj)
|
{
|
||||||
=> obj is UnmuteTimer ut ? ut.UserId == UserId : false;
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.UserId
|
||||||
|
}).IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,27 @@
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
// todo UN* remove unroletimer in favor of temprole
|
||||||
public class UnroleTimer : DbEntity
|
public class UnroleTimer : DbEntity
|
||||||
{
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
public ulong UserId { get; set; }
|
public ulong UserId { get; set; }
|
||||||
public ulong RoleId { get; set; }
|
public ulong RoleId { get; set; }
|
||||||
public DateTime UnbanAt { get; set; }
|
public DateTime UnbanAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public class UnroleTimerEntityConfiguration : IEntityTypeConfiguration<UnroleTimer>
|
||||||
=> UserId.GetHashCode() ^ RoleId.GetHashCode();
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<UnroleTimer> builder)
|
||||||
public override bool Equals(object obj)
|
{
|
||||||
=> obj is UnroleTimer ut ? ut.UserId == UserId && ut.RoleId == RoleId : false;
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.GuildId,
|
||||||
|
x.UserId
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
}
|
}
|
14
src/EllieBot/Db/Models/xp/ExcludedItem.cs
Normal file
14
src/EllieBot/Db/Models/xp/ExcludedItem.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
public class ExcludedItem : DbEntity
|
||||||
|
{
|
||||||
|
public int? XpSettingsId { get; set; }
|
||||||
|
public ulong ItemId { get; set; }
|
||||||
|
public ExcludedItemType ItemType { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
=> ItemId.GetHashCode() ^ ItemType.GetHashCode();
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
=> obj is ExcludedItem ei && ei.ItemId == ItemId && ei.ItemType == ItemType;
|
||||||
|
}
|
3
src/EllieBot/Db/Models/xp/ExcludedItemType.cs
Normal file
3
src/EllieBot/Db/Models/xp/ExcludedItemType.cs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
public enum ExcludedItemType { Channel, Role }
|
|
@ -1,4 +1,3 @@
|
||||||
#nullable disable
|
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class UserXpStats : DbEntity
|
public class UserXpStats : DbEntity
|
||||||
|
|
8
src/EllieBot/Db/Models/xp/XpCurrencyReward.cs
Normal file
8
src/EllieBot/Db/Models/xp/XpCurrencyReward.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
public class XpCurrencyReward : DbEntity
|
||||||
|
{
|
||||||
|
public int XpSettingsId { get; set; }
|
||||||
|
public int Level { get; set; }
|
||||||
|
public int Amount { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
public class XpCurrencyRewardEntityConfiguration : IEntityTypeConfiguration<XpCurrencyReward>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<XpCurrencyReward> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.Level,
|
||||||
|
x.XpSettingsId
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
namespace EllieBot.Db.Models;
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public enum XpNotificationLocation
|
public enum XpNotificationLocation
|
||||||
{
|
{
|
||||||
|
|
13
src/EllieBot/Db/Models/xp/XpRoleReward.cs
Normal file
13
src/EllieBot/Db/Models/xp/XpRoleReward.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
public class XpRoleReward : DbEntity
|
||||||
|
{
|
||||||
|
public int XpSettingsId { get; set; }
|
||||||
|
public int Level { get; set; }
|
||||||
|
public ulong RoleId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the role should be removed (true) or added (false)
|
||||||
|
/// </summary>
|
||||||
|
public bool Remove { get; set; }
|
||||||
|
}
|
17
src/EllieBot/Db/Models/xp/XpRoleRewardEntityConfiguration.cs
Normal file
17
src/EllieBot/Db/Models/xp/XpRoleRewardEntityConfiguration.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
public class XpRoleRewardEntityConfiguration : IEntityTypeConfiguration<XpRoleReward>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<XpRoleReward> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => new
|
||||||
|
{
|
||||||
|
x.XpSettingsId,
|
||||||
|
x.Level
|
||||||
|
})
|
||||||
|
.IsUnique();
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,62 +3,8 @@ namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
public class XpSettings : DbEntity
|
public class XpSettings : DbEntity
|
||||||
{
|
{
|
||||||
public int GuildConfigId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
public GuildConfig GuildConfig { get; set; }
|
|
||||||
|
|
||||||
public HashSet<XpRoleReward> RoleRewards { get; set; } = new();
|
public HashSet<XpRoleReward> RoleRewards { get; set; } = new();
|
||||||
public HashSet<XpCurrencyReward> CurrencyRewards { get; set; } = new();
|
public HashSet<XpCurrencyReward> CurrencyRewards { get; set; } = new();
|
||||||
public HashSet<ExcludedItem> ExclusionList { get; set; } = new();
|
|
||||||
public bool ServerExcluded { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ExcludedItemType { Channel, Role }
|
|
||||||
|
|
||||||
public class XpRoleReward : DbEntity
|
|
||||||
{
|
|
||||||
public int XpSettingsId { get; set; }
|
|
||||||
public XpSettings XpSettings { get; set; }
|
|
||||||
|
|
||||||
public int Level { get; set; }
|
|
||||||
public ulong RoleId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the role should be removed (true) or added (false)
|
|
||||||
/// </summary>
|
|
||||||
public bool Remove { get; set; }
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
=> Level.GetHashCode() ^ XpSettingsId.GetHashCode();
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
=> obj is XpRoleReward xrr && xrr.Level == Level && xrr.XpSettingsId == XpSettingsId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class XpCurrencyReward : DbEntity
|
|
||||||
{
|
|
||||||
public int XpSettingsId { get; set; }
|
|
||||||
public XpSettings XpSettings { get; set; }
|
|
||||||
|
|
||||||
public int Level { get; set; }
|
|
||||||
public int Amount { get; set; }
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
=> Level.GetHashCode() ^ XpSettingsId.GetHashCode();
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
=> obj is XpCurrencyReward xrr && xrr.Level == Level && xrr.XpSettingsId == XpSettingsId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ExcludedItem : DbEntity
|
|
||||||
{
|
|
||||||
public XpSettings XpSettings { get; set; }
|
|
||||||
|
|
||||||
public ulong ItemId { get; set; }
|
|
||||||
public ExcludedItemType ItemType { get; set; }
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
=> ItemId.GetHashCode() ^ ItemType.GetHashCode();
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
=> obj is ExcludedItem ei && ei.ItemId == ItemId && ei.ItemType == ItemType;
|
|
||||||
}
|
}
|
19
src/EllieBot/Db/Models/xp/XpSettingsEntityConfiguration.cs
Normal file
19
src/EllieBot/Db/Models/xp/XpSettingsEntityConfiguration.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace EllieBot.Db.Models;
|
||||||
|
|
||||||
|
public class XpSettingsEntityConfiguration : IEntityTypeConfiguration<XpSettings>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<XpSettings> builder)
|
||||||
|
{
|
||||||
|
builder.HasIndex(x => x.GuildId)
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
builder.HasMany(x => x.CurrencyRewards)
|
||||||
|
.WithOne();
|
||||||
|
|
||||||
|
builder.HasMany(x => x.RoleRewards)
|
||||||
|
.WithOne();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,146 +1,138 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>true</ImplicitUsings>
|
<ImplicitUsings>true</ImplicitUsings>
|
||||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||||
<Version>5.3.9</Version>
|
<Version>6.0.2</Version>
|
||||||
|
|
||||||
<!-- Output/build -->
|
<!-- Output/build -->
|
||||||
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
|
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
|
||||||
<OutputType>exe</OutputType>
|
<OutputType>exe</OutputType>
|
||||||
<ApplicationIcon>ellie_icon.ico</ApplicationIcon>
|
<ApplicationIcon>ellie_icon.ico</ApplicationIcon>
|
||||||
|
<NoWarn>CS1066;CS8981</NoWarn>
|
||||||
|
|
||||||
<!-- Analysis/Warnings -->
|
<!-- Profile-guided optimization -->
|
||||||
<!-- <AnalysisMode>Recommended</AnalysisMode>-->
|
<TieredPGO>true</TieredPGO>
|
||||||
<!-- <AnalysisModeGlobalization>None</AnalysisModeGlobalization>-->
|
<DebugType>embedded</DebugType>
|
||||||
<NoWarn>CS1066;CS8981</NoWarn>
|
|
||||||
|
|
||||||
<!-- Profile-guided optimization -->
|
|
||||||
<TieredPGO>true</TieredPGO>
|
|
||||||
<DebugType>embedded</DebugType>
|
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AngleSharp" Version="1.1.2">
|
<PackageReference Include="AngleSharp" Version="1.2.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<Publish>True</Publish>
|
<Publish>True</Publish>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.6" />
|
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.6" />
|
||||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageReference Include="Discord.Net" Version="3.16.0" />
|
<PackageReference Include="Discord.Net" Version="3.17.1" />
|
||||||
<PackageReference Include="CoreCLR-NCalc" Version="3.1.246" />
|
<PackageReference Include="CoreCLR-NCalc" Version="3.1.253" />
|
||||||
<PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.41.1.138" />
|
<PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.41.1.138" />
|
||||||
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.68.0.3414" />
|
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.68.0.3653" />
|
||||||
<PackageReference Include="Google.Apis.Customsearch.v1" Version="1.49.0.2084" />
|
<PackageReference Include="Google.Apis.Customsearch.v1" Version="1.49.0.2084" />
|
||||||
|
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.28.2" />
|
<PackageReference Include="Google.Protobuf" Version="3.29.3" />
|
||||||
<PackageReference Include="Grpc" Version="2.46.6" />
|
<PackageReference Include="Grpc" Version="2.46.6" />
|
||||||
<PackageReference Include="Grpc.Net.Client" Version="2.62.0" />
|
<PackageReference Include="Grpc.Net.Client" Version="2.67.0" />
|
||||||
<PackageReference Include="Grpc.Tools" Version="2.66.0" PrivateAssets="All" />
|
<PackageReference Include="Grpc.Tools" Version="2.69.0" PrivateAssets="All" />
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.5.0" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.8.0" />
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.1" />
|
||||||
|
|
||||||
<PackageReference Include="MorseCode.ITask" Version="2.0.3" />
|
<PackageReference Include="MorseCode.ITask" Version="2.0.3" />
|
||||||
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="3.1.0" />
|
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="3.1.0" />
|
||||||
|
|
||||||
<!-- DI -->
|
<!-- DI -->
|
||||||
<!-- <PackageReference Include="Ninject" Version="3.3.6"/>-->
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.1" />
|
||||||
<!-- <PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0"/>-->
|
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
|
||||||
<!-- <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />-->
|
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
|
|
||||||
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
|
|
||||||
<!-- <PackageReference Include="Scrutor" Version="4.2.0" />-->
|
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.1" />
|
||||||
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
|
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="NonBlocking" Version="2.1.2" />
|
<PackageReference Include="NonBlocking" Version="2.1.2" />
|
||||||
<PackageReference Include="OneOf" Version="3.0.263" />
|
<PackageReference Include="OneOf" Version="3.0.271" />
|
||||||
<PackageReference Include="OneOf.SourceGenerator" Version="3.0.263" />
|
<PackageReference Include="OneOf.SourceGenerator" Version="3.0.271" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Seq" Version="7.0.1" />
|
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
|
||||||
|
|
||||||
<PackageReference Include="SixLabors.Fonts" Version="2.0.4" />
|
<PackageReference Include="SixLabors.Fonts" Version="2.1.0" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.4" />
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.5" />
|
||||||
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009" />
|
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009" />
|
||||||
<PackageReference Include="StackExchange.Redis" Version="2.8.0" />
|
<PackageReference Include="StackExchange.Redis" Version="2.8.24" />
|
||||||
<PackageReference Include="YamlDotNet" Version="15.1.4" />
|
<PackageReference Include="YamlDotNet" Version="15.1.6" />
|
||||||
<PackageReference Include="SharpToken" Version="2.0.3" />
|
<PackageReference Include="SharpToken" Version="2.0.3" />
|
||||||
|
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
|
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
|
||||||
|
|
||||||
|
|
||||||
<!-- Db-related packages -->
|
<!-- Db-related packages -->
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.4">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
||||||
<PackageReference Include="linq2db.EntityFrameworkCore" Version="8.1.0" />
|
<PackageReference Include="linq2db.EntityFrameworkCore" Version="9.0.0" />
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.1" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.3" />
|
||||||
|
|
||||||
<PackageReference Include="EFCore.NamingConventions" Version="8.0.3" />
|
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
|
||||||
|
|
||||||
<!-- Used by stream notifications -->
|
<!-- Used by stream notifications -->
|
||||||
<PackageReference Include="TwitchLib.Api" Version="3.4.1" />
|
<PackageReference Include="TwitchLib.Api" Version="3.4.1" />
|
||||||
|
|
||||||
<!-- sqlselectcsv and stock -->
|
<!-- sqlselectcsv and stock -->
|
||||||
<PackageReference Include="CsvHelper" Version="32.0.3" />
|
<PackageReference Include="CsvHelper" Version="33.0.1" />
|
||||||
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\EllieBot.GrpcApiBase\EllieBot.GrpcApiBase.csproj" />
|
|
||||||
<ProjectReference Include="..\Ellie.Marmalade\Ellie.Marmalade.csproj" />
|
|
||||||
<ProjectReference Include="..\EllieBot.Voice\EllieBot.Voice.csproj" />
|
|
||||||
<ProjectReference Include="..\EllieBot.Generators\EllieBot.Generators.csproj" OutputItemType="Analyzer" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AdditionalFiles Include="data\strings\responses\responses.en-US.json" />
|
<ProjectReference Include="..\EllieBot.GrpcApiBase\EllieBot.GrpcApiBase.csproj" />
|
||||||
|
<ProjectReference Include="..\Ellie.Marmalade\Ellie.Marmalade.csproj" />
|
||||||
|
<ProjectReference Include="..\EllieBot.Voice\EllieBot.Voice.csproj" />
|
||||||
|
<ProjectReference Include="..\EllieBot.Generators\EllieBot.Generators.csproj" OutputItemType="Analyzer" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="data\**\*">
|
<AdditionalFiles Include="strings\responses\responses.en-US.json" />
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="creds.yml">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="creds_example.yml">
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Protobuf Include="..\EllieBot.Coordinator\Protos\coordinator.proto">
|
<None Update="data/**/*">
|
||||||
<Link>_common\CoordinatorProtos\coordinator.proto</Link>
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
<!-- <GrpcServices>Client</GrpcServices>-->
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Protobuf>
|
</None>
|
||||||
|
<None Update="strings/**">
|
||||||
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Migrations/**/*.sql">
|
||||||
|
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="..\EllieBot.Coordinator\Protos\coordinator.proto">
|
||||||
|
<Link>_common\CoordinatorProtos\coordinator.proto</Link>
|
||||||
|
<GrpcServices>Client</GrpcServices>
|
||||||
|
</Protobuf>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'GlobalEllie' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'GlobalEllie' ">
|
||||||
<!-- Define trace doesn't seem to affect the build at all so I had to remove $(DefineConstants)-->
|
<!-- Define trace doesn't seem to affect the build at all so I had to remove $(DefineConstants)-->
|
||||||
<DefineTrace>false</DefineTrace>
|
<DefineTrace>false</DefineTrace>
|
||||||
<DefineConstants>GLOBAL_ELLIE</DefineConstants>
|
<DefineConstants>GLOBAL_ELLIE</DefineConstants>
|
||||||
<NoWarn>$(NoWarn);CS1573;CS1591</NoWarn>
|
<NoWarn>$(NoWarn);CS1573;CS1591</NoWarn>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<DebugType>portable</DebugType>
|
<DebugType>portable</DebugType>
|
||||||
<DebugSymbols>false</DebugSymbols>
|
<DebugSymbols>false</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
17
src/EllieBot/EllieBot.csproj.DotSettings
Normal file
17
src/EllieBot/EllieBot.csproj.DotSettings
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Canti/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cbtnrole/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cclub/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Ccurrency/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cexpr/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cfilter/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cgiveaway/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cncanvas/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cpunish/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Croles/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cslowmode/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Csupport/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Ctodo/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cuntimer/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=db_005Cmodels_005Cxp/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=modules_005Cadministration_005Cnotify_005Cmodels/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
@ -1,133 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace EllieBot.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.IsSqlite())
|
|
||||||
{
|
|
||||||
migrationBuilder.Sql(
|
|
||||||
@"insert or 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.IsNpgsql())
|
|
||||||
{
|
|
||||||
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
|
|
||||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id
|
|
||||||
ON CONFLICT DO NOTHING;");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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
|
@ -1,26 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class stondel : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
|
||||||
name: "deletestreamonlinemessage",
|
|
||||||
table: "guildconfigs",
|
|
||||||
type: "boolean",
|
|
||||||
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,40 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class bank : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "bankusers",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
userid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
balance = table.Column<long>(type: "bigint", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_bankusers", x => x.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
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,114 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class newrero : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "reactionroles",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
messageid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
emote = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
|
|
||||||
roleid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
group = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
levelreq = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_reactionroles", x => x.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
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: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
guildconfigid = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
|
||||||
exclusive = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
index = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
messageid = table.Column<decimal>(type: "numeric(20,0)", 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);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "reactionrole",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
dateadded = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
|
||||||
emotename = table.Column<string>(type: "text", nullable: true),
|
|
||||||
reactionrolemessageid = table.Column<int>(type: "integer", nullable: true),
|
|
||||||
roleid = table.Column<decimal>(type: "numeric(20,0)", 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);
|
|
||||||
});
|
|
||||||
|
|
||||||
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,169 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
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: "integer");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<long>(
|
|
||||||
name: "awardedxp",
|
|
||||||
table: "userxpstats",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "integer");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<long>(
|
|
||||||
name: "amountrewardedthismonth",
|
|
||||||
table: "rewardedusers",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "integer");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<bool>(
|
|
||||||
name: "verboseerrors",
|
|
||||||
table: "guildconfigs",
|
|
||||||
type: "boolean",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: true,
|
|
||||||
oldClrType: typeof(bool),
|
|
||||||
oldType: "boolean");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<long>(
|
|
||||||
name: "totalxp",
|
|
||||||
table: "discorduser",
|
|
||||||
type: "bigint",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0L,
|
|
||||||
oldClrType: typeof(int),
|
|
||||||
oldType: "integer",
|
|
||||||
oldDefaultValue: 0);
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "patronquotas",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
userid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
featuretype = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
feature = table.Column<string>(type: "text", nullable: false),
|
|
||||||
hourlycount = table.Column<long>(type: "bigint", nullable: false),
|
|
||||||
dailycount = table.Column<long>(type: "bigint", nullable: false),
|
|
||||||
monthlycount = table.Column<long>(type: "bigint", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_patronquotas", x => new { x.userid, x.featuretype, x.feature });
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "patrons",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
userid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
uniqueplatformuserid = table.Column<string>(type: "text", nullable: true),
|
|
||||||
amountcents = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
lastcharge = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
|
||||||
validthru = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_patrons", x => x.userid);
|
|
||||||
});
|
|
||||||
|
|
||||||
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: "integer",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(long),
|
|
||||||
oldType: "bigint");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "awardedxp",
|
|
||||||
table: "userxpstats",
|
|
||||||
type: "integer",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(long),
|
|
||||||
oldType: "bigint");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "amountrewardedthismonth",
|
|
||||||
table: "rewardedusers",
|
|
||||||
type: "integer",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(long),
|
|
||||||
oldType: "bigint");
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<bool>(
|
|
||||||
name: "verboseerrors",
|
|
||||||
table: "guildconfigs",
|
|
||||||
type: "boolean",
|
|
||||||
nullable: false,
|
|
||||||
oldClrType: typeof(bool),
|
|
||||||
oldType: "boolean",
|
|
||||||
oldDefaultValue: true);
|
|
||||||
|
|
||||||
migrationBuilder.AlterColumn<int>(
|
|
||||||
name: "totalxp",
|
|
||||||
table: "discorduser",
|
|
||||||
type: "integer",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0,
|
|
||||||
oldClrType: typeof(long),
|
|
||||||
oldType: "bigint",
|
|
||||||
oldDefaultValue: 0L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,36 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class stondeldbcache : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "streamonlinemessages",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
messageid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
type = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
name = table.Column<string>(type: "text", nullable: true),
|
|
||||||
dateadded = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_streamonlinemessages", x => x.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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 EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class logwarns : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<decimal>(
|
|
||||||
name: "logwarnsid",
|
|
||||||
table: "logsettings",
|
|
||||||
type: "numeric(20,0)",
|
|
||||||
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,42 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class xpitemshop : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "xpshopowneditem",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
userid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
itemtype = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
isusing = table.Column<bool>(type: "boolean", nullable: false),
|
|
||||||
itemkey = table.Column<string>(type: "text", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_xpshopowneditem", x => x.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
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 EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class linkonlychannels : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "type",
|
|
||||||
table: "imageonlychannels",
|
|
||||||
type: "integer",
|
|
||||||
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
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,25 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class banprune : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "prunedays",
|
|
||||||
table: "bantemplates",
|
|
||||||
type: "integer",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "prunedays",
|
|
||||||
table: "bantemplates");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,25 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class shoprolereq : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<decimal>(
|
|
||||||
name: "rolerequirement",
|
|
||||||
table: "shopentry",
|
|
||||||
type: "numeric(20,0)",
|
|
||||||
nullable: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "rolerequirement",
|
|
||||||
table: "shopentry");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,40 +0,0 @@
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
namespace EllieBot.Migrations.PostgreSql
|
|
||||||
{
|
|
||||||
public partial class autopub : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "autopublishchannel",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
id = table.Column<int>(type: "integer", nullable: false)
|
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
|
||||||
dateadded = table.Column<DateTime>(type: "timestamp without time zone", nullable: true)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("pk_autopublishchannel", x => x.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "ix_autopublishchannel_guildid",
|
|
||||||
table: "autopublishchannel",
|
|
||||||
column: "guildid",
|
|
||||||
unique: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "autopublishchannel");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue