82 changed files with 7680 additions and 2850 deletions
@ -0,0 +1,44 @@ |
|||
name: crowdin download |
|||
|
|||
on: |
|||
schedule: |
|||
- cron: '0 18 * * 1' |
|||
workflow_dispatch: |
|||
|
|||
jobs: |
|||
download: |
|||
runs-on: ubuntu-latest |
|||
environment: Crowdin |
|||
name: download |
|||
steps: |
|||
- uses: actions/checkout@v2 |
|||
with: |
|||
fetch-depth: 0 |
|||
ref: master |
|||
|
|||
- name: Install system dependencies |
|||
run: | |
|||
wget -qO - https://artifacts.crowdin.com/repo/GPG-KEY-crowdin | sudo apt-key add - |
|||
echo "deb https://artifacts.crowdin.com/repo/deb/ /" | sudo tee -a /etc/apt/sources.list.d/crowdin.list |
|||
sudo apt-get update -qq |
|||
sudo apt-get install -y crowdin3 |
|||
|
|||
- name: Download translations |
|||
shell: bash |
|||
run: | |
|||
cd docs |
|||
crowdin download --all |
|||
env: |
|||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }} |
|||
|
|||
- name: Create pull request |
|||
id: cpr_crowdin |
|||
uses: peter-evans/create-pull-request@v3 |
|||
with: |
|||
token: ${{ secrets.GITHUB_TOKEN }} |
|||
commit-message: Crowdin translations download |
|||
title: "[Crowdin] Updated translation files" |
|||
body: | |
|||
Created by the [Crowdin download workflow](.github/workflows/crowdin_download.yml). |
|||
branch: "auto/crowdin" |
|||
author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
@ -0,0 +1,44 @@ |
|||
name: crowdin upload |
|||
|
|||
on: |
|||
workflow_dispatch: |
|||
|
|||
jobs: |
|||
upload: |
|||
runs-on: ubuntu-latest |
|||
environment: Crowdin |
|||
name: upload |
|||
steps: |
|||
- uses: actions/checkout@v2 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Set up CPython 3.x |
|||
uses: actions/setup-python@v2 |
|||
with: |
|||
python-version: 3.x |
|||
|
|||
- name: Install system dependencies |
|||
run: | |
|||
wget -qO - https://artifacts.crowdin.com/repo/GPG-KEY-crowdin | sudo apt-key add - |
|||
echo "deb https://artifacts.crowdin.com/repo/deb/ /" | sudo tee -a /etc/apt/sources.list.d/crowdin.list |
|||
sudo apt-get update -qq |
|||
sudo apt-get install -y crowdin3 |
|||
|
|||
- name: Install Python dependencies |
|||
run: | |
|||
python -m pip install --upgrade pip setuptools wheel |
|||
pip install -e .[docs,speed,voice] |
|||
|
|||
- name: Build gettext |
|||
run: | |
|||
cd docs |
|||
make gettext |
|||
|
|||
- name: Upload sources |
|||
shell: bash |
|||
run: | |
|||
cd docs |
|||
crowdin upload |
|||
env: |
|||
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }} |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,242 @@ |
|||
""" |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2015-present Rapptz |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a |
|||
copy of this software and associated documentation files (the "Software"), |
|||
to deal in the Software without restriction, including without limitation |
|||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|||
and/or sell copies of the Software, and to permit persons to whom the |
|||
Software is furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in |
|||
all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
|||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|||
DEALINGS IN THE SOFTWARE. |
|||
""" |
|||
|
|||
from __future__ import annotations |
|||
|
|||
from typing import TYPE_CHECKING, Dict, List, Literal, TypedDict, Union |
|||
|
|||
|
|||
from .channel import ChannelTypeWithoutThread, ThreadMetadata |
|||
from .threads import ThreadType |
|||
from .member import Member |
|||
from .message import Attachment |
|||
from .role import Role |
|||
from .snowflake import Snowflake |
|||
from .user import User |
|||
|
|||
if TYPE_CHECKING: |
|||
from .message import Message |
|||
|
|||
|
|||
InteractionType = Literal[1, 2, 3, 4, 5] |
|||
|
|||
|
|||
class _BasePartialChannel(TypedDict): |
|||
id: Snowflake |
|||
name: str |
|||
permissions: str |
|||
|
|||
|
|||
class PartialChannel(_BasePartialChannel): |
|||
type: ChannelTypeWithoutThread |
|||
|
|||
|
|||
class PartialThread(_BasePartialChannel): |
|||
type: ThreadType |
|||
thread_metadata: ThreadMetadata |
|||
parent_id: Snowflake |
|||
|
|||
|
|||
class ResolvedData(TypedDict, total=False): |
|||
users: Dict[str, User] |
|||
members: Dict[str, Member] |
|||
roles: Dict[str, Role] |
|||
channels: Dict[str, Union[PartialChannel, PartialThread]] |
|||
messages: Dict[str, Message] |
|||
attachments: Dict[str, Attachment] |
|||
|
|||
|
|||
class _BaseApplicationCommandInteractionDataOption(TypedDict): |
|||
name: str |
|||
|
|||
|
|||
class _CommandGroupApplicationCommandInteractionDataOption(_BaseApplicationCommandInteractionDataOption): |
|||
type: Literal[1, 2] |
|||
options: List[ApplicationCommandInteractionDataOption] |
|||
|
|||
|
|||
class _BaseValueApplicationCommandInteractionDataOption(_BaseApplicationCommandInteractionDataOption, total=False): |
|||
focused: bool |
|||
|
|||
|
|||
class _StringValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): |
|||
type: Literal[3] |
|||
value: str |
|||
|
|||
|
|||
class _IntegerValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): |
|||
type: Literal[4] |
|||
value: int |
|||
|
|||
|
|||
class _BooleanValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): |
|||
type: Literal[5] |
|||
value: bool |
|||
|
|||
|
|||
class _SnowflakeValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): |
|||
type: Literal[6, 7, 8, 9, 11] |
|||
value: Snowflake |
|||
|
|||
|
|||
class _NumberValueApplicationCommandInteractionDataOption(_BaseValueApplicationCommandInteractionDataOption): |
|||
type: Literal[10] |
|||
value: float |
|||
|
|||
|
|||
_ValueApplicationCommandInteractionDataOption = Union[ |
|||
_StringValueApplicationCommandInteractionDataOption, |
|||
_IntegerValueApplicationCommandInteractionDataOption, |
|||
_BooleanValueApplicationCommandInteractionDataOption, |
|||
_SnowflakeValueApplicationCommandInteractionDataOption, |
|||
_NumberValueApplicationCommandInteractionDataOption, |
|||
] |
|||
|
|||
|
|||
ApplicationCommandInteractionDataOption = Union[ |
|||
_CommandGroupApplicationCommandInteractionDataOption, |
|||
_ValueApplicationCommandInteractionDataOption, |
|||
] |
|||
|
|||
|
|||
class _BaseApplicationCommandInteractionDataOptional(TypedDict, total=False): |
|||
resolved: ResolvedData |
|||
guild_id: Snowflake |
|||
|
|||
|
|||
class _BaseApplicationCommandInteractionData(_BaseApplicationCommandInteractionDataOptional): |
|||
id: Snowflake |
|||
name: str |
|||
|
|||
|
|||
class ChatInputApplicationCommandInteractionData(_BaseApplicationCommandInteractionData, total=False): |
|||
type: Literal[1] |
|||
options: List[ApplicationCommandInteractionDataOption] |
|||
|
|||
|
|||
class _BaseNonChatInputApplicationCommandInteractionData(_BaseApplicationCommandInteractionData): |
|||
target_id: Snowflake |
|||
|
|||
|
|||
class UserApplicationCommandInteractionData(_BaseNonChatInputApplicationCommandInteractionData): |
|||
type: Literal[2] |
|||
|
|||
|
|||
class MessageApplicationCommandInteractionData(_BaseNonChatInputApplicationCommandInteractionData): |
|||
type: Literal[3] |
|||
|
|||
|
|||
ApplicationCommandInteractionData = Union[ |
|||
ChatInputApplicationCommandInteractionData, |
|||
UserApplicationCommandInteractionData, |
|||
MessageApplicationCommandInteractionData, |
|||
] |
|||
|
|||
|
|||
class _BaseMessageComponentInteractionData(TypedDict): |
|||
custom_id: str |
|||
|
|||
|
|||
class ButtonMessageComponentInteractionData(_BaseMessageComponentInteractionData): |
|||
component_type: Literal[2] |
|||
|
|||
|
|||
class SelectMessageComponentInteractionData(_BaseMessageComponentInteractionData): |
|||
component_type: Literal[3] |
|||
values: List[str] |
|||
|
|||
|
|||
MessageComponentInteractionData = Union[ButtonMessageComponentInteractionData, SelectMessageComponentInteractionData] |
|||
|
|||
|
|||
class ModalSubmitTextInputInteractionData(TypedDict): |
|||
type: Literal[4] |
|||
custom_id: str |
|||
value: str |
|||
|
|||
|
|||
ModalSubmitComponentItemInteractionData = ModalSubmitTextInputInteractionData |
|||
|
|||
|
|||
class ModalSubmitActionRowInteractionData(TypedDict): |
|||
type: Literal[1] |
|||
components: List[ModalSubmitComponentItemInteractionData] |
|||
|
|||
|
|||
ModalSubmitComponentInteractionData = Union[ModalSubmitActionRowInteractionData, ModalSubmitComponentItemInteractionData] |
|||
|
|||
|
|||
class ModalSubmitInteractionData(TypedDict): |
|||
custom_id: str |
|||
components: List[ModalSubmitActionRowInteractionData] |
|||
|
|||
|
|||
InteractionData = Union[ |
|||
ApplicationCommandInteractionData, |
|||
MessageComponentInteractionData, |
|||
ModalSubmitInteractionData, |
|||
] |
|||
|
|||
|
|||
class _BaseInteractionOptional(TypedDict, total=False): |
|||
guild_id: Snowflake |
|||
channel_id: Snowflake |
|||
locale: str |
|||
guild_locale: str |
|||
|
|||
|
|||
class _BaseInteraction(_BaseInteractionOptional): |
|||
id: Snowflake |
|||
application_id: Snowflake |
|||
token: str |
|||
version: Literal[1] |
|||
|
|||
|
|||
class PingInteraction(_BaseInteraction): |
|||
type: Literal[1] |
|||
|
|||
|
|||
class ApplicationCommandInteraction(_BaseInteraction): |
|||
type: Literal[2, 4] |
|||
data: ApplicationCommandInteractionData |
|||
|
|||
|
|||
class MessageComponentInteraction(_BaseInteraction): |
|||
type: Literal[3] |
|||
data: MessageComponentInteractionData |
|||
|
|||
|
|||
class ModalSubmitInteraction(_BaseInteraction): |
|||
type: Literal[5] |
|||
data: ModalSubmitInteractionData |
|||
|
|||
|
|||
Interaction = Union[PingInteraction, ApplicationCommandInteraction, MessageComponentInteraction, ModalSubmitInteraction] |
|||
|
|||
|
|||
class MessageInteraction(TypedDict): |
|||
id: Snowflake |
|||
type: InteractionType |
|||
name: str |
|||
user: User |
File diff suppressed because it is too large
@ -0,0 +1,21 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
project_id: "362783" |
|||
api_token_env: CROWDIN_API_KEY |
|||
|
|||
files: |
|||
- source: /_build/locale/**/*.pot |
|||
translation: /locale/%two_letters_code%/LC_MESSAGES/%original_path%/%file_name%.po |
|||
|
|||
# You must use `crowdin download --all` for this project |
|||
# I discovered after like an hour of debugging the Java CLI that `--all` actually means "use server sources" |
|||
# Without this, crowdin tries to determine the mapping itself, and decides that because |
|||
# `/locale/ja/LC_MESSAGES/_build/locale/...` doesn't exist, that it won't download anything |
|||
# There is no workaround for this. I tried. Trying to adjust the project base path just breaks things further. |
|||
|
|||
# Crowdin does the conflict resolution on its end. The process to update translations is thus: |
|||
# - make gettext |
|||
# - crowdin upload |
|||
# - crowdin download --all |
|||
# You must set ${CROWDIN_API_KEY} in the environment. |
|||
# I will write an Actions workflow for this at a later date. |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,69 @@ |
|||
import discord |
|||
from discord import app_commands |
|||
|
|||
import traceback |
|||
|
|||
# Just default intents and a `discord.Client` instance |
|||
# We don't need a `commands.Bot` instance because we are not |
|||
# creating text-based commands. |
|||
intents = discord.Intents.default() |
|||
client = discord.Client(intents=intents) |
|||
|
|||
# We need an `discord.app_commands.CommandTree` instance |
|||
# to register application commands (slash commands in this case) |
|||
tree = app_commands.CommandTree(client) |
|||
|
|||
# The guild in which this slash command will be registered. |
|||
# As global commands can take up to an hour to propagate, it is ideal |
|||
# to test it in a guild. |
|||
TEST_GUILD = discord.Object(ID) |
|||
|
|||
@client.event |
|||
async def on_ready(): |
|||
print(f'Logged in as {client.user} (ID: {client.user.id})') |
|||
print('------') |
|||
|
|||
# Sync the application command with Discord. |
|||
await tree.sync(guild=TEST_GUILD) |
|||
|
|||
class Feedback(discord.ui.Modal, title='Feedback'): |
|||
# Our modal classes MUST subclass `discord.ui.Modal`, |
|||
# but the title can be whatever you want. |
|||
|
|||
# This will be a short input, where the user can enter their name |
|||
# It will also have a placeholder, as denoted by the `placeholder` kwarg. |
|||
# By default, it is required and is a short-style input which is exactly |
|||
# what we want. |
|||
name = discord.ui.TextInput( |
|||
label='Name', |
|||
placeholder='Your name here...', |
|||
) |
|||
|
|||
# This is a longer, paragraph style input, where user can submit feedback |
|||
# Unlike the name, it is not required. If filled out, however, it will |
|||
# only accept a maximum of 300 characters, as denoted by the |
|||
# `max_length=300` kwarg. |
|||
feedback = discord.ui.TextInput( |
|||
label='What do you think of this new feature?', |
|||
style=discord.TextStyle.long, |
|||
placeholder='Type your feedback here...', |
|||
required=False, |
|||
max_length=300, |
|||
) |
|||
|
|||
async def on_submit(self, interaction: discord.Interaction): |
|||
await interaction.response.send_message(f'Thanks for your feedback, {self.name.value}!', ephemeral=True) |
|||
|
|||
async def on_error(self, error: Exception, interaction: discord.Interaction) -> None: |
|||
await interaction.response.send_message('Oops! Something went wrong.', ephemeral=True) |
|||
|
|||
# Make sure we know what the error actually is |
|||
traceback.print_tb(error.__traceback__) |
|||
|
|||
|
|||
@tree.command(guild=TEST_GUILD, description="Submit feedback") |
|||
async def feedback(interaction: discord.Interaction): |
|||
# Send the modal with an instance of our `Feedback` class |
|||
await interaction.response.send_modal(Feedback()) |
|||
|
|||
client.run('token') |
@ -1 +1 @@ |
|||
aiohttp>=3.6.0,<3.9.0 |
|||
aiohttp>=3.6.0,<4 |
|||
|
Loading…
Reference in new issue