discord_proxy/discord/
mod.rs1use anyhow::Result;
2use std::{fmt, path::Path, str::FromStr};
3
4#[cfg(windows)]
5mod windows;
6
7#[cfg(windows)]
8pub use windows::{
9 DiscordInstall, InstallCandidateReport, LaunchPlan, discover_install, inspect_candidates,
10 is_process_running,
11};
12
13#[cfg(not(windows))]
14mod unsupported {
15 use super::DiscordChannel;
16 use anyhow::{Result, bail};
17 use std::path::Path;
18 use tokio::process::Child;
19
20 #[derive(Debug)]
21 pub struct DiscordInstall;
22
23 #[derive(Debug)]
24 pub struct InstallCandidateReport;
25
26 pub struct LaunchPlan;
27
28 impl DiscordInstall {
29 pub fn source(&self) -> &str {
30 ""
31 }
32
33 pub fn channel(&self) -> DiscordChannel {
34 DiscordChannel::Stable
35 }
36
37 pub fn root(&self) -> &Path {
38 Path::new("")
39 }
40
41 pub fn app_dir(&self) -> &Path {
42 Path::new("")
43 }
44
45 pub fn update_exe(&self) -> Option<&Path> {
46 None
47 }
48
49 pub fn exe_path(&self) -> &Path {
50 Path::new("")
51 }
52
53 pub fn exe_name(&self) -> &str {
54 ""
55 }
56 }
57
58 impl LaunchPlan {
59 pub fn new(_install: DiscordInstall, _proxy_url: String) -> Self {
60 Self
61 }
62
63 pub fn describe(&self) -> String {
64 "this MVP currently supports Windows launch plans only".to_string()
65 }
66
67 pub fn spawn(&self) -> Result<Child> {
68 bail!("this MVP currently supports Windows launch plans only")
69 }
70 }
71
72 pub fn discover_install(
73 _channel: DiscordChannel,
74 _override_dir: Option<&Path>,
75 ) -> Result<DiscordInstall> {
76 bail!("this MVP currently supports Windows Discord discovery only")
77 }
78
79 pub fn inspect_candidates(
80 _channel: DiscordChannel,
81 _override_dir: Option<&Path>,
82 ) -> Vec<InstallCandidateReport> {
83 Vec::new()
84 }
85
86 pub fn is_process_running(_exe_name: &str) -> bool {
87 false
88 }
89}
90
91#[cfg(not(windows))]
92pub use unsupported::{
93 DiscordInstall, InstallCandidateReport, LaunchPlan, discover_install, inspect_candidates,
94 is_process_running,
95};
96
97#[derive(Debug, Clone, Copy, Eq, PartialEq)]
98pub enum DiscordChannel {
99 Stable,
100 Canary,
101 Ptb,
102 Development,
103}
104
105impl DiscordChannel {
106 pub fn valid_values() -> &'static [&'static str] {
107 &["stable", "canary", "ptb", "development"]
108 }
109
110 pub fn install_dir_name(self) -> &'static str {
111 match self {
112 Self::Stable => "Discord",
113 Self::Canary => "DiscordCanary",
114 Self::Ptb => "DiscordPTB",
115 Self::Development => "DiscordDevelopment",
116 }
117 }
118
119 pub fn exe_candidates(self) -> &'static [&'static str] {
120 match self {
121 Self::Stable => &["Discord.exe"],
122 Self::Canary => &["DiscordCanary.exe"],
123 Self::Ptb => &["DiscordPTB.exe"],
124 Self::Development => &["DiscordDevelopment.exe"],
125 }
126 }
127}
128
129impl FromStr for DiscordChannel {
130 type Err = anyhow::Error;
131
132 fn from_str(value: &str) -> Result<Self> {
133 match value.trim().to_ascii_lowercase().as_str() {
134 "stable" | "discord" => Ok(Self::Stable),
135 "canary" | "discordcanary" => Ok(Self::Canary),
136 "ptb" | "discordptb" => Ok(Self::Ptb),
137 "development" | "dev" | "discorddevelopment" => Ok(Self::Development),
138 other => anyhow::bail!("unsupported Discord channel: {other}"),
139 }
140 }
141}
142
143impl fmt::Display for DiscordChannel {
144 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
145 let value = match self {
146 Self::Stable => "stable",
147 Self::Canary => "canary",
148 Self::Ptb => "ptb",
149 Self::Development => "development",
150 };
151 formatter.write_str(value)
152 }
153}
154
155#[allow(dead_code)]
156pub fn discover(_channel: DiscordChannel, _override_dir: Option<&Path>) -> Result<DiscordInstall> {
157 discover_install(_channel, _override_dir)
158}