From 6fd6ece695548f41f3a72d8c320fd8f7cb3cd803 Mon Sep 17 00:00:00 2001 From: SagalVanderklok Date: Sat, 8 Feb 2025 13:01:00 +0700 Subject: [PATCH] v1.6.4 --- ChatRoomRecorder/ChatRoom.cs | 596 +++++++++++++++-------- ChatRoomRecorder/ChatRoomRecorder.csproj | 4 +- ChatRoomRecorder/ChatRoomWebsite.cs | 3 +- ChatRoomRecorder/MainForm.Designer.cs | 162 ++++-- ChatRoomRecorder/MainForm.cs | 123 +++-- ChatRoomRecorder/MainForm.resx | 64 +-- ChatRoomRecorder/Settings.cs | 32 +- 7 files changed, 654 insertions(+), 330 deletions(-) diff --git a/ChatRoomRecorder/ChatRoom.cs b/ChatRoomRecorder/ChatRoom.cs index 5d8378f..0be14f7 100644 --- a/ChatRoomRecorder/ChatRoom.cs +++ b/ChatRoomRecorder/ChatRoom.cs @@ -8,16 +8,57 @@ using System.Net; using System.Net.Http; using System.Text; -using System.Text.Json; using System.Text.Json.Nodes; using System.Text.RegularExpressions; using System.Threading; +using System.Threading.Tasks; namespace ChatRoomRecorder { public class ChatRoom : IDisposable { - public event EventHandler UpdateCompleted; + public static Tuple ParseUrl(string url) + { + if (url == null || url.Length == 0) + { + return null; + } + + url = url.ToLower(); + if (url[url.Length - 1] != '/') + { + url += '/'; + } + + MatchCollection matches; + + if ((matches = Regex.Matches(url, @"^https://chaturbate.com/([^/]+)/.*$", RegexOptions.IgnoreCase)).Count > 0 || + (matches = Regex.Matches(url, @"^chaturbate[ ]+([^ ]+).*/$", RegexOptions.IgnoreCase)).Count > 0) + + { + return Tuple.Create(ChatRoomWebsite.Chaturbate, matches[0].Groups[1].Value, string.Format("https://chaturbate.com/{0}/", matches[0].Groups[1].Value)); + } + + if ((matches = Regex.Matches(url, @"^https://(?:[a-z0-9-.]+.)?bongacams[0-9]*.com/([^/]+(?=#!/.*$)|[^/]+(?=/.*$))", RegexOptions.IgnoreCase)).Count > 0 || + (matches = Regex.Matches(url, @"^bongacams[ ]+([^ ]+).*/$", RegexOptions.IgnoreCase)).Count > 0) + { + return Tuple.Create(ChatRoomWebsite.BongaCams, matches[0].Groups[1].Value, string.Format("https://bongacams.com/{0}/", matches[0].Groups[1].Value)); + } + + if ((matches = Regex.Matches(url, @"^https://(?:[a-z0-9-.]+.)?stripchat.com/([^/]+)/.*$", RegexOptions.IgnoreCase)).Count > 0 || + (matches = Regex.Matches(url, @"^stripchat[ ]+([^ ]+).*/$", RegexOptions.IgnoreCase)).Count > 0) + { + return Tuple.Create(ChatRoomWebsite.Stripchat, matches[0].Groups[1].Value, string.Format("https://stripchat.com/{0}/", matches[0].Groups[1].Value)); + } + + if ((matches = Regex.Matches(url, @"^https://www.flirt4free.com/\?model=([^/]+)/.*$", RegexOptions.IgnoreCase)).Count > 0 || + (matches = Regex.Matches(url, @"^flirt4free[ ]+([^ ]+).*/$", RegexOptions.IgnoreCase)).Count > 0) + { + return Tuple.Create(ChatRoomWebsite.Flirt4Free, matches[0].Groups[1].Value, string.Format("https://www.flirt4free.com/?model={0}/", matches[0].Groups[1].Value)); + } + + return null; + } public ChatRoom(string url) { @@ -36,6 +77,7 @@ public ChatRoom(string url) _outputDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyVideos); _ffmpegPath = string.Format("{0}\\Streamlink\\ffmpeg\\ffmpeg.exe", Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)); _streamlinkPath = string.Format("{0}\\Streamlink\\bin\\streamlink.exe", Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)); + _delay = 0; _processes = new List(); _fileName = string.Empty; _fileSize = -1; @@ -48,6 +90,7 @@ public ChatRoom(string url) _cancellationToken = _cancellationTokenSource.Token; _browser = null; _browserInitialized = false; + _uri = string.Empty; _timer = new System.Windows.Forms.Timer(); _timer.Interval = 1000; _timer.Tick += _timer_Tick; @@ -79,43 +122,6 @@ public void Dispose() } } - private void _timer_Tick(object sender, EventArgs e) - { - if (_semaphore.CurrentCount > 0) - { - _semaphore.Wait(); - try - { - if (_timer.Enabled && !_disposingFinished && (!_isUpdating || _isUpdating && (DateTime.Now - _lastUpdated).TotalSeconds >= c_updateLimit)) - { - _timer.Stop(); - - foreach (Process process in _processes) - { - if (process.HasExited == false) - { - process.Kill(); - process.WaitForExit(); - } - process.Close(); - } - - if (_browser != null) - { - _browser.Dispose(); - } - - _disposingFinished = true; - Interlocked.Decrement(ref s_totalCount); - } - } - finally - { - _semaphore.Release(); - } - } - } - public void Update() { _semaphore.Wait(); @@ -222,6 +228,9 @@ public void Update() case ChatRoomWebsite.Stripchat: SendRequestStripchat(); break; + case ChatRoomWebsite.Flirt4Free: + SendRequestFlirt4Free(); + break; } } } @@ -236,23 +245,49 @@ public void Update() } } - private void _browser_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e) + private async void _timer_Tick(object sender, EventArgs e) { - _semaphore.Wait(); - try + if (_semaphore.CurrentCount > 0) { - switch (_website) + await _semaphore.WaitAsync(); + try { - case ChatRoomWebsite.Chaturbate: - _browser.CoreWebView2.WebResourceResponseReceived += _browser_WebResourceResponseReceivedChaturbate; - break; - case ChatRoomWebsite.BongaCams: - _browser.CoreWebView2.WebResourceResponseReceived += _browser_WebResourceResponseReceivedBongaCams; - break; - case ChatRoomWebsite.Stripchat: - _browser.CoreWebView2.WebResourceResponseReceived += _browser_WebResourceResponseReceivedStripchat; - break; + if (_timer.Enabled && !_disposingFinished && (!_isUpdating || _isUpdating && (DateTime.Now - _lastUpdated).TotalSeconds >= c_updateLimit)) + { + _timer.Stop(); + + foreach (Process process in _processes) + { + if (process.HasExited == false) + { + process.Kill(); + process.WaitForExit(); + } + process.Close(); + } + + if (_browser != null) + { + _browser.Dispose(); + } + + _disposingFinished = true; + Interlocked.Decrement(ref s_totalCount); + } + } + finally + { + _semaphore.Release(); } + } + } + + private async void _browser_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e) + { + await _semaphore.WaitAsync(); + try + { + _browser.CoreWebView2.WebResourceResponseReceived += _browser_WebResourceResponseReceived; _browser.CoreWebView2.NavigationCompleted += _browser_NavigationCompleted; _browserInitialized = true; _isUpdating = false; @@ -260,14 +295,60 @@ private void _browser_CoreWebView2InitializationCompleted(object sender, CoreWeb finally { _semaphore.Release(); + } + + UpdateCompleted?.Invoke(this, EventArgs.Empty); + } + + private async void _browser_WebResourceResponseReceived(object sender, CoreWebView2WebResourceResponseReceivedEventArgs e) + { + if (_isUpdating && e.Request.Uri == _uri) + { + try + { + string response = await (new StreamReader(await e.Response.GetContentAsync())).ReadToEndAsync(); - UpdateCompleted?.Invoke(this, EventArgs.Empty); + await Task.Factory.StartNew(async () => + { + await _semaphore.WaitAsync(); + try + { + switch (_website) + { + case ChatRoomWebsite.Chaturbate: + ProcessResponseChaturbate(response); + break; + case ChatRoomWebsite.BongaCams: + ProcessResponseBongaCams(response); + break; + case ChatRoomWebsite.Stripchat: + ProcessResponseStripchat(response); + break; + case ChatRoomWebsite.Flirt4Free: + ProcessResponseFlirt4Free(response); + break; + } + + _isUpdating = false; + } + finally + { + _semaphore.Release(); + } + }, TaskCreationOptions.LongRunning).WaitAsync(_cancellationToken); + + UpdateCompleted?.Invoke(this, EventArgs.Empty); + } + catch (Exception exception) + { + AddLogEntry(string.Format("{0} - {1}", c_errorOccuredLogMessage, exception.Message)); + } } } - private void _browser_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e) + private async void _browser_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e) { - _semaphore.Wait(); + await _semaphore.WaitAsync(); try { if (_isUpdating && !e.IsSuccess) @@ -284,63 +365,103 @@ private void _browser_NavigationCompleted(object sender, CoreWebView2NavigationC } } - private void SendRequestChaturbate() + private async void SendRequestChaturbate() { - string postData = "room_slug=" + _name; - CoreWebView2WebResourceRequest request = _browser.CoreWebView2.Environment.CreateWebResourceRequest( - "https://chaturbate.com/get_edge_hls_url_ajax/", - "POST", - new MemoryStream(Encoding.UTF8.GetBytes(postData)), - "Content-Type: application/x-www-form-urlencoded\r\nX-Requested-With: XMLHttpRequest"); - _browser.CoreWebView2.NavigateWithWebResourceRequest(request); + try + { + await Task.Delay(s_random.Next(0, _delay * 1000), _cancellationToken); + + _uri = "https://chaturbate.com/get_edge_hls_url_ajax/"; + + string postData = "room_slug=" + _name; + CoreWebView2WebResourceRequest request = _browser.CoreWebView2.Environment.CreateWebResourceRequest( + _uri, + "POST", + new MemoryStream(Encoding.UTF8.GetBytes(postData)), + "Content-Type: application/x-www-form-urlencoded\r\nX-Requested-With: XMLHttpRequest"); + _browser.CoreWebView2.NavigateWithWebResourceRequest(request); + } + catch + { + //do nothing + } } - private void SendRequestBongaCams() + private async void SendRequestBongaCams() { - string postData = "model_search[display_name]=" + _name; - CoreWebView2WebResourceRequest request = _browser.CoreWebView2.Environment.CreateWebResourceRequest( - "https://bongacams.com/tools/listing_v3.php", - "POST", - new MemoryStream(Encoding.UTF8.GetBytes(postData)), - "Content-Type: application/x-www-form-urlencoded\r\nX-Requested-With: XMLHttpRequest"); - _browser.CoreWebView2.NavigateWithWebResourceRequest(request); + try + { + await Task.Delay(s_random.Next(0, _delay * 1000), _cancellationToken); + + _uri = "https://bongacams.com/tools/listing_v3.php"; + + string postData = "model_search[display_name]=" + _name; + CoreWebView2WebResourceRequest request = _browser.CoreWebView2.Environment.CreateWebResourceRequest( + _uri, + "POST", + new MemoryStream(Encoding.UTF8.GetBytes(postData)), + "Content-Type: application/x-www-form-urlencoded\r\nX-Requested-With: XMLHttpRequest"); + _browser.CoreWebView2.NavigateWithWebResourceRequest(request); + } + catch + { + //do nothing + } } - private void SendRequestStripchat() + private async void SendRequestStripchat() { - CoreWebView2WebResourceRequest request = _browser.CoreWebView2.Environment.CreateWebResourceRequest( - string.Format("https://stripchat.com/api/front/v2/models/username/{0}/cam", _name), - "GET", - null, - "Content-Type: application/x-www-form-urlencoded\r\nX-Requested-With: XMLHttpRequest"); - _browser.CoreWebView2.NavigateWithWebResourceRequest(request); + try + { + await Task.Delay(s_random.Next(0, _delay * 1000), _cancellationToken); + + _uri = string.Format("https://stripchat.com/api/front/v2/models/username/{0}/cam", _name); + + CoreWebView2WebResourceRequest request = _browser.CoreWebView2.Environment.CreateWebResourceRequest( + _uri, + "GET", + null, + "Content-Type: application/x-www-form-urlencoded\r\nX-Requested-With: XMLHttpRequest"); + _browser.CoreWebView2.NavigateWithWebResourceRequest(request); + } + catch + { + //do nothing + } } - private async void _browser_WebResourceResponseReceivedChaturbate(object sender, Microsoft.Web.WebView2.Core.CoreWebView2WebResourceResponseReceivedEventArgs e) + private async void SendRequestFlirt4Free() { - await _semaphore.WaitAsync(); try { - if (!_isUpdating) - { - return; - } + await Task.Delay(s_random.Next(0, _delay * 1000), _cancellationToken); + + _uri = "https://www.flirt4free.com/?tpl=index2&model=json"; + + CoreWebView2WebResourceRequest request = _browser.CoreWebView2.Environment.CreateWebResourceRequest( + _uri, + "GET", + null, + "Content-Type: application/x-www-form-urlencoded\r\nX-Requested-With: XMLHttpRequest"); + _browser.CoreWebView2.NavigateWithWebResourceRequest(request); } - finally + catch { - _semaphore.Release(); + //do nothing } + } + private void ProcessResponseChaturbate(string response) + { ChatRoomStatus status = ChatRoomStatus.Unknown; string playlistUrl = string.Empty; List availableResolutions = new List(); try { - string respStr = new StreamReader(await e.Response.GetContentAsync()).ReadToEnd(); - JsonDocument doc = JsonDocument.Parse(respStr); + JsonNode chatRoomNode = JsonNode.Parse(response); - switch (doc.RootElement.GetProperty("room_status").GetString()) + switch ((string)chatRoomNode["room_status"]) { case "public": status = ChatRoomStatus.Public; @@ -359,18 +480,18 @@ private async void _browser_WebResourceResponseReceivedChaturbate(object sender, break; } - AddLogEntry(string.Format("{0} - {1}", c_statusObtainedLogMessage, doc.RootElement.GetProperty("room_status").GetString())); + AddLogEntry(string.Format("{0} - {1} ('{2}')", c_statusObtainedLogMessage, status, (string)chatRoomNode["room_status"])); if (status == ChatRoomStatus.Public) { - playlistUrl = doc.RootElement.GetProperty("url").GetString(); + playlistUrl = (string)chatRoomNode["url"]; AddLogEntry(string.Format("{0} - {1}", c_playlistObtainedLogMessage, playlistUrl)); HttpRequestMessage reqMsg = new(HttpMethod.Get, playlistUrl); reqMsg.Headers.Add("Accept-Encoding", "gzip"); - HttpResponseMessage respMsg = await s_httpClient.SendAsync(reqMsg, _cancellationToken); - string[] playlist = (await respMsg.Content.ReadAsStringAsync()).Split('\n'); + HttpResponseMessage respMsg = s_httpClient.Send(reqMsg, _cancellationToken); + string[] playlist = new StreamReader(respMsg.Content.ReadAsStream()).ReadToEnd().Split('\n'); for (int i = 0; i < playlist.Length; i++) { MatchCollection matches = Regex.Matches(playlist[i], "^.*RESOLUTION=([0-9]*x[0-9]*).*$", RegexOptions.IgnoreCase); @@ -402,87 +523,65 @@ private async void _browser_WebResourceResponseReceivedChaturbate(object sender, Record(playlistUrl, streamIndex); } } - - if (status == ChatRoomStatus.Record || status == ChatRoomStatus.Public || status == ChatRoomStatus.Private || status == ChatRoomStatus.Hidden || status == ChatRoomStatus.Away) - { - _lastSeen = DateTime.Now; - } } - catch (Exception) + catch (Exception exception) { status = ChatRoomStatus.Error; playlistUrl = string.Empty; availableResolutions.Clear(); - AddLogEntry(c_errorOccuredLogMessage); + AddLogEntry(string.Format("{0} - {1}", c_errorOccuredLogMessage, exception.Message)); } - - await _semaphore.WaitAsync(); - try + finally { _status = status; _playlistUrl = playlistUrl; _availableResolutions = availableResolutions; - _isUpdating = false; } - finally + + if (_status != ChatRoomStatus.Offline && _status != ChatRoomStatus.Error && _status != ChatRoomStatus.Unknown) { - _semaphore.Release(); + _lastSeen = DateTime.Now; } - - UpdateCompleted?.Invoke(this, EventArgs.Empty); } - private async void _browser_WebResourceResponseReceivedBongaCams(object sender, CoreWebView2WebResourceResponseReceivedEventArgs e) + private void ProcessResponseBongaCams(string response) { - await _semaphore.WaitAsync(); - try - { - if (!_isUpdating) - { - return; - } - } - finally - { - _semaphore.Release(); - } - ChatRoomStatus status = ChatRoomStatus.Unknown; string playlistUrl = string.Empty; List availableResolutions = new List(); try { - string respStr = new StreamReader(await e.Response.GetContentAsync()).ReadToEnd(); - JsonNode rootNode = JsonNode.Parse(respStr); - JsonNode modelNode = null; + JsonNode rootNode = JsonNode.Parse(response); + JsonNode chatRoomNode = null; - for (int i = 0; i < (int)rootNode["total_count"] && modelNode == null; i++) + for (int i = 0; i < (int)rootNode["total_count"] && chatRoomNode == null; i++) { JsonNode node = ((JsonArray)rootNode["models"])[i]; string name = (string)node["username"]; if (name != null && name.ToLower() == _name) { - modelNode = node; + chatRoomNode = node; } } - if (modelNode == null) + if (chatRoomNode == null) { throw new ArgumentException(); } - string esid = (string)modelNode["esid"]; + string esid = (string)chatRoomNode["esid"]; + if (esid == null) { throw new ArgumentException(); } - playlistUrl = string.Format("https://{0}.bcvcdn.com/hls/stream_{1}/playlist.m3u8", esid, (string)modelNode["username"]); + playlistUrl = string.Format("https://{0}.bcvcdn.com/hls/stream_{1}/playlist.m3u8", esid, (string)chatRoomNode["username"]); HttpRequestMessage reqMsg = new(HttpMethod.Get, playlistUrl); - HttpResponseMessage respMsg = await s_httpClient.SendAsync(reqMsg, _cancellationToken); + HttpResponseMessage respMsg = s_httpClient.Send(reqMsg, _cancellationToken); if (respMsg.IsSuccessStatusCode) { status = ChatRoomStatus.Public; @@ -498,7 +597,7 @@ private async void _browser_WebResourceResponseReceivedBongaCams(object sender, { AddLogEntry(string.Format("{0} - {1}", c_playlistObtainedLogMessage, playlistUrl)); - string[] playlist = (await respMsg.Content.ReadAsStringAsync()).Split('\n'); + string[] playlist = new StreamReader(respMsg.Content.ReadAsStream()).ReadToEnd().Split('\n'); for (int i = 0; i < playlist.Length; i++) { MatchCollection matches = Regex.Matches(playlist[i], "^.*RESOLUTION=([0-9]*x[0-9]*).*$", RegexOptions.IgnoreCase); @@ -530,60 +629,37 @@ private async void _browser_WebResourceResponseReceivedBongaCams(object sender, Record(playlistUrl, streamIndex); } } - - if (status == ChatRoomStatus.Record || status == ChatRoomStatus.Public) - { - _lastSeen = DateTime.Now; - } } - catch (Exception) + catch (Exception exception) { status = ChatRoomStatus.Error; playlistUrl = String.Empty; availableResolutions.Clear(); - AddLogEntry(c_errorOccuredLogMessage); + AddLogEntry(string.Format("{0} - {1}", c_errorOccuredLogMessage, exception.Message)); } - - await _semaphore.WaitAsync(); - try + finally { _status = status; _playlistUrl = playlistUrl; _availableResolutions = availableResolutions; - _isUpdating = false; } - finally + + if (_status != ChatRoomStatus.Offline && _status != ChatRoomStatus.Error && _status != ChatRoomStatus.Unknown) { - _semaphore.Release(); + _lastSeen = DateTime.Now; } - - UpdateCompleted?.Invoke(this, EventArgs.Empty); } - private async void _browser_WebResourceResponseReceivedStripchat(object sender, CoreWebView2WebResourceResponseReceivedEventArgs e) + private void ProcessResponseStripchat(string response) { - await _semaphore.WaitAsync(); - try - { - if (!_isUpdating) - { - return; - } - } - finally - { - _semaphore.Release(); - } - ChatRoomStatus status = ChatRoomStatus.Unknown; string playlistUrl = string.Empty; List availableResolutions = new List(); try { - string respStr = new StreamReader(await e.Response.GetContentAsync()).ReadToEnd(); - JsonNode rootNode = JsonNode.Parse(respStr); + JsonNode rootNode = JsonNode.Parse(response); switch ((string)rootNode["user"]["user"]["status"]) { @@ -613,7 +689,7 @@ private async void _browser_WebResourceResponseReceivedStripchat(object sender, break; } - AddLogEntry(string.Format("{0} - {1}", c_statusObtainedLogMessage, rootNode["user"]["user"]["status"])); + AddLogEntry(string.Format("{0} - {1} ('{2}')", c_statusObtainedLogMessage, status, rootNode["user"]["user"]["status"])); if (status == ChatRoomStatus.Public) { @@ -677,35 +753,143 @@ private async void _browser_WebResourceResponseReceivedStripchat(object sender, Record(playlistUrl, -1); } } + } + catch (Exception exception) + { + status = ChatRoomStatus.Error; + playlistUrl = String.Empty; + availableResolutions.Clear(); + + AddLogEntry(string.Format("{0} - {1}", c_errorOccuredLogMessage, exception.Message)); + } + finally + { + _status = status; + _playlistUrl = playlistUrl; + _availableResolutions = availableResolutions; + } + + if (_status != ChatRoomStatus.Offline && _status != ChatRoomStatus.Error && _status != ChatRoomStatus.Unknown) + { + _lastSeen = DateTime.Now; + } + } + + private void ProcessResponseFlirt4Free(string response) + { + ChatRoomStatus status = ChatRoomStatus.Unknown; + string playlistUrl = string.Empty; + List availableResolutions = new List(); + + try + { + string name = string.Format("\"{0}\"", _name); + int pos = response.IndexOf(name); + int first = -1; + int last = -1; + int k = 0; + for (int i = pos - 1; i >= 0 && first == -1; i--) + { + switch (response[i]) + { + case '{': if (k == 0) first = i; else k--; break; + case '}': k++; break; + } + } + for (int i = pos + name.Length; i < response.Length && first != -1 && last == -1; i++) + { + switch (response[i]) + { + case '}': if (k == 0) last = i; else k--; break; + case '{': k++; break; + } + } + JsonNode chatRoomNode = JsonNode.Parse((first != -1 && last != -1) ? response.Substring(first, last - first + 1) : "{\"room_status_char\":\"\"}"); + + switch ((string)chatRoomNode["room_status_char"]) + { + case "O": + status = ChatRoomStatus.Public; + break; + case "P": + status = ChatRoomStatus.Private; + break; + case "F": + status = ChatRoomStatus.Private; + break; + case "": + status = ChatRoomStatus.Offline; + break; + } + + AddLogEntry(string.Format("{0} - {1} ('{2}')", c_statusObtainedLogMessage, status, chatRoomNode["room_status_char"])); + + if (status == ChatRoomStatus.Public) + { + int id = Convert.ToInt32((string)chatRoomNode["model_id"]); + + string streamInfoUrl = string.Format("https://www.flirt4free.com/ws/chat/get-stream-urls.php?model_id={0}", id); + HttpRequestMessage reqMsg = new(HttpMethod.Get, streamInfoUrl); + HttpResponseMessage respMsg = s_httpClient.Send(reqMsg, _cancellationToken); + JsonNode streamInfoNode = JsonNode.Parse(new StreamReader(respMsg.Content.ReadAsStream()).ReadToEnd()); + playlistUrl = string.Format("https:{0}", (string)streamInfoNode["data"]["hls"][0]["url"]); + + AddLogEntry(string.Format("{0} - {1}", c_playlistObtainedLogMessage, playlistUrl)); + + reqMsg = new(HttpMethod.Get, playlistUrl); + respMsg = s_httpClient.Send(reqMsg, _cancellationToken); + string[] playlist = new StreamReader(respMsg.Content.ReadAsStream()).ReadToEnd().Split('\n'); + for (int i = 0; i < playlist.Length; i++) + { + MatchCollection matches = Regex.Matches(playlist[i], "^.*RESOLUTION=([0-9]*x[0-9]*).*$", RegexOptions.IgnoreCase); + if (matches.Count > 0) + { + availableResolutions.Add(ChatRoomResolution.Parse(matches[0].Groups[1].Value)); + } + } + + AddLogEntry(string.Format("{0} - {1}", c_resolutionsObtainedLogMessage, string.Join(", ", availableResolutions))); + } - if (status == ChatRoomStatus.Record || status == ChatRoomStatus.Public || status == ChatRoomStatus.Private || status == ChatRoomStatus.Group) + if (status == ChatRoomStatus.Public && _action == ChatRoomAction.Record) + { + status = ChatRoomStatus.Record; + } + + if (status == ChatRoomStatus.Public || status == ChatRoomStatus.Record) { - _lastSeen = DateTime.Now; + int streamIndex = ChatRoomResolution.FindClosest(_preferredResolution, availableResolutions.ToArray()); + + if (streamIndex == -1) + { + throw new ArgumentException(); + } + + if (status == ChatRoomStatus.Record) + { + Record(playlistUrl, streamIndex); + } } } - catch (Exception) + catch (Exception exception) { status = ChatRoomStatus.Error; - playlistUrl = string.Empty; + playlistUrl = String.Empty; availableResolutions.Clear(); - AddLogEntry(c_errorOccuredLogMessage); + AddLogEntry(string.Format("{0} - {1}", c_errorOccuredLogMessage, exception.Message)); } - - await _semaphore.WaitAsync(); - try + finally { _status = status; _playlistUrl = playlistUrl; _availableResolutions = availableResolutions; - _isUpdating = false; } - finally + + if (_status != ChatRoomStatus.Offline && _status != ChatRoomStatus.Error && _status != ChatRoomStatus.Unknown) { - _semaphore.Release(); + _lastSeen = DateTime.Now; } - - UpdateCompleted?.Invoke(this, EventArgs.Empty); } private void Record(string playlistUrl, int streamIndex) @@ -745,6 +929,13 @@ private void Record(string playlistUrl, int streamIndex) Arguments = string.Format("-reconnect 1 -reconnect_at_eof 1 -reconnect_on_network_error 1 -reconnect_on_http_error 1 -reconnect_streamed 1 -i http://127.0.0.1:{0} -c copy \"{1}\"", port, _fileName) }); break; + case ChatRoomWebsite.Flirt4Free: + psis.Add(new ProcessStartInfo() + { + FileName = _ffmpegPath, + Arguments = string.Format("-analyzeduration 16M -i \"{0}\" -map 0:p:{1} -c copy \"{2}\"", playlistUrl, streamIndex, _fileName) + }); + break; } foreach (ProcessStartInfo psi in psis) @@ -763,42 +954,7 @@ private void AddLogEntry(string info) _log.Enqueue(new Tuple(DateTime.Now, info)); } - public static Tuple ParseUrl(string url) - { - if (url == null || url.Length == 0) - { - return null; - } - - url = url.ToLower(); - if (url[url.Length - 1] != '/') - { - url += '/'; - } - - MatchCollection matches; - - if ((matches = Regex.Matches(url, @"^https://chaturbate.com/([^/]+)/.*$", RegexOptions.IgnoreCase)).Count > 0 || - (matches = Regex.Matches(url, @"^chaturbate[ ]+([^ ]+).*/$", RegexOptions.IgnoreCase)).Count > 0) - - { - return Tuple.Create(ChatRoomWebsite.Chaturbate, matches[0].Groups[1].Value, string.Format("https://chaturbate.com/{0}/", matches[0].Groups[1].Value)); - } - - if ((matches = Regex.Matches(url, @"^https://(?:[a-z0-9-.]+.)?bongacams[0-9]*.com/([^/]+(?=#!/.*$)|[^/]+(?=/.*$))", RegexOptions.IgnoreCase)).Count > 0 || - (matches = Regex.Matches(url, @"^bongacams[ ]+([^ ]+).*/$", RegexOptions.IgnoreCase)).Count > 0) - { - return Tuple.Create(ChatRoomWebsite.BongaCams, matches[0].Groups[1].Value, string.Format("https://bongacams.com/{0}/", matches[0].Groups[1].Value)); - } - - if ((matches = Regex.Matches(url, @"^https://(?:[a-z0-9-.]+.)?stripchat.com/([^/]+)/.*$", RegexOptions.IgnoreCase)).Count > 0 || - (matches = Regex.Matches(url, @"^stripchat[ ]+([^ ]+).*/$", RegexOptions.IgnoreCase)).Count > 0) - { - return Tuple.Create(ChatRoomWebsite.Stripchat, matches[0].Groups[1].Value, string.Format("https://stripchat.com/{0}/", matches[0].Groups[1].Value)); - } - - return null; - } + public event EventHandler UpdateCompleted; public int ID { @@ -941,6 +1097,18 @@ public string StreamlinkPath } } + public int Delay + { + set + { + _delay = (value < 0) ? 0 : value; + } + get + { + return _delay; + } + } + public DateTime LastUpdated { set @@ -1009,6 +1177,7 @@ public static int TotalCount private string _outputDirectory; private string _ffmpegPath; private string _streamlinkPath; + private int _delay; private List _processes; private string _fileName; private long _fileSize; @@ -1021,6 +1190,7 @@ public static int TotalCount private CancellationToken _cancellationToken; private WebView2 _browser; private bool _browserInitialized; + private string _uri; private System.Windows.Forms.Timer _timer; private SemaphoreSlim _semaphore; private ConcurrentQueue> _log; diff --git a/ChatRoomRecorder/ChatRoomRecorder.csproj b/ChatRoomRecorder/ChatRoomRecorder.csproj index 55eac73..f3cae6a 100644 --- a/ChatRoomRecorder/ChatRoomRecorder.csproj +++ b/ChatRoomRecorder/ChatRoomRecorder.csproj @@ -7,8 +7,8 @@ True en-US true - 1.6.3 - Copyright (C) 2024 Sagal Vanderklok + 1.6.4 + Copyright (C) 2025 Sagal Vanderklok https://chatroomrecorder.com | https://github.com/sagalvanderklok/chatroomrecorder AnyCPU;x86;x64 diff --git a/ChatRoomRecorder/ChatRoomWebsite.cs b/ChatRoomRecorder/ChatRoomWebsite.cs index df7ab21..d22016b 100644 --- a/ChatRoomRecorder/ChatRoomWebsite.cs +++ b/ChatRoomRecorder/ChatRoomWebsite.cs @@ -4,6 +4,7 @@ public enum ChatRoomWebsite { BongaCams, Chaturbate, - Stripchat + Stripchat, + Flirt4Free } } diff --git a/ChatRoomRecorder/MainForm.Designer.cs b/ChatRoomRecorder/MainForm.Designer.cs index 45f9951..d27b566 100644 --- a/ChatRoomRecorder/MainForm.Designer.cs +++ b/ChatRoomRecorder/MainForm.Designer.cs @@ -30,11 +30,11 @@ private void InitializeComponent() { components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle6 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle7 = new System.Windows.Forms.DataGridViewCellStyle(); + System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle8 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle(); - System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle5 = new System.Windows.Forms.DataGridViewCellStyle(); FilesBindingSource = new System.Windows.Forms.BindingSource(components); TabControl = new System.Windows.Forms.TabControl(); WebBrowserTabPage = new System.Windows.Forms.TabPage(); @@ -107,6 +107,8 @@ private void InitializeComponent() DefaultResolutionComboBox = new System.Windows.Forms.ComboBox(); StreamlinkPathLabel = new System.Windows.Forms.Label(); StreamlinkPathTextBox = new System.Windows.Forms.TextBox(); + Flirt4FreeConcurrentUpdatesLabel = new System.Windows.Forms.Label(); + Flirt4FreeConcurrentUpdatesNumericUpDown = new System.Windows.Forms.NumericUpDown(); LogTabPage = new System.Windows.Forms.TabPage(); LogListBox = new System.Windows.Forms.ListBox(); LogContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(components); @@ -116,6 +118,8 @@ private void InitializeComponent() ChatRoomsUpdateTimer = new System.Windows.Forms.Timer(components); FormCloseTimer = new System.Windows.Forms.Timer(components); SettingsBindingSource = new System.Windows.Forms.BindingSource(components); + UpdateDelayLabel = new System.Windows.Forms.Label(); + UpdateDelayNumericUpDown = new System.Windows.Forms.NumericUpDown(); ((System.ComponentModel.ISupportInitialize)FilesBindingSource).BeginInit(); TabControl.SuspendLayout(); WebBrowserTabPage.SuspendLayout(); @@ -152,10 +156,12 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)BongaCamsConcurrentUpdatesNumericUpDown).BeginInit(); ((System.ComponentModel.ISupportInitialize)UpdateIntervalNumericUpDown).BeginInit(); ((System.ComponentModel.ISupportInitialize)StripchatConcurrentUpdatesNumericUpDown).BeginInit(); + ((System.ComponentModel.ISupportInitialize)Flirt4FreeConcurrentUpdatesNumericUpDown).BeginInit(); LogTabPage.SuspendLayout(); LogContextMenuStrip.SuspendLayout(); AboutTabPage.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)SettingsBindingSource).BeginInit(); + ((System.ComponentModel.ISupportInitialize)UpdateDelayNumericUpDown).BeginInit(); SuspendLayout(); // // TabControl @@ -533,38 +539,38 @@ private void InitializeComponent() ChatRoomsDataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; ChatRoomsDataGridView.BackgroundColor = System.Drawing.SystemColors.Window; ChatRoomsDataGridView.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single; - dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - ChatRoomsDataGridView.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1; + dataGridViewCellStyle6.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle6.BackColor = System.Drawing.SystemColors.Control; + dataGridViewCellStyle6.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + dataGridViewCellStyle6.ForeColor = System.Drawing.SystemColors.WindowText; + dataGridViewCellStyle6.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle6.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle6.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + ChatRoomsDataGridView.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle6; ChatRoomsDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; ChatRoomsDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { WebsiteColumn, NameColumn, ActionColumn, ResolutionColumn, StatusColumn, UpdatedColumn, SeenColumn, UrlColumn }); ChatRoomsDataGridView.ContextMenuStrip = ChatRoomsContextMenuStrip; ChatRoomsDataGridView.DataSource = ChatRoomsBindingSource; - dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window; - dataGridViewCellStyle2.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText; - dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False; - ChatRoomsDataGridView.DefaultCellStyle = dataGridViewCellStyle2; + dataGridViewCellStyle7.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle7.BackColor = System.Drawing.SystemColors.Window; + dataGridViewCellStyle7.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + dataGridViewCellStyle7.ForeColor = System.Drawing.SystemColors.ControlText; + dataGridViewCellStyle7.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle7.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle7.WrapMode = System.Windows.Forms.DataGridViewTriState.False; + ChatRoomsDataGridView.DefaultCellStyle = dataGridViewCellStyle7; ChatRoomsDataGridView.Dock = System.Windows.Forms.DockStyle.Fill; ChatRoomsDataGridView.Location = new System.Drawing.Point(0, 0); ChatRoomsDataGridView.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); ChatRoomsDataGridView.Name = "ChatRoomsDataGridView"; - dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; - dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Control; - dataGridViewCellStyle3.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - dataGridViewCellStyle3.ForeColor = System.Drawing.SystemColors.WindowText; - dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Highlight; - dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.HighlightText; - dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.True; - ChatRoomsDataGridView.RowHeadersDefaultCellStyle = dataGridViewCellStyle3; + dataGridViewCellStyle8.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; + dataGridViewCellStyle8.BackColor = System.Drawing.SystemColors.Control; + dataGridViewCellStyle8.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + dataGridViewCellStyle8.ForeColor = System.Drawing.SystemColors.WindowText; + dataGridViewCellStyle8.SelectionBackColor = System.Drawing.SystemColors.Highlight; + dataGridViewCellStyle8.SelectionForeColor = System.Drawing.SystemColors.HighlightText; + dataGridViewCellStyle8.WrapMode = System.Windows.Forms.DataGridViewTriState.True; + ChatRoomsDataGridView.RowHeadersDefaultCellStyle = dataGridViewCellStyle8; ChatRoomsDataGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; ChatRoomsDataGridView.Size = new System.Drawing.Size(647, 351); ChatRoomsDataGridView.TabIndex = 6; @@ -736,8 +742,8 @@ private void InitializeComponent() // FileNameColumn // FileNameColumn.DataPropertyName = "Name"; - dataGridViewCellStyle4.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - FileNameColumn.DefaultCellStyle = dataGridViewCellStyle4; + dataGridViewCellStyle1.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + FileNameColumn.DefaultCellStyle = dataGridViewCellStyle1; FileNameColumn.FillWeight = 199.8681F; FileNameColumn.HeaderText = "File name"; FileNameColumn.Name = "FileNameColumn"; @@ -745,10 +751,10 @@ private void InitializeComponent() // FileSizeColumn // FileSizeColumn.DataPropertyName = "Length"; - dataGridViewCellStyle5.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - dataGridViewCellStyle5.Format = "N0"; - dataGridViewCellStyle5.NullValue = null; - FileSizeColumn.DefaultCellStyle = dataGridViewCellStyle5; + dataGridViewCellStyle2.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + dataGridViewCellStyle2.Format = "N0"; + dataGridViewCellStyle2.NullValue = null; + FileSizeColumn.DefaultCellStyle = dataGridViewCellStyle2; FileSizeColumn.FillWeight = 50.25381F; FileSizeColumn.HeaderText = "File size"; FileSizeColumn.Name = "FileSizeColumn"; @@ -796,25 +802,31 @@ private void InitializeComponent() SettingsTableLayoutPanel.Controls.Add(FFmpegPathTextBox, 2, 1); SettingsTableLayoutPanel.Controls.Add(ChaturbateConcurrentUpdatesNumericUpDown, 2, 3); SettingsTableLayoutPanel.Controls.Add(BongaCamsConcurrentUpdatesNumericUpDown, 2, 4); - SettingsTableLayoutPanel.Controls.Add(UpdateIntervalNumericUpDown, 2, 6); + SettingsTableLayoutPanel.Controls.Add(UpdateIntervalNumericUpDown, 2, 8); SettingsTableLayoutPanel.Controls.Add(OutputDirectoryLabel, 1, 0); SettingsTableLayoutPanel.Controls.Add(FFmpegPathLabel, 1, 1); SettingsTableLayoutPanel.Controls.Add(ChaturbateConcurrentUpdatesLabel, 1, 3); SettingsTableLayoutPanel.Controls.Add(BongaCamsConcurrentUpdatesLabel, 1, 4); - SettingsTableLayoutPanel.Controls.Add(UpdateIntervalLabel, 1, 6); + SettingsTableLayoutPanel.Controls.Add(UpdateIntervalLabel, 1, 8); SettingsTableLayoutPanel.Controls.Add(StripchatConcurrentUpdatesLabel, 1, 5); SettingsTableLayoutPanel.Controls.Add(StripchatConcurrentUpdatesNumericUpDown, 2, 5); - SettingsTableLayoutPanel.Controls.Add(DefaultActionLabel, 1, 7); - SettingsTableLayoutPanel.Controls.Add(DefaultResolutionLabel, 1, 8); - SettingsTableLayoutPanel.Controls.Add(DefaultActionComboBox, 2, 7); - SettingsTableLayoutPanel.Controls.Add(DefaultResolutionComboBox, 2, 8); + SettingsTableLayoutPanel.Controls.Add(DefaultActionLabel, 1, 9); + SettingsTableLayoutPanel.Controls.Add(DefaultResolutionLabel, 1, 10); + SettingsTableLayoutPanel.Controls.Add(DefaultActionComboBox, 2, 9); + SettingsTableLayoutPanel.Controls.Add(DefaultResolutionComboBox, 2, 10); SettingsTableLayoutPanel.Controls.Add(StreamlinkPathLabel, 1, 2); SettingsTableLayoutPanel.Controls.Add(StreamlinkPathTextBox, 2, 2); + SettingsTableLayoutPanel.Controls.Add(Flirt4FreeConcurrentUpdatesLabel, 1, 6); + SettingsTableLayoutPanel.Controls.Add(Flirt4FreeConcurrentUpdatesNumericUpDown, 2, 6); + SettingsTableLayoutPanel.Controls.Add(UpdateDelayLabel, 1, 7); + SettingsTableLayoutPanel.Controls.Add(UpdateDelayNumericUpDown, 2, 7); SettingsTableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; SettingsTableLayoutPanel.Location = new System.Drawing.Point(0, 0); SettingsTableLayoutPanel.Margin = new System.Windows.Forms.Padding(0); SettingsTableLayoutPanel.Name = "SettingsTableLayoutPanel"; - SettingsTableLayoutPanel.RowCount = 10; + SettingsTableLayoutPanel.RowCount = 12; + SettingsTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29F)); + SettingsTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29F)); SettingsTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29F)); SettingsTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29F)); SettingsTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29F)); @@ -884,13 +896,13 @@ private void InitializeComponent() // UpdateIntervalNumericUpDown.BackColor = System.Drawing.SystemColors.Window; UpdateIntervalNumericUpDown.Dock = System.Windows.Forms.DockStyle.Top; - UpdateIntervalNumericUpDown.Location = new System.Drawing.Point(388, 179); + UpdateIntervalNumericUpDown.Location = new System.Drawing.Point(388, 237); UpdateIntervalNumericUpDown.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); UpdateIntervalNumericUpDown.Maximum = new decimal(new int[] { int.MaxValue, 0, 0, 0 }); UpdateIntervalNumericUpDown.Minimum = new decimal(new int[] { 1, 0, 0, 0 }); UpdateIntervalNumericUpDown.Name = "UpdateIntervalNumericUpDown"; UpdateIntervalNumericUpDown.Size = new System.Drawing.Size(350, 23); - UpdateIntervalNumericUpDown.TabIndex = 7; + UpdateIntervalNumericUpDown.TabIndex = 9; UpdateIntervalNumericUpDown.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; UpdateIntervalNumericUpDown.Value = new decimal(new int[] { 1, 0, 0, 0 }); // @@ -942,7 +954,7 @@ private void InitializeComponent() // UpdateIntervalLabel.AutoSize = true; UpdateIntervalLabel.Dock = System.Windows.Forms.DockStyle.Fill; - UpdateIntervalLabel.Location = new System.Drawing.Point(38, 179); + UpdateIntervalLabel.Location = new System.Drawing.Point(38, 237); UpdateIntervalLabel.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); UpdateIntervalLabel.Name = "UpdateIntervalLabel"; UpdateIntervalLabel.Size = new System.Drawing.Size(350, 24); @@ -978,7 +990,7 @@ private void InitializeComponent() // DefaultActionLabel.AutoSize = true; DefaultActionLabel.Dock = System.Windows.Forms.DockStyle.Fill; - DefaultActionLabel.Location = new System.Drawing.Point(38, 208); + DefaultActionLabel.Location = new System.Drawing.Point(38, 266); DefaultActionLabel.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); DefaultActionLabel.Name = "DefaultActionLabel"; DefaultActionLabel.Size = new System.Drawing.Size(350, 24); @@ -989,7 +1001,7 @@ private void InitializeComponent() // DefaultResolutionLabel.AutoSize = true; DefaultResolutionLabel.Dock = System.Windows.Forms.DockStyle.Fill; - DefaultResolutionLabel.Location = new System.Drawing.Point(38, 237); + DefaultResolutionLabel.Location = new System.Drawing.Point(38, 295); DefaultResolutionLabel.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); DefaultResolutionLabel.Name = "DefaultResolutionLabel"; DefaultResolutionLabel.Size = new System.Drawing.Size(350, 24); @@ -1002,22 +1014,22 @@ private void InitializeComponent() DefaultActionComboBox.Dock = System.Windows.Forms.DockStyle.Top; DefaultActionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; DefaultActionComboBox.FormattingEnabled = true; - DefaultActionComboBox.Location = new System.Drawing.Point(388, 208); + DefaultActionComboBox.Location = new System.Drawing.Point(388, 266); DefaultActionComboBox.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); DefaultActionComboBox.Name = "DefaultActionComboBox"; DefaultActionComboBox.Size = new System.Drawing.Size(350, 23); - DefaultActionComboBox.TabIndex = 8; + DefaultActionComboBox.TabIndex = 10; // // DefaultResolutionComboBox // DefaultResolutionComboBox.Dock = System.Windows.Forms.DockStyle.Top; DefaultResolutionComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; DefaultResolutionComboBox.FormattingEnabled = true; - DefaultResolutionComboBox.Location = new System.Drawing.Point(388, 237); + DefaultResolutionComboBox.Location = new System.Drawing.Point(388, 295); DefaultResolutionComboBox.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); DefaultResolutionComboBox.Name = "DefaultResolutionComboBox"; DefaultResolutionComboBox.Size = new System.Drawing.Size(350, 23); - DefaultResolutionComboBox.TabIndex = 9; + DefaultResolutionComboBox.TabIndex = 11; // // StreamlinkPathLabel // @@ -1042,6 +1054,30 @@ private void InitializeComponent() StreamlinkPathTextBox.TabIndex = 3; StreamlinkPathTextBox.Click += StreamlinkPathTextBox_Click; // + // Flirt4FreeConcurrentUpdatesLabel + // + Flirt4FreeConcurrentUpdatesLabel.AutoSize = true; + Flirt4FreeConcurrentUpdatesLabel.Dock = System.Windows.Forms.DockStyle.Fill; + Flirt4FreeConcurrentUpdatesLabel.Location = new System.Drawing.Point(38, 179); + Flirt4FreeConcurrentUpdatesLabel.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); + Flirt4FreeConcurrentUpdatesLabel.Name = "Flirt4FreeConcurrentUpdatesLabel"; + Flirt4FreeConcurrentUpdatesLabel.Size = new System.Drawing.Size(350, 24); + Flirt4FreeConcurrentUpdatesLabel.TabIndex = 46; + Flirt4FreeConcurrentUpdatesLabel.Text = "Flirt4Free concurrent updates"; + // + // Flirt4FreeConcurrentUpdatesNumericUpDown + // + Flirt4FreeConcurrentUpdatesNumericUpDown.Dock = System.Windows.Forms.DockStyle.Top; + Flirt4FreeConcurrentUpdatesNumericUpDown.Location = new System.Drawing.Point(388, 179); + Flirt4FreeConcurrentUpdatesNumericUpDown.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); + Flirt4FreeConcurrentUpdatesNumericUpDown.Maximum = new decimal(new int[] { int.MaxValue, 0, 0, 0 }); + Flirt4FreeConcurrentUpdatesNumericUpDown.Minimum = new decimal(new int[] { 1, 0, 0, 0 }); + Flirt4FreeConcurrentUpdatesNumericUpDown.Name = "Flirt4FreeConcurrentUpdatesNumericUpDown"; + Flirt4FreeConcurrentUpdatesNumericUpDown.Size = new System.Drawing.Size(350, 23); + Flirt4FreeConcurrentUpdatesNumericUpDown.TabIndex = 7; + Flirt4FreeConcurrentUpdatesNumericUpDown.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + Flirt4FreeConcurrentUpdatesNumericUpDown.Value = new decimal(new int[] { 1, 0, 0, 0 }); + // // LogTabPage // LogTabPage.Controls.Add(LogListBox); @@ -1117,6 +1153,28 @@ private void InitializeComponent() FormCloseTimer.Interval = 1000; FormCloseTimer.Tick += FormCloseTimer_Tick; // + // UpdateDelayLabel + // + UpdateDelayLabel.AutoSize = true; + UpdateDelayLabel.Dock = System.Windows.Forms.DockStyle.Fill; + UpdateDelayLabel.Location = new System.Drawing.Point(38, 208); + UpdateDelayLabel.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); + UpdateDelayLabel.Name = "UpdateDelayLabel"; + UpdateDelayLabel.Size = new System.Drawing.Size(350, 24); + UpdateDelayLabel.TabIndex = 47; + UpdateDelayLabel.Text = "Update delay"; + // + // UpdateDelayNumericUpDown + // + UpdateDelayNumericUpDown.Dock = System.Windows.Forms.DockStyle.Top; + UpdateDelayNumericUpDown.Location = new System.Drawing.Point(388, 208); + UpdateDelayNumericUpDown.Margin = new System.Windows.Forms.Padding(0, 5, 0, 0); + UpdateDelayNumericUpDown.Maximum = new decimal(new int[] { int.MaxValue, 0, 0, 0 }); + UpdateDelayNumericUpDown.Name = "UpdateDelayNumericUpDown"; + UpdateDelayNumericUpDown.Size = new System.Drawing.Size(350, 23); + UpdateDelayNumericUpDown.TabIndex = 8; + UpdateDelayNumericUpDown.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // // MainForm // AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); @@ -1169,11 +1227,13 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)BongaCamsConcurrentUpdatesNumericUpDown).EndInit(); ((System.ComponentModel.ISupportInitialize)UpdateIntervalNumericUpDown).EndInit(); ((System.ComponentModel.ISupportInitialize)StripchatConcurrentUpdatesNumericUpDown).EndInit(); + ((System.ComponentModel.ISupportInitialize)Flirt4FreeConcurrentUpdatesNumericUpDown).EndInit(); LogTabPage.ResumeLayout(false); LogContextMenuStrip.ResumeLayout(false); AboutTabPage.ResumeLayout(false); AboutTabPage.PerformLayout(); ((System.ComponentModel.ISupportInitialize)SettingsBindingSource).EndInit(); + ((System.ComponentModel.ISupportInitialize)UpdateDelayNumericUpDown).EndInit(); ResumeLayout(false); } @@ -1259,6 +1319,10 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem SetActionToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem SetResolutionToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem CopyUrlToolStripMenuItem; + private System.Windows.Forms.Label Flirt4FreeConcurrentUpdatesLabel; + private System.Windows.Forms.NumericUpDown Flirt4FreeConcurrentUpdatesNumericUpDown; + private System.Windows.Forms.Label UpdateDelayLabel; + private System.Windows.Forms.NumericUpDown UpdateDelayNumericUpDown; } } diff --git a/ChatRoomRecorder/MainForm.cs b/ChatRoomRecorder/MainForm.cs index a6800c6..f1c7411 100644 --- a/ChatRoomRecorder/MainForm.cs +++ b/ChatRoomRecorder/MainForm.cs @@ -60,6 +60,8 @@ public MainForm() ChaturbateConcurrentUpdatesNumericUpDown.DataBindings.Add("Value", SettingsBindingSource, c_chaturbateConcurrentUpdatesSettingName); BongaCamsConcurrentUpdatesNumericUpDown.DataBindings.Add("Value", SettingsBindingSource, c_bongaCamsConcurrentUpdatesSettingName); StripchatConcurrentUpdatesNumericUpDown.DataBindings.Add("Value", SettingsBindingSource, c_stripchatConcurrentUpdatesSettingName); + Flirt4FreeConcurrentUpdatesNumericUpDown.DataBindings.Add("Value", SettingsBindingSource, c_flirt4FreeConcurrentUpdatesSettingName); + UpdateDelayNumericUpDown.DataBindings.Add("Value", SettingsBindingSource, c_updateDelaySettingName); UpdateIntervalNumericUpDown.DataBindings.Add("Value", SettingsBindingSource, c_updateIntervalSettingName); DefaultActionComboBox.DataBindings.Add("SelectedItem", SettingsBindingSource, c_defaultActionSettingName); DefaultResolutionComboBox.DataBindings.Add("SelectedItem", SettingsBindingSource, c_defaultResolutionSettingName); @@ -178,7 +180,8 @@ private void UpdateChatRooms() { { ChatRoomWebsite.Chaturbate, _settings.ChaturbateConcurrentUpdates }, { ChatRoomWebsite.BongaCams, _settings.BongaCamsConcurrentUpdates }, - { ChatRoomWebsite.Stripchat, _settings.StripchatConcurrentUpdates } + { ChatRoomWebsite.Stripchat, _settings.StripchatConcurrentUpdates }, + { ChatRoomWebsite.Flirt4Free, _settings.Flirt4FreeConcurrentUpdates } }; Dictionary curUpdateCounts = new(); @@ -248,11 +251,15 @@ private void UpdateLog(ChatRoom chatRoom) { lock (_lock) { + LogListBox.BeginUpdate(); + Tuple entry = null; while (chatRoom.Log.TryDequeue(out entry)) { - LogListBox.Items.Add(string.Format("{0:yyyy/MM/dd HH:mm:ss} - {1} - {2} - {3}", entry.Item1, chatRoom.Website, chatRoom.Name, entry.Item2).ToLower()); + LogListBox.Items.Add(string.Format("{0:yyyy/MM/dd HH:mm:ss:ffffff} - {1} - {2} - {3}", entry.Item1, chatRoom.Website, chatRoom.Name, entry.Item2).ToLower()); } + + LogListBox.EndUpdate(); } } @@ -1061,6 +1068,30 @@ private void SaveSettings(string propertyName) //do nothing break; + case c_flirt4FreeConcurrentUpdatesSettingName: + //do nothing + break; + + case c_updateDelaySettingName: + if (_root != null) + { + Stack cs = new Stack(); + cs.Push(_root); + while (cs.Count > 0) + { + Category parent = cs.Pop(); + foreach (Category category in parent.Categories) + { + cs.Push(category); + } + foreach (ChatRoom chatRoom in parent.ChatRooms) + { + chatRoom.Delay = _settings.UpdateDelay; + } + } + } + break; + case c_updateIntervalSettingName: ChatRoomsUpdateTimer.Interval = _settings.UpdateInterval * 1000; break; @@ -1139,43 +1170,49 @@ private void CategoriesTreeView_QueryContinueDrag(object sender, QueryContinueDr private void CategoriesTreeView_DragOver(object sender, DragEventArgs e) { - if (e.Data.GetDataPresent(typeof(DataGridViewSelectedRowCollection))) - { - e.Effect = DragDropEffects.Move; - } - else if (e.Data.GetDataPresent(typeof(TreeNode))) - { - bool found = false; - - TreeNode curNode = CategoriesTreeView.SelectedNode; - TreeNode dstNode = CategoriesTreeView.GetNodeAt(CategoriesTreeView.PointToClient(new Point(e.X, e.Y))); + TreeNode dstNode = CategoriesTreeView.GetNodeAt(CategoriesTreeView.PointToClient(new Point(e.X, e.Y))); - Stack ns = new Stack(); - ns.Push(curNode); - while (ns.Count > 0 && !found) + if (dstNode != null) + { + if (e.Data.GetDataPresent(typeof(DataGridViewSelectedRowCollection))) + { + e.Effect = DragDropEffects.Move; + } + else if (e.Data.GetDataPresent(typeof(TreeNode))) { - TreeNodeCollection nodes = ns.Pop().Nodes; - if (!nodes.Contains(dstNode)) + bool cancel = false; + + Stack ns = new Stack(); + ns.Push(CategoriesTreeView.SelectedNode); + while (ns.Count > 0 && !cancel) { - foreach (TreeNode node in nodes) + TreeNodeCollection nodes = ns.Pop().Nodes; + if (!nodes.Contains(dstNode)) { - ns.Push(node); + foreach (TreeNode node in nodes) + { + ns.Push(node); + } + } + else + { + cancel = true; } + }; + + if (!cancel) + { + e.Effect = DragDropEffects.Move; } else { - found = true; + e.Effect = DragDropEffects.None; } } - - if (!found) - { - e.Effect = DragDropEffects.Move; - } - else - { - e.Effect = DragDropEffects.None; - } + } + else + { + e.Effect = DragDropEffects.None; } } @@ -1354,6 +1391,17 @@ private void ReadData() "pragma user_version = 3;"; _command.ExecuteNonQuery(); break; + case 3: + _command.CommandText = + string.Format("alter table {0} add {1} integer;", + c_settingsTableName, + c_settingsTableFlirt4FreeConcurrentUpdatesColumnName) + + string.Format("alter table {0} add {1} integer;", + c_settingsTableName, + c_settingsTableUpdateDelayColumnName) + + "pragma user_version = 4;"; + _command.ExecuteNonQuery(); + break; default: schemaIsUpdated = true; break; @@ -1380,6 +1428,8 @@ private void ReadData() _settings.ChaturbateConcurrentUpdates = reader.GetInt32(c_settingsTableChaturbateConcurrentUpdatesColumnName); _settings.BongaCamsConcurrentUpdates = reader.GetInt32(c_settingsTableBongaCamsConcurrentUpdatesColumnName); _settings.StripchatConcurrentUpdates = reader.GetInt32(c_settingsTableStripchatConcurrentUpdatesColumnName); + _settings.Flirt4FreeConcurrentUpdates = reader.GetInt32(c_settingsTableFlirt4FreeConcurrentUpdatesColumnName); + _settings.UpdateDelay = reader.GetInt32(c_settingsTableUpdateDelayColumnName); _settings.UpdateInterval = reader.GetInt32(c_settingsTableUpdateIntervalColumnName); _settings.DefaultAction = (ChatRoomAction)reader.GetInt32(c_settingsTableDefaultActionColumnName); _settings.DefaultResolution = ChatRoomResolution.Parse(reader.GetInt32(c_settingsTableDefaultResolutionColumnName)); @@ -1438,6 +1488,7 @@ private void ReadData() chatRoom.ID = id; chatRoom.Action = action; chatRoom.PreferredResolution = resolution; + chatRoom.Delay = _settings.UpdateDelay; chatRoom.LastUpdated = updated; chatRoom.LastSeen = seen; chatRoom.UpdateCompleted += ChatRoom_UpdateCompleted; @@ -1482,7 +1533,7 @@ private void WriteData(string table, int operation, ChatRoom chatRoom, Category { case c_settingsTableName: - _command.CommandText = string.Format("delete from {0}; insert into {0} ({1},{3},{5},{7},{9},{11},{13},{15},{17}) values ('{2}','{4}','{6}','{8}','{10}','{12}','{14}','{16}','{18}');", + _command.CommandText = string.Format("delete from {0}; insert into {0} ({1},{3},{5},{7},{9},{11},{13},{15},{17},{19},{21}) values ('{2}','{4}','{6}','{8}','{10}','{12}','{14}','{16}','{18}','{20}','{22}');", c_settingsTableName, c_settingsTableOutputDirectoryColumnName, _settings.OutputDirectory, c_settingsTableFFmpegPathColumnName, _settings.FFmpegPath, @@ -1490,6 +1541,8 @@ private void WriteData(string table, int operation, ChatRoom chatRoom, Category c_settingsTableChaturbateConcurrentUpdatesColumnName, _settings.ChaturbateConcurrentUpdates, c_settingsTableBongaCamsConcurrentUpdatesColumnName, _settings.BongaCamsConcurrentUpdates, c_settingsTableStripchatConcurrentUpdatesColumnName, _settings.StripchatConcurrentUpdates, + c_settingsTableFlirt4FreeConcurrentUpdatesColumnName, _settings.Flirt4FreeConcurrentUpdates, + c_settingsTableUpdateDelayColumnName, _settings.UpdateDelay, c_settingsTableUpdateIntervalColumnName, _settings.UpdateInterval, c_settingsTableDefaultActionColumnName, (int)_settings.DefaultAction, c_settingsTableDefaultResolutionColumnName, _settings.DefaultResolution.ToInt32()); @@ -1617,7 +1670,9 @@ private void WriteData(string table, int operation, ChatRoom chatRoom, Category ChaturbateConcurrentUpdates = 1, BongaCamsConcurrentUpdates = 1, StripchatConcurrentUpdates = 1, - UpdateInterval = 5, + Flirt4FreeConcurrentUpdates = 1, + UpdateDelay = 15, + UpdateInterval = 60, DefaultAction = ChatRoomAction.None, DefaultResolution = ChatRoomResolution.CommonResolutions[ChatRoomResolution.FindClosest(new ChatRoomResolution(1920, 1080), ChatRoomResolution.CommonResolutions)] }; @@ -1635,6 +1690,8 @@ private void WriteData(string table, int operation, ChatRoom chatRoom, Category private const string c_settingsTableChaturbateConcurrentUpdatesColumnName = "ChaturbateConcurrentUpdates"; private const string c_settingsTableBongaCamsConcurrentUpdatesColumnName = "BongaCamsConcurrentUpdates"; private const string c_settingsTableStripchatConcurrentUpdatesColumnName = "StripchatConcurrentUpdates"; + private const string c_settingsTableFlirt4FreeConcurrentUpdatesColumnName = "Flirt4FreeConcurrentUpdates"; + private const string c_settingsTableUpdateDelayColumnName = "UpdateDelay"; private const string c_settingsTableUpdateIntervalColumnName = "UpdateInterval"; private const string c_settingsTableDefaultActionColumnName = "DefaultAction"; private const string c_settingsTableDefaultResolutionColumnName = "DefaultResolution"; @@ -1659,6 +1716,8 @@ private void WriteData(string table, int operation, ChatRoom chatRoom, Category private const string c_chaturbateConcurrentUpdatesSettingName = "ChaturbateConcurrentUpdates"; private const string c_bongaCamsConcurrentUpdatesSettingName = "BongaCamsConcurrentUpdates"; private const string c_stripchatConcurrentUpdatesSettingName = "StripchatConcurrentUpdates"; + private const string c_flirt4FreeConcurrentUpdatesSettingName = "Flirt4FreeConcurrentUpdates"; + private const string c_updateDelaySettingName = "UpdateDelay"; private const string c_updateIntervalSettingName = "UpdateInterval"; private const string c_defaultActionSettingName = "DefaultAction"; private const string c_defaultResolutionSettingName = "DefaultResolution"; @@ -1679,4 +1738,4 @@ private void WriteData(string table, int operation, ChatRoom chatRoom, Category #endregion } -} +} \ No newline at end of file diff --git a/ChatRoomRecorder/MainForm.resx b/ChatRoomRecorder/MainForm.resx index b56eac3..3b2a684 100644 --- a/ChatRoomRecorder/MainForm.resx +++ b/ChatRoomRecorder/MainForm.resx @@ -130,44 +130,44 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAEZTeXN0ZW0uV2luZG93cy5Gb3JtcywgQ3VsdHVyZT1uZXV0cmFs LCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAmU3lzdGVtLldpbmRvd3MuRm9ybXMu - SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAqAgAAAJNU0Z0AUkBTAIBAQIB - AAGIAQMBiAEDARgBAAEYAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABYAMAARgDAAEBAQABIAYAAST/ + SW1hZ2VMaXN0U3RyZWFtZXIBAAAABERhdGEHAgIAAAAJAwAAAA8DAAAAnAgAAAJNU0Z0AUkBTAIBAQIB + AAG4AQMBuAEDARgBAAEYAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABYAMAARgDAAEBAQABIAYAAST/ AP8A/wD/AJoAAyQBNAM5AV0DOQFdAzkBXQM5AV0DOQFdAzkBXQM5AV0DOQFdAzkBXQM5AV0DOQFdAzkB XQM5AV0DOQFdAzkBXQM5AV0DOQFdAzkBXQM5AV0DOQFdAycBOQQAAxIBGANMAY4DUQGfA1EBngNRAZ4D UQGeA1EBngNRAZ4DUQGeA1EBngNRAZ4DUQGeA1EBngNRAZ4DUQGeA1EBngNRAZ4DUQGeA1EBngM2AVjQ AANEAXcDTQH6AXgBdwF/Af8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8C eQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8CeQGBAf8B - egF5AYEB/wJ4AX8B/wFYAVcBYAH+A0QBegNSAaABPAE7AUIB/wGzAbEBtAH/AbUBswG2Af8BsgGzAbYB + egF5AYEB/wJ4AX8B/wFeAV0BZgH+A0QBegNSAaABPAE7AUIB/wGzAbEBtAH/AbUBswG2Af8BsgGzAbYB /wGyAbMBtgH/AbIBswG2Af8BsgGzAbYB/wGyAbMBtgH/AbIBswG2Af8BsgGzAbYB/wGyAbMBtgH/AbIB - swG2Af8BsgGzAbYB/wGyAbMBtgH/AbIBswG2Af8BsgGzAbYB/wG1AbMBtgH/AasBqgGsAf8CVwFYAfUD - FAEbzAADWQHvAucB6FH/A/AB/wNaAekDXgHtAisBLwH8A7cB/ED/AnwBfwH/A0QBeswAA14B8AO+Af1Q - /wO+Af0DYgHuA2EB6wFRAU8BVQH4A3wB+ED/AtwB3QH/A18B2gMIAQrIAANiAe4DvgH9UP8DvgH9A10B - 7ANgAegDbgH1AmABYwH2A9IB/jz/A9IB/gFgAV8BYwH/AzgBW8gAA2IB7gO+Af1Q/wO+Af0DXQHsA2AB - 6AOVAfoBTQFMAVIB9gOEAfhA/wHEAcMBxgH/A1kBwcgAA2IB7gO+Af1Q/wO+Af0DXQHsA2AB6AO+Af0D - fAH4A24B9UD/A9EB/gFdAVwBXgH7AycBOcQAA2IB7gO+Af1Q/wO+Af0DXQHsA2AB6AO+Af0BsQGwAbEB - /ANaAfUDnAH7QP8BpAGiAaUB/wNSAaHEAANiAe4DvgH9UP8DvgH9A10B7ANgAegDqgH8BP8DYwH2AXUB - cwF1AfdA/wPIAf4DYgHuAxgBIcAAA2IB7gO+Af1Q/wO+Af0DXQHsA2AB6AOqAfwE/wOHAfoDWgH1A74B - /UD/AYsBigGOAf8DSQGHwAADYgHuA74B/VD/A74B/QNdAewDYAHoA6oB/AT/A74B/QFQAU8BUwH2A3wB - +AOcAfsDnAH7A5wB+wOcAfsDnAH7A5wB+wOcAfsDnAH7A5wB+wOcAfsDnAH7A5wB+wOcAfsDnQH7Au4B - 7wH/A+4B/wHLAcoBzQH/A10B6sAAA2IB7gO+Af1Q/wO+Af0DXQHsA2AB6AOqAfwI/wKIAYkB+QNaAfUD - UwH0A1oB9QNaAfUDWgH1A1oB9QFTAVIBYAH2A2AB9gNgAfYDYAH2A2AB9gNgAfYDYAH2A2AB9gNAAf0D - YAHjA1sB3gNdAd8DUAGbwAADYgHuA74B/Sz/A9IB/gOcAfsClgGXAfsCpAGmAfwCpAGmAfwCpAGmAfwC - pAGmAfwClwGYAfsClgGXAfsBdwF1AYAB+wNaAfIDYAHoA6oB/Az/A7QB/AOdAfsDsgH8AbMBsgG0AfwB - swKyAfwDogH7A5oB+gO5Af8CuAG6Af8BugG4AboB/wG6AbgBugH/AboBuAG6Af8CuQG7Af8CfAF/Af8D - XAHLAw8BFAMKAQ0DCQEMxAADYgHuA74B/Sz/AnkBewH5A1MB9AFNAUwBVAH2AU4BTQFgAfYBTgFNAWAB - 9gFOAU0BYAH2AU4BTQFgAfYBTgFNAWAB9gFMAUsBUgH2A2wB9wNaAfIDYAHoA6oB/CD/AskBzAH/A14B - 8ANYAbgBVwFVAVcBtAFXAVUBVwG0AVcBVQFXAbQCVgFXAbUCVgFXAbUDTwGXAxcBH9AAA14B8AO+Af0k - /wPSAf4CewF9AfkDWgH1A5EB+QO+Af0DvgH9A74B/QO+Af0DvgH9A74B/QO+Af0DzAH+A1sB5ANdAeoD - rAH8HP8CywHNAf8DWQHvAysBQfAAA1kB7wPrIf8D0gH+ApsBoAH/AgABAwH/AWABXgFoAf8BfgF9AYQB - /wF5AXgBfwH/AXkBeAF/Af8BeQF4AX8B/wF5AXgBfwH/AXkBeAF/Af8BegF4AYAB/wF3AXYBfQH/A1EB - 9wM+AWsDXgHiAcwBywHOFf8D0gH+As4B0AH/A1oB8gMtAUT0AANHAYABXAFbAWQB/gKGAYwB/wGKAYkB - jwH/AYkBiAGPAf8BiQGIAY8B/wGJAYgBjwH/AYkBiAGPAf8BiQGIAY8B/wGJAYgBjwH/AmUBawH/A1kB - vgMxAU4DMQFMAzEBTAMxAUwDMQFMAzEBTAMxAUwDMQFMAzEBTAMxAUwDIAEtBAADPAFmA1EB9wJzAXcB - /wF5AXgBfAH/AngBewH/AngBewH/AnkBfAH/Am0BcAH/A1kB7wMuAUf8AAMpAT4DOgFgAzoBYAM6AWAD - OgFgAzoBYAM6AWADOgFgAzoBYQM1AVUDCAEKNAADIQEwAzkBXwM6AWADOgFgAzoBYAM6AWADOAFcAxoB - JP8A/wD/AP8A/wCBAAFCAU0BPgcAAT4DAAEoAwABYAMAARgDAAEBAQABAQUAASABARYAA/8BAAb/BgAG - /wYABv8GAAGAAQABAQIAAQ8LAAEHCwABBwsAAQMLAAEDCwABAwsAAQELAAEBOwABAQsAAQ8KAAEPAf8K - AAEfAf8IAAEBAQABPwH/BgABgAEPAf8BgAF/Af8GAAb/BgAG/wYABv8GAAs= + swG2Af8BsgGzAbYB/wGyAbMBtgH/AbIBswG2Af8BsgGzAbYB/wG1AbMBtgH/AasBqgGsAf8DWgH1AxQB + G8wAA1kB7wLnAehR/wPwAf8DWgHpA14B7QMrAfwDqwH8QP8CfAF/Af8DRAF6zAADXgHwA74B/VD/A74B + /QNiAe4DYQHrAVsBWgFcAfgDfAH4QP8C3AHdAf8DXwHaAwgBCsgAA2IB7gO+Af1Q/wO+Af0DXQHsA2AB + 6ANuAfUCYAFjAfYDxgH+PP8DxgH+AWABXwFjAf8DOAFbyAADYgHuA74B/VD/A74B/QNdAewDYAHoA4MB + +gFNAUwBUgH2A3wB+ED/AcQBwwHGAf8DWQHByAADYgHuA74B/VD/A74B/QNdAewDYAHoA74B/QN8AfgD + bgH1QP8DxQH+A14B+wMnATnEAANiAe4DvgH9UP8DvgH9A10B7ANgAegDvgH9AaMBoQGjAfwDWgH1A5YB + +0D/AaQBogGlAf8DUgGhxAADYgHuA74B/VD/A74B/QNdAewDYAHoA5gB/AT/A2MB9gNvAfdA/wO8Af4D + YgHuAxgBIcAAA2IB7gO+Af1Q/wO+Af0DXQHsA2AB6AOYAfwE/wN9AfoDWgH1A74B/UD/AYsBigGOAf8D + SQGHwAADYgHuA74B/VD/A74B/QNdAewDYAHoA5gB/AT/A74B/QFQAU8BUwH2A3wB+AOWAfsDlgH7A5YB + +wOWAfsDlgH7A5YB+wOWAfsDlgH7A5YB+wOWAfsDlgH7A5YB+wOWAfsDlwH7Au4B7wH/A+4B/wHLAcoB + zQH/A10B6sAAA2IB7gO+Af1Q/wO+Af0DXQHsA2AB6AOYAfwI/wKCAYMB+QNaAfUDUwH0A1oB9QNaAfUD + WgH1A1oB9QFTAVIBYAH2A2AB9gNgAfYDYAH2A2AB9gNgAfYDYAH2A2AB9gNAAf0DYAHjA1sB3gNdAd8D + UAGbwAADYgHuA74B/Sz/A8YB/gOWAfsCkAGRAfsCkgGUAfwCkgGUAfwCkgGUAfwCkgGUAfwCkQGSAfsC + kAGRAfsBawFpAXUB+wNaAfIDYAHoA5gB/Az/A6cB/AOXAfsDpAH8AaYBpAGnAfwBpgKkAfwDmQH7A4kB + +gO5Af8CuAG6Af8BugG4AboB/wG6AbgBugH/AboBuAG6Af8CuQG7Af8CfAF/Af8DXAHLAw8BFAMKAQ0D + CQEMxAADYgHuA74B/Sz/Am0BbwH5A1MB9AFNAUwBVAH2AU4BTQFgAfYBTgFNAWAB9gFOAU0BYAH2AU4B + TQFgAfYBTgFNAWAB9gFMAUsBUgH2A2wB9wNaAfIDYAHoA5gB/CD/AskBzAH/A14B8ANYAbgBVwFVAVcB + tAFXAVUBVwG0AVcBVQFXAbQCVgFXAbUCVgFXAbUDTwGXAxcBH9AAA14B8AO+Af0k/wPGAf4CbwFxAfkD + WgH1A4sB+QO+Af0DvgH9A74B/QO+Af0DvgH9A74B/QO+Af0DwAH+A1sB5ANdAeoDmwH8HP8CywHNAf8D + WQHvAysBQfAAA1kB7wPrIf8DxgH+ApsBoAH/AgABAwH/AWABXgFoAf8BfgF9AYQB/wF5AXgBfwH/AXkB + eAF/Af8BeQF4AX8B/wF5AXgBfwH/AXkBeAF/Af8BegF4AYAB/wF3AXYBfQH/A1EB9wM+AWsDXgHiAcwB + ywHOFf8DxgH+As4B0AH/A1oB8gMtAUT0AANHAYABYgFhAWoB/gKGAYwB/wGKAYkBjwH/AYkBiAGPAf8B + iQGIAY8B/wGJAYgBjwH/AYkBiAGPAf8BiQGIAY8B/wGJAYgBjwH/AmUBawH/A1kBvgMxAU4DMQFMAzEB + TAMxAUwDMQFMAzEBTAMxAUwDMQFMAzEBTAMxAUwDIAEtBAADPAFmA1EB9wJzAXcB/wF5AXgBfAH/AngB + ewH/AngBewH/AnkBfAH/Am0BcAH/A1kB7wMuAUf8AAMpAT4DOgFgAzoBYAM6AWADOgFgAzoBYAM6AWAD + OgFgAzoBYQM1AVUDCAEKNAADIQEwAzkBXwM6AWADOgFgAzoBYAM6AWADOAFcAxoBJP8A/wD/AP8A/wCB + AAFCAU0BPgcAAT4DAAEoAwABYAMAARgDAAEBAQABAQUAASABARYAA/8BAAb/BgAG/wYABv8GAAGAAQAB + AQIAAQ8LAAEHCwABBwsAAQMLAAEDCwABAwsAAQELAAEBOwABAQsAAQ8KAAEPAf8KAAEfAf8IAAEBAQAB + PwH/BgABgAEPAf8BgAF/Af8GAAb/BgAG/wYABv8GAAs= diff --git a/ChatRoomRecorder/Settings.cs b/ChatRoomRecorder/Settings.cs index d26f65e..ad499ec 100644 --- a/ChatRoomRecorder/Settings.cs +++ b/ChatRoomRecorder/Settings.cs @@ -14,6 +14,8 @@ public void CopyTo(Settings settings) settings._chaturbateConcurrentUpdates = _chaturbateConcurrentUpdates; settings._bongaCamsConcurrentUpdates = _bongaCamsConcurrentUpdates; settings._stripchatConcurrentUpdates = _stripchatConcurrentUpdates; + settings._flirt4FreeConcurrentUpdates = _flirt4FreeConcurrentUpdates; + settings._updateDelay = _updateDelay; settings._updateInterval = _updateInterval; settings._defaultAction = _defaultAction; settings._defaultResolution = _defaultResolution; @@ -105,6 +107,32 @@ public int StripchatConcurrentUpdates } } + public int Flirt4FreeConcurrentUpdates + { + get + { + return _flirt4FreeConcurrentUpdates; + } + set + { + _flirt4FreeConcurrentUpdates = value >= 1 ? value : 1; + NotifyPropertyChanged(nameof(Flirt4FreeConcurrentUpdates)); + } + } + + public int UpdateDelay + { + get + { + return _updateDelay; + } + set + { + _updateDelay = value >= 0 ? value : 0; + NotifyPropertyChanged(nameof(UpdateDelay)); + } + } + public int UpdateInterval { get @@ -150,8 +178,10 @@ public ChatRoomResolution DefaultResolution private int _chaturbateConcurrentUpdates; private int _bongaCamsConcurrentUpdates; private int _stripchatConcurrentUpdates; + private int _flirt4FreeConcurrentUpdates; + private int _updateDelay; private int _updateInterval; private ChatRoomAction _defaultAction; private ChatRoomResolution _defaultResolution; } -} +} \ No newline at end of file