Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
return m.Pkg(
source=self.source,
id=project_metadata['full_name'],
slug=project_metadata['full_name'].lower(),
name=project_metadata['name'],
description=project_metadata['description'],
url=project_metadata['html_url'],
download_url=matching_asset['browser_download_url'],
date_published=release_metadata['published_at'],
version=release_metadata['tag_name'],
options=m.PkgOptions(strategy=defn.strategy.name),
)
class InstawowResolver(Resolver):
source = 'instawow'
name = 'instawow'
strategies = {Strategies.default}
_addons = {
('0', 'weakauras-companion'),
('1', 'weakauras-companion-autoupdate'),
}
async def resolve_one(self, defn: Defn, metadata: Any = None) -> m.Pkg:
try:
id_, slug = next(p for p in self._addons if defn.name in p)
except StopIteration:
raise E.PkgNonexistent
from .wa_updater import BuilderConfig, WaCompanionBuilder
async def resolve(self, defns: List[Defn]) -> Dict[Defn, Any]:
"Resolve add-on definitions into packages."
results = await gather(self.resolve_one(d) for d in defns)
return dict(zip(defns, results))
async def resolve_one(self, defn: Defn, metadata: O[JsonDict] = None) -> m.Pkg:
"Resolve an individual definition into a package."
raise NotImplementedError
async def collect_items(self) -> AsyncIterable[_CItem]:
"Yield add-ons from source for cataloguing."
return
yield
class CurseResolver(Resolver):
source = 'curse'
name = 'CurseForge'
strategies = {
Strategies.default,
Strategies.latest,
Strategies.curse_latest_beta,
Strategies.curse_latest_alpha,
Strategies.any_flavour,
Strategies.version,
}
# Reference: https://twitchappapi.docs.apiary.io/
addon_api_url = URL('https://addons-ecs.forgesvc.net/api/v2/addon')
@staticmethod
def get_name_from_url(value: str) -> O[str]:
async def collect_items(self) -> AsyncIterable[_CItem]:
async with self.web_client.get(self.list_api_url) as response:
json_response = await response.json()
for item in json_response:
yield _CItem(
source=self.source,
id=item['UID'],
name=item['UIName'],
folders=[item['UIDir']],
compatibility={'retail', 'classic'},
)
class TukuiResolver(Resolver):
source = 'tukui'
name = 'Tukui'
strategies = {Strategies.default}
api_url = URL('https://www.tukui.org/api.php')
retail_uis = {'-1': 'tukui', '-2': 'elvui', 'tukui': 'tukui', 'elvui': 'elvui'}
@staticmethod
def get_name_from_url(value: str) -> O[str]:
url = URL(value)
if url.host == 'www.tukui.org' and url.path in {
'/addons.php',
'/classic-addons.php',
'/download.php',
}:
folders = uniq(
tuple(m['foldername'] for m in f['modules'])
for f in item['latestFiles']
if not f['exposeAsAlternative']
)
yield _CItem(
source=self.source,
id=item['id'],
slug=item['slug'],
name=item['name'],
folders=folders,
compatibility=set(excise_compatibility(item['latestFiles'])),
)
class WowiResolver(Resolver):
source = 'wowi'
name = 'WoWInterface'
strategies = {Strategies.default}
# Reference: https://api.mmoui.com/v3/globalconfig.json
# There's also a v4 API corresponding to the as yet unreleased Minion v4,
# which is fair to assume is unstable. They changed the naming scheme to
# camelCase and some fields which were strings were converted to numbers.
# Neither API provides access to classic files for multi-file add-ons and
# 'UICompatibility' can't be relied on to enforce compatibility
# in instawow. The API appears to inherit the version of the _latest_
# file to have been uploaded, which for multi-file add-ons can be the
# classic version. Hoooowever the download link always points to the
# 'retail' version, which for single-file add-ons belonging to the
# classic category would be an add-on for classic.
list_api_url = 'https://api.mmoui.com/v3/game/WOW/filelist.json'
source=self.source,
id=metadata['id'],
name=metadata['name'],
compatibility={compatibility},
)
else:
for item in metadata:
yield _CItem(
source=self.source,
id=item['id'],
name=item['name'],
compatibility={compatibility},
)
class GithubResolver(Resolver):
source = 'github'
name = 'GitHub'
strategies = {
Strategies.default,
Strategies.version,
}
repos_api_url = URL('https://api.github.com/repos')
@staticmethod
def get_name_from_url(value: str) -> O[str]:
url = URL(value)
if url.host == 'github.com' and len(url.parts) > 2:
return '/'.join(url.parts[1:3])
async def resolve_one(self, defn: Defn, metadata: Any = None) -> m.Pkg:
return dict.fromkeys(defns, E.PkgSourceInvalid())
class _ResolverDict(dict):
def __missing__(self, key: str) -> Resolver:
return _DummyResolver
async def _error_out(error: Union[E.ManagerError, E.InternalError]) -> NoReturn:
raise error
class Manager:
config: Config
db_session: scoped_session
resolvers: Mapping[str, Resolver]
catalogue: MasterCatalogue
resolver_classes = (
CurseResolver,
WowiResolver,
TukuiResolver,
GithubResolver,
InstawowResolver,
)
def __init__(self, config: Config, db_session: scoped_session) -> None:
self.config = config
self.db_session = db_session
self.resolvers = _ResolverDict((r.source, r(self)) for r in self.resolver_classes)
self.catalogue = None # type: ignore