diff --git a/core/igncore.py b/core/igncore.py index 72f4210..45a704b 100644 --- a/core/igncore.py +++ b/core/igncore.py @@ -42,7 +42,7 @@ class IgnCore: self.last_timer_event = 0 self.start_time = int(time.time()) self.major_version = "IGNCore v2.6" - self.minor_version = "6" + self.minor_version = "7" self.incoming_queue = FifoQueue() self.mass_message_queue = None self.conns = DictObject() diff --git a/modules/raidbot/tower/contract_controller.py b/modules/raidbot/tower/contract_controller.py index ca396f4..a039709 100644 --- a/modules/raidbot/tower/contract_controller.py +++ b/modules/raidbot/tower/contract_controller.py @@ -46,7 +46,7 @@ class ContractController(BaseModule): "where org_name IS NOT NULL GROUP BY org_name ORDER BY contracts desc", []) page = int(named_params.page or "1") offset = (page - 1) * self.PAGE_SIZE - data = [x for x in data if x.contracts > min_ql] + data = [x for x in data if x.contracts and x.contracts > min_ql] return self.format_pagination(data, offset, page, f"Tower Contracts ({len(data)})", f"There are no orgs with more than " f"{min_ql} contract points.", diff --git a/modules/standard/specials/specials_controller.py b/modules/standard/specials/specials_controller.py index 63be979..edfe787 100644 --- a/modules/standard/specials/specials_controller.py +++ b/modules/standard/specials/specials_controller.py @@ -304,7 +304,7 @@ class SpecialsController: [item_id, item_id]) if not item: - return f"Could not find item with ID {item_id:d}." + return f"Could not find item with ID {item_id}." ql = ql or item.highql @@ -313,7 +313,7 @@ class SpecialsController: if not low_attributes or not high_attributes: return f"Could not find weapon information or item is not a weapon for " \ - f"ID {item_id:d}." + f"ID {item_id}." weapon_attack = self.util.interpolate_value(ql, {item.lowql: low_attributes.attack_time, item.highql: high_attributes.attack_time}) / 100 @@ -330,36 +330,36 @@ class SpecialsController: if high_attributes.aimed_shot: as_info = self.get_aimed_shot_info(weapon_attack, weapon_recharge, 1) - blob += f"Aimed Shot\n{as_info.skill_cap:d} skill needed to cap " \ - f"Aimed Shot recharge at {as_info.hard_cap:d} secs\n\n" + blob += f"Aimed Shot\n{as_info.skill_cap:.0f} skill needed to cap " \ + f"Aimed Shot recharge at {as_info.hard_cap:.2f} secs\n\n" if high_attributes.burst: burst_recharge = self.util.interpolate_value(ql, {item.lowql: low_attributes.burst, item.highql: high_attributes.burst}) burst_info = self.get_burst_info(weapon_attack, weapon_recharge, burst_recharge, 1) - blob += f"Burst Recharge: {burst_recharge:d}\n" \ + blob += f"Burst Recharge: {burst_recharge:.2f}\n" \ f"{burst_info.skill_cap:d} skill needed " \ - f"to cap Burst recharge at {burst_info.hard_cap:d} secs\n\n" + f"to cap Burst recharge at {burst_info.hard_cap:.2f} secs\n\n" if high_attributes.fast_attack: fast_attack_info = self.get_fast_attack_info(weapon_attack, 1) - blob += f"Fast Attack\n{fast_attack_info.skill_cap:d} skill needed " \ + blob += f"Fast Attack\n{fast_attack_info.skill_cap:.0f} skill needed " \ f"to cap Fast Attack recharge at {fast_attack_info.hard_cap:.2f} secs\n\n" if high_attributes.fling_shot: fling_shot_info = self.get_fling_shot_info(weapon_attack, 1) - blob += f"Fling Shot\n{fling_shot_info.skill_cap:d} skill needed " \ + blob += f"Fling Shot\n{fling_shot_info.skill_cap} skill needed " \ f"to cap Fling Shot recharge at {fling_shot_info.hard_cap:.2f} secs\n\n" if high_attributes.full_auto: full_auto_recharge = self.util.interpolate_value(ql, {item.lowql: low_attributes.full_auto, item.highql: high_attributes.full_auto}) full_auto_info = self.get_full_auto_info(weapon_attack, weapon_recharge, full_auto_recharge, 1) - blob += f"Full Auto Recharge: {full_auto_recharge:d}\n" \ - f"{full_auto_info.skill_cap:d} skill needed " \ - f"to cap Full Auto recharge at {full_auto_info.hard_cap:d} secs\n\n" + blob += f"Full Auto Recharge: {full_auto_recharge:.2f}\n" \ + f"{full_auto_info.skill_cap:.0f} skill needed " \ + f"to cap Full Auto recharge at {full_auto_info.hard_cap:.2f} secs\n\n" - return ChatBlob(f"Weapon Info for {item.name} (QL {ql:d})", blob) + return ChatBlob(f"Weapon Info for {item.name} (QL {ql})", blob) def get_init_result(self, weapon_attack, weapon_recharge, init_skill): if init_skill < 1200: @@ -581,6 +581,6 @@ class SpecialsController: blob = "" for i in reversed(range(0, num_steps)): inits_needed = self.get_inits_needed(i * step_size, weapon_attack, weapon_recharge) - blob += f"DEF >{'=' * i}{']['}{'=' * (num_steps - 1 - i)}< AGG {i * step_size:d}% {inits_needed:d} init \n" + blob += f"DEF [{'=' * i}||{'=' * (num_steps - 1 - i)}] AGG {i * step_size:.0f}% {inits_needed:.0f} init \n" return blob diff --git a/modules/standard/translation/translation_controller.py b/modules/standard/translation/translation_controller.py new file mode 100644 index 0000000..28972a4 --- /dev/null +++ b/modules/standard/translation/translation_controller.py @@ -0,0 +1,77 @@ +import re +import urllib +from json import JSONDecodeError + +import requests +import time + +from core.command_param_types import Any +from core.decorators import instance, command, setting +from core.igncore import IgnCore +from core.registry import Registry +from core.setting_service import SettingService +from core.setting_types import TextSettingType +from core.text import Text + +language_codes = [ + 'af', 'am', 'ar', 'az', 'be', 'bg', 'bn', 'bs', 'ca', 'cs', 'cy', 'da', 'de', 'el', + 'en', 'es', 'et', 'eu', 'fa', 'fi', 'fil', 'fo', 'fr', 'ga', 'gl', 'gu', 'he', 'hi', + 'hr', 'hu', 'hy', 'id', 'is', 'it', 'ja', 'ka', 'kk', 'km', 'kn', 'ko', 'ky', 'lo', + 'lt', 'lv', 'mk', 'ml', 'mn', 'mr', 'ms', 'my', 'nb', 'ne', 'nl', 'pa', 'pl', 'pt', + 'ro', 'ru', 'si', 'sk', 'sl', 'sq', 'sr', 'sv', 'sw', 'ta', 'te', 'th', 'ti', 'to', + 'tr', 'uk', 'und', 'ur', 'uz', 'vi', 'yue', 'zh', 'zu' ] + + +@instance() +class TranslationController: + uri = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=%s&tl=%s&dt=t&q=%s" + last_msg = 0 + + def inject(self, registry: Registry): + self.bot: IgnCore = registry.get_instance("bot") + self.text: Text = registry.get_instance("text") + self.setting_service: SettingService = registry.get_instance("setting_service") + + + @setting(name="default_target", value="en", description="Default target language for translations") + def default_target(self) -> TextSettingType: + return TextSettingType(language_codes) + + @command(command="translate", params=[Any("string")], access_level="member", + description="Translates messages to English via the Google API") + def translate(self, _, string): + if left := self.last_msg+10 > time.time(): + return f"Translating is on cooldown, to prevent spamming the service. " \ + f"Please try again in {(self.last_msg+10)-time.time():.2f} seconds." + self.last_msg = time.time() + sl = "auto" + tl = self.default_target().get_value() + text = "" + if match := re.match("^([a-zA-Z]{1,3}) ([a-zA-Z]{1,3}) (.+)$", string.replace("\n", "
"), re.S): + a, b, c = match.groups() + if a in language_codes and b in language_codes: + sl, tl, text = a, b, c + if text == "": + if match := re.match("^([a-zA-Z]{1,3}) (.+)$", string.replace("\n", "
"), re.S): + b, c = match.groups() + if b in language_codes: + tl, text = b, c + if text == "": + text = string + res = requests.get(self.uri % (urllib.parse.quote(sl), + urllib.parse.quote(tl), + urllib.parse.quote(text, safe=""))) + try: + res = res.json() + except JSONDecodeError as e: + return f"There was an error while translating your message: {res.text}" + orig = "" + trans = "" + for i in res[0]: + orig = f"{orig} {i[1]} ".strip() + trans = f"{trans} {i[0]} ".strip() + + return f"[{res[2].upper()}] {orig}
[{tl.upper()}] {trans}" + + # Taken from: https://github.com/rspeer/langcodes/blob/master/langcodes/language_lists.py +