Refactor IRC API
- Moved parse method to factory constructor in IRCMessage for better readability - Renamed irc_message.dart to irc.dart to include other irc-related models - Added ROOMSTATE model - Moved addMessage functionality to chat store
This commit is contained in:
parent
afbb8d7c09
commit
bb74b7bd6e
3 changed files with 84 additions and 66 deletions
|
|
@ -1,56 +1,7 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:frosty/models/irc_message.dart';
|
||||
import 'package:frosty/models/irc.dart';
|
||||
|
||||
class IRC {
|
||||
/// Parses an IRC string and returns its corresponding [IRCMessage] object.
|
||||
static IRCMessage parse(String whole) {
|
||||
// We have three parts:
|
||||
// 1. The tags of the IRC message
|
||||
// 2. The metadata (user, command, and channel)
|
||||
// 3. The message itself
|
||||
|
||||
// First, slice the message tags (1) and set aside the rest for later.
|
||||
// Each part is separated by a space, so we'll start off by breaking off the tags and parsing them.
|
||||
|
||||
// Obtain the index to break off the tags.
|
||||
final tagAndIrcMessageDivider = whole.indexOf(' ');
|
||||
|
||||
// Get the tags substring and escape characters.
|
||||
// IRC messages escape spaces with \s.
|
||||
final tags = whole.substring(1, tagAndIrcMessageDivider).replaceAll('\\s', ' ');
|
||||
|
||||
// Next, parse and map the tags.
|
||||
final mappedTags = <String, String>{};
|
||||
|
||||
// Loop through each tag and store their key value pairs into the map.
|
||||
for (final tag in tags.split(';')) {
|
||||
// Skip if the tag has no value.
|
||||
if (tag.endsWith('=')) continue;
|
||||
|
||||
final tagSplit = tag.split('=');
|
||||
mappedTags[tagSplit[0]] = tagSplit[1];
|
||||
}
|
||||
|
||||
// Now we'll parse the message itself.
|
||||
// Obtain the entire substring after the tags and excluding the first : (colon)
|
||||
final ircMessage = whole.substring(tagAndIrcMessageDivider + 2);
|
||||
|
||||
// Split each section of the message (part 2 and its subparts and part 3).
|
||||
// Index 0 contains the username of sender (user) or tmi.twitch.tv depending on the command
|
||||
// Index 1 is command type
|
||||
// Index 2 is #channel name that we are currently connected to
|
||||
// Index 3 and beyond is the :message (word by word) that is sent by the user or empty depending on the command
|
||||
final splitMessage = ircMessage.split(' ');
|
||||
|
||||
// If the username exists, set it.
|
||||
final String? user = splitMessage[0] == 'tmi.twitch.tv' ? null : splitMessage[0].substring(0, splitMessage[0].indexOf('!'));
|
||||
|
||||
// If there is a message, set it.
|
||||
final String? message = splitMessage.length > 3 ? splitMessage.sublist(3).join(' ').substring(1) : null;
|
||||
|
||||
return IRCMessage(tags: mappedTags, command: splitMessage[1], user: user, message: message);
|
||||
}
|
||||
|
||||
// Applies the given CLEARCHAT message to a list and returns the result.
|
||||
static void clearChat({required List<IRCMessage> messages, required IRCMessage ircMessage}) {
|
||||
debugPrint('CLEARCHAT');
|
||||
|
|
@ -92,12 +43,4 @@ class IRC {
|
|||
static void userNotice({required List<IRCMessage> messages, required IRCMessage ircMessage}) {
|
||||
debugPrint('USERNOTICE');
|
||||
}
|
||||
|
||||
static void addMessage({required List<IRCMessage> messages, required String userState, required String sentMessage}) {
|
||||
debugPrint('USERSTATE');
|
||||
|
||||
final userChatMessage = parse(userState);
|
||||
userChatMessage.message = sentMessage;
|
||||
messages.add(userChatMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
83
lib/models/irc.dart
Normal file
83
lib/models/irc.dart
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
class IRCMessage {
|
||||
final Map<String, String> tags;
|
||||
final String? user;
|
||||
String command;
|
||||
String? message;
|
||||
|
||||
IRCMessage({required this.tags, required this.command, required this.user, required this.message});
|
||||
|
||||
/// Parses an IRC string and returns its corresponding [IRCMessage] object.
|
||||
factory IRCMessage.fromString(String whole) {
|
||||
// We have three parts:
|
||||
// 1. The tags of the IRC message
|
||||
// 2. The metadata (user, command, and channel)
|
||||
// 3. The message itself
|
||||
|
||||
// First, slice the message tags (1) and set aside the rest for later.
|
||||
// Each part is separated by a space, so we'll start off by breaking off the tags and parsing them.
|
||||
|
||||
// Obtain the index to break off the tags.
|
||||
final tagAndIrcMessageDivider = whole.indexOf(' ');
|
||||
|
||||
// Get the tags substring and escape characters.
|
||||
// IRC messages escape spaces with \s.
|
||||
final tags = whole.substring(1, tagAndIrcMessageDivider).replaceAll('\\s', ' ');
|
||||
|
||||
// Next, parse and map the tags.
|
||||
final mappedTags = <String, String>{};
|
||||
|
||||
// Loop through each tag and store their key value pairs into the map.
|
||||
for (final tag in tags.split(';')) {
|
||||
// Skip if the tag has no value.
|
||||
if (tag.endsWith('=')) continue;
|
||||
|
||||
final tagSplit = tag.split('=');
|
||||
mappedTags[tagSplit[0]] = tagSplit[1];
|
||||
}
|
||||
|
||||
// Now we'll parse the message itself.
|
||||
// Obtain the entire substring after the tags and excluding the first : (colon)
|
||||
final ircMessage = whole.substring(tagAndIrcMessageDivider + 2);
|
||||
|
||||
// Split each section of the message (part 2 and its subparts and part 3).
|
||||
// Index 0 contains the username of sender (user) or tmi.twitch.tv depending on the command
|
||||
// Index 1 is command type
|
||||
// Index 2 is #channel name that we are currently connected to
|
||||
// Index 3 and beyond is the :message (word by word) that is sent by the user or empty depending on the command
|
||||
final splitMessage = ircMessage.split(' ');
|
||||
|
||||
// If the username exists, set it.
|
||||
// tmi.twitch.tv means the message was sent by Twitch rather than a user, so will be irrelevant.
|
||||
final String? user = splitMessage[0] == 'tmi.twitch.tv' ? null : splitMessage[0].substring(0, splitMessage[0].indexOf('!'));
|
||||
|
||||
// If there is an associated message, set it.
|
||||
final String? message = splitMessage.length > 3 ? splitMessage.sublist(3).join(' ').substring(1) : null;
|
||||
|
||||
return IRCMessage(
|
||||
tags: mappedTags,
|
||||
command: splitMessage[1],
|
||||
user: user,
|
||||
message: message,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ROOMSTATE {
|
||||
final bool emoteOnly;
|
||||
final bool followersOnly;
|
||||
final bool r9k;
|
||||
final bool slow;
|
||||
final bool subMode;
|
||||
|
||||
const ROOMSTATE(this.emoteOnly, this.followersOnly, this.r9k, this.slow, this.subMode);
|
||||
|
||||
factory ROOMSTATE.fromMessage(IRCMessage ircMessage) {
|
||||
return ROOMSTATE(
|
||||
(ircMessage.tags['emote-only'] == '0') ? false : true,
|
||||
(ircMessage.tags['followers-only'] == '0') ? false : true,
|
||||
(ircMessage.tags['r9k'] == '0') ? false : true,
|
||||
(ircMessage.tags['slow'] == '0') ? false : true,
|
||||
(ircMessage.tags['subs-only'] == '0') ? false : true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
class IRCMessage {
|
||||
final Map<String, String> tags;
|
||||
String command;
|
||||
final String? user;
|
||||
String? message;
|
||||
|
||||
IRCMessage({required this.tags, required this.command, required this.user, required this.message});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue