mirror of
https://github.com/WowUp/WowUp.git
synced 2026-04-23 15:27:03 -04:00
more model prep
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { WowClientType } from "app/models/warcraft/wow-client-type";
|
||||
import { WowClientType } from "../../models/warcraft/wow-client-type";
|
||||
import { Addon } from "../entities/addon";
|
||||
import { PotentialAddon } from "app/models/wowup/potential-addon";
|
||||
import { AddonSearchResult } from "app/models/wowup/addon-search-result";
|
||||
import { PotentialAddon } from "../../models/wowup/potential-addon";
|
||||
import { AddonSearchResult } from "../../models/wowup/addon-search-result";
|
||||
|
||||
export interface AddonProvider {
|
||||
|
||||
|
||||
@@ -11,153 +11,181 @@ import { Observable } from "rxjs";
|
||||
import { AddonSearchResultFile } from "app/models/wowup/addon-search-result-file";
|
||||
import { CurseReleaseType } from "app/models/curse/curse-release-type";
|
||||
import { AddonChannelType } from "app/models/wowup/addon-channel-type";
|
||||
import { PotentialAddon } from "../../models/wowup/potential-addon";
|
||||
|
||||
const API_URL = "https://addons-ecs.forgesvc.net/api/v2";
|
||||
|
||||
export class CurseAddonProvider implements AddonProvider {
|
||||
|
||||
private readonly _httpClient: HttpClient;
|
||||
private readonly _httpClient: HttpClient;
|
||||
|
||||
public readonly name = "Curse";
|
||||
public readonly name = "Curse";
|
||||
|
||||
constructor(httpClient: HttpClient) {
|
||||
this._httpClient = httpClient;
|
||||
}
|
||||
constructor(httpClient: HttpClient) {
|
||||
this._httpClient = httpClient;
|
||||
}
|
||||
|
||||
getAll(clientType: WowClientType, addonIds: string[]): Promise<import("../../models/wowup/addon-search-result").AddonSearchResult[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getAll(clientType: WowClientType, addonIds: string[]): Promise<import("../../models/wowup/addon-search-result").AddonSearchResult[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
getFeaturedAddons(clientType: WowClientType): Promise<import("../../models/wowup/potential-addon").PotentialAddon[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
getFeaturedAddons(clientType: WowClientType): Promise<PotentialAddon[]> {
|
||||
|
||||
searchByQuery(query: string, clientType: WowClientType): Promise<import("../../models/wowup/potential-addon").PotentialAddon[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
searchByUrl(addonUri: URL, clientType: WowClientType): Promise<import("../../models/wowup/potential-addon").PotentialAddon> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
searchByQuery(query: string, clientType: WowClientType): Promise<import("../../models/wowup/potential-addon").PotentialAddon[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
searchByName(addonName: string, folderName: string, clientType: WowClientType, nameOverride?: string): Promise<import("../../models/wowup/addon-search-result").AddonSearchResult[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
searchByUrl(addonUri: URL, clientType: WowClientType): Promise<import("../../models/wowup/potential-addon").PotentialAddon> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
getById(addonId: string, clientType: WowClientType): Promise<AddonSearchResult> {
|
||||
const url = `${API_URL}/addon/${addonId}`;
|
||||
searchByName(addonName: string, folderName: string, clientType: WowClientType, nameOverride?: string): Promise<import("../../models/wowup/addon-search-result").AddonSearchResult[]> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
return this._httpClient.get<CurseSearchResult>(url)
|
||||
.pipe(
|
||||
map(result => {
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
getById(addonId: string, clientType: WowClientType): Promise<AddonSearchResult> {
|
||||
const url = `${API_URL}/addon/${addonId}`;
|
||||
|
||||
const latestFiles = this.getLatestFiles(result, clientType);
|
||||
if (!latestFiles?.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.getAddonSearchResult(result, latestFiles);
|
||||
})
|
||||
)
|
||||
.toPromise();
|
||||
}
|
||||
|
||||
isValidAddonUri(addonUri: URL): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
onPostInstall(addon: Addon): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
private getAddonSearchResult(result: CurseSearchResult, latestFiles: CurseFile[]): AddonSearchResult {
|
||||
try {
|
||||
var thumbnailUrl = this.getThumbnailUrl(result);
|
||||
var id = result.id;
|
||||
var name = result.name;
|
||||
var author = this.getAuthor(result);
|
||||
|
||||
var searchResultFiles: AddonSearchResultFile[] = latestFiles.map(lf => {
|
||||
return {
|
||||
channelType: this.getChannelType(lf.releaseType),
|
||||
version: lf.fileName,
|
||||
downloadUrl: lf.downloadUrl,
|
||||
folders: this.getFolderNames(lf),
|
||||
gameVersion: this.getGameVersion(lf)
|
||||
};
|
||||
});
|
||||
|
||||
var searchResult: AddonSearchResult = {
|
||||
author,
|
||||
externalId: id.toString(),
|
||||
name,
|
||||
thumbnailUrl,
|
||||
externalUrl: result.websiteUrl,
|
||||
providerName: this.name,
|
||||
files: searchResultFiles
|
||||
};
|
||||
|
||||
return searchResult;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return this._httpClient.get<CurseSearchResult>(url)
|
||||
.pipe(
|
||||
map(result => {
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getChannelType(releaseType: CurseReleaseType): AddonChannelType {
|
||||
switch (releaseType) {
|
||||
case CurseReleaseType.Alpha:
|
||||
return AddonChannelType.Alpha;
|
||||
case CurseReleaseType.Beta:
|
||||
return AddonChannelType.Beta;
|
||||
case CurseReleaseType.Release:
|
||||
default:
|
||||
return AddonChannelType.Stable;
|
||||
}
|
||||
}
|
||||
const latestFiles = this.getLatestFiles(result, clientType);
|
||||
if (!latestFiles?.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private getFolderNames(file: CurseFile): string[] {
|
||||
return file.modules.map(m => m.foldername);
|
||||
}
|
||||
return this.getAddonSearchResult(result, latestFiles);
|
||||
})
|
||||
)
|
||||
.toPromise();
|
||||
}
|
||||
|
||||
private getGameVersion(file: CurseFile): string {
|
||||
return _.first(file.gameVersion);
|
||||
}
|
||||
isValidAddonUri(addonUri: URL): boolean {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
private getAuthor(result: CurseSearchResult): string {
|
||||
var authorNames = result.authors.map(a => a.name);
|
||||
return authorNames.join(', ');
|
||||
}
|
||||
onPostInstall(addon: Addon): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
private getThumbnailUrl(result: CurseSearchResult): string {
|
||||
const attachment = _.find(result.attachments, f => f.isDefault && !!f.thumbnailUrl);
|
||||
return attachment?.thumbnailUrl;
|
||||
}
|
||||
private getAddonSearchResult(result: CurseSearchResult, latestFiles: CurseFile[]): AddonSearchResult {
|
||||
try {
|
||||
var thumbnailUrl = this.getThumbnailUrl(result);
|
||||
var id = result.id;
|
||||
var name = result.name;
|
||||
var author = this.getAuthor(result);
|
||||
|
||||
private getLatestFiles(result: CurseSearchResult, clientType: WowClientType): CurseFile[] {
|
||||
const clientTypeStr = this.getClientTypeString(clientType);
|
||||
var searchResultFiles: AddonSearchResultFile[] = latestFiles.map(lf => {
|
||||
return {
|
||||
channelType: this.getChannelType(lf.releaseType),
|
||||
version: lf.fileName,
|
||||
downloadUrl: lf.downloadUrl,
|
||||
folders: this.getFolderNames(lf),
|
||||
gameVersion: this.getGameVersion(lf)
|
||||
};
|
||||
});
|
||||
|
||||
return _.flow(
|
||||
_.filter((f: CurseFile) => f.isAlternate == false && f.gameVersionFlavor == clientTypeStr),
|
||||
_.orderBy((f: CurseFile) => f.id),
|
||||
_.reverse
|
||||
)(result.latestFiles) as CurseFile[];
|
||||
}
|
||||
var searchResult: AddonSearchResult = {
|
||||
author,
|
||||
externalId: id.toString(),
|
||||
name,
|
||||
thumbnailUrl,
|
||||
externalUrl: result.websiteUrl,
|
||||
providerName: this.name,
|
||||
files: searchResultFiles
|
||||
};
|
||||
|
||||
private getClientTypeString(clientType: WowClientType): string {
|
||||
switch (clientType) {
|
||||
case WowClientType.Classic:
|
||||
case WowClientType.ClassicPtr:
|
||||
return "wow_classic";
|
||||
case WowClientType.Retail:
|
||||
case WowClientType.RetailPtr:
|
||||
case WowClientType.Beta:
|
||||
default:
|
||||
return "wow_retail";
|
||||
}
|
||||
return searchResult;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private getFeaturedAddonList(): Promise<CurseSearchResult[]> {
|
||||
const url = `${API_URL}/addon/featured`;
|
||||
const body = {
|
||||
gameId: 1,
|
||||
featuredCount: 6,
|
||||
popularCount: 50,
|
||||
updatedCount: 0
|
||||
};
|
||||
|
||||
return this._httpClient.post<CurseGetFeaturedResponse>(url, body)
|
||||
.pipe(
|
||||
map(result => {
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const latestFiles = this.getLatestFiles(result, clientType);
|
||||
if (!latestFiles?.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.getAddonSearchResult(result, latestFiles);
|
||||
})
|
||||
)
|
||||
.toPromise();
|
||||
}
|
||||
|
||||
private getChannelType(releaseType: CurseReleaseType): AddonChannelType {
|
||||
switch (releaseType) {
|
||||
case CurseReleaseType.Alpha:
|
||||
return AddonChannelType.Alpha;
|
||||
case CurseReleaseType.Beta:
|
||||
return AddonChannelType.Beta;
|
||||
case CurseReleaseType.Release:
|
||||
default:
|
||||
return AddonChannelType.Stable;
|
||||
}
|
||||
}
|
||||
|
||||
private getFolderNames(file: CurseFile): string[] {
|
||||
return file.modules.map(m => m.foldername);
|
||||
}
|
||||
|
||||
private getGameVersion(file: CurseFile): string {
|
||||
return _.first(file.gameVersion);
|
||||
}
|
||||
|
||||
private getAuthor(result: CurseSearchResult): string {
|
||||
var authorNames = result.authors.map(a => a.name);
|
||||
return authorNames.join(', ');
|
||||
}
|
||||
|
||||
private getThumbnailUrl(result: CurseSearchResult): string {
|
||||
const attachment = _.find(result.attachments, f => f.isDefault && !!f.thumbnailUrl);
|
||||
return attachment?.thumbnailUrl;
|
||||
}
|
||||
|
||||
private getLatestFiles(result: CurseSearchResult, clientType: WowClientType): CurseFile[] {
|
||||
const clientTypeStr = this.getClientTypeString(clientType);
|
||||
|
||||
return _.flow(
|
||||
_.filter((f: CurseFile) => f.isAlternate == false && f.gameVersionFlavor == clientTypeStr),
|
||||
_.orderBy((f: CurseFile) => f.id),
|
||||
_.reverse
|
||||
)(result.latestFiles) as CurseFile[];
|
||||
}
|
||||
|
||||
private getClientTypeString(clientType: WowClientType): string {
|
||||
switch (clientType) {
|
||||
case WowClientType.Classic:
|
||||
case WowClientType.ClassicPtr:
|
||||
return "wow_classic";
|
||||
case WowClientType.Retail:
|
||||
case WowClientType.RetailPtr:
|
||||
case WowClientType.Beta:
|
||||
default:
|
||||
return "wow_retail";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +1,19 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { WowClientType } from "app/models/warcraft/wow-client-type";
|
||||
import { WowClientType } from "../../../models/warcraft/wow-client-type";
|
||||
import { AddonStorageService } from "../storage/addon.storage.service";
|
||||
import { Addon } from "app/core/entities/addon";
|
||||
import { Addon } from "../../entities/addon";
|
||||
import { WarcraftService } from "../warcraft/warcraft.service";
|
||||
import { AddonProvider } from "app/core/addon-providers/addon-provider";
|
||||
import { CurseAddonProvider } from "app/core/addon-providers/curse-addon-provider";
|
||||
import { AddonProvider } from "../../addon-providers/addon-provider";
|
||||
import { CurseAddonProvider } from "../../addon-providers/curse-addon-provider";
|
||||
import { HttpClient } from "@angular/common/http";
|
||||
import { AddonSearchResult } from "app/models/wowup/addon-search-result";
|
||||
import { AddonSearchResultFile } from "app/models/wowup/addon-search-result-file";
|
||||
import { AddonChannelType } from "app/models/wowup/addon-channel-type";
|
||||
import { AddonSearchResult } from "../../../models/wowup/addon-search-result";
|
||||
import { AddonSearchResultFile } from "../../../models/wowup/addon-search-result-file";
|
||||
import { AddonChannelType } from "../../../models/wowup/addon-channel-type";
|
||||
import * as _ from 'lodash';
|
||||
import * as uuid from 'uuid';
|
||||
import { AddonFolder } from "app/models/wowup/addon-folder";
|
||||
import { AddonFolder } from "../../../models/wowup/addon-folder";
|
||||
import { WowUpApiService } from "../wowup-api/wowup-api.service";
|
||||
import { PotentialAddon } from "../../../models/wowup/potential-addon";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@@ -51,6 +52,11 @@ export class AddonService {
|
||||
return addons;
|
||||
}
|
||||
|
||||
public async getFeaturedAddons(clientType: WowClientType) : Promise<PotentialAddon[]>{
|
||||
const results = await Promise.all(this._addonProviders.map(p => p.getFeaturedAddons(clientType)));
|
||||
return results.flat(1);
|
||||
}
|
||||
|
||||
private getAllStoredAddons(clientType: WowClientType) {
|
||||
const addons: Addon[] = [];
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WowClientType } from '../models/warcraft/wow-client-type';
|
||||
import { AddonService } from '../core/services/addons/addon.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-get-addons',
|
||||
@@ -22,12 +24,21 @@ export class GetAddonsComponent implements OnInit {
|
||||
{ position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
|
||||
];
|
||||
|
||||
public selectedClient = 'retail';
|
||||
public query = '';
|
||||
public selectedClient = WowClientType.Classic;
|
||||
|
||||
constructor() { }
|
||||
constructor(
|
||||
private _addonService: AddonService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
private loadPopularAddons(){
|
||||
if(this.selectedClient === WowClientType.None){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { CurseSearchResult } from './curse-search-result';
|
||||
|
||||
export interface CurseGetFeaturedResponse {
|
||||
featured: CurseSearchResult[];
|
||||
popular: CurseSearchResult[];
|
||||
recentlyUpdated: CurseSearchResult[];
|
||||
}
|
||||
@@ -3,5 +3,6 @@ export enum WowClientType {
|
||||
Classic,
|
||||
RetailPtr,
|
||||
ClassicPtr,
|
||||
Beta
|
||||
Beta,
|
||||
None
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { WarcraftService } from 'app/core/services/warcraft/warcraft.service';
|
||||
import { WowClientType } from 'app/models/warcraft/wow-client-type';
|
||||
import { AddonService } from 'app/core/services/addons/addon.service';
|
||||
import { WarcraftService } from '../core/services/warcraft/warcraft.service';
|
||||
import { WowClientType } from '../models/warcraft/wow-client-type';
|
||||
import { AddonService } from '../core/services/addons/addon.service';
|
||||
import { first, tap } from 'rxjs/operators';
|
||||
import { from, BehaviorSubject } from 'rxjs';
|
||||
import { Addon } from 'app/core/entities/addon';
|
||||
import { AddonTableColumnComponent } from 'app/components/addon-table-column/addon-table-column.component';
|
||||
import { AddonStatusColumnComponent } from 'app/components/addon-status-column/addon-status-column.component';
|
||||
import { Addon } from '../core/entities/addon';
|
||||
import { AddonTableColumnComponent } from '../components/addon-table-column/addon-table-column.component';
|
||||
import { AddonStatusColumnComponent } from '../components/addon-status-column/addon-status-column.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-my-addons',
|
||||
@@ -77,7 +77,7 @@ export class MyAddonsComponent implements OnInit {
|
||||
this.warcraftService.clientTypes$
|
||||
.pipe(
|
||||
first(types => Array.isArray(types) && types.length > 0),
|
||||
tap(() => this.loadAddons())
|
||||
tap(() => this.loadAddons(this.selectedClient))
|
||||
)
|
||||
.subscribe(types => this.selectedClient = types[0]);
|
||||
|
||||
@@ -87,27 +87,24 @@ export class MyAddonsComponent implements OnInit {
|
||||
}
|
||||
|
||||
onReScan() {
|
||||
this.loadAddons(true)
|
||||
this.loadAddons(this.selectedClient, true)
|
||||
}
|
||||
|
||||
onClientChange() {
|
||||
this.busy = true;
|
||||
console.log(this.selectedClient);
|
||||
this.busy = false;
|
||||
this.loadAddons(this.selectedClient, false);
|
||||
}
|
||||
|
||||
onGridReady(params) {
|
||||
this.gridApi = params.api;
|
||||
this.gridApi.sizeColumnsToFit();
|
||||
|
||||
}
|
||||
|
||||
private loadAddons(rescan: boolean = false) {
|
||||
private loadAddons(clientType: WowClientType, rescan: boolean = false) {
|
||||
this.busy = true;
|
||||
|
||||
console.log('Load-addons')
|
||||
console.log('Load-addons', clientType);
|
||||
|
||||
from(this.addonService.getAddons(this.selectedClient, rescan))
|
||||
from(this.addonService.getAddons(clientType, rescan))
|
||||
.subscribe((addons) => {
|
||||
this.busy = false;
|
||||
this.formatAddons(addons);
|
||||
|
||||
Reference in New Issue
Block a user