From c4b56bee9b24649de0f85d14fbf5fc576b063340 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Sun, 12 Apr 2026 14:57:04 +0000
Subject: [PATCH] Added and updated repositories 2026-04-12 14:57:04
---
Fixyres/FModules/.gitignore | 207 ++++
Fixyres/FModules/BSR.py | 254 +++++
Fixyres/FModules/FHeta.py | 986 ++++++++++++++++++
Fixyres/FModules/LICENSE | 201 ++++
Fixyres/FModules/README.md | 1 +
Fixyres/FModules/SCD.py | 197 ++++
Fixyres/FModules/akinator.py | 456 ++++++++
Fixyres/FModules/assets/BSR/banner.png | Bin 0 -> 196853 bytes
Fixyres/FModules/assets/FHeta/empty_pic.png | Bin 0 -> 11147 bytes
Fixyres/FModules/assets/FHeta/logo.png | Bin 0 -> 14003 bytes
.../assets/FHeta/magnifying_glass.png | Bin 0 -> 7500 bytes
.../FModules/assets/FHeta/try_other_query.png | Bin 0 -> 4297 bytes
Fixyres/FModules/assets/SCD/banner.png | Bin 0 -> 250478 bytes
Fixyres/FModules/assets/akinator/banner.png | Bin 0 -> 29226 bytes
Fixyres/FModules/assets/akinator/idk.png | Bin 0 -> 102073 bytes
Fixyres/FModules/full.txt | 4 +
.../5dfab071f9ac968d824a4cbd2f52c7ab.png | Bin 0 -> 645055 bytes
Midga3/Heroku-modules/BirthdayCount.py | 68 ++
Midga3/Heroku-modules/PingEmoji.py | 29 +
Midga3/Heroku-modules/ZOV.py | 208 ++++
.../bleabratanspapibobolshoyevyrychil.py | 8 +
Midga3/Heroku-modules/deletelinux.py | 27 +
.../doc_2026-01-28_20-39-33.gif | Bin 0 -> 6326295 bytes
Midga3/Heroku-modules/fhetastatus.py | 40 +
Midga3/Heroku-modules/new_module.jpg | Bin 0 -> 35573 bytes
Midga3/Heroku-modules/radiolistener.py | 70 ++
Midga3/Heroku-modules/radios.json | 37 +
Midga3/Heroku-modules/speedrun.py | 140 +++
.../testoffhetapingdonttouch.py | 1 +
Midga3/Heroku-modules/virus.py | 3 +
archquise/q.mods/.DS_Store | Bin 0 -> 6148 bytes
archquise/q.mods/.gitignore | 7 +
archquise/q.mods/AniLiberty.py | 248 +++++
archquise/q.mods/CodeShare.py | 94 ++
archquise/q.mods/FolderAutoRead.py | 158 +++
archquise/q.mods/IrisSimpleMod.py | 126 +++
archquise/q.mods/LICENSE | 661 ++++++++++++
archquise/q.mods/README.md | 2 +
archquise/q.mods/TempChat.py | 150 +++
archquise/q.mods/WindowsKeys.py | 134 +++
archquise/q.mods/face.py | 78 ++
archquise/q.mods/full.txt | 10 +
archquise/q.mods/shortener.py | 160 +++
archquise/q.mods/timezone.py | 85 ++
archquise/q.mods/ytdl.py | 234 +++++
fiksofficial/python-modules/PyInstall.py | 110 +-
fiksofficial/python-modules/stream.py | 436 +++++++-
47 files changed, 5628 insertions(+), 2 deletions(-)
create mode 100644 Fixyres/FModules/.gitignore
create mode 100644 Fixyres/FModules/BSR.py
create mode 100644 Fixyres/FModules/FHeta.py
create mode 100644 Fixyres/FModules/LICENSE
create mode 100644 Fixyres/FModules/README.md
create mode 100644 Fixyres/FModules/SCD.py
create mode 100644 Fixyres/FModules/akinator.py
create mode 100644 Fixyres/FModules/assets/BSR/banner.png
create mode 100644 Fixyres/FModules/assets/FHeta/empty_pic.png
create mode 100644 Fixyres/FModules/assets/FHeta/logo.png
create mode 100644 Fixyres/FModules/assets/FHeta/magnifying_glass.png
create mode 100644 Fixyres/FModules/assets/FHeta/try_other_query.png
create mode 100644 Fixyres/FModules/assets/SCD/banner.png
create mode 100644 Fixyres/FModules/assets/akinator/banner.png
create mode 100644 Fixyres/FModules/assets/akinator/idk.png
create mode 100644 Fixyres/FModules/full.txt
create mode 100644 Midga3/Heroku-modules/5dfab071f9ac968d824a4cbd2f52c7ab.png
create mode 100644 Midga3/Heroku-modules/BirthdayCount.py
create mode 100644 Midga3/Heroku-modules/PingEmoji.py
create mode 100644 Midga3/Heroku-modules/ZOV.py
create mode 100644 Midga3/Heroku-modules/bleabratanspapibobolshoyevyrychil.py
create mode 100644 Midga3/Heroku-modules/deletelinux.py
create mode 100644 Midga3/Heroku-modules/doc_2026-01-28_20-39-33.gif
create mode 100644 Midga3/Heroku-modules/fhetastatus.py
create mode 100644 Midga3/Heroku-modules/new_module.jpg
create mode 100644 Midga3/Heroku-modules/radiolistener.py
create mode 100644 Midga3/Heroku-modules/radios.json
create mode 100644 Midga3/Heroku-modules/speedrun.py
create mode 100644 Midga3/Heroku-modules/testoffhetapingdonttouch.py
create mode 100644 Midga3/Heroku-modules/virus.py
create mode 100644 archquise/q.mods/.DS_Store
create mode 100644 archquise/q.mods/.gitignore
create mode 100644 archquise/q.mods/AniLiberty.py
create mode 100644 archquise/q.mods/CodeShare.py
create mode 100644 archquise/q.mods/FolderAutoRead.py
create mode 100644 archquise/q.mods/IrisSimpleMod.py
create mode 100644 archquise/q.mods/LICENSE
create mode 100644 archquise/q.mods/README.md
create mode 100644 archquise/q.mods/TempChat.py
create mode 100644 archquise/q.mods/WindowsKeys.py
create mode 100644 archquise/q.mods/face.py
create mode 100644 archquise/q.mods/full.txt
create mode 100644 archquise/q.mods/shortener.py
create mode 100644 archquise/q.mods/timezone.py
create mode 100644 archquise/q.mods/ytdl.py
diff --git a/Fixyres/FModules/.gitignore b/Fixyres/FModules/.gitignore
new file mode 100644
index 0000000..b7faf40
--- /dev/null
+++ b/Fixyres/FModules/.gitignore
@@ -0,0 +1,207 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[codz]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py.cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# UV
+# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+#uv.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+#poetry.toml
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
+# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
+#pdm.lock
+#pdm.toml
+.pdm-python
+.pdm-build/
+
+# pixi
+# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
+#pixi.lock
+# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
+# in the .venv directory. It is recommended not to include this directory in version control.
+.pixi
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.envrc
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
+
+# Abstra
+# Abstra is an AI-powered process automation framework.
+# Ignore directories containing user credentials, local state, and settings.
+# Learn more at https://abstra.io/docs
+.abstra/
+
+# Visual Studio Code
+# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
+# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
+# and can be added to the global gitignore or merged into this file. However, if you prefer,
+# you could uncomment the following to ignore the entire vscode folder
+# .vscode/
+
+# Ruff stuff:
+.ruff_cache/
+
+# PyPI configuration file
+.pypirc
+
+# Cursor
+# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
+# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
+# refer to https://docs.cursor.com/context/ignore-files
+.cursorignore
+.cursorindexingignore
+
+# Marimo
+marimo/_static/
+marimo/_lsp/
+__marimo__/
diff --git a/Fixyres/FModules/BSR.py b/Fixyres/FModules/BSR.py
new file mode 100644
index 0000000..8d383c4
--- /dev/null
+++ b/Fixyres/FModules/BSR.py
@@ -0,0 +1,254 @@
+__version__ = (1, 0, 0)
+
+# ©️ Fixyres, 2026-2030
+# 🌐 https://github.com/Fixyres/FModules
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 🔑 http://www.apache.org/licenses/LICENSE-2.0
+
+# meta banner: https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/BSR/banner.png
+# meta developer: @FModules
+# meta fhsdesc: brawlstars, game, funny
+
+from .. import loader, utils
+from urllib.parse import urlparse, parse_qs
+
+async def extract_code(value: str) -> str:
+ if value.startswith("http"):
+ tags = parse_qs(urlparse(value).query).get("tag")
+ return tags[0] if tags else value
+ return value
+
+async def to_id(code: str) -> int:
+ code = code.strip().upper()
+ if not code.startswith("X"):
+ return 0
+ val = 0
+ for ch in code[1:]:
+ i = "QWERTYUPASDFGHJKLZCVBNM23456789".find(ch)
+ if i == -1:
+ return 0
+ val = val * 31 + i
+ return val >> 8
+
+async def to_code(n: int) -> str:
+ if n < 0:
+ return "X"
+ n_shifted = n << 8
+ res = []
+ chars = "QWERTYUPASDFGHJKLZCVBNM23456789"
+ while n_shifted > 0:
+ res.append(chars[n_shifted % 31])
+ n_shifted //= 31
+ return "X" + "".join(reversed(res))
+
+@loader.tds
+class BSR(loader.Module):
+ '''Module for finding nearby game rooms in BrawlStars.'''
+
+ strings = {
+ "name": "BSR",
+ "invalid_args": "Usage: {prefix}bsr (room code/link) (previous) (next)",
+ "invalid_code": "Invalid room code!",
+ "at_least_one": "At least one argument (previous or next) must be greater than 0!",
+ "prev_block": "Previous:\n{prev_list}
",
+ "next_block": "Next:\n{next_list}
",
+ "btn_target": "Target Room"
+ }
+
+ strings_ru = {
+ "_cls_doc": "Модуль для поиска ближайших игровых комнат в BrawlStars.",
+ "invalid_args": "Использование: {prefix}bsr (код комнаты/ссылка) (предыдущие) (следующие)",
+ "invalid_code": "Неверный код комнаты!",
+ "at_least_one": "Хотя бы один аргумент (предыдущие или следующие) должен быть больше 0!",
+ "prev_block": "Предыдущие:\n{prev_list}
",
+ "next_block": "Следующие:\n{next_list}
",
+ "btn_target": "Целевая комната"
+ }
+
+ strings_ua = {
+ "_cls_doc": "Модуль для пошуку найближчих ігрових кімнат у BrawlStars.",
+ "invalid_args": "Використання: {prefix}bsr (код кімнати/посилання) (попередні) (наступні)",
+ "invalid_code": "Невірний код кімнати!",
+ "at_least_one": "Хоча б один аргумент (попередні або наступні) повинен бути більшим за 0!",
+ "prev_block": "Попередні:\n{prev_list}
",
+ "next_block": "Наступні:\n{next_list}
",
+ "btn_target": "Цільова кімната"
+ }
+
+ strings_kz = {
+ "_cls_doc": "BrawlStars ойынында жақын маңдағы ойын бөлмелерін табуға арналған модуль.",
+ "invalid_args": "Қолдану: {prefix}bsr (бөлме коды/сілтеме) (алдыңғы) (келесі)",
+ "invalid_code": "Қате бөлме коды!",
+ "at_least_one": "Кем дегенде бір аргумент (алдыңғы немесе келесі) 0-ден үлкен болуы керек!",
+ "prev_block": "Алдыңғы:\n{prev_list}
",
+ "next_block": "Келесі:\n{next_list}
",
+ "btn_target": "Мақсатты бөлме"
+ }
+
+ strings_uz = {
+ "_cls_doc": "BrawlStars'da eng yaqin o'yin xonalarini topish uchun modul.",
+ "invalid_args": "Qo'llanilishi: {prefix}bsr (xona kodi/havolasi) (oldingi) (keyingi)",
+ "invalid_code": "Noto'g'ri xona kodi!",
+ "at_least_one": "Kamida bitta argument (oldingi yoki keyingi) 0 dan katta bo'lishi kerak!",
+ "prev_block": "Oldingi:\n{prev_list}
",
+ "next_block": "Keyingi:\n{next_list}
",
+ "btn_target": "Maqsadli xona"
+ }
+
+ strings_fr = {
+ "_cls_doc": "Module pour trouver des salles de jeu à proximité dans BrawlStars.",
+ "invalid_args": "Utilisation: {prefix}bsr (code/lien) (précédents) (suivants)",
+ "invalid_code": "Code de salle invalide!",
+ "at_least_one": "Au moins un argument doit être supérieur à 0 !",
+ "prev_block": "Précédents:\n{prev_list}
",
+ "next_block": "Suivants:\n{next_list}
",
+ "btn_target": "Salle cible"
+ }
+
+ strings_de = {
+ "_cls_doc": "Modul zum Finden von nahegelegenen Spielräumen in BrawlStars.",
+ "invalid_args": "Verwendung: {prefix}bsr (Raumcode/Link) (vorherige) (nächste)",
+ "invalid_code": "Ungültiger Raumcode!",
+ "at_least_one": "Mindestens ein argument muss größer als 0 sein!",
+ "prev_block": "Vorherige:\n{prev_list}
",
+ "next_block": "Nächste:\n{next_list}
",
+ "btn_target": "Zielraum"
+ }
+
+ strings_jp = {
+ "_cls_doc": "BrawlStarsで近くのゲームルームを検索するためのモジュール。",
+ "invalid_args": "使用法: {prefix}bsr (コード/リンク) (前) (次)",
+ "invalid_code": "無効なルームコード!",
+ "at_least_one": "少なくとも1つの引数は0より大きくなければなりません!",
+ "prev_block": "前:\n{prev_list}
",
+ "next_block": "次:\n{next_list}
",
+ "btn_target": "ターゲットルーム"
+ }
+
+ @loader.command(
+ ru_doc="(код комнаты/ссылка) (предыдущие) (следующие) - найти комнаты.",
+ ua_doc="(код кімнати/посилання) (попередні) (наступні) - знайти кімнати.",
+ kz_doc="(бөлме коды/сілтеме) (алдыңғы) (келесі) - бөлмелерді табу.",
+ uz_doc="(xona kodi/havolasi) (oldingi) (keyingi) - xonalarni topish.",
+ fr_doc="(code/lien) (précédents) (suivants) - trouver des salles.",
+ de_doc="(Raumcode/Link) (vorherige) (nächste) - Räume finden.",
+ jp_doc="(コード/リンク) (前) (次) - ルームを検索します。"
+ )
+ async def bsr(self, message):
+ '''(room code/link) (previous) (next) - find rooms.'''
+ args = utils.get_args_raw(message).split()
+ if not args:
+ return await utils.answer(message, self.strings("invalid_args").format(prefix=self.get_prefix()))
+
+ raw_input = args[0]
+ before = 0
+ nxt = 10
+
+ if len(args) >= 2:
+ try:
+ before = int(args[1])
+ except ValueError:
+ pass
+
+ if len(args) >= 3:
+ try:
+ nxt = int(args[2])
+ except ValueError:
+ pass
+
+ before = max(0, min(before, 5000))
+ nxt = max(0, min(nxt, 5000))
+
+ if before == 0 and nxt == 0:
+ return await utils.answer(message, self.strings("at_least_one"))
+
+ clean_tag = await extract_code(raw_input)
+ base_id = await to_id(clean_tag)
+
+ if base_id == 0:
+ return await utils.answer(message, self.strings("invalid_code"))
+
+ text, page, total_pages = await self.get_page_content(base_id, before, nxt, 0)
+ kb = self.build_keyboard(base_id, before, nxt, page, total_pages, clean_tag)
+
+ await self.inline.form(
+ message=message,
+ text=text,
+ photo="https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/BSR/banner.png",
+ reply_markup=kb
+ )
+
+ async def get_page_content(self, base_id: int, before: int, nxt: int, page: int):
+ actual_before = min(before, base_id)
+ total_pages = max(1, (actual_before + 9) // 10, (nxt + 9) // 10)
+
+ if page < 0:
+ page = total_pages - 1
+ if page >= total_pages:
+ page = 0
+
+ start = page * 10
+
+ prev_list = []
+ for i in range(start + 1, min(start + 10, actual_before) + 1):
+ c = await to_code(base_id - i)
+ link = f'{c}'
+ prev_list.append(link)
+
+ next_list = []
+ for i in range(start + 1, min(start + 10, nxt) + 1):
+ c = await to_code(base_id + i)
+ link = f'{c}'
+ next_list.append(link)
+
+ blocks = []
+
+ if prev_list:
+ blocks.append(self.strings("prev_block").format(prev_list="\n".join(prev_list)))
+
+ if next_list:
+ blocks.append(self.strings("next_block").format(next_list="\n".join(next_list)))
+
+ res = "\n\n".join(blocks)
+ if not res.strip():
+ res = " "
+
+ return res, page, total_pages
+
+ def build_keyboard(self, base_id: int, before: int, nxt: int, page: int, total_pages: int, clean_tag: str):
+ kb = [
+ [
+ {
+ "text": self.strings("btn_target"),
+ "copy": clean_tag
+ }
+ ]
+ ]
+
+ if total_pages > 1:
+ nav_row = []
+ if page > 0:
+ nav_row.append({"text": "←", "callback": self.page_cb, "args": (base_id, before, nxt, page - 1, clean_tag)})
+
+ nav_row.append({"text": f"{page + 1} / {total_pages}", "callback": self.dummy_cb, "args": ()})
+
+ if page < total_pages - 1:
+ nav_row.append({"text": "→", "callback": self.page_cb, "args": (base_id, before, nxt, page + 1, clean_tag)})
+
+ kb.append(nav_row)
+
+ return kb
+
+ async def dummy_cb(self, call):
+ await call.answer()
+
+ async def page_cb(self, call, base_id: int, before: int, nxt: int, page: int, clean_tag: str):
+ text, new_page, total_pages = await self.get_page_content(base_id, before, nxt, page)
+ kb = self.build_keyboard(base_id, before, nxt, new_page, total_pages, clean_tag)
+
+ await call.edit(
+ text=text,
+ photo="https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/BSR/banner.png",
+ reply_markup=kb
+ )
diff --git a/Fixyres/FModules/FHeta.py b/Fixyres/FModules/FHeta.py
new file mode 100644
index 0000000..ab706ae
--- /dev/null
+++ b/Fixyres/FModules/FHeta.py
@@ -0,0 +1,986 @@
+__version__ = (9, 3, 9)
+
+# meta developer: @FModules
+# meta pic: https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/logo.png
+# meta banner: https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/logo.png
+# scope: hikka_min 2.0.0
+
+# ©️ Fixyres, 2024-2030
+# 🌐 https://github.com/Fixyres/FModules
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# 🔑 http://www.apache.org/licenses/LICENSE-2.0
+
+import asyncio
+import aiohttp
+import ast
+import re
+import sys
+import uuid
+import importlib
+from contextlib import suppress
+from typing import Optional, Dict, List, Union, Tuple, Any
+from urllib.parse import unquote
+from importlib.machinery import ModuleSpec
+
+from .. import loader, utils
+from ..types import CoreOverwriteError
+from herokutl.tl.functions.contacts import UnblockRequest
+from aiogram.types import InlineQueryResultArticle, InputTextMessageContent, LinkPreviewOptions, ChosenInlineResult, CallbackQuery, Message
+
+
+class FHetaAPI:
+ def __init__(self) -> None:
+ self.token: Optional[str] = None
+ self.session: Optional[aiohttp.ClientSession] = None
+
+ async def connect(self) -> aiohttp.ClientSession:
+ if self.session is None or self.session.closed:
+ self.session = aiohttp.ClientSession()
+ return self.session
+
+ async def fetch(self, path: str, **params: Any) -> Dict[str, Any]:
+ session = await self.connect()
+ try:
+ async with session.get(
+ f"https://api.fixyres.com/{path}",
+ params=params,
+ headers={"Authorization": self.token},
+ timeout=aiohttp.ClientTimeout(total=10)
+ ) as response:
+ if response.status == 200:
+ return await response.json()
+ return {}
+ except Exception:
+ return {}
+
+ async def send(self, path: str, payload: Optional[Dict[str, Any]] = None, **params: Any) -> Dict[str, Any]:
+ session = await self.connect()
+ try:
+ async with session.post(
+ f"https://api.fixyres.com/{path}",
+ json=payload,
+ params=params,
+ headers={"Authorization": self.token},
+ timeout=aiohttp.ClientTimeout(total=10)
+ ) as response:
+ if response.status == 200:
+ return await response.json()
+ return {}
+ except Exception:
+ return {}
+
+
+class MInstaller:
+ async def execute(self, plugin: 'loader.Module', url: str) -> Tuple[str, List[str]]:
+ try:
+ code = await plugin._storage.fetch(url, auth=plugin.config.get("basic_auth"))
+ except Exception:
+ return "error", []
+
+ for step in range(5):
+ state = await self.load(plugin, code, url, step)
+
+ if state == "success":
+ if plugin.fully_loaded:
+ plugin.update_modules_in_db()
+ return "success", []
+
+ if state == "overwrite":
+ return "overwrite", []
+
+ if isinstance(state, list):
+ return "dependency", state
+
+ if state == "error":
+ return "error", []
+
+ await asyncio.sleep(0.5)
+
+ return "dependency", []
+
+ async def pip(self, dependencies: List[str]) -> bool:
+ virtualenv = hasattr(sys, 'real_prefix') or sys.prefix != getattr(sys, 'base_prefix', sys.prefix)
+ flags = ["--user"] if loader.USER_INSTALL and not virtualenv else []
+
+ process = await asyncio.create_subprocess_exec(
+ sys.executable, "-m", "pip", "install", "-U", "-q",
+ "--disable-pip-version-check", "--no-warn-script-location",
+ *flags, *dependencies
+ )
+
+ return await process.wait() == 0
+
+ async def load(self, plugin: 'loader.Module', code: str, origin: str, step: int) -> Union[str, List[str]]:
+ if step == 0:
+ try:
+ dependencies = list(filter(
+ lambda requirement: not requirement.startswith(("-", "_", ".")),
+ map(lambda raw: raw.strip().rstrip(','), loader.VALID_PIP_PACKAGES.search(code)[1].split())
+ ))
+
+ if dependencies:
+ if not await self.pip(dependencies):
+ return dependencies
+ importlib.invalidate_caches()
+ return "retry"
+ except Exception:
+ pass
+
+ try:
+ packages = list(filter(
+ lambda requirement: not requirement.startswith(("-", "_", ".")),
+ map(lambda raw: raw.strip().rstrip(','), loader.VALID_APT_PACKAGES.search(code)[1].split())
+ ))
+
+ if packages:
+ if not await plugin.install_packages(packages):
+ return packages
+ importlib.invalidate_caches()
+ return "retry"
+ except Exception:
+ pass
+
+ try:
+ tree = ast.parse(code)
+ identifier = next(
+ node.name for node in tree.body
+ if isinstance(node, ast.ClassDef) and any(
+ isinstance(base, ast.Attribute) and base.value.id == "Module" or
+ isinstance(base, ast.Name) and base.id == "Module"
+ for base in node.bases
+ )
+ )
+ except Exception:
+ identifier = "__extmod_" + str(uuid.uuid4())
+
+ name = f"heroku.modules.{identifier}"
+ instance = None
+
+ try:
+ spec = ModuleSpec(name, loader.StringLoader(code, f""), origin=f"")
+ instance = await plugin.allmodules.register_module(spec, name, origin, save_fs=False)
+
+ plugin.allmodules.send_config_one(instance)
+ await plugin.allmodules.send_ready_one(instance, no_self_unload=True, from_dlmod=False)
+
+ return "success"
+
+ except ImportError as exception:
+ alternative = {"sklearn": "scikit-learn", "pil": "Pillow", "herokutl": "Heroku-TL-New"}.get(exception.name.lower(), exception.name)
+ dependencies = [alternative]
+
+ if not alternative or not await self.pip(dependencies):
+ return dependencies
+
+ importlib.invalidate_caches()
+ return "retry"
+
+ except CoreOverwriteError:
+ return "overwrite"
+
+ except Exception:
+ return "error"
+
+ finally:
+ if instance and sys.exc_info()[0] is not None:
+ with suppress(Exception):
+ await plugin.allmodules.unload_module(instance.__class__.__name__)
+ plugin.allmodules.modules.remove(instance)
+
+
+class FHetaUI:
+ def __init__(self, main: 'FHeta') -> None:
+ self.main = main
+
+ def emoji(self, key: str) -> str:
+ return self.main.THEMES[self.main.config["theme"]][key]
+
+ def format(self, data: Dict[str, Any], query: str = "", index: int = 1, total: int = 1, inline: bool = False) -> str:
+ version = data.get("version", "?.?.?")
+ limit = 3700
+ name = utils.escape_html(data.get("name", ""))
+ author = utils.escape_html(data.get("author", "???"))
+
+ text = f"{self.emoji('module')} {name} {self.main.strings['author']} {author}"
+ if version != "?.?.?":
+ text += f" (v{version})"
+
+ description = data.get("description")
+ if description:
+ if isinstance(description, dict):
+ string = description.get(self.main.strings["lang"]) or description.get("doc") or next(iter(description.values()), "")
+ else:
+ string = description
+ text += f"\n\n{self.emoji('description')} {self.main.strings['description']}:\n{utils.escape_html(str(string))}
"
+
+ text += self.render(data.get("commands", []), "cmd", limit - len(re.sub(r'<[^>]+>', '', text)))
+ text += self.render(data.get("placeholders", []), "ph", limit - len(re.sub(r'<[^>]+>', '', text)))
+
+ return text
+
+ def render(self, items: List[Dict[str, Any]], kind: str, limit: int) -> str:
+ if not items:
+ return ""
+
+ lines = []
+ language = self.main.strings["lang"]
+
+ title = "commands" if kind == "cmd" else "placeholders"
+ more = "morecommands" if kind == "cmd" else "moreplaceholders"
+
+ for index, item in enumerate(items):
+ description = item.get("description", {})
+ if isinstance(description, dict):
+ description = description.get(language) or description.get("doc") or ""
+
+ description = utils.escape_html(description).split('\n')[0] if description else ""
+ name = utils.escape_html(item.get("name", ""))
+
+ if kind == "cmd":
+ character = '@' + self.main.inline.bot_username + ' ' if item.get('inline') else self.main.get_prefix()
+ row = f"{character}{name} {description}".strip()
+ else:
+ row = f"{{{name}}} {description}".strip()
+
+ extra = f"{self.main.strings[more].format(remaining=len(items) - index)}"
+ test = "\n".join(lines + [row, extra])
+
+ if len(re.sub(r'<[^>]+>', '', test)) > limit and index > 0:
+ lines.append(extra)
+ break
+
+ lines.append(row)
+
+ return f"\n\n{self.emoji('command' if kind == 'cmd' else 'placeholder')} {self.main.strings[title]}:\n{chr(10).join(lines)}
"
+
+ def buttons(self, link: str, stats: Dict[str, Any], index: int, modules: Optional[List[Dict[str, Any]]] = None, query: str = "") -> List[List[Dict[str, Any]]]:
+ buttons = []
+ decoded = unquote(link.replace('%20', '___SPACE___')).replace('___SPACE___', '%20')
+ url = decoded[4:] if decoded.startswith('dlm ') else decoded
+
+ if query:
+ buttons.append([
+ {"text": self.main.strings["query"], "copy": query},
+ {"text": self.main.strings["install"], "callback": self.main.install, "args": (url, index, modules, query)},
+ {"text": self.main.strings["code"], "url": url}
+ ])
+
+ buttons.append([
+ {"text": f"↑ {stats.get('likes', 0)}", "callback": self.main.rate, "args": (link, "like", index, modules, query)},
+ {"text": f"↓ {stats.get('dislikes', 0)}", "callback": self.main.rate, "args": (link, "dislike", index, modules, query)}
+ ])
+
+ if modules and len(modules) > 1:
+ count = {"text": self.main.strings["counter"].format(idx=index+1, total=len(modules)), "callback": self.main.show, "args": (index, modules, query)}
+ buttons[-1].insert(1, count)
+
+ navigation = []
+ if index > 0:
+ navigation.append({"text": "←", "callback": self.main.navigate, "args": (index - 1, modules, query)})
+ if index < len(modules) - 1:
+ navigation.append({"text": "→", "callback": self.main.navigate, "args": (index + 1, modules, query)})
+
+ if navigation:
+ buttons.append(navigation)
+
+ return buttons
+
+ def pagination(self, modules: List[Dict[str, Any]], query: str, page: int = 0, current: int = 0) -> List[List[Dict[str, Any]]]:
+ buttons = []
+ start = page * 8
+ end = min(start + 8, len(modules))
+
+ for index in range(start, end):
+ name = modules[index].get('name', 'Unknown')
+ author = modules[index].get('author', '???')
+ buttons.append([
+ {"text": f"{index + 1}. {name} by {author}", "callback": self.main.navigate, "args": (index, modules, query)}
+ ])
+
+ navigation = []
+ if page > 0:
+ navigation.append({"text": "←", "callback": self.main.page, "args": (page - 1, modules, query, current)})
+ if page < (len(modules) + 7) // 8 - 1:
+ navigation.append({"text": "→", "callback": self.main.page, "args": (page + 1, modules, query, current)})
+
+ if navigation:
+ buttons.append(navigation)
+
+ buttons.append([{"text": "✘", "callback": self.main.navigate, "args": (current, modules, query)}])
+ return buttons
+
+
+@loader.tds
+class FHeta(loader.Module):
+ '''Module for searching modules! Watch all FHeta news in @FHeta_Updates!'''
+
+ strings = {
+ "name": "FHeta",
+ "lang": "en",
+ "author": "by",
+ "description": "Description",
+ "commands": "Commands",
+ "placeholders": "Placeholders",
+ "morecommands": "...and {remaining} more commands.",
+ "moreplaceholders": "...and {remaining} more placeholders.",
+ "list": "All found modules:",
+ "search": "Searching for {query}...",
+ "noquery": "You didn't enter a search query, example: {prefix}fheta your query",
+ "notfound": "Nothing found for query {query}.",
+ "toolong": "Your query is too big, please try reducing it to 168 characters.",
+ "added": "✔ Rating submitted!",
+ "changed": "✔ Rating has been changed!",
+ "deleted": "✔ Rating deleted!",
+ "prompt": "Enter a query to search.",
+ "hint": "Name, command, description, author.",
+ "retry": "Try another query.",
+ "query": "Query",
+ "install": "Install",
+ "counter": "{idx}/{total}",
+ "code": "Code",
+ "success": "✔ Module successfully installed!",
+ "error": "✘ Error, perhaps the module is broken!",
+ "overwrite": "✘ Error, module tried to overwrite built-in module!",
+ "dependency": "✘ Dependencies installation error! {deps}",
+ "docdevs": "Use only modules from official Heroku developers when searching?",
+ "doctheme": "Theme for emojis."
+ }
+
+ strings_ru = {
+ "_cls_doc": "Модуль для поиска модулей! Следите за всеми новостями FHeta в @FHeta_Updates!",
+ "lang": "ru",
+ "author": "от",
+ "description": "Описание",
+ "commands": "Команды",
+ "placeholders": "Плейсхолдеры",
+ "morecommands": "...и еще {remaining} команд.",
+ "moreplaceholders": "...и еще {remaining} плейсхолдеров.",
+ "list": "Все найденные модули:",
+ "search": "Поиск по запросу {query}...",
+ "noquery": "Вы не ввели запрос для поиска, пример: {prefix}fheta ваш запрос",
+ "notfound": "Ничего не найдено по запросу {query}.",
+ "toolong": "Ваш запрос слишком большой, пожалуйста, сократите его до 168 символов.",
+ "added": "✔ Оценка добавлена!",
+ "changed": "✔ Оценка изменена!",
+ "deleted": "✔ Оценка удалена!",
+ "prompt": "Введите запрос для поиска.",
+ "hint": "Название, команда, описание, автор.",
+ "retry": "Попробуйте другой запрос.",
+ "query": "Запрос",
+ "install": "Установить",
+ "counter": "{idx}/{total}",
+ "code": "Код",
+ "success": "✔ Модуль успешно установлен!",
+ "error": "✘ Ошибка, возможно, модуль поломан!",
+ "overwrite": "✘ Ошибка, модуль пытался перезаписать встроенный модуль!",
+ "dependency": "✘ Ошибка установки зависимостей! {deps}",
+ "docdevs": "Использовать только модули от официальных разработчиков Heroku при поиске?",
+ "doctheme": "Тема для эмодзи."
+ }
+
+ strings_ua = {
+ "_cls_doc": "Модуль для пошуку модулів! Слідкуйте за всіма новинами FHeta в @FHeta_Updates!",
+ "lang": "ua",
+ "author": "від",
+ "description": "Опис",
+ "commands": "Команды",
+ "placeholders": "Плейсхолдери",
+ "morecommands": "...і ще {remaining} команд.",
+ "moreplaceholders": "...і ще {remaining} плейсхолдерів.",
+ "list": "Всі знайдені модули:",
+ "search": "Пошук за запитом {query}...",
+ "noquery": "Ви не ввели запит для пошуку, приклад: {prefix}fheta ваш запит",
+ "notfound": "Нічого не знайдено за запитом {query}.",
+ "toolong": "Ваш запит занадто великий, будь ласка, скоротіть його до 168 символів.",
+ "added": "✔ Оцінку додано!",
+ "changed": "✔ Оцінку змінено!",
+ "deleted": "✔ Оцінку видалено!",
+ "prompt": "Введіть запит для пошуку.",
+ "hint": "Назва, команда, опис, автор.",
+ "retry": "Спробуйте інший запит.",
+ "query": "Запит",
+ "install": "Встановити",
+ "counter": "{idx}/{total}",
+ "code": "Код",
+ "success": "✔ Модуль успішно встановлено!",
+ "error": "✘ Помилка, можливо, модуль поламаний!",
+ "overwrite": "✘ Помилка, модуль намагався перезаписати вбудований модуль!",
+ "dependency": "✘ Помилка встановлення залежностей! {deps}",
+ "docdevs": "Використовувати тільки модулі від офіційних розробників Heroku при пошуку?",
+ "doctheme": "Тема для емодзі."
+ }
+
+ strings_kz = {
+ "_cls_doc": "Модульдерді іздеу модулі! FHeta барлық жаңалықтарын @FHeta_Updates арнасында қадағалаңыз!",
+ "lang": "kz",
+ "author": "авторы",
+ "description": "Сипаттама",
+ "commands": "Командалар",
+ "placeholders": "Плейсхолдерлер",
+ "morecommands": "...және тағы {remaining} команда.",
+ "moreplaceholders": "...және тағы {remaining} плейсхолдер.",
+ "list": "Барлық табылған модульдер:",
+ "search": "{query} сұрауы бойынша іздеу...",
+ "noquery": "Сіз іздеу сұрауын енгізбедіңіз, мысал: {prefix}fheta сіздің сұрауыңыз",
+ "notfound": "{query} сұрауы бойынша ештеңе табылмады.",
+ "toolong": "Сіздің сұрауыңыз тым үлкен, оны 168 таңбаға дейін қысқартыңыз.",
+ "added": "✔ Бағалау қосылды!",
+ "changed": "✔ Бағалау өзгертілді!",
+ "deleted": "✔ Бағалау жойылды!",
+ "prompt": "Іздеу үшін сұрау енгізіңіз.",
+ "hint": "Атауы, команда, сипаттама, автор.",
+ "retry": "Басқа сұрауды қолданып көріңіз.",
+ "query": "Сұрау",
+ "install": "Орнату",
+ "counter": "{idx}/{total}",
+ "code": "Код",
+ "success": "✔ Модуль сәтті орнатылды!",
+ "error": "✘ Қате, мүмкін модуль бұзылған!",
+ "overwrite": "✘ Қате, модуль кіріктірілген модульді қайта жазуға тырысты!",
+ "dependency": "✘ Тәуелділіктерді орнату қатесі! {deps}",
+ "docdevs": "Іздеу кезінде тек ресми Heroku әзірлеушілерінің модульдерін пайдалану керек пе?",
+ "doctheme": "Эмодзилер үшін тақырып."
+ }
+
+ strings_uz = {
+ "_cls_doc": "Modullarni qidirish moduli! FHeta barcha yangilanishlarini @FHeta_Updates kanalida kuzatib boring!",
+ "lang": "uz",
+ "author": "muallif",
+ "description": "Tavsif",
+ "commands": "Buyruqlar",
+ "placeholders": "Pleysholderlar",
+ "morecommands": "...va yana {remaining} ta buyruq.",
+ "moreplaceholders": "...va yana {remaining} ta pleysholder.",
+ "list": "Barcha topilgan modullar:",
+ "search": "{query} so'rovi bo'yicha qidiruv...",
+ "noquery": "Siz qidiruv so'rovini kiritmadingiz, misol: {prefix}fheta sizning sorovingiz",
+ "notfound": "{query} so'rovi bo'yicha hech narsa topilmadi.",
+ "toolong": "Sizning so'rovingiz juda katta, iltimos uni 168 belgigacha qisqartiring.",
+ "added": "✔ Reyting qo'shildi!",
+ "changed": "✔ Reyting o'zgartirildi!",
+ "deleted": "✔ Reyting o'chirildi!",
+ "prompt": "Qidirish uchun so'rov kiriting.",
+ "hint": "Nomi, buyruq, tavsif, muallif.",
+ "retry": "Boshqa so'rovni sinab ko'ring.",
+ "query": "So'rov",
+ "install": "O'rnatish",
+ "counter": "{idx}/{total}",
+ "code": "Kod",
+ "success": "✔ Modul muvaffaqiyatli o'rnatildi!",
+ "error": "✘ Xatolik, ehtimol modul buzilgan!",
+ "overwrite": "✘ Xatolik, modul o'rnatilgan modulni qayta yozishga harakat qildi!",
+ "dependency": "✘ Bog'liqliklarni o'rnatish xatosi! {deps}",
+ "docdevs": "Qidiruv paytida faqat rasmiy Heroku ishlab chiquvchilarining modullaridan foydalanish kerakmi?",
+ "doctheme": "Emojilar uchun mavzu."
+ }
+
+ strings_fr = {
+ "_cls_doc": "Module de recherche de modules! Suivez toutes les actualités FHeta sur @FHeta_Updates!",
+ "lang": "fr",
+ "author": "par",
+ "description": "Description",
+ "commands": "Commandes",
+ "placeholders": "Espaces réservés",
+ "morecommands": "...et {remaining} commandes supplémentaires.",
+ "moreplaceholders": "...et {remaining} espaces réservés supplémentaires.",
+ "list": "Tous les modules trouvés:",
+ "search": "Recherche pour {query}...",
+ "noquery": "Vous n'avez pas entré de requête de recherche, exemple: {prefix}fheta votre requête",
+ "notfound": "Rien trouvé pour la requête {query}.",
+ "toolong": "Votre requête est trop longue, veuillez la réduire à 168 caractères.",
+ "added": "✔ Note ajoutée!",
+ "changed": "✔ Note modifiée!",
+ "deleted": "✔ Note supprimée!",
+ "prompt": "Entrez une requête pour rechercher.",
+ "hint": "Nom, commande, description, auteur.",
+ "retry": "Essayez une autre requête.",
+ "query": "Requête",
+ "install": "Installer",
+ "counter": "{idx}/{total}",
+ "code": "Code",
+ "success": "✔ Module installé avec succès!",
+ "error": "✘ Erreur, le module est peut-être cassé!",
+ "overwrite": "✘ Erreur, le module a tenté d'écraser le module intégré!",
+ "dependency": "✘ Erreur d'installation des dépendances! {deps}",
+ "docdevs": "Utiliser uniquement les modules des développeurs Heroku officiels lors de la recherche?",
+ "doctheme": "Thème pour les emojis."
+ }
+
+ strings_de = {
+ "_cls_doc": "Modul zur Suche nach Modulen! Verfolgen Sie alle FHeta-Neuigkeiten auf @FHeta_Updates!",
+ "lang": "de",
+ "author": "von",
+ "description": "Beschreibung",
+ "commands": "Befehle",
+ "placeholders": "Platzhalter",
+ "morecommands": "...und {remaining} weitere Befehle.",
+ "moreplaceholders": "...und {remaining} weitere Platzhalter.",
+ "list": "Alle gefundenen Module:",
+ "search": "Suche nach {query}...",
+ "noquery": "Sie haben keine Suchanfrage eingegeben, Beispiel: {prefix}fheta ihre anfrage",
+ "notfound": "Nichts gefunden für Anfrage {query}.",
+ "toolong": "Ihre Anfrage ist zu groß, bitte reduzieren Sie sie auf 168 Zeichen.",
+ "added": "✔ Bewertung hinzugefügt!",
+ "changed": "✔ Bewertung geändert!",
+ "deleted": "✔ Bewertung gelöscht!",
+ "prompt": "Geben Sie eine Suchanfrage ein.",
+ "hint": "Name, Befehl, Beschreibung, Autor.",
+ "retry": "Versuchen Sie eine andere Anfrage.",
+ "query": "Anfrage",
+ "install": "Installieren",
+ "counter": "{idx}/{total}",
+ "code": "Code",
+ "success": "✔ Modul erfolgreich installiert!",
+ "error": "✘ Fehler, vielleicht ist das Modul kaputt!",
+ "overwrite": "✘ Fehler, Modul hat versucht, das integrierte Modul zu überschreiben!",
+ "dependency": "✘ Fehler bei der Installation von Abhängigkeiten! {deps}",
+ "docdevs": "Nur Module von offiziellen Heroku-Entwicklern bei der Suche verwenden?",
+ "doctheme": "Thema für Emojis."
+ }
+
+ strings_jp = {
+ "_cls_doc": "モジュール検索用モジュール!@FHeta_UpdatesでFHetaのすべてのニュースをフォローしてください!",
+ "lang": "jp",
+ "author": "作成者",
+ "description": "説明",
+ "commands": "コマンド",
+ "placeholders": "プレースホルダー",
+ "morecommands": "...さらに {remaining} 個のコマンド。",
+ "moreplaceholders": "...さらに {remaining} 個のプレースホルダー。",
+ "list": "見つかったすべてのモジュール:",
+ "search": "{query}を検索中...",
+ "noquery": "検索クエリを入力していません、例: {prefix}fheta あなたのクエリ",
+ "notfound": "クエリ{query}で何も見つかりませんでした。",
+ "toolong": "クエリが大きすぎます。168文字に短縮してください。",
+ "added": "✔ 評価が追加されました!",
+ "changed": "✔ 評価が変更されました!",
+ "deleted": "✔ 評価が削除されました!",
+ "prompt": "検索するクエリを入力してください。",
+ "hint": "名前、コマンド、説明、作成者。",
+ "retry": "別のクエリを試してください。",
+ "query": "クエリ",
+ "install": "インストール",
+ "counter": "{idx}/{total}",
+ "code": "コード",
+ "success": "✔ モジュールが正常にインストールされました!",
+ "error": "✘ エラー、モジュールが壊れている可能性があります!",
+ "overwrite": "✘ エラー、モジュールが組み込みモジュールを上書きしようとしました!",
+ "dependency": "✘ 依存関係のインストールエラー! {deps}",
+ "docdevs": "検索時に公式Heroku開発者のモジュールのみを使用しますか?",
+ "doctheme": "絵文字のテーマ。"
+ }
+
+ THEMES = {
+ "default": {
+ "search": '🔍',
+ "error": '❌',
+ "warn": '⚠️',
+ "description": '📝',
+ "command": '⚙️',
+ "placeholder": '🗒️',
+ "module": '📦',
+ "channel": '📢',
+ "modules_list": '📋'
+ },
+ "winter": {
+ "search": '❄️',
+ "error": '🧊',
+ "warn": '🌨️',
+ "description": '📜',
+ "command": '🎅',
+ "placeholder": '🗒️',
+ "module": '🎁',
+ "channel": '📢',
+ "modules_list": '🎄'
+ },
+ "summer": {
+ "search": '🔍',
+ "error": '🌡️',
+ "warn": '⚠️',
+ "description": '🍹',
+ "command": '🏄',
+ "placeholder": '🗒️',
+ "module": '🏖️',
+ "channel": '📢',
+ "modules_list": '🏖️'
+ },
+ "spring": {
+ "search": '🌱',
+ "error": '🥀',
+ "warn": '⚠️',
+ "description": '🍃',
+ "command": '🦋',
+ "placeholder": '🗒️',
+ "module": '🌿',
+ "channel": '📢',
+ "modules_list": '🌺'
+ },
+ "autumn": {
+ "search": '🍂',
+ "error": '🍁',
+ "warn": '⚠️',
+ "description": '📜',
+ "command": '🍂',
+ "placeholder": '🗒️',
+ "module": '🍄',
+ "channel": '📢',
+ "modules_list": '🍂'
+ }
+ }
+
+ def __init__(self) -> None:
+ self.config = loader.ModuleConfig(
+ loader.ConfigValue(
+ "only_official_developers",
+ False,
+ lambda: self.strings("docdevs"),
+ validator=loader.validators.Boolean()
+ ),
+ loader.ConfigValue(
+ "theme",
+ "default",
+ lambda: self.strings("doctheme"),
+ validator=loader.validators.Choice(["default", "winter", "summer", "spring", "autumn"])
+ )
+ )
+
+ async def on_unload(self) -> None:
+ if hasattr(self, "api") and self.api.session and not self.api.session.closed:
+ await self.api.session.close()
+
+ async def client_ready(self, client: 'telethon.TelegramClient', database: 'loader.Database') -> None:
+ try:
+ await client(UnblockRequest("@FHeta_robot"))
+ await utils.dnd(client, "@FHeta_robot", archive=True)
+ except Exception:
+ pass
+
+ self.identifier = (await client.get_me()).id
+ self.token = database.get("FHeta", "token")
+
+ self.api = FHetaAPI()
+ self.installer = MInstaller()
+ self.ui = FHetaUI(self)
+
+ self.api.token = self.token
+
+ router = None
+ try:
+ frame = sys._getframe()
+ while frame:
+ if 'self' in frame.f_locals and type(frame.f_locals['self']).__name__ == "Modules":
+ router = getattr(frame.f_locals['self'], "inline", None)
+ if router:
+ break
+ frame = frame.f_back
+ except Exception:
+ pass
+
+ router = router or self.inline
+ dispatcher = getattr(router, "_dp", getattr(router, "dp", getattr(router, "router", None)))
+ self.bot = getattr(router, "_bot", getattr(router, "bot", getattr(self.inline, "bot", None)))
+
+ if dispatcher:
+ if not getattr(dispatcher, "_fpatched", False):
+
+ async def fmiddleware(handler: Any, event: Any, data: Any) -> Any:
+ try:
+ module = self.lookup("FHeta")
+
+ if module and getattr(event, "result_id", "").startswith("fh_"):
+ await module.click(event)
+ return None
+ except Exception:
+ pass
+
+ return await handler(event, data)
+
+ try:
+ dispatcher.chosen_inline_result.middleware(fmiddleware)
+ dispatcher._fpatched = True
+ except Exception:
+ pass
+
+ if self.token and not await self.api.fetch("validatetkn", user_id=str(self.identifier)):
+ self.token = None
+ self.api.token = None
+
+ if not self.token:
+ try:
+ async with client.conversation("@FHeta_robot") as conversation:
+ await conversation.send_message('/token')
+ self.token = (await conversation.get_response(timeout=5)).text.strip()
+ database.set("FHeta", "token", self.token)
+ self.api.token = self.token
+ except Exception:
+ pass
+
+ @loader.loop(interval=1, autostart=True)
+ async def sync(self):
+ now = self.strings["lang"]
+ if now != getattr(self, "past_lang", None):
+ await self.api.send("dataset", params={"user_id": getattr(self, "identifier", 0), "lang": now})
+ self.past_lang = now
+
+ async def answer(self, callback: Union[CallbackQuery, ChosenInlineResult], text: Optional[str] = None, alert: bool = False) -> None:
+ try:
+ if text:
+ await callback.answer(text, show_alert=alert)
+ else:
+ await callback.answer()
+ except Exception:
+ pass
+
+ async def edit(self, target: Union[str, ChosenInlineResult, CallbackQuery, Message, 'telethon.types.Message'], text: str, buttons: List[List[Dict[str, Any]]], banner: Optional[str] = None) -> None:
+ try:
+ options = LinkPreviewOptions(url=banner, show_above_text=True, prefer_large_media=True) if banner else LinkPreviewOptions(is_disabled=True)
+ markup = self.inline.generate_markup(buttons)
+
+ if not self.bot:
+ return
+
+ arguments = {
+ "text": text,
+ "reply_markup": markup,
+ "link_preview_options": options,
+ "parse_mode": "HTML"
+ }
+
+ inline = target if isinstance(target, str) else getattr(target, "inline_message_id", None)
+
+ if inline:
+ arguments["inline_message_id"] = inline
+ else:
+ message = getattr(target, "message", target)
+ chat = getattr(getattr(message, "chat", message), "id", getattr(message, "chat_id", None))
+ identifier = getattr(message, "message_id", getattr(message, "id", None))
+
+ if chat and identifier:
+ arguments["chat_id"] = chat
+ arguments["message_id"] = identifier
+ else:
+ return
+
+ await self.bot.edit_message_text(**arguments)
+ except Exception:
+ pass
+
+ async def click(self, callback: ChosenInlineResult) -> None:
+ try:
+ if not getattr(callback, "result_id", "").startswith("fh_"):
+ return
+
+ parts = callback.result_id.split("_")
+ if len(parts) != 3:
+ return
+
+ queryid = parts[1]
+ index = int(parts[2])
+
+ cache = getattr(self.inline, "fheta_cache", {})
+ saved = cache.get(queryid, {})
+ query = saved.get("query", "")
+ modules = saved.get("mods", [])
+
+ if not modules or index >= len(modules):
+ return
+
+ data = modules[index]
+ text = self.ui.format(data, query, index+1, len(modules), True)
+ buttons = self.ui.buttons(data.get("install", ""), data, index, None, query)
+
+ await self.edit(callback, text, buttons, data.get("banner"))
+ except Exception:
+ pass
+
+ async def show(self, callback: Union[CallbackQuery, ChosenInlineResult], index: int, modules: List[Dict[str, Any]], query: str) -> None:
+ await self.answer(callback)
+ text = f"{self.ui.emoji('modules_list')} {self.strings['list']}"
+ await self.edit(callback, text, self.ui.pagination(modules, query, 0, index))
+
+ async def page(self, callback: Union[CallbackQuery, ChosenInlineResult], current: int, modules: List[Dict[str, Any]], query: str, index: int) -> None:
+ await self.answer(callback)
+ text = f"{self.ui.emoji('modules_list')} {self.strings['list']}"
+ await self.edit(callback, text, self.ui.pagination(modules, query, current, index))
+
+ async def navigate(self, callback: Union[CallbackQuery, ChosenInlineResult], index: int, modules: List[Dict[str, Any]], query: str = "") -> None:
+ await self.answer(callback)
+ if 0 <= index < len(modules):
+ data = modules[index]
+ text = self.ui.format(data, query, index + 1, len(modules))
+ buttons = self.ui.buttons(data.get('install', ''), data, index, modules, query)
+ await self.edit(callback, text, buttons, data.get("banner"))
+
+ async def rate(self, callback: Union[CallbackQuery, ChosenInlineResult, Message, 'telethon.types.Message'], link: str, action: str, index: int, modules: Optional[List[Dict[str, Any]]], query: str = "") -> None:
+ response = await self.api.send(f"rate/{self.identifier}/{link}/{action}")
+
+ request = await self.api.send("get", payload=[unquote(link)])
+ stats = request.get(unquote(link), {"likes": 0, "dislikes": 0})
+
+ if modules and index < len(modules):
+ modules[index].update(stats)
+
+ try:
+ await callback.edit(reply_markup=self.ui.buttons(link, stats, index, modules, query))
+ except Exception:
+ pass
+
+ if response and response.get("status"):
+ status = response.get("status")
+ if status == "added":
+ text = self.strings["added"]
+ elif status == "changed":
+ text = self.strings["changed"]
+ elif status == "removed":
+ text = self.strings["deleted"]
+ else:
+ text = ""
+ await self.answer(callback, text, True)
+
+ async def install(self, callback: Union[CallbackQuery, ChosenInlineResult], link: str, index: int, modules: Optional[List[Dict[str, Any]]], query: str = "") -> None:
+ state, dependencies = await self.installer.execute(self.lookup("loader"), link)
+
+ try:
+ if state == "success":
+ await self.answer(callback, self.strings["success"], True)
+ elif state == "dependency":
+ formatted = f"({','.join(dependencies[:5])})" if dependencies else ""
+ await self.answer(callback, self.strings["dependency"].format(deps=formatted), True)
+ elif state == "overwrite":
+ await self.answer(callback, self.strings["overwrite"], True)
+ else:
+ await self.answer(callback, self.strings["error"], True)
+ except Exception:
+ pass
+
+ @loader.inline_handler(
+ ru_doc="(запрос) - поиск модулей.",
+ ua_doc="(запит) - пошук модулів.",
+ kz_doc="(сұрау) - модульдерді іздеу.",
+ uz_doc="(so'rov) - modullarni qidirish.",
+ fr_doc="(requête) - rechercher des modules.",
+ de_doc="(anfrage) - module suchen.",
+ jp_doc="(クエリ) - モジュールを検索します。"
+ )
+ async def fheta(self, event: 'loader.InlineCall') -> Union[Dict[str, str], None]:
+ '''(query) - search modules.'''
+ query = event.args
+
+ if not query:
+ return {
+ "title": self.strings["prompt"],
+ "description": self.strings["hint"],
+ "message": f"{self.ui.emoji('error')} {self.strings['prompt']}",
+ "thumb": "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/magnifying_glass.png"
+ }
+
+ if len(query) > 168:
+ return {
+ "title": self.strings["toolong"],
+ "description": self.strings["retry"],
+ "message": f"{self.ui.emoji('warn')} {self.strings['toolong']}",
+ "thumb": "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/try_other_query.png"
+ }
+
+ modules = await self.api.fetch("search", query=query, inline="true", token=self.token, user_id=self.identifier, ood=str(self.config["only_official_developers"]).lower())
+
+ if not modules or not isinstance(modules, list):
+ return {
+ "title": self.strings["retry"],
+ "description": self.strings["hint"],
+ "message": f"{self.ui.emoji('error')} {self.strings['notfound'].format(query=utils.escape_html(query))}",
+ "thumb": "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/try_other_query.png"
+ }
+
+ queryid = str(uuid.uuid4())[:8]
+ if not hasattr(self.inline, "fheta_cache"):
+ self.inline.fheta_cache = {}
+
+ if len(self.inline.fheta_cache) >= 50:
+ self.inline.fheta_cache.pop(next(iter(self.inline.fheta_cache)))
+
+ self.inline.fheta_cache[queryid] = {"query": query, "mods": modules}
+
+ results = []
+
+ for index, data in enumerate(modules[:50]):
+ description = data.get("description", "")
+ if isinstance(description, dict):
+ description = description.get(self.strings["lang"]) or description.get("doc") or next(iter(description.values()), "")
+
+ markup = None
+ try:
+ markup = self.inline.generate_markup(self.ui.buttons(data.get("install", ""), data, index, None, query))
+ except Exception:
+ pass
+
+ results.append(InlineQueryResultArticle(
+ id=f"fh_{queryid}_{index}",
+ title=utils.escape_html(data.get("name", "")),
+ description=utils.escape_html(str(description)[:250] + ("..." if len(str(description)) > 250 else "")),
+ thumbnail_url=data.get("pic") or "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/FHeta/empty_pic.png",
+ input_message_content=InputTextMessageContent(message_text="ㅤ", parse_mode="HTML"),
+ reply_markup=markup
+ ))
+
+ await event.inline_query.answer(results, cache_time=0)
+
+ @loader.command(
+ ru_doc="(запрос) - поиск модулей.",
+ ua_doc="(запит) - пошук модулів.",
+ kz_doc="(сұрау) - модульдерді іздеу.",
+ uz_doc="(so'rov) - modullarni qidirish.",
+ fr_doc="(requête) - rechercher des modules.",
+ de_doc="(anfrage) - module suchen.",
+ jp_doc="(クエリ) - モジュールを検索します。"
+ )
+ async def fhetacmd(self, message: 'telethon.types.Message') -> Any:
+ '''(query) - search modules.'''
+ query = utils.get_args_raw(message)
+
+ if not query:
+ return await utils.answer(message, f"{self.ui.emoji('error')} {self.strings['noquery'].format(prefix=self.get_prefix())}")
+
+ if len(query) > 168:
+ return await utils.answer(message, f"{self.ui.emoji('warn')} {self.strings['toolong']}")
+
+ message = await utils.answer(message, f"{self.ui.emoji('search')} {self.strings['search'].format(query=utils.escape_html(query))}")
+
+ modules = await self.api.fetch("search", query=query, inline="false", token=self.token, user_id=self.identifier, ood=str(self.config["only_official_developers"]).lower())
+
+ if not modules or not isinstance(modules, list):
+ return await utils.answer(message, f"{self.ui.emoji('error')} {self.strings['notfound'].format(query=utils.escape_html(query))}")
+
+ data = modules[0]
+ buttons = self.ui.buttons(data.get("install", ""), data, 0, modules, query)
+ form = await self.inline.form("ㅤ", message, reply_markup=buttons, silent=True)
+ text = self.ui.format(data, query, 1, len(modules))
+
+ await self.edit(form, text, buttons, data.get("banner"))
+
+ @loader.watcher(chat_id=7575472403)
+ async def watcher(self, message: 'telethon.types.Message') -> None:
+ url = message.raw_text.strip()
+
+ if not url.startswith("https://api.fixyres.com/module/"):
+ return
+
+ try:
+ state, dependencies = await self.installer.execute(self.lookup("loader"), url)
+
+ if state == "success":
+ reply = await message.respond("✅")
+ elif state == "dependency":
+ reply = await message.respond(f"📋{','.join(dependencies[:5])}" if dependencies else "📋")
+ elif state == "overwrite":
+ reply = await message.respond("😨")
+ else:
+ reply = await message.respond("❌")
+
+ await asyncio.sleep(1)
+ await reply.delete()
+ await message.delete()
+ except Exception:
+ pass
diff --git a/Fixyres/FModules/LICENSE b/Fixyres/FModules/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/Fixyres/FModules/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Fixyres/FModules/README.md b/Fixyres/FModules/README.md
new file mode 100644
index 0000000..f071c12
--- /dev/null
+++ b/Fixyres/FModules/README.md
@@ -0,0 +1 @@
+My modules for Heroku userbot, telegram channel: https://t.me/FModules
diff --git a/Fixyres/FModules/SCD.py b/Fixyres/FModules/SCD.py
new file mode 100644
index 0000000..7b3a48b
--- /dev/null
+++ b/Fixyres/FModules/SCD.py
@@ -0,0 +1,197 @@
+__version__ = (1, 0, 0)
+
+# ©️ Fixyres, 2026-2030
+# 🌐 https://github.com/Fixyres/FModules
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 🔑 http://www.apache.org/licenses/LICENSE-2.0
+
+# meta banner: https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/SCD/banner.png
+# meta developer: @FModules
+
+# requires: curl_cffi
+
+import io
+import re
+import json
+from telethon.tl.types import DocumentAttributeAudio
+from curl_cffi import requests
+from .. import loader, utils
+
+
+@loader.tds
+class SCD(loader.Module):
+ '''Module for downloading songs from SoundCloud.'''
+
+ _client_id = None
+
+ strings = {
+ "name": "SCD",
+ "_cls_doc": "Module for downloading songs from SoundCloud.",
+ "no_args": "✘ You didn't provide a link to the song, example of using the command: {prefix}sc (link)",
+ "downloading": "↓ Downloading...",
+ "not_found": "✘ Song not found."
+ }
+
+ strings_ru = {
+ "_cls_doc": "Модуль для скачивания песен с SoundCloud.",
+ "no_args": "✘ Вы не указали ссылку на песню, пример использования команды: {prefix}sc (ссылка)",
+ "downloading": "↓ Скачивание...",
+ "not_found": "✘ Песня не найдена."
+ }
+
+ strings_ua = {
+ "_cls_doc": "Модуль для завантаження пісень із SoundCloud.",
+ "no_args": "✘ Ви не вказали посилання на пісню, приклад використання команди: {prefix}sc (посилання)",
+ "downloading": "↓ Завантаження...",
+ "not_found": "✘ Пісню не знайдено."
+ }
+
+ strings_de = {
+ "_cls_doc": "Modul zum Herunterladen von Liedern von SoundCloud.",
+ "no_args": "✘ Sie haben keinen Link zum Lied angegeben, Anwendungsbeispiel des Befehls: {prefix}sc (Link)",
+ "downloading": "↓ Wird heruntergeladen...",
+ "not_found": "✘ Lied nicht gefunden."
+ }
+
+ strings_uz = {
+ "_cls_doc": "SoundCloud-dan qo'shiqlarni yuklab olish uchun modul.",
+ "no_args": "✘ Siz qo'shiq havolasini kiritmadingiz, buyruqdan foydalanish misoli: {prefix}sc (havola)",
+ "downloading": "↓ Yuklab olinmoqda...",
+ "not_found": "✘ Qo'shiq topilmadi."
+ }
+
+ strings_kz = {
+ "_cls_doc": "SoundCloud-тан әндерді жүктеп алуға арналған модуль.",
+ "no_args": "✘ Сіз әнге сілтеме көрсетпедіңіз, бұйрықты пайдалану мысалы: {prefix}sc (сілтеме)",
+ "downloading": "↓ Жүктелуде...",
+ "not_found": "✘ Ән табылмады."
+ }
+
+ strings_fr = {
+ "_cls_doc": "Module pour télécharger des chansons depuis SoundCloud.",
+ "no_args": "✘ Vous n'avez pas fourni de lien vers la chanson, exemple d'utilisation de la commande: {prefix}sc (lien)",
+ "downloading": "↓ Téléchargement...",
+ "not_found": "✘ Chanson non trouvée."
+ }
+
+ strings_jp = {
+ "_cls_doc": "SoundCloudから曲をダウンロードするためのモジュール。",
+ "no_args": "✘ 曲へのリンクが指定されていません。コマンドの使用例: {prefix}sc (リンク)",
+ "downloading": "↓ ダウンロード中...",
+ "not_found": "✘ 曲が見つかりません。"
+ }
+
+ async def _get_client_id(self, ses, html):
+ if self._client_id:
+ return self._client_id
+ for scr in reversed(re.findall(r'src="(https://a-v2\.sndcdn\.com/assets/[^"]+\.js)"', html)):
+ m = re.search(r'client_id:"([a-zA-Z0-9]{32})"', (await ses.get(scr)).text)
+ if m:
+ self._client_id = m.group(1)
+ return self._client_id
+ raise ValueError()
+
+ @loader.command(
+ ru_doc="(ссылка) - скачать песню с SoundCloud.",
+ ua_doc="(посилання) - завантажити пісню з SoundCloud.",
+ de_doc="(Link) - laden Sie ein Lied von SoundCloud herunter.",
+ uz_doc="(havola) - SoundCloud-dan qo'shiq yuklab olish.",
+ kz_doc="(сілтеме) - SoundCloud-тан әнді жүктеп алу.",
+ fr_doc="(lien) - télécharger une chanson depuis SoundCloud.",
+ jp_doc="(リンク) - SoundCloudから曲をダウンロードします。"
+ )
+ async def scd(self, message):
+ '''(link) - download a song from SoundCloud.'''
+ args = utils.get_args_raw(message)
+ if not args:
+ await utils.answer(message, self.strings("no_args").format(prefix=self.get_prefix()))
+ return
+
+ m = re.search(r"(https?://(?:[a-zA-Z0-9-]+\.)?soundcloud\.com/[^\s]+)", args)
+ if not m:
+ await utils.answer(message, self.strings("not_found"))
+ return
+
+ msg = await utils.answer(message, self.strings("downloading"))
+
+ try:
+ async with requests.AsyncSession(impersonate="chrome120") as ses:
+ h_resp = await ses.get(m.group(1))
+ if h_resp.status_code != 200:
+ raise ValueError()
+
+ html = h_resp.text
+ c_id = await self._get_client_id(ses, html)
+
+ h_m = re.search(r'window\.__sc_hydration\s*=\s*(\[.*?\]);', html)
+ if not h_m:
+ raise ValueError()
+
+ t_d = next((i.get("data") for i in json.loads(h_m.group(1)) if i.get("hydratable") == "sound"), None)
+ if not t_d or t_d.get('kind') != 'track':
+ raise ValueError()
+
+ art = t_d.get("artwork_url") or t_d.get("user", {}).get("avatar_url")
+ if art:
+ art = art.replace("-large.jpg", "-t500x500.jpg")
+
+ tr = t_d.get("media", {}).get("transcodings", [])
+ if not tr:
+ raise ValueError()
+
+ s_info = next((t for t in tr if t.get("format", {}).get("protocol") == "progressive"), tr[0])
+ s_url = s_info.get("url") + f"?client_id={c_id}" + (f"&track_authorization={t_d.get('track_authorization')}" if t_d.get("track_authorization") else "")
+
+ s_resp = await ses.get(s_url)
+ if s_resp.status_code != 200 or not s_resp.json().get("url"):
+ raise ValueError()
+
+ a_buf = io.BytesIO()
+ a_buf.name = "track.mp3"
+
+ if s_info.get("format", {}).get("protocol") == "progressive":
+ m_resp = await ses.get(s_resp.json().get("url"))
+ if m_resp.status_code != 200:
+ raise ValueError()
+ a_buf.write(m_resp.content)
+ else:
+ m3_resp = await ses.get(s_resp.json().get("url"))
+ if m3_resp.status_code != 200:
+ raise ValueError()
+ chk = [l for l in m3_resp.text.splitlines() if l and not l.startswith('#')]
+ if not chk:
+ raise ValueError()
+ for c_u in chk:
+ c_r = await ses.get(c_u)
+ if c_r.status_code != 200:
+ raise ValueError()
+ a_buf.write(c_r.content)
+
+ a_buf.seek(0)
+
+ t_buf = None
+ if art:
+ try:
+ a_r = await ses.get(art)
+ if a_r.status_code == 200:
+ t_buf = io.BytesIO(a_r.content)
+ t_buf.name = "cover.jpg"
+ except:
+ pass
+
+ await message.client.send_file(
+ message.peer_id,
+ a_buf,
+ thumb=t_buf,
+ attributes=[DocumentAttributeAudio(
+ duration=t_d.get("duration", 0) // 1000,
+ title=t_d.get("title", "Unknown"),
+ performer=t_d.get("user", {}).get("username", "Unknown Artist")
+ )],
+ reply_to=message.reply_to_msg_id
+ )
+ await msg.delete()
+
+ except:
+ await utils.answer(msg, self.strings("not_found"))
diff --git a/Fixyres/FModules/akinator.py b/Fixyres/FModules/akinator.py
new file mode 100644
index 0000000..3aa0caf
--- /dev/null
+++ b/Fixyres/FModules/akinator.py
@@ -0,0 +1,456 @@
+__version__ = (1, 1, 0)
+
+# ©️ Fixyres, 2026-2030
+# 🌐 https://github.com/Fixyres/FModules
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 🔑 http://www.apache.org/licenses/LICENSE-2.0
+
+# meta banner: https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/akinator/banner.png
+# meta developer: @FModules
+# meta fhsdesc: game, funny, guess, question game
+
+# requires: curl_cffi
+
+import html
+import re
+import inspect
+from curl_cffi import requests
+from .. import loader, utils
+from telethon.tl.functions.messages import TranslateTextRequest
+from telethon.tl.types import TextWithEntities
+
+
+class AsyncAki:
+ def __init__(self, lang="en", cm=False):
+ self.user_lang = lang
+ aki_langs =[
+ "en", "ar", "cn", "de", "es", "fr", "il", "it",
+ "jp", "kr", "nl", "pl", "pt", "ru", "tr", "id"
+ ]
+
+ if lang in aki_langs:
+ self.aki_lang = lang
+ elif lang in ["uk", "uz", "kk", "be"]:
+ self.aki_lang = "ru"
+ else:
+ self.aki_lang = "en"
+
+ self.cm = str(cm).lower()
+ self.uri = f"https://{self.aki_lang}.akinator.com"
+
+ self.session = requests.AsyncSession(impersonate="chrome120")
+ self.session.headers.update({
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
+ "Accept-Language": "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7",
+ "Sec-Fetch-Dest": "document",
+ "Sec-Fetch-Mode": "navigate",
+ "Sec-Fetch-Site": "none",
+ "Sec-Fetch-User": "?1",
+ "Upgrade-Insecure-Requests": "1"
+ })
+
+ self.win = False
+ self.prog = "0.0"
+ self.step = "0"
+ self.slp = ""
+ self.name = None
+ self.desc = ""
+ self.photo = "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/akinator/banner.png"
+ self.q = ""
+
+ async def _req(self, ep, data=None):
+ method = "POST" if data else "GET"
+ url = f"{self.uri}/{ep}"
+
+ headers = {}
+ if data:
+ headers["x-requested-with"] = "XMLHttpRequest"
+ headers["Content-Type"] = "application/x-www-form-urlencoded"
+
+ r = await self.session.request(method, url, data=data, headers=headers)
+
+ if r.status_code != 200:
+ raise Exception(f"AE{r.status_code}")
+
+ try:
+ return r.json()
+ except Exception:
+ return r.text
+
+ async def start(self):
+ t = await self._req("game", {"sid": 1, "cm": self.cm})
+
+ if "technical problem" in (t if isinstance(t, str) else "").lower():
+ raise Exception("ATP")
+
+ ses_m = re.search(r"session['\"]\)\.val\(['\"](.+?)['\"]", t if isinstance(t, str) else str(t))
+ sig_m = re.search(r"signature['\"]\)\.val\(['\"](.+?)['\"]", t if isinstance(t, str) else str(t))
+ q_m = re.search(r'class="question-text".*?>(.+?)
', t if isinstance(t, str) else str(t), re.S)
+
+ if not ses_m or not sig_m or not q_m:
+ raise Exception("AECF")
+
+ self.ses = ses_m.group(1)
+ self.sig = sig_m.group(1)
+ self.q = html.unescape(q_m.group(1)).strip()
+
+ async def answer(self, a):
+ data = {
+ "step": self.step, "progression": self.prog, "sid": 1,
+ "cm": self.cm, "answer": a, "step_last_proposition": self.slp,
+ "session": self.ses, "signature": self.sig
+ }
+ res = await self._req("answer", data)
+ self._upd(res)
+
+ async def exclude(self):
+ data = {
+ "step": self.step, "progression": self.prog, "sid": 1,
+ "cm": self.cm, "session": self.ses, "signature": self.sig,
+ "forward_answer": "1"
+ }
+ try:
+ res = await self._req("exclude", data)
+
+ if isinstance(res, dict) and res.get("question"):
+ self.win = False
+ self.name = None
+ self._upd(res)
+ else:
+ self.win = False
+ self.name = None
+ self.q = None
+ except Exception:
+ self.win, self.name, self.q = False, None, None
+
+ def _upd(self, d):
+ if not isinstance(d, dict):
+ return
+
+ if d.get("id_proposition"):
+ self.win = True
+ self.name = html.unescape(d.get("name_proposition", ""))
+ self.desc = html.unescape(d.get("description_proposition", ""))
+ self.photo = d.get("photo", "https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/akinator/banner.png")
+
+ self.step = str(d.get("step", self.step))
+ self.slp = self.step
+
+ if "progression" in d and d["progression"] is not None:
+ self.prog = str(d["progression"])
+
+ elif d.get("question"):
+ self.win = False
+ self.q = html.unescape(d.get("question", ""))
+ self.prog = str(d.get("progression", "0"))
+ self.step = str(d.get("step", "0"))
+ self.slp = str(d.get("step_last_proposition", self.slp))
+ else:
+ self.win = False
+ self.name = None
+ self.q = None
+
+ async def close(self):
+ try:
+ if inspect.iscoroutinefunction(self.session.close):
+ await self.session.close()
+ else:
+ res = self.session.close()
+ if inspect.isawaitable(res):
+ await res
+ except Exception:
+ pass
+
+
+@loader.tds
+class Akinator(loader.Module):
+ '''Akinator will guess any character you have in mind, you just need to answer a couple of questions.'''
+
+ strings = {
+ "name": "Akinator",
+ "lang": "en",
+ "child_mode": "Child mode. If enabled, it will be easier to guess 18+ heroes.",
+ "start": "Start",
+ "text": "Guess any character you have in mind, and click on the Start button.",
+ "yes": "Yes",
+ "no": "No",
+ "idk": "I don't know",
+ "probably": "Probably",
+ "probably_not": "Probably not",
+ "this_is": "This is {name}\n{description}",
+ "this_is_no_desc": "This is {name}",
+ "not_right": "Not right",
+ "failed": "Failed to guess the character."
+ }
+
+ strings_ru = {
+ "lang": "ru",
+ "_cls_doc": "Акинатор угадает любого вами загаданного персонажа.",
+ "child_mode": "Детский режим. Сложнее отгадать 18+ героев.",
+ "start": "Начать",
+ "text": "Задумайте персонажа, и нажмите начать.",
+ "yes": "Да",
+ "no": "Нет",
+ "idk": "Не знаю",
+ "probably": "Возможно",
+ "probably_not": "Скорее нет",
+ "this_is": "Это {name}\n{description}",
+ "this_is_no_desc": "Это {name}",
+ "not_right": "Это не он",
+ "failed": "Не удалось угадать персонажа."
+ }
+
+ strings_ua = {
+ "lang": "uk",
+ "_cls_doc": "Акінатор вгадає будь-якого персонажа.",
+ "child_mode": "Дитячий режим. Складніше відгадати 18+ героїв.",
+ "start": "Почати",
+ "text": "Загадайте персонажа, і натисніть почати.",
+ "yes": "Так",
+ "no": "Ні",
+ "idk": "Не знаю",
+ "probably": "Можливо",
+ "probably_not": "Швидше ні",
+ "this_is": "Це {name}\n{description}",
+ "this_is_no_desc": "Це {name}",
+ "not_right": "Це не він",
+ "failed": "Не вдалося вгадати персонажа."
+ }
+
+ strings_de = {
+ "lang": "de",
+ "_cls_doc": "Akinator errät jeden Charakter, den du dir vorstellst.",
+ "child_mode": "Kindermodus. Wenn aktiviert, wird es schwieriger sein, 18+ Helden zu erraten.",
+ "start": "Start",
+ "text": "Denk dir einen Charakter aus und klicke auf Start.",
+ "yes": "Ja",
+ "no": "Nein",
+ "idk": "Ich weiß nicht",
+ "probably": "Wahrscheinlich",
+ "probably_not": "Wahrscheinlich nicht",
+ "this_is": "Das ist {name}\n{description}",
+ "this_is_no_desc": "Das ist {name}",
+ "not_right": "Das ist er nicht",
+ "failed": "Charakter konnte nicht erraten werden."
+ }
+
+ strings_fr = {
+ "lang": "fr",
+ "_cls_doc": "Akinator devinera n'importe quel personnage.",
+ "child_mode": "Mode enfant. Héros 18+ plus difficiles à deviner.",
+ "start": "Commencer",
+ "text": "Pensez à un personnage et cliquez sur Commencer.",
+ "yes": "Oui",
+ "no": "Non",
+ "idk": "Je ne sais pas",
+ "probably": "Probablement",
+ "probably_not": "Probablement pas",
+ "this_is": "C'est {name}\n{description}",
+ "this_is_no_desc": "C'est {name}",
+ "not_right": "Ce n'est pas lui",
+ "failed": "Impossible de deviner."
+ }
+
+ strings_jp = {
+ "lang": "ja",
+ "_cls_doc": "アキネーターはあなたが考えているキャラクターを当てます。",
+ "child_mode": "子供モード。有効にすると、18歳以上のキャラクターを推測するのが難しくなります。",
+ "start": "開始",
+ "text": "キャラクターを思い浮かべて開始。",
+ "yes": "はい",
+ "no": "いいえ",
+ "idk": "わかりません",
+ "probably": "おそらく",
+ "probably_not": "おそらく違う",
+ "this_is": "これは {name}\n{description}",
+ "this_is_no_desc": "これは {name}",
+ "not_right": "違います",
+ "failed": "推測できませんでした。"
+ }
+
+ strings_uz = {
+ "lang": "uz",
+ "_cls_doc": "Akinator siz o'ylagan har qanday qahramonni topadi.",
+ "child_mode": "Bolalar rejimi. Yoqilgan bo'lsa, 18+ qahramonlarni topish qiyinroq bo'ladi.",
+ "start": "Boshlash",
+ "text": "Qahramonni o'ylang va Boshlash tugmasini bosing.",
+ "yes": "Ha",
+ "no": "Yo'q",
+ "idk": "Bilmayman",
+ "probably": "Ehtimol",
+ "probably_not": "Ehtimol yo'q",
+ "this_is": "Bu {name}\n{description}",
+ "this_is_no_desc": "Bu {name}",
+ "not_right": "Bu u emas",
+ "failed": "Qahramonni topib bo'lmadi."
+ }
+
+ strings_kz = {
+ "lang": "kk",
+ "_cls_doc": "Акинатор сіз ойлаған кез келген кейіпкерді табады.",
+ "child_mode": "Балалар режимі. Қосылған болса, 18+ кейіпкерлерді табу қиынырақ болады.",
+ "start": "Бастау",
+ "text": "Кейіпкерді ойлаңыз және Бастау түймесін басыңыз.",
+ "yes": "Иә",
+ "no": "Жоқ",
+ "idk": "Білмеймін",
+ "probably": "Мүмкін",
+ "probably_not": "Мүмкін емес",
+ "this_is": "Бұл {name}\n{description}",
+ "this_is_no_desc": "Бұл {name}",
+ "not_right": "Бұл ол емес",
+ "failed": "Кейіпкерді таба алмадық."
+ }
+
+ def __init__(self):
+ self.config = loader.ModuleConfig(
+ loader.ConfigValue(
+ "child_mode",
+ False,
+ lambda: self.strings("child_mode"),
+ validator=loader.validators.Boolean()
+ )
+ )
+ self.games = {}
+
+ async def _tr(self, client, text, to_lang):
+ if not text:
+ return text
+ try:
+ request = TranslateTextRequest(
+ to_lang=to_lang,
+ text=[TextWithEntities(text=text, entities=[])]
+ )
+ result = await client(request)
+ return result.result[0].text
+ except Exception:
+ return text
+
+ @loader.command(
+ ru_doc="- начать игру.",
+ ua_doc="- почати гру.",
+ de_doc="- Spiel starten.",
+ fr_doc="- commencer le jeu.",
+ jp_doc="- ゲームを開始します。",
+ uz_doc="- o'yinni boshlash.",
+ kz_doc="- ойынды бастау.",
+ )
+ async def akinator(self, message):
+ '''- start the game.'''
+ try:
+ aki = AsyncAki(self.strings("lang"), self.config["child_mode"])
+ await aki.start()
+
+ self.games.setdefault(message.chat_id, {})[message.id] = aki
+
+ await self.inline.form(
+ text=self.strings("text"),
+ message=message,
+ photo="https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/akinator/banner.png",
+ reply_markup={
+ "text": self.strings("start"),
+ "callback": self._cb,
+ "args": (message,)
+ }
+ )
+ except Exception as e:
+ await utils.answer(message, f"{e}")
+
+ async def _cb(self, call, message):
+ aki = self.games.get(message.chat_id, {}).get(message.id)
+ if aki:
+ await self._sq(call, aki, message)
+
+ async def _sq(self, call, aki, message):
+ if aki.aki_lang != aki.user_lang:
+ question = await self._tr(message.client, aki.q, aki.user_lang)
+ else:
+ question = aki.q
+
+ markup = [[
+ {"text": self.strings("yes"), "callback": self._ans, "args": (0, message)},
+ {"text": self.strings("no"), "callback": self._ans, "args": (1, message)},
+ {"text": self.strings("idk"), "callback": self._ans, "args": (2, message)}
+ ],[
+ {"text": self.strings("probably"), "callback": self._ans, "args": (3, message)},
+ {"text": self.strings("probably_not"), "callback": self._ans, "args": (4, message)}
+ ]
+ ]
+
+ await call.edit(
+ f"{question}",
+ photo="https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/akinator/banner.png",
+ reply_markup=markup
+ )
+
+ async def _show_guess(self, call, aki, message):
+ if aki.aki_lang != aki.user_lang:
+ name = await self._tr(message.client, aki.name, aki.user_lang)
+ desc = await self._tr(message.client, aki.desc, aki.user_lang) if aki.desc else aki.desc
+ else:
+ name = aki.name
+ desc = aki.desc
+
+ if desc:
+ text = self.strings("this_is").format(name=name, description=desc)
+ else:
+ text = self.strings("this_is_no_desc").format(name=name)
+
+ markup = [[
+ {"text": self.strings("yes"), "callback": self._fin, "args": (True, message, text, aki.photo)},
+ {"text": self.strings("not_right"), "callback": self._rej, "args": (message,)}
+ ]
+ ]
+
+ await call.edit(
+ text,
+ photo=aki.photo,
+ reply_markup=markup
+ )
+
+ async def _ans(self, call, answer_id, message):
+ aki = self.games.get(message.chat_id, {}).get(message.id)
+ if not aki:
+ return
+
+ await aki.answer(answer_id)
+
+ if aki.win:
+ await self._show_guess(call, aki, message)
+ elif getattr(aki, 'q', None):
+ await self._sq(call, aki, message)
+ else:
+ await self._fin(call, False, message, "", "")
+
+ async def _rej(self, call, message):
+ aki = self.games.get(message.chat_id, {}).get(message.id)
+ if not aki:
+ return
+
+ try:
+ await aki.exclude()
+ except Exception:
+ pass
+
+ if aki.win:
+ await self._show_guess(call, aki, message)
+ elif getattr(aki, 'q', None):
+ await self._sq(call, aki, message)
+ else:
+ await self._fin(call, False, message, "", "")
+
+ async def _fin(self, call, won, message, text, photo):
+ aki = self.games.get(message.chat_id, {}).pop(message.id, None)
+
+ if aki:
+ await aki.close()
+
+ if won:
+ await call.edit(text, photo=photo, reply_markup=[])
+ else:
+ await call.edit(
+ self.strings("failed"),
+ photo="https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/akinator/idk.png",
+ reply_markup=[]
+ )
diff --git a/Fixyres/FModules/assets/BSR/banner.png b/Fixyres/FModules/assets/BSR/banner.png
new file mode 100644
index 0000000000000000000000000000000000000000..49ea6fd75f371abf759a3eff2dc87e6b48bfd23a
GIT binary patch
literal 196853
zcmeFa2UL{1*6=?Jy>}@J3NCoEEEA1L^}Tm29J7<_dVyHdwjqDx4z3-EGBvKBs6nXe!Y{qdw65w`Le~S%xDo>>U18qV%oXol-kaK&4n4K
zUJCu&AZ-9U$&meE^kpD-B8>fHRQsxTdiAZ2$FfTabe}%O7W^}yk2l;b>PKQ
z8;lq3+>?|wF_}c_Z9U!ETiv?bG#M}vBjJc`x){_YThVPfd}=8%jeDVFnL;K+W=@jv
zj7jdZmc&fX3q@(3jSX%O0-D+DnyWrqtUTI$;vKvcIC|_0Q*v3Vu4Y$}ez|Oxq^x1`
zJ=+@5WyHiavSIzsTN~T&E(RPQcwZdyZ08mv{gKi8RH;tO@>>FvIcnW;&bv`N%L2%g
zA(z-2b0nSiKyQ_$@7{bI=W@J7)*>wN>GIg)()f0TXiuDa8ji89jTZ$*KI6$}8;{fw
ztoNK(fPI$gj_=7BFsZJ6HV_*#Xwh8nXKv}#{dsS^t#0_D)5<-s#Y9I-0hye2P085^4VXy!Ofx(|$?1G4mnngxgWd`2!~N02-=e;SGZ
zoJl;#vBa_|{(9WPVkg^Z*MeI1%CWPLy$6He&7HDav@<0;UEj!#Z!
z7j?ayxuNE{c*^8mKPnz=p5Bynx7atq!)8w80_)9MRYhmi*u3LSp7x5=
zpIcJ_FDLulSbRxdOtUh2I(zu-Dy`6!iFuqGWNfsWBVA8XYU2xI3}H=3X3INcCC(>D
zBWDYT9)C1{p_0B3QF#(Ls*>`aV%LMJhP6Pz
zT6D`~$e3m0NW>GHYVP7_2bp(|#IMs8+(wNy_O59dpXO^Xmb&O^K|VlmW0NYX8C?8C
zvFqBMZ0nW))ukZRr~0>Dq&L0pT}y2A2K7j!zhG}=nDxm~RYBxK%oNm&j<()p4*QfX
z26p!x!a9NDVmDQ!*&~V4ygPmrMbP|$;-yk}Q6ecWND0bvIpQTx|4U!GHQUIw`B@*V
zxb*rx?N{KDI=|-uokKTMV>i*q!-%5Sa8_taE#}Das9WKd~d-2p(
zQ%BFH7oN5Cbyeh*ge)k-^J&IxuHmeYIsMQ1P6(Wd`S-g&OjYb~%|T=UHP
zu<;XJXkW4c=k6{~b?M}|M2Riii+6;a=JV0&jHAMzJlt4HFMLw7%khaxB8~Nn-E{PY
z&tHF^uSET&Ho!E}#*jWZ>rGPm`>Kd5N8jX_Bt)|fDTCiVD7g3>)$x+VSnQ=N#o6M=
z-KXp1PxUnwsWA->LA>;)-J|%Ay(laVXbl5v(3~@6M?L``FB~-_Pcg1)T&P#Nnp`W#
znqDXwV-wP>+(?mvb8^J%6^t?@czE*G`(O|*Ns`AcR~
zu}j=`2@j3Ch^;AyCLL3h>n;ohGn6-(SV#;pNntj{hC;9n6nS)q|Z_m8@(BqX=!MruNt}MP?Fch;K)gHY+mT
z4ld#`$h)O!nrdecyEC=RNqkRW3AgJt)Q(a&tq4zjM%8b6^T*;In-n%=$@fV+#jObi7l}Vg7fGEP;Mo5Zk90?P_|j#RchKJ!Tej?2r}
z|8CPwaGhPpZTKvalsnd^^Uao!5NxUVrmdS4;I2n;MyrbtyC7l;XOD{9>`T_VPoO3E
zAeSlAr#m>1cG?YAB4=#K{aj;!9LDwnkt`5Q=|4*mpoHz$)({s-ARO@;^jQU7!f>TO
z`q|yGwMWWGMR@enDw#8}@Xm0(9xcn*nv$Aig(Pf+y=lW&N__IYM?E8#m6JhNHT;?J
zpGSpsMa}1j=(*$DMM4mi<*bF^!MWkY3;6-*Bb_m*vMIVVb|H=wBI9*$s|`AIjvgV+
z$0=94ca~;tJ!am;@Fm~Mj+$zBO87$h$G2v_ZWl4u)UA`uer5=t%ml@%*o
zI+6yuSh@zKgxjBQ+uB*0w62C*UkOKL9sPn-<%d2rw7O|W=6VycwMmp|NJv^-G;$KD
z&t5ha&UZWNzM|3x*+rS`r1K{_wA(gX$l=epTUZm*
zZjCw9P@d&}C
z3+?$I=V$qnz{3OXVz1u~`YhJh&IaYtS&?0Xk}@vRj#Ivl*kH4cx{i+atT
zPSL3yAGqB^L1lF8!Udl}rj<*L&Jx@{V?^{M@>9%->NRE(o*Q122Jkt^
zKs7MS3yOLEw5$=Foy5B6bepgP*O7Tybuy{_q3t@!1HolkVtu0<9~2RcxBahpy&J?$
z>E#YPnekFmvfzsh-!;?QX7um-Y;d$Yj)Qr*EZ6WU9=!F(D(>f5(oGUd!xlbiHtXQV
zwy9B9uizFDIICX!)Qy;pQo=;+ELt$|=q@2%yaiovO3`FgOn$M$jVJdTAj`ag)A5|=
zgAsjH6jC?iYw3=|JgSHMX$m5z!?aIcOT3Lt<(`TrbbX76m>^*XKV{;3kT>`gkJ~M1
z-7uE=BOkqb@~jmR=_wP*Ytu@46lJnO*YT7mg&j1bU6NWo$se+O+#=&VTIyp~DxstG
z5kg8+`bdND@mZIf1z+O&KXCDhaUP>vRFC;YIBx!mpe_3{Pg{g1ESyVT%J2O2ZG3i+
zVK@OLOYRKq3>~?gYW)!YZBLKT&HFl#xbpjMjDl|*j<<+jIFUv?i*ds8lvr1
zxZH-RI1TgFix=>a5n(&f0XD%SRanog21CvJ@Crin`&&L1g>i}D6se2d>^V!}JeKyd
z<@TO3JXiTW_%ajg1*Tau?TqD~V}4OldShKv!%O|5hBvU6sCZSSrF!ed#!ayj?nU{ZFx68_3rDb-P
zBqQ(Q@hqy%8yms_P%(#h3XL>ZbqF(ct>yCMGpe&0NyT)MX!@@7&!=JCYa3t9FA=>7
zw~y*9$A=-s6h6*Hzp~!6?UN-P&Ab)`;ZNMk_=vvLJe4MSMC}@lN?Tr5s|*o*z3PI}
z)Eoi9L?asySIdP2j=5B~7?FfZ7nKB_8_m;pYv!SpGcsFp_gl{uvXD*^_RLD{#y907
z*V`>CXUT#C5~XB)mzXX>JUL`#`8%mx_ulM*QuP(N1FzbMgFpu9NQ8pX{$EFLXKP>$
z%MARrK?=GdK$IYgP!Q-ANG#JG`yc`YqW_vo6_d*O$5h@PE)x4GB}7DF!s4P(TRx<<
zHHr_45<&5aAz>nXa8abKsJJjnPz+%Ultm3XER+kA9n$j;h4Onk*tsCQygg7rda6F8
zwX4UoNMk(Sd@N3S)^KBNS!g)6Bs3h{nu`s_0)uHl*D7eO!;00xM@-fBjEbGvGnk)1
ziSP(`qST&9<6vV$&%lVGgm~Czaqy_YXZ2vzP|E!P5ebp1tE(NbM%U6(gz-Un_am`M
z*bgHW1$E>hr%*Ny2#6la!^Z)M@`S*2AnJ4Gaad*2viUTR2ujdGy#I5Kv3`?
z2s42?{k%x(?~6PJW!x{4n40>qNIic~FO)Mx1PT=rgmFVp90)`WIedzdMaRPxki^r$
z#qKw;pvF*YJp6;&g0T*(jg5tmtpLKgjf`!1vi#8H2nlE3+Ff|Befpx%E03HcWS+hT>%v?yL2tHC_oAi1KliTtA+(Kza0;cX(pNu{Kiekv=>O+l>o0Dsz
zQ1sVQu&{8fpcYWhuVE-w6r;VDmz#uuz`hppxgtH?_}!cw`0aqM6@bEjO9zhPI!yQ5
z)BP6&ocDW}59Y?_fJE@w3GpL6yr6XZ(n4@3pkzQbeybD~7L);x@M{&ZalU(mO#~JC
z_6P@ulY|`#6GsZcZG`wlg@kPRL=kXNK5KE9D4#IY#zsiY77jxpQQs>mwgU)i3xyC;4og$MlO+|e1;TCPEUv`yKr@sPd)1M3)|XTpFh2Puq}18-OTICeJWoM;FXr!
zI!%L|0wVQZih7x{Hz(058cOQsG>~}1A^qB-yuLlO-BIy7T@N(xt14*4R)dYfuK?>A
z1AdW*79_t}z^dxQYBUm(d2%md=LjM5lFawQK^1?l&OcZX%RwIfr$3(|FU^@4n}
z8DXd}R7_A%NJLNsuo)rfcfns_ran-LZNk5L
zfZ_pW1;zqFZN6$ZU=>DC1L(=GVJJ8X@>6a10D9xAmj6{7IxzJ^O0&SWrb
z6nlap1c!%*@78z5{ZrfhZY0LG1B3=c!JYj$V}mv0&7?!i8-w%HZvE%Vz7-kF!07LmiTiIgstsaIK_$_LBJUVB5IZ@39ba@#y?itNi
zFc?o|?<%7$<+E*S{c@MjFsSE-9pFRsJ-r0;9K1Ze^j)1$E}mg|NFM~+7=H>Hjz5k^
z2#l9eUr4d=!MWl1Pk^XyFcvn96iSRoXceV~g~G-G2C=XtJmSN2gcMjfxnZF=!O%c3
z7S`dYFys#=!h*t}q~E=S3&Md|4k1#T^b95_`lvLvZ_C=YGG>1!z>ycXde3+nWx)Ok
zObhCil&tf(OKc%%-L4bYs+X}eWw1j}E(is@3LFZ9iNImPP!lK~P*x}w5tx7vv4IXJ
zcj(Ct$IS%{w+r~y{_6g!1_xPK?JTI9<)OEtnkPI%2#Nw+%bnt~*|Q8e7LVJEZod9N?i^zJ
ztcnuD<=!UyY*>@v2M2+eo0o;xBCO};hU%HOKK#)>4qQe$?qH}JaUtJx=FE;cicApY
zJH6FKj_Y$L9p8OG=lJ3p`5$whnr!?SD|>?abbTYEuFP>hSU6S?;Qjr9u^Z|L{RO%N
zEO~x5=6~H%_tBbErju7x{KX@|ev2V|CVdMvkneW_=z_+J3Fg6@Wl+0cDOn3P7
z3_9b0NN56|
zz;`!YB%^9uBjuRq*=?mm3fsRkZ7_}+R0Yfm%7~TW+O``~GwGAQh}Wbn84m2^MUl>}
z(;tz^uOqr603?aF8O%0?5~ZA@pvX-+dW5$!q;9i`d|ThE!AghmqQJ!wDE;cBSLnkgI1cM0+!k~Z?4@-rHU4lCNVU|$Ulhjq5BlyA4LMOcW
zc|?6bVPB`wtAMLaowK)Sk1X=wK(ZKjEMJ6TJ1Xq-@>$FdHPvxXw2KXH9m{4ZRf3kkwua3Q$h!2%taSqTaq
z1c3$mf85Xi!)&CR1o;ko;dYI3Pd9IimFF;kD_~31U_5brt#x
zrNfg^@;7>vf*%Sj^7sAr4?{EIznq~kcb_+q
zyr+8wYtUD!mG=n^QSABRA7&^&ovSN-oeltIAqE8+>}wcUQT+AwGx;~`!o>mOg1+x-
z%*+A`)sJNCTYNvuUR2I@I|_02LUxu|>$T7v2tRjdE4xj;TvYIVOP6&}9z1)hTQcM6djryY?`N{*
zkZuSYBSl~j=|BCk0WuPl2dx>&b-9P7zFo+mCRgWCbbBesm!l%&b*$K9Helh?IS?$!
z*g&JhSB*8>NzB!YqJt{SVbUu`Ue($?z5k<$in@f*6A%bYb-4d^;&A^9{m1<;BpTu1
z%XTl)Rp|$5w=KMgs`;@pN$Pnj87aUD9&eV4Hx2r+uGWS
zp^#8f8$pEEK^~TNC>N9m!pqge(!s^nHQ&Ys;f(TQ`#Rm;-{Cr#;;Vj52GMe`_CR>}
z+xeh8JRMwJJjKMsg~i1LMa3n4`{aT2Kq0(PHkJraPn3t(eyWIkq_+p!kIxf@wmrUI
zKU?Yj%@zJ{DGqjL_<;q42e99Qa`EE#5wfvIc-k956ralDat1Fow>`r-R(D3YM*xIC
z`<+;fKGCrCB)~}gGA3)DKg$|{JdgxvwZnW(9>_>Z>{(OgEVPmB4SB^YW}mTix-hjC
z113pX`W!Ysh_F&N_SnvxN%i
z#~)SbH?jBAqxW^_h9k-kiS|C|)v$aNpiUlMG`47zi=CG}1AW(bA|2M$hf|vTOU>rR
z8>=7cuf9k?I}W6ic1j-^$e!Pfn7#?a**CA#``Lg0gSGxcWqvB#x2^)-#Co_dT%O%w
zWcUqR%qR4L0v)QFlMTuf>EYnE-^G3qMU4JIto^@kjUMW+gAZ`jN}b=`#=*|P3xU>i
z_4Yub^nn9dekx!02z~g0T#)>(9(DpQC|^&cE0D9mVS3Ml^!o?41iU;D4lXDgd9>aB
z;?v&Q0eP_d>ga~>04&H0FpfN@Z_4Z$_6zm@`eB1O9W)4FJ%H)`&>md!Zf3B81^x+^K#GZpAdm<_KA1HM
z&L=2lE6N8GwYA{`<^*sNTVa$i5(OZU{{Tzye8mznz$8)vnDqRHB`!|&7#Bh3b=Q?q
zTv-7fw_X-beeVf>#eOFSO8_1LCJszJ_qSyLECB;1LHj{qTjoE)62Qz6{?A~Ej@uj=
zn>kt+!Y4{)$@{m;W`gPNlsd&&BDB4%OIxQ0Dr&@X%(F7yD!wVSza>`p{ucZbb>$mP
z>zAq_=mI?cd;dI^z~@xE=__{694yOm)5VeSiduDV?4M7U{;$LmVlZ245k6oZjNlW6
z+W=SsE)L}r5)?#PTf^Yi2y2_~mGp4BMk*C=zsyGdGD6pw;D!^Ugw3u_pkK|Y`#uWq
zK20NSS&m6;1RQJXzuL|@D|V^SDj%4xy*8jpGgH07v)GOHgO!IT_1H7LsZ
z^KIkc4^V;-G|=l4L|csx0jNYC;Q6|N-$N=v9dPD~+upEAS~iK?@ad?J!*1*m-;XQ5
zVq5G0%723r;y*$OF%zi%U)bA$LisUJ;>6cg(*Fo0V6gvTAHWoHW%-$1d&85AB_nCU
zGmWv0+d`~g>K+sLEBBf8M!qST61w)87vIKC+KxKwsw7o~49P}$5%eP;=d+!xv9XkY
zmrBq-9SyWAYBGEgcrTAgZ?Esm_Quc;PVA>!q`%II{o_>PkdaRyoka5Z?C=5-7odU8
zw=M?7Tv^+YbMwA@r^2Ij58>O2M@l>9EBrSPA>vZ_F
zj8gJ|*WLz%cE>s{;Bal~yg$*yIOreH8R5`tPj%yY43RpZ$^XR?|HTsj>Ridc!Nh-R
zbN`31#5n*<`0Qf|hhH)Nf`2;b|2isR@#2Ed=sn2uxy^dCvvTdUsE(Ef9gT7+qv;x5l6PRZau{Jd(&VXmHnOZqw_oQ
z7u6i{=%ARj
zF0}&pYL~3VV=e!LNvr@1#$^nXm<2w*{?smPJ()1oQ5>Np4tmGalj`4=jUP42?;;?g$F`U^hYN;C
zWSvUMZ_gd?MmwrWHnu)mv>0=SXM?t9-|Et!FLD3}JpKzMKsf(}68mTO4v^pfaVVj@
zzx(wc|9ry|=cn&@r(KU1*RV=+HKDW98)2-z!~6w085|%;wdgDVhijgAYgpLaFjKln6Ql?A6y&`
z7e~OM!f*uqAHx#jFd^XN5nN0{?CYn07)!)l-73HCWN#{VnWZks#9-`UJ?LV;6Qj_(xyCYFGfTj|$J
z(D=7M=Q4VgH=Y)Hazyh8+@7?#bjSlmU`+P!V+n%lA9nHu{}-_YJ?mF4Au{ntE|Ic;
zn3$P9El&jkOF9+tTnYbRSlYCn_YAm4nT1n~FSO4kPW{ffup)n`%ulzcf5Z}cKVXT7
z{2zAVUEKg+X7ej(z@MqzpV0tcc^ex51^58{y$=C?+x-6t6A}A2nF!L=+0E4xzz<*B
z!Ucn9TwMTI_&X@!uJ|<;;^hkAcXP1=f$)%reeiD}0z82OboB!wum>OvKoGTU-GSqr
z4gi`1pb&8S!W-@7ndh?Ki9V=P2p0!i0C8Qnvqdr
zcyP#&|1cAj%>lwZ^&PW2V3q>^)&&O)=KPKGVG48qR+yKEH*m!N*A)dYN8s)RKuQ2c
zW&<>m0|L$e%gbasV9k18FKqyn*VDlU1suF_0AQ8>FKbpm)<4$u;P}6btCudy2RQTl
z3)`9gcXj^tTI9#@8wBRxr@JVdv%2d1&H(ARKWJjaKcTt572)|4V2{z}Ka<1aSIF^g
zZ2oIPnEwhPeq-u~GSL6lS_cON)b>vbeCv;2D}wX>c@6;U?hk$lbm;HKJ#QsH5pQq&!i4Co;R(++#d#ALx
zV%``p5fh)~4eWkFan~kCWF;eooQB1%e%*fhFTAUU5Jdo%ASw!n^NB)51o^~8Y{dBl1)NU61d3RlkJHf!cOV%c6xukNblqQR=YO5l4
zEuzhEJ752{g#{RDV=ZnoA!kEb&EvFn+NfiI@2YbcOZwOvh0aLOWo_=tttVAEc1mZ6
zSahQMKVQ3L^Is_ZUnu10Lf9?d*Kn^(<)8oTflB2qVEOXfadHe57X5Zr
zjS%!g?8;TD-DmlKysJiy=3H9r%Nl#{<2I=Hc0}j2M3%+(1Iw?V5OBS_D-zBjp65qpwvr1!4iM*E09&3;msf6i
zNLRaR6nr#%%+TSHP9_eQIU48E_P9xlxmZySXrSLSyY(sN^``xUTB$vkwREP
zE*Z1U0vLKac{_QSwf(qU$z4RDHe^z(-IVUd-Lr@rSJHNlGmauozBnf}>N^!Z~
z?XeHr!xV78H=U{Mqg?ev^Qr1^(7%Mj{sduT(n1*@h2CiK58Z0+_i+yCprNnMFU`?n
zxQu?|{GFfrdQ~lK`5Kl7c$FAo5-X8`J^!kFVyfU$jnCytYnRv7SpraiUcRGqeXQ^x
zYH{HFD{G!iM}PB&vl)rG%`{yk4=2191fBl>fQ9!j{t3f>Jr@4S()Twkd?ieeuiiNN4Er@S@wi|P)y0kj8BwuZ2MjBIA{90JQhC|SNluREC(QLksxANAW
z;kL1yl`#2Bq{!uohzsYW%oo@=2{)$5`~C$M4$66UZ?`;V?LyeK82O=O!%!XAcjf=G
z1-b}y|HdF34y>mS7U)p85O9|s2m{my3YPzyQ_u}YAQ@h#@8(AKnT~WekN*Ik(yfaVDHYY3FSKZ
z*jdJ;8LxuWX`Ye9jv_rq{*?i6+-xnzr?-o4Ip6;>-X@u)JV6Asps`yaaYa8%(Qcw{_~BSkL6zk)oMis@kf0wY9GDmd`}9V>n`C9tH39FICQW0q)6EL
zm9D=Dg&VS*a9>JN3N{lwKA&+-DQC;)iZu5_aFuP%PMM28tJA*^g^6r_;HdwbP?&*i
z@GBKIxc)~fjHBT;2LE8cYH>YhE<^`hLg*N}Hs0eIPV{1ZqAYi9W}gac{YZtep8Qam
zzW{}^e}KZ_Kf+iH6#o9=lAHDcC;oO(?N<=vKhw#tLb@K%THs=v%fYQTo1YNjfA^Lg
zaEtNl^*96??XT=&zkfybmvHevt0f48-}Ud~W&E`L4lQu7K}sCb6bEO79ZCS;)qfQ^
z=l>49{1G|FVQ`V>HwyfhVc}o7y!HxR&knElU3Dw-o@#Cj5SV^SB)j@&KR52=hnB5c)g$
zf9Fa56ypDt7Cc1f_;jGXivB$1s3WxTcz5sN-u&Ra`6c&dqU`A#(DZy_?0*;H|COSD
z=a>#9$uu&1#e9NGe$_kl9UkQ4E0~0N9(Q*67o>JohWJO*Acj73cMu2yQdg4K_se=e
z?q6+l*8jtv-Lj`+v!3tszEi%V5It-*c?%1Dyk07$7&+*(P>oNu#%GRA5VUPqt&;MH
zwfHj`#Fw*MYxR|~lfj6E&v3FvmnGRBk02TEkycP7_r3Ws>uyNM`&&UzrHgKDuDLBc
zy9CL`4GxqA%nuYdp0!)v$+D9*RX%g0#z4c^seteEOzGUm=3PS#ZpxQ4i+81Wv1|73
zjz0|?-wSJ$ex7ro;he19xh-t(ZE2gFb3WJV9)7Gp8l2a>CPF3cuUz^9j4nfV*{dcALxf
zbx#9wWyr^`hNgG>TNQE_#KYL~Yifr!p9C&gINY0)z6$(L8sG;?Zd0*l>{N4haq@~d
zaltwl+0?Ov2eu|6;;kknDTs)M?&eRbD!br==sOTeaZ!DP2MOKYyed#TReVfhWsmh`
zmxTsN`hy_!OKD9fJ)ho!;=xOy{wHh3E?&etX2yVn!+nq<<4o}gScAJjp8{v(md}S=
zX^}cMPhqVhFs2kw1>S=TzZnw4!GySJkY&VVTpk!P
zX7x;zN^4HC96XbgB~EjB$`8FvgUNFRFn3Za;E1YZ-dFuvT7URZU9$U~%QA*
z{aKQ%1{tb@0Mt&Q5YzpkNvj971<8?OT2C$%lUxgrpp>BIP)tJ`3QX*o#j_;w(G&s)
zpnzyV+Fy(;q)2i4yZw*o5rQ9?*tZiQx7}Er~vJOsZ
z(QCp4(R2rI^NS;g2?Oc~GuJgl}u{nDG=eFw${zJ+H0Cs%f^0i&@X
z=$Gopj5=&G{<)({*qo4q$52b}N03>O{!kDmpOv$ca#o|>n5L22>+hs@Dy!c+mmkS`
zkbEVrHs(yovO3P88fH`g0&(1bb)e~?GH;zIbixi2hVBj`Xt57I_PG)qHt=DszLrHn
z2hpM7I;d&xJ%@Zu>QHWs#>goYr0QyC!mAu*
zHAg55Xy!1&u9gkaV6#AO4^d%8libNjw*1m)T@xoKzB^yLsIjIMAsJ+qNRAPp2NxB8
zMk6MUBuN@mGfSc}DoTVkru}!co_@xB3T-G#qvc>TK%;NUV-kiu8!|!0vkwVCv@j9(
z`q`3AMv~IV4&Im*)pMkvU_5vPC{BMjkHgOJHM7=}7+E)Cm*|NhX$Ox(Tc{k*SSvSh
zg>mv@vXUh_ABZV;(}Jth#G%4n?Z#o!8z+Eq0W$*jRa8@I&K;)9s?~@$8WP6zU(R`#
z*f3qTA;HI(w{~x&aiL82=qPnD1JJBuH+{R{g@cEy;)|{vp7@WBAB1u%xR7PhTI#HB
zZCF+N|ECNDnmzh$wBUyiaTPp>t+GzzDmXO%+{tP|f>heP)q}*K9gP#|P#q1*!|cc%
z=qPV5a$#vQADBbm1z=Drtud%6qJOcbfYGg7S)fST5@lm2(>d&uo*1jk=^vsWd_o89
zG;&g=#Edh!_qdQfsX4`m?Z4NbpBl|okjf!(P_SIivs&{cx2nUTXjVw#idb%H)iWY$
zBg*3jCbEo_&z(dMQobtC+L{fm8B)d>lQt-&;?UuQzf4Sfyw`E$xtL1sif5KK5WPXPp}~?Y-rIRpJ|2oAj?+GEWt(CJ=z=%
zs}pfFjh0o@tOxNcSADL44NALJ@Q)pub&s!!u|pcG8!=ODI}V%5gGU2eUn?+Ypsp}V
zM$UD~hXL%MOl0P*pnx&99@Fmn%}5RJ3^R=Un-QmXU)>>;a2Z()K8X3COQ&J25Z2Uh
z@zyPwDjk(8bZBEM@=iUIlD?SNdR%#GJ57#q)wLp^!w)gW@HX`FKo9tRO)t*
zteIhdT_$6=zR#64Or_)3td>T6Eh*VDK-y5Eo)AqWo*@{-_CY&4bVJxIpF45phst-5*e
zo}Ffa#2knYn5jvOvXXiq8PPi1`4n&bx@P`Ol86C=|xQCR}yQ78as$nbyE)qJXr@mjX0`)Hj~s(lwe+KPD5$OpcV
zmATjCB4-l&V$bH^Fuw?C=)~llVOMBFYJcVA=~$Iw&&S1Q-5=n@)iEM0U0MsAj^fI)ob-M={DJTo{tET02tE9f>qF`9iXTp(8
zM5Hw&pwFgJbre&5e}%Z{%FcIRXJ0o`&JvcwdQe+Jr4t0Y(-t&g?G$f>Tz`ZG
zdV6AcLYdR2&KZp!HDh4}du0bU#MpDNHJB}xH!U?z$MU)~ytxb^U`&Ww;Dg=8
z1$}r{sAT5JnP1}q&$ldZTBgp~UVWhCJ$kuJqgX6a&)tnt2Gn};c_$;s9DBG6DHSQL
zZ8TMZlCe_)%w&PjwAL(m?bBil`p}noJVVY@4b`O
zmiZh%bZ(}z_Y4gKa$4-#LIf^oRhWrqG2}zK<9G$2J904;^sOg#G?dT4Wh4qq2N*x^
z?X=0Z>;nITQ7m!Bi2IEKwme18XJDAQJq(D;)@$qe?g?E*%Vq@mSjc3bm3TU_2-*)F
z7$`*$4j~vzZETP+0s%uVoAoHl)66duj@3i>McgahfattJgIVItdgDU*R^J5~C09bA
z36igJzpBS2)+l&pC$n-T)1|RkhpWC3TU+YmgG46Da7f>|`OW9mL7>o=1sx`fE7+;Y
zYid2Q8Ec`vBSsJUG!TUhNX7(}yA~Jox#%JrAScrwTkgyo4wo7WNl5SjvOez>j4qp+
zApnW_alcs*WvEmst*N!BFm<}Ov*;S~xx|u*k+Dj{=lzI7*?5EJyXV@ni;VRa!USk*
zZeSF#ZB0GbuteqJlpkhfm%RpyR!bURNdd
zrX;|&?x@#A^s79uzk*Ipt_zX|GxGINaO9&)@Z|5lj4mr4Ug)*GqgxEm>}_jnlU#0I
z$&U;9Vkc`^lIjR&?2fJ8vQZ&00}M-LxbaEM=Be)3ganxF^TJbxJ6(fKDyn74m6b4L
ze2jIv!H4xtQj<9YJo!2;tXKsskZnfd=n6rh0asS|1FRl!otk`&Ntr=Om-jWZvqfQH
zVHa3}*Yo4}H|s*S>Z~hghr%@qtid3+4<8m&ha^ba9cwmKm;Jv~1b;4pk}UKV8kL}V
zQF2Z@AKJ+cIXO*A==-Vxv7!w`L_~CXZW|c$^24Q#edSE^Qd&nPq*lW8oaxrLi
zZPfMY8xLwEQY7|4EvIYan#;`FQ%LF=ej}?c8W5<5l8?>AA%wx8xC;$_O2q{H2dp4&
z(L1g0?y#>AIM$ft=}=rMDQ}#=&az`qA0QQHi1Rv^#~pG&(Ji+-EStB+mnRxLi(sAR0au!Up=Y&b
zAZeoD9z$h*TGQ;O9TvcUhI|Z3OFLI{MEI&kDplp8v4=s-*{XmqOAlE>q=2hsEBO1P
z1DiFvPyruHSeF|uBj+5drb(oIp2Rk=NiL#MIkbeKoYR9UnU
z<@0h&d-mG1jkLC2J&<=X9Rz@NUdv7MqVV_Y)0?ds40*qe5o
zfq~h4XupeYR?YMRSv4bPnG*G2=gH`q7tuB5GWNGlDFIzqW77L>WoBl^X{dCg+ps0S
zrhL#*3l0cMcyHb1dOroSVn;S)cgEDk!tYVON*S~0bu^{@!?NM)spmH5ihP&Gu9)E<
zYAu1a-EvLr!s)lo-i~((tdKtTWecCrIbA9`ozrL&9-3MA5-sA{kfl2x!Lt48g6uZJ
zcXTju&Gg9{Fh%dVBrg7Lt3H(X9nC{`nVh|ad%Fu2fp2&f6%~<4B+#-C+skUMU%$@w
z={~UldbBoS0R{>czo8tTW>nm2^2S8ep{7FR!MZwriqM--24q>;@B%+>F7nHx3W7IV
z+Gl7IE?#`-E+r+k4QTsREN}UXmY^m}1Cx>Qn)ESMQSVlPh8g@&aoCpPf(>*eZRD)R
z&iX^ymNg^`A2}I(A)$LcvRdes#I+vt=24zv;rXXBTczwgfcZfmSJxPH*~Gmul+Y@y
zW4NMw4V1w;G-6U#SlG{}ahd-1kVs}PSL_jfv-RxdK)cWLgGWVOyf_F`bz4$bHPt?4
zsKaqXBd*BGHm!SC8kyC(j5kg0EIHONMj`IJOug2R<&g8vv%&0`GP(3>QnXQ}0lJPG
zSitlgE7OPMo0Epy2)$l%b!IPQ=6BO`;Jg~hVkzW-^+
z?#g5SruTUlm_Jb;F=KIZ5x8GeML%}2#Vj0F*l(|N<~18rg35K^MpE5<`k5k45U6UK
zP^4y}tSOs_>*<5JfnF!iqJ@N`qAg$UE|0ea1<*%H`YxeGGBvn)hqQVLb)L-|Zg7Q4
zj(lDiZt`rQ;sjQGZ$l08ACa|Y=`9lI-?d0rBGVjREV8gl_lbSGzP|qG(W9L&lOZ2F
z==SCf@A1$OouO%(qQJY^0rrYqf6UoafE}-
zWiU!y+yf+*Q7}~MUN`PGK0a5~we5B1%Iso&qd0=T(>?G_nqj$VUAY;*Xy&O*EyTja
z%?51ZaJiU~+X%%PlkC%}$3UT1ayv};G?cdPe=Or_ijMPXDl~{}BeYGjG`M3?7NbTV
zNJEOn!Z0rvN7Sz4uo(yH3mY2gFs&I{
zs^#@r2nWkksBLXFvpc?IU%v9>j@M}E=jMDgTIO@H_V~GlvJPu^VB+BjuW@8jymeEq
zq*||u)+uek0j_MbF!au6Y0NqPQo7aWW1v;nq$X
zvXLGlE+{AngHb-Lbaj_l(kraBE-wJ)9s@9q`8c`;E$0~3es<+_cUm
zXcB*7(q4q9p*cF*pi`qS$o%O}2zQz}GeeiE_ydz%$|
zn=iasT$N7g-6>~HdGP5%*FztYkT^9O<&D4=11I#0+f(oFJoRFY!rn2!0^PriS`4ljJ
zE6_}5_8vF`c-q&u&X!yjuxvrUtO6p*NJ#1*ZhF>?=EpV=?B-yTO^ZkQMZ-BJK{XpeI7b=KY?
z1V-RgN=leUwMWVunoHmwdP{l7W
zXcXey^D+5c1mTaW=OLYE^pvWH5>%=ko)^~0Zq0@4z6;si
zekVKG=G7t!8^j;q}ITPD_~mxJ5`+25qvQ8ronBhUut8RZ=QX%RcO=Ch%W)+Nq>whuTwF+@OiWFROY@t1~`3zUnM;QtVU>w&R@E83Agv1*^LyIz4eE0JQ_^OI4|;eC%t6ZL2OOp
z$?Nc>T{|~l91}xG2f4k-76-UjGFsE?O5Cs^lLGrlsOZ>PU%vTdP5y?t!c4%E*CQX2
zb!iQ!YI$=Bc-wg_-CVGuCBhZ0+*<&asl`RtOe%&~HkzaBTZZ8gmcg5$6&Z_54oase
z&lu!$odX=+^1Z#?OxKo;rKaWJ=@`;p+mrdgzn0ER%FM_BeBBuuz>BjO>u40qjlM8)
z@;o2dU}j(t{2_uR%X`S!<%|l|DXdma4k6B?xGXxs?<*fpe25Z#|Dv*;enz`CSR|}z
zkqzvA3}`d!%8bWvN|S+VQFkP$94Ao}6)4r`q4n5kzszrZ+o}yvH-mDs2FJl$9GaJp
z1+DhS9pT%&5VC$@p}YxjoWqVa%#T+Ki5R@l_mph>{OVt#9m_)YjV5IKW56J=RpKTW
z$!6X0Y~9Lb<9&BbOw8-Z@Bx}rvebDqrzJRjMtmw;xniTDqL}xy=5L&JvfLWMr8Cnh
zGZ;_XhLRM$#9mpTWOveYDs!qCq1KkFTwBW7_jO;!eJ6gQuld1|yE_5uUy53-vk5o{jQ
zF()j%2hR>$1e7(AEr*w}O+Tv{lLnT`hIid@!APf18-W=DB;@255VLsO8-X%9=YToJ
z!f=JJ_S7dz6&00F8{2D(qr~UKT`6@>saL(u^NJ;2-x_zOQ(|TTlXmFXZISfPiH49OdtXR2?MK3VxD!?>}=pf>OR>GQJKel%11Z>swA1hGGz*J
zIfVcOE7#inA>U=fn}37=^}v_(u&~(uWEXPFmc;^*sD(3_bHFwz_n^IkF+iJ`v97Ff
z{!+-!!`3>rDXAkfWpPg{gua(DvfHfS&o?bDFo5?^J+4;=D(1#p!rNK=LqoCxv2iRVf8$V=78X
ziS3~~&m-8(fPRzKs7473bI=t$=<0Y(HE2yR*QMi-9QW$9JZh7$M}^~ENcd2uDAI4g
z&1(*wlzY8nJuG**O&hTEa|b{bI5AnRitlDNR-FR@10}Fz+)m?
zj}LY!c0{;)S`6W)0Dr$&@tirB60bL*t63>*TZxH~JRW&26*~E|6$h&``mO>e63sG8
zBUNPA{M!kOR*$z&&?6hpXU#azO?H`MQuannaTz6gJX`9JnU5sJWRrHA3yLI<}k?lt06DwsfN6|Tq!+p
zc-cg0rar$9)o6Ki{MPNSft5P9|Bj4|{QC8478y95uMp+n=d*hqU~uaTVc{Be4||
zT=xBIonG$IP}@7gbVw7x(DSp7O$(@FgVp>LWeUg1E)g_|0(n?9zs|Dk>SliZdT&78
zIX{LXQG#c)1Z8FY-7KHVL}d4*1N8F*dW?DIGOTkh);O)>Va<(
zSXih*_H{hjf19d7mwzF7M1D8)Pm(FNNgP(XI%vomCGu?Lq6XPbQpO$!4M`na
zI{5w0R?#je_z$10#G70#QBs=tA0V&ik=MgF7m)e$4xKVUuy!>d15r;J=9Us~&pim0
z%Uc{p8wn_g68um#j{jxJZSUy!cSow#!mCiJ@(0Qv$<-uJzhey(pWP13!V!#vu8V#&i^p_qQ}akmsR_H+R`F>%tsY6Boa
z!T6bwKumlvZ4uZo<^v$&PUZ+30*^#Aw3->Hi557tHZd={VqzYfj8sHvS;^KT_C{xv5;wT5Xl7t2qBj@4nHz|jMV9N7l|%o!)9-Op
zpOXg0wN@^ixpVuE9M~+2Ifg?0_6c^d4Ei&(XzKhivLe5nbEga%1;PPaN
zPmS$f_fU62UPa@A9ss8zndp2K5hlU1+0?$-5~az$kK@}XVzE)(OHq97-T?CTxH!NF
zy7=)!fBcZeU>v{#NF(C2(r3)Y%U;FdXQHfF^B+xw4ea?#4@t2I;-501C1NGa2T8e03Fogy4tT)RNWwa<6v;Ai}IY87XGO!t&FN~R68k#TyG*#
zZOE33wM-+k>^hNH^GSM@Vt+pHzPzw6GSKBzi4*Bz;q%7EOJz7hRcj0p%dGFMH?t%SwZQ_lO2XZf@8z4@DGodvzeKW7p9+lcZFW
zIr3N?i*D*dnDAZrizZl#8SDYUgTNhg1~*c;#^$AdX;L4uKB>uNe>KUW%Ugnc`-;jyp+Ytt^f`c)g*73b;B$v12tc;^
zFgSzVc8g`1x?-j=FHmd@hU(n5U(DBP4_nt@A{wt3e^g9CEB5-9F6CYot{z|xog%=qK
zt3uq#hY4`KO}(`iyiINkbMCl4z0cby^AV8EyBVX2#_3)OxBaNdb`mG$&yb{djH52@d?ZFuRVJ%4a;
z@E>4|5x`WCg@ahHET6RuO#c>jUf4;4zN;bp+7t`K@p+qryUuiR=b
z$7d_kcA3jZ#SOht0&4*9N?&di6uhW0RQB1*F%Y&Wrmx^79?fMbc6ZE
zLFdYO$HX3x*Qd{9zlzvN^&=ZmM%we)5?+zLBO_plMqy}g^u@Y~_umgUSHm}w($ag8
z=ZzXIo%X;c_`c&7uQ|)jgF&^w-_YhnaCpjfh2JmpLLAPU{=y&(Ch&
z0U%89kWk;ACZ2O6NjWVzreC3F65zq#QygHHk
z7xK`$J26A`I(_wnaQyFeKq7*|DDHhQs{%kV=yEJ~ArQ4&rUPqUNmSOUFbsV+FQ3i!_w60$b5Krx7fXp}
zw%jAKT-FP)L6VJ52)|F4;vTcxr9o
zxtDdpA1WFe@R~rk0lfm0h5&H!fuJrlSPgv!F%8KR0X(us#`enoqBKVS1n}cl0>iDZ@
zn=RlXTxju>yxPQ0N4-Xjl`_zN(s4K9V!gWuHIsf}E1kk86|;;!aYKW%N=9z=C0afc
z^vx{~LZ^Diqk}EZI|-a(^e7*XKwC7fp|-3rv%VRl^adS!ShTiMG+%xeRXlqf9Pg=N
zxSZ=^wl9Mr$_ys8nyk41uu0&ivWe^cTa7=CYSC28`LjlB+=!l1sQ?*y*QTt8IK-Uf
zkuJ1g7H)hb{JnAT10XMk*RLat08bo|&k@U9mB{^`B-}5HEdENciE`E0yAJ9h>@=|I
zN~VCk`0eG?y!lo0&9haYiK0GG8aJAC-z(B0Q(z_u&kN#Nue}~c4P{a~@4ohbRc*_I
z^-zSX{%ado#YQ<&2OE5MpSXy~9#oAg{69Jf2nnV?LT>}w%HK0q<~01Ziok}a1ncZs
zws2Cws?7S44^1Y9Z>R{m-Y%LS&KwHMP{HGpsT|HuSz+*v^ZSB~4pVEW$$f3qDg5kQ
zwCCKkh9MsXzpN@EBx=;(W*&7Ap^14xrT}2UY=bkh)#nHdIgJ1mDitmDZvu2~RkMk9
zw4~L0474#?cz()#qQdI7WDQxOZ!#ZE0rUq$tn?sxRJUA-n2?axAmtrAypNR8JkVO3
zAOCtoZ{G*c8-Nw5%6mTnn;$aDYXpfk&lSwQ{>ir7!TWt@xLlp=gQ?B0*x1;diy6Us
zhv`upAu#A0U$GkM_Cak`)6_x$qA=U}_wQZX^b~+9)lUIf=jX39>y89){s4%hCavBF
ze?Ky`TlA5nF{cfzhBAJe+%8xKmt@}I^DmDt=whJ7bN60o=WWBUK0MQcDRuQ~fVR0^
zlpNIr2*WEN$zluzZzOhw&c=tV1apU57(e9hFj`cZ@>zyOPn)p*sl?_Z?@wzkQjLE0
zcfHXLc5|$HbL@;>a|Q^$-f?yr+=cd<2X5y!;?^XW*~<$23~VZ!gGY
zp7UXSi+J`uqKH>SxL~Yit->(1C%yshn9p(3dX68c%(;P=o4~&SXirOj|JG>-&~pL1
zsarMyxDpJ)(9(z+DEw{fmn;Q2^L8M@1sp`$KojFnAdPf($^gokmevp);D8DGuq%yE
z0)Wpn`g)6t!&UIR02Cfw@IQzlF8T#6NPfzuloev2dDg}6AYw3f?>yh3
zcO$^ne2t5t&mTVfB~_=q`fmTVCj?~vmWAG-WIU4kjl7GdA-1}cgvym>&;3H
zA`0tWJbukxzs{X^QY@2-u8xW@9XH*o#M$Gi=k@C=K|50fL&h@Oja^!Xj4el-bGgmQ
zXue@?#ur&
zYG9zEdN)iCccBVbC*v&o$$zYx_JDzTEjLj}Ua;?R_tks!XD1a2jcWN7&iggAAqR2L
zI>qSF602GdYv#+unfBQO_d&K+#X4@^MYCX!{2M=MU
z>xZj7qn2M^`NWIdX|GV|{)N?tjmhff0qYLchxHoe;q@)W2KOiHVrr96y1Urprc|l-
zx;09UYrwqN`#3JSq{f;ZnfuFPadTbmoTlWt$}YSkf2C|d=b`Ey!)o)Lg_o;mNzGDp
zbjWqvKoZ}bu^>r}I2DE1uZCPZqdwSHF*oBAnK6v`wH(AQf*13WH&fJJEjne7s?^D(
zF3w5gFvBAF0SG8(AhCdV7Nbbo*L|*-+E2VvV2ND@7+&MS+}lz1Tp;za(KYfZkSXvA
zF@8$qMdKG=K(9Xaa^3adzi7K(n~Inmp-ZO;T08O)P4tARiHed@gw=bP2jS!+C
zVC^ReSFo_Lu>oBJkUx@J-wJ>#0vKTSa;V2ne+oAxk6xwCALdLw_YvxoU!hg0C$?D@?2V4z#0N^h>suOTAKd+DG|w<2(v2I&qapBNxeo%OR@
zDKRrHF^fGtVcA*0E7G#`UjmZD^+don;8V0q{cav9cJzrW+
zrfcHb$BI$iqq_6$_}uvE=CKb@Zoh;2HmCM%)a!+Bu}VeefUksx!n&ZD4pA+;L6_Gd
z*FjI(EOqH!#vJGR+4cf6F4YS+agF8VV6~39C2N;&`EM?Mq~Ek&*v6NKYr5i3`hCmY
zv#QgyyUylP|HIGuEIvmPAYC00(BSr~Qb>B2XjZ;h&KnLJVATy5Ux?Vdbw
z=UyfS1_k{lS4&!Wx#*7W${VBO1@oHhR_1kv#AqIO+Bv9wij&dmt9hq3KO%gxg#@$ExydH)@HxC6!AX)W{os~q}eyGUX-loVxly
zHm!|r@YE*;i0eaLAkplnIvN1r((1GP)u_d@>0?VC5bA+&WGh4sI?{vZx+T9^b495M
zOx#DPmiGqlSl5^w1)L+;8J6tU>e8p;`jZra!o%u=wMR8a=1X_Sl*$eU@O+F45Jv=J
z!D|f23#a+ZIUoV;uu%nV(7r29^i(y9i~)BnyvOHy%AUZE)D*_ylL&TDxfCv
zwTW;=MEZz7v$X#PXLrBIU%JC@otM~WEOX(w9O#{MZb&sA3b&?E!ivVRv}&{HgAdsn
zOugeYOF`R{UQ-QcBAk!dJYTL_@jiHn`GAocgNCC3w}tUJIr}fufQmI&R;-+ppJY9M
zs$9b?z1;Df3wdkuv092`s}nr_dfQ@Fv*V@@Ul)GVnz9new*R{vE_ssI$LoFS)3RGS
zTjARf#zjn_8u*6g;0{~RPCC1p!40%1*(802YS~2B^+sBG9Fk>6*(u9QX3NKEQS(UM
zKg1=N)gT+8T_G>KeJqES3SqIXhcIgUWez_FW)I3B%DahH~$)Gw*Tl
z|6W1N@bffM(imvk3yC^-FNNUICwhi-0>XyDZBU>%H_*4>4+lZ=_DQow>E<#{bHD@W
zZPWDO_4)Uqug1HfIwu%0N+Tx4m{e7xKF2f
zFI8p4v~!yESaMa76tb(GBUk#wKD*PXC-O~Dx`d?in$2|$>ML>=X+-jBZSr;O@I*5F
z>uJ*Wf(-vQ00~v9yI<2=A2tNe4>{e6-9c-Qn&S|umjAtt$dbRRpg>w
za4Yv`Lr@8r^CzGv;fAt_Ejq8cgZcfy1}!e&9(h`KKhbcc%6#9D1ZO$6;Trd&mi4z;
ztQL6Z>~)(Vbqz9(VznZ%#PeR!zI7w7`bQ^tZQKv3iv9N&rv4wxO;O(dAKAubp9&G-
z$^u#(%nMXhm~#eG;?EEF2UZWk{9U3&{oe=L_|7y>4Ga{(PXmTTJs$8| cd;hb-+T>iIg%k$*n7M}vNJD5N=iy7dA!){u^rg9*A5tE
zDf9~Igx!Qn^r$JA%MVQfoqM}U&EBX2G54}++TrwDWG=M(3tUFPM`U){3hlWcQxm7s
zE=U*0exbc(l-I-XnkqbBTRNA}W6_+q-Uz#MRkLyPZXl!Mj3PC2e%RZCrS5XQ<%|lc
zWpf796bdBsL`)LmOfUryT#ozP%5q7j~afUJNrv1uekf(jX078Nj02cgiXl
z|EB(=kHEo-+Gt;3R|p3;yFmHVk9uSn;TP2l?|s{;EZ@^q`IgiLJntM;y0S;??WHFi|TP%xOBOv@6>)f0JWihrYF5eio#3tu
zfkY$93+uGBdDCjx#8DpBMs7nBrc~jk=+1U>V~k_r2Gwzc`t?h`&Nym$%E(XALq#L|
z6Q}NEj7!MXLfU>J>Y%NBMXhkzyoLPx){ObUFJWKW!S;je;2k*UMCPD$!m#_R+i@CF
zaX^UTO#^I2s3Cxu;dmdzKYk>X*r^1>>J$Cym59f&des(viLAw&-zi;r?u;+4IFuhh_6+fIUe#1HD
zJCP9$8_#jf|82GvQWB$CV&Q4G<`!2>ksuc9Xi@ND3{qmi`eS03n<5Hkzu43Gr@BsO
zrsWAm6!4f$#%6=dxb9ttoc;Dfw;McG0~x!A*p9G?kcSpe_2&NCGzT)m<}5ls?(x_c`%h
zY|7Ww=s31ddZjEV=RTS}tr}520vW^*qyD`x!yBk_An(6qPwf
zFK^Y
znP$_&$4vhrkNW+$>0!wluv5qqB)<;2PR=E9p
zFwiHB6x|s90Iw6qm4wK22L3JsjFewhRmBkrEX$yv0!aBE=i)*e7ZWpmn)2?3tTaGa
zEMq3ryUb%ir?_{kwW1X0uVBHKE$NHI}MdN
z82kOA{7s>{vYmt}UG>029_!V*41mqC=|?)Y(SGT7L+|a_lXs6&Uf)m$9R3Wq5&u+PZhf$3n5{yna&3(41|*d*SRuua@%@Y2Ri+tdgl4zt
zkt4C!WwC4wnZ4s~`b;6Cz_I^}Tvb?|HUlv|NOv?fHMKY2BI-29p*hSCc!}I$K4|R*
zhS8}q>jpZZ55}bgriqsf*N1=q`}j*Uz^gQ7RFe{3)0>pyEOz0}8+Qwt@L?(Py5ZBl
z>oZo^zKkxD_@do5jo0VYDDOhPvt92|hi{pPGalUX%0o1Fqa@P6bN<^3Em
zb0c;QfQvSlnq9R3R<+ZV=9(GAn)%Jdqgco|oE&9hC0zfY_VP2c>?
zszVHEc>bkHdksvpAgE#@Cnvu1LvFkjQ5b7iq~(A~;IVpfmTSKNoYoC!*cEzJ
zKRsHEiaSykVJWY+`wJn#J2X)~eK)q(Z|j6hg%A-gQV!-r<=HKmc52|1idVTl%S1pWO$X{aH?#lffvS?POrdzw_&wQ~L-3vob`CRJpCXCC+~NBr6|
zP?ZFw7*p+wOXf?fYKIdfVPY4|N;(7iK=(Ygr)<=~+%}rle*D|39pDmT_5PT@
zVdKwWXWZHJ=8g`(>?Y8SJC^o>tKD3GOx1W(lQkCQSv~*f1ps&8Bc12e&Bec$<*kSP
zfWl$%IaN-vS3#4XUb(|=M=+n!H{W%adSgbX`seA1KW{d=QL29bPoU-OuZ3A_hO)1B
z&XSy6^=sphnv1v^EI&6-sBz0GI^9k=&1#;HQO0(GE6*V
zZ$i`%aw@7FJNz^DO;%8iJ}#(@}8%5SF%W4Z+5SolXgU?HzlvewZ$
z;e3VGoLAXOs)wUOq>G~^!d}^n&lxfhuBBLLj&J$ZSuZ&v+pjOTD{g@4U^DU!e5e;@
zvRc3ItuV7+dd9EOTpKa%I2Qw+?txW6Y(fH$dVooKu-{_0`Fg#jwEfXS?dG)LZ!vRs
zf9A-1rvZHr`<~-*OR_{hm=~P4r7b9*{_*>r(>9Z@pP^acwe9*;SR|Lc80T0ppf>`mb!lXC8-Q315
zKku>w_KgX=av6H|q)87Gb>%in25IOZfBTxr)yZzlE`FZJxMGe>&d`f^5D?u8tUAcB
zHj)c5NG{hXY1HdX4!s$panOv+!@EtK)9y7adsSYf+i_
z>-1IEXGO_2+7$>;F}EhlAcqNY-=TF}KIAiTA*?Rg$-D<=@yuuj(m1(}FzGZjU`X
zqq04l8a9r>t@hgxnHgTl4P5wj+wf-13aLm;4Er7dp}gF#Eg4Qkh>y!UsDR1&2%NPx
z&^XFYWmiZx8@x%Lc^Ohm$u^QHE4^67x3~%hej@i?&hB=um
z05*UcVKp2wouCT$V)JOZE}*BTE(PJQBZ-b9Oa^DQKgDJ40ru*{x!tF;JsuKkQq_oN
z!WbG(TXpF8!rH@H<7^U`2i2BY6)=1jSRDbkGbWn{MqdZ7_h?eF)#%Ap_`;0ySJyr=
zx{uXu_eQuTxL~3uC7P-UmsdLnQ_Xds=!P@sME9;eHm1T)rPJG<4tce|9DZqOhKtsn
zuUAD+JrQ4Y{`TcL?B2E?=cl%!NVZbX_d?{E@BG=KGyv#s6g16?ce^i%@#bcVI5r>s
zZu$Ao9&{%#Rf%1I@XoW<xNZ_}Gbj!}^(RdpIh>fS}B{!URzGz;#n1)*a%@@Vy1=TcJ+by!UcU`Q6uaTghqs
zb%c&E$0xit>tQ??j_@V
z&tQ95T7PzqKljxsBJ$ggpY*fFY8`Q)iUpiS3#gdOmjLk|rrjNhXnypvUEa;Uq?>UH
zSVh-{GM$0lh5y0J7cXJ~K?M?o*8nj4faut^E~PSk{Wh27GUM0|v$+%Nk;m@%1LC0B
z7gpEHH0^*1_P;?PO>Q>K_n1~)^*ObHiEW~^4gr*_Dq96SUkfcuNXC49AHCiFWa6CL
zR_3V7`h5M_emL?wys>C@vuwGCt^lWGNaN$AfXH7}IuM5N_Wp4+?CiH~fb<3Ri^sTi
z>ULcn!f9eXmOvhUur9~iMa
z?FMxE*>3RsSU1}ngj*k?#zrck4pDE$HR{wcW8fLV%$m!30w2n`DZU{|oK+QM9x>09
zs!th{tPGfKUyg}|XW2#hIUuV7hNW9H`kPJaZW>1gp-i7Tyh|x;?NAm}wHhU_wts4L
zQPG6gYjHJo%1Y-}=#&AE=?$<~9{~|k;z3u}LxU?2x;g}wFM^Ki*^V~5i7H_Ia_Vy+
z-*{2;SLf-|qz@s`AED#jBi9#b?4zj#%d=a4D{#raghCo7OtkYFIMX{oU=A3GtiCki
zyKGe%+huK{=BA${%~}((P2VXyZ58&42TpWTs)rAf1M5$V2h!SJ%hx_kQpkLWZx3s+
zx$0s-|8sQqGiWmO%;=&sk%O;s317Xbzn;&jTK-M=b62xMbaoTDyuIs5vVG9$1WzI$
zU}@Mtom8Z+-@glxuMX=Q?sAkdOvk9u;qBYE00v-4MDUCp199aDygQ!vVVp&YAKDXD
zlS}*Fhb5U{k6li5z#^Qo?}DU($9lFGdJJ+s25c-KWkQS_Qr2AuF6l+VUpDbiwdKK|
zUh`%k3NrSjI(u_2eIbRjr}MF<6{ko?Z_q5RcP;p9mrq5Am5!qFE$=__^gkahQU?8v
zT-VU$`ec%jfS}3Q5+38{IxIYo*MqPr^4gvA*=t&F=DaiUNvQ&_wxZL(UO|y4yxaeW
z!e3wwEzyG3SPgxYKF$N)=oQyzG&Fzq#@#!AM%A~;AC%Lz3O=QJ)l!z*rf4^TMW53&G2RaL#_w|{2)ejVMAAOqtQi#J~zOqghTPP9x2wM
za;mc3$j~R0FLjzrs|%7Fvis{w(zex;tl9Z;C9@^JM~n${n*&6uQL0Y4zLDcEyBXpP
z{D05e{<`E+0jx(QVsENy8B_Ak03n!{mj_7fO-#)gFj#OMRb&S+7UlsGM3j!BP7zCZ
zTv=6wu6v(r?mq=8ZqVt1q;Yw^5-mjAYj?FR?Kb{D1vUNTTeOx@_z^O}!MNC_q(3Pr
zrnPYcsmO>{Nngs>-+E*kZYqCUUgi<5yt`UGu?4X_>Ebd+===2DCvEeqSLknhz7yIW
zW!t9)hr!Ye(tq0lVUS(wS3mQnO8NCot-~gu?OZ0aA-=mQx*>^RLg(iPJ{#_odo6jv
zsvHr84@|vY(z-A{DJd%2KBEASQCS$433&?n$>)7Gf(Uw3hGzt=cw;J
zyLN550_ojcKx1GysB!x#cCyctJ^Imluj~);rxI>qCy#POZk>oT^XgSDa)Sv&$G}lx
z-YQ&6j#KW4+K9%bdWnJ<-y&O4dlf!CxF^}{q5+M28HSVVAvBHqj(zWzUgcNID(?miW9xb+@jMEwizF%tnaAV|wR_s((EBx8pB(Qg0de>$f%)37c`8
z&U~Ie@!YA`DGN9QQAIFWHvuPNdwV;yz_?=aRzm&Z+@Zu4YrKETN><^9PE^5dmr6=p
z**vv~{L9C2lGR_bp&NmiCJ@KAcV-fDe#g53|3$!sI
zBj%%iG?!L`Jb{IT7Crmv%FoK$W|$NAMcoo7jEM^?KP^Y$(6?_X;}ch$lW-Erg)%bw
zH#{>V!UZi8izxiB$gD#RM!*4{T!xF@myzAfxnyrsG~l=DiZVic3E9Y}&Mcqt=yU13
z9%WI)xK$VYkA}`5|7t*_HWaX}1%KY=!P3vO)B3AF`uy-e`gU*aR;Hb8-MJaH`sU=_
zpOezT^K+4nyG?pLUpaXU8~;UeqgnB>Cp|v7-Y_t+?C)XGyp_P$selSv|IUJ39k42K
zDjUxta17yhLu#il+V@d`>0fPWMLidM*7*VtqTJR7Imxi)UWIaEdB;Lx{arhC%(^Ga
z5S4Ve@8e&x17$5ytLF&h$1w)&~zmHHb%5-
z!Fhu(t`RXM60+fA4Aio1iYNsvsz;CV$d<%F-Yy1$K8Ry@*ExsrnuCPmr+w6%Z{>yW
zlaF`!*F9ezXu;NQ{zR)34m#Gy1Gd@t%>nC3Eo;dk)a{?_>DY_I7DGz(2prVjGfu
zXq%%f#A2aQad9g>_X
zf{(6AfJc*|RYRI}75nWaeMbTBhT}ZSyG#fW1g1M)vV3O68E%9v^?ir*8TP_
z4qnhWk|`wYw$pnXZg%KVqm`)2VvE3!zy*d82Q@7iLUi7JtUHR&
z5HR*tdLUU|uKY~8a45ikx%Y{lD$%=io12u$j%Z2<=}KJlnsxpGJSxcXho?VVRR%ot
zm7sq7AjyCE^zElXN?`TJa=dgse-Da{|
z!D?F9f&F*6GzY$uYx%2GCyUEjp^?E+_7@U=qf4hU{Llh(=U&CDC`t{))55C
zuBCJHE{;@0i|Jh^Oz>*EqQjUst-!Y+n;}E$Kz1Ny!+rv<^4%;+fZvr%Az#4Pz4J|M
zlkek|T-g2oA-zpXNdA=0BCQqKL}Pid>tpB8deS3|5x=Vv+>rCdFbK#J)X%vNfXaUe
zLOIiRWiWiEm=|H$2`}X9DWMi(Q8DzJOpDdT
zqIXix@#_G*-*I7p%HZuk6DVpdIu#Q^d*z6na#AGv
zX%^O!c=b{2`g5!!U&tHunSkQ*
zi(hv_dPVZK^(ZnQpM;;Xu540lTE5iqe_NpQ;aErEChWH#;631eoxY15K9
z4jXto#^p*dXo+?b#~sUB+ow7l!_<+X*6~44R;pu~{wZ938RMh5ymP&3_C1?Z_$c58v&I256~*Jo_CSsK>7ba9KLv;Qb4)v7U7K$^Uw+R$K$~#I+w6@d0Yn
zG-sWOEmkmcI6_V77V=S(VxcCJ$RU=M`7E|DPVOU<6};-JZmRRXs9}>gZ0$vmA^V`t
zpVBgZO0R^S`dl3g>pZ?Sg;fZvbmsHPvtZRJ)#;S^?dm4hMhFBDr!~%h_
zA&ikDMah&(7yV2l1ZTlW?4`+PXTN5+p_`A14Yd
ziTcPe%Dl1%?zny8#bJ{58Md-tFNvRG^J%+h&>rsMJP0ughu4!=1|(uioh%+*?b{!r
zcntpWDn$I7OJ;L5E9Q8JTuw&p!r&2co#3By$g+xdUyK{ZeX$iDbd;GNy%mA&1k9w2@I3H375o`)%U--Vn`tpMlJ!{{u21S73?e
zJmJ_SdY84|1?x%siYjXW<$P*W8%b;o`l(QYKp2xH$72UcC
zto~0RB+gvYeNx7x#n)NX%Ejm55ohG>tG@Bkq|eo(euzz-Ll9)KI##vIvE}m1f$-7y=@5b`zZ!Efd6zOry$2BZ+%0L!m+7~Ak
zXdK8AKx^(d0VzVS4<|x|m#q&9wklrr2UoNqN(+dp1!9jCrqreDO*)TS|5MKV!MXwZ
zcb&I@@NIEnnPF8mFaDh|_p!+26lkduGOxU6bAqvETch{|=flp3ggPW@qUQvwb}F#`
zVVdfD(lC1$m
z97ea{&$(b(^gqB$^BC0g;A6wxWSbMpRfb+nX4mq3;=5S9RgGfTE!JN$Xm7ZfyNV&>
zO+ToUjJmPQ=*!P7L(2Cm)qN>O=6JuRF1J=t$QS>Yo6k`SV*0*Pihyfa^jQEVFn`R}
z5SL%Xs!}J(+p)%7KPHG|+=lh}ehJ_(;c_q~li ^u=neIb1x
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 |