feat: add multiple discord bot cogs
Adds new cogs including DataManager, Hiring, KofiShop, Logging, ModMail, MORS, ServiceReview, StaffMsg, and Translator to enhance bot functionality for data management, hiring processes, logging events, and more.
This commit is contained in:
196
translator/logic.py
Normal file
196
translator/logic.py
Normal file
@@ -0,0 +1,196 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import random
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
|
||||
def reverse_map(m): return {v: k for k, v in m.items()}
|
||||
|
||||
class TranslationLogicMixin:
|
||||
"""This class holds all the translation logic for the cog."""
|
||||
|
||||
def _escape_regex(self, s):
|
||||
return re.escape(s)
|
||||
|
||||
def _generic_translator(self, text, lang_map, char_separator):
|
||||
# Regex to find custom emojis
|
||||
emoji_regex = re.compile(r"<a?:\w+:\d+>")
|
||||
|
||||
# Find all emojis and store them
|
||||
emojis = emoji_regex.findall(text)
|
||||
|
||||
# Replace emojis with a unique placeholder
|
||||
placeholder = "||EMOJI||"
|
||||
text_with_placeholders = emoji_regex.sub(placeholder, text)
|
||||
|
||||
# Translate the text with placeholders
|
||||
word_separator = ' ' if char_separator == '' else ' '
|
||||
words = text_with_placeholders.split(' ')
|
||||
translated_words = []
|
||||
emoji_counter = 0
|
||||
|
||||
for word in words:
|
||||
if placeholder in word:
|
||||
# If a word contains a placeholder, it might be part of the emoji code that got split.
|
||||
# We simply re-insert the emoji from our list.
|
||||
translated_words.append(emojis[emoji_counter])
|
||||
emoji_counter += 1
|
||||
else:
|
||||
translated_word = char_separator.join([lang_map.get(char.lower(), char) for char in word])
|
||||
translated_words.append(translated_word)
|
||||
|
||||
return word_separator.join(translated_words)
|
||||
|
||||
def _generic_decoder(self, text, reverse_map, chunk_size):
|
||||
result = ""
|
||||
text_no_space = text.replace(' ','')
|
||||
for i in range(0, len(text_no_space), chunk_size):
|
||||
chunk = text_no_space[i:i+chunk_size]
|
||||
result += reverse_map.get(chunk, '?')
|
||||
return result
|
||||
|
||||
def _greedy_decoder(self, text, reverse_map):
|
||||
syllables = sorted(reverse_map.keys(), key=len, reverse=True)
|
||||
regex = re.compile('|'.join(map(self._escape_regex, syllables)))
|
||||
matches = regex.findall(text.replace(' ', ''))
|
||||
return "".join([reverse_map.get(m, '?') for m in matches])
|
||||
|
||||
def _leet_decoder(self, text, reverse_map):
|
||||
decoded_text = text
|
||||
sorted_keys = sorted(reverse_map.keys(), key=len, reverse=True)
|
||||
for key in sorted_keys:
|
||||
decoded_text = decoded_text.replace(key, reverse_map[key])
|
||||
return decoded_text
|
||||
|
||||
def _morse_decoder(self, text, reverse_map):
|
||||
words = text.split(' ')
|
||||
decoded_words = []
|
||||
for word in words:
|
||||
chars = word.split(' ')
|
||||
decoded_words.append("".join([reverse_map.get(c, '?') for c in chars]))
|
||||
return " ".join(decoded_words)
|
||||
|
||||
def _pig_latin_translator(self, text):
|
||||
vowels = "aeiou"
|
||||
translated_words = []
|
||||
for word in text.split(' '):
|
||||
if not word: continue
|
||||
match = re.match(r"^([^a-zA-Z0-9]*)(.*?)([^a-zA-Z0-9]*)$", word)
|
||||
leading_punct, clean_word, trailing_punct = match.groups()
|
||||
|
||||
if not clean_word:
|
||||
translated_words.append(word)
|
||||
continue
|
||||
|
||||
if clean_word and clean_word[0].lower() in vowels:
|
||||
translated_word = clean_word + "way"
|
||||
else:
|
||||
first_vowel_index = -1
|
||||
for i, char in enumerate(clean_word):
|
||||
if char.lower() in vowels:
|
||||
first_vowel_index = i
|
||||
break
|
||||
if first_vowel_index == -1:
|
||||
translated_word = clean_word + "ay"
|
||||
else:
|
||||
translated_word = clean_word[first_vowel_index:] + clean_word[:first_vowel_index] + "ay"
|
||||
translated_words.append(leading_punct + translated_word + trailing_punct)
|
||||
return " ".join(translated_words)
|
||||
|
||||
def _pig_latin_decoder(self, text):
|
||||
decoded_words = []
|
||||
for word in text.split(' '):
|
||||
if not word: continue
|
||||
match = re.match(r"^([^a-zA-Z0-9]*)(.*?)([^a-zA-Z0-9]*)$", word)
|
||||
leading_punct, clean_word, trailing_punct = match.groups()
|
||||
|
||||
if not clean_word:
|
||||
decoded_words.append(word)
|
||||
continue
|
||||
|
||||
original_word = ""
|
||||
if clean_word.lower().endswith("way"):
|
||||
original_word = clean_word[:-3]
|
||||
elif clean_word.lower().endswith("ay"):
|
||||
base_word = clean_word[:-2]
|
||||
last_consonant_block_index = -1
|
||||
for i in range(len(base_word) - 1, -1, -1):
|
||||
if base_word[i].lower() not in "aeiou":
|
||||
last_consonant_block_index = i
|
||||
else:
|
||||
break
|
||||
if last_consonant_block_index != -1:
|
||||
while last_consonant_block_index > 0 and base_word[last_consonant_block_index-1].lower() not in "aeiou":
|
||||
last_consonant_block_index -= 1
|
||||
consonants = base_word[last_consonant_block_index:]
|
||||
stem = base_word[:last_consonant_block_index]
|
||||
original_word = consonants + stem
|
||||
else:
|
||||
original_word = base_word
|
||||
else:
|
||||
original_word = clean_word
|
||||
decoded_words.append(leading_punct + original_word + trailing_punct)
|
||||
return " ".join(decoded_words)
|
||||
|
||||
def _uwu_translator(self, text):
|
||||
text = text.lower()
|
||||
text = text.replace('l', 'ww')
|
||||
text = text.replace('r', 'w')
|
||||
text = text.replace('na', 'nya').replace('ne', 'nye').replace('ni', 'nyi').replace('no', 'nyo').replace('nu', 'nyu')
|
||||
text = text.replace('ove', 'uv')
|
||||
words = text.split(' ')
|
||||
uwu_words = []
|
||||
for word in words:
|
||||
if len(word) > 3 and random.random() < 0.3:
|
||||
uwu_words.append(f"{word[0]}-{word}")
|
||||
else:
|
||||
uwu_words.append(word)
|
||||
text = " ".join(uwu_words)
|
||||
if random.random() < 0.5:
|
||||
emoticons = [' uwu', ' owo', ' >w<', ' ^-^', ' ;;']
|
||||
text += random.choice(emoticons)
|
||||
return text
|
||||
|
||||
def _uwu_decoder(self, text):
|
||||
emoticons = [' uwu', ' owo', ' >w<', ' ^-^', ' ;;']
|
||||
for emo in emoticons:
|
||||
if text.endswith(emo):
|
||||
text = text[:-len(emo)]
|
||||
text = re.sub(r'(\w)-(\w+)', r'\2', text)
|
||||
text = text.replace('uv', 'ove')
|
||||
text = text.replace('nyu', 'nu').replace('nyo', 'no').replace('nyi', 'ni').replace('nye', 'ne').replace('nya', 'na')
|
||||
text = text.replace('ww', 'l')
|
||||
text = text.replace('w', 'r')
|
||||
return text
|
||||
|
||||
async def _find_language(self, query: str):
|
||||
"""Finds languages by key or name, case-insensitively."""
|
||||
query = query.lower()
|
||||
exact_key_match = [key for key in self.all_languages if key.lower() == query]
|
||||
if exact_key_match:
|
||||
return exact_key_match
|
||||
|
||||
exact_name_match = [key for key, lang in self.all_languages.items() if lang['name'].lower() == query]
|
||||
if exact_name_match:
|
||||
return exact_name_match
|
||||
|
||||
partial_matches = [
|
||||
key for key, lang in self.all_languages.items()
|
||||
if query in key.lower() or query in lang['name'].lower()
|
||||
]
|
||||
return partial_matches
|
||||
|
||||
async def _auto_translate_to_common(self, text: str) -> list:
|
||||
"""Helper to find all possible translations for a given text."""
|
||||
possible_translations = []
|
||||
for lang_key, lang_obj in self.all_languages.items():
|
||||
if lang_key == 'common':
|
||||
continue
|
||||
try:
|
||||
decoded_text = lang_obj['from_func'](text)
|
||||
re_encoded_text = lang_obj['to_func'](decoded_text)
|
||||
if re_encoded_text == text:
|
||||
possible_translations.append(f"**As {lang_obj['name']}:**\n{box(decoded_text)}")
|
||||
except Exception:
|
||||
continue
|
||||
return possible_translations
|
||||
|
||||
Reference in New Issue
Block a user