mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
Compare commits
127 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2797e56666 | ||
|
11f27ab67a | ||
|
c5f8bf1891 | ||
|
66b57482bd | ||
|
dd9d914943 | ||
|
8b0b1af1f3 | ||
|
bdff19c718 | ||
|
eec4a91743 | ||
|
42caefbd1e | ||
|
3edf435fa9 | ||
|
32da43ad46 | ||
|
3f2d1e128e | ||
|
352ced1553 | ||
|
17a3fb2c52 | ||
|
2235729158 | ||
|
3e4d5d07e5 | ||
|
1857d65b77 | ||
|
38da171675 | ||
|
df076be15c | ||
|
190f030b93 | ||
|
411b873c84 | ||
|
50346fc5b4 | ||
|
e32a65bca4 | ||
|
ffff539545 | ||
|
4b3b6e37a9 | ||
|
620bcae4bb | ||
|
ab0fd44b46 | ||
|
b61f499f91 | ||
|
53d365db3a | ||
|
140c4f7fd6 | ||
|
5627a3b172 | ||
|
4795fa98a0 | ||
|
93453ba522 | ||
|
c6a9108474 | ||
|
c3ba805acf | ||
|
c0ce22a6b7 | ||
|
22183501fe | ||
|
2fbdab3235 | ||
|
804d3f79fd | ||
|
fb119cca4c | ||
|
31af5ea8c2 | ||
|
e1776d6093 | ||
|
33dd4bbf0e | ||
|
af343ac1f0 | ||
|
065807c180 | ||
|
9cd24feccc | ||
|
a2d1506915 | ||
|
54a32a5770 | ||
|
5b9abeb0b2 | ||
|
accfb2d1ac | ||
|
71d383c4db | ||
|
197ee9f5ff | ||
|
d51d159962 | ||
|
89b0eabd41 | ||
|
8d932d546a | ||
|
9ea3460e3d | ||
|
7bd4db60a8 | ||
|
42e1f35df2 | ||
|
179784da3e | ||
|
9ed0c870d1 | ||
|
77e288ee54 | ||
|
58adaa9110 | ||
|
d3a73945e7 | ||
|
caca407abd | ||
|
4fd7b2d8cd | ||
|
eaea6e3c54 | ||
|
0bb68c7723 | ||
|
52b2c0910c | ||
|
9a4bb7bff9 | ||
|
ab5450a125 | ||
|
bcce32423c | ||
|
c42d529016 | ||
|
cbea5077be | ||
|
cdc2cc1439 | ||
|
87819f21bf | ||
|
d1be56fbc1 | ||
|
14016a761d | ||
|
12a64c4c4d | ||
|
d922120f58 | ||
|
8e8e349e65 | ||
|
ccdf0fc077 | ||
|
8c66bcb1e1 | ||
|
77fb47183f | ||
|
d275dc36b2 | ||
|
7bff20cc70 | ||
|
29f5dcc359 | ||
|
14f2851072 | ||
|
a2b25f8246 | ||
|
a38951b5ad | ||
|
4c1b911cb7 | ||
|
6c9f231453 | ||
|
83daf3c30f | ||
|
9be8140d4d | ||
|
96c9b699aa | ||
|
3c0768a372 | ||
|
58b22e3d9e | ||
|
0474551e2f | ||
|
c85bdec396 | ||
|
5fa39eaa9f | ||
|
8eaaa35c7a | ||
|
1c24f95efa | ||
|
fcc49dbbdb | ||
|
3a317590b4 | ||
|
36c013fbb5 | ||
|
a9ec8049f6 | ||
|
ced0d97e3a | ||
|
24d0f57dc3 | ||
|
514ecd6be8 | ||
|
02eb6e172b | ||
|
d22c579875 | ||
|
f70e49fc6a | ||
|
8b410561f9 | ||
|
3c79fd1d6f | ||
|
e9f1a9b1dd | ||
|
3c293ae6db | ||
|
a5d9e7de66 | ||
|
4d9e48cd41 | ||
|
b7ead22e09 | ||
|
9f219cddbb | ||
|
cf9792f24a | ||
|
0187dd57ac | ||
|
2d2e54e31e | ||
|
cb7c5e48fd | ||
|
771c2745dc | ||
|
59c0f2f4b3 | ||
|
219ca39cd1 | ||
|
1e6d0806d7 |
41
CHANGELOG.md
41
CHANGELOG.md
@@ -2,6 +2,47 @@
|
||||
|
||||
Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o
|
||||
|
||||
## [3.0.13] - 14.04.2021
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `.greetdm` causing ratelimits during raids
|
||||
- Fixed `.gelbooru`
|
||||
|
||||
## [3.0.12] - 06.01.2021
|
||||
|
||||
### Fixed
|
||||
- `.smch` Fixed
|
||||
- `.trans` command will now work properly with capitilized language names
|
||||
- Ban message color with plain text fixed
|
||||
- Fixed some grpc coordinator bugs
|
||||
- Fixed a string in `.xpex`
|
||||
- Google version of .img will now have safe search enabled
|
||||
- Fixed a small bug in `.hangman`
|
||||
|
||||
## [3.0.11] - 17.12.2021
|
||||
|
||||
### Added
|
||||
- `.remindl` and `.remindrm` commands now supports optional 'server' parameter for Administrators which allows them to delete any reminder created on the server
|
||||
- Added slots.currencyFontColor to gambling.yml
|
||||
- Added `.qexport` and `.qimport` commands which allow you to export and import quotes just like `.crsexport`
|
||||
- Added `.showembed <msgid>` and `.showembed #channel <msgid>` which will show you embed json from the specified message
|
||||
|
||||
### Changed
|
||||
- `.at` and `.atl` commands reworked
|
||||
- Persist restarts
|
||||
- Will now only translate non-commands
|
||||
- You can switch between `.at del` and `.at` without clearing the user language registrations
|
||||
- Disabling `.at` will clear all user language registrations on that channel
|
||||
- Users can't register languages if the `.at` is not enabled
|
||||
- Looks much nicer
|
||||
- Bot will now reply to user messages with a translation if `del` is disabled
|
||||
- Bot will make an embed with original and translated text with user avatar and name if `del` is enabled
|
||||
- If the bot is unable to delete messages while having `del` enabled, it will reset back to the no-del behavior for the current session
|
||||
|
||||
### Fixed
|
||||
- `.crypto` now supports top 5000 coins
|
||||
|
||||
## [3.0.10] - 01.12.2021
|
||||
|
||||
### Changed
|
||||
|
@@ -13,8 +13,13 @@ This document aims to guide you through the process of creating a Discord accoun
|
||||
- Click on the `Add a Bot` button and confirm that you do want to add a bot to this app.
|
||||
- **Optional:** Add bot's avatar and description.
|
||||
- Copy your Token to `creds.yml` as shown above.
|
||||
- Scroll down to the `Privileged Gateway Intents` section and enable both intents.
|
||||
These are required for a number of features to function properly, and should both be on.
|
||||
- Scroll down to the `Privileged Gateway Intents` section
|
||||
- Enabled the following:
|
||||
- PRESENCE INTENT
|
||||
- SERVER MEMBERS INTENT
|
||||
- MESSAGE CONTENT INTENT
|
||||
|
||||
These are required for a number of features to function properly, and all should be on.
|
||||
|
||||
##### Getting Owner ID*(s)*:
|
||||
|
||||
@@ -32,7 +37,7 @@ For a single owner, it should look like this:
|
||||
- 105635576866156544
|
||||
```
|
||||
|
||||
For multiple owners, it should look like this (pay attention to the commas, the last ID should **never** have a comma next to it):
|
||||
For multiple owners, it should look like this:
|
||||
|
||||
```yml
|
||||
OwnerIds:
|
||||
@@ -56,4 +61,4 @@ For multiple owners, it should look like this (pay attention to the commas, the
|
||||
|
||||
That's it! You may now go back to the installation guide you were following before 🎉
|
||||
|
||||
[DiscordApp]: https://discordapp.com/developers/applications/me
|
||||
[DiscordApp]: https://discordapp.com/developers/applications/me
|
||||
|
@@ -4,6 +4,19 @@
|
||||
|
||||
#### [Linux migration instructions](../migration-guide/#linux)
|
||||
|
||||
#### Operating System Compatibility
|
||||
|
||||
It is recommended that you use **Ubuntu 20.04**, as there have been nearly no problems with it. Also, **32-bit systems are incompatible**.
|
||||
|
||||
##### Compatible operating systems:
|
||||
|
||||
- Ubuntu: 16.04, 18.04, 20.04, 21.04, 21.10
|
||||
- Mint: 19, 20
|
||||
- Debian: 9, 10
|
||||
- CentOS: 7
|
||||
- openSUSE
|
||||
- Fedora: 33, 34, 35
|
||||
|
||||
## Linux From Source
|
||||
|
||||
Open Terminal (if you're on an installation with a window manager) and navigate to the location where you want to install the bot (for example `cd ~`)
|
||||
@@ -13,11 +26,11 @@ Open Terminal (if you're on an installation with a window manager) and navigate
|
||||
1. Download and run the **new** installer script `cd ~ && wget -N https://gitlab.com/Kwoth/nadeko-bash-installer/-/raw/master/linuxAIO.sh && bash linuxAIO.sh`
|
||||
2. Install prerequisites (type `1` and press enter)
|
||||
3. Download the bot (type `2` and press enter)
|
||||
4. Exit the installer in order to set up your `creds.yml`
|
||||
4. Exit the installer (type `5` and press enter)
|
||||
5. Copy the creds.yml template `cp nadekobot/output/creds_example.yml nadekobot/output/creds.yml`
|
||||
6. Open `nadekobot/output/creds.yml` with your favorite text editor. We will use nano here
|
||||
- `nano nadekobot/output/creds.yml`
|
||||
7. [Enter your bot's token](../../creds-guide)
|
||||
7. [Click here to follow creds guide](../../creds-guide)
|
||||
- After you're done, you can close nano (and save the file) by inputting, in order
|
||||
- `CTRL` + `X`
|
||||
- `Y`
|
||||
@@ -34,6 +47,8 @@ Open Terminal (if you're on an installation with a window manager) and navigate
|
||||
|
||||
## Linux Release
|
||||
|
||||
⚠ IF YOU ARE FOLLOWING THE GUIDE ABOVE, IGNORE THIS SECTION ⚠
|
||||
|
||||
##### Installation Instructions
|
||||
|
||||
1. Download the latest release from <https://gitlab.com/Kwoth/nadekobot/-/releases>
|
||||
@@ -48,8 +63,8 @@ Open Terminal (if you're on an installation with a window manager) and navigate
|
||||
5. Copy the creds.yml template
|
||||
- `cp creds_example.yml creds.yml`
|
||||
6. Open `creds.yml` with your favorite text editor. We will use nano here
|
||||
- `nano nadekobot/output/creds.yml`
|
||||
8. [Enter your bot's token](#creds-guide)
|
||||
- `nano creds.yml`
|
||||
8. [Click here to follow creds guide](../../creds-guide)
|
||||
- After you're done, you can close nano (and save the file) by inputting, in order
|
||||
- `CTRL` + `X`
|
||||
- `Y`
|
||||
@@ -244,3 +259,34 @@ This method is similar to the one above, but requires one extra step, with the a
|
||||
|
||||
5. Start Nadeko:
|
||||
- `sudo systemctl start nadeko.service && sudo systemctl enable nadeko.service`
|
||||
|
||||
### Setting up Nadeko on a Linux VPS (Digital Ocean Droplet)
|
||||
|
||||
If you want Nadeko to play music for you 24/7 without having to hosting it on your PC and want to keep it cheap, reliable and convenient as possible, you can try Nadeko on Linux Digital Ocean Droplet using the link [DigitalOcean](http://m.do.co/c/46b4d3d44795/) (by using this link, you will get **$10 credit** and also support Nadeko)
|
||||
|
||||
**Setting up NadekoBot**
|
||||
Assuming you have followed the link above to setup an account and a Droplet with a 64-bit operational system on Digital Ocean and got the `IP address and root password (in your e-mail)` to login, it's time to get started.
|
||||
|
||||
**This section is only relevant to those who want to host Nadeko on DigitalOcean. Go through this whole section before setting the bot up.**
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
- Download [PuTTY](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html)
|
||||
- Download [WinSCP](https://winscp.net/eng/download.php) *(optional)*
|
||||
- [Create and invite the bot](../../creds-guide).
|
||||
|
||||
#### Starting up
|
||||
|
||||
- **Open PuTTY** and paste or enter your `IP address` and then click **Open**.
|
||||
If you entered your Droplets IP address correctly, it should show **login as:** in a newly opened window.
|
||||
- Now for **login as:**, type `root` and press enter.
|
||||
- It should then ask for a password. Type the `root password` you have received in your e-mail address, then press Enter.
|
||||
|
||||
If you are running your droplet for the first time, it will most likely ask you to change your root password. To do that, copy the **password you've received by e-mail** and paste it on PuTTY.
|
||||
|
||||
- To paste, just right-click the window (it won't show any changes on the screen), then press Enter.
|
||||
- Type a **new password** somewhere, copy and paste it on PuTTY. Press Enter then paste it again.
|
||||
|
||||
**Save the new password somewhere safe.**
|
||||
|
||||
After that, your droplet should be ready for use. [Follow the guide from the beginning](#linux-from-source) to set Nadeko up on your newly created VPS.
|
||||
|
@@ -15,9 +15,9 @@
|
||||
|
||||
## Linux
|
||||
|
||||
1. In order to migrate a bot hosted on **Linux**, first update your current version to the latest 2.x version using the 2.x installer, run the bot, and make sure it works. Then:
|
||||
- Run the **old** installer with `cd ~ && wget -N https://github.com/Kwoth/NadekoBot-BashScript/raw/1.9/linuxAIO.sh && bash linuxAIO.sh`
|
||||
- Run option **1** again
|
||||
1. In order to migrate a bot hosted on **Linux**, first **BACKUP** then update your current version to the latest **2.x** version using the **2.x** installer, run the bot, and make sure it works. Then:
|
||||
- Run the **old** installer with `cd ~ && wget -N https://gitlab.com/hokutochen/becausekwoth/-/raw/main/linuxAIO.sh && bash linuxAIO.sh`
|
||||
- Run option **2**
|
||||
- You **MUST** Run the bot now to ensure database is ready for migration
|
||||
- Type `.stats` and ensure the version is `2.46.5` or later
|
||||
- Stop the bot
|
||||
|
@@ -2,13 +2,32 @@
|
||||
|
||||
Open Terminal (if you don't know how to, click on the magnifying glass on the top right corner of your screen and type **Terminal** on the window that pops up) and navigate to the location where you want to install the bot (for example `cd ~`)
|
||||
|
||||
##### Installing Homebrew and wget
|
||||
##### Installing Homebrew, wget and dotnet
|
||||
|
||||
###### Homebrew/wget
|
||||
*Skip this step if you already have homebrew installed*
|
||||
- Copy and paste this command, then press Enter:
|
||||
- `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`
|
||||
- Install wget
|
||||
- `brew install wget`
|
||||
- `brew install wget`
|
||||
|
||||
###### Dotnet
|
||||
- Download [.net5 SDK](https://dotnet.microsoft.com/download/dotnet/5.0)
|
||||
- Open the `.pkg` file you've downloaded and install it.
|
||||
- Run this command in Terminal. There might be output. If there is, disregard it. (copy-paste the entire block)
|
||||
```bash
|
||||
sudo mkdir /usr/local/bin
|
||||
|
||||
sudo mkdir /usr/local/lib
|
||||
```
|
||||
- Run this command in Terminal. There won't be any output. (copy-paste the entire block):
|
||||
```bash
|
||||
sudo ln -s /usr/local/share/dotnet/dotnet /usr/local/bin
|
||||
|
||||
sudo ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/
|
||||
|
||||
sudo ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/
|
||||
```
|
||||
|
||||
##### Installation Instructions
|
||||
|
||||
@@ -37,6 +56,8 @@ Open Terminal (if you don't know how to, click on the magnifying glass on the to
|
||||
|
||||
## MacOS Manual Release installation instructions
|
||||
|
||||
⚠ IF YOU ARE FOLLOWING THE GUIDE ABOVE, IGNORE THIS SECTION ⚠
|
||||
|
||||
##### Installation Instructions
|
||||
|
||||
1. Download the latest release from <https://gitlab.com/Kwoth/nadekobot/-/releases>
|
||||
@@ -101,4 +122,4 @@ rm -r nadekobot-old/data/strings && \
|
||||
cp -RT nadekobot-old/data/ nadekobot/data/ && \
|
||||
cp nadekobot-old/creds.yml nadekobot/ && \
|
||||
cd nadekobot && chmod +x NadekoBot
|
||||
```
|
||||
```
|
||||
|
@@ -12,11 +12,11 @@
|
||||
| [Setup](#setup) |
|
||||
| [Starting the Bot](#starting-the-bot) |
|
||||
| [Updating Nadeko](#updating-nadeko) |
|
||||
| [Manually Installing the Prerequisites from the Updater](#if-the-updater-fails-to-install-the-prerequisites-for-any-reason) |
|
||||
| [Manually Installing the Prerequisites from the Updater](#music-prerequisites) |
|
||||
|
||||
*Note: If you want to make changes to Nadeko's source code, please follow the [From Source][SourceGuide] guide instead.*
|
||||
*Note: If you want to make changes to Nadeko's source code, please follow the [From Source](#windows-from-source) guide instead.*
|
||||
|
||||
*If you have Windows 7 or a 32-bit system, please refer to the [From Source][SourceGuide] guide.*
|
||||
*If you have Windows 7 or a 32-bit system, please refer to the [From Source](#windows-from-source)) guide.*
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
- Click on **`DOWNLOAD`** at the lower right
|
||||

|
||||
- Click on **`Install`** next to **`Redis`**.
|
||||
- **Note: If Redis fails to install, install Redis manually here: [Redis Installer](https://github.com/MicrosoftArchive/redis/releases/tag/win-3.0.504) Download and run the **`.msi`** file.
|
||||
- Note: If Redis fails to install, install Redis manually here: [Redis Installer](https://github.com/MicrosoftArchive/redis/releases/tag/win-3.0.504) Download and run the **`.msi`** file.
|
||||
- If you will use the music module, click on **`Install`** next to **`FFMPEG`** and **`Youtube-DL`**.
|
||||
- If any dependencies fail to install, you can temporarily disable your Windows Defender/AV until you install them. If you don't want to, then read [the last section of this guide](#Manual-Prerequisite-Installation).
|
||||
- When installation is finished, click on **`CREDS`** to the left of **`RUN`** at the lower right.
|
||||
@@ -69,6 +69,8 @@ You can still install them manually:
|
||||
|
||||
### Windows From Source
|
||||
|
||||
⚠ IF YOU ARE FOLLOWING THE GUIDE ABOVE, IGNORE THIS SECTION ⚠
|
||||
|
||||
##### Prerequisites
|
||||
|
||||
**Install these before proceeding or your bot will not work!**
|
||||
@@ -83,11 +85,12 @@ Open PowerShell (press windows button on your keyboard and type powershell, it s
|
||||
1. `git clone https://gitlab.com/kwoth/nadekobot -b v3 --depth 1`
|
||||
2. `cd nadekobot`
|
||||
3. `dotnet publish -c Release -o output/ src/NadekoBot/`
|
||||
4. `cd output && cp creds_example.yml creds.yml`
|
||||
5. Open `creds.yml` with your favorite text editor (Please don't use Notepad or WordPad. You can use Notepad++, VSCode, Atom, Sublime, or something similar)
|
||||
6. [Enter your bot's token](#creds-guide)
|
||||
7. Run the bot `dotnet NadekoBot.dll`
|
||||
8. 🎉
|
||||
4. `cd output`
|
||||
5. `cp creds_example.yml creds.yml`
|
||||
6. Open `creds.yml` with your favorite text editor (Please don't use Notepad or WordPad. You can use Notepad++, VSCode, Atom, Sublime, or something similar)
|
||||
7. [Enter your bot's token](#creds-guide)
|
||||
8. Run the bot `dotnet NadekoBot.dll`
|
||||
9. 🎉
|
||||
|
||||
##### Update Instructions
|
||||
|
||||
@@ -129,8 +132,6 @@ In order to use music commands, you need ffmpeg and youtube-dl installed.
|
||||
[Redis]: https://github.com/MicrosoftArchive/redis/releases/download/win-3.0.504/Redis-x64-3.0.504.msi
|
||||
[Visual C++ 2010 (x86)]: https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe
|
||||
[Visual C++ 2017 (x64)]: https://aka.ms/vs/15/release/vc_redist.x64.exe
|
||||
[SourceGuide]: ../from-source
|
||||
[ffmpeg-32bit]: https://cdn.nadeko.bot/dl/ffmpeg-32.zip
|
||||
[ffmpeg-64bit]: https://cdn.nadeko.bot/dl/ffmpeg-64.zip
|
||||
[youtube-dl]: https://yt-dl.org/downloads/latest/youtube-dl.exe
|
||||
|
||||
|
@@ -8,8 +8,14 @@ This part is completely optional, **however it's necessary for music and a few o
|
||||
- Go to [Google Console][Google Console] and log in.
|
||||
- Create a new project (name does not matter).
|
||||
- Once the project is created, go into `Library`
|
||||
- Under the `YouTube APIs` section, enable `YouTube Data API`
|
||||
- On the left tab, access `Credentials`,
|
||||
- Under the `YouTube APIs` section
|
||||
- Select `YouTube Data API v3`,
|
||||
- Click enable.
|
||||
- Search for `Custom Search API`
|
||||
- Select `Custom Search API`,
|
||||
- Click enable.
|
||||
- Open up the `Navigation menu` on the top right with the three lines.
|
||||
- select `APIs & Services`, then select `Credentials`,
|
||||
- Click `Create Credentials` button,
|
||||
- Click on `API Key`
|
||||
- A new window will appear with your `Google API key`
|
||||
@@ -18,7 +24,7 @@ This part is completely optional, **however it's necessary for music and a few o
|
||||
- Open up `creds.yml` and look for `GoogleAPIKey`, paste your API key after the `:`.
|
||||
- It should look like this:
|
||||
```yml
|
||||
GoogleApiKey: "AIzaSyDSci1sdlWQOWNVj1vlXxxxxxbk0oWMEzM"
|
||||
GoogleApiKey: AIzaSyDSci1sdlWQOWNVj1vlXxxxxxbk0oWMEzM
|
||||
```
|
||||
- **MashapeKey**
|
||||
- Required for Hearthstone cards.
|
||||
@@ -69,6 +75,7 @@ For Windows (Updater), add this to your `creds.yml`
|
||||
```yml
|
||||
RestartCommand:
|
||||
Cmd: "NadekoBot.exe"
|
||||
args: "{0}"
|
||||
```
|
||||
|
||||
For Windows (Source), Linux or OSX, add this to your `creds.yml`
|
||||
@@ -92,11 +99,10 @@ version: 1
|
||||
token: 'MTE5Nzc3MDIxMzE5NTc3NjEw.VlhNCw.BuqJFyzdIUAK1PRf1eK1Cu89Jew'
|
||||
# List of Ids of the users who have bot owner permissions
|
||||
# **DO NOT ADD PEOPLE YOU DON'T TRUST**
|
||||
ownerIds: [
|
||||
105635123466156544,
|
||||
145521851676884992,
|
||||
341420590009417729
|
||||
]
|
||||
ownerIds:
|
||||
- 105635123466156544
|
||||
- 145521851676884992
|
||||
- 341420590009417729
|
||||
# The number of shards that the bot will running on.
|
||||
# Leave at 1 if you don't know what you're doing.
|
||||
totalShards: 1
|
||||
@@ -156,8 +162,8 @@ osuApiKey: 4c8c8fdffdsfdsfsdfsfa33f3f3140a7d93320d6
|
||||
# cmd: dotnet
|
||||
# args: "NadekoBot.dll -- {0}"
|
||||
# Windows default
|
||||
# cmd: NadekoBot.exe
|
||||
# args: {0}
|
||||
# cmd: "NadekoBot.exe"
|
||||
# args: "{0}"
|
||||
restartCommand:
|
||||
cmd:
|
||||
args:
|
||||
|
@@ -9,9 +9,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.38.0" />
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.41.0" />
|
||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
|
||||
<PackageReference Include="YamlDotNet" Version="11.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@@ -160,18 +160,24 @@ namespace NadekoBot.Coordinator
|
||||
private void StartShard(int shardId)
|
||||
{
|
||||
var status = _shardStatuses[shardId];
|
||||
if (status.Process is {HasExited: false} p)
|
||||
try
|
||||
{
|
||||
try
|
||||
if (status.Process is { HasExited: false } p)
|
||||
{
|
||||
p.Kill(true);
|
||||
try
|
||||
{
|
||||
p.Kill(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
status.Process?.Dispose();
|
||||
status.Process?.Dispose();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
var proc = StartShardProcess(shardId);
|
||||
_shardStatuses[shardId] = status with
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@@ -19,6 +19,7 @@ using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Common.Configs;
|
||||
using NadekoBot.Db;
|
||||
using NadekoBot.Modules.Administration.Services;
|
||||
using NadekoBot.Modules.Searches;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot
|
||||
@@ -105,7 +106,7 @@ namespace NadekoBot
|
||||
.AddSingleton<ISeria, JsonSeria>()
|
||||
.AddSingleton<IPubSub, RedisPubSub>()
|
||||
.AddSingleton<IConfigSeria, YamlSeria>()
|
||||
.AddBotStringsServices()
|
||||
.AddBotStringsServices(_creds.TotalShards)
|
||||
.AddConfigServices()
|
||||
.AddConfigMigrators()
|
||||
.AddMemoryCache()
|
||||
|
@@ -19,6 +19,9 @@ namespace NadekoBot.Common
|
||||
/// <returns>Task representing download state</returns>
|
||||
public async Task EnsureUsersDownloadedAsync(IGuild guild)
|
||||
{
|
||||
#if GLOBAL_NADEKO
|
||||
return;
|
||||
#endif
|
||||
await downloadUsersSemaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
|
@@ -14,11 +14,15 @@ namespace NadekoBot.Extensions
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddBotStringsServices(this IServiceCollection services)
|
||||
=> services
|
||||
.AddSingleton<IStringsSource, LocalFileStringsSource>()
|
||||
.AddSingleton<IBotStringsProvider, LocalBotStringsProvider>()
|
||||
.AddSingleton<IBotStrings, BotStrings>();
|
||||
public static IServiceCollection AddBotStringsServices(this IServiceCollection services, int totalShards)
|
||||
=> totalShards <= 1
|
||||
? services
|
||||
.AddSingleton<IStringsSource, LocalFileStringsSource>()
|
||||
.AddSingleton<IBotStringsProvider, LocalBotStringsProvider>()
|
||||
.AddSingleton<IBotStrings, BotStrings>()
|
||||
: services.AddSingleton<IStringsSource, LocalFileStringsSource>()
|
||||
.AddSingleton<IBotStringsProvider, RedisBotStringsProvider>()
|
||||
.AddSingleton<IBotStrings, BotStrings>();
|
||||
|
||||
public static IServiceCollection AddConfigServices(this IServiceCollection services)
|
||||
{
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Discord;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Services;
|
||||
@@ -29,6 +30,47 @@ namespace NadekoBot
|
||||
(Footer != null && (!string.IsNullOrWhiteSpace(Footer.Text) || !string.IsNullOrWhiteSpace(Footer.IconUrl))) ||
|
||||
(Fields != null && Fields.Length > 0);
|
||||
|
||||
public static SmartEmbedText FromEmbed(IEmbed eb, string plainText = null)
|
||||
{
|
||||
var set = new SmartEmbedText();
|
||||
|
||||
set.PlainText = plainText;
|
||||
set.Title = eb.Title;
|
||||
set.Description = eb.Description;
|
||||
set.Url = eb.Url;
|
||||
set.Thumbnail = eb.Thumbnail?.Url;
|
||||
set.Image = eb.Image?.Url;
|
||||
set.Author = eb.Author is EmbedAuthor ea
|
||||
? new()
|
||||
{
|
||||
Name = ea.Name,
|
||||
Url = ea.Url,
|
||||
IconUrl = ea.IconUrl
|
||||
}
|
||||
: null;
|
||||
set.Footer = eb.Footer is EmbedFooter ef
|
||||
? new()
|
||||
{
|
||||
Text = ef.Text,
|
||||
IconUrl = ef.IconUrl
|
||||
}
|
||||
: null;
|
||||
|
||||
if (eb.Fields.Length > 0)
|
||||
set.Fields = eb
|
||||
.Fields
|
||||
.Select(field => new SmartTextEmbedField()
|
||||
{
|
||||
Inline = field.Inline,
|
||||
Name = field.Name,
|
||||
Value = field.Value,
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
set.Color = eb.Color?.RawValue ?? 0;
|
||||
return set;
|
||||
}
|
||||
|
||||
public EmbedBuilder GetEmbed()
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
|
@@ -9,6 +9,11 @@ namespace NadekoBot.Db
|
||||
{
|
||||
public static class QuoteExtensions
|
||||
{
|
||||
public static IEnumerable<Quote> GetForGuild(this DbSet<Quote> quotes, ulong guildId)
|
||||
{
|
||||
return quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
||||
}
|
||||
|
||||
public static IEnumerable<Quote> GetGroup(this DbSet<Quote> quotes, ulong guildId, int page, OrderType order)
|
||||
{
|
||||
var q = quotes.AsQueryable().Where(x => x.GuildId == guildId);
|
||||
|
@@ -18,5 +18,12 @@ namespace NadekoBot.Db
|
||||
.OrderBy(x => x.DateAdded)
|
||||
.Skip(page * 10)
|
||||
.Take(10);
|
||||
|
||||
public static IEnumerable<Reminder> RemindersForServer(this DbSet<Reminder> reminders, ulong serverId, int page)
|
||||
=> reminders.AsQueryable()
|
||||
.Where(x => x.ServerId == serverId)
|
||||
.OrderBy(x => x.DateAdded)
|
||||
.Skip(page * 10)
|
||||
.Take(10);
|
||||
}
|
||||
}
|
||||
|
12
src/NadekoBot/Db/Models/AutoTranslateChannel.cs
Normal file
12
src/NadekoBot/Db/Models/AutoTranslateChannel.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NadekoBot.Services.Database.Models
|
||||
{
|
||||
public class AutoTranslateChannel : DbEntity
|
||||
{
|
||||
public ulong GuildId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
public bool AutoDelete { get; set; }
|
||||
public IList<AutoTranslateUser> Users { get; set; } = new List<AutoTranslateUser>();
|
||||
}
|
||||
}
|
11
src/NadekoBot/Db/Models/AutoTranslateUser.cs
Normal file
11
src/NadekoBot/Db/Models/AutoTranslateUser.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace NadekoBot.Services.Database.Models
|
||||
{
|
||||
public class AutoTranslateUser : DbEntity
|
||||
{
|
||||
public int ChannelId { get; set; }
|
||||
public AutoTranslateChannel Channel { get; set; }
|
||||
public ulong UserId { get; set; }
|
||||
public string Source { get; set; }
|
||||
public string Target { get; set; }
|
||||
}
|
||||
}
|
@@ -8,6 +8,6 @@
|
||||
public bool Forgiven { get; set; }
|
||||
public string ForgivenBy { get; set; }
|
||||
public string Moderator { get; set; }
|
||||
public int Weight { get; set; }
|
||||
public long Weight { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -60,6 +60,8 @@ namespace NadekoBot.Services.Database
|
||||
public DbSet<WaifuInfo> WaifuInfo { get; set; }
|
||||
public DbSet<ImageOnlyChannel> ImageOnlyChannels { get; set; }
|
||||
public DbSet<NsfwBlacklistedTag> NsfwBlacklistedTags { get; set; }
|
||||
public DbSet<AutoTranslateChannel> AutoTranslateChannels { get; set; }
|
||||
public DbSet<AutoTranslateUser> AutoTranslateUsers { get; set; }
|
||||
|
||||
public NadekoContext(DbContextOptions<NadekoContext> options) : base(options)
|
||||
{
|
||||
@@ -368,6 +370,21 @@ namespace NadekoBot.Services.Database
|
||||
modelBuilder.Entity<NsfwBlacklistedTag>(nbt => nbt
|
||||
.HasIndex(x => x.GuildId)
|
||||
.IsUnique(false));
|
||||
|
||||
var atch = modelBuilder.Entity<AutoTranslateChannel>();
|
||||
atch.HasIndex(x => x.GuildId)
|
||||
.IsUnique(false);
|
||||
|
||||
atch.HasIndex(x => x.ChannelId)
|
||||
.IsUnique();
|
||||
|
||||
atch
|
||||
.HasMany(x => x.Users)
|
||||
.WithOne(x => x.Channel)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
modelBuilder.Entity<AutoTranslateUser>(atu => atu
|
||||
.HasAlternateKey(x => new { x.ChannelId, x.UserId }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2725
src/NadekoBot/Migrations/20211213145407_atl-rework.Designer.cs
generated
Normal file
2725
src/NadekoBot/Migrations/20211213145407_atl-rework.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
71
src/NadekoBot/Migrations/20211213145407_atl-rework.cs
Normal file
71
src/NadekoBot/Migrations/20211213145407_atl-rework.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
public partial class atlrework : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AutoTranslateChannels",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
ChannelId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
AutoDelete = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AutoTranslateChannels", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AutoTranslateUsers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
ChannelId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
UserId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
Source = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Target = table.Column<string>(type: "TEXT", nullable: true),
|
||||
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AutoTranslateUsers", x => x.Id);
|
||||
table.UniqueConstraint("AK_AutoTranslateUsers_ChannelId_UserId", x => new { x.ChannelId, x.UserId });
|
||||
table.ForeignKey(
|
||||
name: "FK_AutoTranslateUsers_AutoTranslateChannels_ChannelId",
|
||||
column: x => x.ChannelId,
|
||||
principalTable: "AutoTranslateChannels",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AutoTranslateChannels_ChannelId",
|
||||
table: "AutoTranslateChannels",
|
||||
column: "ChannelId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AutoTranslateChannels_GuildId",
|
||||
table: "AutoTranslateChannels",
|
||||
column: "GuildId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AutoTranslateUsers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AutoTranslateChannels");
|
||||
}
|
||||
}
|
||||
}
|
@@ -340,6 +340,62 @@ namespace NadekoBot.Migrations
|
||||
b.ToTable("AutoCommands");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("AutoDelete")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("ChannelId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<ulong>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ChannelId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.ToTable("AutoTranslateChannels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ChannelId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Source")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Target")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<ulong>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasAlternateKey("ChannelId", "UserId");
|
||||
|
||||
b.ToTable("AutoTranslateUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -2194,6 +2250,17 @@ namespace NadekoBot.Migrations
|
||||
b.Navigation("GuildConfig");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b =>
|
||||
{
|
||||
b.HasOne("NadekoBot.Services.Database.Models.AutoTranslateChannel", "Channel")
|
||||
.WithMany("Users")
|
||||
.HasForeignKey("ChannelId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Channel");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b =>
|
||||
{
|
||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null)
|
||||
@@ -2541,6 +2608,11 @@ namespace NadekoBot.Migrations
|
||||
b.Navigation("IgnoredChannels");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b =>
|
||||
{
|
||||
b.Navigation("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
|
||||
{
|
||||
b.Navigation("AntiAltSetting");
|
||||
|
@@ -318,7 +318,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task Die()
|
||||
public async Task Die(bool graceful = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -329,7 +329,7 @@ namespace NadekoBot.Modules.Administration
|
||||
// ignored
|
||||
}
|
||||
await Task.Delay(2000).ConfigureAwait(false);
|
||||
_coord.Die();
|
||||
_coord.Die(graceful);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -506,6 +506,14 @@ namespace NadekoBot.Modules.Administration
|
||||
_strings.Reload();
|
||||
await ReplyConfirmLocalizedAsync(strs.bot_strings_reloaded).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task CoordReload()
|
||||
{
|
||||
await _coord.Reload();
|
||||
await ctx.OkAsync();
|
||||
}
|
||||
|
||||
private static UserStatus SettableUserStatusToUserStatus(SettableUserStatus sus)
|
||||
{
|
||||
|
@@ -258,8 +258,7 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
user = user ?? (IGuildUser) ctx.User;
|
||||
|
||||
var channel = await user.GetOrCreateDMChannelAsync();
|
||||
var success = await _service.GreetDmTest(channel, user);
|
||||
var success = await _service.GreetDmTest(user);
|
||||
if (success)
|
||||
await ctx.OkAsync();
|
||||
else
|
||||
|
@@ -63,27 +63,29 @@ namespace NadekoBot.Modules.Administration.Services
|
||||
Weight = weight,
|
||||
};
|
||||
|
||||
int warnings = 1;
|
||||
long previousCount;
|
||||
List<WarningPunishment> ps;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
ps = uow.GuildConfigsForId(guildId, set => set.Include(x => x.WarnPunishments))
|
||||
.WarnPunishments;
|
||||
|
||||
warnings += uow
|
||||
.Warnings
|
||||
.ForId(guildId, userId)
|
||||
.Where(w => !w.Forgiven && w.UserId == userId)
|
||||
.Sum(x => x.Weight);
|
||||
previousCount = uow.Warnings.ForId(guildId, userId)
|
||||
.Where(w => !w.Forgiven && w.UserId == userId)
|
||||
.Sum(x => x.Weight);
|
||||
|
||||
uow.Warnings.Add(warn);
|
||||
|
||||
uow.SaveChanges();
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
var p = ps.FirstOrDefault(x => x.Count == warnings);
|
||||
var totalCount = previousCount + weight;
|
||||
var p = ps.Where(x => x.Count > previousCount && x.Count <= totalCount)
|
||||
.OrderByDescending(x => x.Count)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (p != null)
|
||||
|
||||
if (p is not null)
|
||||
{
|
||||
var user = await guild.GetUserAsync(userId).ConfigureAwait(false);
|
||||
if (user is null)
|
||||
@@ -99,6 +101,10 @@ namespace NadekoBot.Modules.Administration.Services
|
||||
public async Task ApplyPunishment(IGuild guild, IGuildUser user, IUser mod, PunishmentAction p, int minutes,
|
||||
ulong? roleId, string reason)
|
||||
{
|
||||
|
||||
if (!await CheckPermission(guild, p))
|
||||
return;
|
||||
|
||||
switch (p)
|
||||
{
|
||||
case PunishmentAction.Mute:
|
||||
@@ -171,6 +177,40 @@ namespace NadekoBot.Modules.Administration.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to prevent the bot from hitting 403's when it needs to
|
||||
/// apply punishments with insufficient permissions
|
||||
/// </summary>
|
||||
/// <param name="guild">Guild the punishment is applied in</param>
|
||||
/// <param name="punish">Punishment to apply</param>
|
||||
/// <returns>Whether the bot has sufficient permissions</returns>
|
||||
private async Task<bool> CheckPermission(IGuild guild, PunishmentAction punish)
|
||||
{
|
||||
|
||||
var botUser = await guild.GetCurrentUserAsync();
|
||||
switch (punish)
|
||||
{
|
||||
case PunishmentAction.Mute:
|
||||
return botUser.GuildPermissions.MuteMembers && botUser.GuildPermissions.ManageRoles;
|
||||
case PunishmentAction.Kick:
|
||||
return botUser.GuildPermissions.KickMembers;
|
||||
case PunishmentAction.Ban:
|
||||
return botUser.GuildPermissions.BanMembers;
|
||||
case PunishmentAction.Softban:
|
||||
return botUser.GuildPermissions.BanMembers; // ban + unban
|
||||
case PunishmentAction.RemoveRoles:
|
||||
return botUser.GuildPermissions.ManageRoles;
|
||||
case PunishmentAction.ChatMute:
|
||||
return botUser.GuildPermissions.ManageRoles; // adds nadeko-mute role
|
||||
case PunishmentAction.VoiceMute:
|
||||
return botUser.GuildPermissions.MuteMembers;
|
||||
case PunishmentAction.AddRole:
|
||||
return botUser.GuildPermissions.ManageRoles;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CheckAllWarnExpiresAsync()
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
@@ -461,7 +501,9 @@ WHERE GuildId={guildId}
|
||||
{
|
||||
template = JsonConvert.SerializeObject(new
|
||||
{
|
||||
color = _bcs.Data.Color.Error,
|
||||
//To get the decimal version of the color that's expected, take the packed value of the Rgba32
|
||||
//and bitshift it to the right by 8 bits, thereby dropping the "a" and getting a reprensentation of the RGB value
|
||||
color = _bcs.Data.Color.Error.PackedValue >> 8,
|
||||
description = defaultMessage
|
||||
});
|
||||
}
|
||||
@@ -476,7 +518,9 @@ WHERE GuildId={guildId}
|
||||
{
|
||||
template = JsonConvert.SerializeObject(new
|
||||
{
|
||||
color = _bcs.Data.Color.Error,
|
||||
//To get the decimal version of the color that's expected, take the packed value of the Rgba32
|
||||
//and bitshift it to the right by 8 bits, thereby dropping the "a" and getting a reprensentation of the RGB value
|
||||
color = _bcs.Data.Color.Error.PackedValue >> 8,
|
||||
description = template
|
||||
});
|
||||
}
|
||||
|
@@ -310,7 +310,7 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
_ = ctx.Channel.TriggerTypingAsync();
|
||||
|
||||
var serialized = _service.ExportCrs(ctx.Guild?.Id);
|
||||
using var stream = await serialized.ToStream();
|
||||
await using var stream = await serialized.ToStream();
|
||||
await ctx.Channel.SendFileAsync(stream, "crs-export.yml", text: null);
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using Cloneable;
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Common.Yml;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace NadekoBot.Modules.Gambling.Common
|
||||
@@ -20,6 +21,7 @@ namespace NadekoBot.Modules.Gambling.Common
|
||||
Generation = new GenerationConfig();
|
||||
Timely = new TimelyConfig();
|
||||
Decay = new DecayConfig();
|
||||
Slots = new SlotsConfig();
|
||||
}
|
||||
|
||||
[Comment(@"DO NOT CHANGE")]
|
||||
@@ -64,6 +66,9 @@ Set 0 for unlimited")]
|
||||
[Comment(@"Currency reward per vote.
|
||||
This will work only if you've set up VotesApi and correct credentials for topgg and/or discords voting")]
|
||||
public long VoteReward { get; set; } = 100;
|
||||
|
||||
[Comment(@"Slot config")]
|
||||
public SlotsConfig Slots { get; set; }
|
||||
}
|
||||
|
||||
public class CurrencyConfig
|
||||
@@ -273,6 +278,12 @@ Example: If a waifu is worth 1000, and she receives a negative gift worth 100, h
|
||||
public decimal NegativeGiftEffect { get; set; } = 0.50M;
|
||||
}
|
||||
|
||||
public sealed partial class SlotsConfig
|
||||
{
|
||||
[Comment(@"Hex value of the color which the numbers on the slot image will have.")]
|
||||
public Rgba32 CurrencyFontColor { get; set; } = SixLabors.ImageSharp.Color.Red;
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
public sealed partial class WaifuItemModel
|
||||
{
|
||||
|
@@ -265,7 +265,15 @@ namespace NadekoBot.Modules.Gambling
|
||||
if (amount <= 0)
|
||||
return;
|
||||
|
||||
await _cs.AddAsync(usrId,
|
||||
var usr = await ((DiscordSocketClient)Context.Client).Rest.GetUserAsync(usrId);
|
||||
|
||||
if(usr is null)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.user_not_found).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await _cs.AddAsync(usr,
|
||||
$"Awarded by bot owner. ({ctx.User.Username}/{ctx.User.Id}) {(msg ?? "")}",
|
||||
amount,
|
||||
gamble: (ctx.Client.CurrentUser.Id != usrId)).ConfigureAwait(false);
|
||||
@@ -275,7 +283,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[OwnerOnly]
|
||||
[Priority(2)]
|
||||
[Priority(3)]
|
||||
public async Task Award(long amount, [Leftover] IRole role)
|
||||
{
|
||||
var users = (await ctx.Guild.GetUsersAsync().ConfigureAwait(false))
|
||||
|
@@ -68,9 +68,18 @@ namespace NadekoBot.Modules.Gambling.Services
|
||||
{
|
||||
ModifyConfig(c =>
|
||||
{
|
||||
c.Version = 3;
|
||||
c.VoteReward = 100;
|
||||
});
|
||||
}
|
||||
|
||||
if (_data.Version < 4)
|
||||
{
|
||||
ModifyConfig(c =>
|
||||
{
|
||||
c.Version = 4;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,6 +19,7 @@ using SixLabors.ImageSharp.Processing;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Drawing.Processing;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using Color = SixLabors.ImageSharp.Color;
|
||||
|
||||
namespace NadekoBot.Modules.Gambling
|
||||
{
|
||||
@@ -186,6 +187,8 @@ namespace NadekoBot.Modules.Gambling
|
||||
var numbers = new int[3];
|
||||
result.Rolls.CopyTo(numbers, 0);
|
||||
|
||||
Color fontColor = _config.Slots.CurrencyFontColor;
|
||||
|
||||
bgImage.Mutate(x => x.DrawText(new TextGraphicsOptions
|
||||
{
|
||||
TextOptions = new TextOptions()
|
||||
@@ -194,9 +197,11 @@ namespace NadekoBot.Modules.Gambling
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
WrapTextWidth = 140,
|
||||
}
|
||||
}, result.Won.ToString(), _fonts.DottyFont.CreateFont(65), SixLabors.ImageSharp.Color.Red,
|
||||
}, result.Won.ToString(), _fonts.DottyFont.CreateFont(65), fontColor,
|
||||
new PointF(227, 92)));
|
||||
|
||||
var bottomFont = _fonts.DottyFont.CreateFont(50);
|
||||
|
||||
bgImage.Mutate(x => x.DrawText(new TextGraphicsOptions
|
||||
{
|
||||
TextOptions = new TextOptions()
|
||||
@@ -205,7 +210,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
WrapTextWidth = 135,
|
||||
}
|
||||
}, amount.ToString(), _fonts.DottyFont.CreateFont(50), SixLabors.ImageSharp.Color.Red,
|
||||
}, amount.ToString(), bottomFont, fontColor,
|
||||
new PointF(129, 472)));
|
||||
|
||||
bgImage.Mutate(x => x.DrawText(new TextGraphicsOptions
|
||||
@@ -216,7 +221,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
WrapTextWidth = 135,
|
||||
}
|
||||
}, ownedAmount.ToString(), _fonts.DottyFont.CreateFont(50), SixLabors.ImageSharp.Color.Red,
|
||||
}, ownedAmount.ToString(), bottomFont, fontColor,
|
||||
new PointF(325, 472)));
|
||||
//sw.PrintLap("drew red text");
|
||||
|
||||
|
@@ -104,7 +104,8 @@ namespace NadekoBot.Modules.Games.Hangman
|
||||
CurrentPhase = Phase.Ended;
|
||||
return GetState(GuessResult.Win);
|
||||
}
|
||||
|
||||
|
||||
_correct.Add(charGuess);
|
||||
return GetState(GuessResult.Guess);
|
||||
}
|
||||
|
||||
|
@@ -763,7 +763,7 @@ namespace NadekoBot.Modules.Music
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task MusicQuality()
|
||||
{
|
||||
var quality = await _service.GetMusicQualityAsync(ctx.Guild.Id);
|
||||
@@ -772,7 +772,7 @@ namespace NadekoBot.Modules.Music
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task MusicQuality(QualityPreset preset)
|
||||
{
|
||||
await _service.SetMusicQualityAsync(ctx.Guild.Id, preset);
|
||||
|
@@ -195,7 +195,7 @@ namespace NadekoBot.Modules.Music.Services
|
||||
public Task<IUserMessage?> SendToOutputAsync(ulong guildId, IEmbedBuilder embed)
|
||||
{
|
||||
if (_outputChannels.TryGetValue(guildId, out var chan))
|
||||
return (chan.Default ?? chan.Override).EmbedAsync(embed);
|
||||
return (chan.Override ?? chan.Default).EmbedAsync(embed);
|
||||
|
||||
return Task.FromResult<IUserMessage?>(null);
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -13,10 +14,11 @@ namespace NadekoBot.Modules.Nsfw.Common
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<List<DapiImageObject>> DownloadImagesAsync(string[] tags, int page, bool isExplicit = false, CancellationToken cancel = default)
|
||||
public override async Task<List<DapiImageObject>> DownloadImagesAsync(string[] tags, int page,
|
||||
bool isExplicit = false, CancellationToken cancel = default)
|
||||
{
|
||||
var tagString = ImageDownloaderHelper.GetTagString(tags, isExplicit);
|
||||
var uri = $"http://gelbooru.com/index.php?page=dapi&s=post&json=1&q=index&limit=100" +
|
||||
var uri = $"https://gelbooru.com/index.php?page=dapi&s=post&json=1&q=index&limit=100" +
|
||||
$"&tags={tagString}&pid={page}";
|
||||
using var req = new HttpRequestMessage(HttpMethod.Get, uri);
|
||||
using var res = await _http.SendAsync(req, cancel).ConfigureAwait(false);
|
||||
@@ -24,12 +26,18 @@ namespace NadekoBot.Modules.Nsfw.Common
|
||||
var resString = await res.Content.ReadAsStringAsync(cancel);
|
||||
if (string.IsNullOrWhiteSpace(resString))
|
||||
return new();
|
||||
|
||||
var images = JsonSerializer.Deserialize<List<DapiImageObject>>(resString, _serializerOptions);
|
||||
if (images is null)
|
||||
|
||||
var images = JsonSerializer.Deserialize<GelbooruResponse>(resString, _serializerOptions);
|
||||
if (images is null or { Post: null })
|
||||
return new();
|
||||
|
||||
return images.Where(x => x.FileUrl is not null).ToList();
|
||||
return images.Post.Where(x => x.FileUrl is not null).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public class GelbooruResponse
|
||||
{
|
||||
[JsonPropertyName("post")]
|
||||
public List<DapiImageObject> Post { get; set; }
|
||||
}
|
||||
}
|
@@ -24,7 +24,7 @@ namespace NadekoBot.Modules.Nsfw.Common
|
||||
return new();
|
||||
|
||||
return images
|
||||
.Where(img => !string.IsNullOrWhiteSpace(img.Directory) && !string.IsNullOrWhiteSpace(img.Image))
|
||||
.Where(img => !string.IsNullOrWhiteSpace(img.Image))
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
public class Rule34Object : IImageData
|
||||
{
|
||||
public string Image { get; init; }
|
||||
public string Directory { get; init; }
|
||||
public int Directory { get; init; }
|
||||
public string Tags { get; init; }
|
||||
public int Score { get; init; }
|
||||
|
||||
|
@@ -0,0 +1,12 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace SystemTextJsonSamples
|
||||
{
|
||||
public class LowerCaseNamingPolicy : JsonNamingPolicy
|
||||
{
|
||||
public static LowerCaseNamingPolicy Default = new LowerCaseNamingPolicy();
|
||||
|
||||
public override string ConvertName(string name) =>
|
||||
name.ToLower();
|
||||
}
|
||||
}
|
@@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Searches
|
||||
|
||||
var (crypto, nearest) = await _service.GetCryptoData(name).ConfigureAwait(false);
|
||||
|
||||
if (nearest != null)
|
||||
if (nearest is not null)
|
||||
{
|
||||
var embed = _eb.Create()
|
||||
.WithTitle(GetText(strs.crypto_not_found))
|
||||
|
16
src/NadekoBot/Modules/Searches/Services/AtlExtensions.cs
Normal file
16
src/NadekoBot/Modules/Searches/Services/AtlExtensions.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Modules.Searches
|
||||
{
|
||||
public static class AtlExtensions
|
||||
{
|
||||
public static Task<AutoTranslateChannel> GetByChannelId(this IQueryable<AutoTranslateChannel> set, ulong channelId)
|
||||
=> set
|
||||
.Include(x => x.Users)
|
||||
.FirstOrDefaultAsyncEF(x => x.ChannelId == channelId);
|
||||
}
|
||||
}
|
@@ -35,6 +35,9 @@ namespace NadekoBot.Modules.Searches.Services
|
||||
name = name.ToUpperInvariant();
|
||||
var cryptos = await CryptoData().ConfigureAwait(false);
|
||||
|
||||
if (cryptos is null)
|
||||
return (null, null);
|
||||
|
||||
var crypto = cryptos
|
||||
?.FirstOrDefault(x => x.Id.ToUpperInvariant() == name || x.Name.ToUpperInvariant() == name
|
||||
|| x.Symbol.ToUpperInvariant() == name);
|
||||
@@ -42,7 +45,8 @@ namespace NadekoBot.Modules.Searches.Services
|
||||
(CryptoResponseData Elem, int Distance)? nearest = null;
|
||||
if (crypto is null)
|
||||
{
|
||||
nearest = cryptos.Select(x => (x, Distance: x.Name.ToUpperInvariant().LevenshteinDistance(name)))
|
||||
nearest = cryptos
|
||||
.Select(x => (x, Distance: x.Name.ToUpperInvariant().LevenshteinDistance(name)))
|
||||
.OrderBy(x => x.Distance)
|
||||
.Where(x => x.Distance <= 2)
|
||||
.FirstOrDefault();
|
||||
@@ -68,18 +72,17 @@ namespace NadekoBot.Modules.Searches.Services
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var _http = _httpFactory.CreateClient())
|
||||
{
|
||||
var strData = await _http.GetStringAsync(new Uri($"https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?" +
|
||||
$"CMC_PRO_API_KEY={_creds.CoinmarketcapApiKey}" +
|
||||
$"&start=1" +
|
||||
$"&limit=500" +
|
||||
$"&convert=USD"));
|
||||
using var _http = _httpFactory.CreateClient();
|
||||
var strData = await _http.GetStringAsync(
|
||||
$"https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest?" +
|
||||
$"CMC_PRO_API_KEY={_creds.CoinmarketcapApiKey}" +
|
||||
$"&start=1" +
|
||||
$"&limit=5000" +
|
||||
$"&convert=USD");
|
||||
|
||||
JsonConvert.DeserializeObject<CryptoResponse>(strData); // just to see if its' valid
|
||||
JsonConvert.DeserializeObject<CryptoResponse>(strData); // just to see if its' valid
|
||||
|
||||
return strData;
|
||||
}
|
||||
return strData;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -87,7 +90,7 @@ namespace NadekoBot.Modules.Searches.Services
|
||||
return default;
|
||||
}
|
||||
|
||||
}, "", TimeSpan.FromHours(1));
|
||||
}, "", TimeSpan.FromHours(2));
|
||||
|
||||
return JsonConvert.DeserializeObject<CryptoResponse>(fullStrData).Data;
|
||||
}
|
||||
|
14
src/NadekoBot/Modules/Searches/Services/ITranslateService.cs
Normal file
14
src/NadekoBot/Modules/Searches/Services/ITranslateService.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Searches
|
||||
{
|
||||
public interface ITranslateService
|
||||
{
|
||||
public Task<string> Translate(string source, string target, string text = null);
|
||||
Task<bool> ToggleAtl(ulong guildId, ulong channelId, bool autoDelete);
|
||||
IEnumerable<string> GetLanguages();
|
||||
Task<bool?> RegisterUserAsync(ulong userId, ulong channelId, string @from, string to);
|
||||
Task<bool> UnregisterUser(ulong channelId, ulong userId);
|
||||
}
|
||||
}
|
@@ -1,10 +1,6 @@
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Modules.Searches.Common;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NadekoBot.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
@@ -13,18 +9,14 @@ using SixLabors.ImageSharp.Drawing.Processing;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Html.Dom;
|
||||
using AngleSharp.Html.Parser;
|
||||
using NadekoBot.Db;
|
||||
using NadekoBot.Modules.Administration;
|
||||
using Serilog;
|
||||
using HorizontalAlignment = SixLabors.Fonts.HorizontalAlignment;
|
||||
using Image = SixLabors.ImageSharp.Image;
|
||||
@@ -34,71 +26,31 @@ namespace NadekoBot.Modules.Searches.Services
|
||||
public class SearchesService : INService
|
||||
{
|
||||
private readonly IHttpClientFactory _httpFactory;
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly IGoogleApiService _google;
|
||||
private readonly DbService _db;
|
||||
private readonly IImageCache _imgs;
|
||||
private readonly IDataCache _cache;
|
||||
private readonly FontProvider _fonts;
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly IEmbedBuilderService _eb;
|
||||
private readonly NadekoRandom _rng;
|
||||
|
||||
public ConcurrentDictionary<ulong, bool> TranslatedChannels { get; } = new ConcurrentDictionary<ulong, bool>();
|
||||
// (userId, channelId)
|
||||
public ConcurrentDictionary<(ulong UserId, ulong ChannelId), string> UserLanguages { get; } = new ConcurrentDictionary<(ulong, ulong), string>();
|
||||
|
||||
public List<WoWJoke> WowJokes { get; } = new List<WoWJoke>();
|
||||
public List<MagicItem> MagicItems { get; } = new List<MagicItem>();
|
||||
private readonly List<string> _yomamaJokes;
|
||||
|
||||
public SearchesService(DiscordSocketClient client, IGoogleApiService google,
|
||||
DbService db, Bot bot, IDataCache cache, IHttpClientFactory factory,
|
||||
FontProvider fonts, IBotCredentials creds, IEmbedBuilderService eb)
|
||||
public SearchesService(IGoogleApiService google,
|
||||
IDataCache cache,
|
||||
IHttpClientFactory factory,
|
||||
FontProvider fonts,
|
||||
IBotCredentials creds)
|
||||
{
|
||||
_httpFactory = factory;
|
||||
_client = client;
|
||||
_google = google;
|
||||
_db = db;
|
||||
_imgs = cache.LocalImages;
|
||||
_cache = cache;
|
||||
_fonts = fonts;
|
||||
_creds = creds;
|
||||
_eb = eb;
|
||||
_rng = new NadekoRandom();
|
||||
|
||||
//translate commands
|
||||
_client.MessageReceived += (msg) =>
|
||||
{
|
||||
var _ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!(msg is SocketUserMessage umsg))
|
||||
return;
|
||||
|
||||
if (!TranslatedChannels.TryGetValue(umsg.Channel.Id, out var autoDelete))
|
||||
return;
|
||||
|
||||
var key = (umsg.Author.Id, umsg.Channel.Id);
|
||||
|
||||
if (!UserLanguages.TryGetValue(key, out string langs))
|
||||
return;
|
||||
|
||||
var text = await Translate(langs, umsg.Resolve(TagHandling.Ignore))
|
||||
.ConfigureAwait(false);
|
||||
if (autoDelete)
|
||||
try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { }
|
||||
|
||||
await umsg.Channel.SendConfirmAsync(_eb, $"{umsg.Author.Mention} `:` "
|
||||
+ text.Replace("<@ ", "<@", StringComparison.InvariantCulture)
|
||||
.Replace("<@! ", "<@!", StringComparison.InvariantCulture)).ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
//joke commands
|
||||
if (File.Exists("data/wowjokes.json"))
|
||||
{
|
||||
@@ -340,19 +292,6 @@ namespace NadekoBot.Modules.Searches.Services
|
||||
_rng.Next(1, max).ToString("000") + ".png";
|
||||
}
|
||||
|
||||
public async Task<string> Translate(string langs, string text = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
throw new ArgumentException("Text is empty or null", nameof(text));
|
||||
var langarr = langs.ToLowerInvariant().Split('>');
|
||||
if (langarr.Length != 2)
|
||||
throw new ArgumentException("Langs does not have 2 parts separated by a >", nameof(langs));
|
||||
var from = langarr[0];
|
||||
var to = langarr[1];
|
||||
text = text?.Trim();
|
||||
return (await _google.Translate(text, from, to).ConfigureAwait(false)).SanitizeMentions(true);
|
||||
}
|
||||
|
||||
private readonly object yomamaLock = new object();
|
||||
private int yomamaJokeIndex = 0;
|
||||
public Task<string> GetYomamaJoke()
|
||||
|
235
src/NadekoBot/Modules/Searches/Services/TranslateService.cs
Normal file
235
src/NadekoBot/Modules/Searches/Services/TranslateService.cs
Normal file
@@ -0,0 +1,235 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Net;
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Services;
|
||||
|
||||
namespace NadekoBot.Modules.Searches
|
||||
{
|
||||
public sealed class TranslateService : ITranslateService, ILateExecutor, IReadyExecutor, INService
|
||||
{
|
||||
private readonly IGoogleApiService _google;
|
||||
private readonly DbService _db;
|
||||
private readonly IEmbedBuilderService _eb;
|
||||
private readonly Bot _bot;
|
||||
|
||||
private readonly ConcurrentDictionary<ulong, bool> _atcs = new();
|
||||
private readonly ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, (string From, string To)>> _users = new();
|
||||
|
||||
public TranslateService(IGoogleApiService google,
|
||||
DbService db,
|
||||
IEmbedBuilderService eb,
|
||||
Bot bot)
|
||||
{
|
||||
_google = google;
|
||||
_db = db;
|
||||
_eb = eb;
|
||||
_bot = bot;
|
||||
}
|
||||
|
||||
public async Task OnReadyAsync()
|
||||
{
|
||||
var ctx = _db.GetDbContext();
|
||||
|
||||
var guilds = _bot.AllGuildConfigs.Select(x => x.GuildId).ToList();
|
||||
var cs = await ctx.AutoTranslateChannels
|
||||
.Include(x => x.Users)
|
||||
.Where(x => guilds.Contains(x.GuildId))
|
||||
.ToListAsyncEF();
|
||||
|
||||
foreach (var c in cs)
|
||||
{
|
||||
_atcs[c.ChannelId] = c.AutoDelete;
|
||||
_users[c.ChannelId] = new(c.Users.ToDictionary(x => x.UserId, x => (x.Source.ToLower(), x.Target.ToLower())));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task LateExecute(IGuild guild, IUserMessage msg)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(msg.Content))
|
||||
return;
|
||||
|
||||
if (msg is IUserMessage { Channel: ITextChannel tch } um)
|
||||
{
|
||||
if (!_atcs.TryGetValue(tch.Id, out var autoDelete))
|
||||
return;
|
||||
|
||||
if (!_users.TryGetValue(tch.Id, out var users)
|
||||
|| !users.TryGetValue(um.Author.Id, out var langs))
|
||||
return;
|
||||
|
||||
var output = await _google.Translate(msg.Content, langs.From, langs.To);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(output)
|
||||
|| msg.Content.Equals(output, StringComparison.InvariantCultureIgnoreCase))
|
||||
return;
|
||||
|
||||
var embed = _eb.Create()
|
||||
.WithOkColor();
|
||||
|
||||
if (autoDelete)
|
||||
{
|
||||
embed
|
||||
.WithAuthor(um.Author.ToString(), um.Author.GetAvatarUrl())
|
||||
.AddField(langs.From, um.Content)
|
||||
.AddField(langs.To, output);
|
||||
|
||||
await tch.EmbedAsync(embed);
|
||||
|
||||
try
|
||||
{
|
||||
await um.DeleteAsync();
|
||||
}
|
||||
catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.Forbidden)
|
||||
{
|
||||
_atcs.TryUpdate(tch.Id, false, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await um.ReplyAsync(embed: embed
|
||||
.AddField(langs.To, output)
|
||||
.Build(),
|
||||
allowedMentions: AllowedMentions.None);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> Translate(string source, string target, string text = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
throw new ArgumentException("Text is empty or null", nameof(text));
|
||||
|
||||
var res = await _google.Translate(text, source, target).ConfigureAwait(false);
|
||||
return res.SanitizeMentions(true);
|
||||
}
|
||||
|
||||
public async Task<bool> ToggleAtl(ulong guildId, ulong channelId, bool autoDelete)
|
||||
{
|
||||
var ctx = _db.GetDbContext();
|
||||
|
||||
var old = await ctx.AutoTranslateChannels
|
||||
.ToLinqToDBTable()
|
||||
.FirstOrDefaultAsyncLinqToDB(x => x.ChannelId == channelId);
|
||||
|
||||
if (old is null)
|
||||
{
|
||||
ctx.AutoTranslateChannels
|
||||
.Add(new()
|
||||
{
|
||||
GuildId = guildId,
|
||||
ChannelId = channelId,
|
||||
AutoDelete = autoDelete,
|
||||
});
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
_atcs[channelId] = autoDelete;
|
||||
_users[channelId] = new();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// if autodelete value is different, update the autodelete value
|
||||
// instead of disabling
|
||||
if (old.AutoDelete != autoDelete)
|
||||
{
|
||||
old.AutoDelete = autoDelete;
|
||||
await ctx.SaveChangesAsync();
|
||||
_atcs[channelId] = autoDelete;
|
||||
return true;
|
||||
}
|
||||
|
||||
await ctx.AutoTranslateChannels
|
||||
.ToLinqToDBTable()
|
||||
.DeleteAsync(x => x.ChannelId == channelId);
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
_atcs.TryRemove(channelId, out _);
|
||||
_users.TryRemove(channelId, out _);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private void UpdateUser(ulong channelId, ulong userId, string from, string to)
|
||||
{
|
||||
var dict = _users.GetOrAdd(channelId, new ConcurrentDictionary<ulong, (string, string)>());
|
||||
dict[userId] = (from, to);
|
||||
}
|
||||
|
||||
public async Task<bool?> RegisterUserAsync(ulong userId, ulong channelId, string from, string to)
|
||||
{
|
||||
if (!_google.Languages.ContainsKey(from) || !_google.Languages.ContainsKey(to))
|
||||
return null;
|
||||
|
||||
var ctx = _db.GetDbContext();
|
||||
var ch = await ctx.AutoTranslateChannels
|
||||
.GetByChannelId(channelId);
|
||||
|
||||
if (ch is null)
|
||||
return null;
|
||||
|
||||
var user = ch.Users
|
||||
.FirstOrDefault(x => x.UserId == userId);
|
||||
|
||||
if (user is null)
|
||||
{
|
||||
ch.Users.Add(user = new()
|
||||
{
|
||||
Source = from,
|
||||
Target = to,
|
||||
UserId = userId,
|
||||
});
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
UpdateUser(channelId, userId, from, to);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// if it's different from old settings, update
|
||||
if (user.Source != from || user.Target != to)
|
||||
{
|
||||
user.Source = from;
|
||||
user.Target = to;
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
UpdateUser(channelId, userId, from, to);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return await UnregisterUser(channelId, userId);
|
||||
}
|
||||
|
||||
public async Task<bool> UnregisterUser(ulong channelId, ulong userId)
|
||||
{
|
||||
var ctx = _db.GetDbContext();
|
||||
var rows = await ctx.AutoTranslateUsers
|
||||
.ToLinqToDBTable()
|
||||
.DeleteAsync(x => x.UserId == userId &&
|
||||
x.Channel.ChannelId == channelId);
|
||||
|
||||
if (_users.TryGetValue(channelId, out var inner))
|
||||
inner.TryRemove(userId, out _);
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
return rows > 0;
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetLanguages() => _google.Languages.Select(x => x.Key);
|
||||
}
|
||||
}
|
@@ -2,35 +2,29 @@
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Extensions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using NadekoBot.Common.Attributes;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Modules.Searches.Services;
|
||||
|
||||
namespace NadekoBot.Modules.Searches
|
||||
{
|
||||
public partial class Searches
|
||||
{
|
||||
[Group]
|
||||
public class TranslateCommands : NadekoSubmodule
|
||||
public class TranslateCommands : NadekoSubmodule<ITranslateService>
|
||||
{
|
||||
private readonly SearchesService _searches;
|
||||
private readonly IGoogleApiService _google;
|
||||
|
||||
public TranslateCommands(SearchesService searches, IGoogleApiService google)
|
||||
{
|
||||
_searches = searches;
|
||||
_google = google;
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
public async Task Translate(string langs, [Leftover] string text = null)
|
||||
public async Task Translate(string from, string to, [Leftover] string text)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ctx.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||
var translation = await _searches.Translate(langs, text).ConfigureAwait(false);
|
||||
await SendConfirmAsync(GetText(strs.translation) + " " + langs, translation).ConfigureAwait(false);
|
||||
var translation = await _service.Translate(from.ToLower(), to.ToLower(), text).ConfigureAwait(false);
|
||||
|
||||
var embed = _eb.Create(ctx)
|
||||
.WithOkColor()
|
||||
.AddField(from, text, false)
|
||||
.AddField(to, translation, false);
|
||||
|
||||
await ctx.Channel.EmbedAsync(embed);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -38,27 +32,6 @@ namespace NadekoBot.Modules.Searches
|
||||
}
|
||||
}
|
||||
|
||||
//[NadekoCommand, Usage, Description, Aliases]
|
||||
//[OwnerOnly]
|
||||
//public async Task Obfuscate([Leftover] string txt)
|
||||
//{
|
||||
// var lastItem = "en";
|
||||
// foreach (var item in _google.Languages.Except(new[] { "en" }).Where(x => x.Length < 4))
|
||||
// {
|
||||
// var txt2 = await _searches.Translate(lastItem + ">" + item, txt);
|
||||
// await ctx.Channel.EmbedAsync(_eb.Create()
|
||||
// .WithOkColor()
|
||||
// .WithTitle(lastItem + ">" + item)
|
||||
// .AddField("Input", txt)
|
||||
// .AddField("Output", txt2));
|
||||
// txt = txt2;
|
||||
// await Task.Delay(500);
|
||||
// lastItem = item;
|
||||
// }
|
||||
// txt = await _searches.Translate(lastItem + ">en", txt);
|
||||
// await SendConfirmAsync("Final output:\n\n" + txt);
|
||||
//}
|
||||
|
||||
public enum AutoDeleteAutoTranslate
|
||||
{
|
||||
Del,
|
||||
@@ -68,56 +41,52 @@ namespace NadekoBot.Modules.Searches
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
[BotPerm(ChannelPerm.ManageMessages)]
|
||||
[OwnerOnly]
|
||||
public async Task AutoTranslate(AutoDeleteAutoTranslate autoDelete = AutoDeleteAutoTranslate.Nodel)
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
if (autoDelete == AutoDeleteAutoTranslate.Del)
|
||||
{
|
||||
_searches.TranslatedChannels.AddOrUpdate(channel.Id, true, (key, val) => true);
|
||||
await ReplyConfirmLocalizedAsync(strs.atl_ad_started).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_searches.TranslatedChannels.TryRemove(channel.Id, out _))
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(strs.atl_stopped).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
if (_searches.TranslatedChannels.TryAdd(channel.Id, autoDelete == AutoDeleteAutoTranslate.Del))
|
||||
var toggle = await _service.ToggleAtl(ctx.Guild.Id, ctx.Channel.Id, autoDelete == AutoDeleteAutoTranslate.Del);
|
||||
if (toggle)
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(strs.atl_started).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(strs.atl_stopped).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task AutoTransLang([Leftover] string langs = null)
|
||||
public async Task AutoTransLang()
|
||||
{
|
||||
var ucp = (ctx.User.Id, ctx.Channel.Id);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(langs))
|
||||
if (await _service.UnregisterUser(ctx.Channel.Id, ctx.User.Id))
|
||||
{
|
||||
if (_searches.UserLanguages.TryRemove(ucp, out langs))
|
||||
await ReplyConfirmLocalizedAsync(strs.atl_removed).ConfigureAwait(false);
|
||||
await ReplyConfirmLocalizedAsync(strs.atl_removed).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task AutoTransLang(string from, string to)
|
||||
{
|
||||
var succ = await _service.RegisterUserAsync(ctx.User.Id,
|
||||
ctx.Channel.Id,
|
||||
from.ToLower(),
|
||||
to.ToLower());
|
||||
|
||||
if (succ is null)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.atl_not_enabled);
|
||||
return;
|
||||
}
|
||||
|
||||
var langarr = langs.ToLowerInvariant().Split('>');
|
||||
if (langarr.Length != 2)
|
||||
return;
|
||||
var from = langarr[0];
|
||||
var to = langarr[1];
|
||||
|
||||
if (!_google.Languages.Contains(from) || !_google.Languages.Contains(to))
|
||||
|
||||
if (succ is false)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.invalid_lang).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_searches.UserLanguages.AddOrUpdate(ucp, langs, (key, val) => langs);
|
||||
|
||||
await ReplyConfirmLocalizedAsync(strs.atl_set(from, to));
|
||||
}
|
||||
|
||||
@@ -125,7 +94,7 @@ namespace NadekoBot.Modules.Searches
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Translangs()
|
||||
{
|
||||
await ctx.Channel.SendTableAsync(_google.Languages, str => $"{str,-15}", 3).ConfigureAwait(false);
|
||||
await ctx.Channel.SendTableAsync(_service.GetLanguages(), str => $"{str,-15}", 3).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -32,35 +32,40 @@ namespace NadekoBot.Modules.Utility
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
guildName = guildName?.ToUpperInvariant();
|
||||
SocketGuild guild;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(guildName))
|
||||
guild = (SocketGuild)channel.Guild;
|
||||
else
|
||||
guild = _client.Guilds.FirstOrDefault(g => g.Name.ToUpperInvariant() == guildName.ToUpperInvariant());
|
||||
|
||||
if (guild is null)
|
||||
return;
|
||||
|
||||
var ownername = guild.GetUser(guild.OwnerId);
|
||||
var textchn = guild.TextChannels.Count();
|
||||
var voicechn = guild.VoiceChannels.Count();
|
||||
|
||||
var textchn = guild.TextChannels.Count;
|
||||
var voicechn = guild.VoiceChannels.Count;
|
||||
var channels = $@"{GetText(strs.text_channels(textchn))}
|
||||
{GetText(strs.voice_channels(voicechn))}";
|
||||
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(guild.Id >> 22);
|
||||
var features = string.Join("\n", guild.Features);
|
||||
var features = string.Join(", ", guild.Features);
|
||||
if (string.IsNullOrWhiteSpace(features))
|
||||
features = "-";
|
||||
|
||||
var embed = _eb.Create()
|
||||
.WithAuthor(GetText(strs.server_info))
|
||||
.WithTitle(guild.Name)
|
||||
.AddField(GetText(strs.id), guild.Id.ToString(), true)
|
||||
.AddField(GetText(strs.owner), ownername.ToString(), true)
|
||||
.AddField(GetText(strs.members), guild.MemberCount.ToString(), true)
|
||||
.AddField(GetText(strs.text_channels), textchn.ToString(), true)
|
||||
.AddField(GetText(strs.voice_channels), voicechn.ToString(), true)
|
||||
.AddField(GetText(strs.channels), channels, true)
|
||||
.AddField(GetText(strs.created_at), $"{createdAt:dd.MM.yyyy HH:mm}", true)
|
||||
.AddField(GetText(strs.region), guild.VoiceRegionId.ToString(), true)
|
||||
.AddField(GetText(strs.roles), (guild.Roles.Count - 1).ToString(), true)
|
||||
.AddField(GetText(strs.features), features, true)
|
||||
.AddField(GetText(strs.features), features)
|
||||
.WithOkColor();
|
||||
|
||||
if (Uri.IsWellFormedUriString(guild.IconUrl, UriKind.Absolute))
|
||||
embed.WithThumbnailUrl(guild.IconUrl);
|
||||
|
||||
if (guild.Emotes.Any())
|
||||
{
|
||||
embed.AddField(GetText(strs.custom_emojis) + $"({guild.Emotes.Count})",
|
||||
|
@@ -7,10 +7,13 @@ using NadekoBot.Db.Models;
|
||||
using NadekoBot.Extensions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Common.Yml;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NadekoBot.Db;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace NadekoBot.Modules.Utility
|
||||
{
|
||||
@@ -20,10 +23,12 @@ namespace NadekoBot.Modules.Utility
|
||||
public class QuoteCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbService _db;
|
||||
private readonly IHttpClientFactory _http;
|
||||
|
||||
public QuoteCommands(DbService db)
|
||||
public QuoteCommands(DbService db, IHttpClientFactory http)
|
||||
{
|
||||
_db = db;
|
||||
_http = http;
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -203,7 +208,7 @@ namespace NadekoBot.Modules.Utility
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task QuoteDelete(int id)
|
||||
{
|
||||
var isAdmin = ((IGuildUser)ctx.Message.Author).GuildPermissions.ManageMessages;
|
||||
var hasManageMessages = ((IGuildUser)ctx.Message.Author).GuildPermissions.ManageMessages;
|
||||
|
||||
var success = false;
|
||||
string response;
|
||||
@@ -211,7 +216,7 @@ namespace NadekoBot.Modules.Utility
|
||||
{
|
||||
var q = uow.Quotes.GetById(id);
|
||||
|
||||
if ((q?.GuildId != ctx.Guild.Id) || (!isAdmin && q.AuthorId != ctx.Message.Author.Id))
|
||||
if ((q?.GuildId != ctx.Guild.Id) || (!hasManageMessages && q.AuthorId != ctx.Message.Author.Id))
|
||||
{
|
||||
response = GetText(strs.quotes_remove_none);
|
||||
}
|
||||
@@ -248,6 +253,140 @@ namespace NadekoBot.Modules.Utility
|
||||
|
||||
await ReplyConfirmLocalizedAsync(strs.quotes_deleted(Format.Bold(keyword.SanitizeAllMentions()))).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public class ExportedQuote
|
||||
{
|
||||
public static ExportedQuote FromModel(Quote quote)
|
||||
=> new ExportedQuote()
|
||||
{
|
||||
Id = ((kwum)quote.Id).ToString(),
|
||||
An = quote.AuthorName,
|
||||
Aid = quote.AuthorId,
|
||||
Txt = quote.Text
|
||||
};
|
||||
|
||||
public string Id { get; set; }
|
||||
public string An { get; set; }
|
||||
public ulong Aid { get; set; }
|
||||
public string Txt { get; set; }
|
||||
}
|
||||
|
||||
private const string _prependExport =
|
||||
@"# Keys are keywords, Each key has a LIST of quotes in the following format:
|
||||
# - id: Alphanumeric id used for commands related to the quote. (Note, when using .quotesimport, a new id will be generated.)
|
||||
# an: Author name
|
||||
# aid: Author id
|
||||
# txt: Quote text
|
||||
";
|
||||
private static readonly ISerializer _exportSerializer = new SerializerBuilder()
|
||||
.WithEventEmitter(args => new MultilineScalarFlowStyleEmitter(args))
|
||||
.WithNamingConvention(YamlDotNet.Serialization.NamingConventions.CamelCaseNamingConvention.Instance)
|
||||
.WithIndentedSequences()
|
||||
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults)
|
||||
.DisableAliases()
|
||||
.Build();
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task QuotesExport()
|
||||
{
|
||||
IEnumerable<Quote> quotes;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
quotes = uow.Quotes
|
||||
.GetForGuild(ctx.Guild.Id)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
var crsDict = quotes
|
||||
.GroupBy(x => x.Keyword)
|
||||
.ToDictionary(x => x.Key, x => x.Select(ExportedQuote.FromModel));
|
||||
|
||||
var text = _prependExport + _exportSerializer
|
||||
.Serialize(crsDict)
|
||||
.UnescapeUnicodeCodePoints();
|
||||
|
||||
await using var stream = await text.ToStream();
|
||||
await ctx.Channel.SendFileAsync(stream, "quote-export.yml", text: null);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
[Ratelimit(300)]
|
||||
#if GLOBAL_NADEKO
|
||||
[OwnerOnly]
|
||||
#endif
|
||||
public async Task QuotesImport([Leftover]string input = null)
|
||||
{
|
||||
input = input?.Trim();
|
||||
|
||||
_ = ctx.Channel.TriggerTypingAsync();
|
||||
|
||||
if (input is null)
|
||||
{
|
||||
var attachment = ctx.Message.Attachments.FirstOrDefault();
|
||||
if (attachment is null)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.expr_import_no_input);
|
||||
return;
|
||||
}
|
||||
|
||||
using var client = _http.CreateClient();
|
||||
input = await client.GetStringAsync(attachment.Url);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.expr_import_no_input);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var succ = await ImportCrsAsync(ctx.Guild.Id, input);
|
||||
if (!succ)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.expr_import_invalid_data);
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.OkAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> ImportCrsAsync(ulong guildId, string input)
|
||||
{
|
||||
Dictionary<string, List<ExportedQuote>> data;
|
||||
try
|
||||
{
|
||||
data = Yaml.Deserializer.Deserialize<Dictionary<string, List<ExportedQuote>>>(input);
|
||||
if (data.Sum(x => x.Value.Count) == 0)
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
foreach (var entry in data)
|
||||
{
|
||||
var keyword = entry.Key;
|
||||
await uow.Quotes
|
||||
.AddRangeAsync(entry.Value
|
||||
.Where(quote => !string.IsNullOrWhiteSpace(quote.Txt))
|
||||
.Select(quote => new Quote()
|
||||
{
|
||||
GuildId = guildId,
|
||||
Keyword = keyword,
|
||||
Text = quote.Txt,
|
||||
AuthorId = quote.Aid,
|
||||
AuthorName = quote.An,
|
||||
}));
|
||||
}
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -80,21 +80,50 @@ namespace NadekoBot.Modules.Utility
|
||||
}
|
||||
}
|
||||
|
||||
public enum Server
|
||||
{
|
||||
Server = int.MinValue,
|
||||
Srvr = int.MinValue,
|
||||
Serv = int.MinValue,
|
||||
S = int.MinValue,
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
public async Task RemindList(int page = 1)
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
[Priority(0)]
|
||||
public Task RemindList(Server _, int page = 1)
|
||||
=> RemindList(page, true);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[Priority(1)]
|
||||
public Task RemindList(int page = 1)
|
||||
=> RemindList(page, false);
|
||||
|
||||
private async Task RemindList(int page, bool isServer)
|
||||
{
|
||||
if (--page < 0)
|
||||
return;
|
||||
|
||||
var embed = _eb.Create()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.reminder_list));
|
||||
.WithTitle(GetText(isServer ? strs.reminder_server_list : strs.reminder_list));
|
||||
|
||||
List<Reminder> rems;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
rems = uow.Reminders.RemindersFor(ctx.User.Id, page)
|
||||
.ToList();
|
||||
if (isServer)
|
||||
{
|
||||
rems = uow.Reminders
|
||||
.RemindersForServer(ctx.Guild.Id, page)
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
rems = uow.Reminders
|
||||
.RemindersFor(ctx.User.Id, page)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
if (rems.Any())
|
||||
@@ -121,18 +150,33 @@ namespace NadekoBot.Modules.Utility
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
public async Task RemindDelete(int index)
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
[Priority(0)]
|
||||
public Task RemindDelete(Server _, int index)
|
||||
=> RemindDelete(index, true);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[Priority(1)]
|
||||
public Task RemindDelete(int index)
|
||||
=> RemindDelete(index, false);
|
||||
|
||||
private async Task RemindDelete(int index, bool isServer)
|
||||
{
|
||||
if (--index < 0)
|
||||
return;
|
||||
|
||||
var embed = _eb.Create();
|
||||
|
||||
Reminder rem = null;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var rems = uow.Reminders.RemindersFor(ctx.User.Id, index / 10)
|
||||
.ToList();
|
||||
var rems = isServer
|
||||
? uow.Reminders
|
||||
.RemindersForServer(ctx.Guild.Id, index / 10)
|
||||
.ToList()
|
||||
: uow.Reminders
|
||||
.RemindersFor(ctx.User.Id, index / 10)
|
||||
.ToList();
|
||||
|
||||
var pageIndex = index % 10;
|
||||
if (rems.Count > pageIndex)
|
||||
{
|
||||
|
@@ -4,7 +4,9 @@ using NadekoBot.Services.Database.Models;
|
||||
using NadekoBot.Modules.Utility.Common.Patreon;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
@@ -146,15 +148,22 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
if (DateTime.UtcNow.Day < 5)
|
||||
return;
|
||||
|
||||
// if the user has the necessary patreon creds
|
||||
// and the access token expired or doesn't exist
|
||||
// -> update access token
|
||||
if (!HasPatreonCreds(creds))
|
||||
if (string.IsNullOrWhiteSpace(creds.Patreon.CampaignId))
|
||||
return;
|
||||
|
||||
if (LastAccessTokenUpdate(creds).Month < DateTime.UtcNow.Month
|
||||
var lastUpdate = LastAccessTokenUpdate(creds);
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
if (lastUpdate.Year != now.Year
|
||||
|| lastUpdate.Month != now.Month
|
||||
|| string.IsNullOrWhiteSpace(creds.Patreon.AccessToken))
|
||||
{
|
||||
// if the user has the necessary patreon creds
|
||||
// and the access token expired or doesn't exist
|
||||
// -> update access token
|
||||
if (!HasPatreonCreds(creds))
|
||||
return;
|
||||
|
||||
var success = await UpdateAccessToken(creds);
|
||||
if (!success)
|
||||
return;
|
||||
@@ -164,7 +173,7 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
await getPledgesLocker.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
var members = new List<PatreonMember>();
|
||||
var users = new List<PatreonUser>();
|
||||
using (var http = _httpFactory.CreateClient())
|
||||
@@ -185,7 +194,7 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
|
||||
if (data is null)
|
||||
break;
|
||||
|
||||
|
||||
members.AddRange(data.Data);
|
||||
users.AddRange(data.Included);
|
||||
} while (!string.IsNullOrWhiteSpace(page = data?.Links?.Next));
|
||||
@@ -209,12 +218,19 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
EntitledTo: > 0
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
||||
foreach (var pledge in userData)
|
||||
{
|
||||
await ClaimReward(pledge.UserId, pledge.PatreonUserId, pledge.EntitledTo);
|
||||
}
|
||||
}
|
||||
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
Log.Warning("Patreon credentials invalid or expired. I will try to refresh them during the next run");
|
||||
var db = _redis.GetDatabase();
|
||||
await db.KeyDeleteAsync($"{creds.RedisKey()}_patreon_update");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "Error refreshing patreon pledges");
|
||||
@@ -223,7 +239,6 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
{
|
||||
getPledgesLocker.Release();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async Task<int> ClaimReward(ulong userId, string patreonUserId, int cents)
|
||||
@@ -280,7 +295,7 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
var toAward = eligibleFor - usr.AmountRewardedThisMonth;
|
||||
|
||||
usr.LastReward = now;
|
||||
usr.AmountRewardedThisMonth = toAward;
|
||||
usr.AmountRewardedThisMonth = eligibleFor;
|
||||
await uow.SaveChangesAsync();
|
||||
|
||||
await _currency.AddAsync(userId, "Patreon reward - update", toAward, gamble: true);
|
||||
|
@@ -227,6 +227,9 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
|
||||
private async Task RescanUser(IGuildUser user, StreamRoleSettings setting, IRole addRole = null)
|
||||
{
|
||||
if (user.IsBot)
|
||||
return;
|
||||
|
||||
var g = (StreamingGame)user.Activities
|
||||
.FirstOrDefault(a => a is StreamingGame &&
|
||||
(string.IsNullOrWhiteSpace(setting.Keyword)
|
||||
@@ -240,7 +243,7 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
{
|
||||
try
|
||||
{
|
||||
addRole = addRole ?? user.Guild.GetRole(setting.AddRoleId);
|
||||
addRole ??= user.Guild.GetRole(setting.AddRoleId);
|
||||
if (addRole is null)
|
||||
{
|
||||
await StopStreamRole(user.Guild).ConfigureAwait(false);
|
||||
@@ -249,9 +252,12 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
}
|
||||
|
||||
//check if he doesn't have addrole already, to avoid errors
|
||||
if (!user.RoleIds.Contains(setting.AddRoleId))
|
||||
if (!user.RoleIds.Contains(addRole.Id))
|
||||
{
|
||||
await user.AddRoleAsync(addRole).ConfigureAwait(false);
|
||||
Log.Information("Added stream role to user {0} in {1} server", user.ToString(), user.Guild.ToString());
|
||||
Log.Information("Added stream role to user {0} in {1} server", user.ToString(),
|
||||
user.Guild.ToString());
|
||||
}
|
||||
}
|
||||
catch (HttpException ex) when (ex.HttpCode == System.Net.HttpStatusCode.Forbidden)
|
||||
{
|
||||
|
@@ -11,11 +11,14 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Common.Replacements;
|
||||
using NadekoBot.Services;
|
||||
using Serilog;
|
||||
using SystemTextJsonSamples;
|
||||
using JsonSerializer = Newtonsoft.Json.JsonSerializer;
|
||||
|
||||
namespace NadekoBot.Modules.Utility
|
||||
{
|
||||
@@ -105,7 +108,9 @@ namespace NadekoBot.Modules.Utility
|
||||
await ctx.Channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||
await _tracker.EnsureUsersDownloadedAsync(ctx.Guild).ConfigureAwait(false);
|
||||
|
||||
var users = await ctx.Guild.GetUsersAsync();
|
||||
var users = await ctx.Guild.GetUsersAsync(
|
||||
CacheMode.CacheOnly
|
||||
);
|
||||
var roleUsers = users
|
||||
.Where(u => role is null ? u.RoleIds.Count == 1 : u.RoleIds.Contains(role.Id))
|
||||
.Select(u => $"`{u.Id, 18}` {u}")
|
||||
@@ -119,9 +124,9 @@ namespace NadekoBot.Modules.Utility
|
||||
|
||||
if (pageUsers.Count == 0)
|
||||
return _eb.Create().WithOkColor().WithDescription(GetText(strs.no_user_on_this_page));
|
||||
|
||||
|
||||
return _eb.Create().WithOkColor()
|
||||
.WithTitle(GetText(strs.inrole_list(Format.Bold(role?.Name ?? "No Role") + $" - {roleUsers.Length}")))
|
||||
.WithTitle(GetText(strs.inrole_list(Format.Bold(role?.Name ?? "No Role"), roleUsers.Length)))
|
||||
.WithDescription(string.Join("\n", pageUsers));
|
||||
}, roleUsers.Length, 20).ConfigureAwait(false);
|
||||
}
|
||||
@@ -284,24 +289,24 @@ namespace NadekoBot.Modules.Utility
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireBotPermission(GuildPermission.ManageEmojis)]
|
||||
[RequireUserPermission(GuildPermission.ManageEmojis)]
|
||||
[BotPerm(GuildPerm.ManageEmojis)]
|
||||
[UserPerm(GuildPerm.ManageEmojis)]
|
||||
[Priority(2)]
|
||||
public Task EmojiAdd(string name, Emote emote)
|
||||
=> EmojiAdd(name, emote.Url);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireBotPermission(GuildPermission.ManageEmojis)]
|
||||
[RequireUserPermission(GuildPermission.ManageEmojis)]
|
||||
[BotPerm(GuildPerm.ManageEmojis)]
|
||||
[UserPerm(GuildPerm.ManageEmojis)]
|
||||
[Priority(1)]
|
||||
public Task EmojiAdd(Emote emote)
|
||||
=> EmojiAdd(emote.Name, emote.Url);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireBotPermission(GuildPermission.ManageEmojis)]
|
||||
[RequireUserPermission(GuildPermission.ManageEmojis)]
|
||||
[BotPerm(GuildPerm.ManageEmojis)]
|
||||
[UserPerm(GuildPerm.ManageEmojis)]
|
||||
[Priority(0)]
|
||||
public async Task EmojiAdd(string name, string url = null)
|
||||
{
|
||||
@@ -362,7 +367,48 @@ namespace NadekoBot.Modules.Utility
|
||||
|
||||
await ctx.Channel.EmbedAsync(embed);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public Task ShowEmbed(ulong messageId)
|
||||
=> ShowEmbed((ITextChannel)ctx.Channel, messageId);
|
||||
|
||||
private static readonly JsonSerializerOptions _showEmbedSerializerOptions = new JsonSerializerOptions()
|
||||
{
|
||||
WriteIndented = true,
|
||||
IgnoreNullValues = true,
|
||||
PropertyNamingPolicy = LowerCaseNamingPolicy.Default
|
||||
};
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ShowEmbed(ITextChannel ch, ulong messageId)
|
||||
{
|
||||
var user = (IGuildUser)ctx.User;
|
||||
var perms = user.GetPermissions(ch);
|
||||
if (!perms.ReadMessageHistory || !perms.ViewChannel)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.insuf_perms_u);
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = await ch.GetMessageAsync(messageId);
|
||||
if (msg is null)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.msg_not_found);
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = msg.Embeds.FirstOrDefault();
|
||||
if (embed is null)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.not_found);
|
||||
return;
|
||||
}
|
||||
|
||||
var json = SmartEmbedText.FromEmbed(embed, msg.Content).ToJson(_showEmbedSerializerOptions);
|
||||
await SendConfirmAsync(Format.Sanitize(json).Replace("](", "]\\("));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
@@ -433,6 +479,8 @@ namespace NadekoBot.Modules.Utility
|
||||
New
|
||||
}
|
||||
|
||||
|
||||
|
||||
// [NadekoCommand, Usage, Description, Aliases]
|
||||
// [RequireContext(ContextType.Guild)]
|
||||
// public async Task CreateMyInvite(CreateInviteType type = CreateInviteType.Any)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
using Discord;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Common.Attributes;
|
||||
@@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Xp
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task XpRewsReset()
|
||||
{
|
||||
var reply = await PromptUserConfirmAsync(_eb.Create()
|
||||
@@ -278,7 +278,7 @@ namespace NadekoBot.Modules.Xp
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(strs.excluded(Format.Bold(channel.ToString())));
|
||||
await ReplyConfirmLocalizedAsync(strs.not_excluded(Format.Bold(channel.ToString())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -9,29 +9,29 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AngleSharp" Version="0.16.0" />
|
||||
<PackageReference Include="AWSSDK.S3" Version="3.7.1.19" />
|
||||
<PackageReference Include="AngleSharp" Version="0.16.1" />
|
||||
<PackageReference Include="AWSSDK.S3" Version="3.7.7.3" />
|
||||
<PackageReference Include="Cloneable" Version="1.3.0" />
|
||||
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.1" />
|
||||
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.2" />
|
||||
<PackageReference Include="CommandLineParser" Version="2.8.0" />
|
||||
<PackageReference Include="Discord.Net" Version="2.4.0" />
|
||||
<PackageReference Include="CoreCLR-NCalc" Version="2.2.92" />
|
||||
<PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.41.1.138" />
|
||||
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.53.0.2378" />
|
||||
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.55.0.2449" />
|
||||
<PackageReference Include="Google.Apis.Customsearch.v1" Version="1.49.0.2084" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.17.3" />
|
||||
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.38.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.38.1">
|
||||
<PackageReference Include="Google.Protobuf" Version="3.19.1" />
|
||||
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.41.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.42.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Html2Markdown" Version="4.0.0.427" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.8">
|
||||
<PackageReference Include="Html2Markdown" Version="5.0.0.468" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.13" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.13">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.13" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
|
||||
@@ -44,15 +44,13 @@
|
||||
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Scrutor" Version="3.3.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Seq" Version="5.0.1" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.3" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Seq" Version="5.1.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta0010" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.2.62" />
|
||||
<PackageReference Include="VideoLibrary" Version="3.1.2" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.2.88" />
|
||||
<PackageReference Include="YamlDotNet" Version="11.2.1" />
|
||||
<PackageReference Include="YoutubeExplode" Version="6.0.5" />
|
||||
<PackageReference Include="linq2db.EntityFrameworkCore" Version="5.4.0" />
|
||||
<PackageReference Include="linq2db.EntityFrameworkCore" Version="5.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -8,14 +8,16 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Db;
|
||||
using NadekoBot.Modules.Administration;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Services
|
||||
{
|
||||
public class GreetSettingsService : INService
|
||||
public class GreetSettingsService : INService, IReadyExecutor
|
||||
{
|
||||
private readonly DbService _db;
|
||||
|
||||
@@ -51,6 +53,17 @@ namespace NadekoBot.Services
|
||||
|
||||
_client.GuildMemberUpdated += ClientOnGuildMemberUpdated;
|
||||
}
|
||||
|
||||
public async Task OnReadyAsync()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var (conf, user, compl) = await _greetDmQueue.Reader.ReadAsync();
|
||||
var res = await GreetDmUserInternal(conf, user);
|
||||
compl.TrySetResult(res);
|
||||
await Task.Delay(2000);
|
||||
}
|
||||
}
|
||||
|
||||
private Task ClientOnGuildMemberUpdated(SocketGuildUser oldUser, SocketGuildUser newUser)
|
||||
{
|
||||
@@ -240,17 +253,48 @@ namespace NadekoBot.Services
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> GreetDmUser(GreetSettings conf, IDMChannel channel, IGuildUser user)
|
||||
private readonly Channel<(GreetSettings, IGuildUser, TaskCompletionSource<bool>)> _greetDmQueue =
|
||||
Channel.CreateBounded<(GreetSettings, IGuildUser, TaskCompletionSource<bool>)>(new BoundedChannelOptions(60)
|
||||
{
|
||||
// The limit of 60 users should be only hit when there's a raid. In that case
|
||||
// probably the best thing to do is to drop newest (raiding) users
|
||||
FullMode = BoundedChannelFullMode.DropNewest
|
||||
});
|
||||
|
||||
private async Task<bool> GreetDmUser(GreetSettings conf, IGuildUser user)
|
||||
{
|
||||
var completionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
await _greetDmQueue.Writer.WriteAsync((conf, user, completionSource));
|
||||
return await completionSource.Task;
|
||||
}
|
||||
|
||||
private async Task<bool> GreetDmUserInternal(GreetSettings conf, IGuildUser user)
|
||||
{
|
||||
var rep = new ReplacementBuilder()
|
||||
.WithDefault(user, channel, (SocketGuild)user.Guild, _client)
|
||||
.Build();
|
||||
|
||||
var text = SmartText.CreateFrom(conf.DmGreetMessageText);
|
||||
rep.Replace(text);
|
||||
try
|
||||
{
|
||||
await channel.SendAsync(text).ConfigureAwait(false);
|
||||
var rep = new ReplacementBuilder()
|
||||
.WithUser(user)
|
||||
.WithServer(_client, (SocketGuild)user.Guild)
|
||||
.Build();
|
||||
|
||||
var text = SmartText.CreateFrom(conf.DmGreetMessageText);
|
||||
text = rep.Replace(text);
|
||||
|
||||
if (text is SmartPlainText pt)
|
||||
{
|
||||
text = new SmartEmbedText() { PlainText = pt.Text };
|
||||
}
|
||||
|
||||
((SmartEmbedText)text).Footer = new()
|
||||
{
|
||||
Text = $"This message was sent from {user.Guild} server.", IconUrl = user.Guild.IconUrl
|
||||
};
|
||||
|
||||
var ch = await user.GetOrCreateDMChannelAsync();
|
||||
if (ch is null)
|
||||
return false;
|
||||
|
||||
await ch.SendAsync(text);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -301,12 +345,7 @@ namespace NadekoBot.Services
|
||||
|
||||
if (conf.SendDmGreetMessage)
|
||||
{
|
||||
var channel = await user.GetOrCreateDMChannelAsync().ConfigureAwait(false);
|
||||
|
||||
if (channel != null)
|
||||
{
|
||||
await GreetDmUser(conf, channel, user);
|
||||
}
|
||||
await GreetDmUser(conf, user);
|
||||
}
|
||||
}
|
||||
catch
|
||||
@@ -477,10 +516,10 @@ namespace NadekoBot.Services
|
||||
return GreetUsers(conf, channel, user);
|
||||
}
|
||||
|
||||
public Task<bool> GreetDmTest(IDMChannel channel, IGuildUser user)
|
||||
public Task<bool> GreetDmTest(IGuildUser user)
|
||||
{
|
||||
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
||||
return GreetDmUser(conf, channel, user);
|
||||
return GreetDmUser(conf, user);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@@ -1,15 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Services
|
||||
{
|
||||
public interface ICoordinator
|
||||
{
|
||||
bool RestartBot();
|
||||
void Die();
|
||||
void Die(bool graceful);
|
||||
bool RestartShard(int shardId);
|
||||
IList<ShardStatus> GetAllShardStatuses();
|
||||
int GetGuildCount();
|
||||
Task Reload();
|
||||
}
|
||||
|
||||
public class ShardStatus
|
||||
|
@@ -7,7 +7,7 @@ namespace NadekoBot.Services
|
||||
{
|
||||
public interface IGoogleApiService : INService
|
||||
{
|
||||
IEnumerable<string> Languages { get; }
|
||||
IReadOnlyDictionary<string, string> Languages { get; }
|
||||
|
||||
Task<IEnumerable<string>> GetVideoLinksByKeywordAsync(string keywords, int count = 1);
|
||||
Task<IEnumerable<(string Name, string Id, string Url)>> GetVideoInfosByKeywordAsync(string keywords, int count = 1);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
using Google;
|
||||
using Google;
|
||||
using Google.Apis.Customsearch.v1;
|
||||
using Google.Apis.Services;
|
||||
using Google.Apis.Urlshortener.v1;
|
||||
@@ -220,14 +220,14 @@ namespace NadekoBot.Services
|
||||
req.Fields = "items(image(contextLink,thumbnailLink),link)";
|
||||
req.SearchType = CseResource.ListRequest.SearchTypeEnum.Image;
|
||||
req.Start = new NadekoRandom().Next(0, 20);
|
||||
req.Safe = CseResource.ListRequest.SafeEnum.Active;
|
||||
|
||||
var search = await req.ExecuteAsync().ConfigureAwait(false);
|
||||
|
||||
return new ImageResult(search.Items[0].Image, search.Items[0].Link);
|
||||
}
|
||||
|
||||
public IEnumerable<string> Languages => _languageDictionary.Keys.OrderBy(x => x);
|
||||
private readonly Dictionary<string, string> _languageDictionary = new Dictionary<string, string>() {
|
||||
public IReadOnlyDictionary<string, string> Languages { get; } = new Dictionary<string, string>() {
|
||||
{ "afrikaans", "af"},
|
||||
{ "albanian", "sq"},
|
||||
{ "arabic", "ar"},
|
||||
@@ -365,8 +365,8 @@ namespace NadekoBot.Services
|
||||
await Task.Yield();
|
||||
string text;
|
||||
|
||||
if (!_languageDictionary.ContainsKey(sourceLanguage) ||
|
||||
!_languageDictionary.ContainsKey(targetLanguage))
|
||||
if (!Languages.ContainsKey(sourceLanguage) ||
|
||||
!Languages.ContainsKey(targetLanguage))
|
||||
throw new ArgumentException(nameof(sourceLanguage) + "/" + nameof(targetLanguage));
|
||||
|
||||
|
||||
@@ -385,8 +385,8 @@ namespace NadekoBot.Services
|
||||
|
||||
private string ConvertToLanguageCode(string language)
|
||||
{
|
||||
_languageDictionary.TryGetValue(language, out var mode);
|
||||
Languages.TryGetValue(language, out var mode);
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -39,11 +39,11 @@ namespace NadekoBot.Services
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Die()
|
||||
public void Die(bool graceful)
|
||||
{
|
||||
_coordClient.Die(new DieRequest()
|
||||
{
|
||||
Graceful = false
|
||||
Graceful = graceful
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,6 +79,11 @@ namespace NadekoBot.Services
|
||||
return res.Statuses.Sum(x => x.GuildCount);
|
||||
}
|
||||
|
||||
public async Task Reload()
|
||||
{
|
||||
await _coordClient.ReloadAsync(new());
|
||||
}
|
||||
|
||||
public Task OnReadyAsync()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
|
@@ -36,7 +36,7 @@ namespace NadekoBot.Services
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Die()
|
||||
public void Die(bool graceful = false)
|
||||
{
|
||||
Environment.Exit(5);
|
||||
}
|
||||
@@ -64,5 +64,10 @@ namespace NadekoBot.Services
|
||||
{
|
||||
return _client.Guilds.Count;
|
||||
}
|
||||
|
||||
public Task Reload()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
using Discord;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Extensions;
|
||||
@@ -20,7 +20,7 @@ namespace NadekoBot.Services
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly DateTime _started;
|
||||
|
||||
public const string BotVersion = "3.0.9";
|
||||
public const string BotVersion = "3.0.13";
|
||||
public string Author => "Kwoth#2452";
|
||||
public string Library => "Discord.Net";
|
||||
public double MessagesPerSecond => MessageCounter / GetUptime().TotalSeconds;
|
||||
|
@@ -22,10 +22,12 @@ using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Common.Attributes;
|
||||
using Color = Discord.Color;
|
||||
using JsonSerializer = System.Text.Json.JsonSerializer;
|
||||
|
||||
namespace NadekoBot.Extensions
|
||||
{
|
||||
@@ -286,8 +288,8 @@ namespace NadekoBot.Extensions
|
||||
public static async Task<IEnumerable<IGuildUser>> GetMembersAsync(this IRole role) =>
|
||||
(await role.Guild.GetUsersAsync(CacheMode.CacheOnly).ConfigureAwait(false)).Where(u => u.RoleIds.Contains(role.Id)) ?? Enumerable.Empty<IGuildUser>();
|
||||
|
||||
public static string ToJson<T>(this T any, Formatting formatting = Formatting.Indented) =>
|
||||
JsonConvert.SerializeObject(any, formatting);
|
||||
public static string ToJson<T>(this T any, JsonSerializerOptions options = null) =>
|
||||
JsonSerializer.Serialize(any, options);
|
||||
|
||||
/// <summary>
|
||||
/// Adds fallback fonts to <see cref="TextOptions"/>
|
||||
|
@@ -74,8 +74,8 @@ osuApiKey:
|
||||
# cmd: dotnet
|
||||
# args: "NadekoBot.dll -- {0}"
|
||||
# Windows default
|
||||
# cmd: NadekoBot.exe
|
||||
# args: {0}
|
||||
# cmd: "NadekoBot.exe"
|
||||
# args: "{0}""
|
||||
restartCommand:
|
||||
cmd:
|
||||
args:
|
||||
|
@@ -1263,3 +1263,13 @@ imageonlychannel:
|
||||
- imageonlychannel
|
||||
- imageonly
|
||||
- imagesonly
|
||||
coordreload:
|
||||
- coordreload
|
||||
quotesexport:
|
||||
- quotesexport
|
||||
- qexport
|
||||
quotesimport:
|
||||
- quotesimport
|
||||
- qimport
|
||||
showembed:
|
||||
- showembed
|
@@ -1,5 +1,5 @@
|
||||
# DO NOT CHANGE
|
||||
version: 2
|
||||
version: 4
|
||||
# Currency settings
|
||||
currency:
|
||||
# What is the emoji/character which represents the currency
|
||||
@@ -240,3 +240,7 @@ patreonCurrencyPerCent: 1
|
||||
# Currency reward per vote.
|
||||
# This will work only if you've set up VotesApi and correct credentials for topgg and/or discords voting
|
||||
voteReward: 100
|
||||
# Slot config
|
||||
slots:
|
||||
# Hex value of the color which the numbers on the slot image will have.
|
||||
currencyFontColor: ff0000
|
||||
|
@@ -406,13 +406,15 @@ remind:
|
||||
- "me 1d5h Do something"
|
||||
- "#general 1m Start now!"
|
||||
reminddelete:
|
||||
desc: "Deletes a reminder on the specified index."
|
||||
desc: "Deletes a reminder on the specified index. You can specify 'server' option if you're an Administrator, and you want to delete a reminder on this server created by someone else. "
|
||||
args:
|
||||
- "3"
|
||||
- "server 2"
|
||||
remindlist:
|
||||
desc: "Lists all reminders you created. Paginated."
|
||||
desc: "Lists all reminders you created. You can specify 'server' option if you're an Administrator to list all reminders created on this server. Paginated."
|
||||
args:
|
||||
- "1"
|
||||
- "server 2"
|
||||
serverinfo:
|
||||
desc: "Shows info about the server the bot is on. If no server is supplied, it defaults to current one."
|
||||
args:
|
||||
@@ -609,7 +611,7 @@ quoteid:
|
||||
args:
|
||||
- "123456"
|
||||
quotedelete:
|
||||
desc: "Deletes a quote with the specified ID. You have to be either server Administrator or the creator of the quote to delete it."
|
||||
desc: "Deletes a quote with the specified ID. You have to either have the Manage Messages permission or be the creator of the quote to delete it."
|
||||
args:
|
||||
- "123456"
|
||||
draw:
|
||||
@@ -1141,9 +1143,9 @@ butts:
|
||||
args:
|
||||
- ""
|
||||
translate:
|
||||
desc: "Translates from>to text. From the given language to the destination language."
|
||||
desc: "Translates text from the given language to the destination language."
|
||||
args:
|
||||
- "en>fr Hello"
|
||||
- "en fr Hello"
|
||||
translangs:
|
||||
desc: "Lists the valid languages for translation."
|
||||
args:
|
||||
@@ -1304,7 +1306,7 @@ poll:
|
||||
autotranslang:
|
||||
desc: "Sets your source and target language to be used with `{0}at`. Specify no parameters to remove previously set value."
|
||||
args:
|
||||
- "en>fr"
|
||||
- "en fr"
|
||||
autotranslate:
|
||||
desc: "Starts automatic translation of all messages by users who set their `{0}atl` in this channel. You can set \"del\" parameter to automatically delete all translated user messages."
|
||||
args:
|
||||
@@ -1576,6 +1578,14 @@ crsexport:
|
||||
desc: "Exports custom reactions from the current server (or global custom reactions in DMs) into a .yml file"
|
||||
args:
|
||||
- ""
|
||||
quotesimport:
|
||||
desc: "Upload the file or send the raw .yml data with this command to import all quotes from the specified string or file into the current server."
|
||||
args:
|
||||
- "<upload .yml file>"
|
||||
quotesexport:
|
||||
desc: "Exports quotes from the current server into a .yml file"
|
||||
args:
|
||||
- ""
|
||||
aliaslist:
|
||||
desc: "Shows the list of currently set aliases. Paginated."
|
||||
args:
|
||||
@@ -2066,7 +2076,7 @@ rollduel:
|
||||
- "50 @Someone"
|
||||
- "@Challenger"
|
||||
reactionroles:
|
||||
desc: "Specify role names and server emojis with which they're represented, the bot will then add those emojis to the previous message in the channel, and users will be able to get the roles by clicking on the emoji. You can set 'excl' as the parameter before the reactions and roles to make them exclusive. You can have up to 5 of these enabled on one server at a time. Optionally you can specify target message if you don't want it to be the previous one."
|
||||
desc: "Specify role names and server emojis with which they're represented, the bot will then add those emojis to the previous message in the channel, and users will be able to get the roles by clicking on the emoji. You can set 'excl' as the parameter before the reactions and roles to make them exclusive. You can have up to 10 of these enabled on one server at a time. Optionally you can specify target message if you don't want it to be the previous one."
|
||||
args:
|
||||
- "Gamer :SomeServerEmoji: Streamer :Other: Watcher :Other2:"
|
||||
- "excl Horde :Horde: Alliance :Alliance:"
|
||||
@@ -2138,4 +2148,13 @@ imageonlychannel:
|
||||
Toggles whether the channel only allows images.
|
||||
Users who send more than a few non-image messages will be banned from using the channel.
|
||||
args:
|
||||
- ""
|
||||
- ""
|
||||
coordreload:
|
||||
desc: "Reloads coordinator config"
|
||||
args:
|
||||
- ""
|
||||
showembed:
|
||||
desc: "Prints the json equivalent of the embed of the message specified by its Id."
|
||||
args:
|
||||
- "820022733172121600"
|
||||
- "#some-channel 820022733172121600"
|
@@ -593,8 +593,6 @@
|
||||
"log_all": "Alle Events werden nun in diesem Channel geloggt.",
|
||||
"log_disabled": "Protokollierung ausgeschaltet.",
|
||||
"log_events": "Protokoll Ereignisse die du Abonnieren kannst:",
|
||||
"log_ignore": "Protokollierung wird {0} ignorieren",
|
||||
"log_not_ignore": "Protokollierung wird {0} nicht ignorieren",
|
||||
"log_stop": "Protokollierung des {0} Ereignisses wurde gestoppt.",
|
||||
"msg_not_found": "Nachricht wurde nicht gefunden.",
|
||||
"time_too_long": "Die spezifizierte Zeit ist zu lang.",
|
||||
@@ -953,5 +951,29 @@
|
||||
"empty_page": "Diese Seite ist leer.",
|
||||
"pages": "Seiten",
|
||||
"favorites": "Favoriten",
|
||||
"tags": "Stichworte"
|
||||
"tags": "Stichworte",
|
||||
"invalid_emoji_link": "",
|
||||
"emoji_add_error": "",
|
||||
"emoji_added": "",
|
||||
"boost_on": "",
|
||||
"boost_off": "",
|
||||
"boostmsg_cur": "",
|
||||
"boostmsg_enable": "",
|
||||
"boostmsg_new": "",
|
||||
"boostdel_off": "",
|
||||
"boostdel_on": "",
|
||||
"log_ignored_channels": "",
|
||||
"log_ignored_users": "",
|
||||
"log_ignore_user": "",
|
||||
"log_not_ignore_user": "",
|
||||
"log_ignore_chan": "",
|
||||
"log_not_ignore_chan": "",
|
||||
"streams_cleared": "",
|
||||
"warn_weight": "",
|
||||
"warn_count": "",
|
||||
"mass_ban_in_progress": "",
|
||||
"mass_ban_completed": "",
|
||||
"reminder_server_list": "",
|
||||
"imageonly_enable": "",
|
||||
"imageonly_disable": ""
|
||||
}
|
@@ -450,6 +450,7 @@
|
||||
"atl_set": "Your auto-translate language has been set to {0}>{1}",
|
||||
"atl_started": "Started automatic translation of messages on this channel.",
|
||||
"atl_stopped": "Stopped automatic translation of messages on this channel.",
|
||||
"atl_not_enabled": "Automatic translation is not enabled on this channel or you've provided an invalid language.",
|
||||
"bad_input_format": "Bad input format, or something went wrong.",
|
||||
"card_not_found": "Couldn't find that card.",
|
||||
"catfact": "fact",
|
||||
@@ -555,7 +556,7 @@
|
||||
"error": "Error",
|
||||
"features": "Features",
|
||||
"index_out_of_range": "Index out of range.",
|
||||
"inrole_list": "List of users in {0} role",
|
||||
"inrole_list": "List of users in {0} role ({1})",
|
||||
"joined_discord": "Joined Discord",
|
||||
"joined_server": "Joined server",
|
||||
"listservers": "ID: {0}\nMembers: {1}\nOwner ID: {2}",
|
||||
@@ -605,12 +606,13 @@
|
||||
"shard": "Shard",
|
||||
"showemojis": "**Name:** {0} **Link:** {1}",
|
||||
"showemojis_none": "No special emojis found.",
|
||||
"text_channels": "Text channels",
|
||||
"channels": "Channels",
|
||||
"text_channels": "Text: {0}",
|
||||
"voice_channels": "Voice: {0}",
|
||||
"uptime": "Uptime",
|
||||
"userid": "{0} of the user {1} is {2}",
|
||||
"roleid": "{0} of the role {1} is {2}",
|
||||
"users": "Users",
|
||||
"voice_channels": "Voice channels",
|
||||
"current_poll_results": "Current poll results",
|
||||
"poll_already_running": "Poll is already running on this server.",
|
||||
"poll_created": "📃 {0} has created a poll",
|
||||
@@ -682,7 +684,7 @@
|
||||
"clpa_obsolete": ":tada: **Patreon currency rewards are now automatic!** :tada:\nThis command is now obsolete.\nIf you did not receive your reward for this month's pledge, below are some of the reasons as to why that might be.",
|
||||
"clpa_fail_already": "Maybe you've already received your reward for this month. You can receive rewards only once a month unless you increase your pledge.\nYou can check it by using `.curtrs` command.",
|
||||
"clpa_fail_already_title": "Already rewarded",
|
||||
"clpa_fail_conn": "Your discord account might not be connected to Patreon. If you are unsure what that means, or don't know how to connect it - you have to go to [Patreon account settings page](https://patreon.com/settings/account) and click 'Connect to discord' button.",
|
||||
"clpa_fail_conn": "Your discord account might not be connected to Patreon. If you are unsure what that means, or don't know how to connect it - you have to go to [Patreon account settings page](https://www.patreon.com/settings/apps) and click 'Connect to discord' button.",
|
||||
"clpa_fail_conn_title": "Discord account not connected",
|
||||
"clpa_fail_sup": "In order to be eligible for the reward, you must support the project on patreon. You can use {0} command to get the link.",
|
||||
"clpa_fail_sup_title": "Not supporting",
|
||||
@@ -919,6 +921,7 @@
|
||||
"reaction_role_removed": "Removed ReactionRole message #{0}",
|
||||
"reaction_roles_full": "You've reached the limit on ReactionRole messages. You have to delete some.",
|
||||
"reminder_list": "List of reminders",
|
||||
"reminder_server_list": "List of server reminders",
|
||||
"reminder_deleted": "Reminder #{0} was deleted.",
|
||||
"reminder_not_exist": "Reminder at that index does not exist.",
|
||||
"reminders_none": "No reminder on this page.",
|
||||
|
@@ -177,7 +177,7 @@
|
||||
"cleverbot_enabled": "Cleverbot activado en este canal.",
|
||||
"curgen_disabled": "La generación de moneda ha sido desactivada en este canal.",
|
||||
"curgen_enabled": "La generación de moneda ha sido habilitada en este canal.",
|
||||
"curgen_pl": "¡{0} {1} han aparecido!",
|
||||
"curgen_pl": "¡{0} {1} ha aparecido!",
|
||||
"curgen_sn": "¡Ha aparecido {0}!",
|
||||
"game_started": "Juego iniciado",
|
||||
"hangman_game_started": "Juego del ahorcado iniciado",
|
||||
@@ -593,8 +593,6 @@
|
||||
"log_all": "Registrando todos los eventos en este canal.",
|
||||
"log_disabled": "Registros desactivados.",
|
||||
"log_events": "Registrar los eventos que puedes seguir en:",
|
||||
"log_ignore": "Los registros ignorarán {0}",
|
||||
"log_not_ignore": "Los registros no ignorarán {0}",
|
||||
"log_stop": "Se detuvo el registro del evento {0}.",
|
||||
"msg_not_found": "Mensaje no encontrado.",
|
||||
"time_too_long": "El tiempo especificado es mucho.",
|
||||
@@ -805,7 +803,7 @@
|
||||
"warn_expire_set_clear": "Las advertencias se reiniciarán cada {0} días.",
|
||||
"warn_expire_reset": "Las advertencias ya no expirarán.",
|
||||
"warn_punish_set_timed": "Aplicaré el castigo {0} por {2} a los usuarios con {1} advertencias.",
|
||||
"clpa_obsolete": ":tada: **¡Las recompensas de Patreon ahora son automáticas!** :tada:\nEste comando está obsoleto.\nSi no recibiste tu recompensa de este mes, abajo tienes alguna de las posibles razones.",
|
||||
"clpa_obsolete": ":tada: **¡Las recompensas de Patreon ahora son automáticas!** :tada:\nEste comando está obsoleto.\nSi no recibiste tu recompensa de este mes, abajo tienes algunas de las posibles razones.",
|
||||
"time_new": "Tiempo",
|
||||
"timezone_db_api_key": "Necesitas activar tu clave de API de TimezoneDB. Puedes hacerlo haciendo click en el link que recibiste en tu e-mail con tu clave de API.",
|
||||
"rolehoist_enabled": "El rol {0} ahora se muestra separado de los miembros en línea.",
|
||||
@@ -934,7 +932,7 @@
|
||||
"module_page_empty": "No hay módulos en esta pagina",
|
||||
"module_description_help": "Obtén ayuda con los comandos, descripciones y ejemplos de uso.",
|
||||
"module_description_gambling": "Apuesta a las tiradas de dados, al blackjack, a las tragamonedas, al lanzamiento de monedas y a otros\n",
|
||||
"module_description_games": "Juega a la trivia, al nunchi, al colgado, conecta4 y otros juegos.",
|
||||
"module_description_games": "Juega al trivial, al nunchi, al colgado, conecta4 y a otros juegos.",
|
||||
"module_description_nsfw": "Comandos NSFW",
|
||||
"module_description_music": "Reproduce música de YouTube, archivos locales, SoundCloud y radios.",
|
||||
"module_description_utility": "Administra citas personalizadas, repeticiones de mensajes y revisa datos sobre el servidor",
|
||||
@@ -953,5 +951,29 @@
|
||||
"empty_page": "Esta página está vacía.",
|
||||
"pages": "Páginas",
|
||||
"favorites": "Favoritos",
|
||||
"tags": "Etiquetas"
|
||||
"tags": "Etiquetas",
|
||||
"invalid_emoji_link": "La liga especificada o no es una imagen, o se excede de los 256KB.",
|
||||
"emoji_add_error": "Error al agregar emoji. Ya no hay espacio para más, o el tamaño de la imagen no es adecuado.",
|
||||
"emoji_added": "Se agregó un emoji nuevo: {0}",
|
||||
"boost_on": "Los anuncios de Aumentos se han activado en este canal.",
|
||||
"boost_off": "Los anuncios de Aumentos se han desactivado.",
|
||||
"boostmsg_cur": "Mensaje de Aumento actual: {0}",
|
||||
"boostmsg_enable": "Active los mensajes de Aumento tecleando {0}",
|
||||
"boostmsg_new": "Nuevo mensaje de Aumento configurado.",
|
||||
"boostdel_off": "Se ha desactivado la eliminación automática de mensajes de Aumento.",
|
||||
"boostdel_on": "Los mensajes de Aumento se eliminarán después de {0} segundos.",
|
||||
"log_ignored_channels": "Canales ignorados",
|
||||
"log_ignored_users": "Usuarios ignorados",
|
||||
"log_ignore_user": "El registro ignorará al usuario {0}",
|
||||
"log_not_ignore_user": "El registró ya no ignorará al usuario {0}",
|
||||
"log_ignore_chan": "El registro ignorará el canal {0}",
|
||||
"log_not_ignore_chan": "El registro ya no ignorará el canal {0}",
|
||||
"streams_cleared": "Todos los streams seguidos en este servidor se han eliminado.",
|
||||
"warn_weight": "Peso: {0}",
|
||||
"warn_count": "Actual {0}, total {1}",
|
||||
"mass_ban_in_progress": "Corriendo a {0} usuarios...",
|
||||
"mass_ban_completed": "Se han corrido a {0} usuarios.",
|
||||
"reminder_server_list": "Lista de recordatorios del servidor",
|
||||
"imageonly_enable": "Este canal ahora es exclusivo para imágenes.",
|
||||
"imageonly_disable": "Este canal ya no es exclusivo para imágenes."
|
||||
}
|
@@ -5,26 +5,26 @@
|
||||
"trigger": "Déclencheur",
|
||||
"response": "Réponse",
|
||||
"fw_cleared": "Suppression de tous les mots filtrés et des réglages de mots filtrés du salon.",
|
||||
"aar_disabled": "Les membres qui rejoignent le serveur ne recevront aucun rôle automatiquement.",
|
||||
"aar_disabled": "L'**assignation automatique de rôles** aux nouveaux membres est **désactivée**.",
|
||||
"bandm": "Vous avez été banni du serveur {0}.\nRaison : {1}",
|
||||
"banned_user": "Membre banni",
|
||||
"byedel_off": "La suppression automatique des messages de départ a été désactivée.",
|
||||
"byedel_on": "Les messages de départ seront supprimés après {0} secondes.",
|
||||
"byedel_on": "Les messages d'au revoir seront supprimés après {0} secondes.",
|
||||
"byemsg_cur": "Message d'au revoir actuel : {0}",
|
||||
"byemsg_enable": "Activez les messages de départ en tapant {0}",
|
||||
"byemsg_new": "Nouveau message de départ réglé.",
|
||||
"bye_off": "Annonces de départ désactivées.",
|
||||
"bye_on": "Annonces de départ désactivées dans ce salon.",
|
||||
"cr": "Le rôle {0} a été créé avec succès",
|
||||
"byemsg_enable": "Activez les messages d'au revoir en tapant {0}",
|
||||
"byemsg_new": "Nouveau message d'au revoir réglé.",
|
||||
"bye_off": "Annonces de d'au revoir désactivées.",
|
||||
"bye_on": "Annonces d'au revoir désactivées dans ce salon.",
|
||||
"cr": "Le rôle {0} a été créé avec succès.",
|
||||
"dr": "Le rôle {0} a été supprimé.",
|
||||
"createtextchan": "Salon textuel {0} créé.",
|
||||
"createvoich": "Salon vocal {0} créé.",
|
||||
"deafen": "Mise en sourdine effectuée.",
|
||||
"delmsg_off": "Je ne supprimerai plus automatiquement les messages qui auront exécuté avec succès une commande sur ce serveur.",
|
||||
"delmsg_on": "Je supprimerai automatiquement les messages qui auront exécuté avec succès une commande sur ce serveur.",
|
||||
"delmsg_channel_off": "Je ne supprimerai jamais automatiquement les messages qui auront exécuté avec succès une commande sur ce salon.",
|
||||
"delmsg_channel_on": "Je supprimerai toujours automatiquement les messages qui auront exécuté avec succès une commande sur ce salon.",
|
||||
"delmsg_channel_inherit": "Je supprimerai automatiquement les messages qui auront exécuté avec succès une commande sur ce salon uniquement si l'option est activée sur le serveur.",
|
||||
"delmsg_off": "Les messages exécutant une commande avec succès ne seront plus supprimés automatiquement sur ce serveur.",
|
||||
"delmsg_on": "Les messages exécutant une commande avec succès seront supprimés automatiquement sur ce serveur.",
|
||||
"delmsg_channel_off": "Les messages exécutant une commande avec succès ne seront jamais supprimés sur ce salon.",
|
||||
"delmsg_channel_on": "Les messages exécutant une commande avec succès seront toujours supprimés automatiquement sur ce salon, en dehors des réglages du serveur.",
|
||||
"delmsg_channel_inherit": "Les messages exécutant une commande avec succès seront supprimés automatiquement sur ce salon seulement si l'option est activée sur le serveur.",
|
||||
"deltextchan": "Salon textuel {0} supprimé.",
|
||||
"delvoich": "Salon vocal {0} supprimé.",
|
||||
"fwall_start": "Je transmettrai les MPs à tous les propriétaires.",
|
||||
@@ -48,91 +48,91 @@
|
||||
"kickdm": "Vous avez été expulsé du serveur {0}.\nRaison : {1}",
|
||||
"kicked_user": "Membre expulsé",
|
||||
"lang_list": "Liste des langues",
|
||||
"lang_set_bot": "Les paramètres régionaux par défaut du bot sont désormais {0} - {1}",
|
||||
"lang_set_bot_show": "La langage du bot a été réglé sur {0} - {1}",
|
||||
"lang_set_bot": "La localisation par défaut du bot est désormais {0} - {1}",
|
||||
"lang_set_bot_show": "Le langage du bot a été réglé sur {0} - {1}",
|
||||
"lang_set": "La localisation du serveur a été réglée sur {0} - {1}",
|
||||
"message_sent": "Message envoyé.",
|
||||
"mute_error": "Je n'ai probablement pas les permissions nécessaires pour ça.",
|
||||
"mute_error": "Je n'ai certainement pas les permissions nécessaires pour cela.",
|
||||
"mute_role_set": "Nouveau rôle muet défini.",
|
||||
"prot_active": "Protections actives",
|
||||
"prot_disable": "{0} a été **désactivé** sur ce serveur",
|
||||
"prot_disable": "{0} a été **désactivé** sur ce serveur.",
|
||||
"prot_enable": "{0} Activé",
|
||||
"prot_none": "Aucune protection d'activée.",
|
||||
"raid_cnt": "Le seuil d'utilisateurs doit être entre {0} et {1}",
|
||||
"raid_stats": "Si {0} ou plus d'utilisateurs rejoignent dans {1} secondes, je les {2}.",
|
||||
"raid_time": "Le temps doit être entre {0} et {1} secondes.",
|
||||
"rar": "Suppression de tout les rôles de l'utilisateur {0} avec succès",
|
||||
"rc": "La couleur de {0} a été changée",
|
||||
"raid_cnt": "Le seuil d'utilisateurs doit être entre {0} et {1}.",
|
||||
"raid_stats": "Si {0} utilisateurs ou plus rejoignent en {1} secondes, ils seront {2}.",
|
||||
"raid_time": "La durée doit être définie entre {0} et {1} secondes.",
|
||||
"rar": "Tous les rôles de l'utilisateur {0} ont été retirés avec succès.",
|
||||
"rc": "La couleur de {0} a été changée.",
|
||||
"renrole": "Rôle renommé.",
|
||||
"reprm": "Suppression du message de lecture: {0}",
|
||||
"role_added": "Le rôle {0] a été ajouté à la liste du groupe {1}.",
|
||||
"reprm": "Suppression du message de lecture: {0}.",
|
||||
"role_added": "Le rôle {0} a été ajouté à la liste du groupe {1}.",
|
||||
"role_in_list": "Le rôle {0} est déjà dans la liste.",
|
||||
"self_assign_already": "Vous avez déjà le rôle {0}",
|
||||
"self_assign_excl": "Les rôles auto-attribués sont désormais exclusifs !",
|
||||
"self_assign_already": "Vous disposez déjà du rôle {0}.",
|
||||
"self_assign_excl": "Les rôles auto-attribués sont désormais exclusifs!",
|
||||
"self_assign_list": "Il y a {0} rôles auto-attribués",
|
||||
"self_assign_not": "Ce rôle n'est pas auto-attribuable.",
|
||||
"self_assign_not_have": "Vous n'avez pas le rôle {0}.",
|
||||
"self_assign_no_excl": "Les rôles auto-attribués ne sont plus désormais exclusifs !",
|
||||
"self_assign_perms": "Je suis dans l'incapacité de t'ajouter ce rôle. `Je ne peux pas ajouter de rôles aux propriétaires ou aux autres rôles supérieur à mon rôle dans la hiérarchie des rôles.`",
|
||||
"self_assign_not_have": "Vous ne disposez pas du rôle {0}.",
|
||||
"self_assign_no_excl": "Les rôles auto-attribués ne sont désormais plus exclusifs!",
|
||||
"self_assign_perms": "Je suis dans l'incapacité de t'ajouter ce rôle. `« Je ne peux pas ajouter de rôles aux propriétaires ou aux autres supérieurs au mien dans la hiérarchie des rôles. »`",
|
||||
"self_assign_rem": "{0} a été supprimé de la liste des rôles auto-attribuable.",
|
||||
"self_assign_remove": "Vous n'avez plus le rôle {0}.",
|
||||
"self_assign_success": "Vous avez désormais le rôle {0}.",
|
||||
"self_assign_remove": "Vous ne disposez plus du rôle {0}.",
|
||||
"self_assign_success": "Vous disposez désormais du rôle {0}.",
|
||||
"adsarm_enable": "L'effacement automatique des réponses `{0}iam` et `{0}iamn` a été activé.",
|
||||
"adsarm_disable": "Le bot ne supprimera plus désormais les réponses `{0}iam` et `{0}iamn`.",
|
||||
"adsarm_disable": "Le bot ne supprimera plus les réponses `{0}iam` et `{0}iamn`.",
|
||||
"setrole": "Ajout du rôle {0} à l'utilisateur {1} avec succès.",
|
||||
"set_channel_name": "Nouveau nom de salon défini.",
|
||||
"shutting_down": "Arrêt",
|
||||
"spam_ignore": "{0} ignorera ce salon.",
|
||||
"spam_not_ignore": "{0} n'ignorera désormais plus ce salon.",
|
||||
"spam_stats": "Si un utilisateur publie {0} messages identiques à la fois, je le {1}.\n __Canaux Ignorés__: {2}",
|
||||
"spam_not_ignore": "{0} n'ignorera plus ce salon.",
|
||||
"spam_stats": "Si un utilisateur publie {0} messages identiques à la fois, il sera {1}.\n __Salons Ignorés__: {2}",
|
||||
"undeafen": "Mise en sourdine désactivée avec succès.",
|
||||
"username": "Nom d'utilisateur",
|
||||
"user_chat_mute": "{0} a été mis en sourdine du tchat.",
|
||||
"user_chat_unmute": "**La parole a été rétablie** dans le salon textuel pour {0}.",
|
||||
"user_muted": "{0} a été mise en sourdine du tchat textuel et vocal.",
|
||||
"user_unmuted": "{0} n'est plus en sourdine dans le tchat textuel et vocal.",
|
||||
"user_voice_mute": "{0} est maintenant **muet** en vocal.",
|
||||
"user_voice_unmute": "{0} n'est plus **muet**",
|
||||
"sbdm": "Vous avez été expulsé du serveur {0}.\nRaison : {1}",
|
||||
"sb_user": "L'utilisateur a été expulsé",
|
||||
"better_luck": "Vous aurez plus de chance la prochaine fois ^-^",
|
||||
"roll": "Tu es tombé sur {0}.",
|
||||
"br_win": "Félicitations ! Tu gagnes {0} pour être tombé au dessus de {1}",
|
||||
"flip_guess": "Tu as trouvé ! Tu gagnes {0}",
|
||||
"flip_results": "Jeté de {0} pièces. {1} faces, {2} piles.",
|
||||
"user_chat_mute": "{0} a été **rendu muet** dans les salons textuels.",
|
||||
"user_chat_unmute": "{0} n'est **plus muet** dans les salons textuels.",
|
||||
"user_muted": "{0} a été **rendu muet** dans les salons textuels et vocaux.",
|
||||
"user_unmuted": "{0} n'est **plus muet** dans les salons textuels et vocaux.",
|
||||
"user_voice_mute": "{0} a été **rendu muet** en vocal.",
|
||||
"user_voice_unmute": "{0} n'est **plus muet** en vocal.",
|
||||
"sbdm": "Vous avez été radié du serveur {0}.\nRaison : {1}",
|
||||
"sb_user": "L'utilisateur a été radié.",
|
||||
"better_luck": "Vous aurez plus de chance la prochaine fois ^_^",
|
||||
"roll": "Tu as roulé un {0}.",
|
||||
"br_win": "Félicitations ! Tu as gagné {0} pour avoir roulé au delà de {1}",
|
||||
"flip_guess": "Tu as deviné ! Tu gagnes {0}",
|
||||
"flip_results": "a jeté {0} pièces. {1} faces, {2} piles.",
|
||||
"has": "{0} a {1}",
|
||||
"leaderboard": "Classement",
|
||||
"mass_award": "Récompense de {0} accordée aux utilisateurs {0} ayant de rôle {2}.",
|
||||
"mass_award": "Une récompense de {0} sera accordée aux {1} utilisateurs disposant du rôle {2}.",
|
||||
"max_bet_limit": "Vous ne pouvez pas parier plus de {0}",
|
||||
"min_bet_limit": "Tu ne peux pas parier moins de '0}",
|
||||
"not_enough": "Tu n'as pas assez de {0}",
|
||||
"min_bet_limit": "Vous ne pouvez pas parier moins de {0}",
|
||||
"not_enough": "Vous n'avez pas assez de {0}",
|
||||
"raffled_user": "Utilisateur tiré au sort",
|
||||
"slot_bet": "Pari",
|
||||
"slot_jackpot": "WOAAHHHHHHH !!! Félicitations !!! x{0}",
|
||||
"slot_jackpot": "WOAAHHHHHHH !!! Félicitations!!! x{0}",
|
||||
"slot_single": "Un simple {0}, x{1}",
|
||||
"slot_three": "Wow ! Chanceux ! Un brelan ! x{0}",
|
||||
"slot_two": "Bon travail ! Deux {0} - pari x{1}",
|
||||
"slot_three": "Wow! Chanceux! Un brelan! x{0}",
|
||||
"slot_two": "Bon travail! Deux {0} - pari x{1}",
|
||||
"won": "Gagné",
|
||||
"transactions": "Transactions de l'utilisateur {0}",
|
||||
"commands_instr": "Taper `{0}h NomCommande` pour voir l'aide de cette commande spécifique. Ex : `{0}h {0}8ball`",
|
||||
"command_not_found": "Je ne peux pas trouver cette commande. Vérifiez que cette commande existe avant de réessayer.",
|
||||
"module_not_found": "Ce module n'existe pas.",
|
||||
"module_not_found_or_cant_exec": "Soit ce module n'existe pas, soit vous ne pouvez exécuter aucunes des commandes dans le module spécifié.",
|
||||
"module_not_found_or_cant_exec": "Soit ce module n'existe pas, soit vous ne pouvez exécuter aucunes de ces commandes dans le module spécifié.",
|
||||
"usage": "Usage",
|
||||
"options": "Options",
|
||||
"requires": "Requiert",
|
||||
"blacklisted_tag_list": "Liste des mots-clés en liste noire:",
|
||||
"blacklisted_tag_add": "Le mot-clé {0} est maintenant sur liste noire.",
|
||||
"blacklisted_tag_remove": "Le mot-clé {0} n'est désormais plus sur liste noire.",
|
||||
"blacklisted_tag_list": "Liste des mots-clés sur la liste noire:",
|
||||
"blacklisted_tag_add": "Le mot-clé *NSFW* «{0}» est intégré à la liste noire.",
|
||||
"blacklisted_tag_remove": "Le mot-clé *NSFW* «{0}» n'est plus sur la liste noire.",
|
||||
"animal_race": "Course d'animaux",
|
||||
"animal_race_failed": "Échec du lancement car il n'y avait pas assez de participants.",
|
||||
"animal_race_join": "{0} a rejoint en tant que {1}",
|
||||
"animal_race_join_instr": "Taper `{0}jr` pour rejoindre la course.",
|
||||
"animal_race_starting": "Début dans {0} secondes ou quand la salle est pleine.",
|
||||
"animal_race_won": "{0} en tant que {1} a gagné la course !",
|
||||
"dice_invalid_number": "Nombre spécifié invalide. Vous pouvez jeter {0}-{1} dés à la fois",
|
||||
"animal_race_starting": "Début dans {0} secondes ou quand la salle sera pleine.",
|
||||
"animal_race_won": "{0} a gagné la course en tant que {1}!",
|
||||
"dice_invalid_number": "Nombre spécifié invalide. Vous pouvez jeter {0}-{1} dés à la fois.",
|
||||
"dice_rolled": "tiré au sort {0}",
|
||||
"dice_rolled_num": "Dés lancés : {0}",
|
||||
"dice_rolled_num": "Dés lancés: {0}",
|
||||
"changes_of_heart": "Changements d'avis",
|
||||
"claimed_by": "Réclamé par",
|
||||
"divorces": "Divorces",
|
||||
@@ -142,59 +142,59 @@
|
||||
"waifus_none": "Aucunes waifus n'ont encore été réclamées.",
|
||||
"waifus_top_waifus": "Meilleures Waifu",
|
||||
"waifu_claimed": "a revendiqué {0} comme sa waifu pour {1} !",
|
||||
"waifu_divorced_like": "Vous avez divorcé d'une waifu qui vous aimait. Espèce de monstre sans cœur. {0} a reçu {1} en compensation.",
|
||||
"waifu_egomaniac": "vous ne pouvez pas définir votre affinité pour vous-même, espèce d'égoïste.",
|
||||
"waifu_divorced_like": "Vous avez divorcé d'une waifu qui vous aimait. Vous n'êtes qu'un monstre sans cœur, {0} a reçu {1} en compensation.",
|
||||
"waifu_egomaniac": "vous ne pouvez pas tomber amoureux de vous-même, gros narcissique.",
|
||||
"waifu_fulfilled": "🎉 Leur amour est accompli 🎉\nLa nouvelle valeur de {0} est {1} !",
|
||||
"waifu_not_enough": "Vous devez payer {0} ou plus pour revendiquer cette waifu !",
|
||||
"waifu_not_yours": "Cette waifu n'est pas vôtre.",
|
||||
"waifu_not_yourself": "Vous ne pouvez pas vous revendiquer vous-même.",
|
||||
"waifu_recent_divorce": "Vous avez divorcé récemment. Vous devez attendre {0} heures et {1} minutes avant de divorcer à nouveau.",
|
||||
"waifu_recent_divorce": "Vous avez récemment divorcé. Vous devez attendre {0} heures et {1} minutes avant de pouvoir divorcer à nouveau.",
|
||||
"waifu_transfer_fail": "Vous n'êtes pas le propriétaire de cette waifu.",
|
||||
"waifu_transfer_success": "Le prétendant de {0} n'est plus {1} mais {2}.",
|
||||
"waifu_transfer_success": "La propriété de {0} a été transférée de {1} à {2}.",
|
||||
"nobody": "Personne",
|
||||
"waifu_divorced_notlike": "Vous avez divorcé d'une waifu qui ne vous aimait pas. Vous avez reçu {0} en compensation.",
|
||||
"waifu_reset": "Vous stats de waifu ont été remise à zéro.",
|
||||
"waifu_reset_fail": "Échec de la remise à zéro des stats de waifu. Assurez-vous d'avoir assez de devises.",
|
||||
"waifu_reset_confirm": "Ceci remettra à zéro vos stats de waifu",
|
||||
"waifu_reset": "Vos stats de waifu ont été réinitialisée.",
|
||||
"waifu_reset_fail": "Échec de la réinitialisation des stats de waifu. Assurez-vous d'avoir assez de devises.",
|
||||
"waifu_reset_confirm": "Cela réinitialisera vos stats de waifu",
|
||||
"acrophobia": "Acrophobie",
|
||||
"acro_ended_no_sub": "La partie s'est terminée sans soumissions.",
|
||||
"acro_no_votes_cast": "Aucun votes émis. La partie s'est terminée avec aucun gagnant.",
|
||||
"acro_nym_was": "L'acronyme était {0}.",
|
||||
"acro_running": "Une partie d'acrophobie est déjà en cours dans ce salon.",
|
||||
"acro_started": "La partie a commencée. Créez une phrase avec l'acronyme suivant: {0}.",
|
||||
"acro_started_footer": "Vous avez {0} pour faire une soumission.",
|
||||
"acro_running": "Une partie d'Acrophobia est déjà en cours dans ce salon.",
|
||||
"acro_started": "La partie a commencé. Créez une phrase avec l'acronyme suivant: {0}.",
|
||||
"acro_started_footer": "Vous avez {0} secondes pour faire une soumission.",
|
||||
"acro_vote": "Votez en tapant le numéro de la soumission",
|
||||
"acro_vote_cast": "{0} a voté !",
|
||||
"acro_vote_cast": "{0} a voté!",
|
||||
"acro_winner": "Le gagnant est {0} avec {1} points.",
|
||||
"acro_winner_only": "{0} est le gagnant puisqu'il est le seul à avoir participé !",
|
||||
"acro_winner_only": "{0} est le gagnant car il est le seul à avoir participé!",
|
||||
"question": "Question",
|
||||
"rps_draw": "C'est un match nul ! Les deux ont choisi {0}",
|
||||
"rps_win": "{0} a gagné ! {1} bats {2}",
|
||||
"rps_draw": "C'est un match nul! Les deux ont choisi {0}",
|
||||
"rps_win": "{0} a gagné! {1} bat {2}",
|
||||
"submissions_closed": "Soumissions fermées",
|
||||
"total_average": "Total: {0} Moyenne: {1}",
|
||||
"category": "Catégorie",
|
||||
"cleverbot_disabled": "Cleverbot désactivé dans ce salon.",
|
||||
"cleverbot_enabled": "Cleverbot activé dans ce salon.",
|
||||
"curgen_disabled": "La génération de devises a été désactivée dans ce salon.",
|
||||
"curgen_enabled": "La génération de devises a été activée dans ce salon.",
|
||||
"curgen_pl": "{0} {1} aléatoires sont apparues !",
|
||||
"curgen_sn": "Une {0} aléatoire est apparue !",
|
||||
"cleverbot_disabled": "Cleverbot est désactivé sur ce serveur.",
|
||||
"cleverbot_enabled": "Cleverbot est activé sur ce serveur.",
|
||||
"curgen_disabled": "La génération de devises a été désactivée sur ce salon.",
|
||||
"curgen_enabled": "La génération de devises a été activée sur ce salon.",
|
||||
"curgen_pl": "{0} {1} aléatoires sont apparues!",
|
||||
"curgen_sn": "Une {0} aléatoire est apparue!",
|
||||
"game_started": "La partie a commencée",
|
||||
"hangman_game_started": "La partie de pendu a commencée",
|
||||
"hangman_running": "Une partie de pendu est déjà en cours dans ce salon",
|
||||
"hangman_running": "Une partie de pendu est déjà en cours dans ce salon.",
|
||||
"hangman_types": "Liste des types de termes \"{0}hangman\":",
|
||||
"no_results": "Aucun résultats.",
|
||||
"picked": "a choisi {0}",
|
||||
"planted": "{0} a planté {1}",
|
||||
"trivia_already_running": "Une partie de Trivial Pursuit est déjà en cours sur ce serveur.",
|
||||
"trivia_game": "Jeu du Trivial Pursuit",
|
||||
"trivia_guess": "{0} a trouvé ! La réponse était: {1} ",
|
||||
"trivia_guess": "{0} a deviné! La réponse était: {1}",
|
||||
"trivia_none": "Aucun Trivial Pursuit est en cours sur ce serveur",
|
||||
"trivia_points": "{0} a {1} points",
|
||||
"trivia_stopping": "La partie s'arrêtera après cette question.",
|
||||
"trivia_times_up": "Fin du temps imparti ! La réponse correcte était {0}",
|
||||
"trivia_stopping": "La partie prendra fin après cette question.",
|
||||
"trivia_times_up": "Fin du temps imparti ! La bonne réponse était {0}",
|
||||
"ttt_against_yourself": "Vous ne pouvez pas jouer contre vous-même.",
|
||||
"ttt_already_running": "Une partie de morpion est déjà en cours dans ce salon.",
|
||||
"ttt_already_running": "Une partie de morpion est déjà en cours sur ce salon.",
|
||||
"ttt_a_draw": "Égalité !",
|
||||
"ttt_created": "a créé une partie de morpion.",
|
||||
"ttt_has_won": "{0} a gagné !",
|
||||
@@ -202,7 +202,7 @@
|
||||
"ttt_no_moves": "Aucun coups restants !",
|
||||
"ttt_time_expired": "Temps écoulé !",
|
||||
"ttt_users_move": "Au tour de {0}",
|
||||
"vs": "{0} vs {1}",
|
||||
"vs": "{0} contre {1}",
|
||||
"attempting_to_queue": "Tentative d'ajout de {0} morceaux à la file d'attente...",
|
||||
"fairplay": "Fair-play",
|
||||
"finished_song": "Morceau fini",
|
||||
@@ -214,36 +214,36 @@
|
||||
"no_search_results": "Aucuns résultats de recherche",
|
||||
"player_queue": "File d'attente du lecteur - Page {0}/{1}",
|
||||
"playing_song": "Lecture du morceau #{0}",
|
||||
"playlist_queue_complete": "La file d'attente de la playlist est terminée.",
|
||||
"queued_song": "Morceau mis en file d'attente",
|
||||
"playlist_queue_complete": "La file d'attente de la liste de lecture est terminée.",
|
||||
"queued_song": "Morceau ajouté à la file d'attente",
|
||||
"removed_song": "Morceau retiré",
|
||||
"repeating_track": "Répétition de la piste",
|
||||
"repeating_track": "Le lecteur continuera de jouer la même piste.",
|
||||
"volume_set": "Volume mis à {0}%",
|
||||
"acm_disable": "Désactivation de l'utilisation de TOUS LES MODULES dans le salon {0}.",
|
||||
"acm_enable": "Activation de l'utilisation de TOUS LES MODULES dans le salon {0}.",
|
||||
"arm_disable": "Désactivation de l'utilisation de TOUS LES MODULES pour le rôle {0}.",
|
||||
"arm_enable": "Activation de l'utilisation de TOUS LES MODULES pour le rôle {0}.",
|
||||
"asm_disable": "Désactivation de l'utilisation de TOUS LES MODULES sur ce serveur.",
|
||||
"asm_enable": "Activation de l'utilisation de TOUS LES MODULES sur ce serveur.",
|
||||
"aum_disable": "Désactivation de l'utilisation de TOUS LES MODULES pour le membre {0}.",
|
||||
"aum_enable": "Activation de l'utilisation de TOUS LES MODULES pour le membre {0}.",
|
||||
"blacklisted": "{0} mis sur liste noire avec les IDs : {1}",
|
||||
"unblacklisted": "{0} retirés de la liste noire avec les IDs : {1}",
|
||||
"acm_disable": "Utilisation de TOUS LES MODULES **désactivée** sur le salon {0}.",
|
||||
"acm_enable": "Utilisation de TOUS LES MODULES **activée** sur le salon {0}.",
|
||||
"arm_disable": "Utilisation de TOUS LES MODULES **désactivée** pour le rôle {0}.",
|
||||
"arm_enable": "Utilisation de TOUS LES MODULES **activée** pour le rôle {0}.",
|
||||
"asm_disable": "Utilisation de TOUS LES MODULES **désactivée** sur ce serveur.",
|
||||
"asm_enable": "Utilisation de TOUS LES MODULES **activée** sur ce serveur.",
|
||||
"aum_disable": "Utilisation de TOUS LES MODULES **désactivée** pour le membre {0}.",
|
||||
"aum_enable": "Utilisation de TOUS LES MODULES **activée** pour le membre {0}.",
|
||||
"blacklisted": "{0} est inscrit sur la liste noire avec l'ID {1}",
|
||||
"unblacklisted": "{0} est retiré de la liste noire avec l'ID {1}",
|
||||
"cmdcd_add": "La commande {0} a désormais un temps de recharge de {1}s",
|
||||
"cmdcd_cleared": "Commande {0} ne possède plus de cooldown et tous les cooldowns existants ont été supprimés",
|
||||
"cmdcd_none": "Aucuns temps de recharge pour commande réglé.",
|
||||
"cx_disable": "Utilisation de {0} {1} interdite dans le salon {2}",
|
||||
"cx_enable": "Utilisation de {0} {1} autorisé dans le salon {2}",
|
||||
"filter_word_add": "Mot {0} ajouté à la liste des mots filtrés.",
|
||||
"cmdcd_cleared": "La commande {0} ne possède plus de temps de recharge et tous ceux existants ont été retirés.",
|
||||
"cmdcd_none": "Aucun temps de recharge n'est programmé.",
|
||||
"cx_disable": "L'utilisation de {0} {1} est désactivée sur le salon {2}.",
|
||||
"cx_enable": "L'utilisation de {0} {1} est autorisée sur le salon {2}.",
|
||||
"filter_word_add": "Le mot {0} a été ajouté à la liste des mots filtrés.",
|
||||
"filter_word_list": "Liste des mots filtrés",
|
||||
"filter_word_remove": "Mot {0} retiré de la liste des mots filtrés.",
|
||||
"invalid_second_param_between": "Second paramètre invalide. (Doit être un nombre entre {0} et {1})",
|
||||
"invite_filter_channel_off": "Filtre d'invitation désactivé sur ce salon.",
|
||||
"filter_word_remove": "Le mot {0} a été retiré de la liste des mots filtrés.",
|
||||
"invalid_second_param_between": "Le second paramètre est invalide. (Doit être un nombre entre {0} et {1})",
|
||||
"invite_filter_channel_off": "Le filtre d'invitation est désactivé sur ce salon.",
|
||||
"invite_filter_channel_on": "Filtre d'invitation activé sur ce salon.",
|
||||
"invite_filter_server_off": "Filtre d'invitation désactivé sur ce serveur.",
|
||||
"invite_filter_server_on": "Filtre d'invitation activé sur ce serveur.",
|
||||
"moved_permission": "Permission {0} déplacée de {1} à {2}",
|
||||
"perm_not_found": "Impossible de trouver de permission à l'index #{0}",
|
||||
"perm_not_found": "Impossible de trouver de permission dans l'index #{0}",
|
||||
"of_command": "commande",
|
||||
"of_module": "module",
|
||||
"page": "page {0}",
|
||||
@@ -251,7 +251,7 @@
|
||||
"permrole_not_set": "Le rôle de permission n'est pas défini.",
|
||||
"permrole_reset": "Le rôle de permission est réinitialisé.",
|
||||
"permrole_changed": "Les utilisateurs ont désormais besoin du rôle {0} pour modifier les permissions.",
|
||||
"perm_out_of_range": "Aucune permission trouvé sur cet index.",
|
||||
"perm_out_of_range": "Aucune permission trouvée sur cet index.",
|
||||
"removed": "permission retirée #{0} - {1}",
|
||||
"rx_disable": "Usage désactivé de {0} {1} pour {2} rôle.",
|
||||
"rx_enable": "Usage activé de {0} {1} pour {2} rôle.",
|
||||
@@ -263,10 +263,10 @@
|
||||
"ux_enable": "Usage activé de {0} {1} pour {2} utilisateur.",
|
||||
"verbose_false": "Je n'afficherai plus les alertes de permissions.",
|
||||
"verbose_true": "J'afficherai dorénavant les alertes de permissions.",
|
||||
"word_filter_channel_off": "Filtre des mots désactivé dans ce salon.",
|
||||
"word_filter_channel_on": "Filtre des mots activé sur ce salon.",
|
||||
"word_filter_server_off": "Filtrage des mots désactivé sur ce serveur.",
|
||||
"word_filter_server_on": "Filtrage des mots activé sur ce serveur.",
|
||||
"word_filter_channel_off": "Le filtre du langage est désactivé sur ce salon.",
|
||||
"word_filter_channel_on": "Le filtre du langage est activé sur ce salon.",
|
||||
"word_filter_server_off": "Le filtre du langage est désactivé sur ce serveur.",
|
||||
"word_filter_server_on": "Le filtre du langage est activé sur ce serveur.",
|
||||
"abilities": "Aptitudes",
|
||||
"chapters": "Chapitres",
|
||||
"comic_number": "Bande dessinée #",
|
||||
@@ -288,8 +288,8 @@
|
||||
"timezone": "Fuseau horaire",
|
||||
"min_max": "Min/Max",
|
||||
"original_url": "Url originale",
|
||||
"pokemon_ability_none": "Aucune aptitude trouvée",
|
||||
"pokemon_none": "Aucun pokémon trouvé",
|
||||
"pokemon_ability_none": "Aucune aptitude trouvée.",
|
||||
"pokemon_none": "Aucun pokémon trouvé.",
|
||||
"rating": "Évaluation",
|
||||
"score": "Score:",
|
||||
"search_for": "Recherche pour:",
|
||||
@@ -300,7 +300,7 @@
|
||||
"temperature": "Température",
|
||||
"types": "Types",
|
||||
"url": "Url",
|
||||
"wind_speed": "Force du vent",
|
||||
"wind_speed": "Vitesse du vent",
|
||||
"author": "Auteur",
|
||||
"botid": "ID du bot",
|
||||
"channelid": "{0} de ce salon est {1}.",
|
||||
@@ -329,9 +329,9 @@
|
||||
"nobody_playing_game": "Personne ne joue à ce jeu.",
|
||||
"no_topic_set": "Aucun thème réglé",
|
||||
"owner": "Propriétaire",
|
||||
"owner_ids": "Identifiant(s) Propriétaire(s)",
|
||||
"owner_ids": "Identifiant·s Propriétaire·s",
|
||||
"region": "Région",
|
||||
"remind": "Je rappellerai à {0} de {1} dans {2} `({3:d.M.yyyy.} at {4:HH:mm})`",
|
||||
"remind": "Je rappellerai à {0} de {1} dans {2} `(le {3:d.M.yyyy.} à {4:HH:mm}h)`",
|
||||
"remind_too_long": "Le temps de rappel dépasse le maximum.",
|
||||
"repeaters_none": "Pas de répétiteur en cours sur ce serveur.",
|
||||
"repeat_invoke_none": "Aucune répétition de messages trouvé sur ce serveur.",
|
||||
@@ -339,10 +339,10 @@
|
||||
"roles": "Rôles",
|
||||
"serverid": "{0} de ce serveur est {1}",
|
||||
"server_info": "Info du serveur",
|
||||
"shard": "Shard",
|
||||
"shard": "Fragment",
|
||||
"showemojis_none": "Pas d'emojis spéciaux trouvés.",
|
||||
"text_channels": "Salons textuels",
|
||||
"uptime": "Uptime",
|
||||
"uptime": "Temps de fonctionnement",
|
||||
"userid": "{0} de l'utilisateur {1} est {2}",
|
||||
"roleid": "{0} du rôle {1} est {2}",
|
||||
"voice_channels": "Salons vocaux",
|
||||
@@ -356,22 +356,22 @@
|
||||
"pick_pl": "Récupérez les en tapant `{0}pick`",
|
||||
"pick_sn": "Récupérez la en tapant `{0}pick`",
|
||||
"sql_confirm_exec": "Confirmez l'exécution de la commande SQL suivante",
|
||||
"no_vcroles": "Il n'y a pas de rôle pour le salon vocal.",
|
||||
"user_muted_time": "{0} ne peux plus écrire ni parler pendant {1} minutes.",
|
||||
"vcrole_added": "Les utilisateurs qui rejoindrons le salon vocal {0} obtiendrons le rôle {1}.",
|
||||
"vcrole_removed": "Les utilisateurs qui rejoindrons le salon vocal {0} n'obtiendrons plus de rôle.",
|
||||
"no_vcroles": "Il n'y a pas de rôles pour les salons vocaux.",
|
||||
"user_muted_time": "{0} a été **rendu muet** à l'écrit et à l'oral pour {1} minutes.",
|
||||
"vcrole_added": "Les utilisateurs qui rejoindront le salon vocal {0} obtiendront le rôle {1}.",
|
||||
"vcrole_removed": "Les utilisateurs qui rejoindront le salon vocal {0} n'obtiendront plus de rôle.",
|
||||
"vc_role_list": "Rôles du salon vocal",
|
||||
"option_disabled": "L'option {0} est maintenant désactivée pour l'expression avec l'ID {1}.",
|
||||
"option_enabled": "L'option {0} est désormais activée pour l'expression avec l'ID {1}.",
|
||||
"channel": "Salons",
|
||||
"command_text": "Texte de commande",
|
||||
"option_disabled": "L'option {0} est maintenant **désactivée** pour la réaction personnalisée dont l'ID est {1}.",
|
||||
"option_enabled": "L'option {0} est désormais **activée** pour la réaction personnalisée dont l'ID est {1}.",
|
||||
"channel": "Salon",
|
||||
"command_text": "Commande textuelle",
|
||||
"moderator": "Modérateur",
|
||||
"reason": "Raison",
|
||||
"scadd": "Nouvelle commande de démarrage ajoutée.",
|
||||
"scrm": "Commande de démarrage retirée avec succès.",
|
||||
"scrm_fail": "Commande de démarrage non trouvée.",
|
||||
"server": "Server",
|
||||
"startcmdlist_none": "Pas de commandes de démarrage sur cette page.",
|
||||
"server": "Serveur",
|
||||
"startcmdlist_none": "Aucune commandes de démarrage trouvée sur cette page.",
|
||||
"startcmds_cleared": "Toutes les commandes de démarrage ont été effacées.",
|
||||
"unbanned_user": "L'utilisateur {0} à été débanni.",
|
||||
"user_not_found": "Utilisateur introuvable.",
|
||||
@@ -380,25 +380,25 @@
|
||||
"warned_on": "Avertissement envoyé sur le serveur {0}",
|
||||
"warned_on_by": "Le {0} à {1} par {2}",
|
||||
"warnings_cleared": "Tous les avertissements ont été effacés pour {0}.",
|
||||
"warning_clear_fail": "Avertissement non effacé. Soit l'avertissement à cet index n'existe pas, soit il a déjà été effacé.",
|
||||
"warning_clear_fail": "Avertissement non effacé. Soit l'avertissement sur cet index n'existe pas, soit il a déjà été effacé.",
|
||||
"warning_cleared": "L'avertissement {0} a été effacé pour {1}.",
|
||||
"warnings_none": "Aucun avertissement sur cette page.",
|
||||
"warnlog_for": "Journal d'avertissement pour {0}",
|
||||
"warnpl_none": "Aucun châtiment réglé.",
|
||||
"warn_cleared_by": "Effacé par {0}",
|
||||
"warn_punish_list": "Liste des avertissements de punition",
|
||||
"warn_punish_rem": "Avoir {0} avertissement ne déclenche plus une punition.",
|
||||
"warn_punish_set": "J'appliquerais la sanction {0} pour les utilisateurs avec {1} avertissements.",
|
||||
"cant_apply_punishment": "Je ne peux pas appliquer la sanction. Vérifiez mes permissions ou bien que mon rôle est bien au-dessus.",
|
||||
"clpa_fail_already": "Vous avez peut-être déjà reçu votre récompense pour ce mois. Vous ne pouvez recevoir des récompenses seulement qu'une fois par mois, sauf si vous augmentez votre engagement.\nVous pouvez vérifier cela avec la commande `.curtrs`.",
|
||||
"warn_punish_list": "Liste des avertissements punitifs",
|
||||
"warn_punish_rem": "Avoir {0} avertissements ne déclenche plus une punition.",
|
||||
"warn_punish_set": "J'appliquerai la sanction {0} pour les utilisateurs avec {1} avertissements.",
|
||||
"cant_apply_punishment": "Je ne peux pas appliquer la sanction. Veuillez vérifiez mes permissions ainsi que la place de mon rôle, qu'il soit au-dessus des autres dans les paramètres du serveur.",
|
||||
"clpa_fail_already": "Vous avez peut-être déjà reçu votre récompense pour ce mois. Vous pouvez recevoir des récompenses qu'une seule fois par mois, sauf si vous augmentez votre engagement.\nVous pouvez vérifier cela avec la commande `.curtrs`.",
|
||||
"clpa_fail_already_title": "Déjà récompensé",
|
||||
"clpa_fail_conn": "Votre compte Discord n'est peut-être pas connecté à Patreon. Si vous ne savez pas ce que cela signifie ou ne savez pas comment le connecter, vous devez vous rendre sur [Patreon account settings page](https://patreon.com/settings/account) et cliquer sur le bouton 'Connect to discord'.",
|
||||
"clpa_fail_conn": "Votre compte Discord n'est peut-être pas connecté à Patreon. Si vous ne savez pas ce que cela signifie ou ne savez pas comment le connecter, vous devez vous rendre sur [Patreon account settings page](https://patreon.com/settings/account) et cliquer sur le bouton '« Connect to discord »'.",
|
||||
"clpa_fail_conn_title": "Compte Discord non connecté",
|
||||
"clpa_fail_sup": "Pour être éligible à la récompense, vous devez soutenir le projet sur Patreon. Vous pouvez utiliser la commande {0} pour obtenir le lien.",
|
||||
"clpa_fail_sup_title": "Non supporté",
|
||||
"clpa_fail_wait": "Vous devez attendre 5-10 minutes après votre engagement (ainsi que connecter votre compte discord à votre patreon) pour que votre devise apparaisse.",
|
||||
"clpa_fail_wait": "Vous devez attendre 5-10 minutes après votre engagement (ainsi qu'avoir connecté votre compte discord à votre patreon) pour que vos devises apparaissent.",
|
||||
"clpa_fail_wait_title": "Attendez quelque temps",
|
||||
"clpa_too_early": "Les récompenses peuvent être réclamées tout les 5 du mois.",
|
||||
"clpa_too_early": "Les récompenses ne peuvent être réclamées que tous les 5ème jours du mois.",
|
||||
"shop": "Boutique",
|
||||
"shop_item_add": "Article ajouté à la boutique",
|
||||
"shop_none": "Aucun article de boutique trouvé sur cette page.",
|
||||
@@ -408,39 +408,39 @@
|
||||
"gvc_disabled": "La fonctionnalité Salon Vocal de Jeu a été désactivée sur ce serveur.",
|
||||
"gvc_enabled": "{0} est désormais un Salon Vocal de Jeu.",
|
||||
"not_in_voice": "Vous n'êtes pas dans un salon vocal sur ce serveur.",
|
||||
"item": "Objet",
|
||||
"item": "Article",
|
||||
"out_of_stock": "En rupture de stock",
|
||||
"random_unique_item": "Objet aléatoire unique.",
|
||||
"shop_buy_error": "Echec de l'envoi de l'item par DM. Vous avez été remboursé.",
|
||||
"shop_item_not_found": "Aucun élément de cet index n'a été trouvé.",
|
||||
"shop_item_purchase": "Item acheté avec succès.",
|
||||
"shop_item_rm": "Élément de la boutique supprimé",
|
||||
"shop_buy_error": "Échec de l'envoi de l'article par MP. Vous avez été remboursé.",
|
||||
"shop_item_not_found": "Aucun article de cet index n'a été trouvé.",
|
||||
"shop_item_purchase": "Article acheté avec succès.",
|
||||
"shop_item_rm": "Article supprimé de la boutique.",
|
||||
"shop_item_wrong_type": "Cette entrée de boutique ne prend pas en charge l'ajout d'articles.",
|
||||
"shop_list_item_added": "Article ajouté avec succès.",
|
||||
"shop_list_item_not_unique": "Cet article a déjà été ajouté.",
|
||||
"shop_purchase": "Acheter sur le serveur {0}",
|
||||
"shop_role_not_found": "Le rôle qui est vendu n'existe plus.",
|
||||
"shop_role_not_found": "Le rôle qui se vendait n'existe plus.",
|
||||
"role_not_found": "Rôle introuvable : {0}",
|
||||
"shop_role_purchase": "Vous avez acheté le rôle {0}>",
|
||||
"shop_role_purchase": "Vous avez acheté le rôle {0}.",
|
||||
"shop_role_purchase_error": "Une erreur est survenue lors de l'assignation du rôle. Votre achat a été remboursé.",
|
||||
"unique_items_left": "{0} objets uniques restants.",
|
||||
"unique_items_left": "Il reste {0} articles uniques.",
|
||||
"blocked_commands": "Commandes bloquées",
|
||||
"blocked_modules": "Modules bloqués",
|
||||
"gcmd_add": "La commande {0} a été désactivée sur tout les serveurs.",
|
||||
"gcmd_remove": "La commande {0} a été activée sur tout les serveurs.",
|
||||
"gmod_add": "Le module {0} a été désactivé sur tout les serveurs.",
|
||||
"gmod_remove": "Le module {0} a été activé sur tout les serveurs.",
|
||||
"lgp_none": "Aucune commande ou module bloqué.",
|
||||
"cant_read_or_send": "Vous ne pouvez pas lire ou envoyer des messages à ce salon.",
|
||||
"gcmd_add": "La commande {0} a été **désactivée** sur tous les serveurs.",
|
||||
"gcmd_remove": "La commande {0} a été **activée** sur tous les serveurs.",
|
||||
"gmod_add": "Le module {0} a été **désactivé** sur tous les serveurs.",
|
||||
"gmod_remove": "Le module {0} a été **activé** sur tout les serveurs.",
|
||||
"lgp_none": "Aucunes commandes ou modules bloqués.",
|
||||
"cant_read_or_send": "Vous ne pouvez pas lire ou envoyer des messages sur ce salon.",
|
||||
"prefix_current": "Le préfixe sur ce serveur est {0}",
|
||||
"defprefix_current": "Le préfixe par défaut du bot est {0}",
|
||||
"timezone_guild": "Le fuseau horaire de ce serveur est `{0}`",
|
||||
"timezone_not_found": "Fuseau horaire introuvable. Utilisez la commande \"fuseau horaire\" pour voir la liste des fuseaux horaires disponible.",
|
||||
"timezones_available": "Fuseaux horaires disponible",
|
||||
"song_not_found": "Chanson non trouvée",
|
||||
"timezone_not_found": "Fuseau horaire introuvable. Utilisez la commande \"fuseau horaire\" pour voir la liste des fuseaux horaires disponibles.",
|
||||
"timezones_available": "Fuseaux horaires disponibles.",
|
||||
"song_not_found": "Chanson non trouvée.",
|
||||
"not_found": "Introuvable.",
|
||||
"verbose_errors_enabled": "Les erreurs de commande non gérées seront désormais affichées dans le tchat.",
|
||||
"verbose_errors_disabled": "Les erreurs de commande non gérées ne s'afficheront plus dans le tchat.",
|
||||
"verbose_errors_enabled": "Les commandes mal utilisées afficheront désormais un message d'erreur.",
|
||||
"verbose_errors_disabled": "Les commandes mal utilisées n'afficheront plus de message d'erreur.",
|
||||
"perms_reset": "Les permissions pour ce serveur ont été réinitialisées.",
|
||||
"perm_prevent": "Le numéro d'autorisation # {0} {1} empêche cette action.",
|
||||
"global_perms_reset": "Les permissions globales ont été réinitialisées.",
|
||||
@@ -452,60 +452,60 @@
|
||||
"waifu_gift_shop": "Boutique de cadeaux pour waifu",
|
||||
"gifts": "Cadeaux",
|
||||
"connect4_created": "Création d'une partie de Connect4. En attente d'un joueur.",
|
||||
"connect4_created_bet": "Vous avez créé un partie de Connect4 et misez {0}. Attendez qu'un joueur rejoigne avec le même pari.",
|
||||
"connect4_created_bet": "Vous avez créé un partie de Connect4 et vous misez {0}. En attente qu'un joueur rejoigne avec le même pari.",
|
||||
"connect4_player_to_move": "Joueurs à déplacer: {0}",
|
||||
"connect4_failed_to_start": "La partie de Connect4 n'a pas pu démarrer car personne ne l'a rejoint.",
|
||||
"connect4_draw": "La partie de Connect4 a fini sur une égalité.",
|
||||
"connect4_won": "{0} a gagné la partie de Connect4 contre {1}.",
|
||||
"nunchi_joined": "Vous avez rejoint la partie de Nunchi. {0} utilisateurs ont joints jusqu'à présent.",
|
||||
"nunchi_ended": "Le partie de Nunchi s'est terminé. {0} gagné",
|
||||
"nunchi_ended": "Le partie de Nunchi s'est terminé. {0} a gagné",
|
||||
"nunchi_ended_no_winner": "Le partie de Nunchi s'est terminé sans vainqueur.",
|
||||
"nunchi_round_ended": "Fin du round de Nunchi. {0} est hors jeu.",
|
||||
"nunchi_round_ended_boot": "Le round de Nunchi s'est terminé en raison du timeout de certains utilisateurs. Ces utilisateurs sont toujours dans le jeu: {0}",
|
||||
"nunchi_round_started": "Le round de Nunchi a commencé avec {0} utilisateurs. Commencez à compter à partir du nombre {1}.",
|
||||
"nunchi_round_ended": "Fin de la manche de Nunchi. {0} est éliminé·e.",
|
||||
"nunchi_round_ended_boot": "La manche de Nunchi s'est terminé en raison de l'inactivité de certains utilisateurs. Ces utilisateurs sont toujours dans le jeu: {0}",
|
||||
"nunchi_round_started": "La manche de Nunchi a commencé avec {0} utilisateurs. Commencez à compter à partir du nombre {1}.",
|
||||
"nunchi_next_number": "Numéro enregistré. Le dernier numéro était {0}.",
|
||||
"nunchi_failed_to_start": "La partie de Nunchi n'a pas pu démarrer car il n'y avait pas assez de participants.",
|
||||
"nunchi_created": "Une partie de Nunchi ",
|
||||
"nunchi_created": "Une partie de Nunchi a été créé. En attente de la participation d'autres utilisateurs.",
|
||||
"stream_role_enabled": "Lorsqu'un utilisateur du rôle {0} commence à diffuser, je lui donne le rôle {1}.",
|
||||
"stream_role_disabled": "La fonction de rôle streamer a été désactivée.",
|
||||
"stream_role_kw_set": "Les streamers nécessitent désormais {0} mot-clé pour recevoir le rôle.",
|
||||
"stream_role_kw_reset": "Réinitialisation des mots clé du rôle streamer.",
|
||||
"stream_role_bl_add": "L'utilisateur {0} ne recevra jamais le rôle streamer.",
|
||||
"stream_role_bl_add_fail": "L'utilisateur {0} est déjà blacklisté.",
|
||||
"stream_role_bl_rem": "L'utilisateur {0} n'est plus blacklisté.",
|
||||
"stream_role_bl_rem_fail": "L'utilisateur {0} n'est pas blacklisté.",
|
||||
"stream_role_wl_add": "L'utilisateur {0} recevra le rôle streamer même s'il n'a pas le mot-clé dans le titre du stream.",
|
||||
"stream_role_disabled": "La fonction de rôle diffuseur a été **désactivée**.",
|
||||
"stream_role_kw_set": "Les diffuseurs nécessitent désormais le mot-clé {0} pour recevoir le rôle.",
|
||||
"stream_role_kw_reset": "Réinitialisation des mots-clés du rôle diffuseur.",
|
||||
"stream_role_bl_add": "L'utilisateur {0} ne recevra jamais le rôle de diffuseur.",
|
||||
"stream_role_bl_add_fail": "L'utilisateur {0} est déjà sur la liste noire.",
|
||||
"stream_role_bl_rem": "L'utilisateur {0} n'est plus sur la liste noire.",
|
||||
"stream_role_bl_rem_fail": "L'utilisateur {0} n'est pas sur la liste noire.",
|
||||
"stream_role_wl_add": "L'utilisateur {0} recevra le rôle de diffuseur même s'il manque le mot-clé dans le titre du stream.",
|
||||
"stream_role_wl_add_fail": "L'utilisateur {0} est déjà sur la liste blanche.",
|
||||
"stream_role_wl_rem": "L'utilisateur {0} n'est plus sur liste blanche.",
|
||||
"stream_role_wl_rem_fail": "L'utilisateur {0} n'est pas sur liste blanche.",
|
||||
"xp_role_reward_add_role": "L'utilisateur qui atteint le niveau {0} recevra le rôle {1}",
|
||||
"xp_role_reward_remove_role": "L'utilisateur qui atteint le level {0} perdra le rôle {1}",
|
||||
"cur_reward_cleared": "Atteindre le niveau {0} n'offrera plus aucune {0}.",
|
||||
"xp_role_reward_add_role": "L'utilisateur qui atteint le niveau {0} recevra le rôle {1}.",
|
||||
"xp_role_reward_remove_role": "Les utilisateurs qui atteindront le niveau {0} perdront le rôle {1}.",
|
||||
"cur_reward_cleared": "Atteindre le niveau {0} n'offrera plus aucune {1}.",
|
||||
"cur_reward_added": "Les utilisateurs atteignants le niveau {0} recevront {1}.",
|
||||
"level_up_rewards": "Récompenses de monté de niveau",
|
||||
"xp_receive_role": "Reçoit le rôle {0}.",
|
||||
"xp_lose_role": "Perd le rôle {0}",
|
||||
"club_create_error": "Echec de la création du club. Vérifier que vous êtes niveau 5 et plus ou que vous n'êtes pas déjà membre d'un club.",
|
||||
"club_create_error": "Échec de la création du club. Vérifier que vous êtes au minimum niveau 5 ou que vous n'êtes pas déjà membre d'un club.",
|
||||
"club_created": "Club {0} créé avec succès !",
|
||||
"club_not_exists": "Ce club n'existe pas.",
|
||||
"club_applied": "Vous avez candidaté pour le club {0}.",
|
||||
"club_apply_error": "Erreur lors de l'envoie de la candidature. Soit vous faites déjà partie d'un club, soit vous ne possédez pas le niveau minimum requis ou sinon vous avez été banni de ce club.",
|
||||
"club_apply_error": "Erreur lors de l'envoie de la candidature. Soit vous faites déjà partie d'un club, soit vous ne possédez pas le niveau requis ou vous avez été banni de ce club.",
|
||||
"club_accepted": "L'utilisateur {0} a été accepté dans le club.",
|
||||
"club_accept_error": "L'utilisateur est introuvable",
|
||||
"club_left": "Vous avez quitté le club.",
|
||||
"club_not_in_club": "Vous n'êtes pas dans un club, ou vous essayez de quitter le club dont vous êtes le propriétaire.",
|
||||
"club_user_kick": "L'utilisateur {0} a été exclu du club {1} .",
|
||||
"club_user_kick_fail": "Impossible d'exclure l'utilisateur. Vous n'êtes pas le propriétaire du club, où l'utilisateur n'est pas dans votre club.",
|
||||
"club_user_banned": "L'utilisateur {0} a été banni du club {1}",
|
||||
"club_user_kick_fail": "Impossible d'exclure l'utilisateur. Vous n'êtes pas le propriétaire du club, ou l'utilisateur n'est pas dans votre club.",
|
||||
"club_user_banned": "L'utilisateur {0} a été banni du club {1}.",
|
||||
"club_user_ban_fail": "Échec du bannissement. Vous n'êtes pas le propriétaire, ou cet utilisateur n'est pas dans votre club.",
|
||||
"club_user_unbanned": "L'utilisateur {0} a été débanni du club {1}.",
|
||||
"club_user_unban_fail": "Échec du débanissement. Vous n'êtes pas le propriétaire, ou cet utilisateur n'est pas dans votre club.",
|
||||
"club_level_req_changed": "Changement du niveau requis à {0}",
|
||||
"club_user_unban_fail": "Échec du débannissement. Vous n'êtes pas le propriétaire, ou cet utilisateur n'est pas dans votre club.",
|
||||
"club_level_req_changed": "Le niveau requis du club a été changé sur {0}",
|
||||
"club_level_req_change_error": "Échec du changement du niveau requis.",
|
||||
"club_desc_updated": "Description du coup mise à jour : {0}",
|
||||
"club_desc_updated": "La description du club est désormais « {0} ».",
|
||||
"club_desc_update_failed": "Échec du changement de la description du club.",
|
||||
"club_disbanded": "Le club {0} a été dissout",
|
||||
"club_disband_error": "Erreur. Soit vous n'êtes pas dans un club ou soit vous n'êtes pas le propriétaire du club.",
|
||||
"club_disband_error": "Erreur. Soit vous n'êtes pas dans un club ou vous n'êtes pas le propriétaire du club.",
|
||||
"club_icon_error": "L'URL de l'image n'est pas valide ou vous n'êtes pas le propriétaire du club.",
|
||||
"club_icon_set": "Nouvel icône de club défini.",
|
||||
"club_bans_for": "Liste des bans pour le club {0}",
|
||||
@@ -518,7 +518,7 @@
|
||||
"event_duration_footer": "L'événement se fini dans {0} heures.",
|
||||
"start_event_fail": "Échec de l'événement. Un événement est déjà en cours, où il y a une erreur avec le démarrage de l'événement.",
|
||||
"event_title": "L'évènement {0} a commencé !",
|
||||
"poll_closed": "Le sondage Clos !",
|
||||
"poll_closed": "Le sondage est clos !",
|
||||
"club_not_exists_owner": "Vous n'êtes ni le propriétaire ni l'administrateur de ce club.",
|
||||
"club_admin_add": "{0} est désormais administrateur du club.",
|
||||
"club_admin_remove": "{0} n'est plus administrateur du club.",
|
||||
@@ -530,10 +530,10 @@
|
||||
"feed_no_feed": "Vous n'avez souscrit à aucun fil d'actualité sur ce serveur.",
|
||||
"timely_none": "Le propriétaire de ce bot n'a pas spécifié de récompense récurrente.",
|
||||
"timely_already_claimed": "Vous avez déjà obtenu votre récompense récurrente. Vous pourrez l'obtenir de nouveau dans {0}.",
|
||||
"timely": "Vous venez de réclamer vos {0}. Vous pourrez réclamer a nouveau dans {1}h.",
|
||||
"timely": "Vous venez de réclamer vos {0}. Vous pourrez réclamer à nouveau dans {1}h.",
|
||||
"timely_set": "Les utilisateurs pourront réclamer {0} toutes les {1}h.",
|
||||
"timely_set_none": "Les utilisateurs ne pourront réclamer aucune monnaie récurrente.",
|
||||
"timely_reset": "Tous les utilisateurs peuvent réclamer leur monnaie récurrente de nouveau.",
|
||||
"timely_set_none": "Les utilisateurs ne pourront réclamer aucune devise récurrente.",
|
||||
"timely_reset": "Tous les utilisateurs peuvent réclamer leur devise récurrente de nouveau.",
|
||||
"market_cap": "Capitalisation Boursière",
|
||||
"volume_24h": "Volume (24h)",
|
||||
"change_7d_24h": "Change (7j/24h)",
|
||||
@@ -558,13 +558,13 @@
|
||||
"bj_joined": "a rejoint la partie de BlackJack",
|
||||
"no_invites": "Aucune invitation sur cette page.",
|
||||
"invite_deleted": "L'invitation {0} a été supprimée.",
|
||||
"deleted": "Réaction personnalisée supprimée",
|
||||
"deleted": "La réaction personnalisée a été supprimée.",
|
||||
"insuff_perms": "Permissions insuffisantes. Vous devez être le détenteur du bot pour les réactions personnalisées globales ou administrateur pour celles du serveur.",
|
||||
"custom_reactions": "Réactions personnalisées",
|
||||
"new_cust_react": "Nouvelle réaction personnalisée",
|
||||
"no_found": "Aucune réaction personnalisée trouvée.",
|
||||
"no_found_id": "Aucune réaction personnalisée trouvée avec cet ID.",
|
||||
"cleared": "{0} réaction personnalisées ont été supprimées.",
|
||||
"cleared": "L'ensemble des {0} réactions personnalisées ont été supprimées.",
|
||||
"crr_reset": "La réaction personnalisée d'ID {0} n'ajoutera désormais plus de réactions.",
|
||||
"crr_set": "La réaction personnalisée d'ID {0} ajoutera les réactions suivantes au message de réponse : {1}",
|
||||
"invalid_emojis": "Tous les emojis spécifiés sont invalides.",
|
||||
@@ -572,9 +572,9 @@
|
||||
"vcrole_not_found": "Ce salon vocal n'a pas de VcRole.",
|
||||
"attachments": "Pièces jointes",
|
||||
"avatar_changed": "Avatar changé",
|
||||
"banmsg_disabled": "Les messages d'exclusion sont désactivés. Vous pouvez les activer en définissant banmsg autrement que '-'.",
|
||||
"banmsg_default": "Aucun message d'exclusion défini. La conduite par défaut sera appliquée.",
|
||||
"banned_pl": "Exclu",
|
||||
"banmsg_disabled": "Les messages d'exclusion sont désactivés. Vous pouvez les activer en définissant banmsg autrement qu'avec '-'.",
|
||||
"banmsg_default": "Aucun message de bannissement défini. La conduite par défaut sera appliquée.",
|
||||
"banned_pl": "banni",
|
||||
"bot_name": "Le nom du bot a été changé pour {0}",
|
||||
"bot_status": "Le statut du bot a été changé pour {0}",
|
||||
"ch_name_change": "Nom de salon modifié",
|
||||
@@ -588,57 +588,55 @@
|
||||
"insuf_perms_i": "Mes permissions sont insuffisantes.",
|
||||
"insuf_perms_u": "Vos permissions sont insuffisantes.",
|
||||
"lang_set_fail": "Échec de la définition des paramètres régionaux. Revoyez l'aide de cette commande.",
|
||||
"lang_set_show": "La langue de ce serveur est défini sur {0} - {1}",
|
||||
"lang_set_show": "La langue de ce serveur est définie sur {0} - {1}",
|
||||
"log": "Journalisation des évènements de {0} dans ce salon.",
|
||||
"log_all": "Journalisation de tout les évènements dans ce salon.",
|
||||
"log_all": "Journalisation de tous les évènements dans ce salon.",
|
||||
"log_disabled": "Journalisation désactivée.",
|
||||
"log_events": "Evènements de journalisation auxquels vous pouvez vous abonner :",
|
||||
"log_ignore": "La journalisation ignorera {0}",
|
||||
"log_not_ignore": "La journalisation n'ignorera pas {0}",
|
||||
"log_stop": "La journalisation de l'évènement {0} arrêtée.",
|
||||
"msg_not_found": "Message introuvable.",
|
||||
"time_too_long": "Le temps spécifié est trop long.",
|
||||
"log_vc_moved": "{0} à été déplacé du salon vocal {1} à {2}",
|
||||
"msg_del": "Message supprimé dans #{0}",
|
||||
"msg_update": "Message mise-à-jour dans #{0}",
|
||||
"msg_update": "Message mis à jour dans #{0}",
|
||||
"muted_pl": "Muets",
|
||||
"muted_sn": "Muet",
|
||||
"mute_role": "Rôle muet actuel est {0}",
|
||||
"mute_perms": "Vous ne pouvez pas mettre en sourdine un utilisateur dont le rôle est au-dessus du vôtre, sauf si vous êtes le propriétaire du serveur.",
|
||||
"mute_role": "Le rôle muet actuel est {0}",
|
||||
"mute_perms": "Vous ne pouvez pas rendre muet un utilisateur dont le rôle est au-dessus du vôtre, sauf si vous êtes le propriétaire du serveur.",
|
||||
"new_msg": "Nouveau message",
|
||||
"new_nick": "Nouveau surnom",
|
||||
"new_topic": "Nouveau thème",
|
||||
"new_topic": "Nouveau sujet",
|
||||
"nick_change": "Surnom modifié",
|
||||
"no_shard_id": "Aucune shard avec cet ID n'a été trouvée.",
|
||||
"nsfw_set_true": "Le NSFW est activé sur ce salon.",
|
||||
"nsfw_set_false": "Le NSFW est désactivé sur ce salon.",
|
||||
"no_shard_id": "Aucun fragment avec cet ID n'a été trouvée.",
|
||||
"nsfw_set_true": "Le NSFW a été **activé** sur ce salon.",
|
||||
"nsfw_set_false": "Le NSFW a été **désactivé** sur ce salon.",
|
||||
"old_msg": "Ancien message",
|
||||
"old_nick": "Ancien surnom",
|
||||
"old_topic": "Ancien thème",
|
||||
"prot_cant_use_time": "Vous ne pouvez spécifier de durée pour cette sanction.",
|
||||
"rar_err": "Échec de la suppression de rôles. Mes permissions sont insuffisantes.",
|
||||
"old_topic": "Ancien sujet",
|
||||
"prot_cant_use_time": "Vous ne pouvez pas spécifier de durée pour cette sanction.",
|
||||
"rar_err": "Échec de la suppression des rôles. Permissions insuffisantes.",
|
||||
"rc_perms": "Une erreur est survenue suite à une couleur invalide ou des permissions insuffisantes.",
|
||||
"remrole": "Succès du retrait du rôle {0} de l'utilisateur {1} ",
|
||||
"remrole": "Le rôle {0} a été retiré de l'utilisateur {1} avec succès.",
|
||||
"remrole_err": "Échec du retrait du rôle. Permissions insuffisantes.",
|
||||
"renrole_err": "Échec du renommage du rôle. Permissions insuffisantes.",
|
||||
"renrole_perms": "Vous ne pouvez pas modifier des rôles supérieurs au votre ou à mon rôle le plus élevé.",
|
||||
"renrole_perms": "Vous ne pouvez pas modifier des rôles supérieurs au votre, ou mon plus haut.",
|
||||
"ropl_added": "Ajoutés.",
|
||||
"ropl_disabled": "Rotation du statut de jeu désactivée.",
|
||||
"ropl_enabled": "Rotation du statut de jeu activée.",
|
||||
"ropl_list": "Voici une liste de statuts en rotation :\n{0}",
|
||||
"ropl_list": "Voici une liste des statuts en rotation :\n{0}",
|
||||
"ropl_not_set": "Aucun statut en rotation réglé.",
|
||||
"setrole_err": "Échec de l'ajour de rôle. Mes permissions sont insuffisantes.",
|
||||
"set_avatar": "Nouvel avatar défini!",
|
||||
"set_game": "Nouveau jeu défini!",
|
||||
"set_stream": "Nouveau stream défini!",
|
||||
"set_topic": "Nouveau thème du salon réglé.",
|
||||
"shard_reconnecting": "La Shard {0} se reconnecte.\n",
|
||||
"soft_banned_pl": "ban-soft",
|
||||
"text_chan_created": "Salon textuel crée.",
|
||||
"shard_reconnecting": "Le fragment {0} se reconnecte.",
|
||||
"soft_banned_pl": "radié·e·s",
|
||||
"text_chan_created": "Salon textuel créé.",
|
||||
"text_chan_destroyed": "Salon textuel supprimé.",
|
||||
"duration": "Durée",
|
||||
"unmuted_sn": "Démuté",
|
||||
"unable_to_dm_user": "Échec de l'envoi de message par MP.",
|
||||
"unmuted_sn": "Parole rendue",
|
||||
"unable_to_dm_user": "Échec de l'envoi du message par MP.",
|
||||
"username_changed": "Nom de membre changé",
|
||||
"user_banned": "Utilisateur banni",
|
||||
"user_joined": "Un utilisateur à rejoint",
|
||||
@@ -646,21 +644,21 @@
|
||||
"user_role_add": "Rôle utilisateur ajouté",
|
||||
"user_role_rem": "Rôle utilisateur retiré",
|
||||
"user_status_change": "{0} est maintenant {1}",
|
||||
"user_vjoined": "{0} a rejoint {1} salon vocal.",
|
||||
"user_vleft": "{0} a quitté {1} salon vocal.",
|
||||
"user_vjoined": "{0} a rejoint le salon vocal{1}.",
|
||||
"user_vleft": "{0} a quitté le salon vocal {1}.",
|
||||
"user_vmoved": "{0} est passé du salon vocal {1} au salon vocal {2}.",
|
||||
"voice_chan_created": "Salon vocal créé",
|
||||
"voice_chan_destroyed": "Salon vocal détruit",
|
||||
"xmuted_text": "Utilisateur {0} du tchat textuel de {1}",
|
||||
"xmuted_text_and_voice": "Utilisateur {0} du tchat textuel et vocal par {1}",
|
||||
"xmuted_text": "Utilisateur {0} du salon textuel de {1}",
|
||||
"xmuted_text_and_voice": "Utilisateur {0} du salon textuel et vocal par {1}",
|
||||
"xmuted_voice": "Utilisateur {0} du vocal {1}",
|
||||
"user_unbanned": "Utilisateur débanni",
|
||||
"presence_updates": "Présence de mise-à-jours",
|
||||
"presence_updates": "Présence de mises à jour",
|
||||
"awarded": "donne la récompense de {0} à {1}",
|
||||
"deck_reshuffled": "Cartes mélangées.",
|
||||
"flipped": "a retourné {0}.",
|
||||
"flip_invalid": "Chiffre spécifié invalide. Vous pouvez retourner entre 1 et {0} pièces.",
|
||||
"cards_left": "{0} cartes restantes dans le jeu",
|
||||
"cards_left": "{0} cartes restantes dans le jeu.",
|
||||
"gifted": "a offert {0} à {1}",
|
||||
"heads": "Face",
|
||||
"no_more_cards": "Plus de cartes dans le deck.",
|
||||
@@ -669,11 +667,11 @@
|
||||
"take_fail": "Impossibilité de prendre {0} de {1} car l'utilisateur n'a pas autant de {2} !",
|
||||
"commandlist_regen": "Liste de commandes régénérée.",
|
||||
"desc": "Description",
|
||||
"cant_dm": "Je ne peux pas te dm. Assurez-toi que tes DM sont ouverts. Allez dans **options (bouton rouage) -> Confidentialité et sécurité -> Autoriser les messages directs des membres du serveur**",
|
||||
"cant_dm": "Je ne peux pas te dm. Assure-toi que tes MP sont ouverts. Va dans **options (bouton en forme de rouage) -> Confidentialité et sécurité -> Autoriser les messages directs des membres du serveur**",
|
||||
"donate": "Vous pouvez soutenir le projet NadekoBot sur\nPatreon <{0}> ou\nPaypal<{1}>\nN'oubliez pas de laisser votre nom ou ID Discord dans le message.\n\n**Merci beaucoup**♥️",
|
||||
"guide": "**Liste de commandes** : <{0}>\n**Des guides et documents d'hébergement peuvent être trouvés ici** : <{1}>",
|
||||
"list_of_modules": "Liste des modules",
|
||||
"autohentai_started": "Autohentai commencé. Reposte toutes les {0}sec avec un des tags suivant:\n{1}",
|
||||
"autohentai_started": "Autohentai commencé. Reposte toutes les {0}sec avec l'un des tags suivant:\n{1}",
|
||||
"tag": "Tag",
|
||||
"animal_race_full": "La course est pleine! Départ imminent.",
|
||||
"animal_race_join_bet": "{0} rejoint en tant que {1} et parie {2} !",
|
||||
@@ -708,7 +706,7 @@
|
||||
"set_music_channel": "Je vais maintenant sortir les chansons en cours de lecture, terminées, mises en pause et supprimées sur ce salon.",
|
||||
"unset_music_channel": "Je vais maintenant afficher les chansons en cours de lecture, terminées, mises en pause et supprimées des lecteurs de musique nouvellement créés dans le salon à partir de laquelle la musique a été lancée.",
|
||||
"song_moved": "Chanson déplacée",
|
||||
"to_position": "A la position",
|
||||
"to_position": "À la position",
|
||||
"volume_input_invalid": "Le volume doit être entre 0 et 100",
|
||||
"link_filter_channel_off": "Filtrage des liens désactivé sur ce salon.",
|
||||
"link_filter_channel_on": "Filtrage des liens activé sur ce salon.",
|
||||
@@ -717,20 +715,20 @@
|
||||
"avatar_none": "L'utilisateur {0} n'a pas d'avatar défini.",
|
||||
"anime_no_fav": "Pas d’animé favori",
|
||||
"atl_ad_started": "Début de la traduction automatique des messages dans ce salon. Les messages de l'utilisateur seront automatiquement supprimés.",
|
||||
"atl_removed": "Votre langue de traduction automatique a été supprimée.",
|
||||
"atl_removed": "Votre langue de traduction automatique a été retirée.",
|
||||
"atl_set": "Votre langue de traduction automatique a été définie sur {0}>{1}",
|
||||
"atl_started": "Début de la traduction automatique des messages sur cette chaîne.",
|
||||
"atl_stopped": "Arrêt de la traduction automatique des messages sur ce canal.",
|
||||
"atl_started": "Début de la traduction automatique des messages sur ce salon.",
|
||||
"atl_stopped": "Arrêt de la traduction automatique des messages sur ce salon.",
|
||||
"bad_input_format": "Mauvais format d'entrée, ou quelque chose s'est mal passé.",
|
||||
"card_not_found": "N'a pas pu trouver cette carte.",
|
||||
"catfact": "Fait",
|
||||
"comic_not_found": "Comic introuvé.",
|
||||
"completed": "Achevé(e)",
|
||||
"dropped": "Abandonné(e)",
|
||||
"completed": "Achevé·e",
|
||||
"dropped": "Abandonné·e",
|
||||
"error_occured": "Une erreur est survenue.",
|
||||
"failed_finding_anime": "N'a pas pu trouver l'animu.",
|
||||
"failed_finding_manga": "N'a pas pu trouver le mango.",
|
||||
"imdb_fail": "N'a pas pu trouver ce film.",
|
||||
"failed_finding_anime": "Échec pour trouver cet anime.",
|
||||
"failed_finding_manga": "Échec pour trouver ce manga.",
|
||||
"imdb_fail": "Échec pour trouver ce film.",
|
||||
"invalid_lang": "Langue source ou cible invalide.",
|
||||
"jokes_not_loaded": "Blagues non chargées.",
|
||||
"list_of_place_tags": "Liste des {0} tags de lieu",
|
||||
@@ -742,13 +740,13 @@
|
||||
"on_hold": "En attente",
|
||||
"osu_api_key": "Une clé API osu! est demandée.",
|
||||
"osu_failed": "Échec de récupération de la signature osu!.",
|
||||
"osu_user_not_found": "Membre introuvé",
|
||||
"osu_user_not_found": "Membre introuvé.",
|
||||
"plan_to_watch": "À regarder",
|
||||
"something_went_wrong": "Quelque chose a mal tourné.",
|
||||
"specify_search_params": "Veuillez spécifier les paramètres de recherche.",
|
||||
"store_url": "URL de la boutique",
|
||||
"streamer_offline": "Streamer {0} est hors-ligne.",
|
||||
"streamer_online": "Streamer {0} est en ligne avec {0} spectateurs.",
|
||||
"streamer_online": "Streamer {0} est en ligne avec {1} spectateurs.",
|
||||
"streams_follow_title": "Streams que vous suivez",
|
||||
"streams_none": "Vous ne suivez aucun stream sur ce serveur.",
|
||||
"stream_no": "Il n'y a pas de tel stream.",
|
||||
@@ -776,7 +774,7 @@
|
||||
"repeater_created": "Répéteur créé",
|
||||
"repeater_removed": "Répéteur #{0} supprimé",
|
||||
"no_roles_on_page": "Aucun rôle sur cette page.",
|
||||
"no_shards_on_page": "Aucun shard dans cette page.",
|
||||
"no_shards_on_page": "Aucun fragment dans cette page.",
|
||||
"presence": "Présence",
|
||||
"presence_txt": "{0} Serveurs\n{1} Salons Textuels\n{2} Salons Vocaux",
|
||||
"quotes_deleted": "Suppression de toutes les citations avec le mot-clé {0}.",
|
||||
@@ -791,19 +789,19 @@
|
||||
"showemojis": "**Nom:** {0} **Lien:** {1}",
|
||||
"users": "Membres",
|
||||
"no_user_on_this_page": "Aucun membre sur cette page.",
|
||||
"aliases_none": "Aucun psudonyme trouvé",
|
||||
"aliases_none": "Aucun pseudonyme trouvé",
|
||||
"alias_added": "Taper {0} sera désormais un alias de {1}.",
|
||||
"alias_list": "List des pseudonymes",
|
||||
"alias_list": "Liste des pseudonymes",
|
||||
"alias_removed": "Le déclencheur {0} n'a plus d'alias.",
|
||||
"alias_remove_fail": "Le déclencheur {0} n'avait pas d'alias.",
|
||||
"punishment_unsupported": "Vous ne pouvez pas utiliser {0} action de punition avec cette fonctionnalité.",
|
||||
"interval": "Intervalle",
|
||||
"kicked_pl": "Kick",
|
||||
"autocmd_add": "La commande {0} s'exécutera toutes les {1} dans ce salon.",
|
||||
"autocmd_add": "La commande {0} s'exécutera toutes les {1} secondes dans ce salon.",
|
||||
"autocmdlist_none": "Aucune commande automatique sur cette page.",
|
||||
"warn_expire_set_delete": "Les avertissements seront supprimés après {0} jours.",
|
||||
"warn_expire_set_clear": "Les avertissements seront effacés après {0} jours.",
|
||||
"warn_expire_reset": "Les avertissements n'expirent plus.",
|
||||
"warn_expire_set_clear": "Les avertissements seront annulés après {0} jours.",
|
||||
"warn_expire_reset": "Les avertissements n'expireront plus.",
|
||||
"warn_punish_set_timed": "J'appliquerai {0} punition pour {2} aux utilisateurs avec {1} avertissements.",
|
||||
"clpa_obsolete": ":tada: **Les récompenses en devise Patreon sont désormais automatiques !** :tada:\nCette commande est désormais obsolète.\nSi vous n'avez pas reçu votre récompense pour l'engagement de ce mois, voici quelques-unes des raisons pour lesquelles cela pourrait être le cas.",
|
||||
"time_new": "Temps",
|
||||
@@ -818,8 +816,8 @@
|
||||
"user_nick": "Surnom du membre {0} a été changé pour {1}",
|
||||
"perm_override": "Les utilisateurs auront besoin de l'autorisation {0} pour exécuter la commande {1}.",
|
||||
"define_unknown": "N'arrive pas à trouver une définition à ce terme.",
|
||||
"queue_stopped": "Lecteur en arrêt. Utilisez la commande {0} pour commencer à jouer.",
|
||||
"removed_song_error": "Chanson sur cet index n'existe pas",
|
||||
"queue_stopped": "La lecture est arrêtée. Utilisez la commande {0} pour commencer à jouer.",
|
||||
"removed_song_error": "La chanson n'existe pas sur cet index",
|
||||
"nunchi_started": "Jeu de Nunchi a commencé avec {0} participants.",
|
||||
"bot_strings_reloaded": "Les chaînes de caractères du bot ont été mises à jour.",
|
||||
"xpn_setting_global": "Notifications de montée en niveau Global",
|
||||
@@ -866,9 +864,9 @@
|
||||
"leagues_not_found": "Incapable de récupérer les donnes depuis l'API Path of Exile.",
|
||||
"perm_override_page_none": "Aucune dérogation sur cette page.",
|
||||
"perm_override_all": "Toutes les dérogations d'autorisation de Discord ont été effacés.",
|
||||
"perm_override_all_confirm": "Êtes-vous sûr de vouloir supprimer **TOUS** les dérogations d'autorisation de Discord sur ce serveur ? Cette action est irréversible.",
|
||||
"perm_override_all_confirm": "Êtes-vous sûr de vouloir supprimer **TOUTES** les dérogations d'autorisation de Discord sur ce serveur ? Cette action est irréversible.",
|
||||
"perm_overrides": "les dérogations d'autorisation de Discord",
|
||||
"perm_override_reset": "Les dérogations d'autorisation de Discord pour cette commande ont été effacés.",
|
||||
"perm_override_reset": "Les dérogations d'autorisation de Discord pour cette commande ont été effacées.",
|
||||
"reset": "Réinitialisation de l'XP",
|
||||
"reset_server_confirm": "Êtes-vous sûr de vouloir réinitialiser l'XP de tous les utilisateurs du serveur ?",
|
||||
"reset_user_confirm": "Êtes-vous sûr de vouloir réinitialiser l'XP de l'utilisateur spécifié sur ce serveur ?",
|
||||
@@ -888,7 +886,7 @@
|
||||
"aar_roles": "Les rôles suivants sont assignés aux membres qui joignent ce serveur: {0}",
|
||||
"aar_role_removed": "Les membres ne seront plus assignés {0} au moment de joindre le serveur.",
|
||||
"remove_roles_pl": "ont eu leurs rôles supprimés",
|
||||
"role_too_high": "Vous ne pouvez pas utiliser cette commande avec des rôles supérieurs à votre rôle le plus élevé, sauf si vous êtes administrateur de serveur.",
|
||||
"role_too_high": "Vous ne pouvez pas utiliser cette commande avec des rôles supérieurs au votre, sauf si vous êtes administrateur de serveur.",
|
||||
"log_vc_joined": "{0} a rejoint le salon vocal {1}",
|
||||
"log_vc_left": "{0} a quitté le salon vocal {1}",
|
||||
"protection_not_running": "Protection {0} n'est pas activée",
|
||||
@@ -903,9 +901,9 @@
|
||||
"blacklisted_channels": "Salons sur la liste noire",
|
||||
"blacklisted_servers": "Serveurs sur la liste noire",
|
||||
"_class": "Classe",
|
||||
"stream_not_following_any": "Vous ne suivez aucun stream.",
|
||||
"stream_message_set_all": "Tous les {0} streams suivis ont maintenant le message d'annonce spécifié.",
|
||||
"repeater_exceed_limit": "Vous ne pouvez avoir plus de {0} rèpètiteurs par serveur.",
|
||||
"stream_not_following_any": "Vous ne suivez aucune diffusion.",
|
||||
"stream_message_set_all": "Toutes les {0} diffusions suivies ont maintenant le message d'annonce spécifié.",
|
||||
"repeater_exceed_limit": "Vous ne pouvez avoir plus de {0} répéteurs par serveur.",
|
||||
"repeater_remove_fail": "Échec de la suppression du répéteur sur cet index. Soit vous avez spécifié un index non valide, soit le répéteur était en cours d'exécution à ce moment-là, auquel cas, réessayez dans quelques secondes.",
|
||||
"interval_colon": "Intervalle:",
|
||||
"executes_in_colon": "S'exécute dans :",
|
||||
@@ -945,7 +943,7 @@
|
||||
"module_description_xp": "Gagnez de l'XP en fonction de l'activité de tchat, vérifiez les cartes XP des utilisateurs",
|
||||
"module_description_missing": "Description manquante pour ce module.",
|
||||
"obsolete_use": "⚠ Obsolète, utilisez plutôt {0}.",
|
||||
"purge_user_confirm": "Êtes-vous sûr(e) de vouloir purger {0} de la base des données?",
|
||||
"purge_user_confirm": "Êtes-vous sûr·e de vouloir purger {0} de la base des données?",
|
||||
"expr_import_no_input": "Saisie invalide. Aucun chargement de fichier ou saisie de texte trouvé.",
|
||||
"expr_import_invalid_data": "Impossible d'analyser le fichier. Assurez-vous qu'il s'agisse d'un fichier .yml",
|
||||
"inv_expire": "Expire dans:",
|
||||
@@ -953,5 +951,29 @@
|
||||
"empty_page": "Cette page est vide.",
|
||||
"pages": "Pages",
|
||||
"favorites": "Favoris",
|
||||
"tags": "Tags"
|
||||
"tags": "Tags",
|
||||
"invalid_emoji_link": "Le lien spécifié n'est pas une image ou excède 256KB.",
|
||||
"emoji_add_error": "Erreur lors de l'ajout d'emoji. Soit vous n'avez plus d'emplacements pour emoji, soit la taille de l'image est inadéquate.",
|
||||
"emoji_added": "Nouveau emoji ajouté: {0}",
|
||||
"boost_on": "Annonces Boost activées dans ce salon.",
|
||||
"boost_off": "Annonces Boost désactivées.",
|
||||
"boostmsg_cur": "Message Boost actuel: {0}",
|
||||
"boostmsg_enable": "Activez les messages Boost en tapant {0}",
|
||||
"boostmsg_new": "Nouveau message Boost défini.",
|
||||
"boostdel_off": "La suppression automatique des messages Boost a été désactivée.",
|
||||
"boostdel_on": "Les messages Boost seront supprimés après {0} secondes.",
|
||||
"log_ignored_channels": "Salons ignorés",
|
||||
"log_ignored_users": "Utilisateurs ignorés",
|
||||
"log_ignore_user": "La journalisation ignorera le membre {0}",
|
||||
"log_not_ignore_user": "La journalisation n'ignorera plus le membre {0}",
|
||||
"log_ignore_chan": "La journalisation ignorera le salon {0}",
|
||||
"log_not_ignore_chan": "La journalisation n'ignorera plus le salon {0}",
|
||||
"streams_cleared": "Tous les streams suivis sur ce serveur ont été supprimés.",
|
||||
"warn_weight": "Poids: {0}",
|
||||
"warn_count": "{0} actuel·s, {1} total",
|
||||
"mass_ban_in_progress": "En train de bannir {0} membres...",
|
||||
"mass_ban_completed": "{0} membres bannis.",
|
||||
"reminder_server_list": "Liste des rappels du server.",
|
||||
"imageonly_enable": "Ce salon est maintenant exclusivement pour les images.",
|
||||
"imageonly_disable": "Ce salon n'est plus exclusivement pour les images."
|
||||
}
|
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
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"api_key_missing": "A chave de API necessária para esse comando não foi fornecida.",
|
||||
"api_key_missing": "Falta a chave API.",
|
||||
"quote_deleted": "Citação #{0} excluída.",
|
||||
"redacted_too_long": "O texto é longo demais.",
|
||||
"trigger": "Gatilho",
|
||||
"response": "Resposta",
|
||||
"fw_cleared": "Todas as palavras filtradas foram removidas e suas configurações foram resetadas.",
|
||||
"aar_disabled": "Usuários que entrarem no servidor não receberão cargos automaticamente.",
|
||||
"fw_cleared": "Removido todos os filtros e configurações de filtros de palavras do canal.",
|
||||
"aar_disabled": "**Cargos automáticos** para usuários que entrarem está **desativado**",
|
||||
"bandm": "Você foi banido do servidor {0}.\nMotivo: {1}",
|
||||
"banned_user": "Usuário Banido",
|
||||
"byedel_off": "A exclusão automática de mensagens de despedida foi desativada.",
|
||||
"byedel_on": "Mensagens de despedida serão excluídas após {0} segundos.",
|
||||
"byemsg_cur": "Mensagem de despedida atual",
|
||||
"byemsg_cur": "Mensagem de despedida atual: {0}",
|
||||
"byemsg_enable": "Digite {0} para ativar a mensagem de despedida.",
|
||||
"byemsg_new": "Nova mensagem de despedida definida com sucesso.",
|
||||
"bye_off": "A mensagem de despedida foi desativada.",
|
||||
@@ -33,22 +33,22 @@
|
||||
"fwdm_stop": "DMs não serão mais encaminhadas.",
|
||||
"greetdel_off": "Mensagens de boas-vindas não serão mais automaticamente excluídas.",
|
||||
"greetdel_on": "Mensagens de boas-vindas serão excluídas após {0} segundos.",
|
||||
"greetdmmsg_cur": "Mensagem direta de boas-vindas atual",
|
||||
"greetdmmsg_cur": "Mensagem direta de boas-vindas atual: {0}",
|
||||
"greetdmmsg_enable": "Digite {0} para ativar a mensagem direta de boas-vindas.",
|
||||
"greetdmmsg_new": "A mensagem direta de boas-vindas foi definida com sucesso.",
|
||||
"greetdm_off": "A mensagem direta de boas-vindas foi desativada.",
|
||||
"greetdm_on": "A mensagem direta de boas-vindas foi ativada.",
|
||||
"greetmsg_cur": "Mensagem de boas-vindas atual",
|
||||
"greetmsg_cur": "Mensagem de boas-vindas atual: {0}",
|
||||
"greetmsg_enable": "Digite {0} para ativar a mensagem de boas-vindas.",
|
||||
"greetmsg_new": "Mensagem de boas-vindas definida com sucesso.",
|
||||
"greet_off": "A mensagem de boas-vindas foi desativada.",
|
||||
"greet_on": "A mensagem de boas-vindas foi ativada nesse canal.",
|
||||
"hierarchy": "Você não pode usar esse comando em usuários de cargo igual ou superior ao seu na hierarquia de cargos.",
|
||||
"hierarchy": "Você não pode usar esse comando em usuários de cargo igual ou superior ao seu (ou meu) na hierarquia de cargos.",
|
||||
"invalid_format": "Input inválido.",
|
||||
"kickdm": "Você foi expulso do servidor {0}.\nMotivo: {1}",
|
||||
"kicked_user": "Usuário expulso",
|
||||
"lang_list": "Lista de idiomas",
|
||||
"lang_set_bot": "O idioma do bot foi definido para {0} - {1}",
|
||||
"lang_set_bot": "O idoma do bot foi definido para {0} - {1}",
|
||||
"lang_set_bot_show": "O idioma do bot está definido como {0} - {1}",
|
||||
"lang_set": "O idioma do bot no servidor foi definido para {0} - {1}",
|
||||
"message_sent": "Mensagem enviada.",
|
||||
@@ -61,7 +61,7 @@
|
||||
"raid_cnt": "O número de usuários deve estar entre {0} e {1}.",
|
||||
"raid_stats": "Se {0} ou mais usuários entrarem no servidor em um intervalo de {1} segundos, aplicarei {2} a eles.",
|
||||
"raid_time": "O tempo deve ser entre {0} e {1} segundos.",
|
||||
"rar": "Todas os cargos do usuário {0} foram removidos com sucesso.",
|
||||
"rar": "Todos os cargos do usuário {0} foram removidos com sucesso.",
|
||||
"rc": "A cor do cargo {0} foi alterada.",
|
||||
"renrole": "Cargo renomeado.",
|
||||
"reprm": "Mensagem de status removida: {0}",
|
||||
@@ -108,9 +108,9 @@
|
||||
"not_enough": "Você não tem {0} suficiente.",
|
||||
"raffled_user": "Usuário sorteado",
|
||||
"slot_bet": "Aposta",
|
||||
"slot_jackpot": "WOAAHHHHHH!!! Parabéns!!! x{0}",
|
||||
"slot_jackpot": "UHUUUULLLL!!! Parabéns!!! x{0}",
|
||||
"slot_single": "Um único {0}, x{1}",
|
||||
"slot_three": "Whoa! Que sorte! Três do mesmo tipo! x{0}",
|
||||
"slot_three": "Uhul! Que sorte! Três do mesmo tipo! x{0}",
|
||||
"slot_two": "Opa! Dois {0} - ganha x{1}",
|
||||
"won": "Ganhou",
|
||||
"transactions": "Transações do usuário {0}",
|
||||
@@ -123,13 +123,13 @@
|
||||
"requires": "Requer",
|
||||
"blacklisted_tag_list": "Lista de tags na lista negra:",
|
||||
"blacklisted_tag_add": "O termo {0} foi adicionado à lista negra.",
|
||||
"blacklisted_tag_remove": "A tag {0} não está mais na lista negra.",
|
||||
"blacklisted_tag_remove": "O termo {0} não está mais na lista negra.",
|
||||
"animal_race": "Corrida de animais",
|
||||
"animal_race_failed": "Não foi possível iniciar a corrida por não haver participantes suficientes.",
|
||||
"animal_race_join": "{0} entrou como {1}",
|
||||
"animal_race_join_instr": "Digite {0}race para participar da corrida.",
|
||||
"animal_race_join_instr": "Digite {0}jr para participar da corrida.",
|
||||
"animal_race_starting": "Iniciando em {0} segundos ou quando a sala estiver cheia.",
|
||||
"animal_race_won": "{0}, como {1}, venceu a corrida!",
|
||||
"animal_race_won": "{0} como {1} venceu a corrida!",
|
||||
"dice_invalid_number": "Número inválido. Você pode rolar {0}-{1} dados de uma vez.",
|
||||
"dice_rolled": "rolou {0}",
|
||||
"dice_rolled_num": "Dados rolados: {0}",
|
||||
@@ -149,7 +149,7 @@
|
||||
"waifu_not_yours": "Essa waifu não lhe pertence.",
|
||||
"waifu_not_yourself": "Você não pode se reivindicar.",
|
||||
"waifu_recent_divorce": "Por ter se divorciado recentemente, você deve esperar {0} horas e {1} minutos para se divorciar novamente.",
|
||||
"waifu_transfer_fail": "Você não é o dono dessa waifu.",
|
||||
"waifu_transfer_fail": "Você não é o dono desta waifu ou não tem como compra-la.\nSua entrada é inválida.",
|
||||
"waifu_transfer_success": "A posse de {0} foi transferida de {1} para {2}",
|
||||
"nobody": "Ninguém",
|
||||
"waifu_divorced_notlike": "Você se divorciou uma waifu que não gosta de você. Você recebeu {0}.",
|
||||
@@ -183,8 +183,8 @@
|
||||
"hangman_game_started": "Jogo da forca iniciado",
|
||||
"hangman_running": "Já existe um jogo da forca em andamento nesse canal.",
|
||||
"hangman_types": "Lista dos temas disponíveis no \"{0}hangman\":",
|
||||
"no_results": "Nenhum resultado.",
|
||||
"picked": "pegou {0}",
|
||||
"no_results": "Nenhum resultado encontrado.",
|
||||
"picked": "coletou {0}",
|
||||
"planted": "{0} plantou {1}",
|
||||
"trivia_already_running": "Já há um quiz em andamento nesse servidor.",
|
||||
"trivia_game": "Quiz",
|
||||
@@ -217,7 +217,7 @@
|
||||
"playlist_queue_complete": "Playlist adicionada à fila.",
|
||||
"queued_song": "Músicas na fila",
|
||||
"removed_song": "Música removida",
|
||||
"repeating_track": "Repetindo música",
|
||||
"repeating_track": "A música ficará sendo repetida.",
|
||||
"volume_set": "Volume ajustado para {0}%",
|
||||
"acm_disable": "TODOS OS MÓDULOS foram desativados no canal {0}.",
|
||||
"acm_enable": "TODOS OS MÓDULOS foram ativados no canal {0}.",
|
||||
@@ -353,8 +353,8 @@
|
||||
"poll_voted": "{0} votou.",
|
||||
"poll_invalid_input": "Input inválido. Você precisa de uma pergunta e pelo menos 2 respostas, todas separadas por `;`.",
|
||||
"x_votes_cast": "Total de votos: {0}",
|
||||
"pick_pl": "Pegue digitando {0}",
|
||||
"pick_sn": "Pegue digitando {0}",
|
||||
"pick_pl": "Pegue o item digitando `{0}pick`",
|
||||
"pick_sn": "Pegue digitando `{0}pick`",
|
||||
"sql_confirm_exec": "Confirme a execução do seguinte comando SQL",
|
||||
"no_vcroles": "Não há cargos de canal de voz.",
|
||||
"user_muted_time": "{0} foi **mutado** nos chats de voz e texto por {1} minutos.",
|
||||
@@ -390,13 +390,13 @@
|
||||
"warn_punish_rem": "Ter {0} advertências não causará mais uma punição.",
|
||||
"warn_punish_set": "Usuários que acumularem {1} advertências serão punidos com {0}.",
|
||||
"cant_apply_punishment": "Não tenho as permissões necessárias para aplicar essa punição.",
|
||||
"clpa_fail_already": "Talvez você já tenha recebido sua recompensa deste mês. Você só pode recebê-las uma vez a cada mês, a menos que aumente sua doação.",
|
||||
"clpa_fail_already": "Talvez você já tenha recebido sua recompensa deste mês. Você só pode recebê-las uma vez a cada mês, a menos que aumente sua doação.\nCheque utilizando o comando `.curtrs` .",
|
||||
"clpa_fail_already_title": "Já foi recompensado",
|
||||
"clpa_fail_conn": "Sua conta do Discord pode não estar conectada ao Patreon. Se você não sabe o que isso significa ou não sabe como conectá-la, você deve ir à [Página de Configurações de Conta do Patreon](https://patreon.com/settings/account) e clicar no botão 'Connect to Discord'.",
|
||||
"clpa_fail_conn_title": "Sua conta do Discord não está conectada",
|
||||
"clpa_fail_sup": "Para receber recompensas, você precisa apoiar o projeto no Patreon. Use o comando {0} para receber o link.",
|
||||
"clpa_fail_sup_title": "Não é um patrono",
|
||||
"clpa_fail_wait": "Você precisa esperar algumas horas após o pagamento. Tente novamente mais tarde.",
|
||||
"clpa_fail_wait": "Você precisa esperar de 5 a 10 minutos após o pagamento.Tente novamente mais tarde (tambem confira se sua conta do patreon está conectada ao seu discord).",
|
||||
"clpa_fail_wait_title": "Espere um pouco",
|
||||
"clpa_too_early": "Recompensas podem ser reivindicadas a partir do 5° dia de cada mês",
|
||||
"shop": "Loja",
|
||||
@@ -420,7 +420,7 @@
|
||||
"shop_list_item_not_unique": "Esse item já existe na loja.",
|
||||
"shop_purchase": "Compra efetuada no servidor {0}",
|
||||
"shop_role_not_found": "O cargo que está a venda não existe mais.",
|
||||
"role_not_found": "Cargo não encontrado.",
|
||||
"role_not_found": "Cargo não encontrado: {0}",
|
||||
"shop_role_purchase": "Você comprou a cargo {0} com sucesso.",
|
||||
"shop_role_purchase_error": "Erro ao atribuir o cargo. Sua compra foi reembolsada.",
|
||||
"unique_items_left": "Restam {0} itens únicos.",
|
||||
@@ -446,7 +446,7 @@
|
||||
"global_perms_reset": "Permissões globais foram resetadas.",
|
||||
"module": "Módulo: {0}",
|
||||
"hangman_stopped": "O jogo da forca foi encerrado.",
|
||||
"queue_shuffled": "As músicas tocarão em ordem aleatória.",
|
||||
"queue_shuffled": "A fila de música está em modo aleatório.",
|
||||
"warnings_list": "Lista de usuários advertidos no servidor",
|
||||
"waifu_gift": "Presenteou {1} com {0}",
|
||||
"waifu_gift_shop": "Loja de presentes",
|
||||
@@ -498,7 +498,7 @@
|
||||
"club_user_kick_fail": "Erro ao expulsar. Ou você não é o dono do clube ou o usuário não está no seu clube.",
|
||||
"club_user_banned": "O usuário {0} foi banido do clube {1}.",
|
||||
"club_user_ban_fail": "Falha ao banir. Você não é o dono do clube ou o usuário não está, nem se aplicou ao seu clube.",
|
||||
"club_user_unbanned": "O usuário {0} foi desbanido do seu clube.",
|
||||
"club_user_unbanned": "Desbanindo o usuário {0} no clube {1}.",
|
||||
"club_user_unban_fail": "Falha ao desbanir. Você não é o dono do clube ou o usuário não está, nem se aplicou ao seu clube.",
|
||||
"club_level_req_changed": "O requisito de nível do clube foi alterado para {0}.",
|
||||
"club_level_req_change_error": "Falha ao alterar o requisito de nível.",
|
||||
@@ -515,7 +515,7 @@
|
||||
"self_assign_are_not_exclusive": "Agora usuários poderão escolher quaisquer cargos de qualquer grupo.",
|
||||
"new_reaction_event": "Clique na reação {0} para receber {1}\nRestam {2}.",
|
||||
"new_gamestatus_event": "Digite o código secreto em qualquer canal para receber {1}\nRestam {2}.",
|
||||
"event_duration_footer": "O evento termina em {0}h {1}m",
|
||||
"event_duration_footer": "O evento está ativo por {0} horas.",
|
||||
"start_event_fail": "Falha ao iniciar o evento. Já há outro evento em execução ou ocorreu um erro ao iniciá-lo.",
|
||||
"event_title": "Um evento do tipo {0} foi iniciado!",
|
||||
"poll_closed": "Votação encerrada!",
|
||||
@@ -536,8 +536,8 @@
|
||||
"timely_reset": "Agora, usuários poderão reivindicar recompensas periodicamente.",
|
||||
"market_cap": "Valor de mercado",
|
||||
"volume_24h": "Volume (24h)",
|
||||
"change_7d_24h": "Variação (7d/24h)",
|
||||
"crypto_not_found": "Não foi possível encontrar uma criptomoeda com esse nome.",
|
||||
"change_7d_24h": "Variação (7d / 24h)",
|
||||
"crypto_not_found": "Uma criptomoeda com esse nome não foi encontrada.",
|
||||
"did_you_mean": "Você quis dizer {0}?",
|
||||
"self_assign_level_req": "O cargo auto-atribuível {0} agora requer pelo menos nível de servidor {1}.",
|
||||
"self_assign_not_level": "Esse cargo auto-atribuível requer pelo menos nível de servidor {0}.",
|
||||
@@ -593,8 +593,6 @@
|
||||
"log_all": "Registrando todos os eventos nesse canal.",
|
||||
"log_disabled": "Registros desabilitado.",
|
||||
"log_events": "Eventos de registro que você pode assinar:",
|
||||
"log_ignore": "Registros vai ignorar {0}",
|
||||
"log_not_ignore": "Registros não irá ignorar {0}",
|
||||
"log_stop": "Parando de registrar evento {0}.",
|
||||
"msg_not_found": "Mensagem não encontrada.",
|
||||
"time_too_long": "O tempo que você especificou é muito longo.",
|
||||
@@ -847,7 +845,7 @@
|
||||
"stopped": "Repost encerrado.",
|
||||
"restart_fail": "Você precisa configurar o RestartCommand no arquivo creds.yml",
|
||||
"restarting": "Reiniciando.",
|
||||
"edit_fail": "Não existe reação personalizada com essa ID.",
|
||||
"edit_fail": "Não existe reação personalizada com esse ID.",
|
||||
"streaming": "Transmitindo",
|
||||
"rafflecur": "Rifa {0}",
|
||||
"rafflecur_joined": "O usuário {0} entrou no sorteio",
|
||||
@@ -953,5 +951,29 @@
|
||||
"empty_page": "Essa página esta vazia.",
|
||||
"pages": "Páginas",
|
||||
"favorites": "Favoritos",
|
||||
"tags": "Etiquetas"
|
||||
"tags": "Etiquetas",
|
||||
"invalid_emoji_link": "O link especificado não retorna para uma imagem ou excede 256KB.",
|
||||
"emoji_add_error": "Erro ao adicionar emoji. O servidor não possui mais slots de emoji disponíveis ou o tamanho da imagem é incompatível.",
|
||||
"emoji_added": "Novo emoji adicionado: {0}",
|
||||
"boost_on": "Os anúncios de impulsionamento foram ativados neste canal.",
|
||||
"boost_off": "Os anúncios de impulsionamento foram desativados.",
|
||||
"boostmsg_cur": "Mensagem atual de impulsionamento: {0}",
|
||||
"boostmsg_enable": "Ative os anúncios de impulsionamento digitando {0}",
|
||||
"boostmsg_new": "Nova mensagem de impulsionamento definida.",
|
||||
"boostdel_off": "A deleção automática dos anúncios de impulsionamento foi desativada.",
|
||||
"boostdel_on": "Anúncios de impulsionamento serão deletados após {0} segundos.",
|
||||
"log_ignored_channels": "Canais ignorados",
|
||||
"log_ignored_users": "Usuários ignorados",
|
||||
"log_ignore_user": "O registro de logs passará a ignorar o usuário {0}",
|
||||
"log_not_ignore_user": "O registro de logs não vai mais ignorar o usuário {0}",
|
||||
"log_ignore_chan": "O registro de logs passará a ignorar o canal {0}",
|
||||
"log_not_ignore_chan": "O registro de logs não vai mais ignorar o canal {0}",
|
||||
"streams_cleared": "Todas as transmissões seguidas neste servidor foram removidas.",
|
||||
"warn_weight": "Peso: {0}",
|
||||
"warn_count": "{0} atual, {1} total",
|
||||
"mass_ban_in_progress": "Banindo {0} usuários...",
|
||||
"mass_ban_completed": "{0} usuários banidos.",
|
||||
"reminder_server_list": "Lista de lembretes do servidor",
|
||||
"imageonly_enable": "Agora este canal é exclusivo para imagens.",
|
||||
"imageonly_disable": "Este canal não é mais exclusivo para imagens."
|
||||
}
|
@@ -331,7 +331,7 @@
|
||||
"owner": "Владелец",
|
||||
"owner_ids": "Идентификаторы владельцев",
|
||||
"region": "Регион",
|
||||
"remind": "Я напомню пользователю {0}, чтобы он {1} через {2} `({3:d.M.yyyy} в {4:HH:mm}`",
|
||||
"remind": "Я напомню пользователю {0}, чтобы он {1} через {2} `({3:d.M.yyyy} в {4:HH:mm})`",
|
||||
"remind_too_long": "Время напоминания превысило максимум.",
|
||||
"repeaters_none": "Никаких повторений не включено на этом сервере.",
|
||||
"repeat_invoke_none": "На этом сервере не найдено никаких повторяющихся сообщений.",
|
||||
@@ -593,8 +593,6 @@
|
||||
"log_all": "Регистрация всех событий в этом канале.",
|
||||
"log_disabled": "Регистрация событий отключена.",
|
||||
"log_events": "Журнал событий, на которые вы можете подписаться:",
|
||||
"log_ignore": "Ведение журнала игнорирует {0}",
|
||||
"log_not_ignore": "Ведение журнала не игнорирует {0}",
|
||||
"log_stop": "Прекращено ведение журнала события {0}.",
|
||||
"msg_not_found": "Сообщение не найдено.",
|
||||
"time_too_long": "Вы указали слишком много времени.",
|
||||
@@ -953,5 +951,29 @@
|
||||
"empty_page": "Эта страница пуста.",
|
||||
"pages": "Страницы",
|
||||
"favorites": "Любимое",
|
||||
"tags": "Теги"
|
||||
"tags": "Теги",
|
||||
"invalid_emoji_link": "Указанная ссылка либо не является изображением, либо превышает 256 КБ.",
|
||||
"emoji_add_error": "Ошибка добавления эмодзи. Либо у вас закончились слоты для смайликов, либо размер изображения не отвечающий требованиям.",
|
||||
"emoji_added": "Добавлен новый эмодзи: {0}",
|
||||
"boost_on": "На этом канале включены объявления бустов.",
|
||||
"boost_off": "Буст-объявления отключены.",
|
||||
"boostmsg_cur": "Текущее буст сообщение: {0}",
|
||||
"boostmsg_enable": "Включите буст сообщения, набрав {0}",
|
||||
"boostmsg_new": "Новый набор буст сообщений.",
|
||||
"boostdel_off": "Автоматическое удаление буст-сообщений отключено.",
|
||||
"boostdel_on": "Бусте сообщения будут удалены через {0} секунд.",
|
||||
"log_ignored_channels": "Игнорируемые каналы",
|
||||
"log_ignored_users": "Игнорируемые пользователи",
|
||||
"log_ignore_user": "Логирование будет игнорировать пользователя {0}",
|
||||
"log_not_ignore_user": "Логирование больше не будет игнорировать пользователя {0}",
|
||||
"log_ignore_chan": "Логирование будет игнорировать канал {0}",
|
||||
"log_not_ignore_chan": "Логирование больше не будет игнорировать канал {0}",
|
||||
"streams_cleared": "Все стримы, отслеживаемые на этом сервере, были удалены.",
|
||||
"warn_weight": "Вес: {0}",
|
||||
"warn_count": "{0} текущий, {1} всего",
|
||||
"mass_ban_in_progress": "Блокировка {0} пользователей...",
|
||||
"mass_ban_completed": "Заблокировано {0} пользователей.",
|
||||
"reminder_server_list": "Список напоминаний сервера",
|
||||
"imageonly_enable": "Этот канал теперь только для изображений.",
|
||||
"imageonly_disable": "Этот канал больше не предназначен только для изображений."
|
||||
}
|
@@ -1,30 +1,30 @@
|
||||
{
|
||||
"api_key_missing": "Відсутній АРІ ключ.",
|
||||
"quote_deleted": "Цитата #{0} видалена.",
|
||||
"redacted_too_long": "Зменшено, тому що це занадто довго.",
|
||||
"quote_deleted": "Цитату #{0} видалено.",
|
||||
"redacted_too_long": "Відредаговано, тому що це занадто довго.",
|
||||
"trigger": "Тригер",
|
||||
"response": "Відповідь",
|
||||
"fw_cleared": "Усі фільтровані слова і фільтровані слова налаштування каналу видалені.",
|
||||
"aar_disabled": "\n**Автопризначення ролі** на приєднання користувача зараз **вимкнена**.",
|
||||
"bandm": "Ви були забанені на {0} сервері.\nПричина: {1}",
|
||||
"fw_cleared": "Усі фільтровані слова і фільтровані слова налаштування каналу видалено.",
|
||||
"aar_disabled": "\n**Авто-призначення ролі** на приєднання користувача зараз **вимкнено**.",
|
||||
"bandm": "Ви отримали заборону на приєднання до сервер {0}.\nПричина: {1}",
|
||||
"banned_user": "Користувач заблокований",
|
||||
"byedel_off": "Автоматичне видалення прощального повідомлення було вимкнене.",
|
||||
"byedel_on": "Прощальне повідомлення буде видалене через {0} секунд.",
|
||||
"byemsg_cur": "Поточне прощальне повідомлення: {0}",
|
||||
"byemsg_enable": "Увімкнене прощальне повідомлення при написанні {0}",
|
||||
"byemsg_new": "Нова прощальне повідомлення встановлене.",
|
||||
"bye_off": "Прощальне оголошення вимкнене.",
|
||||
"byedel_off": "Автоматичне видалення прощального повідомлення було вимкнено.",
|
||||
"byedel_on": "Прощальне повідомлення буде видалене на протязі {0} секунд.",
|
||||
"byemsg_cur": "Теперішнє прощальне повідомлення: {0}",
|
||||
"byemsg_enable": "Увімкнено прощальне повідомлення при написанні {0}",
|
||||
"byemsg_new": "Нове прощальне повідомлення встановлено.",
|
||||
"bye_off": "Прощальне оголошення вимкнено.",
|
||||
"bye_on": "Прощальне повідомлення увімкнене на цьому каналі.",
|
||||
"cr": "Успішно створена роль {0}",
|
||||
"dr": "Роль {0} була видалена.",
|
||||
"dr": "Роль {0} було видалено.",
|
||||
"createtextchan": "Текстовий канал {0} створено.",
|
||||
"createvoich": "Голосовий канал {0} створено.",
|
||||
"deafen": "Успішно заглушений.",
|
||||
"delmsg_off": "Я не буду більше автоматично видаляти повідомлення яке успішно виконується командою на цьому сервері.",
|
||||
"delmsg_on": "Я буду автоматично видаляти повідомлення яке успішно виконується командою на цьому сервері.",
|
||||
"delmsg_channel_off": "Я ніколи не буду автоматично видаляти повідомлення яке успішно виконується командою на цьому сервері.",
|
||||
"delmsg_channel_on": "Я завжди буду автоматично видаляти повідомлення яке успішно виконується командою на цьому каналі, незважаючи на налаштування сервера.",
|
||||
"delmsg_channel_inherit": "Я завжди буду автоматично видаляти повідомлення яке успішно виконується командою на цьому каналі, тільки якщо ця можливість увімкнена на сервері.",
|
||||
"delmsg_off": "Я більше не буду автоматично видаляти повідомлення успішно виконаної команди.",
|
||||
"delmsg_on": "Я буду автоматично видаляти повідомлення успішно виконаної команди.",
|
||||
"delmsg_channel_off": "Я ніколи не буду автоматично видаляти повідомлення успішно виконаної команди.",
|
||||
"delmsg_channel_on": "Я завжди буду автоматично видаляти повідомлення, яке успішно виконаної команди на цьому каналі, незважаючи на налаштування сервера.",
|
||||
"delmsg_channel_inherit": "Я завжди буду автоматично видаляти повідомлення успішно виконаної команди на цьому каналі, тільки якщо ця можливість увімкнена на сервері.",
|
||||
"deltextchan": "Текстовий канал {0} видалено.",
|
||||
"delvoich": "Голосовий канал {0} видалено.",
|
||||
"fwall_start": "Я відправлятиму ПП усім власникам.",
|
||||
@@ -43,81 +43,81 @@
|
||||
"greetmsg_new": "Нове привітальне повідомлення встановлено.",
|
||||
"greet_off": "Привітальне оголошення вимкнено.",
|
||||
"greet_on": "Привітальне оголошення увімкнено на цьому каналі.",
|
||||
"hierarchy": "Ви не можете використовувати цю команду на користувачі з ролью вищою або рівною за Вашу (або мою) у ролевій ієрархії.",
|
||||
"hierarchy": "Ви не можете використовувати цю команду на користувачі, роль якого вища, однакова з твоєю(моєю) у ролевій ієрархії.",
|
||||
"invalid_format": "Неправильний формат введення.",
|
||||
"kickdm": "Ви були виганані з {0} сервера.\nПричина: {1}",
|
||||
"kickdm": "Вас було вигнано з сервера {0}.\nПричина: {1}",
|
||||
"kicked_user": "Користувач був вигнаний",
|
||||
"lang_list": "Список мов",
|
||||
"lang_set_bot": "Локаль бота по замовчуванню зараз {0} - {1}",
|
||||
"lang_set_bot_show": "Мова бота встановлено {0} - {1}",
|
||||
"lang_set": "Локаль Вашого сервера зараз {0} - {1}",
|
||||
"lang_set_bot": "Поточна мова бота за замовчуванням - {0} - {1} ",
|
||||
"lang_set_bot_show": "Мова бота встановлена {0} - {1}",
|
||||
"lang_set": "Поточна мова твого сервера - {0} - {1}",
|
||||
"message_sent": "Повідомлення відправлено.",
|
||||
"mute_error": "Я не маю необхідних прав для цього.",
|
||||
"mute_role_set": "Нова заглушена роль була встановлена.",
|
||||
"mute_role_set": "Нова роль, яка обмежує можливості була встановлена.",
|
||||
"prot_active": "Активний захист",
|
||||
"prot_disable": "{0} був **вимкнений** на цьому сервері.",
|
||||
"prot_enable": "{0} Увімкнено",
|
||||
"prot_none": "Захист не увімкнено.",
|
||||
"raid_cnt": "Поріг користувача повинен бути між {0} і {1}.",
|
||||
"raid_stats": "Якщо протягом {1} секунд приєднається {0} або більше користувачів, я {2} їх приєднаю.",
|
||||
"raid_stats": "Якщо протягом {1} секунд приєднається {0} або більше користувачів, я даватиму їм {2} ",
|
||||
"raid_time": "Час повинен бути між {0} і {1} секундами.",
|
||||
"rar": "Успішно видалено усі ролі у користувача {0}",
|
||||
"rc": "Колір ролі {0} був змінений.",
|
||||
"renrole": "Роль перейменовано",
|
||||
"reprm": "Вилучено відтворення повідомлення: {0}",
|
||||
"role_added": "Роль {0} була додана у список груп {1}.",
|
||||
"role_in_list": "Роль {0} уже у списку.",
|
||||
"self_assign_already": "У Вас уже є {0} роль.",
|
||||
"self_assign_excl": "Ролі, призначені самостійно, тепер ексклюзивні!",
|
||||
"self_assign_list": "Існує {0} ролей, які самостійно призначаються",
|
||||
"self_assign_not": "Ця роль не призначається самостійно.",
|
||||
"role_in_list": "Роль {0} уже є у списку.",
|
||||
"self_assign_already": "У Вас уже є роль {0}.",
|
||||
"self_assign_excl": "Самопризначені ролі тепер ексклюзивні!",
|
||||
"self_assign_list": "Існує {0} ролей, які самостійно призначаються.",
|
||||
"self_assign_not": "Ця роль не може призначатися самостійно.",
|
||||
"self_assign_not_have": "У вас немає ролі {0}.",
|
||||
"self_assign_no_excl": "Ролі, призначені самостійно, тепер не є ексклюзивними!",
|
||||
"self_assign_perms": "Я не можу додати Вам цю роль. `Я не можу додати ролі власникам або інші ролі, вищі за мою роль у ієрархії ролей. ''",
|
||||
"self_assign_no_excl": "Самопризначені ролі тепер не є ексклюзивними!",
|
||||
"self_assign_perms": "Я не можу надати вам цієї ролі. `Неможливо надати роль власнику сервера або людям з роллю вищою, ніж моя у ієрархії.`",
|
||||
"self_assign_rem": "{0} вилучено зі списку ролей, які можна самостійно призначити.",
|
||||
"self_assign_remove": "Ви більше не маєте ролі {0}.",
|
||||
"self_assign_success": "Тепер у вас є {0} роль.",
|
||||
"self_assign_remove": "У вас більше немає ролі {0}.",
|
||||
"self_assign_success": "Тепер у вас є роль {0}.",
|
||||
"adsarm_enable": "Увімкнено автоматичне видалення відповідей `{0} iam` та `{0} iamn`.",
|
||||
"adsarm_disable": "Бот більше не видалятиме відповіді `{0} iam` та `{0} iamn`.",
|
||||
"setrole": "Успішно додана роль {0} для користувача {1}",
|
||||
"set_channel_name": "Нове ім'я каналу встановлене.",
|
||||
"adsarm_disable": "Бот більше не видалятиме відповідь `{0} iam` та `{0} iamn`.",
|
||||
"setrole": "Успішно додано роль {0} для користувача {1}",
|
||||
"set_channel_name": "Нове ім'я каналу встановлено.",
|
||||
"shutting_down": "Вимикаюсь",
|
||||
"spam_ignore": "{0} ігноруватиме цей канал.",
|
||||
"spam_not_ignore": "{0} більше не ігноруватиме цей канал.",
|
||||
"spam_stats": "Якщо користувач публікує {0} однакові повідомлення поспіль, я їх {1} надсилаю.\n __IgnoredChannels__: {2}",
|
||||
"undeafen": "Успішно не приглушений.",
|
||||
"spam_stats": "Якщо користувач публікує {0} однакових повідомлень поспіль, я даватиму йому {1}.\n__Канали, що ігноруються__: {2}",
|
||||
"undeafen": "Надано дозвіл писати.",
|
||||
"username": "Ім'я користувача",
|
||||
"user_chat_mute": "{0} став **приглушений** у чаті.",
|
||||
"user_chat_unmute": "\n{0} став **не приглушений** у чаті.",
|
||||
"user_muted": "{0} став **приглушений** у текстовому і голосовому чаті.",
|
||||
"user_unmuted": "{0} став **не приглушений** у текстовому і голосовому чаті.",
|
||||
"user_voice_mute": "**голос приглушено** у {0}.",
|
||||
"user_voice_unmute": "**голос не приглушений** у {0}.",
|
||||
"sbdm": "Вас було мягко забанено на {0} сервері.\nПричина: {1}",
|
||||
"sb_user": "Користувач мягко забанений.",
|
||||
"better_luck": "Удачі наступного разу ^_^",
|
||||
"user_chat_mute": "{0} **заборонено писати** в чаті.",
|
||||
"user_chat_unmute": "\n{0} тепер **дозволено писати** у чаті.",
|
||||
"user_muted": "{0} тепер **має можливість писати та розмовляти** у текстовому і голосовому каналі.",
|
||||
"user_unmuted": "{0} тепер **заборонено писати та розмовляти** у текстовому і голосовому каналах.",
|
||||
"user_voice_mute": "**заборонено розмовляти** учаснику {0}.",
|
||||
"user_voice_unmute": "**дозволено розмовляти** учаснику {0}.",
|
||||
"sbdm": "Вас було тимчасово заблоковано на сервері {0}.\nПричина: {1}",
|
||||
"sb_user": "Користувач тимчасово заблокований.",
|
||||
"better_luck": "Нехай пощастить наступного разу ^_^",
|
||||
"roll": "Ви прокрутили {0}.",
|
||||
"br_win": "Вітаємо! Ви виграли {0}, викинувши більше {1}",
|
||||
"flip_guess": "Ви здогадалися! Ви виграли {0}",
|
||||
"flip_results": "Викинуто {0} монету. {1} орел, {2} решка.",
|
||||
"flip_guess": "Овва! Ви здогадались та перемогли! {0}",
|
||||
"flip_results": "Викинуто монету {0}. {1} орел, {2} решка.",
|
||||
"has": "{0} має {1}",
|
||||
"leaderboard": "Таблиця лідерів",
|
||||
"mass_award": "Нагороджені {0} користувачі {1} з ролі {2}.",
|
||||
"max_bet_limit": "Ви не можете поставити більше ніж {0}",
|
||||
"min_bet_limit": "Ви не можете поставити менше ніж {0}",
|
||||
"not_enough": "У вас не вистарчає {0}",
|
||||
"not_enough": "Вам не достатньо {0}",
|
||||
"raffled_user": "Розіграв користувач",
|
||||
"slot_bet": "Ставка",
|
||||
"slot_jackpot": "УРАААААААААА!!! Вітаю!!! х{0}",
|
||||
"slot_single": "Один {0}, х{1}",
|
||||
"slot_three": "Воу! Вдалий! Три підряд! х{0}",
|
||||
"slot_three": "Оце Так! Пощастило! Три одразу! х{0}",
|
||||
"slot_two": "Хороша робота! Два {0} - ставка х{1}",
|
||||
"won": "Перемога",
|
||||
"transactions": "Транзакція користувача {0}",
|
||||
"commands_instr": "Введіть `{0}h CommandName`, щоб побачити довідку для цієї заданої команди. наприклад `{0}h {0}8ball`",
|
||||
"command_not_found": "Я не можу знайти цю команду. Перш ніж повторити спробу, перевірте наявність команди.",
|
||||
"module_not_found": "Такого модуля не існує.",
|
||||
"module_not_found_or_cant_exec": "Або модуль не існує, або ви не можете запустити жодну з команд у зазначеному модулі.",
|
||||
"module_not_found_or_cant_exec": "Модуль не існує, або ви не можете запустити жодну з команд у зазначеному модулі.",
|
||||
"usage": "Використання",
|
||||
"options": "Налаштування",
|
||||
"requires": "Вимоги",
|
||||
@@ -125,14 +125,14 @@
|
||||
"blacklisted_tag_add": "Тег NSFW {0} тепер внесено до чорного списку.",
|
||||
"blacklisted_tag_remove": "Тег NSFW {0} більше не входить у чорний список.",
|
||||
"animal_race": "Гонки тварин",
|
||||
"animal_race_failed": "Не вдалося розпочати, оскільки бракує учасників.",
|
||||
"animal_race_failed": "Не вдалося розпочати, оскільки бракує учасників. ",
|
||||
"animal_race_join": "{0} приєднався як {1}",
|
||||
"animal_race_join_instr": "Щоб приєднатися до перегонів, введіть {0}jr.",
|
||||
"animal_race_starting": "Починається через {0} секунди або коли кімната заповнена.",
|
||||
"animal_race_won": "{0} як {1} Виграв гонку!",
|
||||
"dice_invalid_number": "Вказано недійсний номер. Ви можете кидати кості від {0} - {1} одночасно.",
|
||||
"dice_rolled": "викинуто {0}",
|
||||
"dice_rolled_num": "кості викинули: {0}",
|
||||
"dice_rolled_num": "Кубик викинув: {0}",
|
||||
"changes_of_heart": "Передумав",
|
||||
"claimed_by": "Прийнято",
|
||||
"divorces": "Розлучення",
|
||||
@@ -142,59 +142,59 @@
|
||||
"waifus_none": "Ніяких вайфу не було поки прийнято.",
|
||||
"waifus_top_waifus": "Найкращі Вайфу",
|
||||
"waifu_claimed": "прийнято {0} як вайфу для {1}!",
|
||||
"waifu_divorced_like": "Ви розлучились з вайфу якій Ви подобаєтесь. Ви безсердечний монстер. {0} получив {1} в якості компенсації.",
|
||||
"waifu_egomaniac": "Ви не можете встановити спорідненість до себе, Ви егоманьяк.",
|
||||
"waifu_fulfilled": "🎉 Їхня любов сповнилася! 🎉\nНове значення {0} - {1}!",
|
||||
"waifu_not_enough": "Ви повинні заплатити {0} чи більше щоб прийняти вайфу!",
|
||||
"waifu_not_yours": "Ця вайфу не Ваша.",
|
||||
"waifu_divorced_like": "Ви розійшлися з вайфу якій ви подобались. Ви безсердечні монстер. {0} отримав {1} в якості компенсації.",
|
||||
"waifu_egomaniac": "Ти не можеш бути спорідненим, ти его-маньяк.",
|
||||
"waifu_fulfilled": "🎉 Їхнє кохання взаємне! 🎉\nНове значення {0} - {1}!",
|
||||
"waifu_not_enough": "Ви повинні заплатити {0} чи більше, щоб купити цю вайфу! ",
|
||||
"waifu_not_yours": "Ця вайфу не твоя.",
|
||||
"waifu_not_yourself": "Ви не можете претендувати на себе.",
|
||||
"waifu_recent_divorce": "Ви розлучились недавно. Ви повинні почекати {0} годин і {1} хвилин щоб розлучитись знову.",
|
||||
"waifu_transfer_fail": "Ви або не є власником цієї вайфу, або не можете собі цього дозволити. В іншому випадку введення недійсне.",
|
||||
"waifu_transfer_success": "Претензія на {0} перенесена з {1} на {2}",
|
||||
"waifu_recent_divorce": "Ви розійшлися нещодавно. Ви повинні почекати {0} годин і {1} хвилин щоб розлучитись знову.",
|
||||
"waifu_transfer_fail": "Ви не є власником цієї вайфу, або не можете собі цього дозволити. В іншому випадку - введення недійсне.",
|
||||
"waifu_transfer_success": "Претендування на {0} перенесено з {1} на {2}",
|
||||
"nobody": "Ніхто",
|
||||
"waifu_divorced_notlike": "Ви розлучилися з вайфу, якій Ви не подобаєтесь. Ви отримали {0} назад.",
|
||||
"waifu_reset": "Статистика вашої вайфу були скинуті.",
|
||||
"waifu_reset_fail": "Не вдалось скинути статистику вайфу. Впевніться що у Вас достатньо грошей.",
|
||||
"waifu_reset_confirm": "Це скине статистику Вашої вайфу",
|
||||
"waifu_divorced_notlike": "Ви розійшлися з вайфу, якій ви не подобаєтесь. Ти повернув собі {0} назад.",
|
||||
"waifu_reset": "Статистика вашої вайфу були скинуто.",
|
||||
"waifu_reset_fail": "Не вдалось скинути статистику вайфу. Переконайтеся, що у вас достатньо коштів.",
|
||||
"waifu_reset_confirm": "Це скине статистику вашої вайфу.",
|
||||
"acrophobia": "Акрофобія",
|
||||
"acro_ended_no_sub": "Гра закінчилася без подань.",
|
||||
"acro_no_votes_cast": "Не подано голосів. Гра закінчилася без переможця.",
|
||||
"acro_ended_no_sub": "Гра закінчилася без подач.",
|
||||
"acro_no_votes_cast": "Не подано голоси. Гра закінчилася без переможця.",
|
||||
"acro_nym_was": "Акронім був {0}.",
|
||||
"acro_running": "Акрофобія уже запущена на цьому каналі.",
|
||||
"acro_started": "Гра почалась. Створіть речення з наступними акронімами: {0}.",
|
||||
"acro_started_footer": "У вас {0} секунд щоб зробити подання.",
|
||||
"acro_vote": "Голосуйте написавши номер подання",
|
||||
"acro_started_footer": "У вас {0} секунд, щоб зробити подачу.",
|
||||
"acro_vote": "Голосуйте написавши номер подачі",
|
||||
"acro_vote_cast": "{0} віддав свій голос!",
|
||||
"acro_winner": "Переможець {0} з {1} очками.",
|
||||
"acro_winner_only": "{0} переможець будучи єдиним хто зробив подання!",
|
||||
"acro_winner_only": "{0} переможець, адже він єдиний, хто зробив подачу!",
|
||||
"question": "Питання",
|
||||
"rps_draw": "Це нічия! Обидва обрали {0}",
|
||||
"rps_win": "{0} виграв! {1} переміг {2}",
|
||||
"submissions_closed": "Подання закрито",
|
||||
"submissions_closed": "Подачу закрито",
|
||||
"total_average": "Всього: {0} В середньому: {1}",
|
||||
"category": "Категорія",
|
||||
"cleverbot_disabled": "Розумний бот вимкнений на цьому сервері.",
|
||||
"cleverbot_enabled": "Розумний бот увімкнений на цьому сервері.",
|
||||
"curgen_disabled": "Генерація валюти була вимкнена на цьому сервері.",
|
||||
"curgen_enabled": "Генерація валюти була увімкнена на цьому сервері.",
|
||||
"curgen_pl": "{0} рандомний {1} появився!",
|
||||
"curgen_sn": "Рандомний {0} появився!",
|
||||
"game_started": "Гра розпочата",
|
||||
"curgen_pl": "{0} рандомний {1} по!",
|
||||
"curgen_sn": "Рандомний {0} з'явився!",
|
||||
"game_started": "Гру розпочато",
|
||||
"hangman_game_started": "Шибеник розпочався",
|
||||
"hangman_running": "Шибеник наразі розпочався на цьому каналі.",
|
||||
"hangman_types": "Список \"{0}hangman\" правил пишуть:",
|
||||
"no_results": "Немає результатів",
|
||||
"picked": "вибрано {0}",
|
||||
"planted": "{0} встановлено {1}",
|
||||
"trivia_already_running": "Дрібниці наразі розпочався на цьому каналі.",
|
||||
"trivia_already_running": "\"Дрібниці\" наразі розпочато на цьому каналі.",
|
||||
"trivia_game": "Дрібниці",
|
||||
"trivia_guess": "{0} вгадав це! Відповідь була: {1}",
|
||||
"trivia_none": "Дрібниці не запущена на цьому сервері.",
|
||||
"trivia_guess": "{0} вгадав! Відповідь була: {1}",
|
||||
"trivia_none": "\"Дрібниці\" не запущена на цьому сервері.",
|
||||
"trivia_points": "{0} має {1} очків",
|
||||
"trivia_stopping": "Зупинившись після цього питання.",
|
||||
"trivia_times_up": "Час вийшов! Правильною відповіддю було {0}",
|
||||
"trivia_stopping": "Зупинитись після цього питання.",
|
||||
"trivia_times_up": "Час вийшов! Правильна відповідь {0}",
|
||||
"ttt_against_yourself": "Ви не можете грати проти себе.",
|
||||
"ttt_already_running": "Хрестики-нулики наразі розпочався на цьому сервері.",
|
||||
"ttt_already_running": "Хрестики-нулики наразі розпочато на цьому сервері.",
|
||||
"ttt_a_draw": "Нічия",
|
||||
"ttt_created": "створив гру в Хрестики-нулики.",
|
||||
"ttt_has_won": "{0} виграв!",
|
||||
@@ -206,7 +206,7 @@
|
||||
"attempting_to_queue": "Спроба поставити в чергу {0} пісень у черзі ...",
|
||||
"fairplay": "Чесна гра",
|
||||
"finished_song": "Пісня завершилась",
|
||||
"id": "Id",
|
||||
"id": "ID",
|
||||
"invalid_input": "Не вірне введення.",
|
||||
"must_be_in_voice": "Ви повинні бути в голосовому каналі на цьому сервері.",
|
||||
"name": "Ім'я",
|
||||
@@ -225,25 +225,25 @@
|
||||
"arm_enable": "Увімкнене використання ВСІХ МОДУЛІВ для ролі {0}.",
|
||||
"asm_disable": "Вимкнене використання ВСІХ МОДУЛІВ на цьому сервері.",
|
||||
"asm_enable": "Увімкнене використання ВСІХ МОДУЛІВ на цьому сервері.",
|
||||
"aum_disable": "Вимкнене використання ВСІХ МОДУЛІВ для користувача {0}.",
|
||||
"aum_enable": "Увімкнене використання ВСІХ МОДУЛІВ для користувача {0}.",
|
||||
"blacklisted": "Добавлено у чорний список {0} з ID {1}",
|
||||
"aum_disable": "Вимкнено використання ВСІХ МОДУЛІВ для користувача {0}.",
|
||||
"aum_enable": "Увімкнено використання ВСІХ МОДУЛІВ для користувача {0}.",
|
||||
"blacklisted": "Додано у чорний список {0} з ID {1}",
|
||||
"unblacklisted": "Вилучено з чорного списку {0} з ID {1}",
|
||||
"cmdcd_add": "Команда {0} має {1} секунд відновлення.",
|
||||
"cmdcd_cleared": "Команда {0} не має відновлення і всі існуючі відновлення були очищені.",
|
||||
"cmdcd_add": "Команда {0} має {1} секунд для відновлення.",
|
||||
"cmdcd_cleared": "Команда {0} не має відновлення, і всі існуючі відновлення були очищені.",
|
||||
"cmdcd_none": "Відновлення команд не встановлено.",
|
||||
"cx_disable": "Вимкнено використання {0} {1} на каналі {2}.",
|
||||
"cx_enable": "Увімкнено використання {0} {1} на каналі {2}.",
|
||||
"filter_word_add": "Додане слово {0} в список фільтрованих слів.",
|
||||
"filter_word_add": "Додано слово {0} в список фільтрованих слів.",
|
||||
"filter_word_list": "Список фільтрованих слів",
|
||||
"filter_word_remove": "Вилучено слово {0} з списку фільтрованих слів.",
|
||||
"invalid_second_param_between": "Не вірний другий параметер. (Повинен бути числом між {0} і {1})",
|
||||
"invite_filter_channel_off": "Фільтр запрошень вимкнений на цьому каналі.",
|
||||
"invite_filter_channel_on": "Фільтр запрошень увімкнений на цьому каналі.",
|
||||
"invite_filter_server_off": "Фільтр запрошень вимкнений на цьому сервері.",
|
||||
"invite_filter_server_on": "Фільтр запрошень вимкнений на цьому сервері.",
|
||||
"moved_permission": "Перенесені дозволи {0} з #{1} до #{2}",
|
||||
"perm_not_found": "Не можу знайти дозволи на індексі #{0}",
|
||||
"filter_word_remove": "Вилучено слово {0} зі списку фільтрованих слів.",
|
||||
"invalid_second_param_between": "Не вірний другий параметер. (Повинно бути числом між {0} і {1})",
|
||||
"invite_filter_channel_off": "Фільтрацію запрошень **вимкнено** на цьому каналі. ",
|
||||
"invite_filter_channel_on": "Фільтрацію запрошень **увімкнено** на цьому каналі. ",
|
||||
"invite_filter_server_off": "Фільтрацію запрошень **вимкнено** на цьому сервері.",
|
||||
"invite_filter_server_on": "Фільтрацію запрошень **увімкнено** на цьому сервері.",
|
||||
"moved_permission": "Дозвіл {0} перенесено з #{1} до #{2}",
|
||||
"perm_not_found": "Не можу знайти дозвіл з індексом #{0}",
|
||||
"of_command": "команда",
|
||||
"of_module": "модуль",
|
||||
"page": "Сторінка {0}",
|
||||
@@ -251,22 +251,22 @@
|
||||
"permrole_not_set": "Роль дозволу не встановлена.",
|
||||
"permrole_reset": "Роль дозволу скинута.",
|
||||
"permrole_changed": "Тепер для редагування дозволів користувачам потрібна роль {0}.",
|
||||
"perm_out_of_range": "Дозволи не знайдені на цьому індексі.",
|
||||
"removed": "вилучений дозвіл #{0} - {1}",
|
||||
"rx_disable": "Виключене використання {0} {1} для {2} ролі.",
|
||||
"rx_enable": "Увімкнене використання {0} {1} для {2} ролі.",
|
||||
"perm_out_of_range": "Не знайдено дозвіл з вказаним дозволом.",
|
||||
"removed": " дозвіл видалено #{0} - {1}",
|
||||
"rx_disable": "Вимкнено використання {0} {1} для ролі {2}.",
|
||||
"rx_enable": "Увімкнено використання {0} {1} для ролі {2}.",
|
||||
"sec": "сек.",
|
||||
"sx_disable": "Вимкнене використання {0} {1} на цьому сервері.",
|
||||
"sx_enable": "Увімкнене використання {0} {1} на цьому сервері.",
|
||||
"uneditable": "не підлягає редагуванню",
|
||||
"ux_disable": "Вимкнене використання {0} {1} для користувача {2}.",
|
||||
"ux_enable": "Увімкнене використання {0} {1} для користувача {2}.",
|
||||
"sx_disable": "Вимкнено використання {0} {1} на цьому сервері.",
|
||||
"sx_enable": "Увімкнено використання {0} {1} на цьому сервері.",
|
||||
"uneditable": "не редагується",
|
||||
"ux_disable": "Вимкнено використання {0} {1} для користувача {2}.",
|
||||
"ux_enable": "Увімкнено використання {0} {1} для користувача {2}.",
|
||||
"verbose_false": "Я більше не буду показувати попередження про дозволи.",
|
||||
"verbose_true": "Тепер я буду показувати попередження про дозволи.",
|
||||
"word_filter_channel_off": "Фільтрування слів вимкнена на цьому каналі.",
|
||||
"word_filter_channel_on": "Фільтрування слів увімкнена на цьому каналі.",
|
||||
"word_filter_server_off": "Фільтрування слів вимкнено на цьому сервері.",
|
||||
"word_filter_server_on": "ФІльтрування слів увімкнено на цьому сервері.",
|
||||
"word_filter_channel_off": "Фільтрація слів вимкнена на цьому каналі.",
|
||||
"word_filter_channel_on": "Фільтрація слів увімкнена на цьому каналі.",
|
||||
"word_filter_server_off": "Фільтрація слів вимкнена на цьому сервері.",
|
||||
"word_filter_server_on": "ФІльтрація слів увімкнена на цьому сервері.",
|
||||
"abilities": "Здібності",
|
||||
"chapters": "Розділи",
|
||||
"comic_number": "Комікс #",
|
||||
@@ -289,7 +289,7 @@
|
||||
"min_max": "Мін/Макс",
|
||||
"original_url": "Оригінальна URL-адреса",
|
||||
"pokemon_ability_none": "Здатності не знайдено.",
|
||||
"pokemon_none": "Покемонів не знайдено.",
|
||||
"pokemon_none": "Покемон не знайдено.",
|
||||
"rating": "Рейтинг",
|
||||
"score": "Оцінка:",
|
||||
"search_for": "Шукати:",
|
||||
@@ -310,7 +310,7 @@
|
||||
"convertlist": "Одиниці виміру, які можуть бути використані конвертером",
|
||||
"convert_not_found": "Не можливо конвертувати {0} до {1}: одиниця виміру не знайдена",
|
||||
"convert_type_error": "Не можливо конвертувати {0} до {2}: типи одиниць виміру не одинакові",
|
||||
"created_at": "Створено о",
|
||||
"created_at": "Створено",
|
||||
"created_by": "Створено {0}",
|
||||
"custom_emojis": "Кастомні емодзі",
|
||||
"error": "Помилка",
|
||||
@@ -340,7 +340,7 @@
|
||||
"serverid": "{0} цього сервера {1}",
|
||||
"server_info": "Інформація про сервер",
|
||||
"shard": "Черепок",
|
||||
"showemojis_none": "Спеціальні емодзі не знайдені.",
|
||||
"showemojis_none": "Спеціальні емодзі не знайдено.",
|
||||
"text_channels": "Текстовий канал",
|
||||
"uptime": "Час роботи",
|
||||
"userid": "{0} користувача {1} є {2}",
|
||||
@@ -353,11 +353,11 @@
|
||||
"poll_voted": "{0} проголосував.",
|
||||
"poll_invalid_input": "Не вірне введення. Ви повині мати питання і хочаб дві відповіді, розділенні за допомогою `;`.",
|
||||
"x_votes_cast": "{0} всього голосів.",
|
||||
"pick_pl": "Підніми їх написавши `{0}pick`",
|
||||
"pick_pl": "Підніми їх, написавши `{0}pick`",
|
||||
"pick_sn": "Підніми це написавши `{0}pick`",
|
||||
"sql_confirm_exec": "Підтвердьте виконання наведеної нижче команди SQL",
|
||||
"no_vcroles": "Ролі голосового каналу відсутні.",
|
||||
"user_muted_time": "{0} був **заглушений** від текстового і голосового чату на {1} хвилин.",
|
||||
"user_muted_time": "{0} тепер **заборонено писати і розмовляти** в текстовому і голосового каналах на {1} хвилин.",
|
||||
"vcrole_added": "Користувачі що приєднаються до {0} голосового каналу получать {1} роль.",
|
||||
"vcrole_removed": "Користувачі що приєднаються до {0} голосового каналу більше не получать роль.",
|
||||
"vc_role_list": "Ролі голосового каналу",
|
||||
@@ -373,7 +373,7 @@
|
||||
"server": "Сервер",
|
||||
"startcmdlist_none": "Команд запуску немає на цій сторінці.",
|
||||
"startcmds_cleared": "Очищені всі команди запуску.",
|
||||
"unbanned_user": "Користувач {0} був розбанений.",
|
||||
"unbanned_user": "Користувача {0} розблоковано.",
|
||||
"user_not_found": "Користувач не знайдений",
|
||||
"user_warned": "Користувач {0} був попереджений.",
|
||||
"user_warned_and_punished": "Користувач {0} був попереджений і {1} покарання було застосоване.",
|
||||
@@ -390,13 +390,13 @@
|
||||
"warn_punish_rem": "Маючи {0} попереджень більше не каратиметься покаранням.",
|
||||
"warn_punish_set": "Я застосую {0} покарання для користувача з {1} попередженнями.",
|
||||
"cant_apply_punishment": "Не можу застосувати покарання. Будь ласка переконайтесь що у вас є усі потрібні дозволи, і що моя роль вище всіх інших у настройках сервера.",
|
||||
"clpa_fail_already": "Можливо Ви уже получили нагороду цього місяця. Ви можете получити нагороду лише раз в місць, якщо не збільшите свою заставу.\nВи можете перевірити використавши команду `.curtrs`.",
|
||||
"clpa_fail_already": "Можливо ви вже отримували нагороду цього місяця. Ви можете отримати нагороду лише раз у місяць, якщо не збільшиш свою заставу.\nТи можеш перевірити, використавши команду `.curtrs`.",
|
||||
"clpa_fail_already_title": "Вже нагороджений",
|
||||
"clpa_fail_conn": "Ваш обліковий запис Discord може не бути підключеним до Patreon. Якщо ви не впевнені, що це означає, або не знаєте, як це підключити - вам потрібно перейти на [сторінку налаштувань облікового запису Patreon] (https://patreon.com/settings/account) і натиснути кнопку «Підключитися до Discord'y» .",
|
||||
"clpa_fail_conn": "Ваш обліковий запис Discord може не бути підключеним до Patreon. Якщо ви не впевнені, що це значить, або не знаєте як це підключити - вам потрібно перейти на [сторінку налаштувань облікового запису Patreon] (https://patreon.com/settings/account) і натиснути кнопку «Підключитися до Discord'y» .",
|
||||
"clpa_fail_conn_title": "Discord аккаунт не підключенний",
|
||||
"clpa_fail_sup": "Щоб мати право на винагороду, ви повинні підтримати проект на patreon. Ви можете використати команду {0}, щоб отримати посилання.",
|
||||
"clpa_fail_sup": "Щоб мати право на винагороду, ви повинні підтримати проєкт на patreon. Ви можете використати команду {0}, щоб отримати посилання.",
|
||||
"clpa_fail_sup_title": "Не підтримується",
|
||||
"clpa_fail_wait": "Вам потрібно зачекати 5-10 хвилин після того, як ви зробите свою заставу (і під’єднаєте свій обліковий запис розбрату до свого патріона), щоб ваша валюта з’явилася.",
|
||||
"clpa_fail_wait": "Вам потрібно зачекати 5-10 хвилин після того, як підтвердите свою передплату (і під’єднаєте свій обліковий запис дискорд до свого патреону), щоб ваша валюта з’явилася.",
|
||||
"clpa_fail_wait_title": "Зачекайте деякий час",
|
||||
"clpa_too_early": "Нагорода може бути прийняти до або після 5того числа кожного місяця.",
|
||||
"shop": "Магазин",
|
||||
@@ -412,7 +412,7 @@
|
||||
"out_of_stock": "Не має в наявності.",
|
||||
"random_unique_item": "Рандомний унікальний предмет.",
|
||||
"shop_buy_error": "Помилка відправки предмета. Вам повернуто кошти.",
|
||||
"shop_item_not_found": "Не знайдені предмети з таким індексом.",
|
||||
"shop_item_not_found": "Не знайдено предмети з таким індексом.",
|
||||
"shop_item_purchase": "Купівля предмета успішна.",
|
||||
"shop_item_rm": "Предмет з магазину вилучений",
|
||||
"shop_item_wrong_type": "Цей запис про магазин не підтримує додавання товару.",
|
||||
@@ -489,7 +489,7 @@
|
||||
"club_created": "Клуб {0} успішно створенний!",
|
||||
"club_not_exists": "Такого клубу не існує.",
|
||||
"club_applied": "Ви подали заявку на членство в клубі {0}.",
|
||||
"club_apply_error": "Помилка застосування. Ви або вже є членом клубу, або не відповідаєте вимогам мінімального рівня, або вам заборонили цей клуб.",
|
||||
"club_apply_error": "Помилка застосування. Ви вже є членом клубу, або не відповідаєте вимогам мінімального рівня, також можливо вам заборонено вхід у цей клуб.",
|
||||
"club_accepted": "Прийнято користувача {0} до клубу.",
|
||||
"club_accept_error": "Користувач не знайдений",
|
||||
"club_left": "Ви покинули клуб",
|
||||
@@ -498,7 +498,7 @@
|
||||
"club_user_kick_fail": "Помилка вигнання. Ви або не є власником клубу, або цього користувача немає у вашому клубі.",
|
||||
"club_user_banned": "Користувачу {0} заборонено відвідувати клуб {1}.",
|
||||
"club_user_ban_fail": "Не вдалося заборонити. Ви або не є власником клубу, або цей користувач не перебуває у вашому клубі або не подає до нього звернення.",
|
||||
"club_user_unbanned": "Незаблокований користувач {0} у клубі {1}.",
|
||||
"club_user_unbanned": "Не заблокований користувач {0} у клубі {1}.",
|
||||
"club_user_unban_fail": "Не вдалося скасувати заборону. Ви або не є власником клубу, або цей користувач не перебуває у вашому клубі або не подає до нього звернення.",
|
||||
"club_level_req_changed": "Вимогу щодо рівня клубу змінено на {0}",
|
||||
"club_level_req_change_error": "Не вдалося змінити вимогу до рівня.",
|
||||
@@ -567,14 +567,14 @@
|
||||
"cleared": "Всі {0} кастомні реакції на цьому сервері були видалені.",
|
||||
"crr_reset": "Кастомна реакція з цим id {0} більше не додаватиме реакції.",
|
||||
"crr_set": "Кастомна реакція з цим id {0} буде додавати наступне повідомлення до відповіді: {1}",
|
||||
"invalid_emojis": "Усі вказані вами емодзі недійсні.",
|
||||
"invalid_emojis": "Усі вказані емодзі недійсні.",
|
||||
"aliases_cleared": "Усі {0} псевдоніми на цьому сервері видалено.",
|
||||
"vcrole_not_found": "Цей голосовий канал не має VcRole.",
|
||||
"attachments": "Вкладення",
|
||||
"avatar_changed": "Аватар зміненно",
|
||||
"banmsg_disabled": "Повідомлення про бан вимкнено. Ви можете включити їх, встановивши banmsg на щось інше, ніж '-'.",
|
||||
"banmsg_disabled": "Сповіщення про бан вимкнено. Ви можете увімкнути його, встановивши banmsg на щось інше, ніж '-'.",
|
||||
"banmsg_default": "Повідомлення про бан не встановлено. Буде використано поведінку за замовчуванням.",
|
||||
"banned_pl": "забанений",
|
||||
"banned_pl": "заблокований",
|
||||
"bot_name": "Ім'я бота змінене на {0}",
|
||||
"bot_status": "Статус бота змінений на {0}",
|
||||
"ch_name_change": "Ім'я каналу змінене",
|
||||
@@ -587,24 +587,22 @@
|
||||
"images_loading": "Зображення будуть завантажені протягом декількох секунд. ",
|
||||
"insuf_perms_i": "У мене недостатньо дозволів.",
|
||||
"insuf_perms_u": "У Вас недостатні дозволи.",
|
||||
"lang_set_fail": "Не вдалося налаштувати локаль. Поверніться до допомоги цієї команди.",
|
||||
"lang_set_fail": "Не вдалося налаштувати поточну мову. Повернися в команду-помічник.",
|
||||
"lang_set_show": "Мова цього сервера встановлена на {0} - {1}",
|
||||
"log": "Запис події {0} у цей канал.",
|
||||
"log_all": "Запис усіх подій на цьому каналі.",
|
||||
"log_disabled": "Запис подій вимкнено.",
|
||||
"log_events": "Журнал подій, на які можна підписатися:",
|
||||
"log_ignore": "Запис подій ігноруватиметься {0}",
|
||||
"log_not_ignore": "Запис подій не ігноруватиметься {0}",
|
||||
"log_stop": "Зупинено запис подій {0}.",
|
||||
"msg_not_found": "Повідомлення не знайдено.",
|
||||
"time_too_long": "Вказаний Вами час надто довгий.",
|
||||
"time_too_long": "Вказаний тобою час надто довгий.",
|
||||
"log_vc_moved": "{0} переміщено з {1} на {2} голосовий канал",
|
||||
"msg_del": "Повідомлення видалено в #{0}",
|
||||
"msg_update": "Повідомлення оновлено в #{0}",
|
||||
"muted_pl": "Заглушений",
|
||||
"muted_sn": "Заглушений",
|
||||
"mute_role": "поточна заглушена роль {0}",
|
||||
"mute_perms": "Ви не можете ігнорувати користувача, у ролі якого вище вашої найвищої ролі в ієрархії ролей, якщо ви не є власником сервера.",
|
||||
"muted_sn": "Заглушений ",
|
||||
"mute_role": "поточна роль-заборона {0}",
|
||||
"mute_perms": "Ви не можете заборонити писати користувачу, роль якого вища вашої в ієрархії ролей, якщо ви не є власником сервера.",
|
||||
"new_msg": "Нове повідомлення",
|
||||
"new_nick": "Новий нік",
|
||||
"new_topic": "Нова тема",
|
||||
@@ -633,14 +631,14 @@
|
||||
"set_stream": "Новий стрім встановлений!",
|
||||
"set_topic": "Нова тема каналу встановлена.",
|
||||
"shard_reconnecting": "Черепок {0} перепідключення.",
|
||||
"soft_banned_pl": "мягкий-бан",
|
||||
"soft_banned_pl": "тимчасовий бан",
|
||||
"text_chan_created": "Текстовий канал створений.",
|
||||
"text_chan_destroyed": "Текстовий канал знищений.",
|
||||
"duration": "Тривалість",
|
||||
"unmuted_sn": "Не заглушений",
|
||||
"unable_to_dm_user": "ПП користувачу провалилось.",
|
||||
"username_changed": "Ім'я користувача змінено",
|
||||
"user_banned": "Користувач забанений",
|
||||
"user_banned": "Користувач заблокований",
|
||||
"user_joined": "Користувач приєднався",
|
||||
"user_left": "Користувач покинув",
|
||||
"user_role_add": "Роль користувача додана",
|
||||
@@ -654,7 +652,7 @@
|
||||
"xmuted_text": "Користувач {0} з текстового чата {1}",
|
||||
"xmuted_text_and_voice": "Користувач {0} з текстового і голосового чату {1}",
|
||||
"xmuted_voice": "Користувач {0} з голосового чату {1}",
|
||||
"user_unbanned": "Користувач розбанений",
|
||||
"user_unbanned": "Користувач розблокований",
|
||||
"presence_updates": "Оновлення присутності",
|
||||
"awarded": "нагороджений {0} до {1}",
|
||||
"deck_reshuffled": "Колода перетасована.",
|
||||
@@ -670,10 +668,10 @@
|
||||
"commandlist_regen": "Список команд відновлено.",
|
||||
"desc": "Опис",
|
||||
"cant_dm": "Я не можу надіслати ПП. Переконайтеся, що Ваші ПП відкриті. Перейдіть до опцій ** (кнопка шестерні) -> Конфіденційність та безпека -> Дозволити прямі повідомлення від членів сервера **",
|
||||
"donate": "Ви можете підтримати проект NadekoBot на\nПатреон <{0}> або\nPaypal <{1}>\nНе забудьте залишити у повідомленні своє ім’я або ідентифікатор Discord.\n\n** Дякую ** ♥ ️",
|
||||
"donate": "Ви можете підтримати проєкт NadekoBot на\nПатреон <{0}> або\nPaypal <{1}>\nНе забудьте залишити у повідомленні своє ім’я або ідентифікатор Discord.\n\n** Дякую ** ♥ ️",
|
||||
"guide": "** Список команд **: <{0}>\n** Посібники та документи щодо розміщення можна знайти тут **: <{1}>",
|
||||
"list_of_modules": "Список модулів",
|
||||
"autohentai_started": "Автохентай почався. Повторно публікуйте кожні {0} з одним із таких тегів:\n{1}",
|
||||
"autohentai_started": "Авто-хентай почався. Повторно публікуйте кожні {0} з одним із таких тегів:\n{1}",
|
||||
"tag": "Тег",
|
||||
"animal_race_full": "Гонка повна! Починаєм негайно.",
|
||||
"animal_race_join_bet": "{0} приєднався як {1} і зробив ставку {2}!",
|
||||
@@ -684,9 +682,9 @@
|
||||
"waifu_affinity_already": "ваша близкість уже налаштована на цю вайфу, або ви намагаєтесь видалити свою спорідненість, не маючи її.",
|
||||
"waifu_affinity_changed": "змінили свою близкість з {0} на {1}.\n\n*Це морально сумнівно.*🤔",
|
||||
"waifu_affinity_cooldown": "Вам потрібно почекати {0} годин і {1} хвилин, щоб знову змінити свою близькість.",
|
||||
"waifu_affinity_reset": "Ваша близкість скинута. У тебе більше немає людини, яка тобі подобається.",
|
||||
"waifu_affinity_reset": "Ваша близкість скинута. У вас більше немає людини, яка вам подобається.",
|
||||
"waifu_affinity_set": "хоче бути вайфу {0}. Ой <3",
|
||||
"waifu_isnt_cheap": "Жодна вайфу не така дешева. Ви повинні сплатити щонайменше {0}, щоб отримати вайфу, навіть якщо їх фактична вартість нижча.",
|
||||
"waifu_isnt_cheap": "Жодної вайфу за вказаною ціною немає. Ви повинні сплатити щонайменше {0}, щоб отримати вайфу, навіть якщо їх фактична вартість нижча.",
|
||||
"waifu_reset_price": "Ціна: {0}",
|
||||
"animal_race_already_started": "Гонка Тварин вже запущена.",
|
||||
"failed_loading_question": "Не вдалося завантажити запитання.",
|
||||
@@ -719,7 +717,7 @@
|
||||
"atl_ad_started": "Почався автоматичний переклад повідомлень на цьому каналі. Повідомлення користувачів будуть автоматично видалені.",
|
||||
"atl_removed": "Вашу мову автоперекладу вилучено.",
|
||||
"atl_set": "Вашу мову автоматичного перекладу встановлено на {0}> {1}",
|
||||
"atl_started": "Почався автоматичний переклад повідомлень на цьому каналі.",
|
||||
"atl_started": "Розпочато автоматичний переклад повідомлень на цьому каналі.",
|
||||
"atl_stopped": "Зупинено автоматичний переклад повідомлень на цьому каналі.",
|
||||
"bad_input_format": "Неправильний формат введення або щось пішло не так.",
|
||||
"card_not_found": "Не вдалося знайти цю картку.",
|
||||
@@ -729,7 +727,7 @@
|
||||
"dropped": "Кинуто",
|
||||
"error_occured": "Виникла помилка.",
|
||||
"failed_finding_anime": "Не вдалося знайти це аніму.",
|
||||
"failed_finding_manga": "Не вдалося знайти цю мангу.",
|
||||
"failed_finding_manga": "Не вдалося знайти цю манґу.",
|
||||
"imdb_fail": "Не вдалося знайти цей фільм.",
|
||||
"invalid_lang": "Недійсне джерело або ціль мови.",
|
||||
"jokes_not_loaded": "Жарти не загружені.",
|
||||
@@ -805,9 +803,9 @@
|
||||
"warn_expire_set_clear": "Попередження буде очищено через {0} днів.",
|
||||
"warn_expire_reset": "Термін дії попереджень більше не припиняється.",
|
||||
"warn_punish_set_timed": "Я застосую {0} покарання для {2} до користувачів із попередженнями {1}.",
|
||||
"clpa_obsolete": ": tada: **Винагороди валюти Patreon тепер автоматичні!**: tada:\nЦя команда тепер застаріла.\nЯкщо ви не отримали винагороду за заставу цього місяця, нижче наведено деякі причини, чому це могло бути.",
|
||||
"clpa_obsolete": ": tada: **Винагороди валюти Patreon тепер автоматичні!**: tada:\nЦя команда тепер застаріла.\nЯкщо ви не отримали винагороду за внесок цього місяця, нижче наведено деякі причини, чому це могло бути.",
|
||||
"time_new": "Час",
|
||||
"timezone_db_api_key": "Вам потрібно активувати ключ API TimezoneDB. Ви можете зробити це, натиснувши посилання, яке ви отримали в електронному листі, з ключем API.",
|
||||
"timezone_db_api_key": "Вам потрібно активувати ключ API TimezoneDB. Ви можете зробити це, натиснувши посилання, яке ви отримали в електронному листі з ключем API.",
|
||||
"rolehoist_enabled": "Роль {0} тепер відображається окремо від користувачів у мережі.",
|
||||
"rolehoist_disabled": "Роль {0} більше не відображається окремо від користувачів у мережі.",
|
||||
"shop_role_already_bought": "Ви вже купили цю роль.",
|
||||
@@ -818,7 +816,7 @@
|
||||
"user_nick": "Псевдонім користувача {0} змінено на {1}",
|
||||
"perm_override": "Для виконання команди {1} користувачам потрібен дозвіл {0}.",
|
||||
"define_unknown": "Не можу знайти визначення цього терміну.",
|
||||
"queue_stopped": "Плеєр зупинений. Використовуйте команду {0}, щоб почати відтворення.",
|
||||
"queue_stopped": "Плеєр зупинено. Використовуйте команду {0}, щоб почати відтворення.",
|
||||
"removed_song_error": "Пісня в цьому індексі не існує",
|
||||
"nunchi_started": "Гра Нунчі розпочалася з {0} учасниками.",
|
||||
"bot_strings_reloaded": "Строки ботів були перезавантажені.",
|
||||
@@ -858,7 +856,7 @@
|
||||
"failed_finding_novel": "Не можу знайти цю новелу. Переконайтеся, що ви ввели точне повне ім’я та воно існує на сайті novelupdates.com",
|
||||
"roll_duel_challenge": "{1} викликав на дуель {2}",
|
||||
"roll_duel": "Дуель",
|
||||
"roll_duel_no_funds": "Або Вам, або вашому опонентові не вистачає коштів.",
|
||||
"roll_duel_no_funds": "Вам, або вашому опонентові не вистачає коштів.",
|
||||
"roll_duel_timeout": "Виклик на дуель не прийнято.",
|
||||
"roll_duel_already_challenged": "Цей користувач уже викликав Вас на дуель.",
|
||||
"account_not_found": "Цей обліковий запис не існує або має статус приватного.",
|
||||
@@ -892,32 +890,32 @@
|
||||
"log_vc_joined": "{0} приєднався до {1} голосового каналу",
|
||||
"log_vc_left": "{0} покинув {1} голосовий канал",
|
||||
"protection_not_running": "Захист {0} не ввімкнено.",
|
||||
"anti_alt_status": "Будь -який користувач, що приєднується до сервера з обліковим записом, не старшим за {0}, до нього застосує таку дію: {1}\nНаразі покараний: {2}",
|
||||
"anti_alt_status": "Будь-який користувач, що приєднується до сервера з обліковим записом, не старшим за {0}, до нього застосовується така дія: {1}\nНаразі покараних: {2}",
|
||||
"mass_take": "Взято {0} від {1} користувачів у ролі {2}.",
|
||||
"_8ball": "Магічна куля",
|
||||
"repeating_none": "Плеєр зупиниться, коли буде досягнуто кінця черги.",
|
||||
"repeating_queue": "Плеєр повторить чергу.",
|
||||
"current_music_quality": "Наразі встановлена якість музики: {0}",
|
||||
"music_quality_set": "Якість музики встановлено на {0}. Щоб зміни вступили в силу, вам доведеться знищити та перезапустити музичний плеєр.",
|
||||
"music_quality_set": "Якість музики встановлено на {0}. Щоб зміни вступили в силу, вам доведеться очистити та перезапустити музичний плеєр.",
|
||||
"blacklisted_users": "Користувачі з чорного списку",
|
||||
"blacklisted_channels": "Канали з чорного списку",
|
||||
"blacklisted_servers": "Сервера з чорного списку",
|
||||
"_class": "Клас",
|
||||
"stream_not_following_any": "Ви не стежите за будь-якими стрімами.",
|
||||
"stream_not_following_any": "Ви не стежите ні за якими стрімами.",
|
||||
"stream_message_set_all": "Усі {0} стріми, за якими стежать, тепер мають зазначене повідомлення-оголошення.",
|
||||
"repeater_exceed_limit": "На одному сервері не може бути більше {0} повторювачів.",
|
||||
"repeater_remove_fail": "Не вдалося видалити повторювач для цього індексу. Або ви вказали недійсний індекс, або ретранслятор на той момент перебував у стані виконання, в цьому випадку повторіть спробу за кілька секунд.",
|
||||
"repeater_remove_fail": "Не вдалося видалити повторювач для цього індексу. Ви вказали не дійсний індекс, або ретранслятор на той момент перебував у стані виконання, в цьому випадку повторіть спробу за кілька секунд.",
|
||||
"interval_colon": "Інтервал:",
|
||||
"executes_in_colon": "Виконується в:",
|
||||
"message_colon": "Повідомлення:",
|
||||
"no_redundant": "Не буде опубліковано повторюване повідомлення.",
|
||||
"remind_invalid": "Недійсний формат нагадування. Нагадування повинно мати ціль, таймер і причину. Перевірте список команд.",
|
||||
"user_voice_mute_time": "Користувач {0} ** вимкнено голос ** протягом {1} хвилин.",
|
||||
"user_chat_mute_time": "{0} ** вимкнено чат ** протягом {1} хвилин.",
|
||||
"acrm_fail": "Автоматична команда не знайдена у вказаному індексі.",
|
||||
"warns_dont_expire": "Попередження не встановлені.",
|
||||
"no_redundant": "Повідомлення, яке повторюється не буде публікуватися. ",
|
||||
"remind_invalid": "Не дійсний формат нагадування. Нагадування повинно мати ціль, таймер і причину. Перевірте список команд.",
|
||||
"user_voice_mute_time": "Користувачу {0} **заборонено розмовляти** протягом {1} хвилин.",
|
||||
"user_chat_mute_time": "{0} **заборонено писати ** протягом {1} хвилин.",
|
||||
"acrm_fail": "Авто-команду не знайдено у вказаному індексі.",
|
||||
"warns_dont_expire": "Попередження не встановлено.",
|
||||
"warns_expire_in": "Термін дії попереджень закінчується через {0} днів.",
|
||||
"not_with_bot_in_voice": "Ви не в тому ж голосовому каналі, що і бот.",
|
||||
"not_with_bot_in_voice": "Ви повинні перебувати в одному каналі разом з ботом.",
|
||||
"waifu_gift_not_exist": "Цей предмет вайфу не існує",
|
||||
"fans": "Шанувальники ({0})",
|
||||
"config_edit_fail": "Не вдалося налаштувати {0} значення {1}",
|
||||
@@ -925,26 +923,26 @@
|
||||
"config_prop_not_found": "Ресурс {0} не знайдено в конфігурації {1}",
|
||||
"config_list": "Список конфігурацій",
|
||||
"level_req": "Вимагається рівень.",
|
||||
"xprewsreset_confirm": "Ви впевнені, що хочете видалити ВСІ нагороди за підвищення рівня ХР з цього сервера? Ця дія є незворотною.",
|
||||
"xp_role_reward_cleared": "Досягнення рівня {0} більше не винагороджує роль.",
|
||||
"xprewsreset_confirm": "Ви впевнені, що хочете видалити ВСІ нагороди за підвищення рівня ХР на цьому сервері? Ця дія є незворотною. ",
|
||||
"xp_role_reward_cleared": "Досягнення {0} рівня більше не винагороджує роллю. ",
|
||||
"club_name_too_long": "Назва клубу задовга.",
|
||||
"club_user_not_in_club": "{0} не в клубі.",
|
||||
"reaction_cant_access": "Я не можу отримати доступ до реакції {0}. Ви можете використовувати лише емоції з серверів, на яких я перебуваю.",
|
||||
"club_user_not_in_club": "{0} не є у клубі.",
|
||||
"reaction_cant_access": "Я не можу отримати доступ до реакції {0}. Ви можете використовувати лише емоджі з серверів, на яких я перебуваю.",
|
||||
"module_footer": "{0}cmds {1}",
|
||||
"module_page_empty": "На цій сторінці немає модуля.",
|
||||
"module_description_help": "Отримайте довідку з команд, описи та приклади використання",
|
||||
"module_description_gambling": "Робіть ставку на кидки костей, блекджек, слоти, монети та інші",
|
||||
"module_description_games": "Грайте в дрібниці, нунчі, шибеника, з'єднай4 та інші ігри",
|
||||
"module_description_gambling": "Робіть ставку на кидки кубиків, блекджек, слоти, монети та інші",
|
||||
"module_description_games": "Грайте в гру: дрібниці, нунчі, шибеника, з'єднай4 та інші ігри",
|
||||
"module_description_nsfw": "Команди NSFW.",
|
||||
"module_description_music": "Відтворюйте музику з YouTube, локальні файли soundcloud та радіопотоки",
|
||||
"module_description_music": "Відтворюйте музику з YouTube, локальні файли, soundcloud та радіопотоки",
|
||||
"module_description_utility": "Керуйте власними цитатами, повторюваними повідомленнями та перевіряйте факти про сервер",
|
||||
"module_description_administration": "Модеруйте, карайте користувачів, налаштовуйте самостійно призначені ролі та вітайте повідомлення",
|
||||
"module_description_administration": "Модеруйте, карайте користувачів, налаштовуйте самостійно призначені ролі та вітальні повідомлення",
|
||||
"module_description_customreactions": "Налаштуйте власні відповіді бота на певні слова чи фрази",
|
||||
"module_description_permissions": "Налаштуйте дозволи для команд, фільтруйте слова та налаштуйте час відновлення",
|
||||
"module_description_searches": "Шукайте жарти, зображення тварин, аніме та мангу",
|
||||
"module_description_searches": "Шукайте жарти, зображення тварин, аніме та манґу",
|
||||
"module_description_xp": "Отримайте ХР на основі активності в чаті, перевірте картки ХР користувачів",
|
||||
"module_description_missing": "Опис цього модуля відсутній.",
|
||||
"obsolete_use": "⚠ Застаріло, замість цього використовуйте {0}.",
|
||||
"obsolete_use": "⚠ Застаріло, замість цього використовуй {0}.",
|
||||
"purge_user_confirm": "Ви впевнені, що хочете видалити {0} з бази даних?",
|
||||
"expr_import_no_input": "Неправильні дані. Не знайдено дійсного файлу для завантаження чи введення тексту.",
|
||||
"expr_import_invalid_data": "Не вдалося проаналізувати файл. Переконайтеся, що це дійсний .yml файл",
|
||||
@@ -953,5 +951,29 @@
|
||||
"empty_page": "Ця сторінка пуста.",
|
||||
"pages": "Сторінки",
|
||||
"favorites": "Улюблене",
|
||||
"tags": "Теги"
|
||||
"tags": "Теги",
|
||||
"invalid_emoji_link": "Вказане посилання не є зображенням, або перевищує ліміт 256 КБ.",
|
||||
"emoji_add_error": "Помилка додавання емоджі. У вас вичерпано слоти для емоджі, або невідповідний розмір.",
|
||||
"emoji_added": "Додано новий смайлик: {0}",
|
||||
"boost_on": "Увімкнено буст-сповіщення на цьому каналі.",
|
||||
"boost_off": "Буст-сповіщення вимкнено.",
|
||||
"boostmsg_cur": "Поточне буст-сповіщення: {0} ",
|
||||
"boostmsg_enable": "Увімкність буст-сповіщення ввівши {0}",
|
||||
"boostmsg_new": "Нове буст-сповіщення. ",
|
||||
"boostdel_off": "Автоматичне видалення буст-сповіщень вимкнено. ",
|
||||
"boostdel_on": "Буст-сповіщення буде видалятися через {0} секунд. ",
|
||||
"log_ignored_channels": "Ігноровані канали",
|
||||
"log_ignored_users": "Ігноровані користувачі",
|
||||
"log_ignore_user": "Журнал ігноруватиме користувача {0}",
|
||||
"log_not_ignore_user": "Журнал більше не ігноруватиме користувача {0}",
|
||||
"log_ignore_chan": "Журнал ігноруватиме канал {0}",
|
||||
"log_not_ignore_chan": "Журнал більше не ігноруватиме канал {0}",
|
||||
"streams_cleared": "Усі стріми, за якими ви слідкували, на цьому сервері видалено.",
|
||||
"warn_weight": "Вага: {0} ",
|
||||
"warn_count": "{0} поточно, {1} всього",
|
||||
"mass_ban_in_progress": "Заблокувати {0} користувачів...",
|
||||
"mass_ban_completed": "Заблоковано {0} користувачів. ",
|
||||
"reminder_server_list": "Список нагадувань серверу",
|
||||
"imageonly_enable": "Цей канал доступний лише для зображень.",
|
||||
"imageonly_disable": "Цей канал більше не є лише для зображень. "
|
||||
}
|
Reference in New Issue
Block a user