Split string and replace Discord emoji to [name]

Viewed 62

I have incoming messages such as <a:GG:123456789> <:1Copy:12345678><:14:1256678>:eyes:Hello friend!:eyes: and I want this output to be [GG] [1Copy][14][eyes]Hello friend![eyes]

The below code is what I currently have and it works kind of. The above incoming example outputs [GG] [1Copy] [14] [eyes]

def shorten_emojis(content):
    seperators = ("<a:", "<:")

    output = []

    for chunk in content.split():
        if any(match in chunk for match in seperators):
            parsed_chunk = []

            new_chunk = chunk.replace("<", ";<").replace(">", ">;")

            for emo in new_chunk.split(";"):
                if emo.startswith(seperators):
                    emo = f"<{splits[1]}>" if len(splits := emo.split(":")) == 3 else emo

                parsed_chunk.append(emo)

            chunk = "".join(parsed_chunk)

        output.append(chunk)

    output = " ".join(output)

    for e in re.findall(":.+?:", content):
        output = output.replace(e, f"<{e.replace(':', '')}>")

    return output

Test #1

Input: <a:GG:123456789> <:1Copy:12345678><:14:1256678>:eyes:Hello friend!:eyes:

Output: [GG] [1Copy] [14] :eyes:Hello friend!:eyes:

Desired [GG] [1Copy][14][eyes]Hello friend![eyes]

Test #2

Input: <a:cryLaptop:738450655395446814><:1Copy:817543814481707030><:14:817543815401439232> <:thoonk:621279654711656448><:coolbutdepressed:621279653675532290><:KL1Heart:585547199480332318>Nice<:dogwonder:621251869058269185> OK:eyes:

Output: [cryLaptop] [1Copy] [14] [thoonk] [coolbutdepressed] [KL1Heart] Nice [dogwonder] OK:eyes:

Desired [cryLaptop] [GG] [1Copy] [14] [thoonk] [coolbutdepressed] [KL1Heart] Nice [dogwonder] OK[eyes]

Edit

I have edited my code block, it now works as desired.

2 Answers

You can do this with regular expressions. It is a library that already includes Python itself.

I have modified the code a bit to make it more compact but I think it is understood the same.

The most important thing is to detect the three groups of words. With (<. *?>) We select the <words>, with (:. *? :) the : word: and with (. *?) The rest of the text.

Then we must format it with the expected values and display them.

import re
def shorten_emojis(content):
    tags = re.findall('((<.*?>)|(:.*?:)||(.*?))', content)
    output=""
    for tag in tags:
        if re.findall("<.*?>", tag[0]):
            valor=re.search(':.*?:', tag[0])
            output+=f"[{valor.group()[1:-1]}]"
        elif re.match(":.*?:", tag[0]):
            output+=f"[{tag[0][1:-1]}]"
        else:
            output+=f"{tag[0]}"

    return output


print(shorten_emojis("<a:GG:123456789> <:1Copy:12345678><:14:1256678>:eyes:Hello friend!:eyes:"))
print(shorten_emojis("<a:cryLaptop:738450655395446814><:1Copy:817543814481707030><:14:817543815401439232> <:thoonk:621279654711656448><:coolbutdepressed:621279653675532290><:KL1Heart:585547199480332318>Nice<:dogwonder:621251869058269185> OK:eyes:"))

RESULT:

[GG] [1Copy][14][eyes]Hello friend![eyes]
[cryLaptop][1Copy][14] [thoonk][coolbutdepressed][KL1Heart]Nice[dogwonder] OK[eyes]

You might use a single pattern with an alternation | to match both variations. Then in the callback of sub, you can check for the existence of group 1.

<a?:([^:<>]+)[^<>]*>|:([^:]+):

The pattern matches

  • <a?: Match <, optional a and :
  • ([^:<>]+) Capture in group 1 any char except : < and >
  • [^<>]*> Optionally match any char except < and >, then match >
  • | Or
  • :([^:]+): Capture in group 2 all between :

See a regex demo and a Python demo.

For example

import re

pattern = r"<a?:([^:<>]+)[^<>]*>|:([^:]+):"
def shorten_emojis(content):
    return re.sub(
        pattern, lambda x: f"[{x.group(1)}]" if x.group(1) else f"[{x.group(2)}]"
        ,content
    )

print(shorten_emojis("<a:GG:123456789> <:1Copy:12345678><:14:1256678>:eyes:Hello friend!:eyes:"))
print(shorten_emojis("<a:cryLaptop:738450655395446814><:1Copy:817543814481707030><:14:817543815401439232> <:thoonk:621279654711656448><:coolbutdepressed:621279653675532290><:KL1Heart:585547199480332318>Nice<:dogwonder:621251869058269185> OK:eyes:"))

Output

[GG] [1Copy][14][eyes]Hello friend![eyes]
[cryLaptop][1Copy][14] [thoonk][coolbutdepressed][KL1Heart]Nice[dogwonder] OK[eyes]
Related