Skip to content

Commit

Permalink
add news and season
Browse files Browse the repository at this point in the history
  • Loading branch information
kylekz committed Nov 18, 2023
1 parent a8cad6a commit 1a58ddb
Show file tree
Hide file tree
Showing 11 changed files with 412 additions and 12 deletions.
97 changes: 97 additions & 0 deletions src/api/news.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { initUntypeable } from "untypeable";
import { ValidArtist } from "./artists";

const u = initUntypeable().pushArg<"GET">();
export const router = u.router({
"/news/v1": {
GET: u.input<{ artist: ValidArtist }>().output<HomeNewsResult>(),
},

"/news/v1/feed": {
GET: u
.input<NewsPayload>()
.output<NewsFeedResult<NewsSectionFeedContent>>(),
},

"/news/v1/exclusive": {
GET: u
.input<NewsPayload>()
.output<NewsFeedResult<NewsSectionExclusiveContent>>(),
},
});

export type NewsPayload = {
artist: ValidArtist;
start_after?: number;
limit?: number;
};

export type HomeNewsResult = {
sections: NewsSection[];
};

export type NewsSectionBar = {
type: "bar";
artist: ValidArtist;
contents: [];
};

export type NewsSectionBanner = {
type: "banner";
artist: ValidArtist;
contents: NewsSectionBannerContent[];
};
export type NewsSectionBannerContent = {
id: number;
url: string;
createdAt: string;
label: "release" | "event" | "notice";
order: number;
body: string;
imageUrl: string;
};

export type NewsSectionFeed = {
type: "feed";
artist: ValidArtist;
title: string;
contents: NewsSectionFeedContent[];
};
export type NewsSectionFeedContent = {
id: number;
url: string;
createdAt: string;
artist: ValidArtist;
logoImageUrl: string;
body: string;
imageUrls: string[];
};

export type NewsSectionExclusive = {
type: "exclusive";
artist: ValidArtist;
title: string;
contents: NewsSectionExclusiveContent[];
};
export type NewsSectionExclusiveContent = {
id: number;
url: string;
createdAt: string;
title: string;
body: string;
thumbnailImageUrl: string;
nativeVideoUrl: string;
};

export type NewsSection =
| NewsSectionBar
| NewsSectionBanner
| NewsSectionFeed
| NewsSectionExclusive;

export type NewsFeedResult<TPostType> = {
hasNext: boolean;
total: number;
nextStartAfter: string;
results: TPostType[];
};
33 changes: 33 additions & 0 deletions src/api/season.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { initUntypeable } from "untypeable";

const u = initUntypeable().pushArg<"GET">();
export const router = u.router({
"/season/v2/:artist": {
GET: u.input<{ artist: string }>().output<SeasonResponse>(),
},
});

export type OngoingSeason = {
artist: string;
title: string;
image: string | null;
startDate: string;
endDate: null;
ongoing: true;
};

export type EndedSeason = {
artist: string;
title: string;
image: string | null;
startDate: string;
endDate: string;
ongoing: false;
};

export type Season = OngoingSeason | EndedSeason;

export type SeasonResponse = {
seasons: Season[];
currentSeason: OngoingSeason;
};
8 changes: 0 additions & 8 deletions src/api/types.ts

This file was deleted.

30 changes: 30 additions & 0 deletions src/cosmo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,34 @@ export class Cosmo implements CosmoContract {
async refreshToken(payload: RefreshPayload) {
return await this.client("/auth/v1/refresh", "POST", payload);
}

async getHomeNews(artist: ValidArtist) {
return await this.client("/news/v1", "GET", { artist });
}

async getAtmosphereFeed(
artist: ValidArtist,
options?: { startAfter?: number; limit?: number }
) {
return await this.client("/news/v1/feed", "GET", {
artist,
start_after: options?.startAfter,
limit: options?.limit,
});
}

async getExclusiveFeed(
artist: ValidArtist,
options?: { startAfter?: number; limit?: number }
) {
return await this.client("/news/v1/exclusive", "GET", {
artist,
start_after: options?.startAfter,
limit: options?.limit,
});
}

async getSeasons(artist: ValidArtist) {
return await this.client("/season/v2/:artist", "GET", { artist });
}
}
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { Cosmo } from "./cosmo";
export * from "./api/types";
export * from "./types";
37 changes: 35 additions & 2 deletions src/interface.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { Artist, ArtistWithMembers } from "./api/artists";
import { Artist, ArtistWithMembers, ValidArtist } from "./api/artists";
import {
LoginPayload,
LoginResult,
RefreshPayload,
RefreshResult,
} from "./api/auth";
import { SearchResult, User } from "./api/user";
import {
HomeNewsResult,
NewsFeedResult,
NewsSectionExclusiveContent,
NewsSectionFeedContent,
SeasonResponse,
} from "./types";

export interface CosmoContract {
/**
Expand All @@ -16,7 +23,7 @@ export interface CosmoContract {
/**
* Fetch a single artist and its members.
*/
getArtist(artist: string): Promise<ArtistWithMembers>;
getArtist(artist: ValidArtist): Promise<ArtistWithMembers>;

/**
* Fetch the currently authenticated user.
Expand All @@ -37,4 +44,30 @@ export interface CosmoContract {
* Log into Cosmo using an email and Ramper access token.
*/
refreshToken(payload: RefreshPayload): Promise<RefreshResult>;

/**
* Fetch news on the home page for the given artist.
*/
getHomeNews(artist: ValidArtist): Promise<HomeNewsResult>;

/**
* Fetch the news feed for the given artist.
*/
getAtmosphereFeed(
artist: ValidArtist,
options?: { startAfter?: number; limit?: number }
): Promise<NewsFeedResult<NewsSectionFeedContent>>;

/**
* Fetch the exclusive feed for the given artist.
*/
getExclusiveFeed(
artist: ValidArtist,
options?: { startAfter?: number; limit?: number }
): Promise<NewsFeedResult<NewsSectionExclusiveContent>>;

/**
* Get the past and current seasons for the given artist.
*/
getSeasons(artist: ValidArtist): Promise<SeasonResponse>;
}
9 changes: 8 additions & 1 deletion src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@ import { CosmoUnauthenticatedError, HTTPError } from "./error";
import { router as artistRouter } from "./api/artists";
import { router as userRouter } from "./api/user";
import { router as authRouter } from "./api/auth";
import { router as newsRouter } from "./api/news";
import { router as seasonRouter } from "./api/season";

export type FetcherOptions = {
accessToken?: string;
maxRetries?: number;
};

export const router = artistRouter.merge(userRouter).merge(authRouter);
const COSMO_ENDPOINT = "https://api.cosmo.fans";

export const router = artistRouter
.merge(userRouter)
.merge(authRouter)
.merge(newsRouter)
.merge(seasonRouter);

export function createDefaultFetcher(options: FetcherOptions = {}) {
return (path: string, method: "GET" | "POST", input = {}) => {
const pathWithParams = path.replace(
Expand Down
27 changes: 27 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export { FetcherOptions } from "./router";
export { ValidArtist, Artist, Member, ArtistWithMembers } from "./api/artists";
export { User, SearchResponse, SearchResult } from "./api/user";
export {
LoginPayload,
LoginResult,
RefreshPayload,
RefreshResult,
} from "./api/auth";
export {
HomeNewsResult,
NewsFeedResult,
NewsSection,
NewsSectionBanner,
NewsSectionBannerContent,
NewsSectionBar,
NewsSectionExclusive,
NewsSectionExclusiveContent,
NewsSectionFeed,
NewsSectionFeedContent,
} from "./api/news";
export {
OngoingSeason,
EndedSeason,
Season,
SeasonResponse,
} from "./api/season";
Loading

0 comments on commit 1a58ddb

Please sign in to comment.