Skip to content

Commit

Permalink
Merge pull request #6 from ArTDsL/dev-arth
Browse files Browse the repository at this point in the history
New stuff
  • Loading branch information
ArTDsL committed May 25, 2023
2 parents f712957 + af3d91d commit 82acb58
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 24 deletions.
110 changes: 86 additions & 24 deletions BitABit/chat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
* @file: chat.cs
* @created: 2023-05-14
* @updated: 2023-05-19
* @updated: 2023-05-24
* @autor: Arthur 'ArTDsL'/'ArThDsL' Dias dos Santos Lasso
* @copyright: Copyright (c) 2023. Arthur 'ArTDsL'/'ArThDsL' Dias dos Santos Lasso. All Rights Reserved. Distributed under MIT license.
*
Expand All @@ -24,6 +24,8 @@
using System.Threading.Tasks;
using System.Net.Sockets;
using BitABit.utils;
using System.Reflection;
using System.Reflection.Emit;
using System.Reflection.PortableExecutable;
using System.Threading.Channels;
using System.Diagnostics;
Expand All @@ -32,8 +34,13 @@
using System.Xml;
using System.Drawing;
using System.Runtime.CompilerServices;
#pragma warning disable CS8600, CS8601, CS8602, CS8603, CS0219 // YOU WILL NOT SURVIVE LITTLE WARNING RATS !!!!!
using System.Security.Cryptography.X509Certificates;
#pragma warning disable CS8600, CS8601, CS8602, CS8603, CS0219, CS8604 // YOU WILL NOT SURVIVE LITTLE WARNING RATS !!!!!
namespace BitABit {
/// <summary>
/// Delegate to deal with received chat messages (user).
/// </summary>
public delegate void OnChatMessageReceived();
/// <summary>
/// Chat Class.
/// </summary>
Expand Down Expand Up @@ -68,6 +75,12 @@ public class chat {
private static CancellationTokenSource? TwitchIRCLoopCTS;
/// <summary>Parsed Message List</summary>
public static List<MESSAGE_PARSED>? message_parsed;
/// <summary> Last Message Cache</summary>
public static List<MESSAGE_PARSED>? _last_msgCache { get; set; }
/// <summary>Event Receive Chat Message</summary>
public event OnChatMessageReceived OnChatMessageReceived = new OnChatMessageReceived(fnull);
//Event Variables (loop)
private static bool NOTIFY_MsgRecv = false;
/// <returns>Set to <c>false</c> to stop the loop (not recommended if you don't wan't to close the connection).</returns>
private static bool IRCLoop;
private static readonly string[] IRCCMDS = new string[] { "JOIN", "NICK", "NOTICE", "PART", "PASS", "PING", "PONG", "PRIVMSG", "CLEARCHAT", "CLEARMSG", "GLOBALUSERSTATE", "HOSTTARGET", "NOTICE", "RECONNECT", "ROOMSTATE", "USERNOTICE", "USERSTATE", "WHISPER", "CAP" };
Expand All @@ -87,7 +100,7 @@ public async Task StartChat(string nick, string access_token, string channel, bo
_nick = nick;
_channel = channel;
_access_token = access_token;
if(IsRetrying == false) {
if(IsRetrying == false) {
_userful.SendConsoleLog("Twitch Chat", "StartChat()", "Connecting to " + server + ":" + port, DebugMessageType.INFO);
}
TwitchIRCCli = new TcpClient();
Expand All @@ -105,6 +118,7 @@ public async Task StartChat(string nick, string access_token, string channel, bo
}
}
}
Callback_Exec();
TwitchIRCStream = TwitchIRCCli.GetStream();
TwitchIRCStreamWriter = new StreamWriter(TwitchIRCStream) { NewLine = "\r\n", AutoFlush = true };
TwitchIRCStreamReader = new StreamReader(TwitchIRCStream);
Expand Down Expand Up @@ -143,7 +157,7 @@ public async Task<bool> CloseChat() {
/// </summary>
/// <returns></returns>
private void CloseConnection() {
try {
try {
TwitchIRCStreamReader.Close();
TwitchIRCStreamWriter.Close();
TwitchIRCStream.Close();
Expand Down Expand Up @@ -307,7 +321,7 @@ private async Task ParseInput(string[] data) {
biCount += 1;
}
string badge_check = splitted_tags[i].Replace("badge-info=", String.Empty).Replace("badges=", String.Empty);
if(badge_check != null || badge_check != "" || badge_check != " ") {
if(badge_check != null || badge_check != "" || badge_check != " ") {
string[] _badges = badge_check.Split("/");
bool can_go = true;
foreach(string b in _badges) {
Expand All @@ -327,7 +341,7 @@ private async Task ParseInput(string[] data) {
}
}
}
}else
} else
//parsing emotes
if(splitted_tags[i].Contains("emotes=")) {
if(splitted_tags[i].Contains("/")) {
Expand Down Expand Up @@ -377,7 +391,7 @@ private async Task ParseInput(string[] data) {
}
} else {
//unique emote parsing
if(splitted_tags[i].Replace("emotes=", "").Contains(":")) {
if(splitted_tags[i].Replace("emotes=", "").Contains(":")) {
string[] _emote = splitted_tags[i].Replace("emotes=", "").Split(":");
//check if emote has multipos (repeat)
string emote_splitted_name = _emote[0];
Expand All @@ -386,7 +400,7 @@ private async Task ParseInput(string[] data) {
string[] _emote_splitted_pos = _emote[1].Split(",");
bool can_go = true;
foreach(string e_p in _emote_splitted_pos) {

if(e_p == null || e_p == "" || e_p == " " || e_p == String.Empty) {
isEmotesNull = true;
can_go = false;
Expand Down Expand Up @@ -420,9 +434,9 @@ private async Task ParseInput(string[] data) {
}
}
}
}else
} else
//parsing emote sets
if(splitted_tags[i].Contains("emote-sets=")) {
if(splitted_tags[i].Contains("emote-sets=")) {
if(splitted_tags[i].Contains(",")) {
//more than 1
string[] _emote_sets = splitted_tags[i].Replace("emote-sets=", "").Split(",");
Expand All @@ -432,7 +446,7 @@ private async Task ParseInput(string[] data) {
}
}
if(_emote_sets != null) {
for(int l = 0; l <_emote_sets.Count(); l++) {
for(int l = 0; l < _emote_sets.Count(); l++) {
EMOTE_SET[l] = _emote_sets[l];
}
isEmoteSetNull = false;
Expand Down Expand Up @@ -524,11 +538,11 @@ private async Task ParseInput(string[] data) {
}
//
//--------------- ↓↓ Test Only [ will be removed ] ↓↓ ---------------
if(_debug == true) {
if(_debug == true) {
if(isBadgesNull == false) {
for(int i = 0; i < BADGES.Count(); i++) {
if(BADGES[i] != null) {
Console.WriteLine(": ID [" + BADGES[i][0] + "] | L [" + BADGES[i][1] + "]");
if(BADGES[i] != null) {
Console.WriteLine(": ID [" + BADGES[i][0] + "] | L [" + BADGES[i][1] + "]");
}
}
}
Expand Down Expand Up @@ -625,7 +639,13 @@ private async Task ParseInput(string[] data) {
//<to-user> is one parameter before command but he is also the HOST
break;
}
case "001": case "002": case "003": case "004": case "375": case "372": case "376": {
case "001":
case "002":
case "003":
case "004":
case "375":
case "372":
case "376": {
if(login_count >= 6) {
//login successful
_userful.SendConsoleLog("Twitch Chat", "StartChat()", "Login successful", DebugMessageType.SUCCESS);
Expand All @@ -647,17 +667,17 @@ private async Task ParseInput(string[] data) {
_userful.SendConsoleLog("Twitch Chat", "OnTwitchIRCMessageReceived()", "User joined in channel #" + _channel, DebugMessageType.SUCCESS);
break;
}
}
}
//test message param
if(_debug == true && _param != null) {
_userful.SendConsoleLog("Twitch Chat", "OnTwitchIRCMessageReceived()", "PARAMETER: " + _param, DebugMessageType.INFO);
}
//list the LAST MESSAGE
message_parsed = new List<MESSAGE_PARSED>();
message_parsed.Add(new MESSAGE_PARSED() {
message_parsed.Add(new MESSAGE_PARSED() {
badges = BADGES,
color = _color,
display_name= _display_name,
display_name = _display_name,
emote_only = _emote_only,
emotes = EMOTES,
id = _id,
Expand All @@ -672,30 +692,43 @@ private async Task ParseInput(string[] data) {
command = COMMAND,
parameters = _param
});
I_OnChatMessageReceived();
}
/// <summary>
/// Null returning method to avoid null exception on event creation.
/// </summary>
private static void fnull(){
return;
}
/// <summary>
/// Get the last messsage received in chat
/// </summary>
/// <returns>Last message received in chat in List format <see cref="List{MESSAGE_PARSED}"/></returns>
public List<MESSAGE_PARSED> GetLastMessage() {
return message_parsed;
if(message_parsed.Count() >= 1) {
return chat.message_parsed;
}
List<MESSAGE_PARSED> n = new List<MESSAGE_PARSED>();
n = null;
return n;
}
/// <summary>
/// Handle IRC received messages.
/// Handle IRC received message (ALL);
/// </summary>
/// <returns>Returns a list of with the parsed message.</returns>
static async void OnTwitchIRCMessageReceived(object? obj) {
private static void OnTwitchIRCMessageReceived(object? obj) {
if(obj != null) {
TwitchIRCLoopCT = (CancellationToken)obj;
}
await Task.Run(async () => {
Thread T = new Thread(async () => {
//await Task.Run(async () => {
userful usf = new userful();
chat Chat = new chat();
while(chat.IRCLoop == true) {
if(IRCLoop == false) {
break;
}
try {
try {
string? line = await chat.TwitchIRCStreamReader.ReadLineAsync();
if(line == null || line == " " || line == "") {
line = "NULL_PARSE";
Expand All @@ -707,7 +740,7 @@ await Task.Run(async () => {
string[]? splited_line = line.Split(" ");
await Chat.ParseInput(splited_line);
}
}catch(Exception e) {
} catch(Exception e) {
Chat.CloseConnection();
if(_debug == true) {
usf.SendConsoleLog("Twitch Chat", "OnTwitchIRCMessageReceived()", "Fail to connect " + e.Message + " [ Retrying to connect, attempt {=Yellow}" + retry + "{/} from {=Green}5{/} ]", DebugMessageType.INFO);
Expand All @@ -723,6 +756,35 @@ await Task.Run(async () => {
}
}
});
T.Start();
}
//Handle Callbacks
private void Callback_Exec() {
Thread T = new Thread(() => {
while(true) {
if(chat.NOTIFY_MsgRecv == true) {
OnChatMessageReceived.Invoke();
chat.NOTIFY_MsgRecv = false;
}
Thread.Yield(); //avoid deadlocks
}
});
T.Start();
}
//----------------- EVENT HANDLER FUNCTIONS -----------------------
/// <summary> Handles Received messages (Chat user messages).</summary>
private void I_OnChatMessageReceived() {
Task task = Task.Run(() => {
chat Chat = new chat();
List<MESSAGE_PARSED> last_message = Chat.GetLastMessage();
if(last_message != null && chat._last_msgCache != last_message) {
if(last_message.Count() >= 1) {
Console.WriteLine("COLOR: " + last_message[0].color);
chat.NOTIFY_MsgRecv = true;
}
_last_msgCache = last_message;
}
});
}
}
/// <summary>
Expand Down
Loading

0 comments on commit 82acb58

Please sign in to comment.