1차 제작
기능은 다 만들었는데 테스트를 못해봄 그래서 잘 작동하는지 모름 집가서 테스트해봐야지
This commit is contained in:
315
MainWindow.xaml.cs
Normal file
315
MainWindow.xaml.cs
Normal file
@@ -0,0 +1,315 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace AudioBotProject
|
||||
{
|
||||
public class AppConfig
|
||||
{
|
||||
public string BotToken { get; set; } = "";
|
||||
public string[] SelectedApps { get; set; } = Array.Empty<string>();
|
||||
public ulong LastServerId { get; set; } = 0; // 글자 대신 고유 ID로 저장!
|
||||
public ulong LastChannelId { get; set; } = 0;
|
||||
}
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
// 💡 API 통신 매니저 생성
|
||||
private DiscordBotManager _botManager = new DiscordBotManager();
|
||||
|
||||
private bool _isBotRunning = false;
|
||||
private bool _isInChannel = false;
|
||||
private bool _isRoutingStarted = false;
|
||||
|
||||
private ObservableCollection<string> _selectedApps = new ObservableCollection<string>();
|
||||
private readonly string _configFilePath = "config.json";
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
SelectedAppsListBox.ItemsSource = _selectedApps;
|
||||
|
||||
// 💡 디스코드 매니저에서 오는 신호(로그, 준비완료)를 화면(UI)에 연결
|
||||
// (주의: 디스코드 신호는 백그라운드 스레드에서 오므로 Dispatcher.Invoke를 써야 화면 수정이 가능합니다.)
|
||||
_botManager.OnLog += msg => Dispatcher.Invoke(() => LogToMain(msg));
|
||||
_botManager.OnReady += () => Dispatcher.Invoke(BotReadyHandler);
|
||||
|
||||
LogToMain("프로그램이 시작되었습니다.");
|
||||
LoadConfig();
|
||||
}
|
||||
|
||||
// 봇이 완전히 로그인되었을 때 실행될 UI 업데이트
|
||||
private void BotReadyHandler()
|
||||
{
|
||||
BotToggleBtn.Content = "봇 중지";
|
||||
BotToggleBtn.IsEnabled = true; // 로그인 중에는 버튼 잠갔다가 완료되면 풀기
|
||||
BotResultText.Text = "✅ 봇이 정상적으로 실행되었습니다.";
|
||||
CurrentBotNameText.Text = $"현재 실행중인 봇: {_botManager.GetBotName()}";
|
||||
NavChannelSettingsBtn.IsEnabled = true;
|
||||
}
|
||||
|
||||
#region [ 설정 저장 & 불러오기 로직 ]
|
||||
private void SaveConfig()
|
||||
{
|
||||
var config = new AppConfig
|
||||
{
|
||||
BotToken = TokenTextBox.Text,
|
||||
SelectedApps = _selectedApps.ToArray(),
|
||||
// 콤보박스에서 선택된 서버/채널의 고유 ID 값을 저장합니다.
|
||||
LastServerId = ServerComboBox.SelectedValue is ulong sId ? sId : 0,
|
||||
LastChannelId = ChannelComboBox.SelectedValue is ulong cId ? cId : 0
|
||||
};
|
||||
|
||||
var options = new JsonSerializerOptions { WriteIndented = true };
|
||||
string jsonString = JsonSerializer.Serialize(config, options);
|
||||
File.WriteAllText(_configFilePath, jsonString);
|
||||
}
|
||||
|
||||
private void LoadConfig()
|
||||
{
|
||||
if (File.Exists(_configFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
string jsonString = File.ReadAllText(_configFilePath);
|
||||
var config = JsonSerializer.Deserialize<AppConfig>(jsonString);
|
||||
|
||||
if (config != null)
|
||||
{
|
||||
TokenTextBox.Text = config.BotToken;
|
||||
_selectedApps.Clear();
|
||||
foreach (var app in config.SelectedApps) _selectedApps.Add(app);
|
||||
LogToMain("✅ 이전 설정을 성공적으로 불러왔습니다.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogToMain($"❌ 설정 불러오기 실패: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region [ 화면 전환 로직 (Navigation) ]
|
||||
private void HideAllViews()
|
||||
{
|
||||
MainView.Visibility = Visibility.Collapsed;
|
||||
BotSettingsView.Visibility = Visibility.Collapsed;
|
||||
ChannelSettingsView.Visibility = Visibility.Collapsed;
|
||||
OutputSettingsView.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
private void Nav_BackToMain_Click(object sender, RoutedEventArgs e) { HideAllViews(); MainView.Visibility = Visibility.Visible; }
|
||||
private void Nav_BotSettings_Click(object sender, RoutedEventArgs e) { HideAllViews(); BotSettingsView.Visibility = Visibility.Visible; }
|
||||
private void Nav_ChannelSettings_Click(object sender, RoutedEventArgs e) { HideAllViews(); ChannelSettingsView.Visibility = Visibility.Visible; }
|
||||
private void Nav_OutputSettings_Click(object sender, RoutedEventArgs e) { HideAllViews(); OutputSettingsView.Visibility = Visibility.Visible; }
|
||||
#endregion
|
||||
|
||||
#region [ 봇 설정 기능 (비동기 연동) ]
|
||||
private async void BotToggleBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isBotRunning)
|
||||
{
|
||||
string token = TokenTextBox.Text;
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
BotResultText.Text = "❌ 토큰을 입력해주세요.";
|
||||
return;
|
||||
}
|
||||
|
||||
SaveConfig();
|
||||
_isBotRunning = true;
|
||||
BotToggleBtn.IsEnabled = false; // 로그인 완료 전까지 연타 방지
|
||||
BotResultText.Text = "⏳ 디스코드 서버에 연결 중...";
|
||||
|
||||
// 💡 API 연결 시작!
|
||||
await _botManager.StartBotAsync(token);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_isRoutingStarted)
|
||||
{
|
||||
_isRoutingStarted = false;
|
||||
MainStartRoutingBtn.Content = "🚀 시작";
|
||||
MainStartRoutingBtn.Background = (System.Windows.Media.Brush)new System.Windows.Media.BrushConverter().ConvertFrom("#FF5865F2")!;
|
||||
}
|
||||
|
||||
if (_isInChannel)
|
||||
{
|
||||
_isInChannel = false;
|
||||
ChannelToggleBtn.Content = "채널 접속";
|
||||
ChannelResultText.Text = "봇이 중지되어 채널에서 나왔습니다.";
|
||||
}
|
||||
|
||||
// 💡 API 연결 종료!
|
||||
await _botManager.StopBotAsync();
|
||||
|
||||
_isBotRunning = false;
|
||||
BotToggleBtn.Content = "봇 실행";
|
||||
BotResultText.Text = "봇이 안전하게 중지되었습니다.";
|
||||
CurrentBotNameText.Text = "현재 실행중인 봇: 없음";
|
||||
NavChannelSettingsBtn.IsEnabled = false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region [ 채널 설정 기능 (실제 서버 데이터 바인딩) ]
|
||||
private void ServerComboBox_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
// 💡 봇 매니저에게 실제 서버 목록을 달라고 요청합니다.
|
||||
var servers = _botManager.GetServers()
|
||||
.Select(g => new { Id = g.Id, Name = g.Name })
|
||||
.ToList();
|
||||
|
||||
ServerComboBox.ItemsSource = servers;
|
||||
ServerComboBox.DisplayMemberPath = "Name"; // 화면에 보여줄 글자
|
||||
ServerComboBox.SelectedValuePath = "Id"; // 뒤에 숨겨둘 고유 ID
|
||||
}
|
||||
|
||||
private void ServerComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
ChannelComboBox.IsEnabled = ServerComboBox.SelectedItem != null;
|
||||
ChannelComboBox.ItemsSource = null; // 서버가 바뀌면 채널 목록 초기화
|
||||
}
|
||||
|
||||
private void ChannelComboBox_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
if (ServerComboBox.SelectedValue is ulong guildId)
|
||||
{
|
||||
// 💡 선택한 서버의 고유 ID를 넘겨주고, 실제 음성 채널 목록을 받아옵니다.
|
||||
var channels = _botManager.GetVoiceChannels(guildId)
|
||||
.Select(c => new { Id = c.Id, Name = c.Name })
|
||||
.ToList();
|
||||
|
||||
ChannelComboBox.ItemsSource = channels;
|
||||
ChannelComboBox.DisplayMemberPath = "Name";
|
||||
ChannelComboBox.SelectedValuePath = "Id";
|
||||
}
|
||||
}
|
||||
|
||||
private async void ChannelToggleBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ServerComboBox.SelectedValue == null || ChannelComboBox.SelectedValue == null)
|
||||
{
|
||||
ChannelResultText.Text = "❌ 서버와 채널을 모두 선택해주세요.";
|
||||
return;
|
||||
}
|
||||
|
||||
// 숨겨둔 고유 ID 추출
|
||||
ulong channelId = (ulong)ChannelComboBox.SelectedValue;
|
||||
|
||||
if (!_isInChannel)
|
||||
{
|
||||
ChannelToggleBtn.IsEnabled = false;
|
||||
ChannelResultText.Text = "⏳ 접속 중...";
|
||||
|
||||
// 💡 음성 채널 접속 API 호출
|
||||
await _botManager.JoinChannelAsync(channelId);
|
||||
|
||||
_isInChannel = true;
|
||||
ChannelToggleBtn.IsEnabled = true;
|
||||
ChannelToggleBtn.Content = "채널 나가기";
|
||||
ChannelResultText.Text = "✅ 음성 채널에 정상적으로 접속했습니다.";
|
||||
|
||||
SaveConfig(); // 접속 성공 시 저장
|
||||
}
|
||||
else
|
||||
{
|
||||
ChannelToggleBtn.IsEnabled = false;
|
||||
|
||||
// 💡 음성 채널 퇴장 API 호출
|
||||
await _botManager.LeaveChannelAsync();
|
||||
|
||||
_isInChannel = false;
|
||||
ChannelToggleBtn.IsEnabled = true;
|
||||
ChannelToggleBtn.Content = "채널 접속";
|
||||
ChannelResultText.Text = "채널에서 나왔습니다.";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region [ 출력 설정 기능 ]
|
||||
private void ProcessComboBox_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
ProcessComboBox.Items.Clear();
|
||||
var processes = Process.GetProcesses()
|
||||
.Where(p => p.MainWindowHandle != IntPtr.Zero && !string.IsNullOrEmpty(p.MainWindowTitle))
|
||||
.Select(p => p.ProcessName)
|
||||
.Distinct()
|
||||
.OrderBy(n => n);
|
||||
foreach (var pName in processes) ProcessComboBox.Items.Add(pName);
|
||||
}
|
||||
|
||||
private void AddOutputAppBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ProcessComboBox.SelectedItem != null)
|
||||
{
|
||||
string? appName = ProcessComboBox.SelectedItem.ToString();
|
||||
if (!string.IsNullOrEmpty(appName) && !_selectedApps.Contains(appName))
|
||||
_selectedApps.Add(appName);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveAppBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Button? btn = sender as Button;
|
||||
if (btn != null && btn.Tag != null)
|
||||
{
|
||||
string? appName = btn.Tag.ToString();
|
||||
if (!string.IsNullOrEmpty(appName)) _selectedApps.Remove(appName);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveOutputSettingsBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveConfig();
|
||||
LogToMain($"출력 설정이 저장되었습니다. (대상 앱: {_selectedApps.Count}개)");
|
||||
MessageBox.Show("설정이 성공적으로 저장되었습니다.", "알림", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region [ 메인 화면 라우팅 시작/종료 ]
|
||||
private void MainStartRoutingBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!_isBotRunning) { MessageBox.Show("먼저 봇을 실행해주세요!", "경고", MessageBoxButton.OK, MessageBoxImage.Warning); return; }
|
||||
if (!_isInChannel) { MessageBox.Show("먼저 채널에 접속해주세요!", "경고", MessageBoxButton.OK, MessageBoxImage.Warning); return; }
|
||||
|
||||
if (!_isRoutingStarted)
|
||||
{
|
||||
_isRoutingStarted = true;
|
||||
MainStartRoutingBtn.Content = "⏹️ 종료";
|
||||
MainStartRoutingBtn.Background = System.Windows.Media.Brushes.DarkRed;
|
||||
LogToMain("오디오 라우팅을 시작했습니다!");
|
||||
}
|
||||
else
|
||||
{
|
||||
_isRoutingStarted = false;
|
||||
MainStartRoutingBtn.Content = "🚀 시작";
|
||||
MainStartRoutingBtn.Background = (System.Windows.Media.Brush)new System.Windows.Media.BrushConverter().ConvertFrom("#FF5865F2")!;
|
||||
LogToMain("오디오 라우팅을 종료했습니다.");
|
||||
}
|
||||
}
|
||||
|
||||
private void LogToMain(string message)
|
||||
{
|
||||
MainLogBox.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}\n");
|
||||
MainLogBox.ScrollToEnd();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region [ 프로그램 종료 시 완벽한 정리 ]
|
||||
private async void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
// 프로그램 종료 시 봇도 확실하게 로그아웃 시키기
|
||||
if (_isBotRunning)
|
||||
{
|
||||
await _botManager.StopBotAsync();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user