chojs23/concord

GitHub: chojs23/concord

Concord 是一个基于 Rust 和 ratatui 构建的 Discord 终端客户端,让用户在终端中获得完整的 Discord 使用体验。

Stars: 921 | Forks: 50

# Concord concord - 一个功能丰富的 Discord TUI 客户端 Concord 是一个使用 Rust 和 ratatui 编写的、功能丰富的 Discord TUI(终端用户界面)客户端。在终端中即可获得完整的 Discord 体验。 ## 目录 - [安装](#installation) - [功能](#features) - [配置](#configuration) - [性能](#performance) - [常见问题](#faq) - [安全](#security) - [贡献](#contributing) - [许可证](#license) ## 安装 ### Homebrew ``` brew install concord ``` 或者使用 tap 安装最新版本: ``` brew install chojs23/tap/concord ``` ### npm ``` npm install -g @chojs23/concord ``` 你也可以在不进行全局安装的情况下运行 Concord: ``` npx @chojs23/concord ``` npm 包会从 GitHub Release 构件中安装预编译的二进制文件。 ### Cargo 首先安装原生依赖。 在 macOS 上使用 Homebrew: ``` brew install opus pkg-config ``` 在 Fedora 上: ``` sudo dnf install opus-devel alsa-lib-devel pkgconf-pkg-config ``` 在 Debian 或 Ubuntu 上: ``` sudo apt install libopus-dev libasound2-dev pkg-config ``` ``` cargo install concord --locked ``` ``` cargo install concord --locked --no-default-features ``` 直接从 Git 仓库安装最新未发布的版本: ``` cargo install --locked --git https://github.com/chojs23/concord ``` ### Nix 从 nixpkgs 安装打包好的发行版: ``` nix profile install nixpkgs#concord-tui ``` 不安装直接运行打包好的发行版: ``` nix run nixpkgs#concord-tui ``` 不安装直接运行最新发行版(需要启用 flakes): ``` nix run github:chojs23/concord ``` 安装到你的 profile 中: ``` nix profile install github:chojs23/concord ``` 或者将该 flake 作为输入添加到你自己的 `flake.nix` 中: ``` { inputs.concord.url = "github:chojs23/concord"; } ``` ### GitHub Release 安装程序 使用 cargo-dist shell 安装程序安装最新版本: ``` curl --proto '=https' --tlsv1.2 -LsSf https://github.com/chojs23/concord/releases/latest/download/concord-installer.sh | sh ``` 在 Windows 上,请改用 PowerShell 安装程序: ``` powershell -ExecutionPolicy Bypass -c "irm https://github.com/chojs23/concord/releases/latest/download/concord-installer.ps1 | iex" ``` 安装程序会将 `concord` 放置在 `$CARGO_HOME/bin` 下,通常在 Unix 上是 `~/.cargo/bin`,在 Windows 上是 `%USERPROFILE%\.cargo\bin`。 ### 从源码构建 你需要 Rust 稳定版工具链、Cargo,以及 Cargo 安装部分中列出的原生依赖。 ``` git clone https://github.com/chojs23/concord.git cd concord cargo build --release ``` 编译生成的发行版二进制文件位于: ``` target/release/concord ``` ``` cargo build --release --no-default-features ``` 在 WSLg 上,音频通常通过 PulseAudio 而不是真正的 ALSA 声卡暴露。如果播放没有开始,在调试 Discord 语音本身之前,请先检查 PulseAudio 和 ALSA 路由是否正常工作: ``` pactl info paplay /usr/share/sounds/alsa/Front_Center.wav aplay -D pulse /usr/share/sounds/alsa/Front_Center.wav ``` ## 功能 ### 身份验证 - **Token**:粘贴现有的 Discord token。 - **邮箱 / 密码**:使用凭据登录。完全支持 MFA(TOTP、SMS)。 - **二维码**:从 Discord 移动应用扫描二维码。 - **CONCORD_TOKEN 环境变量**:在启动 Concord 之前设置 `CONCORD_TOKEN=your-token`。它会覆盖所有的 `credentials.store` 模式(`auto`、`keychain`、`plain`)。 邮箱和二维码登录可能会在 Discord 端触发 CAPTCHA 验证。我们无法解决该问题,因此强烈建议使用 token 进行身份验证。 默认情况下,token 在可用时会保存在系统 keychain 中。在默认的 `auto` 模式下,当 keychain 存储不可用时,Concord 会回退到其 state 目录。有关详细信息,请参阅下文的安全部分。 要使用默认快捷键登出,请按 `Space`、`p` 打开你的个人资料,然后选择 `[o] sign out`。 ### 服务器与频道 - 浏览服务器并支持服务器文件夹分组 - 浏览文字频道、讨论区和论坛频道 - 查看、筛选并创建论坛/媒体帖子(活跃 / 已归档) - 创建、编辑、关注、关闭、锁定、置顶和删除讨论区及论坛帖子 - 使用模糊频道切换器切换频道、讨论区和帖子(`Space`,`Space`) - 为每个频道加载置顶消息 - 打开频道操作以查看置顶消息、讨论区列表和标记为已读 - 加入和离开语音频道/DM 通话 - 在语音频道/DM 通话中高亮当前的发言者 - 追踪每个频道的未读消息和提及数量 - 静音和取消静音频道及服务器 - 确认后离开所选服务器 ### 消息 - 发送、编辑和删除消息 - 上传 / 下载附件 - 使用 `/` 通过过滤器搜索消息 - 使用 @提及自动补全 - 当你的账户支持时,可以使用来自其他服务器的自定义 emoji - 在启用时,如果你的账户无法直接使用自定义 emoji,则会作为图片链接发送 - 查看完整的消息历史记录 - 富内容显示(embeds、附件、贴纸和提及) - 检测消息正文和 Markdown 链接中的 URL,并在你的默认浏览器中打开它们 - 用于复制、回复、编辑、删除、回应、打开 URL 和查看图片的私信快捷方式。操作菜单中提供了更多消息操作。 #### Markdown 渲染与代码语法高亮 ![Markdown 渲染示例](https://raw.githubusercontent.com/chojs23/concord/main/docs/markdown-example.png) Concord 会在消息正文中渲染 Discord 风格 Markdown 的实用子集: - 标题:`# H1`,`## H2`,`### H3` - 引用:`> 引用文本` - 列表:`- 项目` 和 `* 项目` - 行内样式:`**粗体**`,`*斜体*`,`__下划线__`,`~~删除线~~`,以及 `` `行内代码` `` - 带有可选语言标签的围栏代码块,渲染为带有语法高亮的紧凑框 - 原始 URL 和 Markdown 链接目标会带有下划线,并且可以从消息操作中打开 ### 表情回应与投票 - 查看、添加和移除 emoji 回应(Unicode 和自定义服务器 emoji) - 当你的账户支持时,可以使用来自其他服务器的自定义 emoji 进行回应 - 浏览使用特定 emoji 回应的用户 - 查看和参与投票 ### 媒体与图片 图片渲染由 [ratatui-image](https://github.com/benjajaja/ratatui-image) 提供支持。启动时,Concord 会查询终端以检测最佳的可用图形协议。支持的协议包括: - **Kitty Graphics Protocol** - Kitty、WezTerm、Ghostty 等。 - **iTerm2 Inline Images** - iTerm2、WezTerm、mintty 等。 - **Sixel** - foot、mlterm、xterm(如果编译时启用了 Sixel 支持)等。 - **Halfblocks**(回退方案) - 可在任何终端上运行,但使用块字符而不是真实像素。 你可以在配置文件中打开或关闭图片查看功能。当关闭图片查看时,附件和 emoji 将显示为文本占位符。 视频和音频播放使用 [mpv](https://mpv.io/)。请确保已安装 `mpv` 并将其添加到你的 PATH 中。 YouTube 播放取决于你本地的 `mpv` 设置,例如是否支持 `yt-dlp`。 外部媒体播放默认处于关闭状态。你可以在 `[display]` 下使用 `media_playback = true` 来启用它,或者从应用内的 Display 选项菜单中切换它。 ### 成员与个人资料 - 带有分组的成员列表 - 在服务器中搜索成员 - 状态指示器(在线、闲置、免打扰、离线) - 配置用户个人资料和自定义活动状态 ### Rich Presence - Concord 提供本地 `discord-ipc` socket,检测已连接的应用,并允许你从个人资料的活动选择器中选择要共享的应用 - 仅检测使用 Discord 的 Rich Presence (RPC/IPC) 协议的应用。 - 检测需要关闭官方 Discord 客户端,因为只有一个程序可以拥有该 socket,而官方客户端会首先占用它 - 可通过 `config.toml` 中 `[presence]` 下的 `share_rich_presence` 进行切换 ### 正在输入指示器与已读状态 - 实时的“用户正在输入...”指示器 - 带有提及计数的未读消息追踪 - 将服务器、频道标记为已读 ### 通知 ### 导航与键盘快捷键 本节中的所有默认按键设置都可以自定义。有关配置格式和支持的操作,请参阅[快捷键映射选项](./docs/keymap-options.md)。 Concord 采用四窗格布局。 **服务器 (1)**,**频道 (2)**,**消息 (3)**,**成员 (4)** 默认采用 vim 风格的导航: | 按键 | 操作 | | ----------------------------------------- | ----------------------------------------------- | | `1` `2` `3` `4` | 聚焦窗格 | | `Tab` / `Shift+Tab` | 向前 / 向后循环聚焦 | | `h` / `l`,`←` / `→` | 向左 / 向右移动焦点 | | `j` / `k`,`↑` / `↓`,`Ctrl+n` / `Ctrl+p` | 向下 / 向上移动 | | `J`,`K` / `H`,`L` | 滚动视口 | | `Ctrl+d` / `Ctrl+u` | 半屏滚动 | | `Alt+h/l/←/→` | 调整聚焦窗格的宽度 | | `gg` / `G` | 跳转或滚动到顶部 / 底部 | | `Enter` | 打开或激活所选项目 | | `/` | 筛选服务器/频道,搜索消息/成员 | | `Space` | 打开引导键快捷窗口 | | `i` | 文本插入模式,或论坛帖子编辑器 | | `Esc` / `q` | 关闭弹窗、取消模式或返回 | | `q` | 退出 Concord | `Ctrl+n` 和 `Ctrl+p` 是固定的行移动键。默认的 `j` 和 `k` 行移动键是 `SelectNext` 和 `SelectPrevious`,可以在 `keymap.toml` 中更改。 #### 引导键 按 `Space` 打开引导键快捷窗口。 | 按键序列 | 操作 | | ---------------- | ------------------------- | | `Space`, `1` | 切换服务器窗格 | | `Space`, `2` | 切换频道窗格 | | `Space`, `4` | 切换成员窗格 | | `Space`, `a` | 打开聚焦窗格的操作 | | `Space`, `p` | 打开我的个人资料设置 | | `Space`, `o` | 选择 concord 选项类别 | | `Space`, `n` | 打开通知收件箱 | | `Space`, `v` | 语音命令前缀 | | `Space`, `Space` | 打开模糊频道切换器 | #### 操作菜单 聚焦某个窗格,然后按 `Space`、`a` 打开该窗格的操作。不适用于当前选择的操作将显示为灰色且被禁用。在消息窗格中,选中的消息还支持以下直接快捷方式: 消息快捷方式: | 快捷键 | 操作 | 描述 | | -------- | ------------------- | ----------------------------------------------------------- | | `y` | 复制 | 复制选中的消息文本并显示短暂的提示 | | `r` | 添加/移除回应 | 打开所选消息的回应选择器 | | `R` | 回复 | 开始回复所选消息 | | `d` | 删除 | 在删除消息之前打开删除确认框 | | `e` | 编辑 | 在允许编辑时开始编辑所选消息 | | `o` | 打开 URL | 打开选中的消息 URL,或从多个 URL 中选择 | | `x` | 播放媒体 | 在外部播放器中播放选中的视频或音频媒体 | | `v` | 查看附件 | 打开选中消息的附件查看器 | 消息操作菜单快捷方式: | 快捷键 | 操作 | 描述 | | -------- | --------------------------- | ----------------------------------------------------------- | | `y` | 复制 | 复制选中的消息文本并显示短暂的提示 | | `r` | 添加/移除回应 | 打开所选消息的回应选择器 | | `R` | 回复 | 开始回复所选消息 | | `d` | 删除 | 在删除消息之前打开删除确认框 | | `e` | 编辑 | 在允许编辑时开始编辑所选消息 | | `o` | 打开 URL | 打开选中的消息 URL,或从多个 URL 中选择 | | `D` | 移除 embeds | 移除所选消息的 embeds | | `x` | 播媒体 | 在外部播放器中播放选中的视频或音频媒体 | | `v` | 查看附件 | 打开选中消息的附件查看器 | | `g` | 转到引用的消息 | 转到被回复或转发的消息 | | `p` | 显示消息发送者资料 | 打开选中消息作者的个人资料 | | `P` | 置顶 / 取消置顶 | 为所选消息打开置顶或取消置顶确认框 | | `t` | 打开讨论区 | 打开选中消息的讨论区 | | `u` | 显示回应的用户 | 显示对所选消息进行了回应的用户 | | `c` | 选择投票选项 | 为所选消息选择投票选项 | 当附件查看器打开时,按 `x` 可在外部播放器中播放当前的视频或音频附件,或按 `d` 直接下载当前附件。 服务器操作: | 快捷键 | 操作 | 描述 | | -------- | ------------------- | ----------------------------------------------------- | | `m` | 标记服务器为已读 | 将此服务器中所有未读的可查看频道标记为已读 | | `u` | 静音 / 取消静音 | 切换服务器通知静音状态 | | `l` | 离开服务器 | 在离开此服务器之前打开确认框 | | `r` | 文件夹设置 | 编辑所选服务器文件夹的名称和颜色 | 频道操作: | 快捷键 | 操作 | 描述 | | -------- | -------------------- | -------------------------------------------- | | `e` | 加入语音 | 加入选中的语音频道或 DM 通话 | | `l` | 离开语音 | 离开当前的语音频道或 DM 通话 | | `p` | 显示置顶消息 | 打开所选频道的置顶消息 | | `t` | 显示讨论区 | 列出所选频道的讨论区 | | `m` | 标记为已读 | 将选中的频道标记为已读 | | `u` | 静音 / 取消静音 | 切换频道或分类的通知静音状态 | 讨论区 / 帖子操作(频道窗格中聚焦的讨论区,或帖子列表中的论坛帖子): | 快捷键 | 操作 | 描述 | | -------- | --------------------- | ----------------------------------------------------------- | | `m` | 标记为已读 | 将讨论区或帖子标记为已读 | | `f` | 关注 / 取消关注 | 关注或取消关注讨论区或帖子 | | `c` | 关闭 / 重新打开 | 关闭或重新打开讨论区或帖子(作者或版主) | | `l` | 锁定 / 解锁 | 锁定或解锁讨论区或帖子(版主) | | `e` | 编辑 | 编辑标题、标签、慢速模式、以及自动归档 | | `y` | 复制链接 | 复制指向该讨论区或帖子的链接 | | `u` | 静音 / 取消静音 | 切换讨论区或帖子的通知静音状态(必须先关注) | | `n` | 通知设置 | 选择讨论区或帖子的通知级别 | | `P` | 置顶 / 取消置顶 | 置顶或取消置顶帖子(仅限论坛帖子,版主) | | `d` | 删除 | 删除整个讨论区或帖子(版主) | | `i` | 复制 ID | 复制讨论区或帖子 ID | 语音命令: | 序列 | 操作 | 描述 | | ----------------- | ------------ | ----------------------------------------- | | `Space`, `v`, `d` | 静音语音 | 切换 Concord 的 Discord 语音 deaf 状态 | | `Space`, `v`, `m` | 麦克风静音 | 切换 Concord 的 Discord 语音 mute 状态 | | `Space`, `v`, `l` | 离开语音 | 离开当前的 Concord 语音频道 | #### 输入器 在论坛或媒体父频道中,相同的输入器按键会打开一个帖子输入器覆盖层。 | 快捷方式 | 操作 | 描述 | | -------------------------------------------- | ----------------- | ---------------------------------------------------------------- | | `Ctrl+v` | 粘贴剪贴板 | 如果存在则附加复制的文件或图片,否则粘贴文本 | | `Ctrl+e` | 打开 $EDITOR | 在当前草稿上打开 $EDITOR 以便进行长文本编辑 | | `Ctrl+c` | 清除 | 清除当前草稿 | | `Ctrl+Left`/ `Ctrl+Right` | 按词跳转 | 按词移动光标 | | `Alt+Backspace`, `Ctrl+Backspace` / `Ctrl+w` | 删除单词 | 删除光标之前的单词 | | `Ctrl+u` / `Ctrl+k` | 删除行文本 | 删除从光标到当前行首/行尾的文本 | | `Delete` | 移除附件 | 移除最后一个待处理的附件 | | `Alt+p` | 切换回复 ping | 切换回复时是否 ping 原作者 | #### 提及选择器 当 @提及 选择器打开时,使用 `Up` / `Down`、`Ctrl+p` / `Ctrl+n`、`Tab` 或 `Enter` 来选择一个提及。 #### Emoji 选择器 输入 `:` 加上至少两个字母(例如 `:he`),即可在编写消息时选择 Unicode、服务器或跨服务器的自定义 emoji。 当启用了 `emojis_as_links` 时,如果你的账户无法直接发送自定义 emoji,则会将它们作为 Discord 图片链接插入。 要从输入器进行回应,请选择一条消息,进入插入模式,然后输入 `+:`。该消息的回应选择器将会打开。按 `/` 进行搜索,按 Enter 锁定过滤器,然后再按一次 Enter 或使用显示的快捷方式进行回应。 #### Bot 命令 当输入器输入以斜杠 `/` 开头时,将弹出命令建议框 ## 配置 Concord 的选项存储在 Concord 的配置目录下。如果设置了 `XDG_CONFIG_HOME`,Concord 将使用 `config.toml` 作为应用选项,使用 `keymap.toml` 作为按键设置。 否则,它将使用平台默认的配置目录。 本地 UI 状态和明文凭据回退存储在 Concord 的 state 目录下。如果设置了 `XDG_STATE_HOME`,Concord 将使用 `$XDG_STATE_HOME/concord/state.toml` 和 `$XDG_STATE_HOME/concord/credentials.toml`。否则,它将使用 `~/.local/state/concord/state.toml` 和 `~/.local/state/concord/credentials.toml`。 你可以从应用内的选项菜单更改某些配置,Concord 会将它们保存回 `config.toml`。按键设置从 `keymap.toml` 读取。
默认配置 ``` [display] # Image protocol:auto、iterm2、kitty、sixel 或 halfblocks。 image_protocol = "auto" # Master switch,为 true 时隐藏所有图像预览。 disable_image_preview = false # 在消息旁边和个人资料视图中显示用户头像。 show_avatars = true # 为附件和 embeds 渲染内联图像预览。 show_images = true # 允许视频和音频媒体在外部播放器中打开。 media_playback = false # 预览质量:efficient、balanced、high 或 original。 image_preview_quality = "balanced" # 附件查看器质量:efficient、balanced、high 或 original。 attachment_viewer_quality = "original" # 尽可能将自定义 Discord emoji 渲染为图像。 show_custom_emoji = true # 将头像裁剪为圆形,而不是显示方形图像。 circular_avatars = false [composer] # 将你的账户无法直接使用的自定义 emoji 作为图像链接发送。 emojis_as_links = false [presence] # 将来自本地应用的 Rich Presence 作为你的活动进行中继。 share_rich_presence = true [credentials] # 凭据存储:auto、keychain 或 plain。 # auto 首先尝试系统 keychain,如果失败则回退到 state 文件。 store = "auto" [notifications] # 为符合通知规则的 Discord 消息显示桌面通知。 desktop_notifications = true # 包含在通知中的可选通知图标。可能并非在所有平台上都有效。 # 未设置时,不使用任何图标。它必须是图标的名称(通常在 /usr/share/icons 中) # 或图标的路径。 notification_icon = "/path/to/icon.svg" # 用于消息、语音加入/离开通知声音的可选 WAV 文件。 # 未设置时,Concord 使用内置生成的提示音。 notification_sound = "/path/to/message.wav" voice_join_sound = "/path/to/join.wav" voice_leave_sound = "/path/to/leave.wav" [voice] # 在 Concord 自我静音的情况下加入或更新 Discord 语音。 self_mute = false # 在 Concord 自我拒听的情况下加入或更新 Discord 语音。 self_deaf = false # 允许在此会话已加入且未自我静音时传输麦克风。 allow_microphone_transmit = false # 语音活动阈值,单位为 dB。较低的值会传输更安静的输入。 microphone_sensitivity = -30 # 麦克风输入音量百分比,从 0 到 100。 microphone_volume = 100 # 接收到的语音播放音量百分比,从 0 到 100。 voice_output_volume = 100 ```

`image_protocol`: - `auto`:使用终端检测。在 iTerm 中,Concord 使用 iTerm2 协议,因为终端能力检测可能会在那里错误地选择 Kitty。 - `iterm2`:强制使用 iTerm2 内联图片协议。 - `kitty`:强制使用 Kitty 图形协议。 - `sixel`:强制使用 Sixel 渲染。 - `halfblocks`:强制使用 Unicode 半块回退渲染。 `image_preview_quality` 和 `attachment_viewer_quality`: - `efficient`:较小的预览请求,以减少带宽和内存使用。 - `balanced`:默认质量,具有受限的资源使用。 - `high`:使用无损质量生成更清晰的调整大小后的预览。 - `original`:在可能的情况下,请求原始源图像进行预览。 此设置仅适用于附件、embeds 和附件查看器预览。头像和自定义 emoji 保持其独立的小图像行为。 `credentials.store`: - `auto`:首先尝试系统 keychain,然后回退到 state-file 凭据存储。 - `keychain`:仅使用系统 keychain。如果 keychain 存储不可用,则不保存 token。 - `plain`:仅使用明文 state-file 凭据存储。
默认快捷键映射配置 ``` [keymap] leader = "space" StartComposer = "i" OpenPaneFilter = "/" ClosePopup = "q" FocusGuildPane = "1" FocusChannelPane = "2" FocusMessagePane = "3" FocusMemberPane = "4" SelectNext = "j" SelectPrevious = "k" CycleFocusNext = { keys = ["tab", "l", "right"] } CycleFocusPrevious = { keys = ["", "h", "left"] } HalfPageDown = "" HalfPageUp = "" ScrollViewportDown = "J" ScrollViewportUp = "K" JumpTop = "gg" JumpBottom = "G" ScrollHorizontalLeft = "H" ScrollHorizontalRight = "L" ResizePaneLeft = { keys = ["", ""] } ResizePaneRight = { keys = ["", ""] } Quit = "q" CopyMessage = "y" ReactMessage = "r" ReplyMessage = "R" DeleteMessage = "d" EditMessage = "e" OpenMessageUrl = "o" PlayMedia = "x" ViewMessageAttachment = "v" ToggleGuildPane = "1" ToggleChannelPane = "2" ToggleMemberPane = "4" OpenFocusedPaneAction = "a" OpenCurrentUserProfile = "p" OpenOptions = "o" OpenNotificationInbox = "n" ChannelSwitcher = "" VoiceDeafen = "vd" VoiceMute = "vm" VoiceLeave = "vl" [keymap.groups] "v" = "Voice" [keymap.guild_actions] MarkAsRead = "m" MuteServer = "u" LeaveServer = "l" FolderSettings = "r" [keymap.channel_actions] JoinVoice = "e" LeaveVoice = "l" ShowPinnedMessages = "p" ShowThreads = "t" MarkAsRead = "m" MuteChannel = "u" [keymap.message_actions] CopyMessage = "y" ReactMessage = "r" ReplyMessage = "R" DeleteMessage = "d" EditMessage = "e" OpenMessageUrl = "o" RemoveMessageEmbeds = "D" PlayMedia = "x" ViewMessageAttachment = "v" GoToReferencedMessage = "g" ShowMessageProfile = "p" PinMessage = "P" OpenThread = "t" ShowReactionUsers = "u" OpenPollVotePicker = "c" [keymap.member_actions] ShowProfile = "p" [keymap.thread_actions] MarkAsRead = "m" ToggleFollow = "f" Close = "c" Lock = "l" Edit = "e" CopyLink = "y" ToggleMute = "u" NotificationSettings = "n" Pin = "P" Delete = "d" CopyId = "i" [keymap.composer] OpenEditor = "" PasteClipboard = "" InsertNewline = { keys = ["", "", "", ""] } Submit = "enter" Close = "esc" ClearInput = "" RemoveLastAttachment = "delete" DeletePreviousChar = "backspace" DeletePreviousWord = { keys = ["", "", ""] } DeleteToLineStart = "" DeleteToLineEnd = "" MoveCursorUp = "up" MoveCursorDown = "down" MoveCursorWordLeft = "" MoveCursorLeft = "left" MoveCursorWordRight = "" MoveCursorRight = "right" MoveCursorHome = "home" MoveCursorEnd = "end" ToggleReplyPing = "" ```

