mirror of
https://github.com/bombsquad-community/plugin-manager.git
synced 2025-10-08 14:54:36 +00:00
Update metadata format
This commit is contained in:
parent
40c4c4d6a8
commit
4f8180d06d
5 changed files with 191 additions and 159 deletions
20
index.json
20
index.json
|
|
@ -1,19 +1,7 @@
|
||||||
{
|
{
|
||||||
"plugin_categories": [
|
"categories": [
|
||||||
{
|
"https://github.com/bombsquad-community/plugin-manager/{content_type}/main/plugins/utilities.json",
|
||||||
"display_name": "Utilities",
|
"https://github.com/bombsquad-community/plugin-manager/{content_type}/main/plugins/minigames.json",
|
||||||
"meta": "https://github.com/bombsquad-community/mod-manager/raw/main/plugins/utilities.json",
|
"https://github.com/bombsquad-community/plugin-manager/{content_type}/main/plugins/maps.json"
|
||||||
"base_download_url": "https://github.com/bombsquad-community/mod-manager/raw/main/plugins/utilities"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"display_name": "Minigames",
|
|
||||||
"meta": "https://github.com/bombsquad-community/mod-manager/raw/main/plugins/minigames.json",
|
|
||||||
"base_download_url": "https://github.com/bombsquad-community/mod-manager/raw/main/plugins/minigames"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"display_name": "Maps",
|
|
||||||
"meta": "https://github.com/bombsquad-community/mod-manager/raw/main/plugins/maps.json",
|
|
||||||
"base_download_url": "https://github.com/bombsquad-community/mod-manager/raw/main/plugins/maps"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ from typing import Union, Optional
|
||||||
_env = _ba.env()
|
_env = _ba.env()
|
||||||
_uiscale = ba.app.ui.uiscale
|
_uiscale = ba.app.ui.uiscale
|
||||||
|
|
||||||
INDEX_META = "https://raw.githubusercontent.com/bombsquad-community/mod-manager/main/index.json"
|
INDEX_META = "https://github.com/bombsquad-community/plugin-manager/{content_type}/main/index.json"
|
||||||
HEADERS = {
|
HEADERS = {
|
||||||
"User-Agent": _env["user_agent_string"],
|
"User-Agent": _env["user_agent_string"],
|
||||||
}
|
}
|
||||||
|
|
@ -83,49 +83,77 @@ def play_sound():
|
||||||
|
|
||||||
|
|
||||||
class Category:
|
class Category:
|
||||||
def __init__(self, name, base_download_url, meta_url):
|
def __init__(self, meta_url):
|
||||||
self.name = name
|
|
||||||
self.base_download_url = base_download_url
|
|
||||||
self.meta_url = meta_url
|
self.meta_url = meta_url
|
||||||
self.request_headers = HEADERS
|
self.request_headers = HEADERS
|
||||||
self._plugins = _CACHE.get("categories", {}).get(self.name)
|
self._metadata = _CACHE.get("categories", {}).get(meta_url, {}).get("metadata")
|
||||||
|
self._plugins = _CACHE.get("categories", {}).get(meta_url, {}).get("plugins")
|
||||||
|
|
||||||
async def get_plugins(self):
|
async def fetch_metadata(self):
|
||||||
if self._plugins is None:
|
if self._metadata is None:
|
||||||
request = urllib.request.Request(
|
request = urllib.request.Request(
|
||||||
self.meta_url,
|
self.meta_url.format(content_type="raw"),
|
||||||
headers=self.request_headers,
|
headers=self.request_headers,
|
||||||
)
|
)
|
||||||
response = await async_send_network_request(request)
|
response = await async_send_network_request(request)
|
||||||
plugins_info = json.loads(response.read())
|
self._metadata = json.loads(response.read())
|
||||||
self._plugins = ([Plugin(plugin_info, self.base_download_url)
|
self.set_category_global_cache("metadata", self._metadata)
|
||||||
for plugin_info in plugins_info.items()])
|
return self
|
||||||
self.set_category_plugins_global_cache(self._plugins)
|
|
||||||
|
async def get_name(self):
|
||||||
|
if self._metadata is None:
|
||||||
|
await self.fetch_metadata()
|
||||||
|
return self._metadata["name"]
|
||||||
|
|
||||||
|
async def get_description(self):
|
||||||
|
if self._metadata is None:
|
||||||
|
await self.fetch_metadata()
|
||||||
|
return self._metadata["description"]
|
||||||
|
|
||||||
|
async def get_plugins_base_url(self):
|
||||||
|
if self._metadata is None:
|
||||||
|
await self.fetch_metadata()
|
||||||
|
return self._metadata["plugins_base_url"]
|
||||||
|
|
||||||
|
async def get_plugins(self):
|
||||||
|
if self._plugins is None:
|
||||||
|
if self._metadata is None:
|
||||||
|
await self.fetch_metadata()
|
||||||
|
self._plugins = ([
|
||||||
|
Plugin(plugin_info, f"{await self.get_plugins_base_url()}/{plugin_info[0]}.py")
|
||||||
|
for plugin_info in self._metadata["plugins"].items()
|
||||||
|
])
|
||||||
|
self.set_category_global_cache("plugins", self._plugins)
|
||||||
return self._plugins
|
return self._plugins
|
||||||
|
|
||||||
def set_category_plugins_global_cache(self, plugins):
|
def set_category_global_cache(self, key, value):
|
||||||
if "categories" not in _CACHE:
|
if "categories" not in _CACHE:
|
||||||
_CACHE["categories"] = {}
|
_CACHE["categories"] = {}
|
||||||
_CACHE["categories"][self.name] = plugins
|
if self.meta_url not in _CACHE["categories"]:
|
||||||
|
_CACHE["categories"][self.meta_url] = {}
|
||||||
|
_CACHE["categories"][self.meta_url][key] = value
|
||||||
|
|
||||||
def unset_category_plugins_global_cache(self):
|
def unset_category_global_cache(self):
|
||||||
try:
|
try:
|
||||||
del _CACHE["categories"][self.name]
|
del _CACHE["categories"][self.meta_url]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def refresh(self):
|
async def refresh(self):
|
||||||
self._plugins.clear()
|
self.cleanup()
|
||||||
self.unset_category_plugins_global_cache()
|
await self.get_plugins()
|
||||||
|
|
||||||
async def cleanup(self):
|
def cleanup(self):
|
||||||
self.refresh()
|
self._metadata = None
|
||||||
return await self.get_plugins()
|
self._plugins.clear()
|
||||||
|
self.unset_category_global_cache()
|
||||||
|
|
||||||
|
|
||||||
class CategoryAll(Category):
|
class CategoryAll(Category):
|
||||||
def __init__(self, plugins={}):
|
def __init__(self, plugins={}):
|
||||||
super().__init__(name="All", base_download_url=None, meta_url=None)
|
super().__init__(meta_url=None)
|
||||||
|
self._name = "All"
|
||||||
|
self._description = "All plugins"
|
||||||
self._plugins = plugins
|
self._plugins = plugins
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -142,7 +170,7 @@ class PluginLocal:
|
||||||
self._content = None
|
self._content = None
|
||||||
self._api_version = None
|
self._api_version = None
|
||||||
self._entry_points = []
|
self._entry_points = []
|
||||||
self._contains_minigames = None
|
self._has_minigames = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_installed(self):
|
def is_installed(self):
|
||||||
|
|
@ -211,10 +239,10 @@ class PluginLocal:
|
||||||
return self._entry_points
|
return self._entry_points
|
||||||
|
|
||||||
async def has_minigames(self):
|
async def has_minigames(self):
|
||||||
if self._contains_minigames is None:
|
if self._has_minigames is None:
|
||||||
content = await self.get_content()
|
content = await self.get_content()
|
||||||
self._contains_minigames = REGEXP["minigames"].search(content) is not None
|
self._has_minigames = REGEXP["minigames"].search(content) is not None
|
||||||
return self._contains_minigames
|
return self._has_minigames
|
||||||
|
|
||||||
async def is_enabled(self):
|
async def is_enabled(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -288,13 +316,14 @@ class PluginVersion:
|
||||||
|
|
||||||
|
|
||||||
class Plugin:
|
class Plugin:
|
||||||
def __init__(self, plugin, base_download_url):
|
def __init__(self, plugin, url):
|
||||||
"""
|
"""
|
||||||
Initialize a plugin from network repository.
|
Initialize a plugin from network repository.
|
||||||
"""
|
"""
|
||||||
self.name, self.info = plugin
|
self.name, self.info = plugin
|
||||||
self.install_path = os.path.join(PLUGIN_DIRECTORY, f"{self.name}.py")
|
self.install_path = os.path.join(PLUGIN_DIRECTORY, f"{self.name}.py")
|
||||||
self.download_url = f"{base_download_url}/{self.name}.py"
|
self.download_url = url.format(content_type="raw")
|
||||||
|
self.view_url = url.format(content_type="blob")
|
||||||
self._local_plugin = None
|
self._local_plugin = None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
@ -475,7 +504,7 @@ class PluginWindow(popup.PopupWindow):
|
||||||
size=(40, 40),
|
size=(40, 40),
|
||||||
button_type="square",
|
button_type="square",
|
||||||
label="",
|
label="",
|
||||||
on_activate_call=self.open_plugin_page)
|
on_activate_call=lambda: ba.open_url(self.plugin.view_url))
|
||||||
ba.imagewidget(parent=self._root_widget,
|
ba.imagewidget(parent=self._root_widget,
|
||||||
position=(open_pos_x, open_pos_y),
|
position=(open_pos_x, open_pos_y),
|
||||||
size=(40, 40),
|
size=(40, 40),
|
||||||
|
|
@ -489,9 +518,6 @@ class PluginWindow(popup.PopupWindow):
|
||||||
play_sound()
|
play_sound()
|
||||||
ba.containerwidget(edit=self._root_widget, transition='out_scale')
|
ba.containerwidget(edit=self._root_widget, transition='out_scale')
|
||||||
|
|
||||||
def open_plugin_page(self) -> None:
|
|
||||||
ba.open_url(f"https://github.com/bombsquad-community/plugin-manager/tree/main/plugins/utilities/{self.plugin.name}.py")
|
|
||||||
|
|
||||||
def button(fn):
|
def button(fn):
|
||||||
async def asyncio_handler(fn, self, *args, **kwargs):
|
async def asyncio_handler(fn, self, *args, **kwargs):
|
||||||
await fn(self, *args, **kwargs)
|
await fn(self, *args, **kwargs)
|
||||||
|
|
@ -538,26 +564,47 @@ class PluginManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.request_headers = HEADERS
|
self.request_headers = HEADERS
|
||||||
self._index = _CACHE.get("index", {})
|
self._index = _CACHE.get("index", {})
|
||||||
|
self.categories = {}
|
||||||
|
|
||||||
async def get_index(self):
|
async def setup_index(self):
|
||||||
global _INDEX
|
global _INDEX
|
||||||
if not self._index:
|
if not self._index:
|
||||||
request = urllib.request.Request(
|
request = urllib.request.Request(
|
||||||
INDEX_META,
|
INDEX_META.format(content_type="raw"),
|
||||||
headers=self.request_headers,
|
headers=self.request_headers,
|
||||||
)
|
)
|
||||||
response = await async_send_network_request(request)
|
response = await async_send_network_request(request)
|
||||||
self._index = json.loads(response.read())
|
self._index = json.loads(response.read())
|
||||||
self.set_index_global_cache(self._index)
|
self.set_index_global_cache(self._index)
|
||||||
return self._index
|
await self._setup_plugin_categories(self._index)
|
||||||
|
|
||||||
|
async def _setup_plugin_categories(self, plugin_index):
|
||||||
|
# A hack to have the "All" category show at the top.
|
||||||
|
self.categories["All"] = None
|
||||||
|
|
||||||
|
requests = []
|
||||||
|
for plugin_category_url in plugin_index["categories"]:
|
||||||
|
category = Category(plugin_category_url)
|
||||||
|
request = category.fetch_metadata()
|
||||||
|
requests.append(request)
|
||||||
|
categories = await asyncio.gather(*requests)
|
||||||
|
|
||||||
|
all_plugins = []
|
||||||
|
for category in categories:
|
||||||
|
self.categories[await category.get_name()] = category
|
||||||
|
all_plugins.extend(await category.get_plugins())
|
||||||
|
self.categories["All"] = CategoryAll(plugins=all_plugins)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
|
for category in self.categories.values():
|
||||||
|
category.cleanup()
|
||||||
|
self.categories.clear()
|
||||||
self._index.clear()
|
self._index.clear()
|
||||||
self.unset_index_global_cache()
|
self.unset_index_global_cache()
|
||||||
|
|
||||||
async def refresh(self):
|
async def refresh(self):
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
return await self.get_index()
|
await self.setup_index()
|
||||||
|
|
||||||
def set_index_global_cache(self, index):
|
def set_index_global_cache(self, index):
|
||||||
_CACHE["index"] = index
|
_CACHE["index"] = index
|
||||||
|
|
@ -572,16 +619,15 @@ class PluginManager:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PluginManagerWindow(ba.Window, PluginManager):
|
class PluginManagerWindow(ba.Window):
|
||||||
def __init__(self, transition: str = "in_right", origin_widget: ba.Widget = None):
|
def __init__(self, transition: str = "in_right", origin_widget: ba.Widget = None):
|
||||||
PluginManager.__init__(self)
|
self.plugin_manager = PluginManager()
|
||||||
self.categories = {}
|
|
||||||
self.category_selection_button = None
|
self.category_selection_button = None
|
||||||
self.selected_category = None
|
self.selected_category = None
|
||||||
self.plugins_in_current_view = {}
|
self.plugins_in_current_view = {}
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
loop.create_task(self.plugin_index())
|
loop.create_task(self.draw_index())
|
||||||
|
|
||||||
self._width = (490 if _uiscale is ba.UIScale.MEDIUM else 570)
|
self._width = (490 if _uiscale is ba.UIScale.MEDIUM else 570)
|
||||||
self._height = (500 if _uiscale is ba.UIScale.SMALL
|
self._height = (500 if _uiscale is ba.UIScale.SMALL
|
||||||
|
|
@ -634,11 +680,11 @@ class PluginManagerWindow(ba.Window, PluginManager):
|
||||||
v_align="center",
|
v_align="center",
|
||||||
maxwidth=270,
|
maxwidth=270,
|
||||||
)
|
)
|
||||||
|
|
||||||
loading_pos_y = self._height - (235 if _uiscale is ba.UIScale.SMALL else
|
loading_pos_y = self._height - (235 if _uiscale is ba.UIScale.SMALL else
|
||||||
220 if _uiscale is ba.UIScale.MEDIUM else 250)
|
220 if _uiscale is ba.UIScale.MEDIUM else 250)
|
||||||
|
|
||||||
self._loading_text = ba.textwidget(
|
self._plugin_manager_status_text = ba.textwidget(
|
||||||
parent=self._root_widget,
|
parent=self._root_widget,
|
||||||
position=(-5, loading_pos_y),
|
position=(-5, loading_pos_y),
|
||||||
size=(self._width, 25),
|
size=(self._width, 25),
|
||||||
|
|
@ -738,43 +784,24 @@ class PluginManagerWindow(ba.Window, PluginManager):
|
||||||
ba.app.ui.set_main_menu_window(
|
ba.app.ui.set_main_menu_window(
|
||||||
AllSettingsWindow(transition='in_left').get_root_widget())
|
AllSettingsWindow(transition='in_left').get_root_widget())
|
||||||
|
|
||||||
async def setup_plugin_categories(self, plugin_index):
|
async def draw_index(self):
|
||||||
self.categories["All"] = None
|
|
||||||
requests = []
|
|
||||||
for plugin_category in plugin_index["plugin_categories"]:
|
|
||||||
category = Category(
|
|
||||||
plugin_category["display_name"],
|
|
||||||
plugin_category["base_download_url"],
|
|
||||||
plugin_category["meta"],
|
|
||||||
)
|
|
||||||
self.categories[plugin_category["display_name"]] = category
|
|
||||||
request = category.get_plugins()
|
|
||||||
requests.append(request)
|
|
||||||
categories = await asyncio.gather(*requests)
|
|
||||||
|
|
||||||
all_plugins = []
|
|
||||||
for plugins in categories:
|
|
||||||
all_plugins.extend(plugins)
|
|
||||||
self.categories["All"] = CategoryAll(plugins=all_plugins)
|
|
||||||
|
|
||||||
async def plugin_index(self):
|
|
||||||
try:
|
try:
|
||||||
index = await super().get_index()
|
|
||||||
await self.draw_search_bar()
|
await self.draw_search_bar()
|
||||||
await self.setup_plugin_categories(index)
|
await self.draw_category_selection_button(post_label="All")
|
||||||
await self.select_category("All")
|
|
||||||
await self.draw_refresh_icon()
|
await self.draw_refresh_icon()
|
||||||
await self.draw_settings_icon()
|
await self.draw_settings_icon()
|
||||||
|
await self.plugin_manager.setup_index()
|
||||||
|
ba.textwidget(edit=self._plugin_manager_status_text,
|
||||||
|
text="")
|
||||||
|
await self.select_category("All")
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
# User probably went back before the PluginManagerWindow could finish loading.
|
# User probably went back before the PluginManagerWindow could finish loading.
|
||||||
pass
|
pass
|
||||||
except urllib.error.URLError:
|
except urllib.error.URLError:
|
||||||
ba.textwidget(edit=self._loading_text,
|
ba.textwidget(edit=self._plugin_manager_status_text,
|
||||||
text="Make sure you are connected\n to the Internet and try again.")
|
text="Make sure you are connected\n to the Internet and try again.")
|
||||||
else:
|
|
||||||
self._loading_text.delete()
|
|
||||||
|
|
||||||
async def draw_category_selection_button(self, label=None):
|
async def draw_category_selection_button(self, post_label):
|
||||||
# v = (self._height - 75) if _uiscale is ba.UIScale.SMALL else (self._height - 105)
|
# v = (self._height - 75) if _uiscale is ba.UIScale.SMALL else (self._height - 105)
|
||||||
# v = 395
|
# v = 395
|
||||||
# h = 440
|
# h = 440
|
||||||
|
|
@ -793,16 +820,14 @@ class PluginManagerWindow(ba.Window, PluginManager):
|
||||||
b_textcolor = (0.75, 0.7, 0.8)
|
b_textcolor = (0.75, 0.7, 0.8)
|
||||||
b_color = (0.6, 0.53, 0.63)
|
b_color = (0.6, 0.53, 0.63)
|
||||||
|
|
||||||
if label is None:
|
label = f"Category: {post_label}"
|
||||||
label = self.selected_category
|
|
||||||
label = f"Category: {label}"
|
|
||||||
|
|
||||||
if self.category_selection_button is None:
|
if self.category_selection_button is None:
|
||||||
self.category_selection_button = ba.buttonwidget(parent=self._root_widget,
|
self.category_selection_button = ba.buttonwidget(parent=self._root_widget,
|
||||||
position=(category_pos_x,
|
position=(category_pos_x,
|
||||||
category_pos_y),
|
category_pos_y),
|
||||||
size=b_size,
|
size=b_size,
|
||||||
on_activate_call=self.show_categories,
|
on_activate_call=lambda: self.show_categories(),
|
||||||
label=label,
|
label=label,
|
||||||
button_type="square",
|
button_type="square",
|
||||||
color=b_color,
|
color=b_color,
|
||||||
|
|
@ -875,7 +900,7 @@ class PluginManagerWindow(ba.Window, PluginManager):
|
||||||
texture=ba.gettexture("replayIcon"),
|
texture=ba.gettexture("replayIcon"),
|
||||||
draw_controller=controller_button)
|
draw_controller=controller_button)
|
||||||
|
|
||||||
async def draw_plugin_names(self):
|
async def draw_plugin_names(self, category):
|
||||||
# v = (self._height - 75) if _uiscale is ba.UIScale.SMALL else (self._height - 105)
|
# v = (self._height - 75) if _uiscale is ba.UIScale.SMALL else (self._height - 105)
|
||||||
# h = 440
|
# h = 440
|
||||||
# next 2 lines belong in 1 line
|
# next 2 lines belong in 1 line
|
||||||
|
|
@ -889,7 +914,7 @@ class PluginManagerWindow(ba.Window, PluginManager):
|
||||||
for plugin in self._columnwidget.get_children():
|
for plugin in self._columnwidget.get_children():
|
||||||
plugin.delete()
|
plugin.delete()
|
||||||
|
|
||||||
plugins = await self.categories[self.selected_category].get_plugins()
|
plugins = await self.plugin_manager.categories[category].get_plugins()
|
||||||
plugin_names_to_draw = tuple(self.draw_plugin_name(plugin) for plugin in plugins)
|
plugin_names_to_draw = tuple(self.draw_plugin_name(plugin) for plugin in plugins)
|
||||||
await asyncio.gather(*plugin_names_to_draw)
|
await asyncio.gather(*plugin_names_to_draw)
|
||||||
|
|
||||||
|
|
@ -939,15 +964,15 @@ class PluginManagerWindow(ba.Window, PluginManager):
|
||||||
position=(200, 0),
|
position=(200, 0),
|
||||||
scale=(2.3 if _uiscale is ba.UIScale.SMALL else
|
scale=(2.3 if _uiscale is ba.UIScale.SMALL else
|
||||||
1.65 if _uiscale is ba.UIScale.MEDIUM else 1.23),
|
1.65 if _uiscale is ba.UIScale.MEDIUM else 1.23),
|
||||||
choices=self.categories.keys(),
|
choices=self.plugin_manager.categories.keys(),
|
||||||
current_choice=self.selected_category,
|
current_choice=self.selected_category,
|
||||||
delegate=self)
|
delegate=self)
|
||||||
|
|
||||||
async def select_category(self, category):
|
async def select_category(self, category):
|
||||||
self.selected_category = category
|
self.selected_category = category
|
||||||
self.plugins_in_current_view.clear()
|
self.plugins_in_current_view.clear()
|
||||||
await self.draw_category_selection_button(label=category)
|
await self.draw_category_selection_button(post_label=category)
|
||||||
await self.draw_plugin_names()
|
await self.draw_plugin_names(category)
|
||||||
|
|
||||||
def popup_menu_selected_choice(self, window, choice):
|
def popup_menu_selected_choice(self, window, choice):
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
@ -957,19 +982,23 @@ class PluginManagerWindow(ba.Window, PluginManager):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
super().cleanup()
|
self.plugin_manager.cleanup()
|
||||||
self.categories.clear()
|
|
||||||
for plugin in self._columnwidget.get_children():
|
for plugin in self._columnwidget.get_children():
|
||||||
plugin.delete()
|
plugin.delete()
|
||||||
self.plugins_in_current_view.clear()
|
self.plugins_in_current_view.clear()
|
||||||
|
|
||||||
async def _refresh(self):
|
async def _refresh(self):
|
||||||
index = await super().refresh()
|
await self.plugin_manager.refresh()
|
||||||
await self.setup_plugin_categories(index)
|
await self.plugin_manager.setup_index()
|
||||||
|
ba.textwidget(edit=self._plugin_manager_status_text,
|
||||||
|
text="")
|
||||||
await self.select_category(self.selected_category)
|
await self.select_category(self.selected_category)
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
play_sound()
|
play_sound()
|
||||||
|
self.cleanup()
|
||||||
|
ba.textwidget(edit=self._plugin_manager_status_text,
|
||||||
|
text="Refreshing...")
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
loop.create_task(self._refresh())
|
loop.create_task(self._refresh())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1,6 @@
|
||||||
{}
|
{
|
||||||
|
"name": "Maps",
|
||||||
|
"description": "Maps",
|
||||||
|
"plugins_base_url": "https://github.com/bombsquad-community/plugin-manager/{content_type}/main/plugins/maps",
|
||||||
|
"plugins": {}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,26 @@
|
||||||
{
|
{
|
||||||
"alliance_elimination": {
|
"name": "Minigames",
|
||||||
"description": "Fight in groups of duo, trio, or more. Last remaining alive wins.",
|
"description": "Minigames",
|
||||||
"external_url": "",
|
"plugins_base_url": "https://github.com/bombsquad-community/plugin-manager/{content_type}/main/plugins/minigames",
|
||||||
"authors": [
|
"plugins": {
|
||||||
{
|
"alliance_elimination": {
|
||||||
"name": "Rikko",
|
"description": "Fight in groups of duo, trio, or more. Last remaining alive wins.",
|
||||||
"email": "rikkolovescats@proton.me",
|
"external_url": "",
|
||||||
"discord": "Rikko#7383"
|
"authors": [
|
||||||
}
|
{
|
||||||
],
|
"name": "Rikko",
|
||||||
"versions": {
|
"email": "rikkolovescats@proton.me",
|
||||||
"1.1.0": {
|
"discord": "Rikko#7383"
|
||||||
"api_version": 7,
|
}
|
||||||
"commit_sha": "cbdb3ead",
|
],
|
||||||
"dependencies": [],
|
"versions": {
|
||||||
"released_on": "08-08-2022",
|
"1.1.0": {
|
||||||
"md5sum": "11dbb3c7e37e97bda028ea1251529ea0"
|
"api_version": 7,
|
||||||
|
"commit_sha": "cbdb3ead",
|
||||||
|
"dependencies": [],
|
||||||
|
"released_on": "08-08-2022",
|
||||||
|
"md5sum": "11dbb3c7e37e97bda028ea1251529ea0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,51 @@
|
||||||
{
|
{
|
||||||
"colorscheme": {
|
"name": "Utilities",
|
||||||
"description": "Create custom UI colorschemes!",
|
"description": "Utilities",
|
||||||
"external_url": "https://www.youtube.com/watch?v=qatwWrBAvjc",
|
"plugins_base_url": "https://github.com/bombsquad-community/plugin-manager/{content_type}/main/plugins/utilities",
|
||||||
"authors": [
|
"plugins": {
|
||||||
{
|
"colorscheme": {
|
||||||
"name": "Rikko",
|
"description": "Create custom UI colorschemes!",
|
||||||
"email": "rikkolovescats@proton.me",
|
"external_url": "https://www.youtube.com/watch?v=qatwWrBAvjc",
|
||||||
"discord": "Rikko#7383"
|
"authors": [
|
||||||
},
|
{
|
||||||
{
|
"name": "Rikko",
|
||||||
"name": "Vishal",
|
"email": "rikkolovescats@proton.me",
|
||||||
"email": "vishal.u338@gmail.com",
|
"discord": "Rikko#7383"
|
||||||
"discord": "𝑽𝑰𝑺𝑯𝑼𝑼𝑼#2921"
|
},
|
||||||
|
{
|
||||||
|
"name": "Vishal",
|
||||||
|
"email": "vishal.u338@gmail.com",
|
||||||
|
"discord": "𝑽𝑰𝑺𝑯𝑼𝑼𝑼#2921"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"versions": {
|
||||||
|
"1.1.0": {
|
||||||
|
"api_version": 7,
|
||||||
|
"commit_sha": "13a9d128",
|
||||||
|
"dependencies": [],
|
||||||
|
"released_on": "03-06-2022",
|
||||||
|
"md5sum": "4b6bbb99037ebda4664da7c510b3717c"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
"versions": {
|
"store_event_specials": {
|
||||||
"1.1.0": {
|
"description": "Exposes event-special store items not normally available for purchase",
|
||||||
"api_version": 7,
|
"external_url": "",
|
||||||
"commit_sha": "13a9d128",
|
"authors": [
|
||||||
"dependencies": [],
|
{
|
||||||
"released_on": "03-06-2022",
|
"name": "Rikko",
|
||||||
"md5sum": "4b6bbb99037ebda4664da7c510b3717c"
|
"email": "rikkolovescats@proton.me",
|
||||||
}
|
"discord": "Rikko#7383"
|
||||||
}
|
}
|
||||||
},
|
],
|
||||||
"store_event_specials": {
|
"versions": {
|
||||||
"description": "Exposes event-special store items not normally available for purchase",
|
"1.0.0": {
|
||||||
"external_url": "",
|
"api_version": 7,
|
||||||
"authors": [
|
"commit_sha": "2aa6df31",
|
||||||
{
|
"dependencies": [],
|
||||||
"name": "Rikko",
|
"released_on": "06-08-2022",
|
||||||
"email": "rikkolovescats@proton.me",
|
"md5sum": "233dfaa7f0e9394d21454f4ffa7d0205"
|
||||||
"discord": "Rikko#7383"
|
}
|
||||||
}
|
|
||||||
],
|
|
||||||
"versions": {
|
|
||||||
"1.0.0": {
|
|
||||||
"api_version": 7,
|
|
||||||
"commit_sha": "2aa6df31",
|
|
||||||
"dependencies": [],
|
|
||||||
"released_on": "06-08-2022",
|
|
||||||
"md5sum": "233dfaa7f0e9394d21454f4ffa7d0205"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue