webamp/packages/skin-database/api/graphql/schema.graphql
2023-03-04 11:03:07 -08:00

786 lines
16 KiB
GraphQL

"""
A globally unique object. The `id` here is intended only for use within
GraphQL.
https://graphql.org/learn/global-object-identification/
"""
interface Node {
id: ID!
}
"""
A Winamp skin. Could be modern or classic.
**Note**: At some point in the future, this might be renamed to `Skin`.
"""
interface Skin {
"""
GraphQL ID of the skin
"""
id: ID!
"""
MD5 hash of the skin's file
"""
md5: String
"""
URL to download the skin
"""
download_url: String
"""
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.
"""
filename(
"""
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 = false
): String
"""
Has the skin been tweeted?
"""
tweeted: Boolean
"""
List of @winampskins tweets that mentioned the skin.
"""
tweets: [Tweet]
"""
List of files contained within the skin's .wsz archive
"""
archive_files: [ArchiveFile]
"""
The skin's "item" at archive.org
"""
internet_archive_item: InternetArchiveItem
"""
Times that the skin has been reviewed either on the Museum's Tinder-style
reivew page, or via the Discord bot.
"""
reviews: [Review]
# BELOW HERE ARE FOR MIGRATION
# We add extra fields for now so that the client will still work using `Skin`.
# After we migrate these will go away.
museum_url: String @deprecated(reason: "Needed for migration")
webamp_url: String @deprecated(reason: "Needed for migration")
screenshot_url: String @deprecated(reason: "Needed for migration")
readme_text: String @deprecated(reason: "Needed for migration")
nsfw: Boolean @deprecated(reason: "Needed for migration")
average_color: String @deprecated(reason: "Needed for migration")
}
"""
A "modern" Winamp skin. These skins use the `.wal` file extension and are free-form.
Most functionality in the Winamp Skin Museum is centered around "classic" skins,
which are currently called just `Skin` in this schema.
"""
type ModernSkin implements Skin & Node {
"""
GraphQL ID of the skin
"""
id: ID!
"""
MD5 hash of the skin's file
"""
md5: String
"""
URL to download the skin
"""
download_url: String
"""
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.
"""
filename(
"""
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 = false
): String
"""
Has the skin been tweeted?
"""
tweeted: Boolean
"""
List of @winampskins tweets that mentioned the skin.
"""
tweets: [Tweet]
"""
List of files contained within the skin's .wsz archive
"""
archive_files: [ArchiveFile]
"""
The skin's "item" at archive.org
"""
internet_archive_item: InternetArchiveItem
"""
Times that the skin has been reviewed either on the Museum's Tinder-style
reivew page, or via the Discord bot.
"""
reviews: [Review]
# BELOW HERE ARE FOR MIGRATION
# We add extra fields for now so that the client will still work using `Skin`.
# After we migrate these will go away.
museum_url: String @deprecated(reason: "Needed for migration")
webamp_url: String @deprecated(reason: "Needed for migration")
screenshot_url: String @deprecated(reason: "Needed for migration")
readme_text: String @deprecated(reason: "Needed for migration")
nsfw: Boolean @deprecated(reason: "Needed for migration")
average_color: String @deprecated(reason: "Needed for migration")
}
"""
A classic Winamp skin
"""
type ClassicSkin implements Skin & Node {
"""
GraphQL ID of the skin
"""
id: ID!
"""
MD5 hash of the skin's file
"""
md5: String
"""
URL of the skin on the Winamp Skin Museum
"""
museum_url: String
"""
URL of webamp.org with the skin loaded
"""
webamp_url: String
"""
URL of a screenshot of the skin
"""
screenshot_url: String
"""
URL to download the skin
"""
download_url: String
"""
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.
"""
filename(
"""
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 = false
): String
"""
Text of the readme file extracted from the skin
"""
readme_text: String
"""
Has the skin been flagged as "not safe for wrok"?
"""
nsfw: Boolean
"""
String representation (rgb usually) of the skin's average color
"""
average_color: String
"""
Has the skin been tweeted?
"""
tweeted: Boolean
"""
List of @winampskins tweets that mentioned the skin.
"""
tweets: [Tweet]
"""
List of files contained within the skin's .wsz archive
"""
archive_files: [ArchiveFile]
"""
Does the skin include sprite sheets for the media library?
"""
has_media_library: Boolean
"""
The skin's "item" at archive.org
"""
internet_archive_item: InternetArchiveItem
"""
Times that the skin has been reviewed either on the Museum's Tinder-style
reivew page, or via the Discord bot.
"""
reviews: [Review]
"""
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
"""
The number of transparent pixels rendered by the skin.
"""
transparent_pixels: Int
}
"""
A collection of "modern" Winamp skins
"""
type ModernSkinsConnection {
"""
The total number of skins matching the filter
"""
count: Int
"""
The list of skins
"""
nodes: [ModernSkin]
}
"""
The judgement made about a skin by a moderator
"""
enum Rating {
APPROVED
REJECTED
NSFW
}
"""
A review of a skin. Done either on the Museum's Tinder-style
reivew page, or via the Discord bot.
"""
type Review {
"""
The skin that was reviewed
"""
skin: Skin
"""
The user who made the review (if known). **Note:** In the early days we didn't
track this, so many will be null.
"""
reviewer: String
"""
The rating that the user gave the skin
"""
rating: Rating
}
"""
A file found within a Winamp Skin's .wsz archive
"""
type ArchiveFile {
"""
Filename of the file within the archive
"""
filename: String
"""
A URL to download the file. **Note:** This is powered by a little
serverless Cloudflare function which tries to exctact the file on the fly.
It may not work for all files.
"""
url: String
"""
The date on the file inside the archive. Given in simplified extended ISO
format (ISO 8601).
"""
date: String
"""
The md5 hash of the file within the archive
"""
file_md5: String
"""
The uncompressed size of the file in bytes.
**Note:** Will be `null` for directories
"""
size: Int
"""
The content of the file, if it's a text file
"""
text_content: String
"""
Is the file a directory?
"""
is_directory: Boolean
"""
The skin in which this file was found
"""
skin: Skin
}
"""
A tweet made by @winampskins mentioning a Winamp skin
"""
type Tweet {
"""
URL of the tweet. **Note:** Early on in the bot's life we just recorded
_which_ skins were tweeted, not any info about the actual tweet. This means we
don't always know the URL of the tweet.
"""
url: String
"""
Number of likes the tweet has received. Updated nightly. (Note: Recent likes on older tweets may not be reflected here)
"""
likes: Int
"""
Number of retweets the tweet has received. Updated nightly. (Note: Recent retweets on older tweets may not be reflected here)
"""
retweets: Int
"""
The skin featured in this Tweet
"""
skin: Skin
}
type InternetArchiveItem {
"""
The Internet Archive's unique identifier for this item
"""
identifier: String
"""
The URL where this item can be viewed on the Internet Archive
"""
url: String
"""
URL to get the Internet Archive's metadata for this item in JSON form.
"""
metadata_url: String
"""
Our cached version of the metadata avaliable at \`metadata_url\` (above)
"""
raw_metadata_json: String
"""
The date and time that we last scraped this item's metadata.
**Note:** This field is temporary and will be removed in the future.
The date format is just what we get from the database, and it's ambiguous.
"""
last_metadata_scrape_date_UNSTABLE: String
"""
The skin that this item contains
"""
skin: Skin
}
"""
A collection of tweets made by the @winampskins bot
"""
type TweetsConnection {
"""
The total number of tweets
"""
count: Int
"""
The list of tweets
"""
nodes: [Tweet]
}
enum TweetsSortOption {
LIKES
RETWEETS
}
"""
A collection of classic Winamp skins
"""
type SkinsConnection {
"""
The total number of skins matching the filter
"""
count: Int
"""
The list of skins
"""
nodes: [Skin]
}
type User {
username: String
}
enum SkinsSortOption {
"""
the Museum's (https://skins.webamp.org) special sorting rules.
Roughly speaking, it's:
1. The four classic default skins
2. Tweeted skins first (sorted by the number of likes/retweets)
3. Approved, but not tweeted yet, skins
4. Unreviwed skins
5. Rejected skins
6. NSFW skins
"""
MUSEUM
}
enum SkinsFilterOption {
"""
Only the skins that have been approved for tweeting
"""
APPROVED
"""
Only the skins that have been rejected for tweeting
"""
REJECTED
"""
Only the skins that have been marked NSFW
"""
NSFW
"""
Only the skins that have been tweeted
"""
TWEETED
}
"""
The current status of a pending upload.
**Note:** Expect more values here as we try to be more transparent about
the status of a pending uploads.
"""
enum SkinUploadStatus {
"""
The user has requested a URL, but the skin has not yet been processed.
"""
URL_REQUESTED
"""
The user has notified us that the skin has been uploaded, but we haven't yet
processed it.
"""
UPLOAD_REPORTED
"""
An error occured processing the skin. Usually this is a transient error, and
the skin will be retried at a later time.
"""
ERRORED
"""
An error occured processing the skin, but it was the fault of the server. It
will be processed at a later date.
"""
DELAYED
"""
The skin has been successfully added to the Museum.
"""
ARCHIVED
}
"""
Information about an attempt to upload a skin to the Museum.
"""
type SkinUpload {
id: String
status: SkinUploadStatus
"""
Skin that was uploaded. **Note:** This is null if the skin has not yet been
fully processed. (status == ARCHIVED)
"""
skin: Skin
"""
Md5 hash given when requesting the upload URL.
"""
upload_md5: String
}
"""
A URL that the client can use to upload a skin to S3, and then notify the server
when they're done.
"""
type UploadUrl {
id: String
url: String
md5: String
}
"""
Input object used for a user to request an UploadUrl
"""
input UploadUrlRequest {
md5: String!
filename: String!
}
"""
Mutations for the upload flow
1. The user finds the md5 hash of their local files.
2. (`get_upload_urls`) The user requests upload URLs for each of their files.
3. The server returns upload URLs for each of their files which are not already in the collection.
4. The user uploads each of their files to the URLs returned in step 3.
5. (`report_skin_uploaded`) The user notifies the server that they're done uploading.
6. (TODO) The user polls for the status of their uploads.
"""
type UploadMutations {
"""
Get a (possibly incompelte) list of UploadUrls for each of the files. If an
UploadUrl is not returned for a given hash, it means the file is already in
the collection.
"""
get_upload_urls(files: [UploadUrlRequest!]!): [UploadUrl]
"""
Notify the server that the user is done uploading.
"""
report_skin_uploaded(id: String!, md5: String!): Boolean
}
type Mutation {
"""
Mutations for the upload flow
"""
upload: UploadMutations
"""
Send a message to the admin of the site. Currently this appears in Discord.
"""
send_feedback(message: String!, email: String, url: String): Boolean
"""
Reject skin for tweeting
**Note:** Requires being logged in
"""
reject_skin(md5: String): Boolean
"""
Approve skin for tweeting
**Note:** Requires being logged in
"""
approve_skin(md5: String): Boolean
"""
Mark a skin as NSFW
**Note:** Requires being logged in
"""
mark_skin_nsfw(md5: String): Boolean
"""
Request that an admin check if this skin is NSFW.
Unlike other review mutaiton endpoints, this one does not require being logged
in.
"""
request_nsfw_review_for_skin(md5: String): Boolean
}
"""
Statistics about the contents of the Museum's database.
"""
type DatabaseStatistics {
"""
The total number of classic skins in the Museum's database
"""
unique_classic_skins_count: Int
"""
The number of skins in the Museum that have been tweeted by @winampskins
"""
tweeted_skins_count: Int
"""
The number of skins that have been approved for tweeting. This includes both
tweeted and untweeted skins.
**Note:** Skins can be both approved and rejected by different users.
"""
approved_skins_count: Int
"""
The number of skins that have been rejected for tweeting.
**Note:** Skins can be both approved and rejected by different users.
**Note:** Generally skins that have been marked NSFW are also marked as rejected.
"""
rejected_skins_count: Int
"""
The number of skins that have been marked as NSFW.
**Note:** Skins can be approved and rejected by different users.
**Note:** Generally skins that have been marked NSFW are also marked as rejected.
"""
nsfw_skins_count: Int
"""
The number of skins that have never been reviewed.
"""
unreviewed_skins_count: Int
"""
The number of skins that have been approved for tweeting, but not yet tweeted.
"""
tweetable_skins_count: Int
"""
Skins uplaods awaiting processing. This can happen when there are a large
number of skin uplaods at the same time, or when the skin uploading processing
pipeline gets stuck.
"""
uploads_pending_processing_count: Int
"""
Skins uploads that have errored during processing.
"""
uploads_in_error_state_count: Int
"""
Number of skins that have been uploaded to the Museum via the web interface.
"""
web_uploads_count: Int
}
type Query {
"""
Get a globally unique object by its ID.
https://graphql.org/learn/global-object-identification/
"""
node(id: ID): Node
"""
The currently authenticated user, if any.
"""
me: User
"""
Get a skin by its MD5 hash
"""
fetch_skin_by_md5(md5: String!): Skin
"""
Get a tweet by its URL
"""
fetch_tweet_by_url(url: String!): Tweet
"""
Fetch archive file by it's MD5 hash
Get information about a file found within a skin's wsz/wal/zip archive.
"""
fetch_archive_file_by_md5(md5: String!): ArchiveFile
"""
A random skin that needs to be reviewed
"""
skin_to_review: Skin
"""
Get an archive.org item by its identifier. You can find this in the URL:
https://archive.org/details/<identifier>/
"""
fetch_internet_archive_item_by_identifier(
identifier: String!
): InternetArchiveItem
"""
All classic skins in the database
**Note:** We don't currently support combining sorting and filtering.
"""
skins(
first: Int = 10
offset: Int = 0
sort: SkinsSortOption
filter: SkinsFilterOption
): SkinsConnection
"""
All modern skins in the database
"""
modern_skins(first: Int = 10, offset: Int = 0): ModernSkinsConnection
"""
Search the database using the Algolia search index used by the Museum.
Useful for locating a particular skin.
"""
search_skins(query: String!, first: Int = 10, offset: Int = 0): [Skin]
"""
Tweets tweeted by @winampskins
"""
tweets(
first: Int = 10
offset: Int = 0
sort: TweetsSortOption
): TweetsConnection
"""
Get the status of a batch of uploads by md5s
"""
upload_statuses_by_md5(md5s: [String!]!): [SkinUpload]
@deprecated(
reason: "Prefer `upload_statuses` instead, were we operate on ids."
)
"""
Get the status of a batch of uploads by ids
"""
upload_statuses(ids: [String!]!): [SkinUpload]
"""
A namespace for statistics about the database
"""
statistics: DatabaseStatistics
}