你可以自定义快捷键绑定。查看[快捷键映射选项](./docs/keymap-options.md)以获取配置格式和支持的操作。 ## 性能 Concord 旨在在正常的终端使用中保持轻量化。在观察到的典型使用中,它通常使用大约 20-40 MB 的内存。 包含大量图片的屏幕可能会暂时使用更多的内存,因为压缩的图像字节需要先解码才能在终端中渲染。当加载大量图像时,内存可能会短暂上升到 100-200 MB 左右,然后在解码完成和缓存被清理后再次下降。 为了保持资源使用在受限范围内,Concord 在多个方面限制了媒体处理: - 附件预览在下载时有每个预览 8 MiB 的上限。 - 一次最多获取 4 个附件预览。 - 一次最多解码 2 个内联图像预览。 - 内联图像预览、头像和自定义 emoji 使用小型 LRU 缓存。 - 图像预览请求倾向于使用为终端调整过大小的 Discord 代理 URL,而不是可能情况下的原始全尺寸媒体。 - 预览质量预设可以降低预览源尺寸或选择使用原始源图像。它不会改变头像或自定义 emoji 的大小。 消息历史记录也有每个频道的缓存限制,因此长时间运行的会话不会永远将每条消息都保留在内存中。 ## 常见问题 ### 我的账户会被封禁吗? 老实说,不会。 确实有一些操作路径触发了账户封禁: - 尝试**创建一个新的 DM 频道并向未知的用户发送消息**(意味着之前没有通过 Discord 客户端创建过预先存在的 DM)会立即导致你的账户被暂时封禁。 - 一些在 Discord 端需要 hCaptcha 验证的功能。 在我的测试中,其他功能并未导致封禁。 也就是说,Concord 不是官方的 Discord 客户端。使用非官方客户端、自动化的用户账户或自我机器人(self-bots)可能会违反 Discord 的服务条款(TOS),因此总是存在一些风险。请自行斟酌使用。 ## 安全 - 默认情况下,token 在可用时会存储在系统 keychain 中。 - 在 Linux 上,当有兼容的服务可用时,keychain 存储会使用 Secret Service。 - `CONCORD_TOKEN` 环境变量允许你提供 token 而无需将其写入磁盘。这避免了在磁盘上留下明文,但在 Concord 运行时,该 token 在 `/proc//environ` 和进程列表中是可见的。 - 在 `credentials.store = "auto"` 中,当 keychain 存储不可用时,Concord 会回退到 Concord state 目录下的**明文**凭据。在 `keychain` 模式下,Concord 不会回退到明文存储。请确保回退凭据文件的安全,不要共享它们。你可以使用该文件中的 token 登录官方 Discord 客户端,因此请像对待密码一样对待它。 - 在 Unix 上,回退凭据的父目录使用 `0700` 权限创建,凭据文件使用 `0600` 权限创建。 ## 许可证 Concord 采用 GPL-3.0-only 许可证。
标签:Discord, ratatui, Rust, TUI, 可视化界面, 暗色界面, 终端客户端, 网络流量审计, 通知系统