I'm trying to parse Twitch IRC emotes and extract it from a string. Twitch IRC message provides a range which is a location of an emote in a string. Example:
string="Kappa abcdef"; range start=0; range end=4
means emote Kappa is located from the index 0 to 4 in the string "Kappa abcdef".
Here's my function that will return an emote based on the range:
func extractEmoteName(from message: String, rangeStart: Int, rangeEnd: Int) -> String? {
guard
let indexStart = message.index(message.startIndex, offsetBy: rangeStart, limitedBy: message.endIndex),
let limitIndex = message.index(message.endIndex, offsetBy: -1, limitedBy: message.startIndex),
let indexEnd = message.index(message.startIndex, offsetBy: rangeEnd, limitedBy: limitIndex)
else {
print("out of bounds")
return nil
}
return String(message[indexStart ... indexEnd])
}
Using this on the example string: extractEmoteName(from: "Kappa abcdef", rangeStart: 0, rangeEnd: 4)
will return Kappa
as a result.
I'm having a trouble with the strings that contain emojis with multiple unicode scalars:
string="⚠️ Kappa"; range start=3; range end=7
Result of the extraction function is nil
:
extractEmoteName(from: "⚠️ Kappa", rangeStart: 3, rangeEnd: 7) // prints "out of bounds"
At the same time, messages with the single scalar emotes parses fine because the range provided by Twitch is different:
string="🙂 Kappa"; range start=2; range end=6
extractEmoteName(from: "🙂 Kappa", rangeStart: 2, rangeEnd: 6) // returns "Kappa"
What should be changed in extractEmoteName
to make it work with all emoji characters?
You need to use unicodeScalars
, it will represent the string in unicode scalars:
func extractEmoteName(from input: String, rangeStart: Int, rangeEnd: Int) -> String? {
let message = input.unicodeScalars
guard
let indexStart = message.index(message.startIndex, offsetBy: rangeStart, limitedBy: message.endIndex),
let limitIndex = message.index(message.endIndex, offsetBy: -1, limitedBy: message.startIndex),
let indexEnd = message.index(message.startIndex, offsetBy: rangeEnd, limitedBy: limitIndex)
else {
print("out of bounds")
return nil
}
return String(message[indexStart ... indexEnd])