Upgrade grats

This commit is contained in:
Jordan Eldredge 2023-09-16 06:53:42 -07:00
parent 67082a0441
commit 989363aa43
6 changed files with 245 additions and 371 deletions

View file

@ -1,39 +1,25 @@
import CommonSkinResolver, { ISkin } from "./CommonSkinResolver";
import { ISkin } from "./CommonSkinResolver";
import { NodeResolver, toId } from "./NodeResolver";
import ReviewResolver from "./ReviewResolver";
import path from "path";
import { ID, Int } from "grats";
import TweetModel from "../../../data/TweetModel";
import ArchiveFileModel from "../../../data/ArchiveFileModel";
import IaItemModel from "../../../data/IaItemModel";
import SkinModel from "../../../data/SkinModel";
/**
* A classic Winamp skin
* @gqlType ClassicSkin */
export default class ClassicSkinResolver
extends CommonSkinResolver
implements NodeResolver, ISkin
{
export default class ClassicSkinResolver implements NodeResolver, ISkin {
_model: SkinModel;
__typename = "ClassicSkin";
/**
* GraphQL ID of the skin
* @gqlField
* @killsParentOnException
*/
md5(): string {
return this._model.getMd5();
}
id(): ID {
return toId(this.__typename, this.md5());
}
/**
* Filename of skin when uploaded to the Museum. Note: In some cases a skin
* has been uploaded under multiple names. Here we just pick one.
* @gqlField */
async filename({
normalize_extension = false,
}: {
/** If true, the the correct file extension (.wsz or .wal) will be .
Otherwise, the original user-uploaded file extension will be used. */
normalize_extension?: boolean;
}): Promise<string> {
async filename(normalize_extension?: boolean): Promise<string> {
const filename = await this._model.getFileName();
if (normalize_extension) {
return path.parse(filename).name + ".wsz";
@ -41,78 +27,21 @@ export default class ClassicSkinResolver
return filename;
}
/**
* MD5 hash of the skin's file
* @gqlField */
md5(): string {
return super.md5();
}
/**
* URL to download the skin
* @gqlField */
download_url(): string {
return super.download_url();
}
/**
* Has the skin been tweeted?
* @gqlField */
tweeted(): Promise<boolean> {
return super.tweeted();
}
/**
* List of @winampskins tweets that mentioned the skin.
* @gqlField */
tweets(): Promise<Array<TweetModel | null>> {
return super.tweets();
}
/**
* List of files contained within the skin's .wsz archive
* @gqlField */
archive_files(): Promise<Array<ArchiveFileModel | null>> {
return super.archive_files();
}
/**
* The skin's "item" at archive.org
* @gqlField */
internet_archive_item(): Promise<IaItemModel | null> {
return super.internet_archive_item();
}
/**
* URL of the skin on the Winamp Skin Museum
* @gqlField */
museum_url(): string {
return this._model.getMuseumUrl();
}
/**
* URL of webamp.org with the skin loaded
* @gqlField */
webamp_url(): string {
return this._model.getWebampUrl();
}
/**
* URL of a screenshot of the skin
* @gqlField */
async screenshot_url(): Promise<string> {
return this._model.getScreenshotUrl();
}
/**
* Text of the readme file extracted from the skin
* @gqlField */
readme_text(): Promise<string | null> {
return this._model.getReadme();
}
/**
* Has the skin been flagged as "not safe for wrok"?
* @gqlField */
nsfw(): Promise<boolean> {
return this._model.getIsNsfw();
}
/**
* String representation (rgb usually) of the skin's average color
* @gqlField */
average_color(): string {
return this._model.getAverageColor();
}
@ -122,10 +51,7 @@ export default class ClassicSkinResolver
has_media_library(): Promise<boolean> {
return this._model.hasMediaLibrary();
}
/**
* Times that the skin has been reviewed either on the Museum's Tinder-style
* reivew page, or via the Discord bot.
* @gqlField */
async reviews(): Promise<Array<ReviewResolver | null>> {
const reviews = await this._model.getReviews();
return reviews.map((row) => new ReviewResolver(row));

View file

@ -13,19 +13,67 @@ import IaItemModel from "../../../data/IaItemModel";
*/
export interface ISkin {
__typename: string;
/**
* GraphQL ID of the skin
* @gqlField
* @killsParentOnException
*/
_model: SkinModel;
id(): ID;
filename(normalize_extension: boolean): Promise<string>;
md5(): string;
museum_url(): string | null;
webamp_url(): string | null;
screenshot_url(): Promise<string | null>;
readme_text(): Promise<string | null>;
nsfw(): Promise<boolean | null>;
average_color(): string | null;
}
/**
* Filename of skin when uploaded to the Museum. Note: In some cases a skin
* has been uploaded under multiple names. Here we just pick one.
* @gqlField
*/
filename({
/**
* URL of webamp.org with the skin loaded
* @gqlField
*/
export function webamp_url(skin: ISkin): string | null {
return skin.webamp_url();
}
/**
* URL of a screenshot of the skin
* @gqlField
*/
export function screenshot_url(skin: ISkin): Promise<string | null> {
return skin.screenshot_url();
}
/**
* Text of the readme file extracted from the skin
* @gqlField
*/
export function readme_text(skin: ISkin): Promise<string | null> {
return skin.readme_text();
}
/**
* Has the skin been flagged as "not safe for work"?"
* @gqlField
*/
export function nsfw(skin: ISkin): Promise<boolean | null> {
return skin.nsfw();
}
/**
* GraphQL ID of the skin
* @gqlField
* @killsParentOnException
*/
export function id(skin: ISkin): ID {
return skin.id();
}
/**
* Filename of skin when uploaded to the Museum. Note: In some cases a skin
* has been uploaded under multiple names. Here we just pick one.
* @gqlField
*/
export function filename(
skin: ISkin,
{
normalize_extension = false,
}: {
/**
@ -33,109 +81,86 @@ export interface ISkin {
* Otherwise, the original user-uploaded file extension will be used.
*/
normalize_extension?: boolean;
}): Promise<string>;
/**
* MD5 hash of the skin's file
* @gqlField
*/
md5(): string;
/**
* URL to download the skin
* @gqlField
*/
download_url(): string;
/**
* Has the skin been tweeted?
* @gqlField
*/
tweeted(): Promise<boolean>;
/**
* List of @winampskins tweets that mentioned the skin.
* @gqlField
*/
tweets(): Promise<Array<TweetModel | null>>;
/**
* List of files contained within the skin's .wsz archive
* @gqlField
*/
archive_files(): Promise<Array<ArchiveFileModel | null>>;
/**
* The skin's "item" at archive.org
* @gqlField
*/
internet_archive_item(): Promise<IaItemModel | null>;
/**
* Times that the skin has been reviewed either on the Museum's Tinder-style
* review page, or via the Discord bot.
* @gqlField
*/
reviews(): Promise<Array<ReviewResolver | null>>;
/**
* @gqlField
* @deprecated Needed for migration
*/
museum_url(): string | null;
/**
* @gqlField
* @deprecated Needed for migration
*/
webamp_url(): string | null;
/** @gqlField */
screenshot_url(): Promise<string | null>;
/**
* @gqlField
* @deprecated Needed for migration */
readme_text(): Promise<string | null>;
/**
* @gqlField
* @deprecated Needed for migration */
nsfw(): Promise<boolean | null>;
/**
* @gqlField
* @deprecated Needed for migration */
average_color(): string | null;
}
): Promise<string> {
return skin.filename(normalize_extension);
}
export default abstract class CommonSkinResolver {
_model: SkinModel;
constructor(model: SkinModel) {
this._model = model;
}
md5(): string {
return this._model.getMd5();
}
download_url(): string {
return this._model.getSkinUrl();
}
tweeted(): Promise<boolean> {
return this._model.tweeted();
}
async tweets(): Promise<Array<TweetModel | null>> {
return this._model.getTweets();
}
async archive_files(): Promise<Array<ArchiveFileModel | null>> {
return this._model.getArchiveFiles();
}
async internet_archive_item(): Promise<IaItemModel | null> {
return this._model.getIaItem();
}
async reviews(): Promise<Array<ReviewResolver | null>> {
const reviews = await this._model.getReviews();
return reviews.map((row) => new ReviewResolver(row));
}
/**
* URL to download the skin
* @gqlField
*/
export function download_url(skin: ISkin): string {
return skin._model.getSkinUrl();
}
/**
* Has the skin been tweeted?
* @gqlField
*/
export function tweeted(skin: ISkin): Promise<boolean> {
return skin._model.tweeted();
}
/**
* List of @winampskins tweets that mentioned the skin.
* @gqlField
*/
export function tweets(skin: ISkin): Promise<Array<TweetModel | null>> {
return skin._model.getTweets();
}
/**
* Times that the skin has been reviewed either on the Museum's Tinder-style
* review page, or via the Discord bot.
* @gqlField
*/
export async function reviews(
skin: ISkin
): Promise<Array<ReviewResolver | null>> {
const reviews = await skin._model.getReviews();
return reviews.map((row) => new ReviewResolver(row));
}
/**
* List of files contained within the skin's .wsz archive
* @gqlField
*/
export function archive_files(
skin: ISkin
): Promise<Array<ArchiveFileModel | null>> {
return skin._model.getArchiveFiles();
}
/**
* The skin's "item" at archive.org
* @gqlField
*/
export function internet_archive_item(
skin: ISkin
): Promise<IaItemModel | null> {
return skin._model.getIaItem();
}
/**
* URL of the skin on the Winamp Skin Museum
* @gqlField
*/
export function museum_url(skin: ISkin): string | null {
return skin.museum_url();
}
/**
* String representation (rgb usually) of the skin's average color
* @gqlField
*/
export function average_color(skin: ISkin): string | null {
return skin.average_color();
}
/**
* MD5 hash of the skin's file
* @gqlField
*/
export function md5(skin: ISkin): string {
return skin.md5();
}

View file

@ -1,13 +1,9 @@
import SkinModel from "../../../data/SkinModel";
import CommonSkinResolver, { ISkin } from "./CommonSkinResolver";
import { ISkin } from "./CommonSkinResolver";
import { NodeResolver, toId } from "./NodeResolver";
import path from "path";
import { ID } from "grats";
import ReviewResolver from "./ReviewResolver";
import { XMLParser } from "fast-xml-parser";
import TweetModel from "../../../data/TweetModel";
import ArchiveFileModel from "../../../data/ArchiveFileModel";
import IaItemModel from "../../../data/IaItemModel";
/**
* A "modern" Winamp skin. These skins use the `.wal` file extension and are free-form.
@ -15,23 +11,14 @@ import IaItemModel from "../../../data/IaItemModel";
* Most functionality in the Winamp Skin Museum is centered around "classic" skins,
* which are currently called just `Skin` in this schema.
* @gqlType ModernSkin */
export default class ModernSkinResolver
extends CommonSkinResolver
implements NodeResolver, ISkin
{
export default class ModernSkinResolver implements NodeResolver, ISkin {
_model: SkinModel;
__typename = "ModernSkin";
/**
* Filename of skin when uploaded to the Museum. Note: In some cases a skin
* has been uploaded under multiple names. Here we just pick one.
* @gqlField */
async filename({
normalize_extension = false,
}: {
/** If true, the the correct file extension (.wsz or .wal) will be .
Otherwise, the original user-uploaded file extension will be used. */
normalize_extension?: boolean;
}): Promise<string> {
md5(): string {
return this._model.getMd5();
}
async filename(normalize_extension: boolean): Promise<string> {
const filename = await this._model.getFileName();
if (normalize_extension) {
return path.parse(filename).name + ".wal";
@ -41,76 +28,17 @@ export default class ModernSkinResolver
/* TODO: Get all of these from the parent class/interface */
/**
* GraphQL ID of the skin
* @gqlField
* @killsParentOnException */
id(): ID {
return toId(this.__typename, this.md5());
}
/**
* MD5 hash of the skin's file
* @gqlField */
md5(): string {
return super.md5();
}
/**
* URL to download the skin
* @gqlField */
download_url(): string {
return super.download_url();
}
/**
* Has the skin been tweeted?
* @gqlField */
tweeted(): Promise<boolean> {
return super.tweeted();
}
/**
* List of @winampskins tweets that mentioned the skin.
* @gqlField */
async tweets(): Promise<Array<TweetModel | null>> {
return super.tweets();
}
/**
* List of files contained within the skin's .wsz archive
* @gqlField */
async archive_files(): Promise<Array<ArchiveFileModel | null>> {
return super.archive_files();
}
/**
* The skin's "item" at archive.org
* @gqlField */
async internet_archive_item(): Promise<IaItemModel | null> {
return super.internet_archive_item();
}
/**
* Times that the skin has been reviewed either on the Museum's Tinder-style
* reivew page, or via the Discord bot.
* @gqlField */
async reviews(): Promise<Array<ReviewResolver | null>> {
return super.reviews();
}
/**
* @gqlField
* @deprecated Needed for migration */
museum_url(): string | null {
return null;
}
/**
* @gqlField
* @deprecated Needed for migration */
webamp_url(): string | null {
return null;
}
/** @gqlField */
async screenshot_url(): Promise<string | null> {
const archiveFiles = await this._model.getArchiveFiles();
const skinXml = archiveFiles.find((f) =>
@ -150,21 +78,12 @@ export default class ModernSkinResolver
return screenshotFile.getUrl();
}
/**
* @gqlField
* @deprecated Needed for migration */
async readme_text(): Promise<string | null> {
return null;
}
/**
* @gqlField
* @deprecated Needed for migration */
async nsfw(): Promise<boolean | null> {
return null;
}
/**
* @gqlField
* @deprecated Needed for migration */
average_color(): string | null {
return null;
}

View file

@ -41,11 +41,11 @@ type ArchiveFile {
"""A classic Winamp skin"""
type ClassicSkin implements Node & Skin {
"""List of files contained within the skin's .wsz archive"""
archive_files: [ArchiveFile]
archive_files: [ArchiveFile] @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "archive_files")
"""String representation (rgb usually) of the skin's average color"""
average_color: String
average_color: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "average_color")
"""URL to download the skin"""
download_url: String
download_url: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "download_url")
"""
Filename of skin when uploaded to the Museum. Note: In some cases a skin
has been uploaded under multiple names. Here we just pick one.
@ -56,41 +56,43 @@ type ClassicSkin implements Node & Skin {
Otherwise, the original user-uploaded file extension will be used.
"""
normalize_extension: Boolean = false
): String
): String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "filename")
"""Does the skin include sprite sheets for the media library?"""
has_media_library: Boolean
"""GraphQL ID of the skin"""
id: ID!
id: ID! @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "id")
"""The skin's "item" at archive.org"""
internet_archive_item: InternetArchiveItem
internet_archive_item: InternetArchiveItem @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "internet_archive_item")
"""
The date on which this skin was last updated in the Algolia search index.
Given in simplified extended ISO format (ISO 8601).
"""
last_algolia_index_update_date: String
"""MD5 hash of the skin's file"""
md5: String
md5: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "md5")
"""URL of the skin on the Winamp Skin Museum"""
museum_url: String
"""Has the skin been flagged as "not safe for wrok"?"""
nsfw: Boolean
museum_url: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "museum_url")
"""
Has the skin been flagged as "not safe for work"?"
"""
nsfw: Boolean @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "nsfw")
"""Text of the readme file extracted from the skin"""
readme_text: String
readme_text: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "readme_text")
"""
Times that the skin has been reviewed either on the Museum's Tinder-style
reivew page, or via the Discord bot.
review page, or via the Discord bot.
"""
reviews: [Review]
reviews: [Review] @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "reviews")
"""URL of a screenshot of the skin"""
screenshot_url: String
screenshot_url: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "screenshot_url")
"""The number of transparent pixels rendered by the skin."""
transparent_pixels: Int
"""Has the skin been tweeted?"""
tweeted: Boolean
tweeted: Boolean @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "tweeted")
"""List of @winampskins tweets that mentioned the skin."""
tweets: [Tweet]
tweets: [Tweet] @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "tweets")
"""URL of webamp.org with the skin loaded"""
webamp_url: String
webamp_url: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "webamp_url")
}
"""Statistics about the contents of the Museum's database."""
@ -116,13 +118,9 @@ type DatabaseStatistics {
**Note:** Generally skins that have been marked NSFW are also marked as rejected.
"""
rejected_skins_count: Int
"""
The number of skins that have been approved for tweeting, but not yet tweeted.
"""
"""The number of skins that have been approved for tweeting, but not yet tweeted."""
tweetable_skins_count: Int
"""
The number of skins in the Museum that have been tweeted by @winampskins
"""
"""The number of skins in the Museum that have been tweeted by @winampskins"""
tweeted_skins_count: Int
"""The total number of classic skins in the Museum's database"""
unique_classic_skins_count: Int
@ -136,9 +134,7 @@ type DatabaseStatistics {
pipeline gets stuck.
"""
uploads_pending_processing_count: Int
"""
Number of skins that have been uploaded to the Museum via the web interface.
"""
"""Number of skins that have been uploaded to the Museum via the web interface."""
web_uploads_count: Int
}
@ -153,9 +149,7 @@ type InternetArchiveItem {
last_metadata_scrape_date_UNSTABLE: String @methodName(name: "getMetadataTimestamp")
"""URL to get the Internet Archive's metadata for this item in JSON form."""
metadata_url: String @methodName(name: "getMetadataUrl")
"""
Our cached version of the metadata available at \`metadata_url\` (above)
"""
"""Our cached version of the metadata available at \`metadata_url\` (above)"""
raw_metadata_json: String @methodName(name: "getMetadataJSON")
"""The skin that this item contains"""
skin: Skin
@ -171,10 +165,11 @@ which are currently called just `Skin` in this schema.
"""
type ModernSkin implements Node & Skin {
"""List of files contained within the skin's .wsz archive"""
archive_files: [ArchiveFile]
average_color: String @deprecated(reason: "Needed for migration")
archive_files: [ArchiveFile] @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "archive_files")
"""String representation (rgb usually) of the skin's average color"""
average_color: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "average_color")
"""URL to download the skin"""
download_url: String
download_url: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "download_url")
"""
Filename of skin when uploaded to the Museum. Note: In some cases a skin
has been uploaded under multiple names. Here we just pick one.
@ -185,27 +180,34 @@ type ModernSkin implements Node & Skin {
Otherwise, the original user-uploaded file extension will be used.
"""
normalize_extension: Boolean = false
): String
): String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "filename")
"""GraphQL ID of the skin"""
id: ID!
id: ID! @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "id")
"""The skin's "item" at archive.org"""
internet_archive_item: InternetArchiveItem
internet_archive_item: InternetArchiveItem @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "internet_archive_item")
"""MD5 hash of the skin's file"""
md5: String
museum_url: String @deprecated(reason: "Needed for migration")
nsfw: Boolean @deprecated(reason: "Needed for migration")
readme_text: String @deprecated(reason: "Needed for migration")
md5: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "md5")
"""URL of the skin on the Winamp Skin Museum"""
museum_url: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "museum_url")
"""
Has the skin been flagged as "not safe for work"?"
"""
nsfw: Boolean @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "nsfw")
"""Text of the readme file extracted from the skin"""
readme_text: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "readme_text")
"""
Times that the skin has been reviewed either on the Museum's Tinder-style
reivew page, or via the Discord bot.
review page, or via the Discord bot.
"""
reviews: [Review]
screenshot_url: String
reviews: [Review] @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "reviews")
"""URL of a screenshot of the skin"""
screenshot_url: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "screenshot_url")
"""Has the skin been tweeted?"""
tweeted: Boolean
tweeted: Boolean @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "tweeted")
"""List of @winampskins tweets that mentioned the skin."""
tweets: [Tweet]
webamp_url: String @deprecated(reason: "Needed for migration")
tweets: [Tweet] @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "tweets")
"""URL of webamp.org with the skin loaded"""
webamp_url: String @exported(filename: "../../../../packages/skin-database/dist/api/graphql/resolvers/CommonSkinResolver.js", functionName: "webamp_url")
}
"""A collection of "modern" Winamp skins"""
@ -241,9 +243,7 @@ type Mutation {
in.
"""
request_nsfw_review_for_skin(md5: String!): Boolean
"""
Send a message to the admin of the site. Currently this appears in Discord.
"""
"""Send a message to the admin of the site. Currently this appears in Discord."""
send_feedback(email: String, message: String!, url: String): Boolean
"""Mutations for the upload flow"""
upload: UploadMutations
@ -340,7 +340,8 @@ A Winamp skin. Could be modern or classic.
interface Skin {
"""List of files contained within the skin's .wsz archive"""
archive_files: [ArchiveFile]
average_color: String @deprecated(reason: "Needed for migration")
"""String representation (rgb usually) of the skin's average color"""
average_color: String
"""URL to download the skin"""
download_url: String
"""
@ -360,20 +361,46 @@ interface Skin {
internet_archive_item: InternetArchiveItem
"""MD5 hash of the skin's file"""
md5: String
museum_url: String @deprecated(reason: "Needed for migration")
nsfw: Boolean @deprecated(reason: "Needed for migration")
readme_text: String @deprecated(reason: "Needed for migration")
"""URL of the skin on the Winamp Skin Museum"""
museum_url: String
"""
Has the skin been flagged as "not safe for work"?"
"""
nsfw: Boolean
"""Text of the readme file extracted from the skin"""
readme_text: String
"""
Times that the skin has been reviewed either on the Museum's Tinder-style
review page, or via the Discord bot.
"""
reviews: [Review]
"""URL of a screenshot of the skin"""
screenshot_url: String
"""Has the skin been tweeted?"""
tweeted: Boolean
"""List of @winampskins tweets that mentioned the skin."""
tweets: [Tweet]
webamp_url: String @deprecated(reason: "Needed for migration")
"""URL of webamp.org with the skin loaded"""
webamp_url: String
}
"""A collection of classic Winamp skins"""
type SkinsConnection {
"""The total number of skins matching the filter"""
count: Int
"""The list of skins"""
nodes: [Skin]
}
enum SkinsFilterOption {
APPROVED
NSFW
REJECTED
TWEETED
}
enum SkinsSortOption {
MUSEUM
}
"""Information about an attempt to upload a skin to the Museum."""
@ -403,34 +430,11 @@ enum SkinUploadStatus {
URL_REQUESTED
}
"""A collection of classic Winamp skins"""
type SkinsConnection {
"""The total number of skins matching the filter"""
count: Int
"""The list of skins"""
nodes: [Skin]
}
enum SkinsFilterOption {
APPROVED
NSFW
REJECTED
TWEETED
}
enum SkinsSortOption {
MUSEUM
}
"""A tweet made by @winampskins mentioning a Winamp skin"""
type Tweet {
"""
Number of likes the tweet has received. Updated nightly. (Note: Recent likes on older tweets may not be reflected here)
"""
"""Number of likes the tweet has received. Updated nightly. (Note: Recent likes on older tweets may not be reflected here)"""
likes: Int @methodName(name: "getLikes")
"""
Number of retweets the tweet has received. Updated nightly. (Note: Recent retweets on older tweets may not be reflected here)
"""
"""Number of retweets the tweet has received. Updated nightly. (Note: Recent retweets on older tweets may not be reflected here)"""
retweets: Int @methodName(name: "getRetweets")
"""The skin featured in this Tweet"""
skin: Skin
@ -494,4 +498,4 @@ input UploadUrlRequest {
type User {
username: String
}
}

View file

@ -29,7 +29,7 @@
"express-sitemap-xml": "^2.0.0",
"fast-xml-parser": "^4.2.2",
"graphql": "14.7.0",
"grats": "^0.0.0-main-8de1c8ac",
"grats": "0.0.0-main-b47472ff",
"imagemin": "^7.0.0",
"imagemin-optipng": "^7.0.0",
"knex": "^0.21.1",

View file

@ -14783,10 +14783,10 @@ graphql@14.7.0, graphql@15.3.0, graphql@^16.6.0:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==
grats@^0.0.0-main-8de1c8ac:
version "0.0.0-main-8de1c8ac"
resolved "https://registry.yarnpkg.com/grats/-/grats-0.0.0-main-8de1c8ac.tgz#ddd0eb60c290951e76307028143b24a3f8608ea4"
integrity sha512-lP/CpAU/6qE/Cn7+MUPbQT100kzuxh5rJ2fAiDbtAzxvG3MFhtXySy8Cz6sFt0eBjHv77a2G3J3Ua6+xoM6GnA==
grats@0.0.0-main-b47472ff:
version "0.0.0-main-b47472ff"
resolved "https://registry.yarnpkg.com/grats/-/grats-0.0.0-main-b47472ff.tgz#ca8d7f9bad66fcf7011090c681207105c4542f13"
integrity sha512-k+O8Jh3rqhCp80lZcYrXY5oWEf4FzwAtvLuTQtFskKPU8y6V/mlzL6per643uFSnisv7lmFrxY+8aBIbUDEFfg==
dependencies:
"@graphql-tools/utils" "^9.2.1"
commander "^10.0.0"